From 01bd03652fef2399c2acfb1930d044b106393f85 Mon Sep 17 00:00:00 2001
From: zj <1772600164@qq.com>
Date: Thu, 21 Aug 2025 03:35:37 +0800
Subject: [PATCH] 1

---
 ruoyi-admin/src/main/java/com/ruoyi/im/dto/UpdateUserBusinessDto.java                |   26 
 ruoyi-system/src/main/java/com/ruoyi/system/domain/vo/UserAccountUpdateVo.java       |   43 
 ruoyi-admin/src/main/java/com/ruoyi/im/config/DynamicRequestBodyBuilder.java         |  190 +++++
 ruoyi-admin/src/main/java/com/ruoyi/RuoYiApplication.java                            |    1 
 ruoyi-admin/src/main/java/com/ruoyi/im/ImApiController.java                          |  114 +++
 ruoyi-admin/src/main/java/com/ruoyi/web/controller/group/ImGroupController.java      |   33 +
 ruoyi-admin/src/main/java/com/ruoyi/im/config/YunxinClientConfig.java                |   26 
 ruoyi-admin/src/main/java/com/ruoyi/im/service/impl/NeteaseTeamServiceImpl.java      |  181 +++++
 ruoyi-system/src/main/java/com/ruoyi/system/domain/NeteaseTeam.java                  |  138 ++++
 ruoyi-admin/src/main/java/com/ruoyi/im/config/UpdateAccountRequest.java              |   34 +
 ruoyi-admin/src/main/resources/application.yml                                       |   16 
 ruoyi-admin/src/main/java/com/ruoyi/im/dto/CreateGroupDto.java                       |  102 +++
 ruoyi-admin/src/main/java/com/ruoyi/im/dto/UpdateGroupDto.java                       |   94 ++
 ruoyi-admin/src/main/java/com/ruoyi/im/service/impl/ImApiServcieImpl.java            |  393 +++++++++++
 ruoyi-admin/src/main/java/com/ruoyi/web/controller/user/UserController.java          |   69 +
 ruoyi-admin/src/main/java/com/ruoyi/im/service/NeteaseTeamService.java               |   16 
 ruoyi-admin/src/main/java/com/ruoyi/im/service/ImApiServcie.java                     |   11 
 ruoyi-admin/src/main/java/com/ruoyi/im/config/CreateTeamRequest.java                 |  124 +++
 ruoyi-admin/src/main/java/com/ruoyi/im/dto/RegisterDto.java                          |    7 
 ruoyi-framework/src/main/java/com/ruoyi/framework/config/SecurityConfig.java         |    2 
 ruoyi-system/src/main/java/com/ruoyi/system/mapper/NeteaseTeamMapper.java            |    9 
 ruoyi-system/src/main/java/com/ruoyi/system/service/UserAccountService.java          |    2 
 ruoyi-admin/src/main/java/com/ruoyi/im/config/NeteaseResponse.java                   |   38 +
 ruoyi-system/src/main/java/com/ruoyi/system/service/impl/UserAccountServiceImpl.java |   15 
 ruoyi-admin/src/main/java/com/ruoyi/im/config/UpdateUserInfoRequest.java             |  207 ++++++
 25 files changed, 1,836 insertions(+), 55 deletions(-)

diff --git a/ruoyi-admin/src/main/java/com/ruoyi/RuoYiApplication.java b/ruoyi-admin/src/main/java/com/ruoyi/RuoYiApplication.java
index d37e153..8b94057 100644
--- a/ruoyi-admin/src/main/java/com/ruoyi/RuoYiApplication.java
+++ b/ruoyi-admin/src/main/java/com/ruoyi/RuoYiApplication.java
@@ -4,6 +4,7 @@
 import org.springframework.boot.SpringApplication;
 import org.springframework.boot.autoconfigure.SpringBootApplication;
 import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
