refactor: 代码生成支持js,已知问题修复

This commit is contained in:
Ray.Hao
2026-01-16 23:23:14 +08:00
parent c30988b2da
commit f9fb9b6eb9
24 changed files with 1151 additions and 144 deletions

View File

@@ -7,7 +7,7 @@ import org.springframework.stereotype.Component;
/**
* 验证码 属性配置
*
* @author haoxr
* @author Ray.Hao
* @since 2023/11/24
*/
@Component

View File

@@ -10,27 +10,21 @@ import com.youlai.boot.platform.ai.model.query.AiAssistantQuery;
import com.youlai.boot.platform.ai.model.vo.AiAssistantRecordVO;
import com.youlai.boot.platform.ai.service.AiAssistantRecordService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.servlet.http.HttpServletRequest;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
/**
* AI 助手控制器
* <p>
* 负责 AI 命令的解析、执行记录管理及回滚操作,
* 表示一次 AI 助手完整的指令生命周期。
* 负责 AI 命令的解析、执行记录查询。
*
* @author Ray.Hao
* @since 3.0.0
*/
@Tag(name = "AI 助手接口")
@Tag(name = "13.AI 助手接口")
@RestController
@RequestMapping("/api/v1/ai/assistant")
@RequiredArgsConstructor
@@ -81,29 +75,5 @@ public class AiAssistantController {
return PageResult.success(page);
}
@Operation(summary = "删除 AI 命令记录")
@DeleteMapping("/records/{ids}")
public Result<Void> deleteRecords(
@Parameter(description = "记录ID多个以英文逗号(,)分割")
@PathVariable String ids
) {
List<Long> idList = Arrays.stream(ids.split(","))
.filter(s -> s != null && !s.isBlank())
.map(String::trim)
.map(Long::valueOf)
.collect(Collectors.toList());
boolean removed = aiAssistantRecordService.deleteRecords(idList);
return Result.judge(removed);
}
@Operation(summary = "撤销命令执行")
@PostMapping("/records/{recordId}/rollback")
public Result<Void> rollbackCommand(
@Parameter(description = "记录ID")
@PathVariable String recordId
) {
aiAssistantRecordService.rollbackCommand(recordId);
return Result.success();
}
// 记录类接口按需扩展,当前开放 parse/execute/records
}

View File

@@ -49,18 +49,4 @@ public interface AiAssistantRecordService extends IService<AiAssistantRecord> {
*/
IPage<AiAssistantRecordVO> getRecordPage(AiAssistantQuery queryParams);
/**
* 删除 AI 助手行为记录。
*
* @param ids 记录ID列表
* @return 是否删除成功
*/
boolean deleteRecords(List<Long> ids);
/**
* 撤销命令执行
*
* @param logId 记录ID
*/
void rollbackCommand(String logId);
}

View File

@@ -299,26 +299,4 @@ public class AiAssistantRecordServiceImpl
return this.baseMapper.getRecordPage(page, queryParams);
}
@Override
public boolean deleteRecords(List<Long> ids) {
if (ids == null || ids.isEmpty()) {
return true;
}
return this.removeByIds(ids);
}
@Override
public void rollbackCommand(String logId) {
AiAssistantRecord commandRecord = this.getById(logId);
if (commandRecord == null) {
throw new RuntimeException("命令记录不存在");
}
if (commandRecord.getExecuteStatus() == null || commandRecord.getExecuteStatus() != 1) {
throw new RuntimeException("只能撤销成功执行的命令");
}
log.info("撤销命令执行: logId={}, function={}", logId, commandRecord.getFunctionName());
throw new UnsupportedOperationException("回滚功能尚未实现");
}
}

View File

