ruoyi-admin/src/main/java/com/ruoyi/im/config/AddTeamMembersRequest.java
@@ -2,7 +2,6 @@ import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonProperty; import com.sun.istack.internal.NotNull; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; ruoyi-admin/src/main/java/com/ruoyi/im/config/UpdateUserInfoRequest.java
@@ -1,207 +1,111 @@ package com.ruoyi.im.config; import cn.hutool.json.JSONObject; import com.fasterxml.jackson.annotation.JsonProperty; import java.util.HashMap; import java.util.Map; public class UpdateUserInfoRequest { private Map<String, Object> bodyData; @JsonProperty("avatar") private String avatar; public UpdateUserInfoRequest() { bodyData = new HashMap<>(); @JsonProperty("name") private String name; @JsonProperty("sign") private String sign; @JsonProperty("email") private String email; @JsonProperty("mobile") private String mobile; // 无参构造函数 public UpdateUserInfoRequest() {} // 全参构造函数(可选) public UpdateUserInfoRequest(String avatar, String name, String sign, String email, String mobile) { this.avatar = avatar; this.name = name; this.sign = sign; this.email = email; this.mobile = mobile; } /** * 设置name字段 */ public UpdateUserInfoRequest setName(String name) { if (name != null) { bodyData.put("name", name); } // Getter 和 Setter 方法 public String getAvatar() { return avatar; } public void setAvatar(String avatar) { this.avatar = avatar; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getSign() { return sign; } public void setSign(String sign) { this.sign = sign; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } public String getMobile() { return mobile; } public void setMobile(String mobile) { this.mobile = mobile; } // toString 方法(可选,便于调试) @Override public String toString() { return "UpdateUserInfoRequest{" + "avatar='" + avatar + '\'' + ", name='" + name + '\'' + ", sign='" + sign + '\'' + ", email='" + email + '\'' + ", mobile=" + mobile + '}'; } // Builder 模式(可选,便于链式调用) public UpdateUserInfoRequest avatar(String avatar) { this.avatar = avatar; return this; } /** * 设置avatar字段 */ public UpdateUserInfoRequest setAvatar(String avatar) { if (avatar != null) { bodyData.put("avatar", avatar); } public UpdateUserInfoRequest name(String name) { this.name = name; return this; } /** * 设置sign字段 */ public UpdateUserInfoRequest setSign(String sign) { if (sign != null) { bodyData.put("sign", sign); } public UpdateUserInfoRequest sign(String sign) { this.sign = sign; return this; } /** * 设置email字段 */ public UpdateUserInfoRequest setEmail(String email) { if (email != null) { bodyData.put("email", email); } public UpdateUserInfoRequest email(String email) { this.email = email; return this; } /** * 设置birthday字段 */ public UpdateUserInfoRequest setBirthday(String birthday) { if (birthday != null) { bodyData.put("birthday", birthday); } public UpdateUserInfoRequest mobile(String mobile) { this.mobile = mobile; return this; } /** * 设置mobile字段 */ public UpdateUserInfoRequest setMobile(String mobile) { if (mobile != null) { bodyData.put("mobile", mobile); } return this; } /** * 设置gender字段 */ public UpdateUserInfoRequest setGender(String gender) { if (gender != null) { bodyData.put("gender", gender); } return this; } /** * 设置extension字段 */ public UpdateUserInfoRequest setExtension(String extension) { if (extension != null) { bodyData.put("extension", extension); } return this; } /** * 批量设置所有字段 */ public UpdateUserInfoRequest setAllFields(Map<String, Object> fields) { if (fields != null) { for (Map.Entry<String, Object> entry : fields.entrySet()) { String key = entry.getKey(); Object value = entry.getValue(); if (value != null) { switch (key) { case "name": setName((String) value); break; case "avatar": setAvatar((String) value); break; case "sign": setSign((String) value); break; case "email": setEmail((String) value); break; case "birthday": setBirthday((String) value); break; case "mobile": setMobile((String) value); break; case "gender": setGender((String) value); break; case "extension": setExtension((String) value); break; default: // 忽略未知字段 break; } } } } return this; } /** * 构建JSON字符串 */ public String build() { JSONObject jsonObject = new JSONObject(bodyData); return jsonObject.toString(); } /** * 获取Map形式的数据 */ public Map<String, Object> getBodyData() { return new HashMap<>(bodyData); } /** * 清空所有已设置的数据 */ public void clear() { bodyData.clear(); } /** * 使用示例 */ public static void main(String[] args) { // 示例1: 只设置部分字段 UpdateUserInfoRequest builder = new UpdateUserInfoRequest(); String partialBody = builder .setName("zhangsan") .setEmail("zhangsan@corp.xx.com") .setMobile("13312345678") .build(); System.out.println("部分字段请求体: " + partialBody); // 示例2: 使用Map批量设置 builder.clear(); Map<String, Object> fields = new HashMap<>(); fields.put("name", "lisi"); fields.put("avatar", "http://xxxx.xx/lisi.png"); fields.put("sign", "Hello World"); fields.put("gender", "1"); String batchBody = builder.setAllFields(fields).build(); System.out.println("批量设置请求体: " + batchBody); // 示例3: 完全不设置任何字段 builder.clear(); String emptyBody = builder.build(); System.out.println("空请求体: " + emptyBody); // 示例4: 设置所有字段 builder.clear(); String fullBody = builder .setName("zhangsan") .setAvatar("http://xxxx.xx/x.png") .setSign("Hello World") .setEmail("zhangsan@corp.xx.com") .setBirthday("1990-01-01") .setMobile("13312345678") .setGender("2") .setExtension("xxxx") .build(); System.out.println("完整请求体: " + fullBody); } } } ruoyi-admin/src/main/java/com/ruoyi/im/dto/RegisterDto.java
@@ -9,15 +9,13 @@ @Data public class RegisterDto { @NotNull(message = "账号不能为空") private String account; // 账号 @NotEmpty(message = "密码不能为空") private String password; // 密码 private String confirmPassword; // 再次确认密码 private String name; // 昵称 private String nickname; // 昵称 private Integer type;//类型 1 批量 2 单一 ruoyi-admin/src/main/java/com/ruoyi/im/out/UserAccountOut.java
New file @@ -0,0 +1,44 @@ package com.ruoyi.im.out; import com.baomidou.mybatisplus.annotation.FieldFill; import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableId; import com.fasterxml.jackson.annotation.JsonFormat; import lombok.Data; import java.math.BigDecimal; import java.util.Date; @Data public class UserAccountOut { // 账号(唯一) private String account; // 手机号(唯一) private String phoneNumber; // 云信账号 private String cloudMessageAccount; // 昵称 private String nickname; // 账号状态: 0:正常 1:禁用 private Integer status; // 最近登录时间 private Date loginTime; // 最近登录IP private String loginIp; // 注册时间 private Date registerTime; // 个性签名 private String signature; } ruoyi-admin/src/main/java/com/ruoyi/im/service/impl/ImApiServcieImpl.java
@@ -72,6 +72,7 @@ @Autowired private JdbcTemplate jdbcTemplate; @Resource private final YunxinApiHttpClient yunxinClient; // 使用构造函数注入(推荐) @@ -102,17 +103,17 @@ @Override @Transactional(rollbackFor = Exception.class) // 添加事务注解确保操作原子性 @Transactional(rollbackFor = Exception.class) public Result register(RegisterDto dto) { try { // 验证手机号是否已存在(数据库唯一索引提供最终保障) // 验证手机号是否已存在 List<UserAccount> accounts = userAccountService.list( new LambdaQueryWrapper<>(UserAccount.class) .eq(UserAccount::getAccount, dto.getAccount()) ); if (!CollectionUtils.isEmpty(accounts)) { return Result.error("手机号已注册!"); return Result.error("账号已被注册!"); } // 创建本地用户账户记录 @@ -122,18 +123,17 @@ userAccount.setCloudMessageAccount(dto.getAccount()); userAccount.setPassword(SymmetricCryptoUtil.encryptPassword(dto.getPassword())); userAccount.setCreateTime(new Date()); userAccount.setNickname(dto.getAccount()); userAccount.setNickname(dto.getNickname()); if (!userAccountService.save(userAccount)) { return Result.error("注册失败,请重试"); throw new RuntimeException("保存用户账户失败"); // 改为抛出异常 } // 注册云信账号(远程调用) Map<String, String> paramMap = new HashMap<>(); paramMap.put("accid", dto.getAccount()); if(StringUtils.isNotEmpty(dto.getName())){ paramMap.put("name", dto.getName()); if(StringUtils.isNotEmpty(dto.getNickname())){ paramMap.put("name", dto.getNickname()); } paramMap.put("token", dto.getPassword()); @@ -159,26 +159,15 @@ neteaseTeamService.inviteTeamMembers(request); } return Result.success("注册成功"); } else if (code == 414) { // 手动触发回滚(事务注解会自动处理) TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); return Result.error("账号已被注册!"); } else { // 其他错误码同样触发回滚 TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); log.error("云信注册失败,响应: {}, traceId: {}", data, response.getTraceId()); return Result.error("注册失败,错误码: " + code); // 所有非200状态码都抛出异常触发回滚 throw new RuntimeException("云信注册失败,错误码: " + code + ", 响应: " + data); } } catch (YunxinSdkException e) { // 云信调用异常时回滚事务 TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); log.error("云信服务调用异常 traceId: {}", e.getTraceId(), e); return Result.error("注册失败,系统异常"); } catch (Exception e) { // 其他异常同样回滚 TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); log.error("注册过程发生未知异常", e); return Result.error("注册失败,请重试"); // 记录异常日志 log.error("注册过程发生异常", e); // 重新抛出异常以确保事务回滚 throw new RuntimeException("注册失败: " + e.getMessage(), e); } } @@ -275,18 +264,24 @@ httpPatch.setHeader("CheckSum", checkSum); // 构建请求体 UpdateUserInfoRequest builder = new UpdateUserInfoRequest(); if(StringUtils.isNotEmpty(dto.getMobile())){ builder.setMobile(dto.getMobile()); }else if(StringUtils.isNotEmpty(dto.getName())){ builder.setName(dto.getName()); }else if(StringUtils.isNotEmpty(dto.getSign())){ builder.setSign(dto.getSign()); }else if(StringUtils.isNotEmpty(dto.getAvatar())){ builder.setAvatar(dto.getAvatar()); } String body = builder.build(); String jsonBody = objectMapper.writeValueAsString(body); // UpdateUserInfoRequest builder = new UpdateUserInfoRequest(); // if(StringUtils.isNotEmpty(dto.getMobile())){ // builder.setMobile(dto.getMobile()); // } // if(StringUtils.isNotEmpty(dto.getName())){ // builder.setName(dto.getName()); // } // if(StringUtils.isNotEmpty(dto.getSign())){ // builder.setSign(dto.getSign()); // } // if(StringUtils.isNotEmpty(dto.getAvatar())){ // builder.setAvatar(dto.getAvatar()); // } // String body = builder.build(); UpdateUserInfoRequest requestBody = new UpdateUserInfoRequest(dto.getAvatar(), dto.getName(),dto.getSign(),dto.getEmail(),dto.getMobile()); String jsonBody = objectMapper.writeValueAsString(requestBody); // String jsonBody = objectMapper.writeValueAsString(body); httpPatch.setEntity(new StringEntity(jsonBody, StandardCharsets.UTF_8)); // 执行请求 @@ -298,11 +293,11 @@ if (neteaseResponse.isSuccess()) { result.put("success", true); result.put("message", "头像更新成功"); result.put("message", "更新成功"); result.put("data", neteaseResponse.getData()); } else { result.put("success", false); result.put("message", "头像更新失败: " + neteaseResponse.getMsg()); result.put("message", "更新失败: " + neteaseResponse.getMsg()); result.put("errorCode", neteaseResponse.getCode()); } @@ -332,9 +327,11 @@ UpdateUserBusinessDto dto = new UpdateUserBusinessDto(); if(StringUtils.isNotEmpty(vo.getPhoneNumber())){ dto.setMobile(vo.getPhoneNumber()); }else if(StringUtils.isNotEmpty(vo.getNickname())){ } if(StringUtils.isNotEmpty(vo.getNickname())){ dto.setName(vo.getNickname()); }else if(StringUtils.isNotEmpty(vo.getSignature())){ } if(StringUtils.isNotEmpty(vo.getSignature())){ dto.setSign(vo.getSignature()); } Map<String, Object> map = updateUserAvatar(vo.getAccountId(), dto); @@ -343,11 +340,25 @@ AjaxResult ajaxResult = updateAccountProperties(vo.getAccountId(), vo); if(ajaxResult.isSuccess()){ UserAccount userAccount = userAccountService.getById(vo.getId()); userAccount.setPhoneNumber(vo.getPhoneNumber()); userAccount.setAccount(vo.getAccountId()); userAccount.setNickname(vo.getNickname()); userAccount.setPassword(SymmetricCryptoUtil.encryptPassword(vo.getPassword())); userAccount.setSignature(vo.getSignature()); if (StringUtils.isNotBlank(vo.getPhoneNumber())) { userAccount.setPhoneNumber(vo.getPhoneNumber()); } if (StringUtils.isNotBlank(vo.getAccountId())) { userAccount.setAccount(vo.getAccountId()); } if (StringUtils.isNotBlank(vo.getNickname())) { userAccount.setNickname(vo.getNickname()); } if (StringUtils.isNotBlank(vo.getPassword())) { userAccount.setPassword(SymmetricCryptoUtil.encryptPassword(vo.getPassword())); } if (StringUtils.isNotBlank(vo.getSignature())) { userAccount.setSignature(vo.getSignature()); } userAccount.setUpdateTime(new Date()); userAccountService.updateById(userAccount); }else{ @@ -391,7 +402,8 @@ if(null != vo.getStatus() && vo.getStatus() == 0){ builder.setEnabled(false); builder.setNeedKick(true); }else if(StringUtils.isNotEmpty(vo.getPassword())){ } if(StringUtils.isNotEmpty(vo.getPassword())){ builder.setToken(vo.getPassword()); } // 只设置需要的字段 @@ -427,6 +439,7 @@ * @return */ @Override @Transactional(rollbackFor = Exception.class) public Result batchRegister(RegisterDto dto) { if(dto.getType() == 2){ return register(dto); ruoyi-admin/src/main/java/com/ruoyi/im/service/impl/NeteaseTeamServiceImpl.java
@@ -30,6 +30,7 @@ @Service public class NeteaseTeamServiceImpl extends ServiceImpl<NeteaseTeamMapper, NeteaseTeam> implements NeteaseTeamService { @Resource private final YunxinApiHttpClient yunxinClient; // 使用构造函数注入(推荐) ruoyi-admin/src/main/java/com/ruoyi/im/util/ConverterUtil.java
New file @@ -0,0 +1,45 @@ package com.ruoyi.im.util; import java.lang.reflect.Field; import java.util.ArrayList; import java.util.List; /** * @program: dabaogp * @description: * @create: 2024-08-19 18:29 **/ public class ConverterUtil { public static <T, V> V convert(T pojo, Class<V> voClass) { try { V vo = voClass.newInstance(); Field[] pojoFields = pojo.getClass().getDeclaredFields(); Field[] voFields = voClass.getDeclaredFields(); for (Field pojoField : pojoFields) { pojoField.setAccessible(true); for (Field voField : voFields) { voField.setAccessible(true); if (pojoField.getName().equals(voField.getName()) && pojoField.getType().equals(voField.getType())) { voField.set(vo, pojoField.get(pojo)); break; } } } return vo; } catch (InstantiationException | IllegalAccessException e) { e.printStackTrace(); return null; } } public static <T, V> List<V> convertToList(List<T> pojoList, Class<V> voClass) { List<V> voList = new ArrayList<>(); for (T pojo : pojoList) { V vo = convert(pojo, voClass); voList.add(vo); } return voList; } } ruoyi-admin/src/main/java/com/ruoyi/im/util/PhoneNumberValidatorUtil.java
New file @@ -0,0 +1,208 @@ package com.ruoyi.im.util; import java.util.regex.Pattern; import java.util.regex.Matcher; import java.util.HashMap; import java.util.Map; /** * 手机号格式校验工具类 * 支持中国大陆手机号和国际手机号验证 */ public class PhoneNumberValidatorUtil { // 中国大陆手机号正则表达式 (11位数字,1开头) private static final String CHINA_MOBILE_PATTERN = "^1[3-9]\\d{9}$"; // 国际手机号正则表达式 (国家代码-号码,如+1-1234567890) private static final String INTERNATIONAL_PATTERN = "^\\+\\d{1,4}-\\d{4,15}$"; // 常见国家/地区代码映射表 private static final Map<String, String> COUNTRY_CODES = new HashMap<>(); static { // 初始化常见国家/地区代码 COUNTRY_CODES.put("1", "美国/加拿大"); COUNTRY_CODES.put("86", "中国大陆"); COUNTRY_CODES.put("852", "香港"); COUNTRY_CODES.put("853", "澳门"); COUNTRY_CODES.put("886", "台湾"); COUNTRY_CODES.put("81", "日本"); COUNTRY_CODES.put("82", "韩国"); COUNTRY_CODES.put("65", "新加坡"); COUNTRY_CODES.put("60", "马来西亚"); COUNTRY_CODES.put("44", "英国"); COUNTRY_CODES.put("33", "法国"); COUNTRY_CODES.put("49", "德国"); COUNTRY_CODES.put("61", "澳大利亚"); // 可以继续添加更多国家/地区代码 } /** * 验证手机号格式 * @param phoneNumber 手机号码 * @return 验证结果 */ public static ValidationResult validatePhoneNumber(String phoneNumber) { if (phoneNumber == null || phoneNumber.trim().isEmpty()) { return new ValidationResult(false, "手机号不能为空"); } // 去除可能存在的空格 phoneNumber = phoneNumber.trim(); // 检查是否为中国大陆手机号 if (Pattern.matches(CHINA_MOBILE_PATTERN, phoneNumber)) { return new ValidationResult(true, "中国大陆手机号格式正确"); } // 检查是否为国际手机号格式 if (Pattern.matches(INTERNATIONAL_PATTERN, phoneNumber)) { // 提取国家代码部分 String[] parts = phoneNumber.split("-", 2); String countryCode = parts[0].substring(1); // 去掉+号 // 验证国家代码是否有效 if (COUNTRY_CODES.containsKey(countryCode)) { return new ValidationResult(true, "国际手机号格式正确 (" + COUNTRY_CODES.get(countryCode) + ")"); } else { return new ValidationResult(false, "不支持的国家/地区代码: +" + countryCode); } } // 如果都不匹配,返回错误信息 if (phoneNumber.startsWith("+")) { return new ValidationResult(false, "国际手机号格式不正确,请使用'+国家代码-本地号码'格式"); } else { return new ValidationResult(false, "中国大陆手机号应为11位数字且以1开头"); } } /** * 验证结果类 */ public static class ValidationResult { private final boolean valid; private final String message; public ValidationResult(boolean valid, String message) { this.valid = valid; this.message = message; } public boolean isValid() { return valid; } public String getMessage() { return message; } @Override public String toString() { return message; } } /** * 提取国家代码(如果是国际手机号) * @param phoneNumber 手机号码 * @return 国家代码(不带+号),如果是中国大陆手机号返回"86" */ public static String extractCountryCode(String phoneNumber) { if (phoneNumber == null || phoneNumber.trim().isEmpty()) { return null; } phoneNumber = phoneNumber.trim(); // 如果是国际手机号格式 if (Pattern.matches(INTERNATIONAL_PATTERN, phoneNumber)) { String[] parts = phoneNumber.split("-", 2); return parts[0].substring(1); // 去掉+号 } // 如果是中国大陆手机号 if (Pattern.matches(CHINA_MOBILE_PATTERN, phoneNumber)) { return "86"; } return null; } /** * 提取本地号码部分 * @param phoneNumber 手机号码 * @return 本地号码部分 */ public static String extractLocalNumber(String phoneNumber) { if (phoneNumber == null || phoneNumber.trim().isEmpty()) { return null; } phoneNumber = phoneNumber.trim(); // 如果是国际手机号格式 if (Pattern.matches(INTERNATIONAL_PATTERN, phoneNumber)) { String[] parts = phoneNumber.split("-", 2); return parts[1]; } // 如果是中国大陆手机号 if (Pattern.matches(CHINA_MOBILE_PATTERN, phoneNumber)) { return phoneNumber; } return null; } /** * 格式化手机号显示 * @param phoneNumber 手机号码 * @return 格式化后的手机号 */ public static String formatPhoneNumber(String phoneNumber) { ValidationResult result = validatePhoneNumber(phoneNumber); if (!result.isValid()) { return phoneNumber; // 如果格式不正确,返回原值 } if (Pattern.matches(CHINA_MOBILE_PATTERN, phoneNumber)) { // 中国大陆手机号格式化为 3-4-4 格式 return phoneNumber.replaceFirst("(\\d{3})(\\d{4})(\\d{4})", "$1-$2-$3"); } else if (Pattern.matches(INTERNATIONAL_PATTERN, phoneNumber)) { // 国际手机号保持原格式 return phoneNumber; } return phoneNumber; } // 测试方法 public static void main(String[] args) { // 测试用例 String[] testNumbers = { "13800138000", // 中国大陆手机号 "+1-1234567890", // 美国手机号 "+852-12345678", // 香港手机号 "12345678901", // 无效的中国大陆手机号(不以1开头) "+86-13800138000", // 带国家代码的中国大陆手机号 "+999-1234567890", // 不支持的国家代码 "+1-123", // 号码部分太短 "abc", // 完全无效 "+1-1234567890123456" // 号码部分太长 }; for (String number : testNumbers) { ValidationResult result = validatePhoneNumber(number); System.out.println(number + " : " + result.getMessage()); if (result.isValid()) { System.out.println(" 国家代码: " + extractCountryCode(number)); System.out.println(" 本地号码: " + extractLocalNumber(number)); System.out.println(" 格式化: " + formatPhoneNumber(number)); } System.out.println(); } } } ruoyi-admin/src/main/java/com/ruoyi/web/controller/group/ImGroupController.java
@@ -1,15 +1,24 @@ package com.ruoyi.web.controller.group; import cn.hutool.core.util.ObjectUtil; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.ruoyi.common.core.controller.BaseController; import com.ruoyi.common.core.domain.AjaxResult; import com.ruoyi.common.core.page.TableDataInfo; import com.ruoyi.im.config.AddTeamMembersRequest; import com.ruoyi.im.config.CreateTeamRequest; import com.ruoyi.im.config.AssignmentRequest; import com.ruoyi.im.service.NeteaseTeamService; import com.ruoyi.system.domain.NeteaseTeam; import com.ruoyi.system.domain.UserAccount; import com.ruoyi.system.domain.vo.UserAccountVo; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; import java.util.List; @RestController @RequestMapping("/im/group") @@ -21,6 +30,34 @@ NeteaseTeamService neteaseGroupService; /** * 获取会员列表 */ @PreAuthorize("@ss.hasPermi('im:group:list')") @GetMapping("/list") public TableDataInfo list(@PathVariable("keyword") String keyword) { // 创建查询条件包装器 LambdaQueryWrapper<NeteaseTeam> queryWrapper = new LambdaQueryWrapper<>(); // 只有当 keyword 不为空时才添加 OR 条件 if (ObjectUtil.isNotEmpty(keyword)) { queryWrapper.and(wrapper -> wrapper .eq(NeteaseTeam::getTid, keyword) .or() .eq(NeteaseTeam::getOwnerAccountId, keyword) .or() .eq(NeteaseTeam::getName,keyword) ); } // 默认按创建时间倒序 queryWrapper.orderByDesc(NeteaseTeam::getCreateTime); List<NeteaseTeam> list = neteaseGroupService.list(queryWrapper); return getDataTable(list); } /** * 创建群组 */ @PostMapping("/create") ruoyi-admin/src/main/java/com/ruoyi/web/controller/user/UserController.java
@@ -9,7 +9,10 @@ import com.ruoyi.common.utils.StringUtils; import com.ruoyi.im.comm.Result; import com.ruoyi.im.dto.RegisterDto; import com.ruoyi.im.out.UserAccountOut; import com.ruoyi.im.service.ImApiServcie; import com.ruoyi.im.util.ConverterUtil; import com.ruoyi.im.util.PhoneNumberValidatorUtil; import com.ruoyi.system.domain.UserAccount; import com.ruoyi.system.domain.vo.UserAccountUpdateVo; import com.ruoyi.system.domain.vo.UserAccountVo; @@ -45,6 +48,7 @@ public TableDataInfo list(UserAccountVo vo) { // 创建查询条件包装器 LambdaQueryWrapper<UserAccount> queryWrapper = new LambdaQueryWrapper<>(); // 只有当 keyword 不为空时才添加 OR 条件 @@ -70,13 +74,14 @@ // 默认按创建时间倒序 queryWrapper.orderByDesc(UserAccount::getCreateTime); List<UserAccount> list = userAccountService.list(queryWrapper); return getDataTable(list); List<UserAccountOut> toList = ConverterUtil.convertToList(list, UserAccountOut.class); return getDataTable(toList); } /** * 修改会员 */ @PreAuthorize("@ss.hasPermi('im:user:updateUserAccount')") // @PreAuthorize("@ss.hasPermi('im:user:updateUserAccount')") @PostMapping("/updateUserAccount") public AjaxResult updateUserAccount(UserAccountUpdateVo vo) { @@ -85,6 +90,11 @@ if(ObjectUtil.isEmpty(userAccount)){ return AjaxResult.error("会员不存在!"); } PhoneNumberValidatorUtil.ValidationResult result = PhoneNumberValidatorUtil.validatePhoneNumber(vo.getPhoneNumber()); if(!result.isValid()){ return AjaxResult.error("手机号格式不正确!"); } vo.setAccountId(userAccount.getCloudMessageAccount()); return imApiServcie.updateUserAccount(vo); }catch (Exception e){ e.printStackTrace(); @@ -94,14 +104,34 @@ } /** * 批量注册 * 创建会员 */ @PostMapping("/batchRegister") public Result batchRegister(@Validated RegisterDto dto){ try { if(null == dto.getType()){ return Result.error("类型不能为空"); }else if(dto.getType() == 2){ if(StringUtils.isEmpty(dto.getAccount())){ return Result.error("账号不能为空"); } if(StringUtils.isEmpty(dto.getPassword())){ return Result.error("密码不能为空"); } if(StringUtils.isEmpty(dto.getNickname())){ return Result.error("昵称不能为空"); } }else if (dto.getType() == 1){ if(dto.getNumber() <= 0){ return Result.error("数量不能为空"); }else if(dto.getNumber() > 100){ return Result.error("批量注册最多一次100"); } } return imApiServcie.batchRegister(dto); }catch (Exception e){ log.error("批量注册报错:",e); e.printStackTrace(); log.error("-----------批量注册报错------------"); return Result.error("注册失败,请稍后再试!"); } } ruoyi-system/src/main/java/com/ruoyi/system/domain/vo/UserAccountVo.java
@@ -28,7 +28,7 @@ private String password; // 账号类型: 0:真实 1:虚拟 private Integer accountType = 0; private Integer accountType; // 云信账号 private String cloudMessageAccount; @@ -37,7 +37,7 @@ private String nickname; // 账号状态: 0:正常 1:禁用 private Integer status = 0; private Integer status; // 最近登录时间 private Date loginTime;