+import org.springframework.context.annotation.ComponentScan;
 
 /**
  * 启动程序
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/im/ImApiController.java b/ruoyi-admin/src/main/java/com/ruoyi/im/ImApiController.java
index 6b12c7b..2ab0c4a 100644
--- a/ruoyi-admin/src/main/java/com/ruoyi/im/ImApiController.java
+++ b/ruoyi-admin/src/main/java/com/ruoyi/im/ImApiController.java
@@ -2,15 +2,29 @@
 
 import com.ruoyi.common.core.domain.R;
 import com.ruoyi.im.comm.Result;
+import com.ruoyi.im.dto.UpdateUserBusinessDto;
 import com.ruoyi.im.service.ImApiServcie;
 import com.ruoyi.im.dto.RegisterDto;
+import io.swagger.annotations.ApiOperation;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
 import org.springframework.validation.annotation.Validated;
-import org.springframework.web.bind.annotation.PostMapping;
-import org.springframework.web.bind.annotation.RequestBody;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.web.multipart.MultipartFile;
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.nio.file.attribute.PosixFilePermission;
+import java.nio.file.attribute.PosixFilePermissions;
+import java.util.Map;
+import java.util.Set;
+import java.util.UUID;
 
 @RestController
 @RequestMapping("/im/api")
@@ -19,6 +33,14 @@
 
     @Autowired
     private ImApiServcie imApiServcie;
+
+
+    @Value("${file.upload-dir}")
+    private String uploadDir;
+
+    @Value("${file.upload-prefix}")
+    private String prefix;
+
 
     /**
      * 获取参数配置列表
@@ -32,4 +54,88 @@
             return Result.error("注册失败,请稍后再试!");
         }
     }
+
+
+    @PostMapping("/upload")
+    public Result uploadFile(@RequestParam("file") MultipartFile file,@RequestParam("accountId") String accountId) {
+        try {
+
+            // 1. 验证文件类型
+            String contentType = file.getContentType();
+            if (contentType == null ||
+                    (!contentType.equals("image/jpeg") &&
+                            !contentType.equals("image/png") &&
+                            !contentType.equals("image/gif"))) {
+
+                return Result.error("只支持JPEG、PNG和GIF格式的图片!");
+            }
+
+            // 确保上传目录存在
+            File directory = new File(uploadDir);
+            if (!directory.exists()) {
+                directory.mkdirs();
+                // 设置目录权限为755 (rwxr-xr-x)
+                setPermissions(directory, "rwxr-xr-x");
+            }
+
+            // 生成唯一文件名
+            String fileName = UUID.randomUUID().toString() + "_" + file.getOriginalFilename();
+            Path filePath = Paths.get(uploadDir, fileName);
+
+            // 保存文件
+            Files.write(filePath, file.getBytes());
+
+            // 设置文件权限为644 (rw-r--r--)
+            setPermissions(filePath.toFile(), "rw-r--r--");
+
+            // 5. 调用网易云信API更新头像
+            fileName = prefix+"/"+fileName;
+            UpdateUserBusinessDto dto = new UpdateUserBusinessDto();
+            dto.setAvatar(fileName);
+            Map<String, Object> result = imApiServcie.updateUserAvatar(accountId,dto);
+            if ((Boolean) result.get("success")) {
+                return Result.success("文件上传成功");
+            } else {
+                return Result.error("上传失败!");
+            }
+        } catch (IOException e) {
+            return Result.error("文件上传失败");
+        } catch (Exception e) {
+            e.printStackTrace();
+            log.error("设置文件权限失败!");
+        }
+        return Result.success();
+    }
+
+    /**
+     * 设置文件/目录权限
+     * @param file 文件或目录对象
+     * @param perm 权限字符串,如 "rw-r--r--"
+     */
+    private void setPermissions(File file, String perm) throws IOException {
+        // 获取当前操作系统
+        String os = System.getProperty("os.name").toLowerCase();
+
+        // 只有在Unix/Linux系统上才能设置POSIX权限
+        if (os.contains("nix") || os.contains("nux") || os.contains("mac")) {
+            Set<PosixFilePermission> permissions = PosixFilePermissions.fromString(perm);
+            Files.setPosixFilePermissions(file.toPath(), permissions);
+        } else {
+            // Windows系统不支持POSIX权限,可以设置基本权限
+            file.setReadable(true, false);    // 所有用户可读
+            if (perm.startsWith("rw")) {
+                file.setWritable(true, false); // 所有用户可写(如果权限字符串以rw开头)
+            } else {
+                file.setWritable(false, false);
+            }
+
+            // 如果是目录且包含执行权限,设置可执行
+            if (file.isDirectory() && perm.contains("x")) {
+                file.setExecutable(true, false);
+            }
+        }
+    }
+
+
+
 }
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/im/config/CreateTeamRequest.java b/ruoyi-admin/src/main/java/com/ruoyi/im/config/CreateTeamRequest.java
new file mode 100644
index 0000000..154dc5f
--- /dev/null
+++ b/ruoyi-admin/src/main/java/com/ruoyi/im/config/CreateTeamRequest.java
@@ -0,0 +1,124 @@
+package com.ruoyi.im.config;
+
+import lombok.Data;
+import javax.validation.constraints.NotBlank;
+import javax.validation.constraints.NotNull;
+import javax.validation.constraints.Size;
+import java.util.List;
+import java.util.Map;
+
+@Data
+public class CreateTeamRequest {
+    /**
+     * 群主(创建者)的 IM 账号 ID
+     */
+    @NotBlank(message = "群主账号不能为空")
+    @Size(max = 32, message = "群主账号长度不能超过32个字符")
+    private String owner_account_id;
+
+    /**
+     * 群组类型:1:高级群。2:超大群。
+     */
+    @NotNull(message = "群组类型不能为空")
+    private Integer team_type;
+
+    /**
+     * 群组名称,长度上限 64 位字符
+     */
+    @NotBlank(message = "群组名称不能为空")
+    @Size(max = 64, message = "群组名称长度不能超过64个字符")
+    private String name;
+
+    /**
+     * 群组头像的 URL 地址,长度上限 1024 位字符
+     */
+    @Size(max = 1024, message = "群组头像URL长度不能超过1024个字符")
+    private String icon;
+
+    /**
+     * 群组公告,长度上限 1024 位字符
+     */
+    @Size(max = 1024, message = "群组公告长度不能超过1024个字符")
+    private String announcement;
+
+    /**
+     * 群组简介,长度上限 512 位字符
+     */
+    @Size(max = 512, message = "群组简介长度不能超过512个字符")
+    private String intro;
+
+    /**
+     * 群组成员数上限(包含群主),默认为 200
+     */
+    private Integer members_limit = 200;
+
+    /**
+     * 自定义群组扩展字段,建议封装成 JSONObject 格式,长度上限 1024 位字符
+     */
+    @Size(max = 1024, message = "服务器扩展字段长度不能超过1024个字符")
+    private String server_extension;
+
+    /**
+     * 客户端自定义扩展字段,长度上限 1024 位字符
+     */
+    @Size(max = 1024, message = "客户端扩展字段长度不能超过1024个字符")
+    private String customer_extension;
+
+    /**
+     * 创建群组时邀请入群的成员列表
+     */
+    @NotNull(message = "邀请成员列表不能为空")
+    private List<String> invite_account_ids;
+
+    /**
+     * 邀请入群的附言,长度上限 150 位字符
+     */
+    @NotBlank(message = "邀请消息不能为空")
+    @Size(max = 150, message = "邀请消息长度不能超过150个字符")
+    private String invite_msg;
+
+    /**
+     * 自定义扩展字段,JSON 格式,长度上限 512 位字符
+     */
+    @Size(max = 512, message = "扩展字段长度不能超过512个字符")
+    private String extension;
+
+
+
+    /**
+     * 通过 SDK 侧操作申请入群的验证方式
+     * 0(默认):无需验证,直接入群
+     * 1:需要群主或管理员验证通过才能入群
+     * 2:不允许任何人申请入群
+     */
+    @NotNull(message = "入群验证方式不能为空")
+    private Integer join_mode = 0;
+
+    /**
+     * 邀请入群时是否需要被邀请人的同意
+     * 0(默认):需要被邀请人同意才能入群
+     * 1:不需要被邀请人同意,直接入群
+     */
+    private Integer agree_mode = 0;
+
+    /**
+     * 邀请权限,即谁可以邀请他人入群
+     * 0(默认):群主和管理员
+     * 1:所有人
+     */
+    private Integer invite_mode = 0;
+
+    /**
+     * 客户端修改群组信息的权限,即谁可以修改群组信息
+     * 0(默认):群主和管理员
+     * 1:所有人
+     */
+    private Integer update_team_info_mode = 0;
+
+    /**
+     * 客户端修改群自定义扩展信息权限
+     * 0(默认):群主和管理员
+     * 1:所有人
+     */
+    private Integer update_extension_mode = 0;
+}
\ No newline at end of file
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/im/config/DynamicRequestBodyBuilder.java b/ruoyi-admin/src/main/java/com/ruoyi/im/config/DynamicRequestBodyBuilder.java
new file mode 100644
index 0000000..ac47f7f
--- /dev/null
+++ b/ruoyi-admin/src/main/java/com/ruoyi/im/config/DynamicRequestBodyBuilder.java
@@ -0,0 +1,190 @@
+package com.ruoyi.im.config;
+
+import java.util.HashMap;
+import java.util.Map;
+import org.json.JSONObject;
+
+public class DynamicRequestBodyBuilder {
+    private Map<String, Object> bodyData;
+    private Map<String, Object> configurationData;
+
+    public DynamicRequestBodyBuilder() {
+        bodyData = new HashMap<>();
+        configurationData = new HashMap<>();
+    }
+
+    /**
+     * 设置token字段
+     */
+    public DynamicRequestBodyBuilder setToken(String token) {
+        if (token != null) {
+            bodyData.put("token", token);
+        }
+        return this;
+    }
+
+    /**
+     * 设置enabled配置字段
+     */
+    public DynamicRequestBodyBuilder setEnabled(boolean enabled) {
+        configurationData.put("enabled", enabled);
+        return this;
+    }
+
+    /**
+     * 设置p2p_chat_banned配置字段
+     */
+    public DynamicRequestBodyBuilder setP2pChatBanned(boolean banned) {
+        configurationData.put("p2p_chat_banned", banned);
+        return this;
+    }
+
+    /**
+     * 设置team_chat_banned配置字段
+     */
+    public DynamicRequestBodyBuilder setTeamChatBanned(boolean banned) {
+        configurationData.put("team_chat_banned", banned);
+        return this;
+    }
+
+    /**
+     * 设置chatroom_chat_banned配置字段
+     */
+    public DynamicRequestBodyBuilder setChatroomChatBanned(boolean banned) {
+        configurationData.put("chatroom_chat_banned", banned);
+        return this;
+    }
+
+    /**
+     * 设置qchat_chat_banned配置字段
+     */
+    public DynamicRequestBodyBuilder setQchatChatBanned(boolean banned) {
+        configurationData.put("qchat_chat_banned", banned);
+        return this;
+    }
+
+    /**
+     * 设置push_enabled_when_desktop_online配置字段
+     */
+    public DynamicRequestBodyBuilder setPushEnabledWhenDesktopOnline(boolean enabled) {
+        configurationData.put("push_enabled_when_desktop_online", enabled);
+        return this;
+    }
+
+    /**
+     * 设置need_kick字段
+     */
+    public DynamicRequestBodyBuilder setNeedKick(boolean needKick) {
+        bodyData.put("need_kick", needKick);
+        return this;
+    }
+
+    /**
+     * 设置kick_notify_extension字段
+     */
+    public DynamicRequestBodyBuilder setKickNotifyExtension(String extension) {
+        if (extension != null) {
+            bodyData.put("kick_notify_extension", extension);
+        }
+        return this;
+    }
+
+    /**
+     * 批量设置配置项
+     */
+    public DynamicRequestBodyBuilder setConfiguration(Map<String, Object> config) {
+        if (config != null) {
+            configurationData.putAll(config);
+        }
+        return this;
+    }
+
+    /**
+     * 批量设置所有字段
+     */
+    public DynamicRequestBodyBuilder setAllFields(Map<String, Object> fields) {
+        if (fields != null) {
+            // 处理顶级字段
+            if (fields.containsKey("token")) {
+                setToken((String) fields.get("token"));
+            }
+            if (fields.containsKey("need_kick")) {
+                setNeedKick((Boolean) fields.get("need_kick"));
+            }
+            if (fields.containsKey("kick_notify_extension")) {
+                setKickNotifyExtension((String) fields.get("kick_notify_extension"));
+            }
+
+            // 处理配置字段
+            if (fields.containsKey("configuration")) {
+                Map<String, Object> config = (Map<String, Object>) fields.get("configuration");
+                setConfiguration(config);
+            }
+        }
+        return this;
+    }
+
+    /**
+     * 构建JSON字符串
+     */
+    public String build() {
+        // 只有在有配置数据时才添加configuration字段
+        if (!configurationData.isEmpty()) {
+            bodyData.put("configuration", new HashMap<>(configurationData));
+        }
+
+        JSONObject jsonObject = new JSONObject(bodyData);
+        return jsonObject.toString();
+    }
+
+    /**
+     * 获取Map形式的数据
+     */
+    public Map<String, Object> getBodyData() {
+        Map<String, Object> result = new HashMap<>(bodyData);
+        if (!configurationData.isEmpty()) {
+            result.put("configuration", new HashMap<>(configurationData));
+        }
+        return result;
+    }
+
+    /**
+     * 清空所有已设置的数据
+     */
+    public void clear() {
+        bodyData.clear();
+        configurationData.clear();
+    }
+
+    /**
+     * 使用示例
+     */
+    public static void main(String[] args) {
+        // 示例1: 只设置部分字段
+        DynamicRequestBodyBuilder builder = new DynamicRequestBodyBuilder();
+        String partialBody = builder
+                .setToken("custom_token_123")
+                .setEnabled(true)
+                .build();
+        System.out.println("部分字段请求体: " + partialBody);
+
+        // 示例2: 使用Map批量设置
+        builder.clear();
+        Map<String, Object> config = new HashMap<>();
+        config.put("enabled", true);
+        config.put("p2p_chat_banned", true);
+
+        Map<String, Object> fields = new HashMap<>();
+        fields.put("token", "batch_token");
+        fields.put("need_kick", true);
+        fields.put("configuration", config);
+
+        String batchBody = builder.setAllFields(fields).build();
+        System.out.println("批量设置请求体: " + batchBody);
+
+        // 示例3: 完全不设置任何字段
+        builder.clear();
+        String emptyBody = builder.build();
+        System.out.println("空请求体: " + emptyBody);
+    }
+}
\ No newline at end of file
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/im/config/NeteaseResponse.java b/ruoyi-admin/src/main/java/com/ruoyi/im/config/NeteaseResponse.java
new file mode 100644
index 0000000..da544dc
--- /dev/null
+++ b/ruoyi-admin/src/main/java/com/ruoyi/im/config/NeteaseResponse.java
@@ -0,0 +1,38 @@
+package com.ruoyi.im.config;
+
+public class NeteaseResponse {
+    private int code;
+    private String msg;
+    private Object data;
+
+    public NeteaseResponse() {
+    }
+
+    public int getCode() {
+        return code;
+    }
+
+    public void setCode(int code) {
+        this.code = code;
+    }
+
+    public String getMsg() {
+        return msg;
+    }
+
+    public void setMsg(String msg) {
+        this.msg = msg;
+    }
+
+    public Object getData() {
+        return data;
+    }
+
+    public void setData(Object data) {
+        this.data = data;
+    }
+
+    public boolean isSuccess() {
+        return code == 200;
+    }
+}
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/im/config/UpdateAccountRequest.java b/ruoyi-admin/src/main/java/com/ruoyi/im/config/UpdateAccountRequest.java
new file mode 100644
index 0000000..c10bbb1
--- /dev/null
+++ b/ruoyi-admin/src/main/java/com/ruoyi/im/config/UpdateAccountRequest.java
@@ -0,0 +1,34 @@
+//package com.ruoyi.im.config;
+//
+//import com.fasterxml.jackson.annotation.JsonProperty;
+//
+//public class UpdateAccountRequest {
+//    @JsonProperty("props")
+//    private String props;
+//
+//    @JsonProperty("token")
+//    private String token;
+//
+//    public UpdateAccountRequest() {}
+//
+//    public UpdateAccountRequest(String props, String token) {
+//        this.props = props;
+//        this.token = token;
+//    }
+//
+//    public String getProps() {
+//        return props;
+//    }
+//
+//    public void setProps(String props) {
+//        this.props = props;
+//    }
+//
+//    public String getToken() {
+//        return token;
+//    }
+//
+//    public void setToken(String token) {
+//        this.token = token;
+//    }
+//}
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/im/config/UpdateUserInfoRequest.java b/ruoyi-admin/src/main/java/com/ruoyi/im/config/UpdateUserInfoRequest.java
new file mode 100644
index 0000000..95c3541
--- /dev/null
+++ b/ruoyi-admin/src/main/java/com/ruoyi/im/config/UpdateUserInfoRequest.java
@@ -0,0 +1,207 @@
+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;
+
+    public UpdateUserInfoRequest() {
+        bodyData = new HashMap<>();
+    }
+
+    /**
+     * 设置name字段
+     */
+    public UpdateUserInfoRequest setName(String name) {
+        if (name != null) {
+            bodyData.put("name", name);
+        }
+        return this;
+    }
+
+    /**
+     * 设置avatar字段
+     */
+    public UpdateUserInfoRequest setAvatar(String avatar) {
+        if (avatar != null) {
+            bodyData.put("avatar", avatar);
+        }
+        return this;
+    }
+
+    /**
+     * 设置sign字段
+     */
+    public UpdateUserInfoRequest setSign(String sign) {
+        if (sign != null) {
+            bodyData.put("sign", sign);
+        }
+        return this;
+    }
+
+    /**
+     * 设置email字段
+     */
+    public UpdateUserInfoRequest setEmail(String email) {
+        if (email != null) {
+            bodyData.put("email", email);
+        }
+        return this;
+    }
+
+    /**
+     * 设置birthday字段
+     */
+    public UpdateUserInfoRequest setBirthday(String birthday) {
+        if (birthday != null) {
+            bodyData.put("birthday", birthday);
+        }
+        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);
+    }
+}
+
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/im/config/YunxinClientConfig.java b/ruoyi-admin/src/main/java/com/ruoyi/im/config/YunxinClientConfig.java
new file mode 100644
index 0000000..a3bf85a
--- /dev/null
+++ b/ruoyi-admin/src/main/java/com/ruoyi/im/config/YunxinClientConfig.java
@@ -0,0 +1,26 @@
+package com.ruoyi.im.config;
+
+import com.netease.nim.server.sdk.core.BizName;
+import com.netease.nim.server.sdk.core.YunxinApiHttpClient;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+public class YunxinClientConfig {
+
+    @Bean
+    public YunxinApiHttpClient yunxinApiHttpClient() {
+        String appkey = AppAuthConfig.DEFAULT_CONFIG.getAppKey();
+        String appsecret = AppAuthConfig.DEFAULT_CONFIG.getAppSecret();
+        int timeoutMillis = 5000;
+
+        try {
+            return new YunxinApiHttpClient.Builder(BizName.IM, appkey, appsecret)
+                    .timeoutMillis(timeoutMillis)
+                    .build();
+        } catch (Exception e) {
+            throw new RuntimeException("Failed to create YunxinApiHttpClient", e);
+        }
+    }
+
+}
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/im/dto/CreateGroupDto.java b/ruoyi-admin/src/main/java/com/ruoyi/im/dto/CreateGroupDto.java
new file mode 100644
index 0000000..7558079
--- /dev/null
+++ b/ruoyi-admin/src/main/java/com/ruoyi/im/dto/CreateGroupDto.java
@@ -0,0 +1,102 @@
+package com.ruoyi.im.dto;
+
+import lombok.Data;
+
+import javax.validation.constraints.NotBlank;
+import javax.validation.constraints.NotNull;
+import javax.validation.constraints.Size;
+import java.util.List;
+
+@Data
+public class CreateGroupDto {
+
+    /**
+     * 群名称
+     */
+    @NotBlank(message = "群名称不能为空")
+    @Size(max = 64, message = "群名称长度不能超过64个字符")
+    private String name;
+
+    /**
+     * 群主账号
+     */
+    @NotBlank(message = "群主账号不能为空")
+    private String owner;
+
+    /**
+     * 初始群成员列表
+     */
+    @Size(min = 3, max = 10, message = "初始成员至少3人,最多10人")
+    private List<String> members;
+
+    /**
+     * 群简介/描述
+     */
+    @Size(max = 512, message = "群简介长度不能超过512个字符")
+    private String introduction;
+
+    /**
+     * 群公告
+     */
+    @Size(max = 1024, message = "群公告长度不能超过1024个字符")
+    private String announcement;
+
+    /**
+     * 群头像URL
+     */
+    private String icon;
+
+    /**
+     * 群类型:1-高级群,2-超级群
+     */
+    @NotNull(message = "群类型不能为空")
+    private Integer type;
+
+    /**
+     * 最大群成员数量
+     */
+    @NotNull(message = "最大群成员数量不能为空")
+    private Integer maxMembers;
+
+    /**
+     * 入群验证模式:0-允许任何人加入,1-需要验证,2-不允许加入
+     */
+    @NotNull(message = "验证方式不能为空")
+    private Integer joinMode;
+
+    /**
+     * 邀请权限:0-管理员,1-所有人
+     */
+    @NotNull(message = "邀请权限不能为空")
+    private Integer inviteMode;
+
+    /**
+     * 修改群信息权限:0-管理员,1-所有人
+     */
+    @NotNull(message = "修改群信息权限不能为空")
+    private Integer updateInfoMode;
+
+    /**
+     * 是否允许私聊:0-允许,1-不允许
+     */
+    @NotNull(message = "私聊设置不能为空")
+    private Integer privateChat;
+
+    /**
+     * 群二维码展示:0-展示,1-隐藏
+     */
+    @NotNull(message = "二维码展示设置不能为空")
+    private Integer qrcodeVisible;
+
+    /**
+     * 入群是否需要同意:0-不需要,1-需要
+     */
+    @NotNull(message = "入群同意设置不能为空")
+    private Integer joinApproval;
+
+    /**
+     * 群自定义扩展字段
+     */
+    private String custom;
+
+}
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/im/dto/RegisterDto.java b/ruoyi-admin/src/main/java/com/ruoyi/im/dto/RegisterDto.java
index 0a7c3ae..75486fb 100644
--- a/ruoyi-admin/src/main/java/com/ruoyi/im/dto/RegisterDto.java
+++ b/ruoyi-admin/src/main/java/com/ruoyi/im/dto/RegisterDto.java
@@ -1,5 +1,6 @@
 package com.ruoyi.im.dto;
 
