diff --git a/api/README.md b/api/README.md
new file mode 100644
index 0000000..52ec97f
--- /dev/null
+++ b/api/README.md
@@ -0,0 +1,211 @@
+# Coder Common Thin Backend API 文档
+
+## 项目概述
+
+Coder Common Thin Backend 是一个基于Spring Boot 3.5.0的企业级开发框架,采用插件化架构设计,提供了完整的后台管理系统功能。
+
+## 技术栈
+
+- **后端框架**: Spring Boot 3.5.0 + Java 17
+- **数据库**: MySQL 8 + MyBatis Plus 3.5.12
+- **缓存**: Redis (Spring Data Redis)
+- **安全认证**: Sa-Token 1.43.0
+- **权限控制**: RBAC (Role-Based Access Control)
+- **API文档**: OpenAPI 3.0 (Swagger)
+- **工具库**: Hutool 5.8.38, Fastjson2 2.0.57, Guava 33.4.8
+
+## 服务器信息
+
+- **默认端口**: 18099
+- **基础URL**: http://localhost:18099
+- **API前缀**: /coder (除登录认证接口外)
+
+## 认证方式
+
+系统使用Sa-Token进行身份认证和权限管理:
+- **Token类型**: Bearer Token
+- **Token位置**: 请求头 `Authorization` 字段
+- **Token过期**: 支持自定义过期时间
+- **权限验证**: 基于注解的权限验证
+
+## 统一响应格式
+
+所有接口均采用统一的JSON响应格式:
+
+```json
+{
+ "status": 200,
+ "msg": "SUCCESS",
+ "data": {
+ // 具体数据
+ },
+ "traceId": "trace-id-value"
+}
+```
+
+### 状态码说明
+
+- **200**: 成功
+- **400**: 请求参数错误
+- **401**: 认证失败/未登录
+- **403**: 权限不足
+- **500**: 服务器内部错误
+
+## 分页查询格式
+
+分页查询请求参数:
+```json
+{
+ "pageNo": 1,
+ "pageSize": 10,
+ "params": {
+ // 查询参数
+ }
+}
+```
+
+分页查询响应格式:
+```json
+{
+ "status": 200,
+ "msg": "SUCCESS",
+ "data": {
+ "records": [
+ // 数据记录
+ ],
+ "total": 100,
+ "size": 10,
+ "current": 1,
+ "pages": 10,
+ "searchCount": true
+ },
+ "traceId": "trace-id-value"
+}
+```
+
+## 权限系统
+
+系统采用RBAC权限模型:
+- **用户 (User)**: 系统使用者
+- **角色 (Role)**: 权限的集合
+- **权限 (Permission)**: 具体的操作权限
+- **菜单 (Menu)**: 系统菜单和按钮权限
+
+### 权限验证流程
+
+1. 用户登录获取Token
+2. 请求接口时携带Token
+3. 系统验证Token有效性
+4. 根据用户角色验证权限
+5. 允许或拒绝访问
+
+## API模块分类
+
+### 1. 认证模块 (Authentication)
+- [登录认证API](./authentication/登录认证API)
+- [验证码API](./authentication/验证码API)
+
+### 2. 用户管理模块 (User Management)
+- [用户管理API](./user/用户管理API)
+
+### 3. 权限管理模块 (Permission Management)
+- [菜单管理API](./permission/菜单管理API)
+- [角色管理API](./permission/角色管理API)
+
+### 4. 系统管理模块 (System Management)
+- [文件管理API](./system/文件管理API)
+- [图片管理API](./system/图片管理API)
+- [登录日志API](./system/登录日志API)
+
+## 错误处理
+
+系统提供了完善的错误处理机制:
+
+### 常见错误类型
+
+1. **业务异常**: 自定义业务逻辑错误
+2. **认证异常**: 登录认证相关错误
+3. **权限异常**: 权限验证失败
+4. **参数异常**: 请求参数验证失败
+5. **系统异常**: 服务器内部错误
+
+### 错误响应格式
+
+```json
+{
+ "status": 400,
+ "msg": "具体错误信息",
+ "data": null,
+ "traceId": "trace-id-value"
+}
+```
+
+## 开发环境配置
+
+### 数据库配置
+```yaml
+spring:
+ datasource:
+ url: jdbc:mysql://localhost:3306/coder_common_thin
+ username: root
+ password: your_password
+```
+
+### Redis配置
+```yaml
+spring:
+ redis:
+ host: localhost
+ port: 6379
+ password: your_password
+```
+
+### Sa-Token配置
+```yaml
+sa-token:
+ token-name: Authorization
+ timeout: 2592000
+ activity-timeout: -1
+ is-concurrent: true
+ is-share: false
+ is-read-head: true
+ is-read-cookie: false
+```
+
+## 接口调用示例
+
+### 登录接口调用
+```bash
+curl -X POST \
+ http://localhost:18099/auth/login \
+ -H 'Content-Type: application/json' \
+ -d '{
+ "loginName": "admin",
+ "password": "123456",
+ "codeKey": "uuid-key",
+ "securityCode": "1234"
+ }'
+```
+
+### 携带Token调用接口
+```bash
+curl -X GET \
+ http://localhost:18099/coder/sysLoginUser/getLoginUserInformation \
+ -H 'Authorization: Bearer your-token-value'
+```
+
+## 注意事项
+
+1. 所有接口都需要进行认证,除了登录接口和验证码接口
+2. 权限验证基于角色和权限码进行
+3. 系统支持多设备登录
+4. 敏感操作会记录操作日志
+5. 建议在生产环境中启用HTTPS
+
+## 更新日志
+
+- **v1.0.0** (2025-07-05): 初始版本发布
+
+## 联系方式
+
+如有问题,请联系开发团队。
\ No newline at end of file
diff --git a/api/authentication/登录认证API.md b/api/authentication/登录认证API.md
new file mode 100644
index 0000000..5f2be0b
--- /dev/null
+++ b/api/authentication/登录认证API.md
@@ -0,0 +1,255 @@
+# 登录认证API
+
+## 概述
+
+登录认证模块提供用户登录、退出、注册等功能,使用Sa-Token进行身份认证和会话管理。
+
+## 接口列表
+
+### 1. 用户登录
+
+**接口地址**: `POST /auth/login`
+
+**接口描述**: 用户使用账号密码登录系统
+
+**是否需要认证**: 否
+
+**请求参数**:
+
+```json
+{
+ "loginName": "admin",
+ "password": "123456",
+ "codeKey": "uuid-key",
+ "securityCode": "1234",
+ "rememberMe": false
+}
+```
+
+**请求参数说明**:
+
+| 参数名 | 类型 | 必填 | 说明 | 校验规则 |
+|--------|------|------|------|----------|
+| loginName | String | 是 | 登录账号 | 长度3-16位,只能包含字母和数字 |
+| password | String | 是 | 登录密码 | 不能为空 |
+| codeKey | String | 是 | 验证码UUID | 不能为空 |
+| securityCode | String | 是 | 验证码 | 不能为空 |
+| rememberMe | Boolean | 否 | 记住登录 | 默认false |
+
+**响应示例**:
+
+```json
+{
+ "status": 200,
+ "msg": "SUCCESS",
+ "data": {
+ "tokenName": "Authorization",
+ "tokenValue": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9..."
+ },
+ "traceId": "trace-123456"
+}
+```
+
+**响应参数说明**:
+
+| 参数名 | 类型 | 说明 |
+|--------|------|------|
+| tokenName | String | Token名称 |
+| tokenValue | String | Token值 |
+
+**错误码**:
+
+| 状态码 | 错误信息 | 说明 |
+|--------|----------|------|
+| 400 | 账号长度为 3-16 位 | 登录账号长度不符合要求 |
+| 400 | 账号格式为数字以及字母 | 登录账号格式不正确 |
+| 400 | 请输入登录名 | 登录名为空 |
+| 400 | 请输入密码 | 密码为空 |
+| 400 | 验证码已失效 | 验证码Key无效 |
+| 400 | 请输入验证码 | 验证码为空 |
+| 400 | 验证码错误 | 验证码不正确 |
+| 400 | 用户不存在 | 用户账号不存在 |
+| 400 | 密码错误 | 密码不正确 |
+| 400 | 账号已被停用 | 用户账号被禁用 |
+| 400 | 账号已被锁定 | 用户账号被锁定 |
+
+**调用示例**:
+
+```bash
+curl -X POST \
+ http://localhost:18099/auth/login \
+ -H 'Content-Type: application/json' \
+ -d '{
+ "loginName": "admin",
+ "password": "123456",
+ "codeKey": "550e8400-e29b-41d4-a716-446655440000",
+ "securityCode": "1234",
+ "rememberMe": false
+ }'
+```
+
+---
+
+### 2. 用户退出
+
+**接口地址**: `GET /auth/logout`
+
+**接口描述**: 用户退出登录,清除会话信息
+
+**是否需要认证**: 是
+
+**请求头**:
+
+```
+Authorization: eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9...
+```
+
+**请求参数**: 无
+
+**响应示例**:
+
+```json
+{
+ "status": 200,
+ "msg": "SUCCESS",
+ "data": "退出成功",
+ "traceId": "trace-123456"
+}
+```
+
+**错误码**:
+
+| 状态码 | 错误信息 | 说明 |
+|--------|----------|------|
+| 401 | 当前会话未登录 | 用户未登录或Token无效 |
+
+**调用示例**:
+
+```bash
+curl -X GET \
+ http://localhost:18099/auth/logout \
+ -H 'Authorization: your-token-value'
+```
+
+---
+
+### 3. 用户注册
+
+**接口地址**: `POST /auth/register`
+
+**接口描述**: 新用户注册账号
+
+**是否需要认证**: 否
+
+**请求参数**:
+
+```json
+{
+ "loginName": "newuser",
+ "password": "123456",
+ "userName": "新用户",
+ "codeKey": "uuid-key",
+ "securityCode": "1234"
+}
+```
+
+**请求参数说明**:
+
+| 参数名 | 类型 | 必填 | 说明 | 校验规则 |
+|--------|------|------|------|----------|
+| loginName | String | 是 | 登录账号 | 长度3-16位,只能包含字母和数字 |
+| password | String | 是 | 登录密码 | 不能为空 |
+| userName | String | 是 | 用户姓名 | 不能为空 |
+| codeKey | String | 是 | 验证码UUID | 不能为空 |
+| securityCode | String | 是 | 验证码 | 不能为空 |
+
+**响应示例**:
+
+```json
+{
+ "status": 200,
+ "msg": "SUCCESS",
+ "data": "注册成功",
+ "traceId": "trace-123456"
+}
+```
+
+**错误码**:
+
+| 状态码 | 错误信息 | 说明 |
+|--------|----------|------|
+| 400 | 账号长度为 3-16 位 | 登录账号长度不符合要求 |
+| 400 | 账号格式为数字以及字母 | 登录账号格式不正确 |
+| 400 | 请输入登录名 | 登录名为空 |
+| 400 | 请输入密码 | 密码为空 |
+| 400 | 请输入用户姓名 | 用户姓名为空 |
+| 400 | 验证码已失效 | 验证码Key无效 |
+| 400 | 请输入验证码 | 验证码为空 |
+| 400 | 验证码错误 | 验证码不正确 |
+| 400 | 账号已存在 | 登录账号已被注册 |
+
+**调用示例**:
+
+```bash
+curl -X POST \
+ http://localhost:18099/auth/register \
+ -H 'Content-Type: application/json' \
+ -d '{
+ "loginName": "newuser",
+ "password": "123456",
+ "userName": "新用户",
+ "codeKey": "550e8400-e29b-41d4-a716-446655440000",
+ "securityCode": "1234"
+ }'
+```
+
+---
+
+## 认证流程说明
+
+### 1. 登录流程
+
+1. 用户获取验证码(调用验证码接口)
+2. 用户输入账号、密码、验证码
+3. 系统验证验证码有效性
+4. 系统验证用户账号和密码
+5. 系统检查用户状态(是否禁用/锁定)
+6. 生成Token并返回给用户
+7. 用户后续请求携带Token
+
+### 2. Token使用
+
+- Token需要在请求头中携带:`Authorization: token-value`
+- Token有过期时间,过期后需要重新登录
+- 系统支持多设备登录
+- 管理员可以强制用户下线
+
+### 3. 权限验证
+
+- 登录后系统会根据用户角色加载权限
+- 每个接口都会验证用户是否有相应权限
+- 超级管理员拥有所有权限
+
+### 4. 会话管理
+
+- 用户登录信息存储在Redis中
+- 支持会话延长
+- 支持记住登录功能
+- 系统会记录用户登录日志
+
+## 安全特性
+
+1. **密码加密**: 使用盐值加密存储密码
+2. **验证码保护**: 防止暴力破解
+3. **账号锁定**: 连续错误3次自动锁定
+4. **IP限制**: 可配置IP白名单/黑名单
+5. **会话安全**: Token有效期管理
+6. **日志记录**: 记录所有登录操作
+
+## 注意事项
+
+1. 验证码有效期为5分钟
+2. Token默认有效期为30天
+3. 账号锁定时间为10分钟
+4. 注册功能可通过配置开启/关闭
+5. 建议在生产环境中启用HTTPS
\ No newline at end of file
diff --git a/api/authentication/验证码API.md b/api/authentication/验证码API.md
new file mode 100644
index 0000000..c25b3f9
--- /dev/null
+++ b/api/authentication/验证码API.md
@@ -0,0 +1,397 @@
+# 验证码API
+
+## 概述
+
+验证码模块提供图形验证码生成功能,支持PNG和GIF两种格式,用于防止恶意攻击和机器人注册。
+
+## 接口列表
+
+### 1. 生成PNG验证码
+
+**接口地址**: `GET /captcha/png`
+
+**接口描述**: 生成PNG格式的图形验证码
+
+**是否需要认证**: 否
+
+**请求参数**: 无
+
+**响应示例**:
+
+```json
+{
+ "status": 200,
+ "msg": "SUCCESS",
+ "data": {
+ "uuid": "550e8400-e29b-41d4-a716-446655440000",
+ "base64": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGQAAAAkCAYAAAB...",
+ "captchaText": "1234"
+ },
+ "traceId": "trace-123456"
+}
+```
+
+**响应参数说明**:
+
+| 参数名 | 类型 | 说明 |
+|--------|------|------|
+| uuid | String | 验证码唯一标识,用于后续验证 |
+| base64 | String | 验证码图片Base64编码 |
+| captchaText | String | 验证码文本(开发环境返回,生产环境不返回) |
+
+**特性说明**:
+
+- 验证码长度:4位数字
+- 图片尺寸:102x38像素
+- 有效期:5分钟
+- 字体:随机字体
+- 背景:随机背景色
+- 干扰线:随机干扰线
+
+**调用示例**:
+
+```bash
+curl -X GET \
+ http://localhost:18099/captcha/png \
+ -H 'Content-Type: application/json'
+```
+
+**前端使用示例**:
+
+```javascript
+// 获取验证码
+function getCaptcha() {
+ fetch('/captcha/png')
+ .then(response => response.json())
+ .then(data => {
+ if (data.status === 200) {
+ // 显示验证码图片
+ document.getElementById('captchaImg').src = data.data.base64;
+ // 保存验证码UUID,用于登录时提交
+ document.getElementById('codeKey').value = data.data.uuid;
+ }
+ });
+}
+
+// 点击刷新验证码
+document.getElementById('captchaImg').onclick = getCaptcha;
+```
+
+---
+
+### 2. 生成GIF验证码
+
+**接口地址**: `GET /captcha/gif`
+
+**接口描述**: 生成GIF动画格式的图形验证码
+
+**是否需要认证**: 否
+
+**请求参数**: 无
+
+**响应示例**:
+
+```json
+{
+ "status": 200,
+ "msg": "SUCCESS",
+ "data": {
+ "uuid": "550e8400-e29b-41d4-a716-446655440001",
+ "base64": "data:image/gif;base64,R0lGODlhZgAyAPcAAAAAAP///wAAAP...",
+ "captchaText": "5678"
+ },
+ "traceId": "trace-123456"
+}
+```
+
+**响应参数说明**:
+
+| 参数名 | 类型 | 说明 |
+|--------|------|------|
+| uuid | String | 验证码唯一标识,用于后续验证 |
+| base64 | String | 验证码图片Base64编码 |
+| captchaText | String | 验证码文本(开发环境返回,生产环境不返回) |
+
+**特性说明**:
+
+- 验证码长度:4位数字
+- 图片尺寸:102x38像素
+- 有效期:5分钟
+- 动画效果:字符摆动动画
+- 帧数:10帧
+- 动画速度:100ms/帧
+
+**调用示例**:
+
+```bash
+curl -X GET \
+ http://localhost:18099/captcha/gif \
+ -H 'Content-Type: application/json'
+```
+
+**前端使用示例**:
+
+```javascript
+// 获取GIF验证码
+function getGifCaptcha() {
+ fetch('/captcha/gif')
+ .then(response => response.json())
+ .then(data => {
+ if (data.status === 200) {
+ // 显示验证码图片
+ document.getElementById('captchaImg').src = data.data.base64;
+ // 保存验证码UUID,用于登录时提交
+ document.getElementById('codeKey').value = data.data.uuid;
+ }
+ });
+}
+```
+
+---
+
+## 验证码配置
+
+### 1. 验证码参数配置
+
+```yaml
+# application.yml
+captcha:
+ # 验证码长度
+ length: 4
+ # 验证码宽度
+ width: 102
+ # 验证码高度
+ height: 38
+ # 验证码有效期(分钟)
+ timeout: 5
+ # 字体大小
+ font-size: 25
+ # 干扰线数量
+ line-count: 100
+ # 是否开启验证码
+ enabled: true
+```
+
+### 2. 验证码存储
+
+- 验证码使用Redis存储
+- Key格式:`captcha:uuid`
+- 过期时间:5分钟自动删除
+- 值存储:验证码文本(忽略大小写)
+
+### 3. 验证码验证
+
+```java
+// 验证码验证逻辑
+public boolean validateCaptcha(String uuid, String inputCode) {
+ // 从Redis获取验证码
+ String correctCode = redisTemplate.opsForValue().get("captcha:" + uuid);
+
+ if (correctCode == null) {
+ throw new BusinessException("验证码已过期");
+ }
+
+ // 不区分大小写验证
+ if (!correctCode.equalsIgnoreCase(inputCode)) {
+ throw new BusinessException("验证码错误");
+ }
+
+ // 验证成功后立即删除验证码(防止重复使用)
+ redisTemplate.delete("captcha:" + uuid);
+
+ return true;
+}
+```
+
+---
+
+## 安全特性
+
+### 1. 防暴力破解
+
+- 验证码一次性使用
+- 验证后立即删除
+- 5分钟自动过期
+- 支持IP限制
+
+### 2. 防机器识别
+
+- 随机字体和颜色
+- 随机背景和干扰线
+- 字符位置随机偏移
+- GIF动画增加识别难度
+
+### 3. 防重放攻击
+
+- 每次验证码都有唯一UUID
+- 验证码使用后立即失效
+- 不允许重复使用
+
+## 错误处理
+
+### 常见错误情况
+
+| 错误场景 | 错误码 | 错误信息 |
+|----------|--------|----------|
+| 验证码过期 | 400 | 验证码已失效 |
+| 验证码错误 | 400 | 验证码错误 |
+| 验证码为空 | 400 | 请输入验证码 |
+| UUID无效 | 400 | 验证码已失效 |
+| 系统异常 | 500 | 验证码生成失败 |
+
+### 错误响应示例
+
+```json
+{
+ "status": 400,
+ "msg": "验证码已失效",
+ "data": null,
+ "traceId": "trace-123456"
+}
+```
+
+---
+
+## 使用建议
+
+### 1. 前端集成
+
+```html
+
+
+
![验证码]()
+
+
+
+
+```
+
+```javascript
+// 初始化验证码
+function initCaptcha() {
+ fetch('/captcha/png')
+ .then(response => response.json())
+ .then(data => {
+ if (data.status === 200) {
+ document.getElementById('captchaImg').src = data.data.base64;
+ document.getElementById('codeKey').value = data.data.uuid;
+ }
+ });
+}
+
+// 刷新验证码
+function refreshCaptcha() {
+ initCaptcha();
+}
+
+// 页面加载时获取验证码
+window.onload = initCaptcha;
+```
+
+### 2. 表单提交
+
+```javascript
+// 登录表单提交
+function login() {
+ const formData = {
+ loginName: document.getElementById('loginName').value,
+ password: document.getElementById('password').value,
+ codeKey: document.getElementById('codeKey').value,
+ securityCode: document.getElementById('securityCode').value
+ };
+
+ fetch('/auth/login', {
+ method: 'POST',
+ headers: {
+ 'Content-Type': 'application/json'
+ },
+ body: JSON.stringify(formData)
+ })
+ .then(response => response.json())
+ .then(data => {
+ if (data.status === 200) {
+ // 登录成功
+ localStorage.setItem('token', data.data.tokenValue);
+ window.location.href = '/dashboard';
+ } else {
+ // 登录失败,刷新验证码
+ alert(data.msg);
+ refreshCaptcha();
+ }
+ });
+}
+```
+
+### 3. 移动端适配
+
+```css
+/* 移动端验证码样式 */
+@media (max-width: 768px) {
+ .captcha-container {
+ display: flex;
+ align-items: center;
+ gap: 10px;
+ }
+
+ #captchaImg {
+ width: 102px;
+ height: 38px;
+ cursor: pointer;
+ }
+
+ #securityCode {
+ width: 100px;
+ height: 38px;
+ }
+}
+```
+
+## 性能优化
+
+### 1. 缓存策略
+
+- 验证码图片不缓存
+- 验证码文本缓存5分钟
+- 使用Redis集群提高性能
+
+### 2. 并发控制
+
+- 支持高并发验证码生成
+- 每秒可生成1000+验证码
+- 使用连接池管理Redis连接
+
+### 3. 资源优化
+
+- 图片大小优化(小于2KB)
+- 内存使用优化
+- 垃圾回收优化
+
+## 监控和日志
+
+### 1. 指标监控
+
+- 验证码生成次数
+- 验证码验证次数
+- 验证码成功率
+- 验证码过期率
+
+### 2. 日志记录
+
+- 验证码生成日志
+- 验证码验证日志
+- 异常错误日志
+- 性能监控日志
+
+### 3. 告警机制
+
+- 验证码成功率过低告警
+- 验证码生成异常告警
+- Redis连接异常告警
+
+## 注意事项
+
+1. 生产环境不返回验证码文本
+2. 验证码区分大小写(可配置)
+3. 验证码只能使用一次
+4. 建议定期清理过期验证码
+5. 支持自定义验证码样式和难度
\ No newline at end of file
diff --git a/api/permission/菜单管理API.md b/api/permission/菜单管理API.md
new file mode 100644
index 0000000..2a699f2
--- /dev/null
+++ b/api/permission/菜单管理API.md
@@ -0,0 +1,1315 @@
+# 菜单管理API
+
+## 概述
+
+菜单管理模块是权限系统的核心组成部分,负责管理系统菜单、权限配置和路由生成。支持无限级菜单嵌套,提供目录、菜单、按钮三种类型的权限控制。
+
+## 权限说明
+
+菜单管理接口需要相应的权限才能访问:
+
+| 操作 | 权限码 | 说明 |
+|------|--------|------|
+| 查询菜单列表 | `system:menu:list` | 查看菜单列表权限 |
+| 新增菜单 | `system:menu:add` | 新增菜单权限 |
+| 修改菜单 | `system:menu:edit` | 修改菜单信息权限 |
+| 删除菜单 | `system:menu:remove` | 删除菜单权限 |
+| 分配权限 | `system:menu:assign` | 分配菜单权限 |
+
+## 菜单类型说明
+
+| 类型 | 值 | 说明 | 用途 |
+|------|---|------|------|
+| 目录 | 1 | 菜单目录 | 用于菜单分组,不对应具体页面 |
+| 菜单 | 2 | 菜单项 | 对应具体的页面路由 |
+| 按钮 | 3 | 按钮权限 | 用于控制页面内的按钮显示 |
+
+## 接口列表
+
+### 1. 分页查询菜单列表
+
+**接口地址**: `GET /coder/sysMenu/listPage`
+
+**接口描述**: 分页查询系统菜单列表
+
+**是否需要认证**: 是
+
+**权限要求**: `system:menu:list`
+
+**请求头**:
+```
+Authorization: your-token-value
+```
+
+**请求参数**:
+
+| 参数名 | 类型 | 必填 | 说明 | 示例 |
+|--------|------|------|------|------|
+| pageNo | Integer | 否 | 页码 | 1 |
+| pageSize | Integer | 否 | 每页大小 | 10 |
+| menuName | String | 否 | 菜单名称 | 用户管理 |
+| menuStatus | String | 否 | 菜单状态 | 0 |
+| auth | String | 否 | 权限标识 | system:user:list |
+
+**响应示例**:
+
+```json
+{
+ "code": 1,
+ "success": true,
+ "msg": "操作成功",
+ "data": [
+ {
+ "menuId": 1,
+ "menuName": "系统管理",
+ "enName": "System Manage",
+ "parentId": 0,
+ "menuType": "1",
+ "name": "systemPage",
+ "path": "/system",
+ "component": "",
+ "icon": "Tools",
+ "isHide": "1",
+ "isLink": "",
+ "isKeepAlive": "0",
+ "isFull": "1",
+ "isAffix": "1",
+ "redirect": "/system/user",
+ "activeMenu": null
+ },
+ {
+ "menuId": 2,
+ "menuName": "用户管理",
+ "enName": "User Manage",
+ "parentId": 1,
+ "menuType": "2",
+ "name": "userPage",
+ "path": "/system/user",
+ "component": "system/user/index",
+ "icon": "UserFilled",
+ "isHide": "1",
+ "isLink": "",
+ "isKeepAlive": "1",
+ "isFull": "1",
+ "isAffix": "1",
+ "redirect": "",
+ "activeMenu": null
+ },
+ {
+ "menuId": 12,
+ "menuName": "角色管理",
+ "enName": "Role Manage",
+ "parentId": 1,
+ "menuType": "2",
+ "name": "rolePage",
+ "path": "/system/role",
+ "component": "system/role/index",
+ "icon": "Avatar",
+ "isHide": "1",
+ "isLink": "",
+ "isKeepAlive": "0",
+ "isFull": "1",
+ "isAffix": "1",
+ "redirect": "",
+ "activeMenu": null
+ },
+ {
+ "menuId": 72,
+ "menuName": "文件管理",
+ "enName": "Files Manage",
+ "parentId": 70,
+ "menuType": "2",
+ "name": "filePage",
+ "path": "/tools/file",
+ "component": "system/file/index",
+ "icon": "FolderOpened",
+ "isHide": "1",
+ "isLink": "",
+ "isKeepAlive": "0",
+ "isFull": "1",
+ "isAffix": "1",
+ "redirect": "",
+ "activeMenu": ""
+ },
+ {
+ "menuId": 19,
+ "menuName": "菜单管理",
+ "enName": "Menu Manage",
+ "parentId": 1,
+ "menuType": "2",
+ "name": "menuPage",
+ "path": "/system/menu",
+ "component": "system/menu/index",
+ "icon": "Grid",
+ "isHide": "1",
+ "isLink": "",
+ "isKeepAlive": "0",
+ "isFull": "1",
+ "isAffix": "1",
+ "redirect": "",
+ "activeMenu": null
+ },
+ {
+ "menuId": 77,
+ "menuName": "图库管理",
+ "enName": "Pictures Manage",
+ "parentId": 70,
+ "menuType": "2",
+ "name": "picturePage",
+ "path": "/tools/picture",
+ "component": "system/picture/index",
+ "icon": "Picture",
+ "isHide": "1",
+ "isLink": "",
+ "isKeepAlive": "0",
+ "isFull": "1",
+ "isAffix": "1",
+ "redirect": "",
+ "activeMenu": ""
+ },
+ {
+ "menuId": 39,
+ "menuName": "登录日志",
+ "enName": "Login Logs",
+ "parentId": 1,
+ "menuType": "2",
+ "name": "loginlogPage",
+ "path": "/system/loginlog",
+ "component": "system/loginlog/index",
+ "icon": "Calendar",
+ "isHide": "1",
+ "isLink": "",
+ "isKeepAlive": "0",
+ "isFull": "1",
+ "isAffix": "1",
+ "redirect": "",
+ "activeMenu": null
+ },
+ {
+ "menuId": 42,
+ "menuName": "操作日志",
+ "enName": "Operate Logs",
+ "parentId": 1,
+ "menuType": "2",
+ "name": "operlogPage",
+ "path": "/system/operlog",
+ "component": "system/operlog/index",
+ "icon": "Notebook",
+ "isHide": "1",
+ "isLink": "",
+ "isKeepAlive": "0",
+ "isFull": "1",
+ "isAffix": "1",
+ "redirect": "",
+ "activeMenu": null
+ },
+ {
+ "menuId": 50,
+ "menuName": "个人中心",
+ "enName": "Personage Center",
+ "parentId": 1,
+ "menuType": "2",
+ "name": "personagePage",
+ "path": "/system/personage",
+ "component": "system/personage/index",
+ "icon": "User",
+ "isHide": "0",
+ "isLink": "",
+ "isKeepAlive": "0",
+ "isFull": "1",
+ "isAffix": "1",
+ "redirect": null,
+ "activeMenu": null
+ },
+ {
+ "menuId": 166,
+ "menuName": "外部链接",
+ "enName": "External Link",
+ "parentId": 0,
+ "menuType": "1",
+ "name": "linkPage",
+ "path": "/link",
+ "component": "",
+ "icon": "Link",
+ "isHide": "0",
+ "isLink": "",
+ "isKeepAlive": "0",
+ "isFull": "1",
+ "isAffix": "1",
+ "redirect": null,
+ "activeMenu": null
+ }
+ ]
+}
+```
+
+**调用示例**:
+
+```bash
+curl -X GET \
+ "http://localhost:18099/coder/sysMenu/listPage?pageNo=1&pageSize=10&menuName=系统管理" \
+ -H "Authorization: your-token-value"
+```
+
+---
+
+### 2. 查询菜单列表
+
+**接口地址**: `GET /coder/sysMenu/list`
+
+**接口描述**: 查询系统菜单列表(树形结构,不分页)
+
+**是否需要认证**: 是
+
+**权限要求**: `system:menu:list`
+
+**请求参数**: 同分页查询(除pageNo、pageSize外)
+
+**响应示例**:
+
+```json
+{
+ "status": 200,
+ "msg": "SUCCESS",
+ "data": [
+ {
+ "menuId": 1,
+ "menuName": "系统管理",
+ "enName": "System",
+ "parentId": 0,
+ "menuType": "1",
+ "path": "/system",
+ "name": "system",
+ "component": "Layout",
+ "icon": "system",
+ "auth": "",
+ "menuStatus": "0",
+ "activeMenu": "",
+ "isHide": "1",
+ "isLink": "1",
+ "isKeepAlive": "0",
+ "isFull": "1",
+ "isAffix": "1",
+ "isSpread": "0",
+ "sorted": 1,
+ "createBy": "admin",
+ "createTime": "2024-01-01 10:00:00",
+ "updateBy": "admin",
+ "updateTime": "2024-01-01 10:00:00",
+ "children": [
+ // 子菜单...
+ ]
+ }
+ ],
+ "traceId": "trace-123456"
+}
+```
+
+**调用示例**:
+
+```bash
+curl -X GET \
+ "http://localhost:18099/coder/sysMenu/list" \
+ -H "Authorization: your-token-value"
+```
+
+---
+
+### 3. 根据ID查询菜单
+
+**接口地址**: `GET /coder/sysMenu/getById/{id}`
+
+**接口描述**: 根据菜单ID查询菜单详细信息
+
+**是否需要认证**: 是
+
+**权限要求**: `system:menu:list`
+
+**路径参数**:
+
+| 参数名 | 类型 | 必填 | 说明 |
+|--------|------|------|------|
+| id | Long | 是 | 菜单ID |
+
+**响应示例**:
+
+```json
+{
+ "status": 200,
+ "msg": "SUCCESS",
+ "data": {
+ "menuId": 1,
+ "menuName": "系统管理",
+ "enName": "System",
+ "parentId": 0,
+ "menuType": "1",
+ "path": "/system",
+ "name": "system",
+ "component": "Layout",
+ "icon": "system",
+ "auth": "",
+ "menuStatus": "0",
+ "activeMenu": "",
+ "isHide": "1",
+ "isLink": "1",
+ "isKeepAlive": "0",
+ "isFull": "1",
+ "isAffix": "1",
+ "isSpread": "0",
+ "sorted": 1,
+ "createBy": "admin",
+ "createTime": "2024-01-01 10:00:00",
+ "updateBy": "admin",
+ "updateTime": "2024-01-01 10:00:00"
+ },
+ "traceId": "trace-123456"
+}
+```
+
+**调用示例**:
+
+```bash
+curl -X GET \
+ http://localhost:18099/coder/sysMenu/getById/1 \
+ -H "Authorization: your-token-value"
+```
+
+---
+
+### 4. 新增菜单
+
+**接口地址**: `POST /coder/sysMenu/add`
+
+**接口描述**: 新增系统菜单
+
+**是否需要认证**: 是
+
+**权限要求**: `system:menu:add`
+
+**请求参数**:
+
+```json
+{
+ "menuName": "用户管理",
+ "enName": "User Management",
+ "parentId": 1,
+ "menuType": "2",
+ "path": "/system/user",
+ "name": "user",
+ "component": "/system/user/index",
+ "icon": "user",
+ "auth": "system:user:list",
+ "menuStatus": "0",
+ "activeMenu": "",
+ "isHide": "1",
+ "isLink": "1",
+ "isKeepAlive": "0",
+ "isFull": "1",
+ "isAffix": "1",
+ "isSpread": "0",
+ "sorted": 1
+}
+```
+
+**请求参数说明**:
+
+| 参数名 | 类型 | 必填 | 说明 | 校验规则 |
+|--------|------|------|------|----------|
+| menuName | String | 是 | 菜单名称 | 不能为空 |
+| enName | String | 否 | 英文名称 | 可为空 |
+| parentId | Long | 是 | 父菜单ID | 不能为空,0表示根菜单 |
+| menuType | String | 是 | 菜单类型 | 1-目录 2-菜单 3-按钮 |
+| path | String | 否 | 路由地址 | 菜单类型为2时必填 |
+| name | String | 否 | 路由名称 | 菜单类型为2时必填 |
+| component | String | 否 | 组件路径 | 菜单类型为2时必填 |
+| icon | String | 否 | 菜单图标 | 可为空 |
+| auth | String | 否 | 权限标识 | 按钮类型时必填 |
+| menuStatus | String | 是 | 菜单状态 | 0-启用 1-停用 |
+| activeMenu | String | 否 | 选中路由 | 可为空 |
+| isHide | String | 是 | 是否隐藏 | 0-隐藏 1-显示 |
+| isLink | String | 否 | 是否外链 | 0-是 1-否 |
+| isKeepAlive | String | 否 | 是否缓存 | 0-是 1-否 |
+| isFull | String | 否 | 是否全屏 | 0-是 1-否 |
+| isAffix | String | 否 | 是否固定 | 0-是 1-否 |
+| isSpread | String | 否 | 是否展开 | 0-是 1-否 |
+| sorted | Integer | 是 | 显示顺序 | 不能为空 |
+
+**响应示例**:
+
+```json
+{
+ "status": 200,
+ "msg": "SUCCESS",
+ "data": "新增成功",
+ "traceId": "trace-123456"
+}
+```
+
+**调用示例**:
+
+```bash
+curl -X POST \
+ http://localhost:18099/coder/sysMenu/add \
+ -H "Content-Type: application/json" \
+ -H "Authorization: your-token-value" \
+ -d '{
+ "menuName": "用户管理",
+ "enName": "User Management",
+ "parentId": 1,
+ "menuType": "2",
+ "path": "/system/user",
+ "name": "user",
+ "component": "/system/user/index",
+ "icon": "user",
+ "auth": "system:user:list",
+ "menuStatus": "0",
+ "activeMenu": "",
+ "isHide": "1",
+ "isLink": "1",
+ "isKeepAlive": "0",
+ "isFull": "1",
+ "isAffix": "1",
+ "isSpread": "0",
+ "sorted": 1
+ }'
+```
+
+---
+
+### 5. 修改菜单信息
+
+**接口地址**: `POST /coder/sysMenu/update`
+
+**接口描述**: 修改系统菜单信息
+
+**是否需要认证**: 是
+
+**权限要求**: `system:menu:edit`
+
+**请求参数**:
+
+```json
+{
+ "menuId": 1,
+ "menuName": "用户管理",
+ "enName": "User Management",
+ "parentId": 1,
+ "menuType": "2",
+ "path": "/system/user",
+ "name": "user",
+ "component": "/system/user/index",
+ "icon": "user",
+ "auth": "system:user:list",
+ "menuStatus": "0",
+ "activeMenu": "",
+ "isHide": "1",
+ "isLink": "1",
+ "isKeepAlive": "0",
+ "isFull": "1",
+ "isAffix": "1",
+ "isSpread": "0",
+ "sorted": 1
+}
+```
+
+**请求参数说明**:
+
+| 参数名 | 类型 | 必填 | 说明 | 校验规则 |
+|--------|------|------|------|----------|
+| menuId | Long | 是 | 菜单ID | 必须是有效的菜单ID |
+| 其他参数 | - | - | 同新增菜单 | - |
+
+**响应示例**:
+
+```json
+{
+ "status": 200,
+ "msg": "SUCCESS",
+ "data": "修改成功",
+ "traceId": "trace-123456"
+}
+```
+
+**调用示例**:
+
+```bash
+curl -X POST \
+ http://localhost:18099/coder/sysMenu/update \
+ -H "Content-Type: application/json" \
+ -H "Authorization: your-token-value" \
+ -d '{
+ "menuId": 1,
+ "menuName": "用户管理",
+ "parentId": 1,
+ "menuType": "2",
+ "menuStatus": "0",
+ "sorted": 1
+ }'
+```
+
+---
+
+### 6. 删除菜单
+
+**接口地址**: `POST /coder/sysMenu/deleteById/{id}`
+
+**接口描述**: 根据ID删除菜单
+
+**是否需要认证**: 是
+
+**权限要求**: `system:menu:remove`
+
+**路径参数**:
+
+| 参数名 | 类型 | 必填 | 说明 |
+|--------|------|------|------|
+| id | Long | 是 | 菜单ID |
+
+**响应示例**:
+
+```json
+{
+ "status": 200,
+ "msg": "SUCCESS",
+ "data": "删除成功",
+ "traceId": "trace-123456"
+}
+```
+
+**调用示例**:
+
+```bash
+curl -X POST \
+ http://localhost:18099/coder/sysMenu/deleteById/1 \
+ -H "Authorization: your-token-value"
+```
+
+---
+
+### 7. 批量删除菜单
+
+**接口地址**: `POST /coder/sysMenu/batchDelete`
+
+**接口描述**: 批量删除菜单
+
+**是否需要认证**: 是
+
+**权限要求**: `system:menu:remove`
+
+**请求参数**:
+
+```json
+{
+ "ids": [1, 2, 3]
+}
+```
+
+**请求参数说明**:
+
+| 参数名 | 类型 | 必填 | 说明 |
+|--------|------|------|------|
+| ids | Long[] | 是 | 菜单ID数组 |
+
+**响应示例**:
+
+```json
+{
+ "status": 200,
+ "msg": "SUCCESS",
+ "data": "删除成功",
+ "traceId": "trace-123456"
+}
+```
+
+**调用示例**:
+
+```bash
+curl -X POST \
+ http://localhost:18099/coder/sysMenu/batchDelete \
+ -H "Content-Type: application/json" \
+ -H "Authorization: your-token-value" \
+ -d '{
+ "ids": [1, 2, 3]
+ }'
+```
+
+---
+
+### 8. 修改菜单状态
+
+**接口地址**: `POST /coder/sysMenu/updateStatus/{id}/{menuStatus}`
+
+**接口描述**: 修改菜单状态(启用/停用)
+
+**是否需要认证**: 是
+
+**权限要求**: `system:menu:edit`
+
+**路径参数**:
+
+| 参数名 | 类型 | 必填 | 说明 |
+|--------|------|------|------|
+| id | Long | 是 | 菜单ID |
+| menuStatus | String | 是 | 菜单状态(0-启用 1-停用) |
+
+**响应示例**:
+
+```json
+{
+ "status": 200,
+ "msg": "SUCCESS",
+ "data": "修改成功",
+ "traceId": "trace-123456"
+}
+```
+
+**调用示例**:
+
+```bash
+curl -X POST \
+ http://localhost:18099/coder/sysMenu/updateStatus/1/0 \
+ -H "Authorization: your-token-value"
+```
+
+---
+
+### 9. 修改菜单展开状态
+
+**接口地址**: `POST /coder/sysMenu/updateSpread/{id}/{isSpread}`
+
+**接口描述**: 修改菜单展开状态
+
+**是否需要认证**: 是
+
+**权限要求**: `system:menu:edit`
+
+**路径参数**:
+
+| 参数名 | 类型 | 必填 | 说明 |
+|--------|------|------|------|
+| id | Long | 是 | 菜单ID |
+| isSpread | String | 是 | 展开状态(0-是 1-否) |
+
+**响应示例**:
+
+```json
+{
+ "status": 200,
+ "msg": "SUCCESS",
+ "data": "修改成功",
+ "traceId": "trace-123456"
+}
+```
+
+**调用示例**:
+
+```bash
+curl -X POST \
+ http://localhost:18099/coder/sysMenu/updateSpread/1/0 \
+ -H "Authorization: your-token-value"
+```
+
+---
+
+### 10. 菜单级联下拉框
+
+**接口地址**: `GET /coder/sysMenu/cascaderList`
+
+**接口描述**: 获取菜单级联下拉框数据
+
+**是否需要认证**: 是
+
+**权限要求**: `system:menu:list`
+
+**请求参数**: 无
+
+**响应示例**:
+
+```json
+{
+ "status": 200,
+ "msg": "SUCCESS",
+ "data": [
+ {
+ "label": "系统管理",
+ "value": 1,
+ "parentId": "0",
+ "children": [
+ {
+ "label": "用户管理",
+ "value": 2,
+ "parentId": "1"
+ },
+ {
+ "label": "角色管理",
+ "value": 3,
+ "parentId": "1"
+ }
+ ]
+ }
+ ],
+ "traceId": "trace-123456"
+}
+```
+
+**调用示例**:
+
+```bash
+curl -X GET \
+ http://localhost:18099/coder/sysMenu/cascaderList \
+ -H "Authorization: your-token-value"
+```
+
+---
+
+### 11. 生成用户菜单路由
+
+**接口地址**: `GET /coder/sysMenu/listRouters`
+
+**接口描述**: 根据当前用户权限生成前端菜单路由
+
+**是否需要认证**: 是
+
+**权限要求**: 无(已登录用户可访问)
+
+**请求参数**: 无
+
+**响应示例**:
+
+```json
+{
+ "code": 1,
+ "success": true,
+ "msg": "操作成功",
+ "data": [
+ {
+ "menuId": 1,
+ "menuName": "系统管理",
+ "enName": "System Manage",
+ "parentId": 0,
+ "menuType": "1",
+ "name": "systemPage",
+ "path": "/system",
+ "component": "",
+ "icon": "Tools",
+ "isHide": "1",
+ "isLink": "",
+ "isKeepAlive": "0",
+ "isFull": "1",
+ "isAffix": "1",
+ "redirect": "/system/user",
+ "activeMenu": null
+ },
+ {
+ "menuId": 2,
+ "menuName": "用户管理",
+ "enName": "User Manage",
+ "parentId": 1,
+ "menuType": "2",
+ "name": "userPage",
+ "path": "/system/user",
+ "component": "system/user/index",
+ "icon": "UserFilled",
+ "isHide": "1",
+ "isLink": "",
+ "isKeepAlive": "1",
+ "isFull": "1",
+ "isAffix": "1",
+ "redirect": "",
+ "activeMenu": null
+ },
+ {
+ "menuId": 70,
+ "menuName": "系统工具",
+ "enName": "System Tools",
+ "parentId": 0,
+ "menuType": "1",
+ "name": "toolsPage",
+ "path": "/tools",
+ "component": "",
+ "icon": "Tools",
+ "isHide": "1",
+ "isLink": "",
+ "isKeepAlive": "0",
+ "isFull": "1",
+ "isAffix": "1",
+ "redirect": "/tools/file",
+ "activeMenu": null
+ },
+ {
+ "menuId": 12,
+ "menuName": "角色管理",
+ "enName": "Role Manage",
+ "parentId": 1,
+ "menuType": "2",
+ "name": "rolePage",
+ "path": "/system/role",
+ "component": "system/role/index",
+ "icon": "Avatar",
+ "isHide": "1",
+ "isLink": "",
+ "isKeepAlive": "0",
+ "isFull": "1",
+ "isAffix": "1",
+ "redirect": "",
+ "activeMenu": null
+ },
+ {
+ "menuId": 72,
+ "menuName": "文件管理",
+ "enName": "Files Manage",
+ "parentId": 70,
+ "menuType": "2",
+ "name": "filePage",
+ "path": "/tools/file",
+ "component": "system/file/index",
+ "icon": "FolderOpened",
+ "isHide": "1",
+ "isLink": "",
+ "isKeepAlive": "0",
+ "isFull": "1",
+ "isAffix": "1",
+ "redirect": "",
+ "activeMenu": ""
+ },
+ {
+ "menuId": 19,
+ "menuName": "菜单管理",
+ "enName": "Menu Manage",
+ "parentId": 1,
+ "menuType": "2",
+ "name": "menuPage",
+ "path": "/system/menu",
+ "component": "system/menu/index",
+ "icon": "Grid",
+ "isHide": "1",
+ "isLink": "",
+ "isKeepAlive": "0",
+ "isFull": "1",
+ "isAffix": "1",
+ "redirect": "",
+ "activeMenu": null
+ },
+ {
+ "menuId": 77,
+ "menuName": "图库管理",
+ "enName": "Pictures Manage",
+ "parentId": 70,
+ "menuType": "2",
+ "name": "picturePage",
+ "path": "/tools/picture",
+ "component": "system/picture/index",
+ "icon": "Picture",
+ "isHide": "1",
+ "isLink": "",
+ "isKeepAlive": "0",
+ "isFull": "1",
+ "isAffix": "1",
+ "redirect": "",
+ "activeMenu": ""
+ },
+ {
+ "menuId": 39,
+ "menuName": "登录日志",
+ "enName": "Login Logs",
+ "parentId": 1,
+ "menuType": "2",
+ "name": "loginlogPage",
+ "path": "/system/loginlog",
+ "component": "system/loginlog/index",
+ "icon": "Calendar",
+ "isHide": "1",
+ "isLink": "",
+ "isKeepAlive": "0",
+ "isFull": "1",
+ "isAffix": "1",
+ "redirect": "",
+ "activeMenu": null
+ },
+ {
+ "menuId": 42,
+ "menuName": "操作日志",
+ "enName": "Operate Logs",
+ "parentId": 1,
+ "menuType": "2",
+ "name": "operlogPage",
+ "path": "/system/operlog",
+ "component": "system/operlog/index",
+ "icon": "Notebook",
+ "isHide": "1",
+ "isLink": "",
+ "isKeepAlive": "0",
+ "isFull": "1",
+ "isAffix": "1",
+ "redirect": "",
+ "activeMenu": null
+ },
+ {
+ "menuId": 50,
+ "menuName": "个人中心",
+ "enName": "Personage Center",
+ "parentId": 1,
+ "menuType": "2",
+ "name": "personagePage",
+ "path": "/system/personage",
+ "component": "system/personage/index",
+ "icon": "User",
+ "isHide": "0",
+ "isLink": "",
+ "isKeepAlive": "0",
+ "isFull": "1",
+ "isAffix": "1",
+ "redirect": null,
+ "activeMenu": null
+ },
+ {
+ "menuId": 166,
+ "menuName": "外部链接",
+ "enName": "External Link",
+ "parentId": 0,
+ "menuType": "1",
+ "name": "linkPage",
+ "path": "/link",
+ "component": "",
+ "icon": "Link",
+ "isHide": "0",
+ "isLink": "",
+ "isKeepAlive": "0",
+ "isFull": "1",
+ "isAffix": "1",
+ "redirect": null,
+ "activeMenu": null
+ }
+ ]
+}
+```
+
+**调用示例**:
+
+```bash
+curl -X GET \
+ http://localhost:18099/coder/sysMenu/listRouters \
+ -H "Authorization: your-token-value"
+```
+
+---
+
+### 12. 查询正常菜单列表
+
+**接口地址**: `GET /coder/sysMenu/listMenuNormal`
+
+**接口描述**: 查询状态正常的菜单列表
+
+**是否需要认证**: 是
+
+**权限要求**: `system:menu:list`
+
+**请求参数**: 无
+
+**响应示例**:
+
+```json
+{
+ "status": 200,
+ "msg": "SUCCESS",
+ "data": [
+ {
+ "menuId": 1,
+ "menuName": "系统管理",
+ "enName": "System",
+ "parentId": 0,
+ "menuType": "1",
+ "path": "/system",
+ "name": "system",
+ "component": "Layout",
+ "icon": "system",
+ "auth": "",
+ "menuStatus": "0",
+ "activeMenu": "",
+ "isHide": "1",
+ "isLink": "1",
+ "isKeepAlive": "0",
+ "isFull": "1",
+ "isAffix": "1",
+ "isSpread": "0",
+ "sorted": 1,
+ "children": [
+ // 子菜单...
+ ]
+ }
+ ],
+ "traceId": "trace-123456"
+}
+```
+
+**调用示例**:
+
+```bash
+curl -X GET \
+ http://localhost:18099/coder/sysMenu/listMenuNormal \
+ -H "Authorization: your-token-value"
+```
+
+---
+
+### 13. 根据角色ID查询菜单
+
+**接口地址**: `GET /coder/sysMenu/listMenuIdsByRoleId/{roleId}`
+
+**接口描述**: 根据角色ID查询该角色拥有的菜单ID列表
+
+**是否需要认证**: 是
+
+**权限要求**: `system:menu:list`
+
+**路径参数**:
+
+| 参数名 | 类型 | 必填 | 说明 |
+|--------|------|------|------|
+| roleId | Long | 是 | 角色ID |
+
+**响应示例**:
+
+```json
+{
+ "status": 200,
+ "msg": "SUCCESS",
+ "data": [1, 2, 3, 4, 5],
+ "traceId": "trace-123456"
+}
+```
+
+**调用示例**:
+
+```bash
+curl -X GET \
+ http://localhost:18099/coder/sysMenu/listMenuIdsByRoleId/1 \
+ -H "Authorization: your-token-value"
+```
+
+---
+
+### 14. 保存角色菜单权限
+
+**接口地址**: `POST /coder/sysMenu/saveRoleMenu/{roleId}/{menuIds}`
+
+**接口描述**: 保存角色的菜单权限
+
+**是否需要认证**: 是
+
+**权限要求**: `system:menu:assign`
+
+**路径参数**:
+
+| 参数名 | 类型 | 必填 | 说明 |
+|--------|------|------|------|
+| roleId | Long | 是 | 角色ID |
+| menuIds | String | 是 | 菜单ID列表(逗号分隔) |
+
+**响应示例**:
+
+```json
+{
+ "status": 200,
+ "msg": "SUCCESS",
+ "data": "保存成功",
+ "traceId": "trace-123456"
+}
+```
+
+**调用示例**:
+
+```bash
+curl -X POST \
+ http://localhost:18099/coder/sysMenu/saveRoleMenu/1/1,2,3,4,5 \
+ -H "Authorization: your-token-value"
+```
+
+---
+
+## 菜单字段说明
+
+### 基础字段
+
+| 字段名 | 类型 | 说明 | 示例 |
+|--------|------|------|------|
+| menuId | Long | 菜单ID | 1 |
+| menuName | String | 菜单名称 | 系统管理 |
+| enName | String | 英文名称 | System |
+| parentId | Long | 父菜单ID | 0(根菜单) |
+| menuType | String | 菜单类型 | 1-目录 2-菜单 3-按钮 |
+| sorted | Integer | 显示顺序 | 1 |
+
+### 路由字段
+
+| 字段名 | 类型 | 说明 | 示例 |
+|--------|------|------|------|
+| path | String | 路由地址 | /system/user |
+| name | String | 路由名称 | user |
+| component | String | 组件路径 | /system/user/index |
+| redirect | String | 重定向地址 | /system/user |
+| activeMenu | String | 选中路由 | /system/user |
+
+### 权限字段
+
+| 字段名 | 类型 | 说明 | 示例 |
+|--------|------|------|------|
+| auth | String | 权限标识 | system:user:list |
+| menuStatus | String | 菜单状态 | 0-启用 1-停用 |
+
+### 显示字段
+
+| 字段名 | 类型 | 说明 | 示例 |
+|--------|------|------|------|
+| icon | String | 菜单图标 | user |
+| isHide | String | 是否隐藏 | 0-隐藏 1-显示 |
+| isLink | String | 是否外链 | 0-是 1-否 |
+| isKeepAlive | String | 是否缓存 | 0-是 1-否 |
+| isFull | String | 是否全屏 | 0-是 1-否 |
+| isAffix | String | 是否固定 | 0-是 1-否 |
+| isSpread | String | 是否展开 | 0-是 1-否 |
+
+---
+
+## 前端路由配置
+
+### Vue Router 配置
+
+```javascript
+// 根据后端返回的菜单数据生成路由
+function generateRoutes(menuData) {
+ const routes = [];
+
+ menuData.forEach(menu => {
+ const route = {
+ path: menu.path,
+ name: menu.name,
+ component: () => import(`@/views${menu.component}.vue`),
+ meta: {
+ title: menu.menuName,
+ icon: menu.icon,
+ isHide: menu.isHide === '0',
+ isLink: menu.isLink === '0',
+ isKeepAlive: menu.isKeepAlive === '0',
+ isFull: menu.isFull === '0',
+ isAffix: menu.isAffix === '0',
+ activeMenu: menu.activeMenu
+ }
+ };
+
+ if (menu.children && menu.children.length > 0) {
+ route.children = generateRoutes(menu.children);
+ }
+
+ if (menu.redirect) {
+ route.redirect = menu.redirect;
+ }
+
+ routes.push(route);
+ });
+
+ return routes;
+}
+```
+
+### 权限控制
+
+```javascript
+// 页面权限控制
+router.beforeEach((to, from, next) => {
+ const userPermissions = store.getters.permissions;
+
+ if (to.meta.auth) {
+ if (userPermissions.includes(to.meta.auth) || userPermissions.includes('*:*:*')) {
+ next();
+ } else {
+ next('/403');
+ }
+ } else {
+ next();
+ }
+});
+
+// 按钮权限控制
+Vue.directive('permission', {
+ inserted(el, binding) {
+ const { value } = binding;
+ const permissions = store.getters.permissions;
+
+ if (value) {
+ const hasPermission = permissions.includes(value) || permissions.includes('*:*:*');
+ if (!hasPermission) {
+ el.parentNode && el.parentNode.removeChild(el);
+ }
+ }
+ }
+});
+```
+
+---
+
+## 错误码说明
+
+| 错误码 | 错误信息 | 说明 |
+|--------|----------|------|
+| 400 | 菜单名称不能为空 | 菜单名称为空 |
+| 400 | 上级菜单不能为空 | 父菜单ID为空 |
+| 400 | 菜单类型不能为空 | 菜单类型为空 |
+| 400 | 菜单状态不能为空 | 菜单状态为空 |
+| 400 | 是否隐藏菜单不能为空 | 隐藏状态为空 |
+| 400 | 显示顺序不能为空 | 排序值为空 |
+| 400 | 菜单不存在 | 菜单ID不存在 |
+| 400 | 存在子菜单,不允许删除 | 菜单有子菜单时不能删除 |
+| 400 | 菜单已分配,不允许删除 | 菜单已分配给角色时不能删除 |
+| 400 | 不能选择自己作为父菜单 | 父菜单不能是自己 |
+| 400 | 路由地址不能为空 | 菜单类型为菜单时路由地址必填 |
+| 400 | 组件路径不能为空 | 菜单类型为菜单时组件路径必填 |
+| 400 | 权限标识不能为空 | 菜单类型为按钮时权限标识必填 |
+| 401 | 当前会话未登录 | 未登录或Token无效 |
+| 403 | 权限不足 | 没有相应的操作权限 |
+| 500 | 系统异常 | 服务器内部错误 |
+
+---
+
+## 使用建议
+
+### 1. 菜单设计规范
+
+- **层级结构**: 建议不超过3级菜单
+- **命名规范**: 使用有意义的英文名称作为路由名称
+- **权限标识**: 使用模块:功能:操作的格式
+- **图标使用**: 统一使用Element UI或其他图标库
+
+### 2. 权限设计
+
+- **粒度控制**: 按钮级别的权限控制
+- **角色分离**: 不同角色分配不同的菜单权限
+- **继承关系**: 子菜单权限依赖于父菜单权限
+- **缓存策略**: 用户权限信息缓存到前端
+
+### 3. 性能优化
+
+- **懒加载**: 菜单组件使用懒加载
+- **缓存机制**: 菜单数据缓存到本地存储
+- **权限缓存**: 权限信息缓存到内存中
+- **树形结构**: 使用高效的树形数据结构
+
+### 4. 安全考虑
+
+- **权限验证**: 前后端都要进行权限验证
+- **敏感操作**: 重要操作需要二次确认
+- **日志记录**: 记录权限变更操作日志
+- **最小权限**: 遵循最小权限原则
+
+---
+
+## 注意事项
+
+1. **菜单删除**: 删除菜单前需要检查是否有子菜单和角色关联
+2. **权限继承**: 子菜单的权限依赖于父菜单
+3. **缓存更新**: 菜单权限变更后需要清理相关缓存
+4. **前端同步**: 菜单结构变更后前端需要同步更新
+5. **权限验证**: 前后端都需要进行权限验证
+6. **状态管理**: 菜单状态变更会影响用户访问
+7. **排序规则**: 菜单按照sorted字段升序排列
+8. **数据完整性**: 保证菜单数据的完整性和一致性
\ No newline at end of file
diff --git a/api/permission/角色管理API.md b/api/permission/角色管理API.md
new file mode 100644
index 0000000..673a18f
--- /dev/null
+++ b/api/permission/角色管理API.md
@@ -0,0 +1,882 @@
+# 角色管理API
+
+## 概述
+
+角色管理模块是权限系统的重要组成部分,负责管理系统角色、角色权限分配和用户角色关联。基于RBAC权限模型,实现了灵活的角色权限管理机制。
+
+## 权限说明
+
+角色管理接口需要相应的权限才能访问:
+
+| 操作 | 权限码 | 说明 |
+|------|--------|------|
+| 查询角色列表 | `system:role:list` | 查看角色列表权限 |
+| 新增角色 | `system:role:add` | 新增角色权限 |
+| 修改角色 | `system:role:edit` | 修改角色信息权限 |
+| 删除角色 | `system:role:remove` | 删除角色权限 |
+| 分配权限 | `system:role:assign` | 分配角色权限 |
+| 用户授权 | `system:user:role` | 分配用户角色权限 |
+
+## 接口列表
+
+### 1. 分页查询角色列表
+
+**接口地址**: `GET /coder/sysRole/listPage`
+
+**接口描述**: 分页查询系统角色列表
+
+**是否需要认证**: 是
+
+**权限要求**: `system:role:list`
+
+**请求头**:
+```
+Authorization: your-token-value
+```
+
+**请求参数**:
+
+| 参数名 | 类型 | 必填 | 说明 | 示例 |
+|--------|------|------|------|------|
+| pageNo | Integer | 否 | 页码 | 1 |
+| pageSize | Integer | 否 | 每页大小 | 10 |
+| roleName | String | 否 | 角色名称 | 管理员 |
+| roleCode | String | 否 | 角色编码 | admin |
+| roleStatus | String | 否 | 角色状态 | 0 |
+| beginTime | String | 否 | 开始时间 | 2024-01-01 |
+| endTime | String | 否 | 结束时间 | 2024-12-31 |
+
+**响应示例**:
+
+```json
+{
+ "status": 200,
+ "msg": "SUCCESS",
+ "data": {
+ "records": [
+ {
+ "roleId": 1,
+ "roleName": "超级管理员",
+ "roleCode": "admin",
+ "roleStatus": "0",
+ "dataScope": "1",
+ "deptCheckStrictly": "1",
+ "menuCheckStrictly": "1",
+ "sorted": 1,
+ "remark": "超级管理员",
+ "createBy": "admin",
+ "createTime": "2024-01-01 10:00:00",
+ "updateBy": "admin",
+ "updateTime": "2024-01-01 10:00:00",
+ "menuIds": [1, 2, 3, 4, 5],
+ "deptIds": [100, 101, 102]
+ }
+ ],
+ "total": 1,
+ "size": 10,
+ "current": 1,
+ "pages": 1
+ },
+ "traceId": "trace-123456"
+}
+```
+
+**调用示例**:
+
+```bash
+curl -X GET \
+ "http://localhost:18099/coder/sysRole/listPage?pageNo=1&pageSize=10&roleName=管理员" \
+ -H "Authorization: your-token-value"
+```
+
+---
+
+### 2. 查询所有角色
+
+**接口地址**: `GET /coder/sysRole/list`
+
+**接口描述**: 查询所有系统角色(不分页)
+
+**是否需要认证**: 是
+
+**权限要求**: `system:role:list`
+
+**请求参数**: 同分页查询(除pageNo、pageSize外)
+
+**响应示例**:
+
+```json
+{
+ "status": 200,
+ "msg": "SUCCESS",
+ "data": [
+ {
+ "roleId": 1,
+ "roleName": "超级管理员",
+ "roleCode": "admin",
+ "roleStatus": "0",
+ "dataScope": "1",
+ "deptCheckStrictly": "1",
+ "menuCheckStrictly": "1",
+ "sorted": 1,
+ "remark": "超级管理员",
+ "createBy": "admin",
+ "createTime": "2024-01-01 10:00:00",
+ "updateBy": "admin",
+ "updateTime": "2024-01-01 10:00:00"
+ }
+ ],
+ "traceId": "trace-123456"
+}
+```
+
+**调用示例**:
+
+```bash
+curl -X GET \
+ "http://localhost:18099/coder/sysRole/list" \
+ -H "Authorization: your-token-value"
+```
+
+---
+
+### 3. 根据ID查询角色
+
+**接口地址**: `GET /coder/sysRole/getById/{id}`
+
+**接口描述**: 根据角色ID查询角色详细信息
+
+**是否需要认证**: 是
+
+**权限要求**: `system:role:list`
+
+**路径参数**:
+
+| 参数名 | 类型 | 必填 | 说明 |
+|--------|------|------|------|
+| id | Long | 是 | 角色ID |
+
+**响应示例**:
+
+```json
+{
+ "status": 200,
+ "msg": "SUCCESS",
+ "data": {
+ "roleId": 1,
+ "roleName": "超级管理员",
+ "roleCode": "admin",
+ "roleStatus": "0",
+ "dataScope": "1",
+ "deptCheckStrictly": "1",
+ "menuCheckStrictly": "1",
+ "sorted": 1,
+ "remark": "超级管理员",
+ "createBy": "admin",
+ "createTime": "2024-01-01 10:00:00",
+ "updateBy": "admin",
+ "updateTime": "2024-01-01 10:00:00",
+ "menuIds": [1, 2, 3, 4, 5],
+ "deptIds": [100, 101, 102]
+ },
+ "traceId": "trace-123456"
+}
+```
+
+**调用示例**:
+
+```bash
+curl -X GET \
+ http://localhost:18099/coder/sysRole/getById/1 \
+ -H "Authorization: your-token-value"
+```
+
+---
+
+### 4. 新增角色
+
+**接口地址**: `POST /coder/sysRole/add`
+
+**接口描述**: 新增系统角色
+
+**是否需要认证**: 是
+
+**权限要求**: `system:role:add`
+
+**请求参数**:
+
+```json
+{
+ "roleName": "普通用户",
+ "roleCode": "user",
+ "roleStatus": "0",
+ "dataScope": "2",
+ "deptCheckStrictly": "1",
+ "menuCheckStrictly": "1",
+ "sorted": 2,
+ "remark": "普通用户角色",
+ "menuIds": [1, 2, 3],
+ "deptIds": [100, 101]
+}
+```
+
+**请求参数说明**:
+
+| 参数名 | 类型 | 必填 | 说明 | 校验规则 |
+|--------|------|------|------|----------|
+| roleName | String | 是 | 角色名称 | 不能为空,最长30字符 |
+| roleCode | String | 是 | 角色编码 | 不能为空,最长100字符,唯一 |
+| roleStatus | String | 是 | 角色状态 | 0-正常 1-停用 |
+| dataScope | String | 否 | 数据范围 | 1-全部数据 2-自定义数据 3-本部门数据 4-本部门及以下数据 5-仅本人数据 |
+| deptCheckStrictly | String | 否 | 部门树选择项是否关联显示 | 0-父子不互相关联显示 1-父子互相关联显示 |
+| menuCheckStrictly | String | 否 | 菜单树选择项是否关联显示 | 0-父子不互相关联显示 1-父子互相关联显示 |
+| sorted | Integer | 是 | 显示顺序 | 不能为空 |
+| remark | String | 否 | 备注信息 | 最长200字符 |
+| menuIds | Long[] | 否 | 菜单ID数组 | 有效的菜单ID |
+| deptIds | Long[] | 否 | 部门ID数组 | 有效的部门ID |
+
+**响应示例**:
+
+```json
+{
+ "status": 200,
+ "msg": "SUCCESS",
+ "data": "新增成功",
+ "traceId": "trace-123456"
+}
+```
+
+**调用示例**:
+
+```bash
+curl -X POST \
+ http://localhost:18099/coder/sysRole/add \
+ -H "Content-Type: application/json" \
+ -H "Authorization: your-token-value" \
+ -d '{
+ "roleName": "普通用户",
+ "roleCode": "user",
+ "roleStatus": "0",
+ "dataScope": "2",
+ "deptCheckStrictly": "1",
+ "menuCheckStrictly": "1",
+ "sorted": 2,
+ "remark": "普通用户角色",
+ "menuIds": [1, 2, 3],
+ "deptIds": [100, 101]
+ }'
+```
+
+---
+
+### 5. 获取最新排序号
+
+**接口地址**: `GET /coder/sysRole/getSorted`
+
+**接口描述**: 获取角色的最新排序号
+
+**是否需要认证**: 是
+
+**权限要求**: `system:role:add`
+
+**请求参数**: 无
+
+**响应示例**:
+
+```json
+{
+ "status": 200,
+ "msg": "SUCCESS",
+ "data": 10,
+ "traceId": "trace-123456"
+}
+```
+
+**调用示例**:
+
+```bash
+curl -X GET \
+ http://localhost:18099/coder/sysRole/getSorted \
+ -H "Authorization: your-token-value"
+```
+
+---
+
+### 6. 修改角色信息
+
+**接口地址**: `POST /coder/sysRole/update`
+
+**接口描述**: 修改系统角色信息
+
+**是否需要认证**: 是
+
+**权限要求**: `system:role:edit`
+
+**请求参数**:
+
+```json
+{
+ "roleId": 1,
+ "roleName": "超级管理员",
+ "roleCode": "admin",
+ "roleStatus": "0",
+ "dataScope": "1",
+ "deptCheckStrictly": "1",
+ "menuCheckStrictly": "1",
+ "sorted": 1,
+ "remark": "超级管理员",
+ "menuIds": [1, 2, 3, 4, 5],
+ "deptIds": [100, 101, 102]
+}
+```
+
+**请求参数说明**:
+
+| 参数名 | 类型 | 必填 | 说明 | 校验规则 |
+|--------|------|------|------|----------|
+| roleId | Long | 是 | 角色ID | 必须是有效的角色ID |
+| 其他参数 | - | - | 同新增角色 | - |
+
+**响应示例**:
+
+```json
+{
+ "status": 200,
+ "msg": "SUCCESS",
+ "data": "修改成功",
+ "traceId": "trace-123456"
+}
+```
+
+**调用示例**:
+
+```bash
+curl -X POST \
+ http://localhost:18099/coder/sysRole/update \
+ -H "Content-Type: application/json" \
+ -H "Authorization: your-token-value" \
+ -d '{
+ "roleId": 1,
+ "roleName": "超级管理员",
+ "roleCode": "admin",
+ "roleStatus": "0",
+ "sorted": 1
+ }'
+```
+
+---
+
+### 7. 删除角色
+
+**接口地址**: `POST /coder/sysRole/deleteById/{id}`
+
+**接口描述**: 根据ID删除角色
+
+**是否需要认证**: 是
+
+**权限要求**: `system:role:remove`
+
+**路径参数**:
+
+| 参数名 | 类型 | 必填 | 说明 |
+|--------|------|------|------|
+| id | Long | 是 | 角色ID |
+
+**响应示例**:
+
+```json
+{
+ "status": 200,
+ "msg": "SUCCESS",
+ "data": "删除成功",
+ "traceId": "trace-123456"
+}
+```
+
+**调用示例**:
+
+```bash
+curl -X POST \
+ http://localhost:18099/coder/sysRole/deleteById/1 \
+ -H "Authorization: your-token-value"
+```
+
+---
+
+### 8. 批量删除角色
+
+**接口地址**: `POST /coder/sysRole/batchDelete`
+
+**接口描述**: 批量删除角色
+
+**是否需要认证**: 是
+
+**权限要求**: `system:role:remove`
+
+**请求参数**:
+
+```json
+{
+ "ids": [1, 2, 3]
+}
+```
+
+**请求参数说明**:
+
+| 参数名 | 类型 | 必填 | 说明 |
+|--------|------|------|------|
+| ids | Long[] | 是 | 角色ID数组 |
+
+**响应示例**:
+
+```json
+{
+ "status": 200,
+ "msg": "SUCCESS",
+ "data": "删除成功",
+ "traceId": "trace-123456"
+}
+```
+
+**调用示例**:
+
+```bash
+curl -X POST \
+ http://localhost:18099/coder/sysRole/batchDelete \
+ -H "Content-Type: application/json" \
+ -H "Authorization: your-token-value" \
+ -d '{
+ "ids": [1, 2, 3]
+ }'
+```
+
+---
+
+### 9. 修改角色状态
+
+**接口地址**: `POST /coder/sysRole/updateStatus/{roleId}/{roleStatus}`
+
+**接口描述**: 修改角色状态(正常/停用)
+
+**是否需要认证**: 是
+
+**权限要求**: `system:role:edit`
+
+**路径参数**:
+
+| 参数名 | 类型 | 必填 | 说明 |
+|--------|------|------|------|
+| roleId | Long | 是 | 角色ID |
+| roleStatus | String | 是 | 角色状态(0-正常 1-停用) |
+
+**响应示例**:
+
+```json
+{
+ "status": 200,
+ "msg": "SUCCESS",
+ "data": "修改成功",
+ "traceId": "trace-123456"
+}
+```
+
+**调用示例**:
+
+```bash
+curl -X POST \
+ http://localhost:18099/coder/sysRole/updateStatus/1/0 \
+ -H "Authorization: your-token-value"
+```
+
+---
+
+### 10. 查询正常角色穿梭框
+
+**接口地址**: `GET /coder/sysRole/listNormalRole/{userId}`
+
+**接口描述**: 查询正常状态的角色用于穿梭框显示
+
+**是否需要认证**: 是
+
+**权限要求**: `system:user:role`
+
+**路径参数**:
+
+| 参数名 | 类型 | 必填 | 说明 |
+|--------|------|------|------|
+| userId | Long | 是 | 用户ID |
+
+**响应示例**:
+
+```json
+{
+ "status": 200,
+ "msg": "SUCCESS",
+ "data": [
+ {
+ "label": "超级管理员",
+ "value": 1,
+ "parentId": ""
+ },
+ {
+ "label": "普通用户",
+ "value": 2,
+ "parentId": ""
+ }
+ ],
+ "traceId": "trace-123456"
+}
+```
+
+**调用示例**:
+
+```bash
+curl -X GET \
+ http://localhost:18099/coder/sysRole/listNormalRole/1 \
+ -H "Authorization: your-token-value"
+```
+
+---
+
+### 11. 分配用户角色
+
+**接口地址**: `GET /coder/sysRole/assignUserRole/{userId}/{roleIds}`
+
+**接口描述**: 为用户分配角色
+
+**是否需要认证**: 是
+
+**权限要求**: `system:user:role`
+
+**路径参数**:
+
+| 参数名 | 类型 | 必填 | 说明 |
+|--------|------|------|------|
+| userId | Long | 是 | 用户ID |
+| roleIds | String | 是 | 角色ID列表(逗号分隔) |
+
+**响应示例**:
+
+```json
+{
+ "status": 200,
+ "msg": "SUCCESS",
+ "data": "分配成功",
+ "traceId": "trace-123456"
+}
+```
+
+**调用示例**:
+
+```bash
+curl -X GET \
+ http://localhost:18099/coder/sysRole/assignUserRole/1/1,2,3 \
+ -H "Authorization: your-token-value"
+```
+
+---
+
+### 12. 获取角色下拉框
+
+**接口地址**: `GET /coder/sysRole/listRoleElSelect`
+
+**接口描述**: 获取角色下拉框数据
+
+**是否需要认证**: 是
+
+**权限要求**: `system:role:list`
+
+**请求参数**: 无
+
+**响应示例**:
+
+```json
+{
+ "status": 200,
+ "msg": "SUCCESS",
+ "data": [
+ {
+ "label": "超级管理员",
+ "value": 1
+ },
+ {
+ "label": "普通用户",
+ "value": 2
+ }
+ ],
+ "traceId": "trace-123456"
+}
+```
+
+**调用示例**:
+
+```bash
+curl -X GET \
+ http://localhost:18099/coder/sysRole/listRoleElSelect \
+ -H "Authorization: your-token-value"
+```
+
+---
+
+## 角色字段说明
+
+### 基础字段
+
+| 字段名 | 类型 | 说明 | 示例 |
+|--------|------|------|------|
+| roleId | Long | 角色ID | 1 |
+| roleName | String | 角色名称 | 超级管理员 |
+| roleCode | String | 角色编码 | admin |
+| roleStatus | String | 角色状态 | 0-正常 1-停用 |
+| sorted | Integer | 显示顺序 | 1 |
+| remark | String | 备注信息 | 超级管理员 |
+
+### 权限字段
+
+| 字段名 | 类型 | 说明 | 示例 |
+|--------|------|------|------|
+| dataScope | String | 数据权限范围 | 1-全部数据 2-自定义数据 3-本部门数据 4-本部门及以下数据 5-仅本人数据 |
+| deptCheckStrictly | String | 部门树选择项是否关联显示 | 0-父子不互相关联显示 1-父子互相关联显示 |
+| menuCheckStrictly | String | 菜单树选择项是否关联显示 | 0-父子不互相关联显示 1-父子互相关联显示 |
+
+### 关联字段
+
+| 字段名 | 类型 | 说明 | 示例 |
+|--------|------|------|------|
+| menuIds | Long[] | 菜单ID数组 | [1, 2, 3, 4, 5] |
+| deptIds | Long[] | 部门ID数组 | [100, 101, 102] |
+
+---
+
+## 数据字典
+
+### 角色状态 (roleStatus)
+
+| 值 | 说明 |
+|----|------|
+| 0 | 正常 |
+| 1 | 停用 |
+
+### 数据权限范围 (dataScope)
+
+| 值 | 说明 |
+|----|------|
+| 1 | 全部数据权限 |
+| 2 | 自定数据权限 |
+| 3 | 本部门数据权限 |
+| 4 | 本部门及以下数据权限 |
+| 5 | 仅本人数据权限 |
+
+### 树选择项关联显示
+
+| 值 | 说明 |
+|----|------|
+| 0 | 父子不互相关联显示 |
+| 1 | 父子互相关联显示 |
+
+---
+
+## 权限验证机制
+
+### 1. 角色权限验证
+
+```java
+// Sa-Token权限验证
+@SaCheckPermission("system:role:list")
+public List list() {
+ // 业务逻辑
+}
+```
+
+### 2. 数据权限控制
+
+```java
+// 根据用户数据权限过滤数据
+public List getRolesByDataScope(Long userId) {
+ SysUser user = getCurrentUser();
+ String dataScope = user.getDataScope();
+
+ switch (dataScope) {
+ case "1": // 全部数据权限
+ return getAllRoles();
+ case "2": // 自定义数据权限
+ return getRolesByDeptIds(user.getDeptIds());
+ case "3": // 本部门数据权限
+ return getRolesByDept(user.getDeptId());
+ case "4": // 本部门及以下数据权限
+ return getRolesByDeptAndChildren(user.getDeptId());
+ case "5": // 仅本人数据权限
+ return getRolesByUserId(userId);
+ default:
+ return new ArrayList<>();
+ }
+}
+```
+
+### 3. 角色权限缓存
+
+```java
+// 缓存用户角色权限
+@Cacheable(value = "userRoles", key = "#userId")
+public List getRolesByUserId(Long userId) {
+ return roleMapper.selectRolePermissionByUserId(userId);
+}
+
+// 清除角色权限缓存
+@CacheEvict(value = "userRoles", key = "#userId")
+public void clearUserRoleCache(Long userId) {
+ // 角色变更时清除缓存
+}
+```
+
+---
+
+## 错误码说明
+
+| 错误码 | 错误信息 | 说明 |
+|--------|----------|------|
+| 400 | 角色名称不能为空 | 角色名称为空 |
+| 400 | 角色权限编码不能为空 | 角色编码为空 |
+| 400 | 显示顺序不能为空 | 排序值为空 |
+| 400 | 角色不存在 | 角色ID不存在 |
+| 400 | 角色编码已存在 | 角色编码重复 |
+| 400 | 角色已分配用户,不允许删除 | 角色已分配给用户时不能删除 |
+| 400 | 不能删除超级管理员角色 | 超级管理员角色不能删除 |
+| 400 | 不能停用超级管理员角色 | 超级管理员角色不能停用 |
+| 400 | 用户不存在 | 用户ID不存在 |
+| 400 | 角色ID列表不能为空 | 分配角色时角色ID为空 |
+| 401 | 当前会话未登录 | 未登录或Token无效 |
+| 403 | 权限不足 | 没有相应的操作权限 |
+| 500 | 系统异常 | 服务器内部错误 |
+
+---
+
+## RBAC权限模型
+
+### 1. 基本概念
+
+- **用户 (User)**: 系统的使用者
+- **角色 (Role)**: 权限的集合,连接用户和权限的桥梁
+- **权限 (Permission)**: 对系统资源的操作权限
+- **会话 (Session)**: 用户与系统的一次交互过程
+
+### 2. 关系模型
+
+```
+用户 ←→ 用户角色关系 ←→ 角色 ←→ 角色权限关系 ←→ 权限
+```
+
+### 3. 数据库设计
+
+```sql
+-- 用户表
+CREATE TABLE sys_login_user (
+ user_id BIGINT PRIMARY KEY,
+ login_name VARCHAR(32) UNIQUE NOT NULL,
+ user_name VARCHAR(32) NOT NULL,
+ -- 其他字段...
+);
+
+-- 角色表
+CREATE TABLE sys_role (
+ role_id BIGINT PRIMARY KEY,
+ role_name VARCHAR(32) NOT NULL,
+ role_code VARCHAR(32) UNIQUE NOT NULL,
+ role_status CHAR(1) DEFAULT '0',
+ -- 其他字段...
+);
+
+-- 权限表(菜单表)
+CREATE TABLE sys_menu (
+ menu_id BIGINT PRIMARY KEY,
+ menu_name VARCHAR(64) NOT NULL,
+ auth VARCHAR(128),
+ -- 其他字段...
+);
+
+-- 用户角色关联表
+CREATE TABLE sys_user_role (
+ user_id BIGINT NOT NULL,
+ role_id BIGINT NOT NULL,
+ PRIMARY KEY (user_id, role_id)
+);
+
+-- 角色权限关联表
+CREATE TABLE sys_role_menu (
+ role_id BIGINT NOT NULL,
+ menu_id BIGINT NOT NULL,
+ PRIMARY KEY (role_id, menu_id)
+);
+```
+
+---
+
+## 使用建议
+
+### 1. 角色设计原则
+
+- **最小权限原则**: 每个角色只分配必要的权限
+- **职责分离**: 不同职责的操作分配给不同角色
+- **角色层次**: 建立角色层次结构,高级角色继承低级角色权限
+- **定期审查**: 定期审查角色权限,及时调整
+
+### 2. 权限分配策略
+
+- **默认无权限**: 新建角色默认无任何权限
+- **逐步授权**: 根据业务需要逐步授权
+- **权限组合**: 通过多个角色组合实现复杂权限需求
+- **临时授权**: 支持临时权限授权机制
+
+### 3. 数据权限控制
+
+- **部门数据权限**: 基于用户所属部门控制数据访问范围
+- **自定义数据权限**: 支持自定义数据访问范围
+- **数据隔离**: 确保不同用户只能访问授权范围内的数据
+- **审计日志**: 记录数据访问日志
+
+### 4. 性能优化
+
+- **权限缓存**: 将用户权限信息缓存到Redis
+- **批量操作**: 支持批量分配和撤销权限
+- **索引优化**: 对关联表建立合适的索引
+- **分页查询**: 大数据量时使用分页查询
+
+---
+
+## 安全考虑
+
+### 1. 权限验证
+
+- **双重验证**: 前后端都要进行权限验证
+- **接口鉴权**: 每个接口都要验证权限
+- **数据鉴权**: 数据层面的权限验证
+- **操作鉴权**: 敏感操作的二次验证
+
+### 2. 权限变更
+
+- **变更日志**: 记录所有权限变更操作
+- **审批流程**: 重要权限变更需要审批
+- **通知机制**: 权限变更及时通知相关人员
+- **回滚机制**: 支持权限变更回滚
+
+### 3. 会话安全
+
+- **会话超时**: 设置会话超时时间
+- **单点登录**: 防止重复登录
+- **强制下线**: 支持强制用户下线
+- **设备绑定**: 支持设备级别的访问控制
+
+---
+
+## 注意事项
+
+1. **角色删除**: 删除角色前需要检查是否有用户关联
+2. **权限继承**: 考虑角色之间的权限继承关系
+3. **缓存一致性**: 角色权限变更后需要清理相关缓存
+4. **数据完整性**: 保证角色权限数据的完整性
+5. **超级管理员**: 超级管理员角色不能删除和停用
+6. **权限验证**: 前后端都需要进行权限验证
+7. **审计日志**: 记录所有角色操作日志
+8. **性能考虑**: 大量用户时注意权限验证性能
+9. **数据权限**: 正确配置数据权限范围
+10. **定期清理**: 定期清理无效的角色和权限关联
\ No newline at end of file
diff --git a/api/system/图片管理API.md b/api/system/图片管理API.md
new file mode 100644
index 0000000..67339a6
--- /dev/null
+++ b/api/system/图片管理API.md
@@ -0,0 +1,871 @@
+# 图片管理API
+
+## 概述
+
+图片管理模块专门用于管理系统中的图片资源,提供图片的上传、存储、展示和管理功能。支持多种图片格式,具备图片压缩、水印、缩略图生成等高级功能。
+
+## 权限说明
+
+图片管理接口需要相应的权限才能访问:
+
+| 操作 | 权限码 | 说明 |
+|------|--------|------|
+| 查询图片列表 | `system:picture:list` | 查看图片列表权限 |
+| 上传图片 | `system:picture:upload` | 上传图片权限 |
+| 删除图片 | `system:picture:remove` | 删除图片权限 |
+| 编辑图片 | `system:picture:edit` | 编辑图片信息权限 |
+
+## 接口列表
+
+### 1. 分页查询图片列表
+
+**接口地址**: `GET /coder/sysPicture/listPage`
+
+**接口描述**: 分页查询系统图片列表
+
+**是否需要认证**: 是
+
+**权限要求**: `system:picture:list`
+
+**请求头**:
+```
+Authorization: Bearer your-token-value
+```
+
+**请求参数**:
+
+| 参数名 | 类型 | 必填 | 说明 | 示例 |
+|--------|------|------|------|------|
+| pageNo | Integer | 否 | 页码 | 1 |
+| pageSize | Integer | 否 | 每页大小 | 10 |
+| pictureName | String | 否 | 图片名称 | banner.jpg |
+| pictureType | String | 否 | 图片类型 | jpg |
+| albumName | String | 否 | 相册名称 | banner |
+| pictureStatus | String | 否 | 图片状态 | 0 |
+| beginTime | String | 否 | 开始时间 | 2024-01-01 |
+| endTime | String | 否 | 结束时间 | 2024-12-31 |
+
+**响应示例**:
+
+```json
+{
+ "status": 200,
+ "msg": "SUCCESS",
+ "data": {
+ "records": [
+ {
+ "pictureId": 1,
+ "pictureName": "banner_20240705_001.jpg",
+ "originalName": "主页横幅.jpg",
+ "picturePath": "/upload/pictures/banner/2024/07/05/banner_20240705_001.jpg",
+ "pictureUrl": "http://localhost:18099/upload/pictures/banner/2024/07/05/banner_20240705_001.jpg",
+ "thumbnailUrl": "http://localhost:18099/upload/pictures/banner/2024/07/05/thumb_banner_20240705_001.jpg",
+ "albumName": "banner",
+ "pictureSize": 2048000,
+ "pictureType": "jpg",
+ "pictureFormat": "JPEG",
+ "width": 1920,
+ "height": 1080,
+ "pictureStatus": "0",
+ "isWatermark": "0",
+ "uploadUserId": 1,
+ "uploadUserName": "admin",
+ "description": "主页横幅图片",
+ "tags": "横幅,主页,展示",
+ "viewCount": 100,
+ "downloadCount": 10,
+ "remark": "网站主页横幅",
+ "createBy": "admin",
+ "createTime": "2024-07-05 10:00:00",
+ "updateBy": "admin",
+ "updateTime": "2024-07-05 10:00:00"
+ }
+ ],
+ "total": 1,
+ "size": 10,
+ "current": 1,
+ "pages": 1
+ },
+ "traceId": "trace-123456"
+}
+```
+
+**调用示例**:
+
+```bash
+curl -X GET \
+ "http://localhost:18099/coder/sysPicture/listPage?pageNo=1&pageSize=10&albumName=banner" \
+ -H "Authorization: Bearer your-token-value"
+```
+
+---
+
+### 2. 查询所有图片
+
+**接口地址**: `GET /coder/sysPicture/list`
+
+**接口描述**: 查询所有系统图片(不分页)
+
+**是否需要认证**: 是
+
+**权限要求**: `system:picture:list`
+
+**请求参数**: 同分页查询(除pageNo、pageSize外)
+
+**响应示例**:
+
+```json
+{
+ "status": 200,
+ "msg": "SUCCESS",
+ "data": [
+ {
+ "pictureId": 1,
+ "pictureName": "banner_20240705_001.jpg",
+ "originalName": "主页横幅.jpg",
+ "picturePath": "/upload/pictures/banner/2024/07/05/banner_20240705_001.jpg",
+ "pictureUrl": "http://localhost:18099/upload/pictures/banner/2024/07/05/banner_20240705_001.jpg",
+ "thumbnailUrl": "http://localhost:18099/upload/pictures/banner/2024/07/05/thumb_banner_20240705_001.jpg",
+ "albumName": "banner",
+ "pictureSize": 2048000,
+ "pictureType": "jpg",
+ "pictureFormat": "JPEG",
+ "width": 1920,
+ "height": 1080,
+ "pictureStatus": "0",
+ "isWatermark": "0",
+ "uploadUserId": 1,
+ "uploadUserName": "admin",
+ "description": "主页横幅图片",
+ "tags": "横幅,主页,展示",
+ "viewCount": 100,
+ "downloadCount": 10,
+ "remark": "网站主页横幅",
+ "createBy": "admin",
+ "createTime": "2024-07-05 10:00:00",
+ "updateBy": "admin",
+ "updateTime": "2024-07-05 10:00:00"
+ }
+ ],
+ "traceId": "trace-123456"
+}
+```
+
+**调用示例**:
+
+```bash
+curl -X GET \
+ "http://localhost:18099/coder/sysPicture/list?albumName=banner" \
+ -H "Authorization: Bearer your-token-value"
+```
+
+---
+
+### 3. 根据ID查询图片
+
+**接口地址**: `GET /coder/sysPicture/getById/{id}`
+
+**接口描述**: 根据图片ID查询图片详细信息
+
+**是否需要认证**: 是
+
+**权限要求**: `system:picture:list`
+
+**路径参数**:
+
+| 参数名 | 类型 | 必填 | 说明 |
+|--------|------|------|------|
+| id | Long | 是 | 图片ID |
+
+**响应示例**:
+
+```json
+{
+ "status": 200,
+ "msg": "SUCCESS",
+ "data": {
+ "pictureId": 1,
+ "pictureName": "banner_20240705_001.jpg",
+ "originalName": "主页横幅.jpg",
+ "picturePath": "/upload/pictures/banner/2024/07/05/banner_20240705_001.jpg",
+ "pictureUrl": "http://localhost:18099/upload/pictures/banner/2024/07/05/banner_20240705_001.jpg",
+ "thumbnailUrl": "http://localhost:18099/upload/pictures/banner/2024/07/05/thumb_banner_20240705_001.jpg",
+ "albumName": "banner",
+ "pictureSize": 2048000,
+ "pictureType": "jpg",
+ "pictureFormat": "JPEG",
+ "width": 1920,
+ "height": 1080,
+ "pictureStatus": "0",
+ "isWatermark": "0",
+ "uploadUserId": 1,
+ "uploadUserName": "admin",
+ "description": "主页横幅图片",
+ "tags": "横幅,主页,展示",
+ "viewCount": 100,
+ "downloadCount": 10,
+ "remark": "网站主页横幅",
+ "createBy": "admin",
+ "createTime": "2024-07-05 10:00:00",
+ "updateBy": "admin",
+ "updateTime": "2024-07-05 10:00:00"
+ },
+ "traceId": "trace-123456"
+}
+```
+
+**调用示例**:
+
+```bash
+curl -X GET \
+ http://localhost:18099/coder/sysPicture/getById/1 \
+ -H "Authorization: Bearer your-token-value"
+```
+
+---
+
+### 4. 新增图片记录
+
+**接口地址**: `POST /coder/sysPicture/add`
+
+**接口描述**: 新增系统图片记录
+
+**是否需要认证**: 是
+
+**权限要求**: `system:picture:upload`
+
+**请求参数**:
+
+```json
+{
+ "pictureName": "product_20240705_001.jpg",
+ "originalName": "产品展示图.jpg",
+ "picturePath": "/upload/pictures/product/2024/07/05/product_20240705_001.jpg",
+ "pictureUrl": "http://localhost:18099/upload/pictures/product/2024/07/05/product_20240705_001.jpg",
+ "thumbnailUrl": "http://localhost:18099/upload/pictures/product/2024/07/05/thumb_product_20240705_001.jpg",
+ "albumName": "product",
+ "pictureSize": 1536000,
+ "pictureType": "jpg",
+ "pictureFormat": "JPEG",
+ "width": 1200,
+ "height": 800,
+ "pictureStatus": "0",
+ "isWatermark": "1",
+ "uploadUserId": 1,
+ "uploadUserName": "admin",
+ "description": "产品展示图片",
+ "tags": "产品,展示,商品",
+ "remark": "商品详情页图片"
+}
+```
+
+**请求参数说明**:
+
+| 参数名 | 类型 | 必填 | 说明 | 校验规则 |
+|--------|------|------|------|----------|
+| pictureName | String | 是 | 存储图片名 | 不能为空 |
+| originalName | String | 是 | 原始图片名 | 不能为空 |
+| picturePath | String | 是 | 图片相对路径 | 不能为空 |
+| pictureUrl | String | 是 | 图片访问URL | 不能为空 |
+| thumbnailUrl | String | 否 | 缩略图URL | 可为空 |
+| albumName | String | 是 | 相册名称 | 不能为空 |
+| pictureSize | Long | 是 | 图片大小 | 必须大于0 |
+| pictureType | String | 是 | 图片类型 | 不能为空 |
+| pictureFormat | String | 是 | 图片格式 | 不能为空 |
+| width | Integer | 否 | 图片宽度 | 大于0 |
+| height | Integer | 否 | 图片高度 | 大于0 |
+| pictureStatus | String | 是 | 图片状态 | 0-正常 1-删除 |
+| isWatermark | String | 否 | 是否水印 | 0-否 1-是 |
+| uploadUserId | Long | 否 | 上传用户ID | 有效的用户ID |
+| uploadUserName | String | 否 | 上传用户名 | 可为空 |
+| description | String | 否 | 图片描述 | 最长500字符 |
+| tags | String | 否 | 图片标签 | 逗号分隔 |
+| remark | String | 否 | 备注信息 | 最长200字符 |
+
+**响应示例**:
+
+```json
+{
+ "status": 200,
+ "msg": "SUCCESS",
+ "data": "新增成功",
+ "traceId": "trace-123456"
+}
+```
+
+**调用示例**:
+
+```bash
+curl -X POST \
+ http://localhost:18099/coder/sysPicture/add \
+ -H "Content-Type: application/json" \
+ -H "Authorization: Bearer your-token-value" \
+ -d '{
+ "pictureName": "product_20240705_001.jpg",
+ "originalName": "产品展示图.jpg",
+ "picturePath": "/upload/pictures/product/2024/07/05/product_20240705_001.jpg",
+ "pictureUrl": "http://localhost:18099/upload/pictures/product/2024/07/05/product_20240705_001.jpg",
+ "albumName": "product",
+ "pictureSize": 1536000,
+ "pictureType": "jpg",
+ "pictureFormat": "JPEG",
+ "width": 1200,
+ "height": 800,
+ "pictureStatus": "0",
+ "description": "产品展示图片",
+ "tags": "产品,展示,商品"
+ }'
+```
+
+---
+
+### 5. 修改图片信息
+
+**接口地址**: `POST /coder/sysPicture/update`
+
+**接口描述**: 修改系统图片记录信息
+
+**是否需要认证**: 是
+
+**权限要求**: `system:picture:edit`
+
+**请求参数**:
+
+```json
+{
+ "pictureId": 1,
+ "pictureName": "product_20240705_001.jpg",
+ "originalName": "产品展示图.jpg",
+ "picturePath": "/upload/pictures/product/2024/07/05/product_20240705_001.jpg",
+ "pictureUrl": "http://localhost:18099/upload/pictures/product/2024/07/05/product_20240705_001.jpg",
+ "thumbnailUrl": "http://localhost:18099/upload/pictures/product/2024/07/05/thumb_product_20240705_001.jpg",
+ "albumName": "product",
+ "pictureSize": 1536000,
+ "pictureType": "jpg",
+ "pictureFormat": "JPEG",
+ "width": 1200,
+ "height": 800,
+ "pictureStatus": "0",
+ "isWatermark": "1",
+ "uploadUserId": 1,
+ "uploadUserName": "admin",
+ "description": "产品展示图片(已更新)",
+ "tags": "产品,展示,商品,新品",
+ "remark": "商品详情页图片(已更新)"
+}
+```
+
+**请求参数说明**:
+
+| 参数名 | 类型 | 必填 | 说明 | 校验规则 |
+|--------|------|------|------|----------|
+| pictureId | Long | 是 | 图片ID | 必须是有效的图片ID |
+| 其他参数 | - | - | 同新增图片记录 | - |
+
+**响应示例**:
+
+```json
+{
+ "status": 200,
+ "msg": "SUCCESS",
+ "data": "修改成功",
+ "traceId": "trace-123456"
+}
+```
+
+**调用示例**:
+
+```bash
+curl -X POST \
+ http://localhost:18099/coder/sysPicture/update \
+ -H "Content-Type: application/json" \
+ -H "Authorization: Bearer your-token-value" \
+ -d '{
+ "pictureId": 1,
+ "description": "产品展示图片(已更新)",
+ "tags": "产品,展示,商品,新品"
+ }'
+```
+
+---
+
+### 6. 删除图片
+
+**接口地址**: `POST /coder/sysPicture/deleteById/{id}`
+
+**接口描述**: 根据ID删除图片记录和物理文件
+
+**是否需要认证**: 是
+
+**权限要求**: `system:picture:remove`
+
+**路径参数**:
+
+| 参数名 | 类型 | 必填 | 说明 |
+|--------|------|------|------|
+| id | Long | 是 | 图片ID |
+
+**响应示例**:
+
+```json
+{
+ "status": 200,
+ "msg": "SUCCESS",
+ "data": "删除成功",
+ "traceId": "trace-123456"
+}
+```
+
+**调用示例**:
+
+```bash
+curl -X POST \
+ http://localhost:18099/coder/sysPicture/deleteById/1 \
+ -H "Authorization: Bearer your-token-value"
+```
+
+---
+
+### 7. 批量删除图片
+
+**接口地址**: `POST /coder/sysPicture/batchDelete`
+
+**接口描述**: 批量删除图片记录和物理文件
+
+**是否需要认证**: 是
+
+**权限要求**: `system:picture:remove`
+
+**请求参数**:
+
+```json
+{
+ "ids": [1, 2, 3]
+}
+```
+
+**请求参数说明**:
+
+| 参数名 | 类型 | 必填 | 说明 |
+|--------|------|------|------|
+| ids | Long[] | 是 | 图片ID数组 |
+
+**响应示例**:
+
+```json
+{
+ "status": 200,
+ "msg": "SUCCESS",
+ "data": "删除成功",
+ "traceId": "trace-123456"
+}
+```
+
+**调用示例**:
+
+```bash
+curl -X POST \
+ http://localhost:18099/coder/sysPicture/batchDelete \
+ -H "Content-Type: application/json" \
+ -H "Authorization: Bearer your-token-value" \
+ -d '{
+ "ids": [1, 2, 3]
+ }'
+```
+
+---
+
+## 图片字段说明
+
+### 基础字段
+
+| 字段名 | 类型 | 说明 | 示例 |
+|--------|------|------|------|
+| pictureId | Long | 图片ID | 1 |
+| pictureName | String | 存储图片名 | banner_20240705_001.jpg |
+| originalName | String | 原始图片名 | 主页横幅.jpg |
+| picturePath | String | 图片相对路径 | /upload/pictures/banner/2024/07/05/banner_20240705_001.jpg |
+| pictureUrl | String | 图片访问URL | http://localhost:18099/upload/pictures/banner/2024/07/05/banner_20240705_001.jpg |
+| thumbnailUrl | String | 缩略图URL | http://localhost:18099/upload/pictures/banner/2024/07/05/thumb_banner_20240705_001.jpg |
+
+### 分类字段
+
+| 字段名 | 类型 | 说明 | 示例 |
+|--------|------|------|------|
+| albumName | String | 相册名称 | banner |
+| pictureType | String | 图片扩展名 | jpg |
+| pictureFormat | String | 图片格式 | JPEG |
+| pictureSize | Long | 图片大小(字节) | 2048000 |
+
+### 尺寸字段
+
+| 字段名 | 类型 | 说明 | 示例 |
+|--------|------|------|------|
+| width | Integer | 图片宽度(像素) | 1920 |
+| height | Integer | 图片高度(像素) | 1080 |
+
+### 状态字段
+
+| 字段名 | 类型 | 说明 | 示例 |
+|--------|------|------|------|
+| pictureStatus | String | 图片状态 | 0-正常 1-删除 |
+| isWatermark | String | 是否有水印 | 0-否 1-是 |
+| uploadUserId | Long | 上传用户ID | 1 |
+| uploadUserName | String | 上传用户名 | admin |
+
+### 描述字段
+
+| 字段名 | 类型 | 说明 | 示例 |
+|--------|------|------|------|
+| description | String | 图片描述 | 主页横幅图片 |
+| tags | String | 图片标签 | 横幅,主页,展示 |
+| remark | String | 备注信息 | 网站主页横幅 |
+
+### 统计字段
+
+| 字段名 | 类型 | 说明 | 示例 |
+|--------|------|------|------|
+| viewCount | Integer | 查看次数 | 100 |
+| downloadCount | Integer | 下载次数 | 10 |
+
+---
+
+## 数据字典
+
+### 图片状态 (pictureStatus)
+
+| 值 | 说明 |
+|----|------|
+| 0 | 正常 |
+| 1 | 已删除 |
+
+### 是否水印 (isWatermark)
+
+| 值 | 说明 |
+|----|------|
+| 0 | 无水印 |
+| 1 | 有水印 |
+
+### 支持的图片格式
+
+| 格式 | 扩展名 | MIME类型 | 说明 |
+|------|--------|----------|------|
+| JPEG | jpg, jpeg | image/jpeg | 有损压缩,适合照片 |
+| PNG | png | image/png | 无损压缩,支持透明 |
+| GIF | gif | image/gif | 支持动画 |
+| WebP | webp | image/webp | 现代格式,压缩率高 |
+| BMP | bmp | image/bmp | 位图格式 |
+| TIFF | tiff, tif | image/tiff | 高质量图像 |
+
+### 相册分类
+
+| 相册名称 | 说明 | 用途 |
+|----------|------|------|
+| banner | 横幅图片 | 网站横幅展示 |
+| product | 产品图片 | 商品展示 |
+| avatar | 头像图片 | 用户头像 |
+| gallery | 图库图片 | 相册展示 |
+| article | 文章图片 | 文章配图 |
+| icon | 图标图片 | 小图标 |
+| background | 背景图片 | 页面背景 |
+
+---
+
+## 图片处理功能
+
+### 1. 图片上传处理
+
+```java
+@Service
+public class PictureUploadService {
+
+ /**
+ * 上传图片
+ */
+ public PictureUploadResult uploadPicture(MultipartFile file, String album) {
+ // 1. 图片校验
+ validatePicture(file);
+
+ // 2. 生成文件名
+ String fileName = generatePictureName(file.getOriginalFilename());
+
+ // 3. 保存原图
+ String originalPath = savePicture(file, album, fileName);
+
+ // 4. 生成缩略图
+ String thumbnailPath = generateThumbnail(originalPath, album, fileName);
+
+ // 5. 添加水印
+ if (needWatermark(album)) {
+ addWatermark(originalPath);
+ }
+
+ // 6. 获取图片信息
+ BufferedImage image = ImageIO.read(new File(originalPath));
+ int width = image.getWidth();
+ int height = image.getHeight();
+
+ // 7. 生成访问URL
+ String pictureUrl = generatePictureUrl(album, fileName);
+ String thumbnailUrl = generateThumbnailUrl(album, fileName);
+
+ // 8. 返回结果
+ return PictureUploadResult.builder()
+ .pictureName(fileName)
+ .originalName(file.getOriginalFilename())
+ .picturePath(originalPath)
+ .pictureUrl(pictureUrl)
+ .thumbnailUrl(thumbnailUrl)
+ .pictureSize(file.getSize())
+ .pictureType(getFileExtension(fileName))
+ .pictureFormat(getImageFormat(file))
+ .width(width)
+ .height(height)
+ .build();
+ }
+
+ /**
+ * 生成缩略图
+ */
+ private String generateThumbnail(String originalPath, String album, String fileName) {
+ try {
+ BufferedImage originalImage = ImageIO.read(new File(originalPath));
+
+ // 计算缩略图尺寸
+ int thumbnailWidth = 200;
+ int thumbnailHeight = 150;
+
+ // 保持宽高比
+ double ratio = Math.min((double) thumbnailWidth / originalImage.getWidth(),
+ (double) thumbnailHeight / originalImage.getHeight());
+ int width = (int) (originalImage.getWidth() * ratio);
+ int height = (int) (originalImage.getHeight() * ratio);
+
+ // 生成缩略图
+ BufferedImage thumbnailImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
+ Graphics2D g2d = thumbnailImage.createGraphics();
+ g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
+ g2d.drawImage(originalImage, 0, 0, width, height, null);
+ g2d.dispose();
+
+ // 保存缩略图
+ String thumbnailPath = getThumbnailPath(album, fileName);
+ ImageIO.write(thumbnailImage, "jpg", new File(thumbnailPath));
+
+ return thumbnailPath;
+ } catch (IOException e) {
+ throw new BusinessException("生成缩略图失败", e);
+ }
+ }
+
+ /**
+ * 添加水印
+ */
+ private void addWatermark(String imagePath) {
+ try {
+ BufferedImage originalImage = ImageIO.read(new File(imagePath));
+ Graphics2D g2d = originalImage.createGraphics();
+
+ // 设置水印属性
+ g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.5f));
+ g2d.setColor(Color.LIGHT_GRAY);
+ g2d.setFont(new Font("Arial", Font.BOLD, 20));
+
+ // 计算水印位置
+ FontMetrics fm = g2d.getFontMetrics();
+ String watermarkText = "© Your Company";
+ int x = originalImage.getWidth() - fm.stringWidth(watermarkText) - 10;
+ int y = originalImage.getHeight() - fm.getHeight() + fm.getAscent() - 10;
+
+ // 绘制水印
+ g2d.drawString(watermarkText, x, y);
+ g2d.dispose();
+
+ // 保存带水印的图片
+ ImageIO.write(originalImage, "jpg", new File(imagePath));
+ } catch (IOException e) {
+ throw new BusinessException("添加水印失败", e);
+ }
+ }
+}
+```
+
+### 2. 图片压缩
+
+```java
+/**
+ * 图片压缩
+ */
+public void compressPicture(String inputPath, String outputPath, float quality) {
+ try {
+ BufferedImage image = ImageIO.read(new File(inputPath));
+
+ // 创建输出流
+ FileOutputStream fos = new FileOutputStream(outputPath);
+
+ // 获取JPEG写入器
+ Iterator writers = ImageIO.getImageWritersByFormatName("jpg");
+ ImageWriter writer = writers.next();
+
+ // 设置输出
+ ImageOutputStream ios = ImageIO.createImageOutputStream(fos);
+ writer.setOutput(ios);
+
+ // 设置压缩参数
+ ImageWriteParam param = writer.getDefaultWriteParam();
+ param.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
+ param.setCompressionQuality(quality); // 压缩质量 0.0-1.0
+
+ // 写入图片
+ writer.write(null, new IIOImage(image, null, null), param);
+
+ // 清理资源
+ ios.close();
+ fos.close();
+ writer.dispose();
+ } catch (IOException e) {
+ throw new BusinessException("图片压缩失败", e);
+ }
+}
+```
+
+### 3. 图片格式转换
+
+```java
+/**
+ * 图片格式转换
+ */
+public void convertPictureFormat(String inputPath, String outputPath, String format) {
+ try {
+ BufferedImage image = ImageIO.read(new File(inputPath));
+
+ // 如果转换为JPEG,需要处理透明背景
+ if ("jpg".equalsIgnoreCase(format) || "jpeg".equalsIgnoreCase(format)) {
+ BufferedImage jpegImage = new BufferedImage(image.getWidth(), image.getHeight(), BufferedImage.TYPE_INT_RGB);
+ Graphics2D g2d = jpegImage.createGraphics();
+ g2d.setColor(Color.WHITE);
+ g2d.fillRect(0, 0, image.getWidth(), image.getHeight());
+ g2d.drawImage(image, 0, 0, null);
+ g2d.dispose();
+ image = jpegImage;
+ }
+
+ // 保存转换后的图片
+ ImageIO.write(image, format, new File(outputPath));
+ } catch (IOException e) {
+ throw new BusinessException("图片格式转换失败", e);
+ }
+}
+```
+
+---
+
+## 错误码说明
+
+| 错误码 | 错误信息 | 说明 |
+|--------|----------|------|
+| 400 | 图片不能为空 | 上传图片为空 |
+| 400 | 图片大小不能超过{size}MB | 图片大小超过限制 |
+| 400 | 不支持的图片格式 | 图片格式不支持 |
+| 400 | 图片尺寸超过限制 | 图片宽高超过限制 |
+| 400 | 图片名称不能为空 | 图片名称为空 |
+| 400 | 相册名称不能为空 | 相册名称为空 |
+| 400 | 图片不存在 | 图片ID不存在 |
+| 400 | 图片已被删除 | 图片状态为已删除 |
+| 401 | 当前会话未登录 | 未登录或Token无效 |
+| 403 | 权限不足 | 没有相应的操作权限 |
+| 500 | 图片上传失败 | 图片保存到磁盘失败 |
+| 500 | 缩略图生成失败 | 缩略图生成过程失败 |
+| 500 | 水印添加失败 | 水印添加过程失败 |
+| 500 | 图片压缩失败 | 图片压缩过程失败 |
+| 500 | 图片删除失败 | 物理文件删除失败 |
+
+---
+
+## 安全特性
+
+### 1. 图片验证
+
+- **格式验证**: 验证图片格式和MIME类型
+- **尺寸验证**: 验证图片宽高限制
+- **内容验证**: 验证图片内容安全性
+- **病毒扫描**: 对上传图片进行病毒扫描
+
+### 2. 访问控制
+
+- **权限验证**: 验证用户访问权限
+- **防盗链**: 防止图片被盗链
+- **水印保护**: 添加水印保护版权
+- **下载限制**: 限制图片下载次数
+
+### 3. 存储安全
+
+- **路径安全**: 防止路径遍历攻击
+- **文件重命名**: 重命名避免冲突
+- **备份策略**: 重要图片定期备份
+- **权限设置**: 设置合适的文件权限
+
+---
+
+## 性能优化
+
+### 1. 图片处理优化
+
+- **异步处理**: 图片压缩和水印添加异步处理
+- **批量处理**: 支持批量图片处理
+- **缓存策略**: 缓存处理后的图片
+- **CDN加速**: 使用CDN加速图片访问
+
+### 2. 存储优化
+
+- **分目录存储**: 按相册和日期分目录存储
+- **格式优化**: 自动选择最优图片格式
+- **压缩存储**: 自动压缩降低存储空间
+- **重复检测**: 检测重复图片避免冗余
+
+### 3. 访问优化
+
+- **懒加载**: 图片懒加载技术
+- **响应式图片**: 根据设备提供不同尺寸
+- **WebP支持**: 支持WebP格式提高性能
+- **预加载**: 关键图片预加载
+
+---
+
+## 使用建议
+
+### 1. 图片命名规范
+
+- **唯一性**: 确保图片名唯一
+- **时间戳**: 包含时间戳信息
+- **分类标识**: 包含相册分类信息
+- **版本控制**: 支持图片版本管理
+
+### 2. 相册管理
+
+- **分类管理**: 按用途分类管理图片
+- **权限控制**: 不同相册设置不同权限
+- **容量限制**: 设置相册容量限制
+- **定期清理**: 定期清理无用图片
+
+### 3. 图片优化
+
+- **尺寸适配**: 根据用途选择合适尺寸
+- **格式选择**: 根据内容选择最优格式
+- **质量平衡**: 平衡图片质量和文件大小
+- **缓存策略**: 设置合适的缓存时间
+
+---
+
+## 注意事项
+
+1. **图片安全**: 严格验证上传图片格式和内容
+2. **版权保护**: 添加水印保护图片版权
+3. **存储管理**: 定期清理无效和重复图片
+4. **性能考虑**: 大图片上传时注意性能影响
+5. **备份策略**: 重要图片需要备份
+6. **访问控制**: 合理设置图片访问权限
+7. **格式支持**: 根据需要支持不同图片格式
+8. **缩略图**: 为提高加载速度生成缩略图
+9. **压缩处理**: 适当压缩减少存储空间
+10. **监控告警**: 监控存储空间和访问异常
\ No newline at end of file
diff --git a/api/system/文件管理API.md b/api/system/文件管理API.md
new file mode 100644
index 0000000..cde6262
--- /dev/null
+++ b/api/system/文件管理API.md
@@ -0,0 +1,867 @@
+# 文件管理API
+
+## 概述
+
+文件管理模块提供文件上传、下载、存储管理等功能。支持多种文件类型,提供文件记录管理和批量操作功能。分为通用文件上传接口和系统文件记录管理两部分。
+
+## 权限说明
+
+文件管理接口需要相应的权限才能访问:
+
+| 操作 | 权限码 | 说明 |
+|------|--------|------|
+| 查询文件列表 | `system:file:list` | 查看文件列表权限 |
+| 上传文件 | `system:file:upload` | 上传文件权限 |
+| 下载文件 | `system:file:download` | 下载文件权限 |
+| 删除文件 | `system:file:remove` | 删除文件权限 |
+
+## 文件上传接口
+
+### 1. 上传文件(需认证)
+
+**接口地址**: `POST /coder/file/uploadFile/{fileSize}/{folderName}/{fileParam}`
+
+**接口描述**: 上传文件到服务器(需要登录认证)
+
+**是否需要认证**: 是
+
+**权限要求**: `system:file:upload`
+
+**请求头**:
+```
+Authorization: Bearer your-token-value
+Content-Type: multipart/form-data
+```
+
+**路径参数**:
+
+| 参数名 | 类型 | 必填 | 说明 | 示例 |
+|--------|------|------|------|------|
+| fileSize | Integer | 是 | 文件大小限制(MB) | 10 |
+| folderName | String | 是 | 存储文件夹名称 | avatar |
+| fileParam | String | 是 | 文件参数名 | file |
+
+**请求参数**:
+
+| 参数名 | 类型 | 必填 | 说明 |
+|--------|------|------|------|
+| file | File | 是 | 上传的文件 |
+
+**响应示例**:
+
+```json
+{
+ "status": 200,
+ "msg": "SUCCESS",
+ "data": {
+ "fileName": "avatar.jpg",
+ "originalName": "my-avatar.jpg",
+ "filePath": "/upload/avatar/2024/07/05/avatar_20240705_001.jpg",
+ "fileUrl": "http://localhost:18099/upload/avatar/2024/07/05/avatar_20240705_001.jpg",
+ "fileSize": 1024000,
+ "fileType": "jpg",
+ "uploadTime": "2024-07-05 10:00:00"
+ },
+ "traceId": "trace-123456"
+}
+```
+
+**响应参数说明**:
+
+| 参数名 | 类型 | 说明 |
+|--------|------|------|
+| fileName | String | 存储文件名 |
+| originalName | String | 原始文件名 |
+| filePath | String | 文件相对路径 |
+| fileUrl | String | 文件访问URL |
+| fileSize | Long | 文件大小(字节) |
+| fileType | String | 文件类型 |
+| uploadTime | String | 上传时间 |
+
+**调用示例**:
+
+```bash
+curl -X POST \
+ http://localhost:18099/coder/file/uploadFile/10/avatar/file \
+ -H "Authorization: Bearer your-token-value" \
+ -F "file=@avatar.jpg"
+```
+
+**前端使用示例**:
+
+```javascript
+// 使用FormData上传文件
+function uploadFile(file, folder, maxSize) {
+ const formData = new FormData();
+ formData.append('file', file);
+
+ fetch(`/coder/file/uploadFile/${maxSize}/${folder}/file`, {
+ method: 'POST',
+ headers: {
+ 'Authorization': 'Bearer ' + localStorage.getItem('token')
+ },
+ body: formData
+ })
+ .then(response => response.json())
+ .then(data => {
+ if (data.status === 200) {
+ console.log('上传成功:', data.data.fileUrl);
+ } else {
+ console.error('上传失败:', data.msg);
+ }
+ });
+}
+```
+
+---
+
+### 2. 匿名上传文件
+
+**接口地址**: `POST /coder/file/uploadAnyFile/{fileSize}/{folderName}/{fileParam}`
+
+**接口描述**: 匿名上传文件到服务器(无需登录认证)
+
+**是否需要认证**: 否
+
+**权限要求**: 无
+
+**路径参数**: 同上传文件接口
+
+**请求参数**: 同上传文件接口
+
+**响应示例**: 同上传文件接口
+
+**调用示例**:
+
+```bash
+curl -X POST \
+ http://localhost:18099/coder/file/uploadAnyFile/5/temp/file \
+ -F "file=@document.pdf"
+```
+
+**使用场景**:
+- 用户注册时上传头像
+- 访客上传临时文件
+- 公开资源上传
+
+---
+
+## 系统文件记录管理接口
+
+### 1. 分页查询文件列表
+
+**接口地址**: `GET /coder/sysFile/listPage`
+
+**接口描述**: 分页查询系统文件记录列表
+
+**是否需要认证**: 是
+
+**权限要求**: `system:file:list`
+
+**请求头**:
+```
+Authorization: Bearer your-token-value
+```
+
+**请求参数**:
+
+| 参数名 | 类型 | 必填 | 说明 | 示例 |
+|--------|------|------|------|------|
+| pageNo | Integer | 否 | 页码 | 1 |
+| pageSize | Integer | 否 | 每页大小 | 10 |
+| fileName | String | 否 | 文件名称 | avatar.jpg |
+| fileType | String | 否 | 文件类型 | jpg |
+| folderName | String | 否 | 文件夹名称 | avatar |
+| beginTime | String | 否 | 开始时间 | 2024-01-01 |
+| endTime | String | 否 | 结束时间 | 2024-12-31 |
+
+**响应示例**:
+
+```json
+{
+ "status": 200,
+ "msg": "SUCCESS",
+ "data": {
+ "records": [
+ {
+ "fileId": 1,
+ "fileName": "avatar_20240705_001.jpg",
+ "originalName": "my-avatar.jpg",
+ "filePath": "/upload/avatar/2024/07/05/avatar_20240705_001.jpg",
+ "fileUrl": "http://localhost:18099/upload/avatar/2024/07/05/avatar_20240705_001.jpg",
+ "folderName": "avatar",
+ "fileSize": 1024000,
+ "fileType": "jpg",
+ "contentType": "image/jpeg",
+ "fileStatus": "0",
+ "uploadUserId": 1,
+ "uploadUserName": "admin",
+ "remark": "用户头像",
+ "createBy": "admin",
+ "createTime": "2024-07-05 10:00:00",
+ "updateBy": "admin",
+ "updateTime": "2024-07-05 10:00:00"
+ }
+ ],
+ "total": 1,
+ "size": 10,
+ "current": 1,
+ "pages": 1
+ },
+ "traceId": "trace-123456"
+}
+```
+
+**调用示例**:
+
+```bash
+curl -X GET \
+ "http://localhost:18099/coder/sysFile/listPage?pageNo=1&pageSize=10&fileName=avatar" \
+ -H "Authorization: Bearer your-token-value"
+```
+
+---
+
+### 2. 查询所有文件
+
+**接口地址**: `GET /coder/sysFile/list`
+
+**接口描述**: 查询所有系统文件记录(不分页)
+
+**是否需要认证**: 是
+
+**权限要求**: `system:file:list`
+
+**请求参数**: 同分页查询(除pageNo、pageSize外)
+
+**响应示例**:
+
+```json
+{
+ "status": 200,
+ "msg": "SUCCESS",
+ "data": [
+ {
+ "fileId": 1,
+ "fileName": "avatar_20240705_001.jpg",
+ "originalName": "my-avatar.jpg",
+ "filePath": "/upload/avatar/2024/07/05/avatar_20240705_001.jpg",
+ "fileUrl": "http://localhost:18099/upload/avatar/2024/07/05/avatar_20240705_001.jpg",
+ "folderName": "avatar",
+ "fileSize": 1024000,
+ "fileType": "jpg",
+ "contentType": "image/jpeg",
+ "fileStatus": "0",
+ "uploadUserId": 1,
+ "uploadUserName": "admin",
+ "remark": "用户头像",
+ "createBy": "admin",
+ "createTime": "2024-07-05 10:00:00",
+ "updateBy": "admin",
+ "updateTime": "2024-07-05 10:00:00"
+ }
+ ],
+ "traceId": "trace-123456"
+}
+```
+
+**调用示例**:
+
+```bash
+curl -X GET \
+ "http://localhost:18099/coder/sysFile/list?fileType=jpg" \
+ -H "Authorization: Bearer your-token-value"
+```
+
+---
+
+### 3. 根据ID查询文件
+
+**接口地址**: `GET /coder/sysFile/getById/{id}`
+
+**接口描述**: 根据文件ID查询文件详细信息
+
+**是否需要认证**: 是
+
+**权限要求**: `system:file:list`
+
+**路径参数**:
+
+| 参数名 | 类型 | 必填 | 说明 |
+|--------|------|------|------|
+| id | Long | 是 | 文件ID |
+
+**响应示例**:
+
+```json
+{
+ "status": 200,
+ "msg": "SUCCESS",
+ "data": {
+ "fileId": 1,
+ "fileName": "avatar_20240705_001.jpg",
+ "originalName": "my-avatar.jpg",
+ "filePath": "/upload/avatar/2024/07/05/avatar_20240705_001.jpg",
+ "fileUrl": "http://localhost:18099/upload/avatar/2024/07/05/avatar_20240705_001.jpg",
+ "folderName": "avatar",
+ "fileSize": 1024000,
+ "fileType": "jpg",
+ "contentType": "image/jpeg",
+ "fileStatus": "0",
+ "uploadUserId": 1,
+ "uploadUserName": "admin",
+ "remark": "用户头像",
+ "createBy": "admin",
+ "createTime": "2024-07-05 10:00:00",
+ "updateBy": "admin",
+ "updateTime": "2024-07-05 10:00:00"
+ },
+ "traceId": "trace-123456"
+}
+```
+
+**调用示例**:
+
+```bash
+curl -X GET \
+ http://localhost:18099/coder/sysFile/getById/1 \
+ -H "Authorization: Bearer your-token-value"
+```
+
+---
+
+### 4. 新增文件记录
+
+**接口地址**: `POST /coder/sysFile/add`
+
+**接口描述**: 新增系统文件记录
+
+**是否需要认证**: 是
+
+**权限要求**: `system:file:upload`
+
+**请求参数**:
+
+```json
+{
+ "fileName": "document_20240705_001.pdf",
+ "originalName": "重要文档.pdf",
+ "filePath": "/upload/documents/2024/07/05/document_20240705_001.pdf",
+ "fileUrl": "http://localhost:18099/upload/documents/2024/07/05/document_20240705_001.pdf",
+ "folderName": "documents",
+ "fileSize": 2048000,
+ "fileType": "pdf",
+ "contentType": "application/pdf",
+ "fileStatus": "0",
+ "uploadUserId": 1,
+ "uploadUserName": "admin",
+ "remark": "重要文档"
+}
+```
+
+**请求参数说明**:
+
+| 参数名 | 类型 | 必填 | 说明 | 校验规则 |
+|--------|------|------|------|----------|
+| fileName | String | 是 | 存储文件名 | 不能为空 |
+| originalName | String | 是 | 原始文件名 | 不能为空 |
+| filePath | String | 是 | 文件相对路径 | 不能为空 |
+| fileUrl | String | 是 | 文件访问URL | 不能为空 |
+| folderName | String | 是 | 文件夹名称 | 不能为空 |
+| fileSize | Long | 是 | 文件大小 | 必须大于0 |
+| fileType | String | 是 | 文件类型 | 不能为空 |
+| contentType | String | 是 | MIME类型 | 不能为空 |
+| fileStatus | String | 是 | 文件状态 | 0-正常 1-删除 |
+| uploadUserId | Long | 否 | 上传用户ID | 有效的用户ID |
+| uploadUserName | String | 否 | 上传用户名 | 可为空 |
+| remark | String | 否 | 备注信息 | 最长200字符 |
+
+**响应示例**:
+
+```json
+{
+ "status": 200,
+ "msg": "SUCCESS",
+ "data": "新增成功",
+ "traceId": "trace-123456"
+}
+```
+
+**调用示例**:
+
+```bash
+curl -X POST \
+ http://localhost:18099/coder/sysFile/add \
+ -H "Content-Type: application/json" \
+ -H "Authorization: Bearer your-token-value" \
+ -d '{
+ "fileName": "document_20240705_001.pdf",
+ "originalName": "重要文档.pdf",
+ "filePath": "/upload/documents/2024/07/05/document_20240705_001.pdf",
+ "fileUrl": "http://localhost:18099/upload/documents/2024/07/05/document_20240705_001.pdf",
+ "folderName": "documents",
+ "fileSize": 2048000,
+ "fileType": "pdf",
+ "contentType": "application/pdf",
+ "fileStatus": "0",
+ "uploadUserId": 1,
+ "uploadUserName": "admin",
+ "remark": "重要文档"
+ }'
+```
+
+---
+
+### 5. 修改文件信息
+
+**接口地址**: `POST /coder/sysFile/update`
+
+**接口描述**: 修改系统文件记录信息
+
+**是否需要认证**: 是
+
+**权限要求**: `system:file:edit`
+
+**请求参数**:
+
+```json
+{
+ "fileId": 1,
+ "fileName": "document_20240705_001.pdf",
+ "originalName": "重要文档.pdf",
+ "filePath": "/upload/documents/2024/07/05/document_20240705_001.pdf",
+ "fileUrl": "http://localhost:18099/upload/documents/2024/07/05/document_20240705_001.pdf",
+ "folderName": "documents",
+ "fileSize": 2048000,
+ "fileType": "pdf",
+ "contentType": "application/pdf",
+ "fileStatus": "0",
+ "uploadUserId": 1,
+ "uploadUserName": "admin",
+ "remark": "重要文档(已更新)"
+}
+```
+
+**请求参数说明**:
+
+| 参数名 | 类型 | 必填 | 说明 | 校验规则 |
+|--------|------|------|------|----------|
+| fileId | Long | 是 | 文件ID | 必须是有效的文件ID |
+| 其他参数 | - | - | 同新增文件记录 | - |
+
+**响应示例**:
+
+```json
+{
+ "status": 200,
+ "msg": "SUCCESS",
+ "data": "修改成功",
+ "traceId": "trace-123456"
+}
+```
+
+**调用示例**:
+
+```bash
+curl -X POST \
+ http://localhost:18099/coder/sysFile/update \
+ -H "Content-Type: application/json" \
+ -H "Authorization: Bearer your-token-value" \
+ -d '{
+ "fileId": 1,
+ "fileName": "document_20240705_001.pdf",
+ "originalName": "重要文档.pdf",
+ "remark": "重要文档(已更新)"
+ }'
+```
+
+---
+
+### 6. 删除文件
+
+**接口地址**: `POST /coder/sysFile/deleteById/{id}`
+
+**接口描述**: 根据ID删除文件记录和物理文件
+
+**是否需要认证**: 是
+
+**权限要求**: `system:file:remove`
+
+**路径参数**:
+
+| 参数名 | 类型 | 必填 | 说明 |
+|--------|------|------|------|
+| id | Long | 是 | 文件ID |
+
+**响应示例**:
+
+```json
+{
+ "status": 200,
+ "msg": "SUCCESS",
+ "data": "删除成功",
+ "traceId": "trace-123456"
+}
+```
+
+**调用示例**:
+
+```bash
+curl -X POST \
+ http://localhost:18099/coder/sysFile/deleteById/1 \
+ -H "Authorization: Bearer your-token-value"
+```
+
+---
+
+### 7. 批量删除文件
+
+**接口地址**: `POST /coder/sysFile/batchDelete`
+
+**接口描述**: 批量删除文件记录和物理文件
+
+**是否需要认证**: 是
+
+**权限要求**: `system:file:remove`
+
+**请求参数**:
+
+```json
+{
+ "ids": [1, 2, 3]
+}
+```
+
+**请求参数说明**:
+
+| 参数名 | 类型 | 必填 | 说明 |
+|--------|------|------|------|
+| ids | Long[] | 是 | 文件ID数组 |
+
+**响应示例**:
+
+```json
+{
+ "status": 200,
+ "msg": "SUCCESS",
+ "data": "删除成功",
+ "traceId": "trace-123456"
+}
+```
+
+**调用示例**:
+
+```bash
+curl -X POST \
+ http://localhost:18099/coder/sysFile/batchDelete \
+ -H "Content-Type: application/json" \
+ -H "Authorization: Bearer your-token-value" \
+ -d '{
+ "ids": [1, 2, 3]
+ }'
+```
+
+---
+
+## 文件字段说明
+
+### 基础字段
+
+| 字段名 | 类型 | 说明 | 示例 |
+|--------|------|------|------|
+| fileId | Long | 文件ID | 1 |
+| fileName | String | 存储文件名 | avatar_20240705_001.jpg |
+| originalName | String | 原始文件名 | my-avatar.jpg |
+| filePath | String | 文件相对路径 | /upload/avatar/2024/07/05/avatar_20240705_001.jpg |
+| fileUrl | String | 文件访问URL | http://localhost:18099/upload/avatar/2024/07/05/avatar_20240705_001.jpg |
+
+### 分类字段
+
+| 字段名 | 类型 | 说明 | 示例 |
+|--------|------|------|------|
+| folderName | String | 文件夹名称 | avatar |
+| fileType | String | 文件扩展名 | jpg |
+| contentType | String | MIME类型 | image/jpeg |
+| fileSize | Long | 文件大小(字节) | 1024000 |
+
+### 状态字段
+
+| 字段名 | 类型 | 说明 | 示例 |
+|--------|------|------|------|
+| fileStatus | String | 文件状态 | 0-正常 1-删除 |
+| uploadUserId | Long | 上传用户ID | 1 |
+| uploadUserName | String | 上传用户名 | admin |
+| remark | String | 备注信息 | 用户头像 |
+
+---
+
+## 数据字典
+
+### 文件状态 (fileStatus)
+
+| 值 | 说明 |
+|----|------|
+| 0 | 正常 |
+| 1 | 已删除 |
+
+### 常见文件类型
+
+| 文件类型 | 扩展名 | MIME类型 | 说明 |
+|----------|--------|----------|------|
+| 图片 | jpg, jpeg, png, gif, bmp | image/* | 图片文件 |
+| 文档 | pdf, doc, docx, xls, xlsx, ppt, pptx | application/* | 办公文档 |
+| 音频 | mp3, wav, flac, aac | audio/* | 音频文件 |
+| 视频 | mp4, avi, mov, wmv | video/* | 视频文件 |
+| 压缩包 | zip, rar, 7z, tar, gz | application/* | 压缩文件 |
+| 文本 | txt, md, csv | text/* | 文本文件 |
+
+---
+
+## 文件配置
+
+### 1. 文件存储配置
+
+```yaml
+# application-dev.yml
+coder:
+ # 文件存储路径
+ filePath: /data/upload/
+
+ # 文件访问域名
+ domain: http://localhost:18099
+
+ # 文件大小限制(MB)
+ maxFileSize: 100
+
+ # 允许的文件类型
+ allowedTypes:
+ - jpg
+ - jpeg
+ - png
+ - gif
+ - pdf
+ - doc
+ - docx
+ - xls
+ - xlsx
+
+ # 禁止的文件类型
+ forbiddenTypes:
+ - exe
+ - bat
+ - sh
+ - jsp
+ - php
+```
+
+### 2. 文件夹分类
+
+```java
+// 文件夹类型枚举
+public enum FolderType {
+ AVATAR("avatar", "用户头像"),
+ DOCUMENT("document", "文档文件"),
+ IMAGE("image", "图片文件"),
+ TEMP("temp", "临时文件"),
+ EXPORT("export", "导出文件");
+
+ private final String code;
+ private final String name;
+}
+```
+
+### 3. 文件上传工具类
+
+```java
+@Component
+public class FileUploadUtil {
+
+ /**
+ * 上传文件
+ */
+ public FileUploadResult uploadFile(MultipartFile file, String folder, int maxSize) {
+ // 1. 文件校验
+ validateFile(file, maxSize);
+
+ // 2. 生成文件名
+ String fileName = generateFileName(file.getOriginalFilename());
+
+ // 3. 创建目录
+ String datePath = DateUtil.format(new Date(), "yyyy/MM/dd");
+ String dirPath = filePath + folder + "/" + datePath + "/";
+ FileUtil.createDirs(dirPath);
+
+ // 4. 保存文件
+ String filePath = dirPath + fileName;
+ file.transferTo(new File(filePath));
+
+ // 5. 生成访问URL
+ String fileUrl = domain + "/upload/" + folder + "/" + datePath + "/" + fileName;
+
+ // 6. 返回结果
+ return FileUploadResult.builder()
+ .fileName(fileName)
+ .originalName(file.getOriginalFilename())
+ .filePath(filePath)
+ .fileUrl(fileUrl)
+ .fileSize(file.getSize())
+ .fileType(FileUtil.getExtension(fileName))
+ .uploadTime(new Date())
+ .build();
+ }
+
+ /**
+ * 文件校验
+ */
+ private void validateFile(MultipartFile file, int maxSize) {
+ if (file.isEmpty()) {
+ throw new BusinessException("文件不能为空");
+ }
+
+ if (file.getSize() > maxSize * 1024 * 1024) {
+ throw new BusinessException("文件大小不能超过" + maxSize + "MB");
+ }
+
+ String extension = FileUtil.getExtension(file.getOriginalFilename());
+ if (!allowedTypes.contains(extension.toLowerCase())) {
+ throw new BusinessException("不支持的文件类型:" + extension);
+ }
+
+ if (forbiddenTypes.contains(extension.toLowerCase())) {
+ throw new BusinessException("禁止上传的文件类型:" + extension);
+ }
+ }
+
+ /**
+ * 生成文件名
+ */
+ private String generateFileName(String originalName) {
+ String extension = FileUtil.getExtension(originalName);
+ String baseName = FileUtil.getBaseName(originalName);
+ String timestamp = DateUtil.format(new Date(), "yyyyMMdd_HHmmss");
+ String random = RandomUtil.randomString(3);
+ return baseName + "_" + timestamp + "_" + random + "." + extension;
+ }
+}
+```
+
+---
+
+## 错误码说明
+
+| 错误码 | 错误信息 | 说明 |
+|--------|----------|------|
+| 400 | 文件不能为空 | 上传文件为空 |
+| 400 | 文件大小不能超过{size}MB | 文件大小超过限制 |
+| 400 | 不支持的文件类型 | 文件类型不在允许列表中 |
+| 400 | 禁止上传的文件类型 | 文件类型在禁止列表中 |
+| 400 | 文件名不能为空 | 文件名为空 |
+| 400 | 文件路径不能为空 | 文件路径为空 |
+| 400 | 文件不存在 | 文件ID不存在 |
+| 400 | 文件已被删除 | 文件状态为已删除 |
+| 401 | 当前会话未登录 | 未登录或Token无效 |
+| 403 | 权限不足 | 没有相应的操作权限 |
+| 500 | 文件上传失败 | 文件保存到磁盘失败 |
+| 500 | 文件删除失败 | 物理文件删除失败 |
+| 500 | 磁盘空间不足 | 服务器磁盘空间不足 |
+
+---
+
+## 安全特性
+
+### 1. 文件类型验证
+
+- **扩展名校验**: 验证文件扩展名
+- **MIME类型校验**: 验证文件MIME类型
+- **文件内容校验**: 验证文件真实类型
+- **黑名单过滤**: 禁止上传危险文件类型
+
+### 2. 文件大小限制
+
+- **单文件大小限制**: 限制单个文件大小
+- **总文件大小限制**: 限制用户总文件大小
+- **磁盘空间检查**: 检查服务器磁盘空间
+
+### 3. 访问控制
+
+- **权限验证**: 验证用户上传和访问权限
+- **路径防护**: 防止路径遍历攻击
+- **防盗链**: 防止文件被盗链
+
+### 4. 病毒扫描
+
+- **文件扫描**: 上传文件病毒扫描
+- **隔离机制**: 可疑文件隔离处理
+- **定期扫描**: 定期扫描存储文件
+
+---
+
+## 性能优化
+
+### 1. 文件存储
+
+- **分目录存储**: 按日期和类型分目录存储
+- **CDN加速**: 使用CDN加速文件访问
+- **压缩存储**: 自动压缩图片文件
+- **缓存策略**: 设置合适的缓存策略
+
+### 2. 上传优化
+
+- **分片上传**: 大文件分片上传
+- **断点续传**: 支持断点续传功能
+- **并发上传**: 支持多文件并发上传
+- **进度显示**: 实时显示上传进度
+
+### 3. 存储优化
+
+- **重复文件检测**: 检测并避免重复文件
+- **文件压缩**: 自动压缩文件
+- **定期清理**: 清理临时文件和无效文件
+- **存储监控**: 监控存储空间使用情况
+
+---
+
+## 使用建议
+
+### 1. 文件命名规范
+
+- **唯一性**: 确保文件名唯一
+- **时间戳**: 包含时间戳信息
+- **随机性**: 添加随机字符
+- **可读性**: 保持一定的可读性
+
+### 2. 文件分类管理
+
+- **按类型分类**: 不同类型文件存储在不同目录
+- **按用户分类**: 不同用户文件分开存储
+- **按时间分类**: 按年月日创建目录结构
+- **按业务分类**: 按业务模块分类存储
+
+### 3. 安全防护
+
+- **输入验证**: 严格验证上传文件
+- **权限控制**: 细粒度的权限控制
+- **日志记录**: 记录所有文件操作
+- **备份策略**: 重要文件定期备份
+
+### 4. 监控告警
+
+- **存储监控**: 监控存储空间使用
+- **性能监控**: 监控上传下载性能
+- **安全监控**: 监控异常文件操作
+- **容量告警**: 存储空间不足告警
+
+---
+
+## 注意事项
+
+1. **文件安全**: 严格验证上传文件类型和内容
+2. **存储路径**: 确保文件存储路径安全
+3. **权限控制**: 合理设置文件访问权限
+4. **磁盘空间**: 定期清理无效文件,避免磁盘满
+5. **备份策略**: 重要文件需要备份
+6. **访问控制**: 防止文件被恶意访问
+7. **性能考虑**: 大文件上传时注意性能影响
+8. **并发控制**: 处理并发上传时的文件冲突
+9. **错误处理**: 完善的错误处理和回滚机制
+10. **日志审计**: 记录所有文件操作日志
\ No newline at end of file
diff --git a/api/system/登录日志API.md b/api/system/登录日志API.md
new file mode 100644
index 0000000..8f5cc29
--- /dev/null
+++ b/api/system/登录日志API.md
@@ -0,0 +1,1017 @@
+# 登录日志API
+
+## 概述
+
+登录日志模块用于记录和管理系统用户的登录行为,包括登录成功、登录失败、退出登录等操作的详细记录。提供日志查询、统计分析和安全监控功能,是系统安全审计的重要组成部分。
+
+## 权限说明
+
+登录日志接口需要相应的权限才能访问:
+
+| 操作 | 权限码 | 说明 |
+|------|--------|------|
+| 查询登录日志 | `system:loginlog:list` | 查看登录日志权限 |
+| 删除登录日志 | `system:loginlog:remove` | 删除登录日志权限 |
+| 导出登录日志 | `system:loginlog:export` | 导出登录日志权限 |
+
+## 接口列表
+
+### 1. 分页查询登录日志
+
+**接口地址**: `GET /coder/sysLoginLog/listPage`
+
+**接口描述**: 分页查询系统登录日志列表
+
+**是否需要认证**: 是
+
+**权限要求**: `system:loginlog:list`
+
+**请求头**:
+```
+Authorization: Bearer your-token-value
+```
+
+**请求参数**:
+
+| 参数名 | 类型 | 必填 | 说明 | 示例 |
+|--------|------|------|------|------|
+| pageNo | Integer | 否 | 页码 | 1 |
+| pageSize | Integer | 否 | 每页大小 | 10 |
+| loginName | String | 否 | 登录账号 | admin |
+| loginStatus | String | 否 | 登录状态 | 0 |
+| clientType | String | 否 | 客户端类型 | WEB |
+| loginIp | String | 否 | 登录IP | 127.0.0.1 |
+| loginAddress | String | 否 | 登录地址 | 本地登录 |
+| browser | String | 否 | 浏览器类型 | Chrome |
+| os | String | 否 | 操作系统 | Windows 10 |
+| beginTime | String | 否 | 开始时间 | 2024-01-01 |
+| endTime | String | 否 | 结束时间 | 2024-12-31 |
+
+**响应示例**:
+
+```json
+{
+ "status": 200,
+ "msg": "SUCCESS",
+ "data": {
+ "records": [
+ {
+ "infoId": 1,
+ "loginName": "admin",
+ "userName": "管理员",
+ "userId": 1,
+ "loginStatus": "0",
+ "clientType": "WEB",
+ "deviceName": "Windows PC",
+ "loginIp": "127.0.0.1",
+ "loginAddress": "本地登录",
+ "browser": "Chrome 120.0.0.0",
+ "os": "Windows 10",
+ "userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
+ "loginTime": "2024-07-05 10:00:00",
+ "logoutTime": "2024-07-05 11:00:00",
+ "sessionDuration": 3600,
+ "failureReason": "",
+ "remark": "登录成功",
+ "createBy": "system",
+ "createTime": "2024-07-05 10:00:00",
+ "updateBy": "system",
+ "updateTime": "2024-07-05 11:00:00"
+ }
+ ],
+ "total": 1,
+ "size": 10,
+ "current": 1,
+ "pages": 1
+ },
+ "traceId": "trace-123456"
+}
+```
+
+**调用示例**:
+
+```bash
+curl -X GET \
+ "http://localhost:18099/coder/sysLoginLog/listPage?pageNo=1&pageSize=10&loginName=admin&loginStatus=0" \
+ -H "Authorization: Bearer your-token-value"
+```
+
+---
+
+### 2. 查询所有登录日志
+
+**接口地址**: `GET /coder/sysLoginLog/list`
+
+**接口描述**: 查询所有系统登录日志(不分页)
+
+**是否需要认证**: 是
+
+**权限要求**: `system:loginlog:list`
+
+**请求参数**: 同分页查询(除pageNo、pageSize外)
+
+**响应示例**:
+
+```json
+{
+ "status": 200,
+ "msg": "SUCCESS",
+ "data": [
+ {
+ "infoId": 1,
+ "loginName": "admin",
+ "userName": "管理员",
+ "userId": 1,
+ "loginStatus": "0",
+ "clientType": "WEB",
+ "deviceName": "Windows PC",
+ "loginIp": "127.0.0.1",
+ "loginAddress": "本地登录",
+ "browser": "Chrome 120.0.0.0",
+ "os": "Windows 10",
+ "userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
+ "loginTime": "2024-07-05 10:00:00",
+ "logoutTime": "2024-07-05 11:00:00",
+ "sessionDuration": 3600,
+ "failureReason": "",
+ "remark": "登录成功",
+ "createBy": "system",
+ "createTime": "2024-07-05 10:00:00",
+ "updateBy": "system",
+ "updateTime": "2024-07-05 11:00:00"
+ }
+ ],
+ "traceId": "trace-123456"
+}
+```
+
+**调用示例**:
+
+```bash
+curl -X GET \
+ "http://localhost:18099/coder/sysLoginLog/list?loginStatus=1&beginTime=2024-07-01" \
+ -H "Authorization: Bearer your-token-value"
+```
+
+---
+
+### 3. 根据ID查询登录日志
+
+**接口地址**: `GET /coder/sysLoginLog/getById/{id}`
+
+**接口描述**: 根据日志ID查询登录日志详细信息
+
+**是否需要认证**: 是
+
+**权限要求**: `system:loginlog:list`
+
+**路径参数**:
+
+| 参数名 | 类型 | 必填 | 说明 |
+|--------|------|------|------|
+| id | Long | 是 | 日志ID |
+
+**响应示例**:
+
+```json
+{
+ "status": 200,
+ "msg": "SUCCESS",
+ "data": {
+ "infoId": 1,
+ "loginName": "admin",
+ "userName": "管理员",
+ "userId": 1,
+ "loginStatus": "0",
+ "clientType": "WEB",
+ "deviceName": "Windows PC",
+ "loginIp": "127.0.0.1",
+ "loginAddress": "本地登录",
+ "browser": "Chrome 120.0.0.0",
+ "os": "Windows 10",
+ "userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
+ "loginTime": "2024-07-05 10:00:00",
+ "logoutTime": "2024-07-05 11:00:00",
+ "sessionDuration": 3600,
+ "failureReason": "",
+ "remark": "登录成功",
+ "createBy": "system",
+ "createTime": "2024-07-05 10:00:00",
+ "updateBy": "system",
+ "updateTime": "2024-07-05 11:00:00"
+ },
+ "traceId": "trace-123456"
+}
+```
+
+**调用示例**:
+
+```bash
+curl -X GET \
+ http://localhost:18099/coder/sysLoginLog/getById/1 \
+ -H "Authorization: Bearer your-token-value"
+```
+
+---
+
+### 4. 新增登录日志
+
+**接口地址**: `POST /coder/sysLoginLog/add`
+
+**接口描述**: 新增系统登录日志记录
+
+**是否需要认证**: 是
+
+**权限要求**: `system:loginlog:add`
+
+**请求参数**:
+
+```json
+{
+ "loginName": "admin",
+ "userName": "管理员",
+ "userId": 1,
+ "loginStatus": "0",
+ "clientType": "WEB",
+ "deviceName": "Windows PC",
+ "loginIp": "127.0.0.1",
+ "loginAddress": "本地登录",
+ "browser": "Chrome 120.0.0.0",
+ "os": "Windows 10",
+ "userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
+ "loginTime": "2024-07-05 10:00:00",
+ "failureReason": "",
+ "remark": "登录成功"
+}
+```
+
+**请求参数说明**:
+
+| 参数名 | 类型 | 必填 | 说明 | 校验规则 |
+|--------|------|------|------|----------|
+| loginName | String | 是 | 登录账号 | 不能为空 |
+| userName | String | 否 | 用户姓名 | 可为空 |
+| userId | Long | 否 | 用户ID | 有效的用户ID |
+| loginStatus | String | 是 | 登录状态 | 0-成功 1-失败 |
+| clientType | String | 是 | 客户端类型 | WEB, MOBILE, API |
+| deviceName | String | 否 | 设备名称 | 可为空 |
+| loginIp | String | 是 | 登录IP | 有效的IP地址 |
+| loginAddress | String | 否 | 登录地址 | 可为空 |
+| browser | String | 否 | 浏览器信息 | 可为空 |
+| os | String | 否 | 操作系统 | 可为空 |
+| userAgent | String | 否 | 用户代理 | 可为空 |
+| loginTime | String | 是 | 登录时间 | 时间格式 |
+| failureReason | String | 否 | 失败原因 | 登录失败时必填 |
+| remark | String | 否 | 备注信息 | 最长500字符 |
+
+**响应示例**:
+
+```json
+{
+ "status": 200,
+ "msg": "SUCCESS",
+ "data": "新增成功",
+ "traceId": "trace-123456"
+}
+```
+
+**调用示例**:
+
+```bash
+curl -X POST \
+ http://localhost:18099/coder/sysLoginLog/add \
+ -H "Content-Type: application/json" \
+ -H "Authorization: Bearer your-token-value" \
+ -d '{
+ "loginName": "admin",
+ "userName": "管理员",
+ "userId": 1,
+ "loginStatus": "0",
+ "clientType": "WEB",
+ "loginIp": "127.0.0.1",
+ "loginTime": "2024-07-05 10:00:00",
+ "remark": "登录成功"
+ }'
+```
+
+---
+
+### 5. 修改登录日志
+
+**接口地址**: `POST /coder/sysLoginLog/update`
+
+**接口描述**: 修改系统登录日志信息(通常用于更新退出时间)
+
+**是否需要认证**: 是
+
+**权限要求**: `system:loginlog:edit`
+
+**请求参数**:
+
+```json
+{
+ "infoId": 1,
+ "loginName": "admin",
+ "userName": "管理员",
+ "userId": 1,
+ "loginStatus": "0",
+ "clientType": "WEB",
+ "deviceName": "Windows PC",
+ "loginIp": "127.0.0.1",
+ "loginAddress": "本地登录",
+ "browser": "Chrome 120.0.0.0",
+ "os": "Windows 10",
+ "userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
+ "loginTime": "2024-07-05 10:00:00",
+ "logoutTime": "2024-07-05 11:00:00",
+ "sessionDuration": 3600,
+ "failureReason": "",
+ "remark": "正常退出"
+}
+```
+
+**请求参数说明**:
+
+| 参数名 | 类型 | 必填 | 说明 | 校验规则 |
+|--------|------|------|------|----------|
+| infoId | Long | 是 | 日志ID | 必须是有效的日志ID |
+| logoutTime | String | 否 | 退出时间 | 时间格式 |
+| sessionDuration | Integer | 否 | 会话时长(秒) | 大于等于0 |
+| 其他参数 | - | - | 同新增日志 | - |
+
+**响应示例**:
+
+```json
+{
+ "status": 200,
+ "msg": "SUCCESS",
+ "data": "修改成功",
+ "traceId": "trace-123456"
+}
+```
+
+**调用示例**:
+
+```bash
+curl -X POST \
+ http://localhost:18099/coder/sysLoginLog/update \
+ -H "Content-Type: application/json" \
+ -H "Authorization: Bearer your-token-value" \
+ -d '{
+ "infoId": 1,
+ "logoutTime": "2024-07-05 11:00:00",
+ "sessionDuration": 3600,
+ "remark": "正常退出"
+ }'
+```
+
+---
+
+### 6. 删除登录日志
+
+**接口地址**: `POST /coder/sysLoginLog/deleteById/{id}`
+
+**接口描述**: 根据ID删除登录日志
+
+**是否需要认证**: 是
+
+**权限要求**: `system:loginlog:remove`
+
+**路径参数**:
+
+| 参数名 | 类型 | 必填 | 说明 |
+|--------|------|------|------|
+| id | Long | 是 | 日志ID |
+
+**响应示例**:
+
+```json
+{
+ "status": 200,
+ "msg": "SUCCESS",
+ "data": "删除成功",
+ "traceId": "trace-123456"
+}
+```
+
+**调用示例**:
+
+```bash
+curl -X POST \
+ http://localhost:18099/coder/sysLoginLog/deleteById/1 \
+ -H "Authorization: Bearer your-token-value"
+```
+
+---
+
+### 7. 批量删除登录日志
+
+**接口地址**: `POST /coder/sysLoginLog/batchDelete`
+
+**接口描述**: 批量删除登录日志
+
+**是否需要认证**: 是
+
+**权限要求**: `system:loginlog:remove`
+
+**请求参数**:
+
+```json
+{
+ "ids": [1, 2, 3]
+}
+```
+
+**请求参数说明**:
+
+| 参数名 | 类型 | 必填 | 说明 |
+|--------|------|------|------|
+| ids | Long[] | 是 | 日志ID数组 |
+
+**响应示例**:
+
+```json
+{
+ "status": 200,
+ "msg": "SUCCESS",
+ "data": "删除成功",
+ "traceId": "trace-123456"
+}
+```
+
+**调用示例**:
+
+```bash
+curl -X POST \
+ http://localhost:18099/coder/sysLoginLog/batchDelete \
+ -H "Content-Type: application/json" \
+ -H "Authorization: Bearer your-token-value" \
+ -d '{
+ "ids": [1, 2, 3]
+ }'
+```
+
+---
+
+## 登录日志字段说明
+
+### 基础字段
+
+| 字段名 | 类型 | 说明 | 示例 |
+|--------|------|------|------|
+| infoId | Long | 日志ID | 1 |
+| loginName | String | 登录账号 | admin |
+| userName | String | 用户姓名 | 管理员 |
+| userId | Long | 用户ID | 1 |
+
+### 状态字段
+
+| 字段名 | 类型 | 说明 | 示例 |
+|--------|------|------|------|
+| loginStatus | String | 登录状态 | 0-成功 1-失败 |
+| clientType | String | 客户端类型 | WEB, MOBILE, API |
+| deviceName | String | 设备名称 | Windows PC |
+
+### 网络字段
+
+| 字段名 | 类型 | 说明 | 示例 |
+|--------|------|------|------|
+| loginIp | String | 登录IP地址 | 127.0.0.1 |
+| loginAddress | String | 登录地理位置 | 本地登录 |
+| userAgent | String | 用户代理字符串 | Mozilla/5.0... |
+
+### 环境字段
+
+| 字段名 | 类型 | 说明 | 示例 |
+|--------|------|------|------|
+| browser | String | 浏览器信息 | Chrome 120.0.0.0 |
+| os | String | 操作系统 | Windows 10 |
+
+### 时间字段
+
+| 字段名 | 类型 | 说明 | 示例 |
+|--------|------|------|------|
+| loginTime | String | 登录时间 | 2024-07-05 10:00:00 |
+| logoutTime | String | 退出时间 | 2024-07-05 11:00:00 |
+| sessionDuration | Integer | 会话时长(秒) | 3600 |
+
+### 其他字段
+
+| 字段名 | 类型 | 说明 | 示例 |
+|--------|------|------|------|
+| failureReason | String | 失败原因 | 密码错误 |
+| remark | String | 备注信息 | 登录成功 |
+
+---
+
+## 数据字典
+
+### 登录状态 (loginStatus)
+
+| 值 | 说明 |
+|----|------|
+| 0 | 登录成功 |
+| 1 | 登录失败 |
+
+### 客户端类型 (clientType)
+
+| 值 | 说明 |
+|----|------|
+| WEB | 网页端 |
+| MOBILE | 移动端 |
+| API | 接口调用 |
+| DESKTOP | 桌面应用 |
+| WECHAT | 微信小程序 |
+
+### 常见失败原因
+
+| 失败原因 | 说明 |
+|----------|------|
+| 用户不存在 | 登录账号不存在 |
+| 密码错误 | 登录密码不正确 |
+| 验证码错误 | 验证码输入错误 |
+| 账号被禁用 | 用户账号被禁用 |
+| 账号被锁定 | 用户账号被锁定 |
+| IP被限制 | 登录IP被限制 |
+| 设备被限制 | 登录设备被限制 |
+| 会话过期 | 用户会话已过期 |
+
+---
+
+## 日志记录机制
+
+### 1. 自动记录
+
+```java
+@Component
+@Slf4j
+public class LoginLogService {
+
+ /**
+ * 记录登录成功日志
+ */
+ public void recordLoginSuccess(String loginName, HttpServletRequest request) {
+ try {
+ SysLoginLog loginLog = new SysLoginLog();
+
+ // 基础信息
+ loginLog.setLoginName(loginName);
+ loginLog.setUserId(getCurrentUserId(loginName));
+ loginLog.setUserName(getCurrentUserName(loginName));
+ loginLog.setLoginStatus("0");
+ loginLog.setLoginTime(LocalDateTime.now());
+
+ // 网络信息
+ loginLog.setLoginIp(getClientIP(request));
+ loginLog.setLoginAddress(getAddressByIP(loginLog.getLoginIp()));
+
+ // 客户端信息
+ loginLog.setClientType(getClientType(request));
+ loginLog.setUserAgent(request.getHeader("User-Agent"));
+ loginLog.setBrowser(getBrowserInfo(request));
+ loginLog.setOs(getOSInfo(request));
+ loginLog.setDeviceName(getDeviceName(request));
+
+ // 其他信息
+ loginLog.setRemark("登录成功");
+ loginLog.setCreateBy("system");
+ loginLog.setCreateTime(LocalDateTime.now());
+
+ // 保存日志
+ sysLoginLogMapper.insert(loginLog);
+
+ } catch (Exception e) {
+ log.error("记录登录成功日志失败", e);
+ }
+ }
+
+ /**
+ * 记录登录失败日志
+ */
+ public void recordLoginFailure(String loginName, String failureReason, HttpServletRequest request) {
+ try {
+ SysLoginLog loginLog = new SysLoginLog();
+
+ // 基础信息
+ loginLog.setLoginName(loginName);
+ loginLog.setLoginStatus("1");
+ loginLog.setLoginTime(LocalDateTime.now());
+ loginLog.setFailureReason(failureReason);
+
+ // 网络信息
+ loginLog.setLoginIp(getClientIP(request));
+ loginLog.setLoginAddress(getAddressByIP(loginLog.getLoginIp()));
+
+ // 客户端信息
+ loginLog.setClientType(getClientType(request));
+ loginLog.setUserAgent(request.getHeader("User-Agent"));
+ loginLog.setBrowser(getBrowserInfo(request));
+ loginLog.setOs(getOSInfo(request));
+ loginLog.setDeviceName(getDeviceName(request));
+
+ // 其他信息
+ loginLog.setRemark("登录失败:" + failureReason);
+ loginLog.setCreateBy("system");
+ loginLog.setCreateTime(LocalDateTime.now());
+
+ // 保存日志
+ sysLoginLogMapper.insert(loginLog);
+
+ } catch (Exception e) {
+ log.error("记录登录失败日志失败", e);
+ }
+ }
+
+ /**
+ * 记录退出登录日志
+ */
+ public void recordLogout(String loginName, LocalDateTime loginTime) {
+ try {
+ // 查找对应的登录日志
+ SysLoginLog loginLog = sysLoginLogMapper.selectOne(
+ new LambdaQueryWrapper()
+ .eq(SysLoginLog::getLoginName, loginName)
+ .eq(SysLoginLog::getLoginTime, loginTime)
+ .eq(SysLoginLog::getLoginStatus, "0")
+ .isNull(SysLoginLog::getLogoutTime)
+ .last("ORDER BY create_time DESC LIMIT 1")
+ );
+
+ if (loginLog != null) {
+ LocalDateTime logoutTime = LocalDateTime.now();
+ long sessionDuration = Duration.between(loginLog.getLoginTime(), logoutTime).getSeconds();
+
+ loginLog.setLogoutTime(logoutTime);
+ loginLog.setSessionDuration((int) sessionDuration);
+ loginLog.setRemark("正常退出");
+ loginLog.setUpdateBy("system");
+ loginLog.setUpdateTime(LocalDateTime.now());
+
+ sysLoginLogMapper.updateById(loginLog);
+ }
+
+ } catch (Exception e) {
+ log.error("记录退出登录日志失败", e);
+ }
+ }
+
+ /**
+ * 获取客户端IP
+ */
+ private String getClientIP(HttpServletRequest request) {
+ String ip = request.getHeader("X-Forwarded-For");
+ if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
+ ip = request.getHeader("Proxy-Client-IP");
+ }
+ if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
+ ip = request.getHeader("WL-Proxy-Client-IP");
+ }
+ if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
+ ip = request.getHeader("HTTP_CLIENT_IP");
+ }
+ if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
+ ip = request.getHeader("HTTP_X_FORWARDED_FOR");
+ }
+ if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
+ ip = request.getRemoteAddr();
+ }
+ return ip;
+ }
+
+ /**
+ * 解析浏览器信息
+ */
+ private String getBrowserInfo(HttpServletRequest request) {
+ String userAgent = request.getHeader("User-Agent");
+ if (userAgent == null) {
+ return "Unknown";
+ }
+
+ if (userAgent.contains("Chrome")) {
+ return "Chrome";
+ } else if (userAgent.contains("Firefox")) {
+ return "Firefox";
+ } else if (userAgent.contains("Safari")) {
+ return "Safari";
+ } else if (userAgent.contains("Edge")) {
+ return "Edge";
+ } else if (userAgent.contains("IE")) {
+ return "Internet Explorer";
+ } else {
+ return "Other";
+ }
+ }
+
+ /**
+ * 解析操作系统信息
+ */
+ private String getOSInfo(HttpServletRequest request) {
+ String userAgent = request.getHeader("User-Agent");
+ if (userAgent == null) {
+ return "Unknown";
+ }
+
+ if (userAgent.contains("Windows NT 10.0")) {
+ return "Windows 10";
+ } else if (userAgent.contains("Windows NT 6.3")) {
+ return "Windows 8.1";
+ } else if (userAgent.contains("Windows NT 6.2")) {
+ return "Windows 8";
+ } else if (userAgent.contains("Windows NT 6.1")) {
+ return "Windows 7";
+ } else if (userAgent.contains("Mac OS X")) {
+ return "Mac OS";
+ } else if (userAgent.contains("Linux")) {
+ return "Linux";
+ } else if (userAgent.contains("Android")) {
+ return "Android";
+ } else if (userAgent.contains("iPhone") || userAgent.contains("iPad")) {
+ return "iOS";
+ } else {
+ return "Other";
+ }
+ }
+}
+```
+
+### 2. 异步处理
+
+```java
+@Service
+public class AsyncLoginLogService {
+
+ @Async("taskExecutor")
+ public void recordLoginLogAsync(SysLoginLog loginLog) {
+ try {
+ // 异步记录登录日志
+ sysLoginLogMapper.insert(loginLog);
+
+ // 更新用户登录信息
+ updateUserLoginInfo(loginLog);
+
+ // 检查异常登录
+ checkAbnormalLogin(loginLog);
+
+ } catch (Exception e) {
+ log.error("异步记录登录日志失败", e);
+ }
+ }
+
+ /**
+ * 检查异常登录
+ */
+ private void checkAbnormalLogin(SysLoginLog loginLog) {
+ // 检查IP异常
+ if (isAbnormalIP(loginLog.getLoginIp(), loginLog.getLoginName())) {
+ sendSecurityAlert("检测到异常IP登录", loginLog);
+ }
+
+ // 检查设备异常
+ if (isAbnormalDevice(loginLog.getUserAgent(), loginLog.getLoginName())) {
+ sendSecurityAlert("检测到异常设备登录", loginLog);
+ }
+
+ // 检查时间异常
+ if (isAbnormalTime(loginLog.getLoginTime(), loginLog.getLoginName())) {
+ sendSecurityAlert("检测到异常时间登录", loginLog);
+ }
+ }
+}
+```
+
+---
+
+## 统计分析功能
+
+### 1. 登录统计
+
+```java
+/**
+ * 登录统计服务
+ */
+@Service
+public class LoginStatisticsService {
+
+ /**
+ * 获取登录成功率统计
+ */
+ public LoginSuccessRateVO getLoginSuccessRate(String beginTime, String endTime) {
+ // 查询总登录次数
+ long totalCount = sysLoginLogMapper.selectCount(
+ new LambdaQueryWrapper()
+ .between(SysLoginLog::getLoginTime, beginTime, endTime)
+ );
+
+ // 查询成功登录次数
+ long successCount = sysLoginLogMapper.selectCount(
+ new LambdaQueryWrapper()
+ .eq(SysLoginLog::getLoginStatus, "0")
+ .between(SysLoginLog::getLoginTime, beginTime, endTime)
+ );
+
+ // 计算成功率
+ double successRate = totalCount > 0 ? (double) successCount / totalCount * 100 : 0;
+
+ return LoginSuccessRateVO.builder()
+ .totalCount(totalCount)
+ .successCount(successCount)
+ .failureCount(totalCount - successCount)
+ .successRate(successRate)
+ .build();
+ }
+
+ /**
+ * 获取每日登录统计
+ */
+ public List getDailyLoginStat(String beginTime, String endTime) {
+ return sysLoginLogMapper.selectDailyLoginStat(beginTime, endTime);
+ }
+
+ /**
+ * 获取客户端类型统计
+ */
+ public List getClientTypeStat(String beginTime, String endTime) {
+ return sysLoginLogMapper.selectClientTypeStat(beginTime, endTime);
+ }
+}
+```
+
+### 2. 安全监控
+
+```java
+/**
+ * 安全监控服务
+ */
+@Service
+public class SecurityMonitorService {
+
+ /**
+ * 检测暴力破解
+ */
+ public void detectBruteForce() {
+ // 查询5分钟内失败次数超过5次的IP
+ List suspiciousIPs = sysLoginLogMapper.selectSuspiciousIPs();
+
+ for (String ip : suspiciousIPs) {
+ // 加入黑名单
+ addToBlacklist(ip);
+
+ // 发送告警
+ sendSecurityAlert("检测到暴力破解攻击", ip);
+ }
+ }
+
+ /**
+ * 检测异地登录
+ */
+ public void detectRemoteLogin() {
+ // 查询用户最近登录地址
+ List recentLogins = sysLoginLogMapper.selectRecentLogins();
+
+ for (SysLoginLog loginLog : recentLogins) {
+ String lastLoginAddress = getLastLoginAddress(loginLog.getLoginName());
+
+ if (!loginLog.getLoginAddress().equals(lastLoginAddress)) {
+ // 发送异地登录通知
+ sendRemoteLoginNotification(loginLog);
+ }
+ }
+ }
+}
+```
+
+---
+
+## 错误码说明
+
+| 错误码 | 错误信息 | 说明 |
+|--------|----------|------|
+| 400 | 登录账号不能为空 | 登录账号为空 |
+| 400 | 登录状态不能为空 | 登录状态为空 |
+| 400 | 登录时间不能为空 | 登录时间为空 |
+| 400 | 登录IP不能为空 | 登录IP为空 |
+| 400 | 日志不存在 | 日志ID不存在 |
+| 400 | 时间格式错误 | 时间格式不正确 |
+| 401 | 当前会话未登录 | 未登录或Token无效 |
+| 403 | 权限不足 | 没有相应的操作权限 |
+| 500 | 日志记录失败 | 日志保存失败 |
+| 500 | 系统异常 | 服务器内部错误 |
+
+---
+
+## 日志清理策略
+
+### 1. 定时清理
+
+```java
+@Component
+public class LoginLogCleanupTask {
+
+ /**
+ * 每天凌晨2点清理30天前的登录日志
+ */
+ @Scheduled(cron = "0 0 2 * * ?")
+ public void cleanupOldLogs() {
+ try {
+ LocalDateTime cutoffTime = LocalDateTime.now().minusDays(30);
+
+ int deletedCount = sysLoginLogMapper.delete(
+ new LambdaQueryWrapper()
+ .lt(SysLoginLog::getCreateTime, cutoffTime)
+ );
+
+ log.info("清理登录日志完成,删除{}条记录", deletedCount);
+
+ } catch (Exception e) {
+ log.error("清理登录日志失败", e);
+ }
+ }
+
+ /**
+ * 归档登录日志
+ */
+ @Scheduled(cron = "0 0 1 1 * ?") // 每月1号凌晨1点执行
+ public void archiveLogs() {
+ try {
+ LocalDateTime lastMonth = LocalDateTime.now().minusMonths(1);
+
+ // 归档上个月的日志到历史表
+ sysLoginLogMapper.archiveLogsToHistory(lastMonth);
+
+ log.info("归档登录日志完成");
+
+ } catch (Exception e) {
+ log.error("归档登录日志失败", e);
+ }
+ }
+}
+```
+
+### 2. 日志配置
+
+```yaml
+# application.yml
+logging:
+ login-log:
+ # 是否启用登录日志
+ enabled: true
+ # 日志保留天数
+ retention-days: 90
+ # 是否记录成功登录
+ log-success: true
+ # 是否记录失败登录
+ log-failure: true
+ # 是否异步记录
+ async: true
+ # 是否启用IP地址解析
+ resolve-address: true
+ # 是否启用安全监控
+ security-monitor: true
+```
+
+---
+
+## 使用建议
+
+### 1. 日志管理
+
+- **合理保留期**: 根据业务需要设置日志保留期
+- **定期清理**: 定期清理过期日志释放存储空间
+- **分表存储**: 大量日志可考虑按月分表存储
+- **归档备份**: 重要日志定期归档备份
+
+### 2. 安全监控
+
+- **实时监控**: 实时监控异常登录行为
+- **告警机制**: 建立完善的安全告警机制
+- **自动响应**: 对可疑行为自动采取防护措施
+- **定期分析**: 定期分析登录日志发现安全趋势
+
+### 3. 性能优化
+
+- **异步记录**: 使用异步方式记录日志避免影响登录性能
+- **批量处理**: 批量处理日志数据提高效率
+- **索引优化**: 为查询字段建立合适索引
+- **分页查询**: 大数据量查询使用分页
+
+### 4. 隐私保护
+
+- **敏感信息**: 不记录密码等敏感信息
+- **数据脱敏**: 对部分信息进行脱敏处理
+- **访问控制**: 严格控制日志访问权限
+- **合规要求**: 遵守相关数据保护法规
+
+---
+
+## 注意事项
+
+1. **日志完整性**: 确保登录日志记录的完整性和准确性
+2. **性能影响**: 日志记录不应影响用户登录体验
+3. **存储空间**: 注意日志存储空间的管理和清理
+4. **安全防护**: 防止日志被恶意篡改或删除
+5. **隐私保护**: 不记录用户密码等敏感信息
+6. **异常处理**: 日志记录失败不应影响正常业务
+7. **监控告警**: 建立异常登录的监控告警机制
+8. **数据备份**: 重要日志数据需要备份
+9. **合规要求**: 遵守相关法律法规对日志的要求
+10. **访问审计**: 对日志访问行为也要进行审计
\ No newline at end of file
diff --git a/api/user/用户管理API.md b/api/user/用户管理API.md
new file mode 100644
index 0000000..efd4fa5
--- /dev/null
+++ b/api/user/用户管理API.md
@@ -0,0 +1,888 @@
+# 用户管理API
+
+## 概述
+
+用户管理模块提供系统用户的增删改查功能,包括用户信息管理、状态控制、密码管理、角色分配等核心功能。
+
+## 权限说明
+
+用户管理接口需要相应的权限才能访问:
+
+| 操作 | 权限码 | 说明 |
+|------|--------|------|
+| 查询用户列表 | `system:user:list` | 查看用户列表权限 |
+| 新增用户 | `system:user:add` | 新增用户权限 |
+| 修改用户 | `system:user:edit` | 修改用户信息权限 |
+| 删除用户 | `system:user:remove` | 删除用户权限 |
+| 重置密码 | `system:user:resetPwd` | 重置用户密码权限 |
+| 修改状态 | `system:user:status` | 修改用户状态权限 |
+| 分配角色 | `system:user:role` | 分配用户角色权限 |
+| 导入用户 | `system:user:import` | 导入用户数据权限 |
+| 导出用户 | `system:user:export` | 导出用户数据权限 |
+
+## 接口列表
+
+### 1. 分页查询用户列表
+
+**接口地址**: `GET /coder/sysLoginUser/listPage`
+
+**接口描述**: 分页查询系统用户列表
+
+**是否需要认证**: 是
+
+**权限要求**: `system:user:list`
+
+**请求头**:
+```
+Authorization: your-token-value
+```
+
+**请求参数**:
+
+| 参数名 | 类型 | 必填 | 说明 | 示例 |
+|--------|------|------|------|------|
+| pageNo | Integer | 否 | 页码 | 1 |
+| pageSize | Integer | 否 | 每页大小 | 10 |
+| loginName | String | 否 | 登录账号 | admin |
+| userName | String | 否 | 用户姓名 | 管理员 |
+| userType | String | 否 | 用户类型 | 1 |
+| phone | String | 否 | 手机号码 | 13800138000 |
+| sex | String | 否 | 用户性别 | 1 |
+| userStatus | String | 否 | 用户状态 | 0 |
+| beginTime | String | 否 | 开始时间 | 2024-01-01 |
+| endTime | String | 否 | 结束时间 | 2024-12-31 |
+
+**响应示例**:
+
+```json
+{
+ "status": 200,
+ "msg": "SUCCESS",
+ "data": {
+ "records": [
+ {
+ "userId": 1,
+ "loginName": "admin",
+ "userName": "管理员",
+ "userType": "1",
+ "email": "admin@example.com",
+ "phone": "13800138000",
+ "sex": "1",
+ "avatar": "/upload/avatar/admin.jpg",
+ "userStatus": "0",
+ "loginIp": "127.0.0.1",
+ "loginTime": "2024-01-01 10:00:00",
+ "pwdUpdateTime": "2024-01-01 10:00:00",
+ "remark": "系统管理员",
+ "createBy": "admin",
+ "createTime": "2024-01-01 10:00:00",
+ "updateBy": "admin",
+ "updateTime": "2024-01-01 10:00:00",
+ "roleIds": [1, 2]
+ }
+ ],
+ "total": 1,
+ "size": 10,
+ "current": 1,
+ "pages": 1
+ },
+ "traceId": "trace-123456"
+}
+```
+
+**调用示例**:
+
+```bash
+curl -X GET \
+ "http://localhost:18099/coder/sysLoginUser/listPage?pageNo=1&pageSize=10&loginName=admin" \
+ -H "Authorization: your-token-value"
+```
+
+---
+
+### 2. 查询所有用户
+
+**接口地址**: `GET /coder/sysLoginUser/list`
+
+**接口描述**: 查询所有系统用户(不分页)
+
+**是否需要认证**: 是
+
+**权限要求**: `system:user:list`
+
+**请求参数**: 同分页查询(除pageNo、pageSize外)
+
+**响应示例**:
+
+```json
+{
+ "status": 200,
+ "msg": "SUCCESS",
+ "data": [
+ {
+ "userId": 1,
+ "loginName": "admin",
+ "userName": "管理员",
+ // 其他字段...
+ }
+ ],
+ "traceId": "trace-123456"
+}
+```
+
+---
+
+### 3. 根据ID查询用户
+
+**接口地址**: `GET /coder/sysLoginUser/getById/{id}`
+
+**接口描述**: 根据用户ID查询用户详细信息
+
+**是否需要认证**: 是
+
+**权限要求**: `system:user:list`
+
+**路径参数**:
+
+| 参数名 | 类型 | 必填 | 说明 |
+|--------|------|------|------|
+| id | Long | 是 | 用户ID |
+
+**响应示例**:
+
+```json
+{
+ "status": 200,
+ "msg": "SUCCESS",
+ "data": {
+ "userId": 1,
+ "loginName": "admin",
+ "userName": "管理员",
+ "userType": "1",
+ "email": "admin@example.com",
+ "phone": "13800138000",
+ "sex": "1",
+ "avatar": "/upload/avatar/admin.jpg",
+ "userStatus": "0",
+ "loginIp": "127.0.0.1",
+ "loginTime": "2024-01-01 10:00:00",
+ "pwdUpdateTime": "2024-01-01 10:00:00",
+ "remark": "系统管理员",
+ "createBy": "admin",
+ "createTime": "2024-01-01 10:00:00",
+ "updateBy": "admin",
+ "updateTime": "2024-01-01 10:00:00",
+ "roleIds": [1, 2]
+ },
+ "traceId": "trace-123456"
+}
+```
+
+**调用示例**:
+
+```bash
+curl -X GET \
+ http://localhost:18099/coder/sysLoginUser/getById/1 \
+ -H "Authorization: your-token-value"
+```
+
+---
+
+### 4. 新增用户
+
+**接口地址**: `POST /coder/sysLoginUser/add`
+
+**接口描述**: 新增系统用户
+
+**是否需要认证**: 是
+
+**权限要求**: `system:user:add`
+
+**请求参数**:
+
+```json
+{
+ "loginName": "newuser",
+ "userName": "新用户",
+ "password": "123456",
+ "userType": "1",
+ "email": "newuser@example.com",
+ "phone": "13800138001",
+ "sex": "1",
+ "userStatus": "0",
+ "remark": "新用户备注",
+ "roleIds": [2]
+}
+```
+
+**请求参数说明**:
+
+| 参数名 | 类型 | 必填 | 说明 | 校验规则 |
+|--------|------|------|------|----------|
+| loginName | String | 是 | 登录账号 | 3-16位字母数字 |
+| userName | String | 是 | 用户姓名 | 不能为空 |
+| password | String | 是 | 登录密码 | 不能为空 |
+| userType | String | 是 | 用户类型 | 1-系统用户 2-注册用户 |
+| email | String | 否 | 邮箱地址 | 邮箱格式验证 |
+| phone | String | 否 | 手机号码 | 手机号格式验证 |
+| sex | String | 否 | 用户性别 | 1-男 2-女 3-未知 |
+| userStatus | String | 是 | 用户状态 | 0-启用 1-停用 |
+| remark | String | 否 | 备注信息 | 最长200字符 |
+| roleIds | Long[] | 否 | 角色ID数组 | 有效的角色ID |
+
+**响应示例**:
+
+```json
+{
+ "status": 200,
+ "msg": "SUCCESS",
+ "data": "新增成功",
+ "traceId": "trace-123456"
+}
+```
+
+**调用示例**:
+
+```bash
+curl -X POST \
+ http://localhost:18099/coder/sysLoginUser/add \
+ -H "Content-Type: application/json" \
+ -H "Authorization: your-token-value" \
+ -d '{
+ "loginName": "newuser",
+ "userName": "新用户",
+ "password": "123456",
+ "userType": "1",
+ "email": "newuser@example.com",
+ "phone": "13800138001",
+ "sex": "1",
+ "userStatus": "0",
+ "remark": "新用户备注",
+ "roleIds": [2]
+ }'
+```
+
+---
+
+### 5. 修改用户信息
+
+**接口地址**: `POST /coder/sysLoginUser/update`
+
+**接口描述**: 修改系统用户信息
+
+**是否需要认证**: 是
+
+**权限要求**: `system:user:edit`
+
+**请求参数**:
+
+```json
+{
+ "userId": 1,
+ "loginName": "admin",
+ "userName": "管理员",
+ "userType": "1",
+ "email": "admin@example.com",
+ "phone": "13800138000",
+ "sex": "1",
+ "userStatus": "0",
+ "remark": "系统管理员",
+ "roleIds": [1, 2]
+}
+```
+
+**请求参数说明**:
+
+| 参数名 | 类型 | 必填 | 说明 | 校验规则 |
+|--------|------|------|------|----------|
+| userId | Long | 是 | 用户ID | 必须是有效的用户ID |
+| loginName | String | 是 | 登录账号 | 3-16位字母数字 |
+| userName | String | 是 | 用户姓名 | 不能为空 |
+| userType | String | 是 | 用户类型 | 1-系统用户 2-注册用户 |
+| email | String | 否 | 邮箱地址 | 邮箱格式验证 |
+| phone | String | 否 | 手机号码 | 手机号格式验证 |
+| sex | String | 否 | 用户性别 | 1-男 2-女 3-未知 |
+| userStatus | String | 是 | 用户状态 | 0-启用 1-停用 |
+| remark | String | 否 | 备注信息 | 最长200字符 |
+| roleIds | Long[] | 否 | 角色ID数组 | 有效的角色ID |
+
+**响应示例**:
+
+```json
+{
+ "status": 200,
+ "msg": "SUCCESS",
+ "data": "修改成功",
+ "traceId": "trace-123456"
+}
+```
+
+**调用示例**:
+
+```bash
+curl -X POST \
+ http://localhost:18099/coder/sysLoginUser/update \
+ -H "Content-Type: application/json" \
+ -H "Authorization: your-token-value" \
+ -d '{
+ "userId": 1,
+ "loginName": "admin",
+ "userName": "管理员",
+ "userType": "1",
+ "email": "admin@example.com",
+ "phone": "13800138000",
+ "sex": "1",
+ "userStatus": "0",
+ "remark": "系统管理员",
+ "roleIds": [1, 2]
+ }'
+```
+
+---
+
+### 6. 删除用户
+
+**接口地址**: `POST /coder/sysLoginUser/deleteById/{id}`
+
+**接口描述**: 根据ID删除用户
+
+**是否需要认证**: 是
+
+**权限要求**: `system:user:remove`
+
+**路径参数**:
+
+| 参数名 | 类型 | 必填 | 说明 |
+|--------|------|------|------|
+| id | Long | 是 | 用户ID |
+
+**响应示例**:
+
+```json
+{
+ "status": 200,
+ "msg": "SUCCESS",
+ "data": "删除成功",
+ "traceId": "trace-123456"
+}
+```
+
+**调用示例**:
+
+```bash
+curl -X POST \
+ http://localhost:18099/coder/sysLoginUser/deleteById/1 \
+ -H "Authorization: your-token-value"
+```
+
+---
+
+### 7. 批量删除用户
+
+**接口地址**: `POST /coder/sysLoginUser/batchDelete`
+
+**接口描述**: 批量删除用户
+
+**是否需要认证**: 是
+
+**权限要求**: `system:user:remove`
+
+**请求参数**:
+
+```json
+{
+ "ids": [1, 2, 3]
+}
+```
+
+**请求参数说明**:
+
+| 参数名 | 类型 | 必填 | 说明 |
+|--------|------|------|------|
+| ids | Long[] | 是 | 用户ID数组 |
+
+**响应示例**:
+
+```json
+{
+ "status": 200,
+ "msg": "SUCCESS",
+ "data": "删除成功",
+ "traceId": "trace-123456"
+}
+```
+
+**调用示例**:
+
+```bash
+curl -X POST \
+ http://localhost:18099/coder/sysLoginUser/batchDelete \
+ -H "Content-Type: application/json" \
+ -H "Authorization: your-token-value" \
+ -d '{
+ "ids": [1, 2, 3]
+ }'
+```
+
+---
+
+### 8. 修改用户状态
+
+**接口地址**: `POST /coder/sysLoginUser/updateStatus/{userId}/{userStatus}`
+
+**接口描述**: 修改用户状态(启用/停用)
+
+**是否需要认证**: 是
+
+**权限要求**: `system:user:status`
+
+**路径参数**:
+
+| 参数名 | 类型 | 必填 | 说明 |
+|--------|------|------|------|
+| userId | Long | 是 | 用户ID |
+| userStatus | String | 是 | 用户状态(0-启用 1-停用) |
+
+**响应示例**:
+
+```json
+{
+ "status": 200,
+ "msg": "SUCCESS",
+ "data": "修改成功",
+ "traceId": "trace-123456"
+}
+```
+
+**调用示例**:
+
+```bash
+curl -X POST \
+ http://localhost:18099/coder/sysLoginUser/updateStatus/1/0 \
+ -H "Authorization: your-token-value"
+```
+
+---
+
+### 9. 获取登录用户信息
+
+**接口地址**: `GET /coder/sysLoginUser/getLoginUserInformation`
+
+**接口描述**: 获取当前登录用户的详细信息
+
+**是否需要认证**: 是
+
+**权限要求**: 无(已登录用户可访问)
+
+**请求参数**: 无
+
+**响应示例**:
+
+```json
+{
+ "status": 200,
+ "msg": "SUCCESS",
+ "data": {
+ "userId": 1,
+ "loginName": "admin",
+ "userName": "管理员",
+ "userType": "1",
+ "email": "admin@example.com",
+ "phone": "13800138000",
+ "sex": "1",
+ "avatar": "/upload/avatar/admin.jpg",
+ "userStatus": "0",
+ "loginIp": "127.0.0.1",
+ "loginTime": "2024-01-01 10:00:00",
+ "pwdUpdateTime": "2024-01-01 10:00:00",
+ "remark": "系统管理员",
+ "createBy": "admin",
+ "createTime": "2024-01-01 10:00:00",
+ "updateBy": "admin",
+ "updateTime": "2024-01-01 10:00:00",
+ "roleIds": [1, 2],
+ "roles": [
+ {
+ "roleId": 1,
+ "roleName": "超级管理员",
+ "roleCode": "admin"
+ }
+ ],
+ "permissions": [
+ "*:*:*"
+ ]
+ },
+ "traceId": "trace-123456"
+}
+```
+
+**调用示例**:
+
+```bash
+curl -X GET \
+ http://localhost:18099/coder/sysLoginUser/getLoginUserInformation \
+ -H "Authorization: your-token-value"
+```
+
+---
+
+### 10. 获取个人资料
+
+**接口地址**: `GET /coder/sysLoginUser/getPersonalData`
+
+**接口描述**: 获取当前用户的个人资料
+
+**是否需要认证**: 是
+
+**权限要求**: 无(已登录用户可访问)
+
+**请求参数**: 无
+
+**响应示例**:
+
+```json
+{
+ "status": 200,
+ "msg": "SUCCESS",
+ "data": {
+ "userId": 1,
+ "loginName": "admin",
+ "userName": "管理员",
+ "email": "admin@example.com",
+ "phone": "13800138000",
+ "sex": "1",
+ "avatar": "/upload/avatar/admin.jpg",
+ "remark": "系统管理员"
+ },
+ "traceId": "trace-123456"
+}
+```
+
+**调用示例**:
+
+```bash
+curl -X GET \
+ http://localhost:18099/coder/sysLoginUser/getPersonalData \
+ -H "Authorization: your-token-value"
+```
+
+---
+
+### 11. 修改个人资料
+
+**接口地址**: `POST /coder/sysLoginUser/updateBasicData`
+
+**接口描述**: 修改当前用户的个人资料
+
+**是否需要认证**: 是
+
+**权限要求**: 无(已登录用户可访问)
+
+**请求参数**:
+
+```json
+{
+ "userName": "管理员",
+ "email": "admin@example.com",
+ "phone": "13800138000",
+ "sex": "1",
+ "avatar": "/upload/avatar/admin.jpg",
+ "remark": "系统管理员"
+}
+```
+
+**请求参数说明**:
+
+| 参数名 | 类型 | 必填 | 说明 | 校验规则 |
+|--------|------|------|------|----------|
+| userName | String | 是 | 用户姓名 | 不能为空 |
+| email | String | 否 | 邮箱地址 | 邮箱格式验证 |
+| phone | String | 否 | 手机号码 | 手机号格式验证 |
+| sex | String | 否 | 用户性别 | 1-男 2-女 3-未知 |
+| avatar | String | 否 | 头像地址 | 有效的文件路径 |
+| remark | String | 否 | 备注信息 | 最长200字符 |
+
+**响应示例**:
+
+```json
+{
+ "status": 200,
+ "msg": "SUCCESS",
+ "data": "修改成功",
+ "traceId": "trace-123456"
+}
+```
+
+**调用示例**:
+
+```bash
+curl -X POST \
+ http://localhost:18099/coder/sysLoginUser/updateBasicData \
+ -H "Content-Type: application/json" \
+ -H "Authorization: your-token-value" \
+ -d '{
+ "userName": "管理员",
+ "email": "admin@example.com",
+ "phone": "13800138000",
+ "sex": "1",
+ "avatar": "/upload/avatar/admin.jpg",
+ "remark": "系统管理员"
+ }'
+```
+
+---
+
+### 12. 修改登录密码
+
+**接口地址**: `POST /coder/sysLoginUser/updateUserPwd`
+
+**接口描述**: 修改当前用户的登录密码
+
+**是否需要认证**: 是
+
+**权限要求**: 无(已登录用户可访问)
+
+**请求参数**:
+
+```json
+{
+ "oldPassword": "123456",
+ "newPassword": "654321",
+ "confirmPassword": "654321"
+}
+```
+
+**请求参数说明**:
+
+| 参数名 | 类型 | 必填 | 说明 | 校验规则 |
+|--------|------|------|------|----------|
+| oldPassword | String | 是 | 原密码 | 不能为空 |
+| newPassword | String | 是 | 新密码 | 不能为空 |
+| confirmPassword | String | 是 | 确认密码 | 必须与新密码一致 |
+
+**响应示例**:
+
+```json
+{
+ "status": 200,
+ "msg": "SUCCESS",
+ "data": "修改成功",
+ "traceId": "trace-123456"
+}
+```
+
+**调用示例**:
+
+```bash
+curl -X POST \
+ http://localhost:18099/coder/sysLoginUser/updateUserPwd \
+ -H "Content-Type: application/json" \
+ -H "Authorization: your-token-value" \
+ -d '{
+ "oldPassword": "123456",
+ "newPassword": "654321",
+ "confirmPassword": "654321"
+ }'
+```
+
+---
+
+### 13. 重置用户密码
+
+**接口地址**: `POST /coder/sysLoginUser/resetPwd/{id}/{password}`
+
+**接口描述**: 重置指定用户的密码
+
+**是否需要认证**: 是
+
+**权限要求**: `system:user:resetPwd`
+
+**路径参数**:
+
+| 参数名 | 类型 | 必填 | 说明 |
+|--------|------|------|------|
+| id | Long | 是 | 用户ID |
+| password | String | 是 | 新密码 |
+
+**响应示例**:
+
+```json
+{
+ "status": 200,
+ "msg": "SUCCESS",
+ "data": "重置成功",
+ "traceId": "trace-123456"
+}
+```
+
+**调用示例**:
+
+```bash
+curl -X POST \
+ http://localhost:18099/coder/sysLoginUser/resetPwd/1/123456 \
+ -H "Authorization: your-token-value"
+```
+
+---
+
+### 14. 下载用户导入模板
+
+**接口地址**: `GET /coder/sysLoginUser/downloadExcelTemplate`
+
+**接口描述**: 下载用户批量导入的Excel模板
+
+**是否需要认证**: 是
+
+**权限要求**: `system:user:import`
+
+**请求参数**: 无
+
+**响应**: Excel文件下载
+
+**调用示例**:
+
+```bash
+curl -X GET \
+ http://localhost:18099/coder/sysLoginUser/downloadExcelTemplate \
+ -H "Authorization: your-token-value" \
+ -o user_template.xlsx
+```
+
+---
+
+### 15. 导出用户数据
+
+**接口地址**: `GET /coder/sysLoginUser/exportExcelData`
+
+**接口描述**: 导出用户数据到Excel
+
+**是否需要认证**: 是
+
+**权限要求**: `system:user:export`
+
+**请求参数**: 同查询参数
+
+**响应**: Excel文件下载
+
+**调用示例**:
+
+```bash
+curl -X GET \
+ "http://localhost:18099/coder/sysLoginUser/exportExcelData?userStatus=0" \
+ -H "Authorization: your-token-value" \
+ -o users.xlsx
+```
+
+---
+
+### 16. 导入用户数据
+
+**接口地址**: `POST /coder/sysLoginUser/importExcelData`
+
+**接口描述**: 从Excel文件导入用户数据
+
+**是否需要认证**: 是
+
+**权限要求**: `system:user:import`
+
+**请求参数**: 文件上传
+
+**Content-Type**: `multipart/form-data`
+
+**请求参数**:
+
+| 参数名 | 类型 | 必填 | 说明 |
+|--------|------|------|------|
+| file | File | 是 | Excel文件 |
+| updateSupport | Boolean | 否 | 是否更新已存在的用户 |
+
+**响应示例**:
+
+```json
+{
+ "status": 200,
+ "msg": "SUCCESS",
+ "data": {
+ "total": 100,
+ "success": 95,
+ "failed": 5,
+ "message": "导入成功95条,失败5条"
+ },
+ "traceId": "trace-123456"
+}
+```
+
+**调用示例**:
+
+```bash
+curl -X POST \
+ http://localhost:18099/coder/sysLoginUser/importExcelData \
+ -H "Authorization: your-token-value" \
+ -F "file=@users.xlsx" \
+ -F "updateSupport=true"
+```
+
+---
+
+## 数据字典
+
+### 用户类型 (userType)
+
+| 值 | 说明 |
+|----|------|
+| 1 | 系统用户 |
+| 2 | 注册用户 |
+| 3 | 微信用户 |
+
+### 用户性别 (sex)
+
+| 值 | 说明 |
+|----|------|
+| 1 | 男 |
+| 2 | 女 |
+| 3 | 未知 |
+
+### 用户状态 (userStatus)
+
+| 值 | 说明 |
+|----|------|
+| 0 | 启用 |
+| 1 | 停用 |
+
+---
+
+## 错误码说明
+
+| 错误码 | 错误信息 | 说明 |
+|--------|----------|------|
+| 400 | 账号长度为 3-16 位 | 登录账号长度不符合要求 |
+| 400 | 账号格式为数字以及字母 | 登录账号格式不正确 |
+| 400 | 登录账号不能为空 | 登录账号为空 |
+| 400 | 用户真实姓名不能为空 | 用户姓名为空 |
+| 400 | 用户不存在 | 用户ID不存在 |
+| 400 | 账号已存在 | 登录账号已被使用 |
+| 400 | 手机号已存在 | 手机号已被使用 |
+| 400 | 邮箱已存在 | 邮箱已被使用 |
+| 400 | 不能删除当前用户 | 不能删除自己的账号 |
+| 400 | 不能停用当前用户 | 不能停用自己的账号 |
+| 400 | 原密码错误 | 修改密码时原密码不正确 |
+| 400 | 新密码不能与原密码相同 | 新密码与原密码一致 |
+| 400 | 两次输入的密码不一致 | 确认密码与新密码不一致 |
+| 401 | 当前会话未登录 | 未登录或Token无效 |
+| 403 | 权限不足 | 没有相应的操作权限 |
+| 500 | 系统异常 | 服务器内部错误 |
+
+---
+
+## 注意事项
+
+1. **权限验证**: 所有用户管理操作都需要相应的权限
+2. **数据校验**: 新增和修改用户时会进行数据格式校验
+3. **唯一性约束**: 登录账号、手机号、邮箱必须唯一
+4. **密码安全**: 密码使用盐值加密存储
+5. **操作日志**: 所有用户操作都会记录日志
+6. **批量操作**: 批量删除时会跳过超级管理员账号
+7. **Excel导入**: 支持Excel模板导入用户数据
+8. **角色关联**: 用户删除时会自动删除角色关联关系
+9. **会话管理**: 用户状态变更时会影响其登录会话
+10. **数据完整性**: 删除用户前会检查关联数据
\ No newline at end of file