@@ -83,8 +83,9 @@ public class CodegenController {
@GetMapping("/{tableName}/preview")
@Log(value = "预览生成代码", module = LogModuleEnum.OTHER)
public Result<List<CodegenPreviewVO>> getTablePreviewData(@PathVariable String tableName,
@RequestParam(value = "pageType", required = false, defaultValue = "classic") String pageType) {
List<CodegenPreviewVO> list = codegenService.getCodegenPreviewData(tableName, pageType);
@RequestParam(value = "pageType", required = false, defaultValue = "classic") String pageType,
@RequestParam(value = "type", required = false, defaultValue = "ts") String type) {
List<CodegenPreviewVO> list = codegenService.getCodegenPreviewData(tableName, pageType, type);
return Result.success(list);
}
@@ -92,9 +93,10 @@ public class CodegenController {
@GetMapping("/{tableName}/download")
@Log(value = "下载代码", module = LogModuleEnum.OTHER)
public void downloadZip(HttpServletResponse response, @PathVariable String tableName,
@RequestParam(value = "pageType", required = false, defaultValue = "classic") String pageType) {
@RequestParam(value = "pageType", required = false, defaultValue = "classic") String pageType,
@RequestParam(value = "type", required = false, defaultValue = "ts") String type) {
String[] tableNames = tableName.split(",");
byte[] data = codegenService.downloadCode(tableNames, pageType);
byte[] data = codegenService.downloadCode(tableNames, pageType, type);
response.reset();
response.setHeader("Content-Disposition", "attachment; filename=" + URLEncoder.encode(codegenProperties.getDownloadFileName(), StandardCharsets.UTF_8));

View File

@@ -29,12 +29,12 @@ public interface CodegenService {
* @param tableName 表名
* @return
*/
List<CodegenPreviewVO> getCodegenPreviewData(String tableName, String pageType);
List<CodegenPreviewVO> getCodegenPreviewData(String tableName, String pageType, String type);
/**
* 下载代码
* @param tableNames 表名
* @return
*/
byte[] downloadCode(String[] tableNames, String pageType);
byte[] downloadCode(String[] tableNames, String pageType, String type);
}

View File

@@ -70,6 +70,52 @@ public class CodegenServiceImpl implements CodegenService {
return databaseMapper.getTablePage(page, queryParams);
}
/**
* 解析前端模板路径
*
* @param templateName 模板标识
* @param templateConfig 模板配置
* @param frontendType 前端类型
* @return 模板路径
*/
private String resolveFrontendTemplatePath(String templateName,
CodegenProperties.TemplateConfig templateConfig,
String frontendType) {
if (!"js".equals(frontendType)) {
return templateConfig.getTemplatePath();
}
if ("API".equals(templateName)) {
return "codegen/api.js.vm";
}
if ("VIEW".equals(templateName)) {
return "codegen/index.js.vue.vm";
}
if ("API_TYPES".equals(templateName)) {
return "codegen/api-types.js.vm";
}
return templateConfig.getTemplatePath();
}
/**
* 解析前端文件后缀
*
* @param templateName 模板标识
* @param templateConfig 模板配置
* @param frontendType 前端类型
* @return 文件后缀
*/
private String resolveFrontendExtension(String templateName,
CodegenProperties.TemplateConfig templateConfig,
String frontendType) {
if (!"js".equals(frontendType)) {
return templateConfig.getExtension();
}
if ("API".equals(templateName) || "API_TYPES".equals(templateName)) {
return ".js";
}
return templateConfig.getExtension();
}
/**
* 获取预览生成代码
*
@@ -77,7 +123,7 @@ public class CodegenServiceImpl implements CodegenService {
* @return 预览数据
*/
@Override
public List<CodegenPreviewVO> getCodegenPreviewData(String tableName, String pageType) {
public List<CodegenPreviewVO> getCodegenPreviewData(String tableName, String pageType, String type) {
List<CodegenPreviewVO> list = new ArrayList<>();
@@ -99,18 +145,25 @@ public class CodegenServiceImpl implements CodegenService {
// 遍历模板配置
Map<String, CodegenProperties.TemplateConfig> templateConfigs = codegenProperties.getTemplateConfigs();
String frontendType = StrUtil.blankToDefault(type, "ts").toLowerCase();
for (Map.Entry<String, CodegenProperties.TemplateConfig> templateConfigEntry : templateConfigs.entrySet()) {
CodegenPreviewVO previewVo = new CodegenPreviewVO();
CodegenProperties.TemplateConfig templateConfig = templateConfigEntry.getValue();
String templateName = templateConfigEntry.getKey();
if ("js".equals(frontendType) && "API_TYPES".equals(templateName)) {
continue;
}
String effectiveTemplatePath = resolveFrontendTemplatePath(templateName, templateConfig, frontendType);
String extension = resolveFrontendExtension(templateName, templateConfig, frontendType);
/* 1. 生成文件名 UserController */
// User Role Menu Dept
String entityName = genTable.getEntityName();
// Controller Service Mapper Entity
String templateName = templateConfigEntry.getKey();
// .java .ts .vue
String extension = templateConfig.getExtension();
// 文件名 UserController.java
String fileName = getFileName(entityName, templateName, extension);
@@ -131,7 +184,13 @@ public class CodegenServiceImpl implements CodegenService {
// 将模板文件中的变量替换为具体的值 生成代码内容
// 优先使用保存的 ui没有则使用请求参数
String finalType = StrUtil.blankToDefault(genTable.getPageType(), pageType);
String content = getCodeContent(templateConfig, genTable, fieldConfigs, finalType);
String content = getCodeContent(
effectiveTemplatePath,
templateConfig.getSubpackageName(),
genTable,
fieldConfigs,
finalType
);
previewVo.setContent(content);
list.add(previewVo);
@@ -232,7 +291,11 @@ public class CodegenServiceImpl implements CodegenService {
* @param pageType 前端页面类型
* @return 渲染后的代码内容
*/
private String getCodeContent(CodegenProperties.TemplateConfig templateConfig, GenTable genTable, List<GenTableColumn> fieldConfigs, String pageType) {
private String getCodeContent(String templatePath,
String subpackageName,
GenTable genTable,
List<GenTableColumn> fieldConfigs,
String pageType) {
Map<String, Object> bindMap = new HashMap<>();
@@ -240,7 +303,7 @@ public class CodegenServiceImpl implements CodegenService {
bindMap.put("packageName", genTable.getPackageName());
bindMap.put("moduleName", genTable.getModuleName());
bindMap.put("subpackageName", templateConfig.getSubpackageName());
bindMap.put("subpackageName", subpackageName);
bindMap.put("date", DateUtil.format(new Date(), "yyyy-MM-dd HH:mm"));
bindMap.put("entityName", entityName);
bindMap.put("tableName", genTable.getTableName());
@@ -282,9 +345,13 @@ public class CodegenServiceImpl implements CodegenService {
TemplateEngine templateEngine = TemplateUtil.createEngine(new TemplateConfig("templates", TemplateConfig.ResourceMode.CLASSPATH));
// 根据 ui 选择不同的前端页面模板:默认 index.vue.vm封装版使用 index.curd.vue.vm
String path = templateConfig.getTemplatePath();
if ("curd".equalsIgnoreCase(pageType) && path.endsWith("index.vue.vm")) {
path = path.replace("index.vue.vm", "index.curd.vue.vm");
String path = templatePath;
if ("curd".equalsIgnoreCase(pageType)) {
if (path.endsWith("index.js.vue.vm")) {
path = path.replace("index.js.vue.vm", "index.curd.js.vue.vm");
} else if (path.endsWith("index.vue.vm")) {
path = path.replace("index.vue.vm", "index.curd.vue.vm");
}
}
Template template = templateEngine.getTemplate(path);
@@ -299,13 +366,13 @@ public class CodegenServiceImpl implements CodegenService {
* @return zip 压缩文件字节数组
*/
@Override
public byte[] downloadCode(String[] tableNames, String ui) {
public byte[] downloadCode(String[] tableNames, String ui, String type) {
try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
ZipOutputStream zip = new ZipOutputStream(outputStream)) {
// 遍历每个表名,生成对应的代码并压缩到 zip 文件中
for (String tableName : tableNames) {
generateAndZipCode(tableName, zip, ui);
generateAndZipCode(tableName, zip, ui, type);
}
// 确保所有压缩数据写入输出流,避免数据残留在内存缓冲区引发的数据不完整
zip.finish();
@@ -324,8 +391,8 @@ public class CodegenServiceImpl implements CodegenService {
* @param zip 压缩文件输出流
* @param ui 页面类型
*/
private void generateAndZipCode(String tableName, ZipOutputStream zip, String ui) {
List<CodegenPreviewVO> codePreviewList = getCodegenPreviewData(tableName, ui);
private void generateAndZipCode(String tableName, ZipOutputStream zip, String ui, String type) {
List<CodegenPreviewVO> codePreviewList = getCodegenPreviewData(tableName, ui, type);
for (CodegenPreviewVO codePreview : codePreviewList) {
String fileName = codePreview.getFileName();

View File

@@ -19,7 +19,7 @@ import org.springframework.web.multipart.MultipartFile;
* @author Ray.Hao
* @since 2022/10/16
*/
@Tag(name = "07.文件接口")
@Tag(name = "10.文件接口")
@RestController
@RequestMapping("/api/v1/files")
@RequiredArgsConstructor

View File

@@ -28,7 +28,7 @@ import org.springframework.security.access.prepost.PreAuthorize;
@Slf4j
@RestController
@RequiredArgsConstructor
@Tag(name = "08.系统配置")
@Tag(name = "07.系统配置")
@RequestMapping("/api/v1/configs")
public class ConfigController {

View File

@@ -16,7 +16,7 @@ import org.springframework.web.bind.annotation.*;
* @author Ray.Hao
* @since 2.10.0
*/
@Tag(name = "10.日志接口")
@Tag(name = "09.日志接口")
@RestController
@RequestMapping("/api/v1/logs")
@RequiredArgsConstructor

View File

@@ -25,7 +25,7 @@ import org.springframework.web.bind.annotation.*;
* @author youlaitech
* @since 2024-08-27 10:31
*/
@Tag(name = "09.通知公告")
@Tag(name = "08.通知公告")
@RestController
@RequestMapping("/api/v1/notices")
@RequiredArgsConstructor

View File

@@ -18,7 +18,7 @@ import java.time.LocalDate;
* @author Ray.Hao
* @since 2025-12-15
*/
@Tag(name = "11.统计分析")
@Tag(name = "12.统计分析")
@RestController
@RequestMapping("/api/v1/statistics")
@RequiredArgsConstructor

View File

@@ -125,6 +125,17 @@ public class UserController {
return Result.judge(result);
}
@Operation(summary = "重置指定用户密码")
@PutMapping(value = "/{userId}/password/reset")
@PreAuthorize("@ss.hasPerm('sys:user:reset-password')")
public Result<?> resetUserPassword(
@Parameter(description = "用户ID") @PathVariable Long userId,
@RequestParam String password
) {
boolean result = userService.resetUserPassword(userId, password);
return Result.judge(result);
}
@Operation(summary = "获取当前登录用户信息")
@GetMapping("/me")
@Log(value = "获取当前登录用户信息", module = LogModuleEnum.USER)
@@ -176,6 +187,13 @@ public class UserController {
.doWrite(exportUserList);
}
@Operation(summary = "获取用户下拉选项")
@GetMapping("/options")
public Result<List<Option<String>>> listUserOptions() {
List<Option<String>> list = userService.listUserOptions();
return Result.success(list);
}
@Operation(summary = "获取个人中心用户信息")
@GetMapping("/profile")
@Log(value = "获取个人中心用户信息", module = LogModuleEnum.USER)
@@ -193,16 +211,6 @@ public class UserController {
return Result.judge(result);
}
@Operation(summary = "重置指定用户密码")
@PutMapping(value = "/{userId}/password/reset")
@PreAuthorize("@ss.hasPerm('sys:user:reset-password')")
public Result<?> resetUserPassword(
@Parameter(description = "用户ID") @PathVariable Long userId,
@RequestParam String password
) {
boolean result = userService.resetUserPassword(userId, password);
return Result.judge(result);
}
@Operation(summary = "当前用户修改密码")
@PutMapping(value = "/password")
@@ -232,6 +240,15 @@ public class UserController {
return Result.judge(result);
}
@Operation(summary = "解绑手机号")
@DeleteMapping(value = "/mobile")
public Result<?> unbindMobile(
@RequestBody @Validated PasswordVerifyForm data
) {
boolean result = userService.unbindMobile(data);
return Result.judge(result);
}
@Operation(summary = "发送邮箱验证码(绑定或更换邮箱)")
@PostMapping(value = "/email/code")
public Result<Void> sendEmailCode(
@@ -250,10 +267,14 @@ public class UserController {
return Result.judge(result);
}
@Operation(summary = "获取用户下拉选项")
@GetMapping("/options")
public Result<List<Option<String>>> listUserOptions() {
List<Option<String>> list = userService.listUserOptions();
return Result.success(list);
@Operation(summary = "解绑邮箱")
@DeleteMapping(value = "/email")
public Result<?> unbindEmail(
@RequestBody @Validated PasswordVerifyForm data
) {
boolean result = userService.unbindEmail(data);
return Result.judge(result);
}
}

View File

@@ -1,6 +1,7 @@
package com.youlai.boot.system.model.form;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.Email;
import jakarta.validation.constraints.NotBlank;
import lombok.Data;
@@ -16,10 +17,15 @@ public class EmailUpdateForm {
@Schema(description = "邮箱")
@NotBlank(message = "邮箱不能为空")
@Email(message = "邮箱格式不正确")
private String email;
@Schema(description = "验证码")
@NotBlank(message = "验证码不能为空")
private String code;
@Schema(description = "当前密码")
@NotBlank(message = "当前密码不能为空")
private String password;
}

View File

@@ -2,6 +2,7 @@ package com.youlai.boot.system.model.form;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Pattern;
import lombok.Data;
/**
@@ -16,10 +17,15 @@ public class MobileUpdateForm {
@Schema(description = "手机号码")
@NotBlank(message = "手机号码不能为空")
@Pattern(regexp = "^1(3\\d|4[5-9]|5[0-35-9]|6[2567]|7[0-8]|8\\d|9[0-35-9])\\d{8}$", message = "手机号码格式不正确")
private String mobile;
@Schema(description = "验证码")
@NotBlank(message = "验证码不能为空")
private String code;
@Schema(description = "当前密码")
@NotBlank(message = "当前密码不能为空")
private String password;
}

View File

@@ -0,0 +1,14 @@
package com.youlai.boot.system.model.form;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank;
import lombok.Data;
@Schema(description = "密码校验表单")
@Data
public class PasswordVerifyForm {
@Schema(description = "当前密码")
@NotBlank(message = "当前密码不能为空")
private String password;
}

View File

@@ -12,13 +12,6 @@ import lombok.Data;
@Schema(description = "个人中心用户信息")
@Data
public class UserProfileForm {
@Schema(description = "用户ID")
private Long id;
@Schema(description = "用户名")
private String username;
@Schema(description = "用户昵称")
private String nickname;
@@ -28,11 +21,4 @@ public class UserProfileForm {
@Schema(description = "性别")
private Integer gender;
@Schema(description = "手机号")
private String mobile;
@Schema(description = "邮箱")
private String email;
}

View File

@@ -158,6 +158,22 @@ public interface UserService extends IService<User> {
*/
boolean bindOrChangeEmail(EmailUpdateForm data);
/**
* 解绑手机号
*
* @param data 表单数据
* @return {@link Boolean} 是否解绑成功
*/
boolean unbindMobile(PasswordVerifyForm data);
/**
* 解绑邮箱
*
* @param data 表单数据
* @return {@link Boolean} 是否解绑成功
*/
boolean unbindEmail(PasswordVerifyForm data);
/**
* 获取用户选项列表
*

View File

@@ -491,9 +491,17 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements Us
@Override
public boolean updateUserProfile(UserProfileForm formData) {
Long userId = SecurityUtils.getUserId();
User entity = userConverter.toEntity(formData);
entity.setId(userId);
return this.updateById(entity);
if (formData.getNickname() == null && formData.getAvatar() == null && formData.getGender() == null) {
throw new BusinessException("请修改至少一个字段");
}
return this.update(new LambdaUpdateWrapper<User>()
.eq(User::getId, userId)
.set(formData.getNickname() != null, User::getNickname, formData.getNickname())
.set(formData.getAvatar() != null, User::getAvatar, formData.getAvatar())
.set(formData.getGender() != null, User::getGender, formData.getGender())
);
}
/**
@@ -523,7 +531,7 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements Us
}
// 判断新密码和确认密码是否一致
if (passwordEncoder.matches(data.getNewPassword(), data.getConfirmPassword())) {
if (!Objects.equals(data.getNewPassword(), data.getConfirmPassword())) {
throw new BusinessException("新密码和确认密码不一致");
}
@@ -569,6 +577,15 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements Us
@Override
public boolean sendMobileCode(String mobile) {
Long currentUserId = SecurityUtils.getUserId();
long mobileCount = this.count(new LambdaQueryWrapper<User>()
.eq(User::getMobile, mobile)
.ne(User::getId, currentUserId)
);
if (mobileCount > 0) {
throw new BusinessException("手机号已被其他账号绑定");
}
// String code = String.valueOf((int) ((Math.random() * 9 + 1) * 1000));
// TODO 为了方便测试,验证码固定为 1234实际开发中在配置了厂商短信服务后可以使用上面的随机验证码
String code = "1234";
@@ -600,6 +617,10 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements Us
throw new BusinessException("用户不存在");
}
if (!passwordEncoder.matches(form.getPassword(), currentUser.getPassword())) {
throw new BusinessException("当前密码错误");
}
// 校验验证码
String inputVerifyCode = form.getCode();
String mobile = form.getMobile();
@@ -614,7 +635,15 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements Us
if (!inputVerifyCode.equals(cachedVerifyCode)) {
throw new BusinessException("验证码错误");
}
// 验证完成删除验证码
long mobileCount = this.count(new LambdaQueryWrapper<User>()
.eq(User::getMobile, mobile)
.ne(User::getId, currentUserId)
);
if (mobileCount > 0) {
throw new BusinessException("手机号已被其他账号绑定");
}
redisTemplate.delete(cacheKey);
// 更新手机号码
@@ -633,6 +662,15 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements Us
@Override
public void sendEmailCode(String email) {
Long currentUserId = SecurityUtils.getUserId();
long emailCount = this.count(new LambdaQueryWrapper<User>()
.eq(User::getEmail, email)
.ne(User::getId, currentUserId)
);
if (emailCount > 0) {
throw new BusinessException("邮箱已被其他账号绑定");
}
// String code = String.valueOf((int) ((Math.random() * 9 + 1) * 1000));
// TODO 为了方便测试,验证码固定为 1234实际开发中在配置了邮箱服务后可以使用上面的随机验证码
String code = "1234";
@@ -659,6 +697,10 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements Us
throw new BusinessException("用户不存在");
}
if (!passwordEncoder.matches(form.getPassword(), currentUser.getPassword())) {
throw new BusinessException("当前密码错误");
}
// 获取前端输入的验证码
String inputVerifyCode = form.getCode();
@@ -674,7 +716,15 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements Us
if (!inputVerifyCode.equals(cachedVerifyCode)) {
throw new BusinessException("验证码错误");
}
// 验证完成删除验证码
long emailCount = this.count(new LambdaQueryWrapper<User>()
.eq(User::getEmail, email)
.ne(User::getId, currentUserId)
);
if (emailCount > 0) {
throw new BusinessException("邮箱已被其他账号绑定");
}
redisTemplate.delete(redisCacheKey);
// 更新邮箱地址
@@ -685,6 +735,66 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements Us
);
}
/**
* 解绑手机号
*
* @param form 表单数据
* @return true|false
*/
@Override
public boolean unbindMobile(PasswordVerifyForm form) {
Long currentUserId = SecurityUtils.getUserId();
User currentUser = this.getById(currentUserId);
if (currentUser == null) {
throw new BusinessException("用户不存在");
}
if (StrUtil.isBlank(currentUser.getMobile())) {
throw new BusinessException("当前账号未绑定手机号");
}
if (!passwordEncoder.matches(form.getPassword(), currentUser.getPassword())) {
throw new BusinessException("当前密码错误");
}
return this.update(new LambdaUpdateWrapper<User>()
.eq(User::getId, currentUserId)
.set(User::getMobile, null)
);
}
/**
* 解绑邮箱
*
* @param form 表单数据
* @return true|false
*/
@Override
public boolean unbindEmail(PasswordVerifyForm form) {
Long currentUserId = SecurityUtils.getUserId();
User currentUser = this.getById(currentUserId);
if (currentUser == null) {
throw new BusinessException("用户不存在");
}
if (StrUtil.isBlank(currentUser.getEmail())) {
throw new BusinessException("当前账号未绑定邮箱");
}
if (!passwordEncoder.matches(form.getPassword(), currentUser.getPassword())) {
throw new BusinessException("当前密码错误");
}
return this.update(new LambdaUpdateWrapper<User>()
.eq(User::getId, currentUserId)
.set(User::getEmail, null)
);
}
/**
* 获取用户选项列表
*