+import io.swagger.models.auth.In;
 import lombok.Data;
 
 import javax.validation.constraints.NotEmpty;
@@ -14,9 +15,13 @@
     @NotEmpty(message = "密码不能为空")
     private String password; // 密码
 
-    @NotEmpty(message = "确认密码不能为空")
     private String confirmPassword; // 再次确认密码
 
+    private String name; // 昵称
+
+    private Integer type;//类型 1 批量  2 单一
+
+    private Integer number;//数量
 //    @NotNull(message = "验证码不能为空")
 //    private Integer verificationCode; // 验证码
 
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/im/dto/UpdateGroupDto.java b/ruoyi-admin/src/main/java/com/ruoyi/im/dto/UpdateGroupDto.java
new file mode 100644
index 0000000..e7c95ad
--- /dev/null
+++ b/ruoyi-admin/src/main/java/com/ruoyi/im/dto/UpdateGroupDto.java
@@ -0,0 +1,94 @@
+package com.ruoyi.im.dto;
+
+import lombok.Data;
+
+import javax.validation.constraints.NotBlank;
+import javax.validation.constraints.NotNull;
+import javax.validation.constraints.Size;
+import java.util.List;
+
+@Data
+public class UpdateGroupDto {
+
+
+    /**
+     * 群名称
+     */
+    @Size(max = 64, message = "群名称长度不能超过64个字符")
+    private String name;
+
+    /**
+     * 群主账号
+     */
+    private String owner;
+
+    /**
+     * 初始群成员列表
+     */
+    @Size(min = 3, max = 10, message = "初始成员至少3人,最多10人")
+    private List<String> members;
+
+    /**
+     * 群简介/描述
+     */
+    @Size(max = 512, message = "群简介长度不能超过512个字符")
+    private String introduction;
+
+    /**
+     * 群公告
+     */
+    @Size(max = 1024, message = "群公告长度不能超过1024个字符")
+    private String announcement;
+
+    /**
+     * 群头像URL
+     */
+    private String icon;
+
+    /**
+     * 群类型:1-高级群,2-超级群
+     */
+    private Integer type;
+
+    /**
+     * 最大群成员数量
+     */
+    private Integer maxMembers;
+
+    /**
+     * 入群验证模式:0-允许任何人加入,1-需要验证,2-不允许加入
+     */
+    private Integer joinMode;
+
+    /**
+     * 邀请权限:0-管理员,1-所有人
+     */
+    private Integer inviteMode;
+
+    /**
+     * 修改群信息权限:0-管理员,1-所有人
+     */
+    private Integer updateInfoMode;
+
+    /**
+     * 是否允许私聊:0-允许,1-不允许
+     */
+    private Integer privateChat;
+
+    /**
+     * 群二维码展示:0-展示,1-隐藏
+     */
+    private Integer qrcodeVisible;
+
+    /**
+     * 入群是否需要同意:0-不需要,1-需要
+     */
+    private Integer joinApproval;
+
+    /**
+     * 群自定义扩展字段
+     */
+    private String custom;
+
+}
+
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/im/dto/UpdateUserBusinessDto.java b/ruoyi-admin/src/main/java/com/ruoyi/im/dto/UpdateUserBusinessDto.java
new file mode 100644
index 0000000..6dc3d2f
--- /dev/null
+++ b/ruoyi-admin/src/main/java/com/ruoyi/im/dto/UpdateUserBusinessDto.java
@@ -0,0 +1,26 @@
+package com.ruoyi.im.dto;
+
+import lombok.Data;
+
+@Data
+public class UpdateUserBusinessDto {
+
+    private String name;//用户昵称
+    private String avatar;//用户头像的 URL 地址
+    private String sign;//用户签名
+    private String email;//用户邮箱地址
+    private String birthday;//用户生日
+    private String mobile;//用户手机号码
+    private String gender;//用户性别
+    private String token;//用户账号对应的登录密钥 Token
+    private Boolean enabled;//该账号是否可用。默认可用,若设为 false,则表示禁用该账号。
+    private String p2p_chat_banned;//单聊禁言标记。true:禁言。
+    private String team_chat_banned;//群聊禁言标记。true:禁言。
+    private String chatroom_chat_banned;//聊天室禁言标记。true:禁言。
+    private String qchat_chat_banned;//圈组禁言标记。true:禁言。
+    private String need_kick;//禁用用户(configuration.enabled = false)时可配置是否在禁用的同时踢掉该用户账号。如果设置为 true,则使该账号强制退出登录。
+    private String kick_notify_extension;//禁用用户(configuration.enabled = false)时可设置强制踢下线操作的扩展字段,可透传至客户端 SDK(7.7.0 及以上版本才支持),长度上限 256 位字符。
+
+
+
+}
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/im/service/ImApiServcie.java b/ruoyi-admin/src/main/java/com/ruoyi/im/service/ImApiServcie.java
index c658f6e..3fe1375 100644
--- a/ruoyi-admin/src/main/java/com/ruoyi/im/service/ImApiServcie.java
+++ b/ruoyi-admin/src/main/java/com/ruoyi/im/service/ImApiServcie.java
@@ -1,8 +1,19 @@
 package com.ruoyi.im.service;
 
