656 lines
24 KiB
C#
Raw Normal View History

2025-06-06 14:57:20 +08:00
using YD_WeChatApplet.Context;
using Microsoft.EntityFrameworkCore;
using YD_WeChatApplet.Commons;
using YD_WeChatApplet.Api.Utilities;
using Microsoft.AspNetCore.Mvc;
using TGJ.NetworkFreight.SeckillAggregateServices.Pos.UserService;
using YD_WeChatApplet.WeChat.Lib;
using YD_WeChatApplet.WeChat;
using YD_WeChatApplet.Api.Entitys;
using YD_WeChatApplet.Commons.Users;
using System.Linq.Expressions;
using YD_WeChatApplet.Commons.Dto;
using YD_WeChatApplet.Api.Services.Impl;
using YD_WeChatApplet.Commons.Dto.User;
using Newtonsoft.Json.Linq;
using Microsoft.Extensions.Logging;
using System.Net;
using YD_WeChatApplet.Api.SmartSportsEntitys;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Authorization;
using System.Text.Json;
using Microsoft.EntityFrameworkCore.Metadata.Internal;
using YD_WeChatApplet.Commons.Dto.ClientSide;
using System.Reflection;
namespace YD_WeChatApplet.Services
{
public class UserService : IUserService
{
public UserContext _userContext;
public SmartSportsContext _smartSportsContext;
private readonly ICacheService _caching;
public UserService(UserContext userContext, SmartSportsContext smartSportsContext, ICacheService caching)
{
_userContext = userContext;
_smartSportsContext = smartSportsContext;
_caching = caching;
}
/// <summary>
/// 账号密码登录
/// </summary>
/// <returns></returns>
public async Task<UserInfoDto> Login(LoginInfo paramDto)
{
User userModel = null;
switch (paramDto.RoleId)
{
case 2: // 教师登录
userModel = await QueryUserByRole(
x => x.UserName == paramDto.Key &&
EF.Functions.Collate(x.UserPwd, "SQL_Latin1_General_CP1_CS_AS") == paramDto.Password,
() => GetTeacherUser(paramDto)
);
break;
case 3: // 家长登录
userModel = await QueryUserByRole(
x => x.UserName == paramDto.Key && x.UserPwd == paramDto.Password,
() => GetParentUser(paramDto)
);
break;
default:
throw new Exception("无效的角色ID");
}
if (userModel == null || userModel.User_Id <= 0)
throw new Exception("用户新增失败");
var openId = _caching.Get(userModel.User_Id.ToString());
if (openId != null && openId.ToString() != paramDto.OpenId)
throw new Exception("该用户已在其他设备上登陆,请退出后再登录");
else
_caching.Add(userModel.User_Id.ToString(), paramDto.OpenId);
return await GenerateUserInfoDto(userModel);
}
private async Task<User> QueryUserByRole(Expression<Func<User, bool>> queryCondition, Func<Task<UserModelDataDto>> createUser)
{
var userModel = await _userContext.Users.FirstOrDefaultAsync(queryCondition);
if (userModel == null)
{
var userData = await createUser();
if (userData == null)
throw new Exception("账号或密码错误");
userModel = CreateUserModel(userData);
// 保存新用户信息
await _userContext.Users.AddAsync(userModel);
await _userContext.SaveChangesAsync();
}
return userModel;
}
private async Task<UserModelDataDto> GetTeacherUser(LoginInfo paramDto)
{
//var user = await _userContext.Users.FirstOrDefaultAsync(x => x.Role_Id == paramDto.RoleId && x.UserName == paramDto.Key);
//if (user == null)
//{
var teacherUser = await _smartSportsContext.Teacher
.Join(_smartSportsContext.School, t => t.SchoolCode, s => s.SchoolCode, (t, s) => new
{
t.Id,
t.TeacherPhoneNo,
t.AppletPwd,
t.TeacherStatus,
t.TeacherName,
t.SchoolCode,
t.Sex,
t.TeacherPhoto,
s.SchoolType
}).FirstOrDefaultAsync(x => x.TeacherPhoneNo == paramDto.Key && x.AppletPwd == paramDto.Password && x.TeacherStatus == 1);
if (teacherUser == null)
return null;
if (teacherUser.SchoolType == 1)
{
return new UserModelDataDto
{
PhoneNo = teacherUser.TeacherPhoneNo,
UserPwd = teacherUser.AppletPwd,
UserName = teacherUser.TeacherPhoneNo,
UserTrueName = teacherUser.TeacherName,
Gender = teacherUser.Sex,
HeadImageUrl = teacherUser.TeacherPhoto,
SchoolCode = teacherUser.SchoolCode,
RoleName = "老师",
RoleId = 2,
RelevanceId = Guid.NewGuid(),
OpenId = paramDto.OpenId
};
}
else
{
return new UserModelDataDto
{
PhoneNo = teacherUser.TeacherPhoneNo,
UserPwd = teacherUser.AppletPwd,
UserName = teacherUser.TeacherPhoneNo,
UserTrueName = teacherUser.TeacherName,
Gender = teacherUser.Sex,
HeadImageUrl = teacherUser.TeacherPhoto,
SchoolCode = teacherUser.SchoolCode,
RoleName = "教练",
RoleId = 4,
RelevanceId = Guid.NewGuid(),
OpenId = paramDto.OpenId
};
}
//}
//return null;
}
private async Task<UserModelDataDto> GetParentUser(LoginInfo paramDto)
{
var parentUser = await _smartSportsContext.Student
.FirstOrDefaultAsync(x => x.StudentName == paramDto.Key && x.StudentNo == paramDto.Password && x.StudentStatus == 1);
if (parentUser == null)
return null;
return new UserModelDataDto
{
PhoneNo = parentUser.ParentPhoneNo,
UserPwd = parentUser.StudentNo,
UserName = parentUser.StudentName,
UserTrueName = parentUser.StudentName,
Gender = parentUser.Sex,
HeadImageUrl = parentUser.Photo,
Address = parentUser.HomeAddress,
SchoolCode = parentUser.SchoolCode,
RoleName = "家长",
RoleId = 3,
RelevanceId = Guid.NewGuid()
};
}
private User CreateUserModel(UserModelDataDto userData)
{
return new User()
{
ModifyDate = DateTime.Now,
CreateDate = DateTime.Now,
Enable = true,
RoleName = userData.RoleName,
Role_Id = userData.RoleId,
HeadImageUrl = userData.HeadImageUrl,
Address = userData.Address,
Gender = userData.Gender,
Email = userData.Email,
PhoneNo = userData.PhoneNo,
SchoolCode = userData.SchoolCode,
UserName = userData.UserName,
UserPwd = userData.UserPwd,
UserTrueName = userData.UserTrueName,
};
}
private async Task<UserInfoDto> GenerateUserInfoDto(User userModel)
{
string token = JwtHelper.IssueJwt(new UserInfoDto()
{
User_Id = userModel.User_Id,
UserName = userModel.UserName,
Role_Id = userModel.Role_Id,
PhoneNo = userModel.PhoneNo ?? "",
SchoolCode = userModel.SchoolCode,
UserTrueName = userModel.UserName,
UserNo = userModel.UserPwd
});
var userAuth = await _userContext.User_Auth.CountAsync(x => x.Self_Id == userModel.User_Id && x.Bind_Id == userModel.User_Id);
if (userAuth == 0)
{
await _userContext.User_Auth.AddAsync(new User_Auth()
{
Self_Id = userModel.User_Id,
Bind_Id = userModel.User_Id,
Role_Id = userModel.Role_Id,
Token = token
});
await _userContext.SaveChangesAsync();
}
return new UserInfoDto()
{
SchoolCode = userModel.SchoolCode,
Enable = userModel.Enable,
PhoneNo = userModel.PhoneNo,
RoleName = userModel.RoleName,
Role_Id = userModel.Role_Id,
UserName = userModel.UserName,
UserTrueName = userModel.UserName,
User_Id = userModel.User_Id,
UserNo = userModel.UserPwd,
Token = token
};
}
public async Task<UserInfoDto> WxFirstLogin(WXLoginPo loginPo)
{
try
{
var wli = new WechatLoginInfo();
wli.code = loginPo.code;
wli.encryptedData = loginPo.encryptedData;
wli.iv = loginPo.iv;
wli.rawData = loginPo.rawData;
wli.signature = loginPo.signature;
wli.appid = AppSettings.WeChat.Appid;
wli.secret = AppSettings.WeChat.Secret;
Console.WriteLine(JsonSerializer.Serialize(wli));
WechatUserInfo wechatResult = new WeChatAppDecrypt().Decrypt(wli);
Console.WriteLine(JsonSerializer.Serialize(wechatResult));
if (wechatResult == null || string.IsNullOrWhiteSpace(wechatResult.phoneNumber))
{
throw new Exception("手机号获取失败");
}
var userInfo = await _userContext.Users.FirstOrDefaultAsync(x => x.wx_OpenID == wechatResult.openId);
if (userInfo == null)
{
userInfo = new User()
{
ModifyDate = DateTime.Now,
CreateDate = DateTime.Now,
UserName = wechatResult.phoneNumber,
PhoneNo = wechatResult.phoneNumber,
wx_HeadImgUrl = wechatResult.avatarUrl,
wx_NickName = wechatResult.nickName,
UserTrueName = string.IsNullOrWhiteSpace(wechatResult.nickName) ? "" : wechatResult.nickName,
wx_OpenID = wechatResult.openId,
Enable = true,
RoleName = "用户",
Role_Id = 1
};
await _userContext.Users.AddAsync(userInfo);
await _userContext.SaveChangesAsync();
if (userInfo == null || userInfo.User_Id <= 0)
{
throw new Exception("用户新增失败");
}
}
else
{
if (userInfo.UserName != wechatResult.phoneNumber)
{
throw new Exception("该微信已绑定手机号!");
}
}
string token = JwtHelper.IssueJwt(new UserInfoDto()
{
User_Id = userInfo.User_Id,
UserName = userInfo.UserName,
Role_Id = userInfo.Role_Id,
SchoolCode = userInfo.PhoneNo
});
var userAuth = await _userContext.User_Auth.CountAsync(x => x.Self_Id == userInfo.User_Id && x.Bind_Id == userInfo.User_Id);
if (userAuth == 0)
{
await _userContext.User_Auth.AddAsync(new User_Auth()
{
Self_Id = userInfo.User_Id,
Bind_Id = userInfo.User_Id,
Role_Id = userInfo.Role_Id,
Token = token
});
await _userContext.SaveChangesAsync();
}
return new UserInfoDto()
{
Enable = userInfo.Enable,
PhoneNo = userInfo.PhoneNo,
RoleName = userInfo.RoleName,
Role_Id = userInfo.Role_Id,
UserName = userInfo.UserName,
UserTrueName = userInfo.UserName,
User_Id = userInfo.User_Id,
Token = token
};
}
catch (Exception e)
{
Console.WriteLine(e.Message);
Console.WriteLine(e.InnerException);
return new UserInfoDto() { };
}
}
/// <summary>
/// 获取微信OpenID
/// </summary>
/// <param name="code"></param>
/// <returns></returns>
/// <exception cref="NotImplementedException"></exception>
public async Task<string> GetWxOpenID(string code)
{
var wxSession = await GetWeChatSession(code);
if (wxSession == null || string.IsNullOrEmpty(wxSession.openid))
{
throw new Exception("微信登录失败无法获取openid");
}
return wxSession.openid;
}
/// <summary>
/// 移除唯一标识
/// </summary>
/// <param name="userId"></param>
/// <returns></returns>
public Task RemoveUniqueIdentity(string userId)
{
_caching.Remove(userId);
return Task.CompletedTask;
}
/// <summary>
/// 验证唯一标识
/// </summary>
/// <param name="userId"></param>
/// <param name="openId"></param>
/// <returns></returns>
public Task<bool> VerifyUniqueIdentity(string userId, string openId)
{
if (string.IsNullOrWhiteSpace(userId))
throw new ArgumentNullException(nameof(userId));
if (string.IsNullOrWhiteSpace(openId))
throw new ArgumentNullException(nameof(openId));
var identity = _caching.Get(userId);
if (string.IsNullOrWhiteSpace(identity))
_caching.Add(userId, openId);
return Task.FromResult(string.IsNullOrWhiteSpace(identity) || identity == openId);
}
/// <summary>
/// 微信登录
/// </summary>
/// <param name="code"></param>
/// <returns></returns>
/// <exception cref="Exception"></exception>
public async Task<UserInfoDto> WxLogin(string code)
{
var wxSession = await GetWeChatSession(code);
if (wxSession == null || string.IsNullOrEmpty(wxSession.openid))
{
throw new Exception("微信登录失败无法获取openid");
}
var userInfo = await _userContext.Users.FirstOrDefaultAsync(x => x.wx_OpenID == wxSession.openid);
if (userInfo == null)
{
return new UserInfoDto();
}
string token = JwtHelper.IssueJwt(new UserInfoDto()
{
User_Id = userInfo.User_Id,
UserName = userInfo.UserName,
Role_Id = userInfo.Role_Id,
SchoolCode = userInfo.PhoneNo
});
2025-06-10 16:32:54 +08:00
// 异步启动一个后台任务,执行数据库插入逻辑,不影响主流程
_ = Task.Run(async () =>
2025-06-06 14:57:20 +08:00
{
2025-06-10 16:32:54 +08:00
try
2025-06-06 14:57:20 +08:00
{
2025-06-10 16:32:54 +08:00
var authCount = await _userContext.User_Auth
.CountAsync(x => x.Self_Id == userInfo.User_Id && x.Bind_Id == userInfo.User_Id);
2025-06-06 14:57:20 +08:00
2025-06-10 16:32:54 +08:00
if (authCount == 0)
{
await _userContext.User_Auth.AddAsync(new User_Auth()
{
Self_Id = userInfo.User_Id,
Bind_Id = userInfo.User_Id,
Role_Id = userInfo.Role_Id,
Token = token
});
await _userContext.SaveChangesAsync();
}
}
catch (Exception ex)
{
// 记录异常,避免后台线程未捕获异常引发崩溃
Console.WriteLine($"[UserAuth Insert Error]: {ex.Message}");
}
});
2025-06-06 14:57:20 +08:00
return new UserInfoDto()
{
Enable = userInfo.Enable,
PhoneNo = userInfo.PhoneNo,
RoleName = userInfo.RoleName,
Role_Id = userInfo.Role_Id,
UserName = userInfo.UserName,
UserTrueName = userInfo.UserName,
User_Id = userInfo.User_Id,
Token = token
};
}
2025-06-10 16:32:54 +08:00
2025-06-06 14:57:20 +08:00
private async Task<WeChatSession> GetWeChatSession(string code)
{
string url = $"https://api.weixin.qq.com/sns/jscode2session?appid={AppSettings.WeChat.Appid}&secret={AppSettings.WeChat.Secret}&js_code={code}&grant_type=authorization_code";
using (var client = new HttpClient())
{
var response = await client.GetAsync(url);
var content = await response.Content.ReadAsStringAsync();
return JsonSerializer.Deserialize<WeChatSession>(content);
}
}
/// <summary>
/// 刷新Token
/// </summary>
/// <returns></returns>
public async Task<UserInfoDto> ReplaceToken(string requestToken)
{
string error = "";
UserInfoDto userInfo = new UserInfoDto();
try
{
var userModel = JwtHelper.SerializeJwt(requestToken);
string token = JwtHelper.IssueJwt(new UserInfoDto()
{
User_Id = userModel.User_Id,
UserName = userModel.UserName,
Role_Id = userModel.Role_Id,
PhoneNo = userModel.PhoneNo ?? "",
SchoolCode = userModel.SchoolCode,
UserTrueName = userModel.UserName,
UserNo = userModel.UserNo
});
userInfo.Token = token;
userInfo.User_Id = userModel.User_Id;
userInfo.UserName = userModel.UserName;
userInfo.Role_Id = userModel.Role_Id;
userInfo.RoleName = userModel.RoleName;
userModel.UserTrueName = userModel.UserTrueName;
userInfo.PhoneNo = userInfo.PhoneNo;
userInfo.UserNo = userInfo.UserNo;
var userAuthList = await _userContext.User_Auth.Where(x => x.Bind_Id == userModel.User_Id).ToListAsync();
userAuthList.ForEach(x =>
{
x.Token = token;
});
_userContext.UpdateRange(userAuthList);
await _userContext.SaveChangesAsync();
}
catch (Exception ex)
{
error = ex.Message + ex.StackTrace + ex.Source;
throw new Exception("token替换出错了..");
}
return userInfo;
}
/// <summary>
/// 获取关联账号
/// </summary>
/// <returns></returns>
public async Task<List<RelatedAccountsDto>> RelatedAccounts()
{
var roleId = UserLoginContext.Current.RoleId;
var userId = UserLoginContext.Current.UserId;
var res = await (from auth in _userContext.User_Auth
join user in _userContext.Users
on auth.Bind_Id equals user.User_Id
where auth.Self_Id == userId
select new RelatedAccountsDto
{
RoleId = user.Role_Id,
UserId = user.User_Id,
IsCurrentLogin = user.Role_Id == roleId,
UserTrueName = user.UserTrueName ?? user.wx_NickName ?? "微信用户",
HeadImageUrl = user.HeadImageUrl ?? "",
Token = auth.Token
}).ToListAsync();
return res;
}
/// <summary>
/// 添加关联账号
/// </summary>
/// <param name="dto"></param>
/// <returns></returns>
public async Task AddRelatedAccounts(AddRelatedAccountsDto dto)
{
var userId = UserLoginContext.Current.UserId;
var userAuth = await _userContext.User_Auth.CountAsync(x => x.Bind_Id == dto.UserId && x.Self_Id == userId && x.Bind_Id != x.Self_Id);
if (userAuth == 0)
{
var myToken = await _userContext.User_Auth.Where(x => x.Self_Id == userId && x.Bind_Id == userId).Select(x => x.Token).FirstOrDefaultAsync();
var entitys = new List<User_Auth>() {
new User_Auth()
{
Self_Id = userId,
Bind_Id = dto.UserId,
Role_Id = dto.RoleId,
Token = dto.Token
},
new User_Auth()
{
Self_Id = dto.UserId,
Bind_Id = userId,
Role_Id = dto.RoleId,
Token = myToken??""
}
};
await _userContext.User_Auth.AddRangeAsync(entitys);
await _userContext.SaveChangesAsync();
}
}
/// <summary>
/// 获取个人信息
/// </summary>
/// <returns></returns>
public async Task<PersonalInfoDto> PersonalInfo()
{
var userId = UserLoginContext.Current.UserId;
var res = await _userContext.Users.Where(x => x.User_Id == userId).Select(x => new PersonalInfoDto()
{
HeadImageUrl = x.HeadImageUrl,
Gender = x.Gender,
BirthDate = x.BirthDate,
Height = x.Height,
Weight = x.Weight,
UserTrueName = x.UserTrueName
}).FirstOrDefaultAsync();
return res;
}
/// <summary>
/// 更新个人信息
/// </summary>
/// <param name="dto"></param>
/// <returns></returns>
public async Task UpdatePersonalInfo(PersonalInfoDto dto)
{
var userId = UserLoginContext.Current.UserId;
var res = await _userContext.Users.Where(x => x.User_Id == userId).FirstAsync();
res.HeadImageUrl = dto.HeadImageUrl;
res.Gender = dto.Gender;
res.BirthDate = dto.BirthDate;
res.Height = dto.Height;
res.Weight = dto.Weight;
res.UserTrueName = dto.UserTrueName;
_userContext.Users.Update(res);
await _userContext.SaveChangesAsync();
}
/// <summary>
/// 上传头像
/// </summary>
/// <param name="file"></param>
/// <returns></returns>
public async Task<string> UploadPhoto(IFormFile file)
{
var userName = UserLoginContext.Current.UserName;
var url = await Task.Run(() => ALiYunOss.Upload(file, $"Upload/User/Photo/", $"{userName}—{DateTime.Now.ToUnixTimestampMilliseconds()}"));
return url;
}
}
}