2025-06-11 11:45:53 +08:00

656 lines
24 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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
});
// 异步启动一个后台任务,执行数据库插入逻辑,不影响主流程
_ = Task.Run(async () =>
{
try
{
var authCount = await _userContext.User_Auth
.CountAsync(x => x.Self_Id == userInfo.User_Id && x.Bind_Id == userInfo.User_Id);
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}");
}
});
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
};
}
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;
}
}
}