+import com.ruoyi.common.core.domain.AjaxResult;
 import com.ruoyi.im.comm.Result;
 import com.ruoyi.im.dto.RegisterDto;
+import com.ruoyi.im.dto.UpdateUserBusinessDto;
+import com.ruoyi.system.domain.vo.UserAccountUpdateVo;
+
+import java.util.Map;
 
 public interface ImApiServcie {
     Result register(RegisterDto dto);
+
+    Map<String, Object> updateUserAvatar(String accountId, UpdateUserBusinessDto dto);
+
+    AjaxResult updateUserAccount(UserAccountUpdateVo vo);
+
+    Result batchRegister(RegisterDto dto);
 }
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/im/service/NeteaseTeamService.java b/ruoyi-admin/src/main/java/com/ruoyi/im/service/NeteaseTeamService.java
new file mode 100644
index 0000000..a486540
--- /dev/null
+++ b/ruoyi-admin/src/main/java/com/ruoyi/im/service/NeteaseTeamService.java
@@ -0,0 +1,16 @@
+package com.ruoyi.im.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.im.comm.Result;
+import com.ruoyi.im.config.CreateTeamRequest;
+import com.ruoyi.im.dto.CreateGroupDto;
+import com.ruoyi.system.domain.NeteaseTeam;
+import org.springframework.transaction.annotation.Transactional;
+
+public interface NeteaseTeamService extends IService<NeteaseTeam> {
+
+
+    AjaxResult createGroup(CreateTeamRequest request);
+
+}
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/im/service/impl/ImApiServcieImpl.java b/ruoyi-admin/src/main/java/com/ruoyi/im/service/impl/ImApiServcieImpl.java
index 3baa728..f252b5e 100644
--- a/ruoyi-admin/src/main/java/com/ruoyi/im/service/impl/ImApiServcieImpl.java
+++ b/ruoyi-admin/src/main/java/com/ruoyi/im/service/impl/ImApiServcieImpl.java
@@ -2,31 +2,56 @@
 
 import com.alibaba.fastjson2.JSONObject;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.fasterxml.jackson.databind.ObjectMapper;
 import com.netease.nim.server.sdk.core.BizName;
 import com.netease.nim.server.sdk.core.YunxinApiHttpClient;
 import com.netease.nim.server.sdk.core.YunxinApiResponse;
 import com.netease.nim.server.sdk.core.exception.YunxinSdkException;
+import com.ruoyi.common.core.domain.AjaxResult;
 import com.ruoyi.common.core.domain.R;
+import com.ruoyi.common.utils.StringUtils;
 import com.ruoyi.im.comm.Result;
 import com.ruoyi.im.config.AppAuthConfig;
+import com.ruoyi.im.config.DynamicRequestBodyBuilder;
+import com.ruoyi.im.config.NeteaseResponse;
+import com.ruoyi.im.config.UpdateUserInfoRequest;
+import com.ruoyi.im.dto.UpdateUserBusinessDto;
 import com.ruoyi.system.domain.UserAccount;
 import com.ruoyi.im.service.ImApiServcie;
 import com.ruoyi.im.dto.RegisterDto;
+import com.ruoyi.system.domain.vo.UserAccountUpdateVo;
 import com.ruoyi.system.service.UserAccountService;
 import com.ruoyi.im.util.SymmetricCryptoUtil;
 import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.codec.digest.DigestUtils;
+import org.apache.http.HttpResponse;
+import org.apache.http.client.methods.HttpPatch;
+import org.apache.http.entity.StringEntity;
+import org.apache.http.impl.client.CloseableHttpClient;
+import org.apache.http.impl.client.HttpClients;
+import org.apache.http.util.EntityUtils;
+import org.apache.poi.util.StringUtil;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.jdbc.core.BatchPreparedStatementSetter;
+import org.springframework.jdbc.core.JdbcTemplate;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.transaction.interceptor.TransactionAspectSupport;
 import org.springframework.util.CollectionUtils;
 
 import javax.annotation.PostConstruct;
+import javax.annotation.Resource;
+import java.nio.charset.StandardCharsets;
+import java.sql.PreparedStatement;
+import java.sql.SQLException;
 import java.time.Instant;
 import java.util.*;
+import java.util.concurrent.CompletableFuture;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ThreadLocalRandom;
 import java.util.concurrent.atomic.AtomicLong;
+import java.util.stream.Collectors;
 
 @Service
 @Slf4j
@@ -34,8 +59,18 @@
     @Autowired
     private UserAccountService userAccountService;
 
