|
@@ -58,49 +58,81 @@ private OnboardingService onboardingService;
|
|
|
private FamilyInvitationService familyInvitationService;
|
|
private FamilyInvitationService familyInvitationService;
|
|
|
|
|
|
|
|
public LoginResultDTO wechatLogin(WechatLoginDTO dto) {
|
|
public LoginResultDTO wechatLogin(WechatLoginDTO dto) {
|
|
|
- // 通过code获取真实openid(调微信code2session接口)
|
|
|
|
|
|
|
+ // 1. 通过code获取openid
|
|
|
Map<String, String> sessionData = wechatService.code2Session(dto.getCode());
|
|
Map<String, String> sessionData = wechatService.code2Session(dto.getCode());
|
|
|
String openid = sessionData.get("openid");
|
|
String openid = sessionData.get("openid");
|
|
|
String unionid = sessionData.get("unionid");
|
|
String unionid = sessionData.get("unionid");
|
|
|
if (openid == null || openid.isEmpty()) {
|
|
if (openid == null || openid.isEmpty()) {
|
|
|
throw new RuntimeException("获取openid失败,请重试");
|
|
throw new RuntimeException("获取openid失败,请重试");
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
- // 查询用户是否存在
|
|
|
|
|
|
|
+
|
|
|
|
|
+ // 2. 如果提供了phoneCode,获取真实手机号
|
|
|
|
|
+ String phone = null;
|
|
|
|
|
+ if (dto.getPhoneCode() != null && !dto.getPhoneCode().isEmpty()) {
|
|
|
|
|
+ phone = wechatService.getPhoneNumber(dto.getPhoneCode());
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 3. 先通过openid查找用户
|
|
|
User user = userMapper.selectOne(new LambdaQueryWrapper<User>()
|
|
User user = userMapper.selectOne(new LambdaQueryWrapper<User>()
|
|
|
.eq(User::getOpenid, openid));
|
|
.eq(User::getOpenid, openid));
|
|
|
|
|
|
|
|
|
|
+ boolean isNewUser = false;
|
|
|
|
|
+
|
|
|
if (user == null) {
|
|
if (user == null) {
|
|
|
- // 新用户,创建家庭和用户
|
|
|
|
|
- Family family = new Family();
|
|
|
|
|
- family.setName("我的家庭");
|
|
|
|
|
- family.setInviteCode(generateInviteCode());
|
|
|
|
|
- family.setCreatedAt(new Date());
|
|
|
|
|
- family.setUpdatedAt(new Date());
|
|
|
|
|
- familyMapper.insert(family);
|
|
|
|
|
|
|
+ // 4. openid不存在,如果有手机号则通过手机号查找
|
|
|
|
|
+ if (phone != null) {
|
|
|
|
|
+ user = userMapper.selectOne(new LambdaQueryWrapper<User>()
|
|
|
|
|
+ .eq(User::getPhone, phone));
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
- user = new User();
|
|
|
|
|
- user.setOpenid(openid);
|
|
|
|
|
- user.setUnionid("");
|
|
|
|
|
- user.setFamilyId(family.getId());
|
|
|
|
|
- user.setRole("parent");
|
|
|
|
|
- user.setNickname(dto.getNickname());
|
|
|
|
|
- user.setAvatar(dto.getAvatar());
|
|
|
|
|
- user.setPassword("");
|
|
|
|
|
- user.setCreatedAt(new Date());
|
|
|
|
|
- user.setUpdatedAt(new Date());
|
|
|
|
|
- userMapper.insert(user);
|
|
|
|
|
- try { onboardingService.initForUser(user.getId()); onboardingService.completeTask(user.getId(), "REGISTER"); } catch (Exception e) { /* onboarding init failure should not block login */ }
|
|
|
|
|
- } else {
|
|
|
|
|
- // 懒创建家庭(admin创建的用户可能 familyId=0L)
|
|
|
|
|
- ensureUserHasFamily(user);
|
|
|
|
|
|
|
+ if (user == null) {
|
|
|
|
|
+ // 5. 全新用户,创建新家庭和用户
|
|
|
|
|
+ isNewUser = true;
|
|
|
|
|
|
|
|
- // 管理员不能登录小程序
|
|
|
|
|
- if ("admin".equals(user.getRole())) {
|
|
|
|
|
- throw new RuntimeException("该账号不允许登录小程序");
|
|
|
|
|
|
|
+ Family family = new Family();
|
|
|
|
|
+ family.setName("我的家庭");
|
|
|
|
|
+ family.setInviteCode(generateInviteCode());
|
|
|
|
|
+ family.setCreatedAt(new Date());
|
|
|
|
|
+ family.setUpdatedAt(new Date());
|
|
|
|
|
+ familyMapper.insert(family);
|
|
|
|
|
+
|
|
|
|
|
+ user = new User();
|
|
|
|
|
+ user.setOpenid(openid);
|
|
|
|
|
+ user.setUnionid(unionid != null ? unionid : "");
|
|
|
|
|
+ user.setFamilyId(family.getId());
|
|
|
|
|
+ user.setRole("parent");
|
|
|
|
|
+ user.setNickname(dto.getNickname() != null ? dto.getNickname() : (phone != null ? "用户" + phone.substring(7) : "微信用户"));
|
|
|
|
|
+ user.setAvatar(dto.getAvatar());
|
|
|
|
|
+ user.setPhone(phone);
|
|
|
|
|
+ user.setPassword("");
|
|
|
|
|
+ user.setCreatedAt(new Date());
|
|
|
|
|
+ user.setUpdatedAt(new Date());
|
|
|
|
|
+ userMapper.insert(user);
|
|
|
|
|
+ try { onboardingService.initForUser(user.getId()); onboardingService.completeTask(user.getId(), "REGISTER"); } catch (Exception e) { /* onboarding init failure should not block login */ }
|
|
|
|
|
+ } else {
|
|
|
|
|
+ // 6. 手机号已存在但openid不同,绑定openid
|
|
|
|
|
+ user.setOpenid(openid);
|
|
|
|
|
+ user.setUnionid(unionid != null ? unionid : "");
|
|
|
|
|
+ user.setUpdatedAt(new Date());
|
|
|
|
|
+ userMapper.updateById(user);
|
|
|
|
|
+ }
|
|
|
|
|
+ } else {
|
|
|
|
|
+ // 7. openid已存在,更新手机号(如果手机号变了)
|
|
|
|
|
+ if (phone != null && !phone.equals(user.getPhone())) {
|
|
|
|
|
+ user.setPhone(phone);
|
|
|
|
|
+ user.setUpdatedAt(new Date());
|
|
|
|
|
+ userMapper.updateById(user);
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ // P3: admin创建的用户可能 familyId=0L,懒创建家庭
|
|
|
|
|
+ ensureUserHasFamily(user);
|
|
|
|
|
+
|
|
|
|
|
+ // 管理员不能登录小程序
|
|
|
|
|
+ if ("admin".equals(user.getRole())) {
|
|
|
|
|
+ throw new RuntimeException("该账号不允许登录小程序");
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
// 生成token
|
|
// 生成token
|
|
|
String token = jwtConfig.generateToken(user.getId(), user.getRole());
|
|
String token = jwtConfig.generateToken(user.getId(), user.getRole());
|
|
|
|
|
|
|
@@ -111,6 +143,11 @@ private FamilyInvitationService familyInvitationService;
|
|
|
result.setRoles(user.getRoles());
|
|
result.setRoles(user.getRoles());
|
|
|
result.setFamilyId(user.getFamilyId());
|
|
result.setFamilyId(user.getFamilyId());
|
|
|
result.setNickname(user.getNickname());
|
|
result.setNickname(user.getNickname());
|
|
|
|
|
+ result.setIsNewUser(isNewUser);
|
|
|
|
|
+ result.setOpenid(openid);
|
|
|
|
|
+
|
|
|
|
|
+ // 新用户需要完善信息(仅当需要选择角色时)
|
|
|
|
|
+ result.setNeedsRoleSelect(isNewUser);
|
|
|
populateTeacherFields(result, user);
|
|
populateTeacherFields(result, user);
|
|
|
|
|
|
|
|
return result;
|
|
return result;
|
|
@@ -196,94 +233,15 @@ private FamilyInvitationService familyInvitationService;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
|
- * 微信手机号登录(正确获取openid和手机号)
|
|
|
|
|
|
|
+ * 微信手机号登录(委托给wechatLogin处理)
|
|
|
*/
|
|
*/
|
|
|
public LoginResultDTO wechatPhoneLogin(WechatPhoneLoginDTO dto) {
|
|
public LoginResultDTO wechatPhoneLogin(WechatPhoneLoginDTO dto) {
|
|
|
- // 1. 通过code获取openid
|
|
|
|
|
- Map<String, String> sessionData = wechatService.code2Session(dto.getCode());
|
|
|
|
|
- String openid = sessionData.get("openid");
|
|
|
|
|
- String unionid = sessionData.get("unionid");
|
|
|
|
|
-
|
|
|
|
|
- // 2. 通过手机号code获取真实手机号
|
|
|
|
|
- String phone = wechatService.getPhoneNumber(dto.getPhoneCode());
|
|
|
|
|
-
|
|
|
|
|
- // 3. 先通过openid查找用户
|
|
|
|
|
- User user = userMapper.selectOne(new LambdaQueryWrapper<User>()
|
|
|
|
|
- .eq(User::getOpenid, openid));
|
|
|
|
|
-
|
|
|
|
|
- boolean isNewUser = false;
|
|
|
|
|
-
|
|
|
|
|
- if (user == null) {
|
|
|
|
|
- // 4. openid不存在,通过手机号查找
|
|
|
|
|
- user = userMapper.selectOne(new LambdaQueryWrapper<User>()
|
|
|
|
|
- .eq(User::getPhone, phone));
|
|
|
|
|
-
|
|
|
|
|
- if (user == null) {
|
|
|
|
|
- // 5. 全新用户,创建新家庭和用户
|
|
|
|
|
- isNewUser = true;
|
|
|
|
|
-
|
|
|
|
|
- Family family = new Family();
|
|
|
|
|
- family.setName("我的家庭");
|
|
|
|
|
- family.setInviteCode(generateInviteCode());
|
|
|
|
|
- family.setCreatedAt(new Date());
|
|
|
|
|
- family.setUpdatedAt(new Date());
|
|
|
|
|
- familyMapper.insert(family);
|
|
|
|
|
-
|
|
|
|
|
- user = new User();
|
|
|
|
|
- user.setOpenid(openid);
|
|
|
|
|
- user.setUnionid(unionid);
|
|
|
|
|
- user.setFamilyId(family.getId());
|
|
|
|
|
- user.setRole("parent");
|
|
|
|
|
- user.setNickname(dto.getNickname() != null ? dto.getNickname() : "用户" + phone.substring(7));
|
|
|
|
|
- user.setAvatar(dto.getAvatar());
|
|
|
|
|
- user.setPhone(phone);
|
|
|
|
|
- user.setPassword("");
|
|
|
|
|
- user.setCreatedAt(new Date());
|
|
|
|
|
- user.setUpdatedAt(new Date());
|
|
|
|
|
- userMapper.insert(user);
|
|
|
|
|
- try { onboardingService.initForUser(user.getId()); onboardingService.completeTask(user.getId(), "REGISTER"); } catch (Exception e) { /* onboarding init failure should not block login */ }
|
|
|
|
|
- } else {
|
|
|
|
|
- // 6. 手机号已存在但openid不同,绑定openid
|
|
|
|
|
- user.setOpenid(openid);
|
|
|
|
|
- user.setUnionid(unionid);
|
|
|
|
|
- user.setUpdatedAt(new Date());
|
|
|
|
|
- userMapper.updateById(user);
|
|
|
|
|
- }
|
|
|
|
|
- } else {
|
|
|
|
|
- // 7. openid已存在,更新手机号(如果手机号变了)
|
|
|
|
|
- if (phone != null && !phone.equals(user.getPhone())) {
|
|
|
|
|
- user.setPhone(phone);
|
|
|
|
|
- user.setUpdatedAt(new Date());
|
|
|
|
|
- userMapper.updateById(user);
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- // P3: admin创建的用户可能 familyId=0L,懒创建家庭
|
|
|
|
|
- ensureUserHasFamily(user);
|
|
|
|
|
-
|
|
|
|
|
- // 管理员不能登录小程序
|
|
|
|
|
- if ("admin".equals(user.getRole())) {
|
|
|
|
|
- throw new RuntimeException("该账号不允许登录小程序");
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- // 生成token
|
|
|
|
|
- String token = jwtConfig.generateToken(user.getId(), user.getRole());
|
|
|
|
|
-
|
|
|
|
|
- LoginResultDTO result = new LoginResultDTO();
|
|
|
|
|
- result.setToken(token);
|
|
|
|
|
- result.setUserId(user.getId());
|
|
|
|
|
- result.setRole(user.getRole());
|
|
|
|
|
- result.setRoles(user.getRoles());
|
|
|
|
|
- result.setFamilyId(user.getFamilyId());
|
|
|
|
|
- result.setNickname(user.getNickname());
|
|
|
|
|
- result.setIsNewUser(isNewUser);
|
|
|
|
|
- result.setOpenid(openid);
|
|
|
|
|
-
|
|
|
|
|
- // 新用户需要完善信息(仅当需要选择角色时)
|
|
|
|
|
- result.setNeedsRoleSelect(isNewUser);
|
|
|
|
|
- populateTeacherFields(result, user);
|
|
|
|
|
-
|
|
|
|
|
- return result;
|
|
|
|
|
|
|
+ WechatLoginDTO mergedDto = new WechatLoginDTO();
|
|
|
|
|
+ mergedDto.setCode(dto.getCode());
|
|
|
|
|
+ mergedDto.setPhoneCode(dto.getPhoneCode());
|
|
|
|
|
+ mergedDto.setNickname(dto.getNickname());
|
|
|
|
|
+ mergedDto.setAvatar(dto.getAvatar());
|
|
|
|
|
+ return wechatLogin(mergedDto);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
@@ -1037,6 +995,10 @@ private FamilyInvitationService familyInvitationService;
|
|
|
if (dto.getFamilyRole() != null) {
|
|
if (dto.getFamilyRole() != null) {
|
|
|
user.setFamilyRole(dto.getFamilyRole());
|
|
user.setFamilyRole(dto.getFamilyRole());
|
|
|
}
|
|
}
|
|
|
|
|
+ // 更新AI助手形象
|
|
|
|
|
+ if (dto.getMascot() != null) {
|
|
|
|
|
+ user.setMascot(dto.getMascot());
|
|
|
|
|
+ }
|
|
|
user.setUpdatedAt(new Date());
|
|
user.setUpdatedAt(new Date());
|
|
|
userMapper.updateById(user);
|
|
userMapper.updateById(user);
|
|
|
return true;
|
|
return true;
|