-    // 使用单例客户端,避免重复初始化
-    private YunxinApiHttpClient yunxinClient;
+
+    @Autowired
+    private JdbcTemplate jdbcTemplate;
+
+    private final YunxinApiHttpClient yunxinClient;
+
+    // 使用构造函数注入(推荐)
+    @Autowired
+    public ImApiServcieImpl(YunxinApiHttpClient yunxinClient) {
+        this.yunxinClient = yunxinClient;
+    }
+
 
     // 使用并发安全的集合存储正在生成的账号,防止重复
     private final Set<Long> generatingAccounts = Collections.newSetFromMap(new ConcurrentHashMap<>());
@@ -44,17 +79,17 @@
     private final AtomicLong lastTimestamp = new AtomicLong(0);
     private final AtomicLong sequence = new AtomicLong(0);
 
-    @PostConstruct
-    public void init() {
-        // 初始化云信客户端,只执行一次
-        String appkey = AppAuthConfig.DEFAULT_CONFIG.getAppKey();
-        String appsecret = AppAuthConfig.DEFAULT_CONFIG.getAppSecret();
-        int timeoutMillis = 5000;
+    private static final String DEFAULT_PASSWORD = "123456";//批量注册密码
+    private static final String ENCRYPTED_PASSWORD = SymmetricCryptoUtil.encryptPassword(DEFAULT_PASSWORD); // 密码加密一次,多次使用
 
-        this.yunxinClient = new YunxinApiHttpClient.Builder(BizName.IM, appkey, appsecret)
-                .timeoutMillis(timeoutMillis)
-                .build();
-    }
+    private static final String YUNXIN_CREATE_PATH = "/user/create.action";
+
+    @Value("${netease.im.api-head-portrait-url}")
+    private String headPortraitUrl;
+
+    private final ObjectMapper objectMapper = new ObjectMapper();
+
+
 
     @Override
     @Transactional(rollbackFor = Exception.class) // 添加事务注解确保操作原子性
@@ -76,18 +111,23 @@
             userAccount.setPhoneNumber(dto.getAccount());
             userAccount.setCloudMessageAccount(dto.getAccount());
             userAccount.setPassword(SymmetricCryptoUtil.encryptPassword(dto.getPassword()));
+            userAccount.setCreateTime(new Date());
+            userAccount.setNickname(dto.getAccount());
+
 
             if (!userAccountService.save(userAccount)) {
                 return Result.error("注册失败,请重试");
             }
 
             // 注册云信账号(远程调用)
-            String path = "/user/create.action";
             Map<String, String> paramMap = new HashMap<>();
             paramMap.put("accid", dto.getAccount());
+            if(StringUtils.isNotEmpty(dto.getName())){
+                paramMap.put("name", dto.getName());
+            }
             paramMap.put("token", dto.getPassword());
 
-            YunxinApiResponse response = yunxinClient.executeV1Api(path, paramMap);
+            YunxinApiResponse response = yunxinClient.executeV1Api(YUNXIN_CREATE_PATH, paramMap);
 
             // 处理云信响应
             String data = response.getData();
@@ -119,6 +159,7 @@
             return Result.error("注册失败,请重试");
         }
     }
+
 
     /**
      * 优化的账号生成方法,使用雪花算法变体提高并发性能
@@ -183,4 +224,328 @@
         // 组合时间戳和序列号,生成9位ID
         return timestamp * 100 + seq;
     }
+
+
+
+    /**
+     * 更新用户名片
+     * @param accountId 用户账号
+     * @return 操作结果
+     */
+    public Map<String, Object> updateUserAvatar(String accountId, UpdateUserBusinessDto dto) {
+        Map<String, Object> result = new HashMap<>();
+
+        try (CloseableHttpClient httpClient = HttpClients.createDefault()) {
+            // 生成请求参数
+            String nonce = UUID.randomUUID().toString().replace("-", "");
+            String curTime = String.valueOf(System.currentTimeMillis() / 1000);
+            String checkSum = generateCheckSum(nonce, curTime);
+
+            // 构建请求URL
+            String url = headPortraitUrl + "/im/v2/users/" + accountId;
+
+            // 构建请求头
+            HttpPatch httpPatch = new HttpPatch(url);
+            httpPatch.setHeader("Content-Type", "application/json;charset=utf-8");
+            httpPatch.setHeader("AppKey", AppAuthConfig.DEFAULT_CONFIG.getAppKey());
+            httpPatch.setHeader("Nonce", nonce);
+            httpPatch.setHeader("CurTime", curTime);
+            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);
+            httpPatch.setEntity(new StringEntity(jsonBody, StandardCharsets.UTF_8));
+
+            // 执行请求
+            HttpResponse response = httpClient.execute(httpPatch);
+            String responseString = EntityUtils.toString(response.getEntity(), StandardCharsets.UTF_8);
+
+            // 解析响应
+            NeteaseResponse neteaseResponse = objectMapper.readValue(responseString, NeteaseResponse.class);
+
+            if (neteaseResponse.isSuccess()) {
+                result.put("success", true);
+                result.put("message", "头像更新成功");
+                result.put("data", neteaseResponse.getData());
+            } else {
+                result.put("success", false);
+                result.put("message", "头像更新失败: " + neteaseResponse.getMsg());
+                result.put("errorCode", neteaseResponse.getCode());
+            }
+
+        } catch (Exception e) {
+            result.put("success", false);
+            result.put("message", "请求网易云信API失败: " + e.getMessage());
+        }
+
+        return result;
+    }
+
+
+
+    /**
+     * 生成校验和
+     */
+    private String generateCheckSum(String nonce, String curTime) {
+        String content = AppAuthConfig.DEFAULT_CONFIG.getAppSecret() + nonce + curTime;
+        return DigestUtils.sha1Hex(content);
+    }
+
+
+
+    @Override
+    public AjaxResult updateUserAccount(UserAccountUpdateVo vo) {
+        //更新用户名片
+        UpdateUserBusinessDto dto = new UpdateUserBusinessDto();
+        if(StringUtils.isNotEmpty(vo.getPhoneNumber())){
+            dto.setMobile(vo.getPhoneNumber());
+        }else if(StringUtils.isNotEmpty(vo.getNickname())){
+            dto.setName(vo.getNickname());
+        }else if(StringUtils.isNotEmpty(vo.getSignature())){
+            dto.setSign(vo.getSignature());
+        }
+        Map<String, Object> map = updateUserAvatar(vo.getAccountId(), dto);
+        //更新用户属性 状态 密码
+        if ((Boolean) map.get("success")) {
+            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());
+                userAccount.setUpdateTime(new Date());
+                userAccountService.updateById(userAccount);
+            }else{
+                return AjaxResult.error("更新用户属性失败!");
+            }
+        } else {
+            return AjaxResult.error("更新用户名片失败!");
+        }
+        return AjaxResult.success("更新成功!");
+    }
+
+
+
+
+    /**
+     * 更新账号属性
+     * @param accountId 用户账号ID
+     * @return 操作结果
+     */
+    public AjaxResult updateAccountProperties(String accountId, UserAccountUpdateVo vo) {
+
+        try (CloseableHttpClient httpClient = HttpClients.createDefault()) {
+            // 生成请求参数
+            String nonce = UUID.randomUUID().toString().replace("-", "");
+            String curTime = String.valueOf(System.currentTimeMillis() / 1000);
+            String checkSum = generateCheckSum(nonce, curTime);
+
+            // 构建请求URL
+            String url = headPortraitUrl + "/im/v2/accounts/" + accountId;
+
+            // 构建请求头
+            HttpPatch httpPatch = new HttpPatch(url);
+            httpPatch.setHeader("Content-Type", "application/json;charset=utf-8");
+            httpPatch.setHeader("AppKey", AppAuthConfig.DEFAULT_CONFIG.getAppKey());
+            httpPatch.setHeader("Nonce", nonce);
+            httpPatch.setHeader("CurTime", curTime);
+            httpPatch.setHeader("CheckSum", checkSum);
+
+            // 创建构建器实例
+            DynamicRequestBodyBuilder builder = new DynamicRequestBodyBuilder();
+            if(null != vo.getStatus() && vo.getStatus() == 0){
+                builder.setEnabled(false);
+                builder.setNeedKick(true);
+            }else if(StringUtils.isNotEmpty(vo.getPassword())){
+                builder.setToken(vo.getPassword());
+            }
+            // 只设置需要的字段
+            String body = builder.build();
+            String jsonBody = objectMapper.writeValueAsString(body);
+            httpPatch.setEntity(new StringEntity(jsonBody, StandardCharsets.UTF_8));
+
+            // 执行请求
+            HttpResponse response = httpClient.execute(httpPatch);
+            String responseString = EntityUtils.toString(response.getEntity(), StandardCharsets.UTF_8);
+
+            // 解析响应
+            NeteaseResponse neteaseResponse = objectMapper.readValue(responseString, NeteaseResponse.class);
+
+            if (neteaseResponse.isSuccess()) {
+                AjaxResult.success("账号属性更新成功");
+            } else {
+                AjaxResult.error("账号属性更新失败");
+            }
+
+        } catch (Exception e) {
+            e.printStackTrace();
+            AjaxResult.error("请求网易云信API失败");
+        }
+
+        return AjaxResult.success();
+    }
+
+
+    /**
+     * 批量注册
+     * @param dto
+     * @return
+     */
+    @Override
+    public Result batchRegister(RegisterDto dto) {
+        if(dto.getType() == 2){
+            return register(dto);
+        }else{
+            return batchRegister(dto.getNumber());
+        }
+    }
+
+    /**
+     * 同步批量注册
+     * 注意:大批量(如超过1000)可能会造成事务过长、数据库连接占用较久,请根据实际情况调整批次大小或考虑异步方式
+     * @param count 要注册的账号数量
+     * @return 批量注册结果
+     */
+    @Transactional(rollbackFor = Exception.class)
+    public Result batchRegister(int count) {
+        if (count <= 0) {
+            return Result.error("注册数量必须大于0");
+        }
+
+        try {
+            // 1. 生成批量账号数据
+            List<UserAccount> accountsToSave = generateBatchAccounts(count);
+            // 2. 批量插入数据库 (使用JDBC Batch,性能远高于MyBatis-Plus的saveBatch)
+            batchInsertAccounts(accountsToSave);
+            // 3. 批量注册云信账号 (并行处理)
+            Result yunxinResult = batchRegisterYunxinAccounts(accountsToSave);
+
+            if (yunxinResult.getCode() != 200) {
+                // 云信注册失败,手动触发回滚
+                TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
+                return yunxinResult;
+            }
+
+            return Result.success("成功批量注册 " + count + " 个账号");
+
+        } catch (Exception e) {
+            // 其他异常,触发回滚
+            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
+            log.error("批量注册过程发生异常", e);
+            return Result.error("批量注册失败: " + e.getMessage());
+        }
+    }
+
+    /**
+     * 生成批量的账号信息
+     * @param count 需要生成的数量
+     * @return 用户账号列表
+     */
+    private List<UserAccount> generateBatchAccounts(int count) {
+        List<UserAccount> accounts = new ArrayList<>(count);
+        Set<String> generatedAccounts = new HashSet<>(count); // 用于内存中去重
+        Random random = new Random();
+
+        for (int i = 0; i < count; i++) {
+            String account;
+            do {
+                // 生成13开头的11位随机手机号作为账号
+                account = "13" + String.format("%09d", random.nextInt(1000000000));
+            } while (generatedAccounts.contains(account)); // 确保本次批量中唯一
+
+            generatedAccounts.add(account);
+
+            UserAccount userAccount = new UserAccount();
+            userAccount.setAccount(account);
+            userAccount.setPhoneNumber(account);
+            userAccount.setCloudMessageAccount(account);
+            userAccount.setPassword(ENCRYPTED_PASSWORD); // 使用预加密的密码
+            userAccount.setCreateTime(new Date());
+            userAccount.setNickname("用户_" + account.substring(7)); // 简单生成昵称
+            userAccount.setAccountType(1); // 设置账号类型为1
+
+            accounts.add(userAccount);
+        }
+        return accounts;
+    }
+
+    /**
+     * 使用JDBC批量插入数据库,最高效的方式
+     * @param accounts 待插入的用户账号列表
+     */
+    private void batchInsertAccounts(List<UserAccount> accounts) {
+        String sql = "INSERT INTO user_account (account, phone_number, cloud_message_account, password, create_time, nickname, account_type) VALUES (?, ?, ?, ?, ?, ?, ?)";
+
+        jdbcTemplate.batchUpdate(sql, new BatchPreparedStatementSetter() {
+            @Override
+            public void setValues(PreparedStatement ps, int i) throws SQLException {
+                UserAccount account = accounts.get(i);
+                ps.setString(1, account.getAccount());
+                ps.setString(2, account.getPhoneNumber());
+                ps.setString(3, account.getCloudMessageAccount());
+                ps.setString(4, account.getPassword());
+                ps.setTimestamp(5, new java.sql.Timestamp(account.getCreateTime().getTime()));
+                ps.setString(6, account.getNickname());
+                ps.setInt(7, account.getAccountType());
+            }
+
+            @Override
+            public int getBatchSize() {
+                return accounts.size();
+            }
+        });
+    }
+
+    /**
+     * 批量注册云信账号(并行调用单个接口)
+     * @param accounts 已存入本地数据库的账号列表
+     * @return 注册结果
+     */
+    private Result batchRegisterYunxinAccounts(List<UserAccount> accounts) {
+        // 使用并行流并行调用云信接口
+        List<CompletableFuture<YunxinApiResponse>> futures = accounts.parallelStream()
+                .map(account -> CompletableFuture.supplyAsync(() -> {
+                    Map<String, String> paramMap = new HashMap<>();
+                    paramMap.put("accid", account.getAccount());
+                    paramMap.put("token", DEFAULT_PASSWORD); // 使用明文密码
+                    // 调用云信接口
+                    return yunxinClient.executeV1Api(YUNXIN_CREATE_PATH, paramMap);
+                }))
+                .collect(Collectors.toList());
+
+        // 等待所有异步操作完成,并获取结果
+        List<YunxinApiResponse> responses = futures.stream()
+                .map(CompletableFuture::join)
+                .collect(Collectors.toList());
+
+        // 检查所有响应结果
+        for (YunxinApiResponse response : responses) {
+            String data = response.getData();
+            JSONObject json = JSONObject.parseObject(data);
+            int code = json.getIntValue("code");
+            if (code != 200) {
+                // 记录具体的错误信息
+                String errorAccid = json.getString("accid"); // 如果返回了accid
+                log.error("云信账号注册失败,accid: {}, 响应: {}, traceId: {}", errorAccid, data, response.getTraceId());
+                // 返回第一个遇到的错误
+                return Result.error("云信注册失败,错误码: " + code + (errorAccid != null ? ", 账号: " + errorAccid : ""));
+            }
+        }
+
+        return Result.success("所有云信账号注册成功");
+    }
+
 }
\ No newline at end of file
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/im/service/impl/NeteaseTeamServiceImpl.java b/ruoyi-admin/src/main/java/com/ruoyi/im/service/impl/NeteaseTeamServiceImpl.java
new file mode 100644
index 0000000..454be10
--- /dev/null
+++ b/ruoyi-admin/src/main/java/com/ruoyi/im/service/impl/NeteaseTeamServiceImpl.java
@@ -0,0 +1,181 @@
+package com.ruoyi.im.service.impl;
+
+import com.alibaba.fastjson2.JSON;
+import com.alibaba.fastjson2.JSONObject;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.netease.nim.server.sdk.core.BizName;
+import com.netease.nim.server.sdk.core.YunxinApiHttpClient;
+import com.netease.nim.server.sdk.core.YunxinApiResponse;
+import com.netease.nim.server.sdk.core.exception.YunxinSdkException;
+import com.netease.nim.server.sdk.core.http.HttpMethod;
+import com.netease.nim.server.sdk.im.v2.team.TeamV2UrlContext;
+import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.common.utils.bean.BeanUtils;
+import com.ruoyi.im.comm.Result;
+import com.ruoyi.im.config.AppAuthConfig;
+import com.ruoyi.im.config.CreateTeamRequest;
+import com.ruoyi.im.dto.CreateGroupDto;
+import com.ruoyi.im.service.NeteaseTeamService;
+import com.ruoyi.system.domain.NeteaseTeam;
+import com.ruoyi.system.mapper.NeteaseTeamMapper;
+import org.aspectj.weaver.loadtime.Aj;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.transaction.interceptor.TransactionAspectSupport;
+
+import javax.annotation.PostConstruct;
+import javax.annotation.Resource;
+import java.util.*;
+
+@Service
+public class NeteaseTeamServiceImpl extends ServiceImpl<NeteaseTeamMapper, NeteaseTeam> implements NeteaseTeamService {
+
+    private final YunxinApiHttpClient yunxinClient;
+
+    // 使用构造函数注入(推荐)
+    @Autowired
+    public NeteaseTeamServiceImpl(YunxinApiHttpClient yunxinClient) {
+        this.yunxinClient = yunxinClient;
+    }
+
+
+
+    @Resource
+    private NeteaseTeamMapper neteaseTeamMapper;
+
+    /**
+     * 创建群组(根据最新参数说明)
+     */
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public AjaxResult createGroup(CreateTeamRequest request) {
+        try {
+            // 1. 构建请求参数Map
+            Map<String, Object> paramMap = buildCreateTeamParams(request);
+
+            // 2. 将Map转换为JSON字符串
+            String jsonBody = JSON.toJSONString(paramMap);
+
+            // 3. 调用网易云信API创建群组
+            YunxinApiResponse response = yunxinClient.executeV2Api(
+                    HttpMethod.POST,
+                    TeamV2UrlContext.CREATE_TEAM,
+                    TeamV2UrlContext.CREATE_TEAM,
+                    null,
+                    jsonBody
+            );
+
+            // 4. 处理响应
+            String data = response.getData();
+            JSONObject json = JSONObject.parseObject(data);
+            int code = json.getIntValue("code");
+
+            if (code != 200) {
+                log.error("网易云信创建群组失败,响应:");
+                return AjaxResult.error("创建群组失败");
+            }
+
+            // 5. 解析响应获取群组ID
+            JSONObject resultData = json.getJSONObject("data");
+            JSONObject teamInfo = resultData.getJSONObject("team_info");
+            String tid = teamInfo.getString("team_id");
+            String ownerAccountId = teamInfo.getString("owner_account_id");
+
+            // 6. 保存群组信息到本地数据库
+            int count = saveTeamToLocal(request,ownerAccountId, tid);
+            if(count > 0){
+                return AjaxResult.success("创建群组成功");
+            }
+            return AjaxResult.error("创建群组失败");
+        } catch (YunxinSdkException e) {
+            // 云信调用异常时回滚事务
+            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
+            e.printStackTrace();
+            log.error("网易云信服务调用异常 traceId:");
+            return AjaxResult.error("创建群组失败,云信服务异常");
+        } catch (Exception e) {
+            // 其他异常同样回滚
+            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
+            e.printStackTrace();
+            log.error("创建群组过程发生未知异常", e);
+            return AjaxResult.error("创建群组失败,系统异常");
+        }
+    }
+
+    /**
+     * 构建创建群组的参数Map
+     */
+    private Map<String, Object> buildCreateTeamParams(CreateTeamRequest request) {
+        Map<String, Object> paramMap = new HashMap<>();
+
+        // 必填参数
+        paramMap.put("owner_account_id", request.getOwner_account_id());
+        paramMap.put("team_type", request.getTeam_type());
+        paramMap.put("name", request.getName());
+        paramMap.put("invite_account_ids", request.getInvite_account_ids());
+        paramMap.put("invite_msg", request.getInvite_msg());
+
+        // 群组配置
+        Map<String, Object> configMap = new HashMap<>();
+        configMap.put("join_mode", request.getJoin_mode());
+        configMap.put("agree_mode", request.getAgree_mode());
+        configMap.put("invite_mode", request.getInvite_mode());
+        configMap.put("update_team_info_mode", request.getUpdate_team_info_mode());
+        configMap.put("update_extension_mode", request.getUpdate_extension_mode());
+        paramMap.put("configuration", configMap);
+
+        // 选填参数
+        if (request.getIcon() != null) {
+            paramMap.put("icon", request.getIcon());
+        }
+        if (request.getAnnouncement() != null) {
+            paramMap.put("announcement", request.getAnnouncement());
+        }
+        if (request.getIntro() != null) {
+            paramMap.put("intro", request.getIntro());
+        }
+        if (request.getMembers_limit() != null) {
+            paramMap.put("members_limit", request.getMembers_limit());
+        }
+        if (request.getServer_extension() != null) {
+            paramMap.put("server_extension", request.getServer_extension());
+        }
+        if (request.getCustomer_extension() != null) {
+            paramMap.put("customer_extension", request.getCustomer_extension());
+        }
+        if (request.getExtension() != null) {
+            paramMap.put("extension", request.getExtension());
+        }
+
+        return paramMap;
+    }
+
+    /**
+     * 保存群组信息到本地数据库
+     */
+    private int saveTeamToLocal(CreateTeamRequest request,String ownerAccountId, String tid) {
+        NeteaseTeam team = new NeteaseTeam();
+        BeanUtils.copyProperties(request, team);
+        team.setTid(tid);
+        team.setCreateTime(new Date());
+        team.setUpdateTime(new Date());
+        team.setStatus(0); // 正常状态
+        team.setOwnerAccountId(ownerAccountId);
+        team.setTeamType(request.getTeam_type());
+        team.setName(request.getName());
+        team.setMembersLimit(request.getMembers_limit());
+
+        // 保存配置信息
+        team.setJoinMode(request.getJoin_mode());
+        team.setAgreeMode(request.getAgree_mode());
+        team.setInviteMode(request.getInvite_mode());
+        team.setUpdateTeamInfoMode(request.getUpdate_team_info_mode());
+        team.setUpdateExtensionMode(request.getUpdate_extension_mode());
+
+        // 保存到数据库
+        int insert = neteaseTeamMapper.insert(team);
+
+        return insert;
+    }
+}
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/group/ImGroupController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/group/ImGroupController.java
new file mode 100644
index 0000000..972d236
--- /dev/null
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/group/ImGroupController.java
@@ -0,0 +1,33 @@
+package com.ruoyi.web.controller.group;
+
+import com.ruoyi.common.core.controller.BaseController;
+import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.im.config.CreateTeamRequest;
+import com.ruoyi.im.dto.CreateGroupDto;
+import com.ruoyi.im.service.NeteaseTeamService;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+@RestController
+@RequestMapping("/im/group")
+@Slf4j
+public class ImGroupController extends BaseController {
+
+
+    @Autowired
+    NeteaseTeamService neteaseGroupService;
+
+    /**
+     * 创建群组
+     */
+    @PostMapping("/create")
+    public AjaxResult createGroup(@Validated @RequestBody CreateTeamRequest request) {
+        return neteaseGroupService.createGroup(request);
+    }
+
+}
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/user/UserController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/user/UserController.java
index 83fdc8f..095fe20 100644
--- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/user/UserController.java
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/user/UserController.java
@@ -7,13 +7,19 @@
 import com.ruoyi.common.core.domain.entity.SysUser;
 import com.ruoyi.common.core.page.TableDataInfo;
 import com.ruoyi.common.utils.StringUtils;
+import com.ruoyi.im.comm.Result;
+import com.ruoyi.im.dto.RegisterDto;
+import com.ruoyi.im.service.ImApiServcie;
 import com.ruoyi.system.domain.UserAccount;
 import com.ruoyi.system.domain.vo.UserAccountUpdateVo;
 import com.ruoyi.system.domain.vo.UserAccountVo;
 import com.ruoyi.system.service.UserAccountService;
+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.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RestController;
 
@@ -22,10 +28,14 @@
 
 @RestController
 @RequestMapping("/im/user")
+@Slf4j
 public class UserController extends BaseController {
 
     @Autowired
     UserAccountService userAccountService;
+
+    @Autowired
+    private ImApiServcie imApiServcie;
 
     /**
      * 获取会员列表
@@ -34,19 +44,32 @@
     @GetMapping("/list")
     public TableDataInfo list(UserAccountVo vo)
     {
-        startPage();
-        List<UserAccount> list = userAccountService.list(new LambdaQueryWrapper<UserAccount>()
-                .eq(UserAccount::getId, vo.getKeyword())
-                .or()
-                .eq(UserAccount::getPhoneNumber, vo.getKeyword())
-                .or()
-                .eq(UserAccount::getAccount, vo.getKeyword())
-                .or()
-                .eq(UserAccount::getNickname, vo.getKeyword())
-                .eq(ObjectUtil.isNotEmpty(vo.getAccountType()),UserAccount::getAccountType,vo.getAccountType())
-                .eq(ObjectUtil.isNotEmpty(vo.getStatus()),UserAccount::getStatus,vo.getStatus())
-                .between(UserAccount::getCreateTime,vo.getStartTime(),vo.getEndTime())
-        );
+        // 创建查询条件包装器
+        LambdaQueryWrapper<UserAccount> queryWrapper = new LambdaQueryWrapper<>();
+
+        // 只有当 keyword 不为空时才添加 OR 条件
+        if (ObjectUtil.isNotEmpty(vo.getKeyword())) {
+            queryWrapper.and(wrapper -> wrapper
+                    .eq(UserAccount::getId, vo.getKeyword())
+                    .or()
+                    .eq(UserAccount::getPhoneNumber, vo.getKeyword())
+                    .or()
+                    .eq(UserAccount::getAccount, vo.getKeyword())
+                    .or()
+                    .eq(UserAccount::getNickname, vo.getKeyword())
+            );
+        }
+
+        // 添加其他条件
+        queryWrapper
+                .eq(ObjectUtil.isNotEmpty(vo.getAccountType()), UserAccount::getAccountType, vo.getAccountType())
+                .eq(ObjectUtil.isNotEmpty(vo.getStatus()), UserAccount::getStatus, vo.getStatus())
+                .between(ObjectUtil.isAllNotEmpty(vo.getStartTime(), vo.getEndTime()),
+                        UserAccount::getCreateTime, vo.getStartTime(), vo.getEndTime());
+
+        // 默认按创建时间倒序
+        queryWrapper.orderByDesc(UserAccount::getCreateTime);
+        List<UserAccount> list = userAccountService.list(queryWrapper);
         return getDataTable(list);
     }
 
@@ -54,11 +77,15 @@
      * 修改会员
      */
     @PreAuthorize("@ss.hasPermi('im:user:updateUserAccount')")
-    @GetMapping("/updateUserAccount")
+    @PostMapping("/updateUserAccount")
     public AjaxResult updateUserAccount(UserAccountUpdateVo vo) {
 
         try {
             UserAccount userAccount = userAccountService.getById(vo.getId());
+            if(ObjectUtil.isEmpty(userAccount)){
+                return AjaxResult.error("会员不存在!");
+            }
+            return imApiServcie.updateUserAccount(vo);
         }catch (Exception e){
             e.printStackTrace();
             logger.error("修改会员失败!");
@@ -66,4 +93,18 @@
         return AjaxResult.success();
     }
 
+    /**
+     * 批量注册
+     */
+    @PostMapping("/batchRegister")
+    public Result batchRegister(@Validated RegisterDto dto){
+        try {
+            return imApiServcie.batchRegister(dto);
+        }catch (Exception e){
+            log.error("批量注册报错:",e);
+            return Result.error("注册失败,请稍后再试!");
+        }
+    }
+
+
 }
diff --git a/ruoyi-admin/src/main/resources/application.yml b/ruoyi-admin/src/main/resources/application.yml
index db8c314..45a5a3e 100644
--- a/ruoyi-admin/src/main/resources/application.yml
+++ b/ruoyi-admin/src/main/resources/application.yml
@@ -30,7 +30,9 @@
       max: 800
       # Tomcat启动初始化的线程数,默认值10
       min-spare: 100
-
+    multipart:
+      max-file-size: 10MB
+      max-request-size: 10MB
 # 日志配置
 logging:
   level:
@@ -140,4 +142,14 @@
   # 排除链接(多个用逗号分隔)
   excludes: /system/notice
   # 匹配链接
-  urlPatterns: /system/*,/monitor/*,/tool/*
\ No newline at end of file
+  urlPatterns: /system/*,/monitor/*,/tool/*
+
+
+file:
+  upload-dir: /www/wwwroot/img
+  upload-prefix: https://img.freessl.help
+
+# 网易云信配置
+netease:
+  im:
+    api-head-portrait-url: https://open.yunxinapi.com
\ No newline at end of file
diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/SecurityConfig.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/SecurityConfig.java
index 222ba3f..d27572d 100644
--- a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/SecurityConfig.java
+++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/SecurityConfig.java
@@ -116,6 +116,8 @@
                     .antMatchers(HttpMethod.GET, "/", "/*.html", "/**/*.html", "/**/*.css", "/**/*.js", "/profile/**").permitAll()
                     .antMatchers("/swagger-ui.html", "/swagger-resources/**", "/webjars/**", "/*/api-docs", "/druid/**").permitAll()
                     .antMatchers("/im/api/**").permitAll()
+                    .antMatchers("/im/user/**").permitAll()
+                    .antMatchers("/im/group/**").permitAll()
                     // 除上面外的所有请求全部需要鉴权认证
                     .anyRequest().authenticated();
             })
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/domain/NeteaseTeam.java b/ruoyi-system/src/main/java/com/ruoyi/system/domain/NeteaseTeam.java
new file mode 100644
index 0000000..ada3659
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/domain/NeteaseTeam.java
@@ -0,0 +1,138 @@
+package com.ruoyi.system.domain;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+
+import java.util.Date;
+
+@Data
+@TableName("netease_team")
+public class NeteaseTeam {
+    /**
+     * 主键ID
+     */
+    @TableId(type = IdType.AUTO)
+    private Long id;
+
+    /**
+     * 网易云信群ID
+     */
+    private String tid;
+
+    /**
+     * 群名称
+     */
+    private String name;
+
+    /**
+     * 群主账号
+     */
+    private String ownerAccountId;
+
+    /**
+     * 群类型:1-高级群,2-超大群
+     */
+    private Integer teamType;
+
+    /**
+     * 群头像URL
+     */
+    private String icon;
+
+    /**
+     * 群公告
+     */
+    private String announcement;
+
+    /**
+     * 群简介
+     */
+    private String intro;
+
+    /**
+     * 最大群成员数量
+     */
+    private Integer membersLimit;
+
+    /**
+     * 服务器扩展字段
+     */
+    private String serverExtension;
+
+    /**
+     * 客户端扩展字段
+     */
+    private String customerExtension;
+
+    /**
+     * 扩展字段
+     */
+    private String extension;
+
+    /**
+     * 入群验证模式:0-无需验证,直接入群,1-需要验证,2-不允许任何人申请入群
+     */
+    private Integer joinMode;
+
+    /**
+     * 同意模式:0-需要被邀请人同意,1-不需要被邀请人同意
+     */
+    private Integer agreeMode;
+
+    /**
+     * 邀请权限:0-群主和管理员,1-所有人
+     */
+    private Integer inviteMode;
+
+    /**
+     * 修改群信息权限:0-群主和管理员,1-所有人
+     */
+    private Integer updateTeamInfoMode;
+
+    /**
+     * 修改扩展字段权限:0-群主和管理员,1-所有人
+     */
+    private Integer updateExtensionMode;
+
+    /**
+     * 是否开启安全通
+     */
+    private Boolean antispamEnabled;
+
+    /**
+     * 安全通业务配置(JSON格式存储)
+     */
+    private String antispamBusinessConfig;
+
+    /**
+     * 创建时间
+     */
+    private Date createTime;
+
+    /**
+     * 更新时间
+     */
+    private Date updateTime;
+
+    /**
+     * 状态:0-正常,1-解散
+     */
+    private Integer status;
+
+    /**
+     * 群成员数量(需要定期同步更新)
+     */
+    private Integer memberCount;
+
+    /**
+     * 群管理员列表(JSON格式存储)
+     */
+    private String managers;
+
+    /**
+     * 自定义字段,用于存储其他信息
+     */
+    private String customData;
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/domain/vo/UserAccountUpdateVo.java b/ruoyi-system/src/main/java/com/ruoyi/system/domain/vo/UserAccountUpdateVo.java
index 4acaeb1..e6dac8f 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/domain/vo/UserAccountUpdateVo.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/domain/vo/UserAccountUpdateVo.java
@@ -23,6 +23,9 @@
     @TableId(type = IdType.AUTO) // 主键自增
     private Integer id;
 
+    // 云信账号
+    private String accountId;
+
     // 手机号(唯一)
     private String phoneNumber;
 
@@ -30,34 +33,34 @@
     private String password;
 
     // 账号类型: 0:真实 1:虚拟
-    private Integer accountType = 0;
+    private Integer accountType;
 
     // 昵称
     private String nickname;
 
-    // 账号状态: 0:正常 1:禁用
-    private Integer status = 0;
+    // 账号状态: 1:正常 0:禁用
+    private Integer status;
 
     // 个性签名
     private String signature;
 
-    // 是否支持昵称搜索
-    private Boolean supportNicknameSearch = true;
+//    // 是否支持昵称搜索
+//    private Boolean supportNicknameSearch = true;
+//
+//    // 是否支持手机搜索
+//    private Boolean supportPhoneSearch = true;
+//
+//    // 是否支持ID搜索
+//    private Boolean supportIdSearch = true;
+//
+//    // 是否支持用户名搜索
+//    private Boolean supportUsernameSearch = true;
+//
+//    // 是否申请删除账号
+//    private Boolean requestDelete = true;
 
-    // 是否支持手机搜索
-    private Boolean supportPhoneSearch = true;
-
-    // 是否支持ID搜索
-    private Boolean supportIdSearch = true;
-
-    // 是否支持用户名搜索
-    private Boolean supportUsernameSearch = true;
-
-    // 是否申请删除账号
-    private Boolean requestDelete = true;
-
-    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
-    @TableField(fill = FieldFill.INSERT_UPDATE)
-    private Date updateTime;
+//    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+//    @TableField(fill = FieldFill.INSERT_UPDATE)
+//    private Date updateTime;
 
 }
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/mapper/NeteaseTeamMapper.java b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/NeteaseTeamMapper.java
new file mode 100644
index 0000000..873d5d7
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/NeteaseTeamMapper.java
@@ -0,0 +1,9 @@
+package com.ruoyi.system.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.ruoyi.system.domain.NeteaseTeam;
+import org.apache.ibatis.annotations.Mapper;
+
+@Mapper
+public interface NeteaseTeamMapper extends BaseMapper<NeteaseTeam> {
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/UserAccountService.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/UserAccountService.java
index d469d22..f1a4db4 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/service/UserAccountService.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/UserAccountService.java
@@ -1,7 +1,9 @@
 package com.ruoyi.system.service;
 
 import com.baomidou.mybatisplus.extension.service.IService;
+import com.ruoyi.common.core.domain.AjaxResult;
 import com.ruoyi.system.domain.UserAccount;
+import com.ruoyi.system.domain.vo.UserAccountUpdateVo;
 
 public interface UserAccountService extends IService<UserAccount> {
 }
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/UserAccountServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/UserAccountServiceImpl.java
index 8ba90d0..a5aca1d 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/UserAccountServiceImpl.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/UserAccountServiceImpl.java
@@ -1,11 +1,26 @@
 package com.ruoyi.system.service.impl;
 
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.netease.nim.server.sdk.core.YunxinApiHttpClient;
+import com.ruoyi.common.core.domain.AjaxResult;
 import com.ruoyi.system.domain.UserAccount;
+import com.ruoyi.system.domain.vo.UserAccountUpdateVo;
 import com.ruoyi.system.mapper.UserAccountMapper;
 import com.ruoyi.system.service.UserAccountService;
+import org.apache.commons.codec.digest.DigestUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
 import org.springframework.stereotype.Service;
 
+import java.nio.charset.StandardCharsets;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.atomic.AtomicLong;
+
 /**
  * @program: ruoyiim
  * @description:

--
Gitblit v1.9.3