commit 52c66444a5cd48efcdfb81235f107c3dc6f61092 Author: 张翔 Date: Wed Mar 11 12:11:59 2026 +0800 feat: 添加系统配置、审计中心、通知中心、文件管理模块 diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000..5008ddf Binary files /dev/null and b/.DS_Store differ diff --git a/.trae/docs/e2e_testing/E2E_TEST_CASES.md b/.trae/docs/e2e_testing/E2E_TEST_CASES.md new file mode 100644 index 0000000..e477f43 --- /dev/null +++ b/.trae/docs/e2e_testing/E2E_TEST_CASES.md @@ -0,0 +1,707 @@ +# E2E测试用例设计文档 + +## 项目概述 + +本项目是一个基于Spring Boot 3.5.9 + WebFlux的响应式管理系统API,采用PostgreSQL数据库,支持用户、角色、字典等核心业务功能。 + +## 测试目标 + +1. 验证关键用户场景的端到端流程 +2. 确保API接口的正确性和稳定性 +3. 验证认证授权机制 +4. 测试数据一致性和完整性 +5. 验证错误处理和边界条件 + +## 测试环境 + +- **测试框架**: Python + Playwright +- **API基础URL**: http://localhost:8080 +- **测试数据库**: PostgreSQL (Test环境) +- **测试数据**: 自动化准备和清理 + +## 测试用例设计 + +### 1. 认证授权测试 + +#### 1.1 用户登录流程 +**用例ID**: TC-AUTH-001 +**优先级**: P0 +**前置条件**: 系统已启动,数据库中存在测试用户 +**测试步骤**: +1. 发送POST请求到 `/api/auth/login` +2. 提供正确的用户名和密码 +3. 验证返回的access_token和refresh_token +4. 验证token格式正确性 + +**预期结果**: +- HTTP状态码: 200 +- 返回包含accessToken和refreshToken +- token格式符合JWT标准 + +**测试数据**: +```json +{ + "username": "admin", + "password": "admin123" +} +``` + +#### 1.2 Token刷新流程 +**用例ID**: TC-AUTH-002 +**优先级**: P0 +**前置条件**: 已获得有效的refresh_token +**测试步骤**: +1. 发送POST请求到 `/api/auth/refresh` +2. 提供有效的refresh_token +3. 验证返回新的access_token + +**预期结果**: +- HTTP状态码: 200 +- 返回新的accessToken +- refreshToken保持不变或更新 + +#### 1.3 用户登出流程 +**用例ID**: TC-AUTH-003 +**优先级**: P1 +**前置条件**: 已登录,持有有效token +**测试步骤**: +1. 发送POST请求到 `/api/auth/logout` +2. 在Header中携带Authorization: Bearer {token} +3. 验证登出成功 + +**预期结果**: +- HTTP状态码: 200 +- 返回成功消息 +- token被加入黑名单 + +#### 1.4 无效登录测试 +**用例ID**: TC-AUTH-004 +**优先级**: P1 +**测试步骤**: +1. 使用错误的用户名或密码登录 +2. 验证错误响应 + +**预期结果**: +- HTTP状态码: 401 +- 返回认证失败消息 + +### 2. 用户管理测试 + +#### 2.1 创建用户 +**用例ID**: TC-USER-001 +**优先级**: P0 +**前置条件**: 已登录,具有ADMIN权限 +**测试步骤**: +1. 发送POST请求到 `/api/users` +2. 提供用户信息 +3. 验证用户创建成功 + +**预期结果**: +- HTTP状态码: 201 +- 返回创建的用户信息 +- 用户ID已生成 +- 密码已加密 + +**测试数据**: +```json +{ + "username": "testuser", + "password": "password123", + "email": "test@example.com", + "roleId": 2, + "status": 1 +} +``` + +#### 2.2 查询单个用户 +**用例ID**: TC-USER-002 +**优先级**: P0 +**测试步骤**: +1. 发送GET请求到 `/api/users/{id}` +2. 验证返回正确的用户信息 + +**预期结果**: +- HTTP状态码: 200 +- 返回完整的用户信息 + +#### 2.3 查询所有用户 +**用例ID**: TC-USER-003 +**优先级**: P0 +**测试步骤**: +1. 发送GET请求到 `/api/users` +2. 验证返回用户列表 + +**预期结果**: +- HTTP状态码: 200 +- 返回用户数组 +- 包含分页信息(如已实现) + +#### 2.4 更新用户 +**用例ID**: TC-USER-004 +**优先级**: P0 +**测试步骤**: +1. 发送PUT请求到 `/api/users/{id}` +2. 提供更新的用户信息 +3. 验证更新成功 + +**预期结果**: +- HTTP状态码: 200 +- 返回更新后的用户信息 + +#### 2.5 删除用户 +**用例ID**: TC-USER-005 +**优先级**: P0 +**测试步骤**: +1. 发送DELETE请求到 `/api/users/{id}` +2. 验证删除成功 + +**预期结果**: +- HTTP状态码: 204 +- 用户已被物理删除 + +#### 2.6 逻辑删除用户 +**用例ID**: TC-USER-006 +**优先级**: P1 +**测试步骤**: +1. 发送DELETE请求到 `/api/users/{id}/logical` +2. 验证逻辑删除成功 +3. 查询已删除用户(带includeDeleted=true) + +**预期结果**: +- HTTP状态码: 200 +- 用户被标记为已删除 +- 可以通过includeDeleted参数查询到 + +#### 2.7 恢复已删除用户 +**用例ID**: TC-USER-007 +**优先级**: P1 +**前置条件**: 用户已被逻辑删除 +**测试步骤**: +1. 发送POST请求到 `/api/users/{id}/restore` +2. 验证恢复成功 + +**预期结果**: +- HTTP状态码: 200 +- 用户状态恢复正常 + +#### 2.8 用户名唯一性检查 +**用例ID**: TC-USER-008 +**优先级**: P1 +**测试步骤**: +1. 发送GET请求到 `/api/users/check/username?username=existing` +2. 验证返回true +3. 使用不存在的用户名验证返回false + +**预期结果**: +- HTTP状态码: 200 +- 返回正确的布尔值 + +#### 2.9 邮箱唯一性检查 +**用例ID**: TC-USER-009 +**优先级**: P1 +**测试步骤**: +1. 发送GET请求到 `/api/users/check/email?email=existing@example.com` +2. 验证返回true +3. 使用不存在的邮箱验证返回false + +**预期结果**: +- HTTP状态码: 200 +- 返回正确的布尔值 + +### 3. 角色管理测试 + +#### 3.1 创建角色 +**用例ID**: TC-ROLE-001 +**优先级**: P0 +**前置条件**: 已登录,具有ADMIN权限 +**测试步骤**: +1. 发送POST请求到 `/api/roles` +2. 提供角色信息 +3. 验证角色创建成功 + +**预期结果**: +- HTTP状态码: 201 +- 返回创建的角色信息 + +**测试数据**: +```json +{ + "name": "TEST_ROLE", + "description": "测试角色", + "permissions": "READ,WRITE" +} +``` + +#### 3.2 查询角色 +**用例ID**: TC-ROLE-002 +**优先级**: P0 +**测试步骤**: +1. 发送GET请求到 `/api/roles/{id}` +2. 验证返回正确的角色信息 + +**预期结果**: +- HTTP状态码: 200 +- 返回完整的角色信息 + +#### 3.3 按名称查询角色 +**用例ID**: TC-ROLE-003 +**优先级**: P1 +**测试步骤**: +1. 发送GET请求到 `/api/roles/name/{name}` +2. 验证返回正确的角色信息 + +**预期结果**: +- HTTP状态码: 200 +- 返回指定名称的角色 + +#### 3.4 查询所有角色 +**用例ID**: TC-ROLE-004 +**优先级**: P0 +**测试步骤**: +1. 发送GET请求到 `/api/roles` +2. 验证返回角色列表 + +**预期结果**: +- HTTP状态码: 200 +- 返回角色数组 + +#### 3.5 更新角色 +**用例ID**: TC-ROLE-005 +**优先级**: P0 +**测试步骤**: +1. 发送PUT请求到 `/api/roles/{id}` +2. 提供更新的角色信息 +3. 验证更新成功 + +**预期结果**: +- HTTP状态码: 200 +- 返回更新后的角色信息 + +#### 3.6 删除角色 +**用例ID**: TC-ROLE-006 +**优先级**: P0 +**测试步骤**: +1. 发送DELETE请求到 `/api/roles/{id}` +2. 验证删除成功 + +**预期结果**: +- HTTP状态码: 204 + +#### 3.7 逻辑删除角色 +**用例ID**: TC-ROLE-007 +**优先级**: P1 +**测试步骤**: +1. 发送DELETE请求到 `/api/roles/{id}/logical` +2. 验证逻辑删除成功 + +**预期结果**: +- HTTP状态码: 200 +- 角色被标记为已删除 + +#### 3.8 恢复已删除角色 +**用例ID**: TC-ROLE-008 +**优先级**: P1 +**测试步骤**: +1. 发送POST请求到 `/api/roles/{id}/restore` +2. 验证恢复成功 + +**预期结果**: +- HTTP状态码: 200 +- 角色状态恢复正常 + +#### 3.9 角色名唯一性检查 +**用例ID**: TC-ROLE-009 +**优先级**: P1 +**测试步骤**: +1. 发送GET请求到 `/api/roles/check/name?name=existing` +2. 验证返回true +3. 使用不存在的角色名验证返回false + +**预期结果**: +- HTTP状态码: 200 +- 返回正确的布尔值 + +### 4. 字典管理测试 + +#### 4.1 创建字典 +**用例ID**: TC-DICT-001 +**优先级**: P0 +**前置条件**: 已登录,具有ADMIN权限 +**测试步骤**: +1. 发送POST请求到 `/api/dictionaries` +2. 提供字典信息 +3. 验证字典创建成功 + +**预期结果**: +- HTTP状态码: 201 +- 返回创建的字典信息 + +**测试数据**: +```json +{ + "type": "USER_STATUS", + "code": "ACTIVE", + "name": "激活", + "value": "1", + "remark": "用户激活状态", + "sort": 1 +} +``` + +#### 4.2 查询字典 +**用例ID**: TC-DICT-002 +**优先级**: P0 +**测试步骤**: +1. 发送GET请求到 `/api/dictionaries/{id}` +2. 验证返回正确的字典信息 + +**预期结果**: +- HTTP状态码: 200 +- 返回完整的字典信息 + +#### 4.3 按类型查询字典 +**用例ID**: TC-DICT-003 +**优先级**: P0 +**测试步骤**: +1. 发送GET请求到 `/api/dictionaries/type/{type}` +2. 验证返回指定类型的字典列表 + +**预期结果**: +- HTTP状态码: 200 +- 返回指定类型的字典数组 +- 按sort字段排序 + +#### 4.4 查询所有字典 +**用例ID**: TC-DICT-004 +**优先级**: P0 +**测试步骤**: +1. 发送GET请求到 `/api/dictionaries` +2. 验证返回字典列表 + +**预期结果**: +- HTTP状态码: 200 +- 返回字典数组 + +#### 4.5 更新字典 +**用例ID**: TC-DICT-005 +**优先级**: P0 +**测试步骤**: +1. 发送PUT请求到 `/api/dictionaries/{id}` +2. 提供更新的字典信息 +3. 验证更新成功 + +**预期结果**: +- HTTP状态码: 200 +- 返回更新后的字典信息 + +#### 4.6 删除字典 +**用例ID**: TC-DICT-006 +**优先级**: P0 +**测试步骤**: +1. 发送DELETE请求到 `/api/dictionaries/{id}` +2. 验证删除成功 + +**预期结果**: +- HTTP状态码: 204 + +#### 4.7 字典类型和编码唯一性检查 +**用例ID**: TC-DICT-007 +**优先级**: P1 +**测试步骤**: +1. 发送GET请求到 `/api/dictionaries/check/exists?type=TYPE&code=CODE` +2. 验证返回true或false + +**预期结果**: +- HTTP状态码: 200 +- 返回正确的布尔值 + +### 5. OAuth2客户端管理测试 + +#### 5.1 创建OAuth2客户端 +**用例ID**: TC-OAUTH2-001 +**优先级**: P1 +**前置条件**: 已登录,具有ADMIN权限 +**测试步骤**: +1. 发送POST请求到 `/api/oauth2/clients` +2. 提供客户端信息 +3. 验证客户端创建成功 + +**预期结果**: +- HTTP状态码: 201 +- 返回创建的客户端信息 +- clientSecret已加密 + +**测试数据**: +```json +{ + "clientId": "test-client", + "clientSecret": "secret123", + "clientName": "Test Client", + "webServerRedirectUri": "http://localhost:8080/callback", + "scope": "read,write", + "authorizedGrantTypes": "authorization_code,refresh_token", + "accessTokenValiditySeconds": 7200, + "refreshTokenValiditySeconds": 2592000, + "autoApprove": false, + "enabled": true +} +``` + +#### 5.2 查询OAuth2客户端 +**用例ID**: TC-OAUTH2-002 +**优先级**: P1 +**测试步骤**: +1. 发送GET请求到 `/api/oauth2/clients/{id}` +2. 验证返回正确的客户端信息 + +**预期结果**: +- HTTP状态码: 200 +- 返回完整的客户端信息 + +#### 5.3 按clientId查询OAuth2凭证 +**用例ID**: TC-OAUTH2-003 +**优先级**: P1 +**测试步骤**: +1. 发送GET请求到 `/api/oauth2/clients/client-id/{clientId}` +2. 验证返回正确的客户端信息 + +**预期结果**: +- HTTP状态码: 200 +- 返回指定clientId的客户端 + +#### 5.4 查询所有OAuth2客户端 +**用例ID**: TC-OAUTH2-004 +**优先级**: P1 +**测试步骤**: +1. 发送GET请求到 `/api/oauth2/clients` +2. 验证返回客户端列表 + +**预期结果**: +- HTTP状态码: 200 +- 返回客户端数组 + +#### 5.5 更新OAuth2客户端 +**用例ID**: TC-OAUTH2-005 +**优先级**: P1 +**测试步骤**: +1. 发送PUT请求到 `/api/oauth2/clients/{id}` +2. 提供更新的客户端信息 +3. 验证更新成功 + +**预期结果**: +- HTTP状态码: 200 +- 返回更新后的客户端信息 + +#### 5.6 删除OAuth2客户端 +**用例ID**: TC-OAUTH2-006 +**优先级**: P1 +**测试步骤**: +1. 发送DELETE请求到 `/api/oauth2/clients/{id}` +2. 验证删除成功 + +**预期结果**: +- HTTP状态码: 204 + +### 6. 权限验证测试 + +#### 6.1 无token访问受保护资源 +**用例ID**: TC-PERM-001 +**优先级**: P0 +**测试步骤**: +1. 不携带token访问需要认证的API +2. 验证返回401 + +**预期结果**: +- HTTP状态码: 401 +- 返回认证失败消息 + +#### 6.2 使用过期token访问 +**用例ID**: TC-PERM-002 +**优先级**: P1 +**测试步骤**: +1. 使用已过期的token访问API +2. 验证返回401 + +**预期结果**: +- HTTP状态码: 401 +- 返回token无效消息 + +#### 6.3 使用已登出的token访问 +**用例ID**: TC-PERM-003 +**优先级**: P1 +**前置条件**: token已被登出 +**测试步骤**: +1. 使用已加入黑名单的token访问API +2. 验证返回401 + +**预期结果**: +- HTTP状态码: 401 +- 返回token无效消息 + +#### 6.4 无权限访问资源 +**用例ID**: TC-PERM-004 +**优先级**: P1 +**前置条件**: 用户没有访问资源的权限 +**测试步骤**: +1. 使用普通用户token访问需要ADMIN权限的资源 +2. 验证返回403 + +**预期结果**: +- HTTP状态码: 403 +- 返回权限不足消息 + +### 7. 边界条件和异常测试 + +#### 7.1 创建重复用户名 +**用例ID**: TC-EDGE-001 +**优先级**: P1 +**测试步骤**: +1. 创建用户A +2. 使用相同的用户名创建用户B +3. 验证返回错误 + +**预期结果**: +- HTTP状态码: 400或409 +- 返回用户名已存在错误 + +#### 7.2 创建重复邮箱 +**用例ID**: TC-EDGE-002 +**优先级**: P1 +**测试步骤**: +1. 创建用户A +2. 使用相同的邮箱创建用户B +3. 验证返回错误 + +**预期结果**: +- HTTP状态码: 400或409 +- 返回邮箱已存在错误 + +#### 7.3 查询不存在的资源 +**用例ID**: TC-EDGE-003 +**优先级**: P1 +**测试步骤**: +1. 查询不存在的用户ID +2. 验证返回404 + +**预期结果**: +- HTTP状态码: 404 +- 返回资源未找到消息 + +#### 7.4 无效的请求参数 +**用例ID**: TC-EDGE-004 +**优先级**: P1 +**测试步骤**: +1. 发送缺少必填字段的请求 +2. 验证返回400 + +**预期结果**: +- HTTP状态码: 400 +- 返回参数验证错误 + +#### 7.5 超长字段输入 +**用例ID**: TC-EDGE-005 +**优先级**: P2 +**测试步骤**: +1. 发送超长用户名或邮箱 +2. 验证返回400 + +**预期结果**: +- HTTP状态码: 400 +- 返回字段长度超限错误 + +### 8. 性能测试 + +#### 8.1 并发登录测试 +**用例ID**: TC-PERF-001 +**优先级**: P2 +**测试步骤**: +1. 模拟100个并发登录请求 +2. 验证所有请求都能正常响应 +3. 记录响应时间 + +**预期结果**: +- 所有请求成功 +- 平均响应时间 < 500ms +- 无错误发生 + +#### 8.2 批量查询性能测试 +**用例ID**: TC-PERF-002 +**优先级**: P2 +**测试步骤**: +1. 创建1000个测试用户 +2. 查询所有用户 +3. 记录响应时间 + +**预期结果**: +- HTTP状态码: 200 +- 响应时间 < 1000ms +- 返回完整数据 + +### 9. 数据一致性测试 + +#### 9.1 缓存一致性测试 +**用例ID**: TC-CONSIST-001 +**优先级**: P1 +**测试步骤**: +1. 查询用户A(首次查询,从数据库) +2. 更新用户A +3. 再次查询用户A(应从缓存获取) +4. 验证返回更新后的数据 + +**预期结果**: +- 第二次查询返回更新后的数据 +- 缓存被正确失效 + +#### 9.2 审计日志测试 +**用例ID**: TC-CONSIST-002 +**优先级**: P1 +**测试步骤**: +1. 创建用户 +2. 更新用户 +3. 删除用户 +4. 查询审计日志 +5. 验证所有操作都被记录 + +**预期结果**: +- 所有操作都被记录 +- 审计日志包含完整的变更信息 + +## 测试执行计划 + +### 测试优先级 +- P0: 核心功能,必须全部通过 +- P1: 重要功能,应该全部通过 +- P2: 辅助功能,尽量通过 + +### 测试顺序 +1. 认证授权测试 +2. 用户管理测试 +3. 角色管理测试 +4. 字典管理测试 +5. OAuth2客户端管理测试 +6. 权限验证测试 +7. 边界条件和异常测试 +8. 性能测试 +9. 数据一致性测试 + +### 测试数据准备 +- 自动化创建测试用户、角色、字典数据 +- 测试完成后自动清理 +- 使用事务回滚确保测试隔离 + +## 测试报告 + +测试报告应包含以下内容: +1. 测试执行摘要 +2. 通过/失败用例统计 +3. 失败用例详情 +4. 性能指标 +5. 缺陷列表 +6. 测试覆盖率 + +## 缺陷分类 + +- 严重: 系统崩溃、数据丢失 +- 高: 核心功能不可用 +- 中: 功能部分不可用 +- 低: 界面、文案问题 diff --git a/.trae/rules/project_rules.md b/.trae/rules/project_rules.md new file mode 100644 index 0000000..439fbfc --- /dev/null +++ b/.trae/rules/project_rules.md @@ -0,0 +1,339 @@ +--- +alwaysApply: false +description: 6A工作流 +--- + +# 6A 工作流执行规范 + +## 概述 + +6A 工作流是一种系统化的软件开发方法论,通过六个阶段确保项目高质量交付: + +Align(对齐) → Architect(架构) → Atomize(原子化) → Approve(审批) → Automate(自动化) → Assess(评估) + +--- + +## 阶段 1: Align 对齐阶段 + +### 🎯 目标 + +``` + + +模糊需求 → 精确规范 + + +``` + +### 📋 执行步骤 + +1.**项目上下文分析** + +- 分析现有项目结构、技术栈、架构模式、依赖关系 +- 分析现有代码模式、文档和约定 +- 理解业务域和数据模型 + + 2.**需求理解确认** + +- 创建 `.trae/docs/任务名/ALIGNMENT_[任务名].md` +- 包含项目和任务特性规范 +- 包含原始需求、边界确认、需求理解、疑问澄清 + + 3.**智能决策策略** + +- 自动识别歧义和不确定性 +- 生成结构化问题清单(按优先级排序) +- 优先基于现有项目内容和行业知识进行决策 +- 有人员倾向或不确定的问题主动中断并询问 +- 基于回答更新理解和规范 + + 4.**中断并询问关键决策点** + +- 主动中断询问,迭代执行智能决策策略 + + 5.**最终共识** + +- 生成 `.trae/docs/任务名/CONSENSUS_[任务名].md` 包含: +- 明确的需求描述和验收标准 +- 技术实现方案、技术约束和集成方案 +- 任务边界限制和验收标准 +- 确认所有不确定性已解决 + +### ✅ 质量门控 + +- [ ] 需求边界清晰无歧义 +- [ ] 技术方案与现有架构对齐 +- [ ] 验收标准具体可测试 +- [ ] 所有关键假设已确认 +- [ ] 项目特性规范已对齐 + +--- + +## 阶段 2: Architect 架构阶段 + +### 🎯 目标 + +``` + + +共识文档 → 系统架构 → 模块设计 → 接口规范 + + +``` + +### 📋 执行步骤 + +1.**系统分层设计** + +- 基于 CONSENSUS、ALIGNMENT 文档设计架构 +- 生成 `.trae/docs/任务名/DESIGN_[任务名].md` 包含: +- 整体架构图(mermaid 绘制) +- 分层设计和核心组件 +- 模块依赖关系图 +- 接口契约定义 +- 数据流向图 +- 异常处理策略 + + 2.**设计原则** + +- 严格按照任务范围,避免过度设计 +- 确保与现有系统架构一致 +- 复用现有组件和模式 + +### ✅ 质量门控 + +- [ ] 架构图清晰准确 +- [ ] 接口定义完整 +- [ ] 与现有系统无冲突 +- [ ] 设计可行性验证 + +--- + +## 阶段 3: Atomize 原子化阶段 + +### 🎯 目标 + +``` + + +架构设计 → 拆分任务 → 明确接口 → 依赖关系 + + +``` + +### 📋 执行步骤 + +1.**子任务拆分** + +- 基于 DESIGN 文档生成 `.trae/docs/任务名/TASK_[任务名].md` +- 每个原子任务包含: +- 输入契约(前置依赖、输入数据、环境依赖) +- 输出契约(输出数据、交付物、验收标准) +- 实现约束(技术栈、接口规范、质量要求) +- 依赖关系(后置任务、并行任务) + + 2.**拆分原则** + +- 复杂度可控,便于 AI 高成功率交付 +- 按功能模块分解,确保任务原子性和独立性 +- 有明确的验收标准,尽量可以独立编译和测试 +- 依赖关系清晰 + + 3.**生成任务依赖图** + +- 使用 mermaid 绘制任务依赖关系图 + +### ✅ 质量门控 + +- [ ] 任务覆盖完整需求 +- [ ] 依赖关系无循环 +- [ ] 每个任务都可独立验证 +- [ ] 复杂度评估合理 + +--- + +## 阶段 4: Approve 审批阶段 + +### 🎯 目标 + +``` + + +原子任务 → 人工审查 → 迭代修改 → 按文档执行 + + +``` + +### 📋 执行步骤 + +1.**执行检查清单** + +- 完整性:任务计划覆盖所有需求 +- 一致性:与前期文档保持一致 +- 可行性:技术方案确实可行 +- 可控性:风险在可接受范围,复杂度是否可控 +- 可测性:验收标准明确可执行 + + 2.**最终确认清单** + +- 明确的实现需求(无歧义) +- 明确的子任务定义 +- 明确的边界和限制 +- 明确的验收标准 +- 代码、测试、文档质量标准 + +--- + +## 阶段 5: Automate 自动化执行 + +### 🎯 目标 + +``` + + +按节点执行 → 编写测试 → 实现代码 → 文档同步 + + +``` + +### 📋 执行步骤 + +1.**逐步实施子任务** + +- 创建 `.trae/docs/任务名/ACCEPTANCE_[任务名].md` 记录完成情况 + + 2.**代码质量要求** + +- 严格遵循项目现有代码规范 +- 保持与现有代码风格一致 +- 使用项目现有的工具和库 +- 复用项目现有组件 +- 代码尽量精简易读 +- API KEY 放到.env 文件中并且不要提交 git + + 3.**异常处理** + +- 遇到不确定问题立刻中断执行 +- 在 TASK 文档中记录问题详细信息和位置 +- 寻求人工澄清后继续 + + 4.**逐步实施流程** + + 按任务依赖顺序执行,对每个子任务执行: + +- 执行前检查(验证输入契约、环境准备、依赖满足) +- 实现核心逻辑(按设计文档编写代码) +- 编写单元测试(边界条件、异常情况) +- 运行验证测试 +- 更新相关文档 +- 每完成一个任务立即验证 + +--- + +## 阶段 6: Assess 评估阶段 + +### 🎯 目标 + +``` + + +执行结果 → 质量评估 → 文档更新 → 交付确认 + + +``` + +### 📋 执行步骤 + +1.**验证执行结果** + +- 更新 `.trae/docs/任务名/ACCEPTANCE_[任务名].md` +- 整体验收检查: +- 所有需求已实现 +- 验收标准全部满足 +- 项目编译通过 +- 所有测试通过 +- 功能完整性验证 +- 实现与设计文档一致 + + 2.**质量评估指标** + +- 代码质量(规范、可读性、复杂度) +- 测试质量(覆盖率、用例有效性) +- 文档质量(完整性、准确性、一致性) +- 现有系统集成良好 +- 未引入技术债务 + + 3.**最终交付物** + +- 生成 `.trae/docs/任务名/FINAL_[任务名].md`(项目总结报告) +- 生成 `.trae/docs/任务名/TODO_[任务名].md`(待办事宜和缺少的配置等) + + 4.**TODO 询问** + +- 询问用户 TODO 的解决方式 +- 精简明确待办事宜和缺少的配置 +- 提供有用的操作指引 + +--- + +## 技术执行规范 + +### 🔐 安全规范 + +- API 密钥等敏感信息使用.env 文件管理 + +### 📝 文档同步 + +- 代码变更同时更新相关文档 + +### 🧪 测试策略 + +- 测试优先:先写测试,后写实现 +- 边界覆盖:覆盖正常流程、边界条件、异常情况 + +### 💡 交互体验优化 + +#### 进度反馈 + +- 显示当前执行阶段 +- 提供详细的执行步骤 +- 标示完成情况 +- 突出需要关注的问题 + +#### 异常处理机制 + +##### 中断条件 + +- 遇到无法自主决策的问题 +- 觉得需要询问用户的问题 +- 技术实现出现阻塞 +- 文档不一致需要确认修正 + +##### 恢复策略 + +- 保存当前执行状态 +- 记录问题详细信息 +- 询问并等待人工干预 +- 从中断点任务继续执行 + +--- + +## 附录:文档模板索引 + +| 阶段 | 文档名称 | 用途 | + +| --------- | ----------------------- | -------------- | + +| Align | ALIGNMENT\_[任务名].md | 需求理解与确认 | + +| Align | CONSENSUS\_[任务名].md | 最终共识与规范 | + +| Architect | DESIGN\_[任务名].md | 系统架构设计 | + +| Atomize | TASK\_[任务名].md | 原子任务定义 | + +| Automate | ACCEPTANCE\_[任务名].md | 执行过程记录 | + +| Assess | FINAL\_[任务名].md | 项目总结报告 | + +| Assess | TODO\_[任务名].md | 待办事宜清单 | diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..c2b11a8 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,14 @@ +{ + "sqltools.connections": [ + { + "ssh": "Disabled", + "previewLimit": 50, + "server": "localhost", + "port": 55432, + "driver": "PostgreSQL", + "name": "local", + "database": "postgres", + "username": "postgres" + } + ] +} diff --git a/README.md b/README.md new file mode 100644 index 0000000..dbf3194 --- /dev/null +++ b/README.md @@ -0,0 +1,61 @@ +# novalon-manage-system + +企业级后台管理系统 + +## 项目结构 + +``` +novalon-manage-system/ +├── novalon-manage-api/ # 后端 API 项目 +│ └── manage-sys/ # 系统管理模块 +├── novalon-manage-web/ # 前端 Web 项目 +└── docs/ # 文档 +``` + +## 技术栈 + +### 后端 +- Java 21 +- Spring Boot 3.4.1 +- Spring Security +- JWT Authentication +- PostgreSQL + +### 前端 +- Vue 3 + TypeScript +- Ant Design Vue +- Pinia +- Vite + +## 快速开始 + +### 后端 + +```bash +cd novalon-manage-api +mvn spring-boot:run +``` + +### 前端 + +```bash +cd novalon-manage-web +pnpm install +pnpm dev +``` + +## 功能模块 + +- 用户管理 +- 角色管理 +- 菜单管理 +- 权限管理 +- 操作日志 +- 系统配置 (规划中) +- 审计中心 (规划中) +- 通知中心 (规划中) +- 文件管理 (规划中) + +## License + +MIT diff --git a/docs/plans/2026-03-11-system-config-audit-notice-plan.md b/docs/plans/2026-03-11-system-config-audit-notice-plan.md new file mode 100644 index 0000000..2e64b05 --- /dev/null +++ b/docs/plans/2026-03-11-system-config-audit-notice-plan.md @@ -0,0 +1,435 @@ +# 系统配置与审计通知中心实施计划 + +> **For Claude:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task. + +**Goal:** 完成系统配置(字典管理、系统参数)、审计中心(登录日志、操作日志、异常追踪)、通知中心(系统公告、消息推送WebSocket)、文件管理(上传/下载/预览)的数据库持久化与功能完善 + +**Architecture:** 基于Spring R2DBC响应式架构,遵循现有分层模式(Handler->Service->Repository->Entity),使用H2/PostgreSQL + Caffeine缓存,消息推送采用WebSocket + +**Tech Stack:** Spring WebFlux, Spring Data R2DBC, H2/PostgreSQL, Caffeine, WebSocket, Lombok + +--- + +## 第一阶段:数据层基础设施建设 + +### Task 1: 创建数据库表SQL脚本 + +**Files:** +- Modify: `docs/sql/init.sql` (创建以下表) + +**Step 1: 编写SQL脚本** + +```sql +-- 字典类型表 +CREATE TABLE IF NOT EXISTS sys_dict_type ( + id BIGINT PRIMARY KEY AUTO_INCREMENT, + dict_name VARCHAR(100) NOT NULL COMMENT '字典名称', + dict_type VARCHAR(100) NOT NULL UNIQUE COMMENT '字典类型', + status VARCHAR(1) DEFAULT '0' COMMENT '状态(0正常 1停用)', + remark VARCHAR(500) COMMENT '备注', + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + deleted_at TIMESTAMP +); + +-- 字典数据表 +CREATE TABLE IF NOT EXISTS sys_dict_data ( + id BIGINT PRIMARY KEY AUTO_INCREMENT, + dict_sort INT DEFAULT 0 COMMENT '字典排序', + dict_label VARCHAR(100) NOT NULL COMMENT '字典标签', + dict_value VARCHAR(100) NOT NULL COMMENT '字典键值', + dict_type VARCHAR(100) NOT NULL COMMENT '字典类型', + css_class VARCHAR(100) COMMENT '样式属性', + list_class VARCHAR(100) COMMENT '表格回显样式', + is_default VARCHAR(1) DEFAULT 'N' COMMENT '是否默认(Y是 N否)', + status VARCHAR(1) DEFAULT '0' COMMENT '状态(0正常 1停用)', + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + deleted_at TIMESTAMP +); + +-- 系统配置表 +CREATE TABLE IF NOT EXISTS sys_config ( + id BIGINT PRIMARY KEY AUTO_INCREMENT, + config_name VARCHAR(100) NOT NULL COMMENT '配置名称', + config_key VARCHAR(100) NOT NULL UNIQUE COMMENT '配置键名', + config_value VARCHAR(500) NOT NULL COMMENT '配置值', + config_type VARCHAR(1) DEFAULT 'N' COMMENT '系统内置(Y是 N否)', + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + deleted_at TIMESTAMP +); + +-- 登录日志表 +CREATE TABLE IF NOT EXISTS sys_login_log ( + id BIGINT PRIMARY KEY AUTO_INCREMENT, + username VARCHAR(50) COMMENT '用户名', + ip VARCHAR(50) COMMENT 'IP地址', + location VARCHAR(255) COMMENT '登录位置', + browser VARCHAR(50) COMMENT '浏览器类型', + os VARCHAR(50) COMMENT '操作系统', + status VARCHAR(1) COMMENT '登录状态(0成功 1失败)', + message VARCHAR(255) COMMENT '提示消息', + login_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP +); + +-- 异常日志表 +CREATE TABLE IF NOT EXISTS sys_exception_log ( + id BIGINT PRIMARY KEY AUTO_INCREMENT, + username VARCHAR(50) COMMENT '用户名', + title VARCHAR(100) COMMENT '异常标题', + exception_name VARCHAR(100) COMMENT '异常名称', + method_name VARCHAR(100) COMMENT '方法名称', + method_params TEXT COMMENT '方法参数', + exception_msg TEXT COMMENT '异常信息', + exception_stack TEXT COMMENT '堆栈信息', + ip VARCHAR(50) COMMENT 'IP地址', + create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP +); + +-- 系统公告表 +CREATE TABLE IF NOT EXISTS sys_notice ( + id BIGINT PRIMARY KEY AUTO_INCREMENT, + notice_title VARCHAR(100) NOT NULL COMMENT '公告标题', + notice_type VARCHAR(1) DEFAULT '1' COMMENT '公告类型(1通知 2公告)', + notice_content TEXT COMMENT '公告内容', + status VARCHAR(1) DEFAULT '0' COMMENT '公告状态(0正常 1关闭)', + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + deleted_at TIMESTAMP +); + +-- 文件管理表 +CREATE TABLE IF NOT EXISTS sys_file ( + id BIGINT PRIMARY KEY AUTO_INCREMENT, + file_name VARCHAR(255) NOT NULL COMMENT '文件名', + file_path VARCHAR(500) NOT NULL COMMENT '文件路径', + file_size VARCHAR(50) COMMENT '文件大小', + file_type VARCHAR(50) COMMENT '文件类型', + storage_type VARCHAR(20) DEFAULT 'local' COMMENT '存储类型(local/oss/s3)', + create_by VARCHAR(50) COMMENT '创建者', + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + deleted_at TIMESTAMP +); + +-- 用户消息表(消息推送用) +CREATE TABLE IF NOT EXISTS sys_user_message ( + id BIGINT PRIMARY KEY AUTO_INCREMENT, + user_id BIGINT NOT NULL COMMENT '接收用户ID', + title VARCHAR(100) COMMENT '消息标题', + content TEXT COMMENT '消息内容', + message_type VARCHAR(1) DEFAULT '1' COMMENT '消息类型(1系统 2通知)', + is_read VARCHAR(1) DEFAULT '0' COMMENT '是否已读(0未读 1已读)', + create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP +); +``` + +**Step 2: 提交SQL脚本** + +```bash +git add docs/sql/init.sql +git commit -m "feat: 添加系统配置和审计模块数据库表脚本" +``` + +--- + +### Task 2: 创建字典类型Entity + +**Files:** +- Create: `novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/infrastructure/db/entity/SysDictTypeEntity.java` +- Modify: `novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/infrastructure/db/entity/BaseEntity.java` + +**Step 1: 在BaseEntity添加公共字段** + +查看现有BaseEntity确保包含: +- id, createdAt, updatedAt, deletedAt + +**Step 2: 创建SysDictTypeEntity** + +```java +package cn.novalon.manage.sys.infrastructure.db.entity; + +import org.springframework.data.annotation.Id; +import org.springframework.data.relational.core.mapping.Column; +import org.springframework.data.relational.core.mapping.Table; + +@Table("sys_dict_type") +public class SysDictTypeEntity { + + @Id + private Long id; + + @Column("dict_name") + private String dictName; + + @Column("dict_type") + private String dictType; + + @Column("status") + private String status; + + @Column("remark") + private String remark; + + @Column("created_at") + private LocalDateTime createdAt; + + @Column("updated_at") + private LocalDateTime updatedAt; + + @Column("deleted_at") + private LocalDateTime deletedAt; + + // Getters and Setters +} +``` + +**Step 3: 提交** + +```bash +git add entity/SysDictTypeEntity.java +git commit -m "feat: 添加字典类型Entity" +``` + +--- + +### Task 3: 创建其他Entity(字典数据、系统配置、登录日志、异常日志、公告、文件、消息) + +**Files:** +- Create: `infrastructure/db/entity/SysDictDataEntity.java` +- Create: `infrastructure/db/entity/SysConfigEntity.java` +- Create: `infrastructure/db/entity/SysLoginLogEntity.java` +- Create: `infrastructure/db/entity/SysExceptionLogEntity.java` +- Create: `infrastructure/db/entity/SysNoticeEntity.java` +- Create: `infrastructure/db/entity/SysFileEntity.java` +- Create: `infrastructure/db/entity/SysUserMessageEntity.java` + +**每Entity结构:** 继承BaseEntity,添加对应字段的@Column注解和getter/setter + +**示例 - SysConfigEntity:** +```java +@Table("sys_config") +public class SysConfigEntity { + @Id + private Long id; + + @Column("config_name") + private String configName; + + @Column("config_key") + private String configKey; + + @Column("config_value") + private String configValue; + + @Column("config_type") + private String configType; + + @Column("created_at") + private LocalDateTime createdAt; + + @Column("updated_at") + private LocalDateTime updatedAt; + + @Column("deleted_at") + private LocalDateTime deletedAt; + + // Getters and Setters +} +``` + +--- + +### Task 4: 创建Repository接口 + +**Files:** +- Create: `infrastructure/db/repository/SysDictTypeRepository.java` +- Create: `infrastructure/db/repository/SysDictDataRepository.java` +- Create: `infrastructure/db/repository/SysConfigRepository.java` +- Create: `infrastructure/db/repository/SysLoginLogRepository.java` +- Create: `infrastructure/db/repository/SysExceptionLogRepository.java` +- Create: `infrastructure/db/repository/SysNoticeRepository.java` +- Create: `infrastructure/db/repository/SysFileRepository.java` +- Create: `infrastructure/db/repository/SysUserMessageRepository.java` + +**每Repository:** 继承 ReactiveCrudRepository + +**示例:** +```java +package cn.novalon.manage.sys.infrastructure.db.repository; + +import cn.novalon.manage.sys.infrastructure.db.entity.SysDictTypeEntity; +import org.springframework.data.repository.reactive.ReactiveCrudRepository; +import org.springframework.stereotype.Repository; + +@Repository +public interface SysDictTypeRepository extends ReactiveCrudRepository { +} +``` + +--- + +## 第二阶段:领域层(Domain + Converter) + +### Task 5: 更新Domain模型 + +**Files:** +- Modify: `core/domain/SysDictType.java` - 添加dictDataList字段 +- Modify: `core/domain/SysDictData.java` - 确保字段完整 +- Modify: `core/domain/SysConfig.java` - 确保字段完整 +- Modify: `core/domain/SysLoginLog.java` - 确保字段完整 +- Create: `core/domain/SysExceptionLog.java` +- Create: `core/domain/SysUserMessage.java` + +--- + +### Task 6: 创建Converter转换器 + +**Files:** +- Create: `infrastructure/db/converter/SysDictTypeConverter.java` +- Create: `infrastructure/db/converter/SysDictDataConverter.java` +- Create: `infrastructure/db/converter/SysConfigConverter.java` +- Create: `infrastructure/db/converter/SysLoginLogConverter.java` +- Create: `infrastructure/db/converter/SysExceptionLogConverter.java` +- Create: `infrastructure/db/converter/SysNoticeConverter.java` +- Create: `infrastructure/db/converter/SysFileConverter.java` + +--- + +## 第三阶段:服务层(Service) + +### Task 7: 创建Service接口和实现 + +**Files:** +- Create: `core/service/ISysDictTypeService.java` + `impl/SysDictTypeServiceImpl.java` +- Create: `core/service/ISysDictDataService.java` + `impl/SysDictDataServiceImpl.java` +- Create: `core/service/ISysConfigService.java` + `impl/SysConfigServiceImpl.java` +- Create: `core/service/ISysLoginLogService.java` + `impl/SysLoginLogServiceImpl.java` +- Create: `core/service/ISysExceptionLogService.java` + `impl/SysExceptionLogServiceImpl.java` +- Create: `core/service/ISysNoticeService.java` + `impl/SysNoticeServiceImpl.java` +- Create: `core/service/ISysFileService.java` + `impl/SysFileServiceImpl.java` +- Create: `core/service/ISysUserMessageService.java` + `impl/SysUserMessageServiceImpl.java` + +**核心方法:** +- CRUD操作 +- 字典: 根据类型查询数据列表 +- 配置: 根据key查询value +- 日志: 分页查询、按条件筛选 +- 消息: 查询用户未读消息 + +--- + +## 第四阶段:Handler层(API接口) + +### Task 8: 重构Handler接入数据库 + +**Files:** +- Modify: `handler/sys/SysDictHandler.java` - 注入Service替换内存Map +- Modify: `handler/sys/SysConfigHandler.java` - 注入Service替换内存Map +- Modify: `handler/sys/SysLogHandler.java` - 添加登录日志和异常日志查询 +- Modify: `handler/sys/SysNoticeHandler.java` - 注入Service替换内存Map +- Modify: `handler/sys/SysFileHandler.java` - 完善文件预览功能 + +--- + +## 第五阶段:消息推送(WebSocket) + +### Task 9: WebSocket配置 + +**Files:** +- Create: `config/WebSocketConfig.java` +- Create: `handler/websocket/WebSocketHandler.java` +- Create: `service/impl/WebSocketService.java` + +```java +@Configuration +@EnableWebSocket +public class WebSocketConfig implements WebSocketConfigurer { + + @Override + public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) { + registry.addHandler(webSocketHandler(), "/ws") + .setAllowedOrigins("*"); + } + + @Bean + public WebSocketHandler webSocketHandler() { + return new WebSocketHandler(); + } +} +``` + +--- + +### Task 10: 消息推送Service + +**Files:** +- Create: `core/service/IWebSocketService.java` +- Create: `core/service/impl/WebSocketServiceImpl.java` + +**功能:** +- 发送消息给指定用户 +- 发送消息给所有在线用户 +- 用户上线/下线跟踪 + +--- + +## 第六阶段:完善文件预览 + +### Task 11: 文件预览支持 + +**Files:** +- Modify: `handler/sys/SysFileHandler.java` - 添加预览接口 +- 创建DTO: `dto/response/FilePreviewResponse.java` + +**预览支持:** +- 图片: 返回Base64或直接流 +- PDF: 返回PDF流 +- 文本: 返回文本内容 + +--- + +## 第七阶段:异常日志自动记录 + +### Task 12: 全局异常处理器 + +**Files:** +- Create: `handler/GlobalExceptionHandler.java` +- Create: `config/GlobalExceptionHandlerConfig.java` + +**功能:** +- 捕获所有Controller异常 +- 自动记录到sys_exception_log表 +- 返回统一格式的错误响应 + +--- + +## 第八阶段:测试 + +### Task 13: 单元测试 + +**Files:** +- Create: `test/service/SysDictTypeServiceTest.java` +- Create: `test/service/SysConfigServiceTest.java` +- Create: `test/service/SysLoginLogServiceTest.java` +- Create: `test/handler/SysDictHandlerTest.java` +- Create: `test/handler/SysNoticeHandlerTest.java` + +**测试覆盖:** +- Service层CRUD操作 +- Handler层API响应 +- 异常场景处理 + +--- + +## 实施顺序 + +1. Task 1: SQL脚本 +2. Task 2-4: Entity + Repository +3. Task 5-6: Domain + Converter +4. Task 7: Service层 +5. Task 8: Handler层重构 +6. Task 9-10: WebSocket消息推送 +7. Task 11: 文件预览 +8. Task 12: 异常日志 +9. Task 13: 测试 diff --git a/docs/sql/init.sql b/docs/sql/init.sql new file mode 100644 index 0000000..9bf3cb0 --- /dev/null +++ b/docs/sql/init.sql @@ -0,0 +1,147 @@ +-- 系统配置与审计通知中心数据库表脚本 +-- 数据库: H2/PostgreSQL + +-- 字典类型表 +CREATE TABLE IF NOT EXISTS sys_dict_type ( + id BIGINT PRIMARY KEY AUTO_INCREMENT, + dict_name VARCHAR(100) NOT NULL COMMENT '字典名称', + dict_type VARCHAR(100) NOT NULL UNIQUE COMMENT '字典类型', + status VARCHAR(1) DEFAULT '0' COMMENT '状态(0正常 1停用)', + remark VARCHAR(500) COMMENT '备注', + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + deleted_at TIMESTAMP +); + +-- 字典数据表 +CREATE TABLE IF NOT EXISTS sys_dict_data ( + id BIGINT PRIMARY KEY AUTO_INCREMENT, + dict_sort INT DEFAULT 0 COMMENT '字典排序', + dict_label VARCHAR(100) NOT NULL COMMENT '字典标签', + dict_value VARCHAR(100) NOT NULL COMMENT '字典键值', + dict_type VARCHAR(100) NOT NULL COMMENT '字典类型', + css_class VARCHAR(100) COMMENT '样式属性', + list_class VARCHAR(100) COMMENT '表格回显样式', + is_default VARCHAR(1) DEFAULT 'N' COMMENT '是否默认(Y是 N否)', + status VARCHAR(1) DEFAULT '0' COMMENT '状态(0正常 1停用)', + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + deleted_at TIMESTAMP +); + +-- 系统配置表 +CREATE TABLE IF NOT EXISTS sys_config ( + id BIGINT PRIMARY KEY AUTO_INCREMENT, + config_name VARCHAR(100) NOT NULL COMMENT '配置名称', + config_key VARCHAR(100) NOT NULL UNIQUE COMMENT '配置键名', + config_value VARCHAR(500) NOT NULL COMMENT '配置值', + config_type VARCHAR(1) DEFAULT 'N' COMMENT '系统内置(Y是 N否)', + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + deleted_at TIMESTAMP +); + +-- 登录日志表 +CREATE TABLE IF NOT EXISTS sys_login_log ( + id BIGINT PRIMARY KEY AUTO_INCREMENT, + username VARCHAR(50) COMMENT '用户名', + ip VARCHAR(50) COMMENT 'IP地址', + location VARCHAR(255) COMMENT '登录位置', + browser VARCHAR(50) COMMENT '浏览器类型', + os VARCHAR(50) COMMENT '操作系统', + status VARCHAR(1) COMMENT '登录状态(0成功 1失败)', + message VARCHAR(255) COMMENT '提示消息', + login_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP +); + +-- 异常日志表 +CREATE TABLE IF NOT EXISTS sys_exception_log ( + id BIGINT PRIMARY KEY AUTO_INCREMENT, + username VARCHAR(50) COMMENT '用户名', + title VARCHAR(100) COMMENT '异常标题', + exception_name VARCHAR(100) COMMENT '异常名称', + method_name VARCHAR(100) COMMENT '方法名称', + method_params TEXT COMMENT '方法参数', + exception_msg TEXT COMMENT '异常信息', + exception_stack TEXT COMMENT '堆栈信息', + ip VARCHAR(50) COMMENT 'IP地址', + create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP +); + +-- 系统公告表 +CREATE TABLE IF NOT EXISTS sys_notice ( + id BIGINT PRIMARY KEY AUTO_INCREMENT, + notice_title VARCHAR(100) NOT NULL COMMENT '公告标题', + notice_type VARCHAR(1) DEFAULT '1' COMMENT '公告类型(1通知 2公告)', + notice_content TEXT COMMENT '公告内容', + status VARCHAR(1) DEFAULT '0' COMMENT '公告状态(0正常 1关闭)', + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + deleted_at TIMESTAMP +); + +-- 文件管理表 +CREATE TABLE IF NOT EXISTS sys_file ( + id BIGINT PRIMARY KEY AUTO_INCREMENT, + file_name VARCHAR(255) NOT NULL COMMENT '文件名', + file_path VARCHAR(500) NOT NULL COMMENT '文件路径', + file_size VARCHAR(50) COMMENT '文件大小', + file_type VARCHAR(50) COMMENT '文件类型', + storage_type VARCHAR(20) DEFAULT 'local' COMMENT '存储类型(local/oss/s3)', + create_by VARCHAR(50) COMMENT '创建者', + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + deleted_at TIMESTAMP +); + +-- 用户消息表(消息推送用) +CREATE TABLE IF NOT EXISTS sys_user_message ( + id BIGINT PRIMARY KEY AUTO_INCREMENT, + user_id BIGINT NOT NULL COMMENT '接收用户ID', + title VARCHAR(100) COMMENT '消息标题', + content TEXT COMMENT '消息内容', + message_type VARCHAR(1) DEFAULT '1' COMMENT '消息类型(1系统 2通知)', + is_read VARCHAR(1) DEFAULT '0' COMMENT '是否已读(0未读 1已读)', + create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP +); + +-- 初始化默认系统配置数据 +INSERT INTO sys_config (config_name, config_key, config_value, config_type) VALUES +('系统名称', 'sys.system.name', 'Novalon管理系统', 'Y'), +('系统版本', 'sys.system.version', '1.0.0', 'Y'), +('文件上传最大大小', 'sys.file.maxSize', '10485760', 'Y'), +('文件上传允许类型', 'sys.file.allowedTypes', 'jpg,jpeg,png,pdf,doc,docx,xls,xlsx', 'Y'), +('会话超时时间(分钟)', 'sys.session.timeout', '30', 'Y'), +('密码最小长度', 'sys.password.minLength', '6', 'Y'); + +-- 初始化默认字典类型 +INSERT INTO sys_dict_type (dict_name, dict_type, status, remark) VALUES +('用户性别', 'sys_user_sex', '0', '用户性别列表'), +('菜单状态', 'sys_show_hide', '0', '菜单显示状态'), +('系统开关', 'sys_normal_disable', '0', '系统开关状态'), +('任务状态', 'sys_job_status', '0', '定时任务状态'), +('任务分组', 'sys_job_group', '0', '定时任务分组'), +('系统是否', 'sys_yes_no', '0', '系统是否列表'); + +-- 初始化默认字典数据 +INSERT INTO sys_dict_data (dict_label, dict_value, dict_type, dict_sort, is_default, status) VALUES +('男', '0', 'sys_user_sex', 1, 'Y', '0'), +('女', '1', 'sys_user_sex', 2, 'N', '0'), +('未知', '2', 'sys_user_sex', 3, 'N', '0'), +('显示', '0', 'sys_show_hide', 1, 'Y', '0'), +('隐藏', '1', 'sys_show_hide', 2, 'N', '0'), +('正常', '0', 'sys_normal_disable', 1, 'Y', '0'), +('停用', '1', 'sys_normal_disable', 2, 'N', '0'), +('是', 'Y', 'sys_yes_no', 1, 'Y', '0'), +('否', 'N', 'sys_yes_no', 2, 'N', '0'); + +-- 创建索引 +CREATE INDEX idx_sys_dict_type_dict_type ON sys_dict_type(dict_type); +CREATE INDEX idx_sys_dict_data_dict_type ON sys_dict_data(dict_type); +CREATE INDEX idx_sys_config_config_key ON sys_config(config_key); +CREATE INDEX idx_sys_login_log_username ON sys_login_log(username); +CREATE INDEX idx_sys_login_log_login_time ON sys_login_log(login_time); +CREATE INDEX idx_sys_exception_log_create_time ON sys_exception_log(create_time); +CREATE INDEX idx_sys_notice_status ON sys_notice(status); +CREATE INDEX idx_sys_file_create_by ON sys_file(create_by); +CREATE INDEX idx_sys_user_message_user_id ON sys_user_message(user_id); +CREATE INDEX idx_sys_user_message_is_read ON sys_user_message(is_read); diff --git a/e2e_tests/.env.example b/e2e_tests/.env.example new file mode 100644 index 0000000..f1f4ed1 --- /dev/null +++ b/e2e_tests/.env.example @@ -0,0 +1,22 @@ +# E2E测试环境配置 + +# API配置 +API_BASE_URL=http://localhost:8080 + +# 数据库配置 +DATABASE_HOST=localhost +DATABASE_PORT=5432 +DATABASE_NAME=manage_system +DATABASE_USERNAME=postgres +DATABASE_PASSWORD=postgres + +# 测试用户凭证 +TEST_USERNAME=admin +TEST_PASSWORD=admin123 + +# 浏览器配置 +HEADLESS_BROWSER=true +BROWSER_TYPE=chromium + +# 超时配置(毫秒) +REQUEST_TIMEOUT=30000 diff --git a/e2e_tests/.gitignore b/e2e_tests/.gitignore new file mode 100644 index 0000000..41570c4 --- /dev/null +++ b/e2e_tests/.gitignore @@ -0,0 +1,55 @@ +# Python +__pycache__/ +*.py[cod] +*$py.class +*.so +.Python +env/ +venv/ +ENV/ +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +*.egg-info/ +.installed.cfg +*.egg + +# Pytest +.pytest_cache/ +.coverage +htmlcov/ +*.cover +.hypothesis/ + +# Allure +allure-results/ +allure-report/ + +# Logs +*.log + +# Environment variables +.env + +# IDE +.vscode/ +.idea/ +*.swp +*.swo +*~ + +# OS +.DS_Store +Thumbs.db + +# Playwright +.playwright/ diff --git a/e2e_tests/README.md b/e2e_tests/README.md new file mode 100644 index 0000000..d6473ff --- /dev/null +++ b/e2e_tests/README.md @@ -0,0 +1,104 @@ +# E2E测试项目 + +## 项目概述 + +本项目使用Python + Playwright框架对Novalon管理系统进行端到端测试。 + +## 技术栈 + +- **Python**: 3.9+ +- **Playwright**: 1.40+ +- **Pytest**: 7.0+ +- **Allure**: 测试报告 + +## 项目结构 + +``` +e2e_tests/ +├── __init__.py +├── conftest.py # Pytest配置和fixtures +├── pytest.ini # Pytest配置文件 +├── requirements.txt # Python依赖 +├── config/ +│ ├── __init__.py +│ └── settings.py # 配置管理 +├── pages/ +│ ├── __init__.py +│ ├── base_page.py # 基础页面类 +│ ├── auth_page.py # 认证相关页面 +│ ├── user_page.py # 用户管理页面 +│ ├── role_page.py # 角色管理页面 +│ └── dictionary_page.py # 字典管理页面 +├── api/ +│ ├── __init__.py +│ ├── base_api.py # 基础API类 +│ ├── auth_api.py # 认证API +│ ├── user_api.py # 用户API +│ ├── role_api.py # 角色API +│ └── dictionary_api.py # 字典API +├── tests/ +│ ├── __init__.py +│ ├── test_auth.py # 认证测试 +│ ├── test_user.py # 用户管理测试 +│ ├── test_role.py # 角色管理测试 +│ ├── test_dictionary.py # 字典管理测试 +│ └── test_oauth2.py # OAuth2测试 +├── utils/ +│ ├── __init__.py +│ ├── data_generator.py # 测试数据生成器 +│ ├── assertions.py # 断言工具 +│ └── logger.py # 日志工具 +└── reports/ # 测试报告目录 +``` + +## 安装依赖 + +```bash +# 安装Python依赖 +pip install -r requirements.txt + +# 安装Playwright浏览器 +playwright install +``` + +## 运行测试 + +```bash +# 运行所有测试 +pytest + +# 运行特定测试文件 +pytest tests/test_auth.py + +# 运行特定测试用例 +pytest tests/test_auth.py::test_login_success + +# 生成Allure报告 +pytest --alluredir=allure-results +allure serve allure-results + +# 并发运行测试 +pytest -n auto +``` + +## 配置说明 + +在 `config/settings.py` 中配置: +- API基础URL +- 测试数据库连接 +- 测试用户凭证 +- 超时设置 + +## 测试数据管理 + +测试数据自动准备和清理: +- 每个测试用例独立运行 +- 使用fixture自动创建和清理测试数据 +- 支持数据回滚 + +## 持续集成 + +测试可在CI/CD流程中自动运行: +- GitHub Actions +- GitLab CI +- Jenkins diff --git a/e2e_tests/__init__.py b/e2e_tests/__init__.py new file mode 100644 index 0000000..89e6c1d --- /dev/null +++ b/e2e_tests/__init__.py @@ -0,0 +1,6 @@ +""" +E2E测试项目 - Novalon管理系统 +使用Playwright进行端到端测试 +""" + +__version__ = "1.0.0" diff --git a/e2e_tests/api/__init__.py b/e2e_tests/api/__init__.py new file mode 100644 index 0000000..c057860 --- /dev/null +++ b/e2e_tests/api/__init__.py @@ -0,0 +1 @@ +"""API模块""" diff --git a/e2e_tests/api/auth_api.py b/e2e_tests/api/auth_api.py new file mode 100644 index 0000000..46912da --- /dev/null +++ b/e2e_tests/api/auth_api.py @@ -0,0 +1,33 @@ +""" +认证API +""" + +from typing import Dict, Any +from httpx import AsyncClient, Response +from .base_api import BaseAPI + + +class AuthAPI(BaseAPI): + """认证API""" + + def __init__(self, client: AsyncClient): + super().__init__(client, "/api/auth") + + async def login(self, username: str, password: str) -> Response: + """用户登录""" + return await self.post("/login", json={ + "username": username, + "password": password + }) + + async def refresh_token(self, refresh_token: str) -> Response: + """刷新token""" + return await self.post("/refresh", json={ + "refreshToken": refresh_token + }) + + async def logout(self, token: str) -> Response: + """用户登出""" + return await self.post("/logout", headers={ + "Authorization": f"Bearer {token}" + }) diff --git a/e2e_tests/api/base_api.py b/e2e_tests/api/base_api.py new file mode 100644 index 0000000..e8e7684 --- /dev/null +++ b/e2e_tests/api/base_api.py @@ -0,0 +1,58 @@ +""" +基础API类 +""" + +from typing import Optional, Dict, Any +from httpx import AsyncClient, Response +from loguru import logger + + +class BaseAPI: + """基础API类""" + + def __init__(self, client: AsyncClient, base_url: str = ""): + self.client = client + self.base_url = base_url + + async def get(self, endpoint: str, params: Optional[Dict[str, Any]] = None, **kwargs) -> Response: + """GET请求""" + url = f"{self.base_url}{endpoint}" + logger.info(f"GET {url} - Params: {params}") + response = await self.client.get(url, params=params, **kwargs) + logger.info(f"Response: {response.status_code}") + return response + + async def post(self, endpoint: str, data: Optional[Dict[str, Any]] = None, json: Optional[Dict[str, Any]] = None, **kwargs) -> Response: + """POST请求""" + url = f"{self.base_url}{endpoint}" + logger.info(f"POST {url} - Data: {data} - JSON: {json}") + response = await self.client.post(url, data=data, json=json, **kwargs) + logger.info(f"Response: {response.status_code}") + return response + + async def put(self, endpoint: str, data: Optional[Dict[str, Any]] = None, json: Optional[Dict[str, Any]] = None, **kwargs) -> Response: + """PUT请求""" + url = f"{self.base_url}{endpoint}" + logger.info(f"PUT {url} - Data: {data} - JSON: {json}") + response = await self.client.put(url, data=data, json=json, **kwargs) + logger.info(f"Response: {response.status_code}") + return response + + async def delete(self, endpoint: str, **kwargs) -> Response: + """DELETE请求""" + url = f"{self.base_url}{endpoint}" + logger.info(f"DELETE {url}") + response = await self.client.delete(url, **kwargs) + logger.info(f"Response: {response.status_code}") + return response + + async def assert_status_code(self, response: Response, expected_status: int): + """断言状态码""" + assert response.status_code == expected_status, f"Expected {expected_status}, got {response.status_code}. Response: {response.text}" + + async def assert_response_contains(self, response: Response, key: str, value: Any = None): + """断言响应包含指定字段""" + data = response.json() + assert key in data, f"Response does not contain key '{key}'" + if value is not None: + assert data[key] == value, f"Expected {value}, got {data[key]}" diff --git a/e2e_tests/api/dictionary_api.py b/e2e_tests/api/dictionary_api.py new file mode 100644 index 0000000..4e5fc95 --- /dev/null +++ b/e2e_tests/api/dictionary_api.py @@ -0,0 +1,42 @@ +""" +字典管理API +""" + +from typing import Dict, Any +from httpx import AsyncClient, Response +from .base_api import BaseAPI + + +class DictionaryAPI(BaseAPI): + """字典管理API""" + + def __init__(self, client: AsyncClient): + super().__init__(client, "/api/dictionaries") + + async def create_dictionary(self, dict_data: Dict[str, Any]) -> Response: + """创建字典""" + return await self.post("", json=dict_data) + + async def get_dictionary_by_id(self, dict_id: int) -> Response: + """根据ID获取字典""" + return await self.get(f"/{dict_id}") + + async def get_dictionaries_by_type(self, dict_type: str) -> Response: + """根据类型获取字典""" + return await self.get(f"/type/{dict_type}") + + async def get_all_dictionaries(self) -> Response: + """获取所有字典""" + return await self.get("") + + async def update_dictionary(self, dict_id: int, dict_data: Dict[str, Any]) -> Response: + """更新字典""" + return await self.put(f"/{dict_id}", json=dict_data) + + async def delete_dictionary(self, dict_id: int) -> Response: + """删除字典""" + return await self.delete(f"/{dict_id}") + + async def check_type_and_code_exists(self, dict_type: str, code: str) -> Response: + """检查类型和编码是否存在""" + return await self.get("/check/exists", params={"type": dict_type, "code": code}) diff --git a/e2e_tests/api/role_api.py b/e2e_tests/api/role_api.py new file mode 100644 index 0000000..8904194 --- /dev/null +++ b/e2e_tests/api/role_api.py @@ -0,0 +1,58 @@ +""" +角色管理API +""" + +from typing import Dict, Any, List +from httpx import AsyncClient, Response +from .base_api import BaseAPI + + +class RoleAPI(BaseAPI): + """角色管理API""" + + def __init__(self, client: AsyncClient): + super().__init__(client, "/api/roles") + + async def create_role(self, role_data: Dict[str, Any]) -> Response: + """创建角色""" + return await self.post("", json=role_data) + + async def get_role_by_id(self, role_id: int) -> Response: + """根据ID获取角色""" + return await self.get(f"/{role_id}") + + async def get_role_by_name(self, role_name: str) -> Response: + """根据名称获取角色""" + return await self.get(f"/name/{role_name}") + + async def get_all_roles(self, include_deleted: bool = False) -> Response: + """获取所有角色""" + return await self.get("", params={"includeDeleted": include_deleted}) + + async def update_role(self, role_id: int, role_data: Dict[str, Any]) -> Response: + """更新角色""" + return await self.put(f"/{role_id}", json=role_data) + + async def delete_role(self, role_id: int) -> Response: + """删除角色""" + return await self.delete(f"/{role_id}") + + async def logical_delete_role(self, role_id: int) -> Response: + """逻辑删除角色""" + return await self.delete(f"/{role_id}/logical") + + async def logical_delete_roles(self, role_ids: List[int]) -> Response: + """批量逻辑删除角色""" + return await self.post("/logical-delete", json=role_ids) + + async def restore_role(self, role_id: int) -> Response: + """恢复角色""" + return await self.post(f"/{role_id}/restore") + + async def restore_roles(self, role_ids: List[int]) -> Response: + """批量恢复角色""" + return await self.post("/restore", json=role_ids) + + async def check_name_exists(self, role_name: str) -> Response: + """检查角色名是否存在""" + return await self.get("/check/name", params={"name": role_name}) diff --git a/e2e_tests/api/user_api.py b/e2e_tests/api/user_api.py new file mode 100644 index 0000000..0e348fe --- /dev/null +++ b/e2e_tests/api/user_api.py @@ -0,0 +1,58 @@ +""" +用户管理API +""" + +from typing import Dict, Any, List +from httpx import AsyncClient, Response +from .base_api import BaseAPI + + +class UserAPI(BaseAPI): + """用户管理API""" + + def __init__(self, client: AsyncClient): + super().__init__(client, "/api/users") + + async def create_user(self, user_data: Dict[str, Any]) -> Response: + """创建用户""" + return await self.post("", json=user_data) + + async def get_user_by_id(self, user_id: int) -> Response: + """根据ID获取用户""" + return await self.get(f"/{user_id}") + + async def get_all_users(self, include_deleted: bool = False) -> Response: + """获取所有用户""" + return await self.get("", params={"includeDeleted": include_deleted}) + + async def update_user(self, user_id: int, user_data: Dict[str, Any]) -> Response: + """更新用户""" + return await self.put(f"/{user_id}", json=user_data) + + async def delete_user(self, user_id: int) -> Response: + """删除用户""" + return await self.delete(f"/{user_id}") + + async def logical_delete_user(self, user_id: int) -> Response: + """逻辑删除用户""" + return await self.delete(f"/{user_id}/logical") + + async def logical_delete_users(self, user_ids: List[int]) -> Response: + """批量逻辑删除用户""" + return await self.post("/logical-delete", json=user_ids) + + async def restore_user(self, user_id: int) -> Response: + """恢复用户""" + return await self.post(f"/{user_id}/restore") + + async def restore_users(self, user_ids: List[int]) -> Response: + """批量恢复用户""" + return await self.post("/restore", json=user_ids) + + async def check_username_exists(self, username: str) -> Response: + """检查用户名是否存在""" + return await self.get("/check/username", params={"username": username}) + + async def check_email_exists(self, email: str) -> Response: + """检查邮箱是否存在""" + return await self.get("/check/email", params={"email": email}) diff --git a/e2e_tests/config/__init__.py b/e2e_tests/config/__init__.py new file mode 100644 index 0000000..439b927 --- /dev/null +++ b/e2e_tests/config/__init__.py @@ -0,0 +1 @@ +"""配置模块""" diff --git a/e2e_tests/config/settings.py b/e2e_tests/config/settings.py new file mode 100644 index 0000000..0311082 --- /dev/null +++ b/e2e_tests/config/settings.py @@ -0,0 +1,74 @@ +""" +配置管理模块 +""" + +import os +from typing import Optional +from pydantic_settings import BaseSettings +from pydantic import Field + + +class Settings(BaseSettings): + """应用配置""" + + API_BASE_URL: str = Field( + default="http://localhost:8080", + description="API基础URL" + ) + + DATABASE_HOST: str = Field( + default="localhost", + description="数据库主机" + ) + + DATABASE_PORT: int = Field( + default=55432, + description="数据库端口" + ) + + DATABASE_NAME: str = Field( + default="manage_system", + description="数据库名称" + ) + + DATABASE_USERNAME: str = Field( + default="postgres", + description="数据库用户名" + ) + + DATABASE_PASSWORD: str = Field( + default="postgres", + description="数据库密码" + ) + + TEST_USERNAME: str = Field( + default="admin", + description="测试用户名" + ) + + TEST_PASSWORD: str = Field( + default="admin123", + description="测试用户密码" + ) + + REQUEST_TIMEOUT: int = Field( + default=30000, + description="请求超时时间(毫秒)" + ) + + HEADLESS_BROWSER: bool = Field( + default=True, + description="无头浏览器模式" + ) + + BROWSER_TYPE: str = Field( + default="chromium", + description="浏览器类型" + ) + + class Config: + env_file = ".env" + env_file_encoding = "utf-8" + + +settings = Settings() diff --git a/e2e_tests/conftest.py b/e2e_tests/conftest.py new file mode 100644 index 0000000..b4a7d6c --- /dev/null +++ b/e2e_tests/conftest.py @@ -0,0 +1,161 @@ +""" +Pytest配置和fixtures +""" + +import asyncio +import pytest +from typing import AsyncGenerator, Generator +from playwright.async_api import async_playwright, Browser, BrowserContext, Page +from httpx import AsyncClient + +from config.settings import settings + + +@pytest.fixture(scope="session") +def event_loop(): + """创建事件循环""" + loop = asyncio.get_event_loop_policy().new_event_loop() + yield loop + loop.close() + + +@pytest.fixture(scope="session") +async def browser() -> AsyncGenerator[Browser, None]: + """浏览器fixture""" + async with async_playwright() as p: + browser = await p.launch( + headless=settings.HEADLESS_BROWSER, + browser_type=settings.BROWSER_TYPE + ) + yield browser + await browser.close() + + +@pytest.fixture +async def context(browser: Browser) -> AsyncGenerator[BrowserContext, None]: + """浏览器上下文fixture""" + context = await browser.new_context() + yield context + await context.close() + + +@pytest.fixture +async def page(context: BrowserContext) -> AsyncGenerator[Page, None]: + """页面fixture""" + page = await context.new_page() + page.set_default_timeout(settings.REQUEST_TIMEOUT) + yield page + await page.close() + + +@pytest.fixture +async def http_client() -> AsyncGenerator[AsyncClient, None]: + """HTTP客户端fixture""" + async with AsyncClient( + base_url=settings.API_BASE_URL, + timeout=settings.REQUEST_TIMEOUT / 1000 + ) as client: + yield client + + +@pytest.fixture +async def auth_token(http_client: AsyncClient) -> str: + """获取认证token""" + response = await http_client.post( + "/api/auth/login", + json={ + "username": settings.TEST_USERNAME, + "password": settings.TEST_PASSWORD + } + ) + assert response.status_code == 200 + data = response.json() + return data.get("accessToken") + + +@pytest.fixture +async def authenticated_client(http_client: AsyncClient, auth_token: str) -> AsyncClient: + """已认证的HTTP客户端""" + http_client.headers.update({"Authorization": f"Bearer {auth_token}"}) + return http_client + + +@pytest.fixture +def test_user_data(): + """测试用户数据""" + import time + timestamp = int(time.time() * 1000) + return { + "username": f"testuser_{timestamp}", + "password": "password123", + "email": f"test_{timestamp}@example.com", + "roleId": 2, + "status": 1 + } + + +@pytest.fixture +def test_role_data(): + """测试角色数据""" + import time + timestamp = int(time.time() * 1000) + return { + "name": f"TEST_ROLE_{timestamp}", + "description": "测试角色", + "permissions": "READ,WRITE" + } + + +@pytest.fixture +def test_dictionary_data(): + """测试字典数据""" + return { + "type": "USER_STATUS", + "code": "ACTIVE", + "name": "激活", + "value": "1", + "remark": "用户激活状态", + "sort": 1 + } + + +@pytest.fixture +async def cleanup_user(authenticated_client: AsyncClient): + """清理测试用户""" + user_ids = [] + + yield user_ids + + for user_id in user_ids: + try: + await authenticated_client.delete(f"/api/users/{user_id}") + except Exception: + pass + + +@pytest.fixture +async def cleanup_role(authenticated_client: AsyncClient): + """清理测试角色""" + role_ids = [] + + yield role_ids + + for role_id in role_ids: + try: + await authenticated_client.delete(f"/api/roles/{role_id}") + except Exception: + pass + + +@pytest.fixture +async def cleanup_dictionary(authenticated_client: AsyncClient): + """清理测试字典""" + dict_ids = [] + + yield dict_ids + + for dict_id in dict_ids: + try: + await authenticated_client.delete(f"/api/dictionaries/{dict_id}") + except Exception: + pass diff --git a/e2e_tests/pytest.ini b/e2e_tests/pytest.ini new file mode 100644 index 0000000..96c0250 --- /dev/null +++ b/e2e_tests/pytest.ini @@ -0,0 +1,23 @@ +[pytest] +testpaths = tests +python_files = test_*.py +python_classes = Test* +python_functions = test_* +addopts = + -v + --strict-markers + --tb=short + --cov=. + --cov-report=html + --cov-report=term-missing + --alluredir=allure-results +markers = + auth: 认证相关测试 + user: 用户管理测试 + role: 角色管理测试 + dictionary: 字典管理测试 + oauth2: OAuth2相关测试 + smoke: 冒烟测试 + regression: 回归测试 + slow: 慢速测试 +asyncio_mode = auto diff --git a/e2e_tests/requirements.txt b/e2e_tests/requirements.txt new file mode 100644 index 0000000..6ad86da --- /dev/null +++ b/e2e_tests/requirements.txt @@ -0,0 +1,29 @@ +# Python依赖包 + +# 测试框架 +pytest==7.4.3 +pytest-asyncio==0.21.1 +pytest-cov==4.1.0 +pytest-xdist==3.5.0 + +# Playwright +playwright==1.40.0 + +# HTTP客户端 +httpx==0.25.2 +requests==2.31.0 + +# 数据处理 +pydantic==2.5.2 +pydantic-settings==2.1.0 +faker==20.1.0 + +# 配置管理 +python-dotenv==1.0.0 +pyyaml==6.0.1 + +# 测试报告 +allure-pytest==2.13.2 + +# 工具库 +loguru==0.7.2 diff --git a/e2e_tests/tests/__init__.py b/e2e_tests/tests/__init__.py new file mode 100644 index 0000000..412ecbc --- /dev/null +++ b/e2e_tests/tests/__init__.py @@ -0,0 +1 @@ +"""测试模块""" diff --git a/e2e_tests/tests/test_auth.py b/e2e_tests/tests/test_auth.py new file mode 100644 index 0000000..3e9534b --- /dev/null +++ b/e2e_tests/tests/test_auth.py @@ -0,0 +1,83 @@ +""" +认证测试用例 +""" + +import pytest +from api.auth_api import AuthAPI +from config.settings import settings + + +@pytest.mark.auth +@pytest.mark.smoke +class TestAuth: + """认证测试类""" + + @pytest.mark.asyncio + async def test_login_success(self, http_client): + """测试成功登录""" + auth_api = AuthAPI(http_client) + response = await auth_api.login(settings.TEST_USERNAME, settings.TEST_PASSWORD) + + assert response.status_code == 200 + data = response.json() + assert "accessToken" in data + assert "refreshToken" in data + assert isinstance(data["accessToken"], str) + assert isinstance(data["refreshToken"], str) + + @pytest.mark.asyncio + async def test_login_invalid_credentials(self, http_client): + """测试无效凭证登录""" + auth_api = AuthAPI(http_client) + response = await auth_api.login("invalid_user", "invalid_password") + + assert response.status_code == 401 + + @pytest.mark.asyncio + async def test_login_missing_fields(self, http_client): + """测试缺少必填字段""" + auth_api = AuthAPI(http_client) + response = await http_client.post("/api/auth/login", json={ + "username": "test" + }) + + assert response.status_code == 400 + + @pytest.mark.asyncio + async def test_refresh_token_success(self, http_client, auth_token): + """测试刷新token成功""" + auth_api = AuthAPI(http_client) + + login_response = await auth_api.login(settings.TEST_USERNAME, settings.TEST_PASSWORD) + refresh_token = login_response.json().get("refreshToken") + + response = await auth_api.refresh_token(refresh_token) + + assert response.status_code == 200 + data = response.json() + assert "accessToken" in data + assert "refreshToken" in data + + @pytest.mark.asyncio + async def test_refresh_token_invalid(self, http_client): + """测试无效刷新token""" + auth_api = AuthAPI(http_client) + response = await auth_api.refresh_token("invalid_refresh_token") + + assert response.status_code == 401 + + @pytest.mark.asyncio + async def test_logout_success(self, http_client, auth_token): + """测试登出成功""" + auth_api = AuthAPI(http_client) + response = await auth_api.logout(auth_token) + + assert response.status_code == 200 + + @pytest.mark.asyncio + async def test_logout_without_token(self, http_client): + """测试无token登出""" + auth_api = AuthAPI(http_client) + response = await http_client.post("/api/auth/logout") + + assert response.status_code == 400 diff --git a/e2e_tests/tests/test_dictionary.py b/e2e_tests/tests/test_dictionary.py new file mode 100644 index 0000000..bfdfaac --- /dev/null +++ b/e2e_tests/tests/test_dictionary.py @@ -0,0 +1,149 @@ +""" +字典管理测试用例 +""" + +import pytest +from api.dictionary_api import DictionaryAPI + + +@pytest.mark.dictionary +@pytest.mark.regression +class TestDictionary: + """字典管理测试类""" + + @pytest.mark.asyncio + async def test_create_dictionary_success(self, authenticated_client, test_dictionary_data, cleanup_dictionary): + """测试创建字典成功""" + dict_api = DictionaryAPI(authenticated_client) + response = await dict_api.create_dictionary(test_dictionary_data) + + assert response.status_code == 201 + data = response.json() + assert "id" in data + assert data["type"] == test_dictionary_data["type"] + assert data["code"] == test_dictionary_data["code"] + assert data["name"] == test_dictionary_data["name"] + + cleanup_dictionary.append(data["id"]) + + @pytest.mark.asyncio + async def test_create_dictionary_duplicate_type_code(self, authenticated_client, test_dictionary_data, cleanup_dictionary): + """测试创建重复类型和编码""" + dict_api = DictionaryAPI(authenticated_client) + + create_response = await dict_api.create_dictionary(test_dictionary_data) + dict_id = create_response.json()["id"] + + response = await dict_api.create_dictionary(test_dictionary_data) + + assert response.status_code in [400, 409] + + cleanup_dictionary.append(dict_id) + + @pytest.mark.asyncio + async def test_get_dictionary_by_id_success(self, authenticated_client, test_dictionary_data, cleanup_dictionary): + """测试根据ID获取字典成功""" + dict_api = DictionaryAPI(authenticated_client) + + create_response = await dict_api.create_dictionary(test_dictionary_data) + dict_id = create_response.json()["id"] + + response = await dict_api.get_dictionary_by_id(dict_id) + + assert response.status_code == 200 + data = response.json() + assert data["id"] == dict_id + assert data["type"] == test_dictionary_data["type"] + + cleanup_dictionary.append(dict_id) + + @pytest.mark.asyncio + async def test_get_dictionary_by_id_not_found(self, authenticated_client): + """测试获取不存在的字典""" + dict_api = DictionaryAPI(authenticated_client) + response = await dict_api.get_dictionary_by_id(999999) + + assert response.status_code == 404 + + @pytest.mark.asyncio + async def test_get_dictionaries_by_type_success(self, authenticated_client, test_dictionary_data, cleanup_dictionary): + """测试根据类型获取字典成功""" + dict_api = DictionaryAPI(authenticated_client) + + create_response = await dict_api.create_dictionary(test_dictionary_data) + dict_id = create_response.json()["id"] + + response = await dict_api.get_dictionaries_by_type(test_dictionary_data["type"]) + + assert response.status_code == 200 + data = response.json() + assert isinstance(data, list) + assert any(d["id"] == dict_id for d in data) + + cleanup_dictionary.append(dict_id) + + @pytest.mark.asyncio + async def test_get_all_dictionaries_success(self, authenticated_client): + """测试获取所有字典成功""" + dict_api = DictionaryAPI(authenticated_client) + response = await dict_api.get_all_dictionaries() + + assert response.status_code == 200 + data = response.json() + assert isinstance(data, list) + + @pytest.mark.asyncio + async def test_update_dictionary_success(self, authenticated_client, test_dictionary_data, cleanup_dictionary): + """测试更新字典成功""" + dict_api = DictionaryAPI(authenticated_client) + + create_response = await dict_api.create_dictionary(test_dictionary_data) + dict_id = create_response.json()["id"] + + update_data = {"name": "Updated name"} + response = await dict_api.update_dictionary(dict_id, update_data) + + assert response.status_code == 200 + data = response.json() + assert data["name"] == "Updated name" + + cleanup_dictionary.append(dict_id) + + @pytest.mark.asyncio + async def test_delete_dictionary_success(self, authenticated_client, test_dictionary_data, cleanup_dictionary): + """测试删除字典成功""" + dict_api = DictionaryAPI(authenticated_client) + + create_response = await dict_api.create_dictionary(test_dictionary_data) + dict_id = create_response.json()["id"] + + response = await dict_api.delete_dictionary(dict_id) + + assert response.status_code == 204 + + @pytest.mark.asyncio + async def test_check_type_and_code_exists_true(self, authenticated_client, test_dictionary_data, cleanup_dictionary): + """测试检查类型和编码存在-返回true""" + dict_api = DictionaryAPI(authenticated_client) + + create_response = await dict_api.create_dictionary(test_dictionary_data) + dict_id = create_response.json()["id"] + + response = await dict_api.check_type_and_code_exists( + test_dictionary_data["type"], + test_dictionary_data["code"] + ) + + assert response.status_code == 200 + assert response.json() is True + + cleanup_dictionary.append(dict_id) + + @pytest.mark.asyncio + async def test_check_type_and_code_exists_false(self, authenticated_client): + """测试检查类型和编码存在-返回false""" + dict_api = DictionaryAPI(authenticated_client) + response = await dict_api.check_type_and_code_exists("NONEXISTENT_TYPE", "NONEXISTENT_CODE") + + assert response.status_code == 200 + assert response.json() is False diff --git a/e2e_tests/tests/test_oauth2.py b/e2e_tests/tests/test_oauth2.py new file mode 100644 index 0000000..676bdd1 --- /dev/null +++ b/e2e_tests/tests/test_oauth2.py @@ -0,0 +1,127 @@ +""" +OAuth2客户端管理测试用例 +""" + +import pytest +from httpx import AsyncClient + + +@pytest.mark.oauth2 +@pytest.mark.regression +class TestOAuth2: + """OAuth2客户端管理测试类""" + + @pytest.fixture + def test_oauth2_client_data(self): + """测试OAuth2客户端数据""" + import time + timestamp = int(time.time() * 1000) + return { + "clientId": f"test-client-{timestamp}", + "clientSecret": "secret123", + "clientName": "Test Client", + "webServerRedirectUri": "http://localhost:8080/callback", + "scope": "read,write", + "authorizedGrantTypes": "authorization_code,refresh_token", + "accessTokenValiditySeconds": 7200, + "refreshTokenValiditySeconds": 2592000, + "autoApprove": False, + "enabled": True + } + + @pytest.fixture + async def cleanup_oauth2_client(self, authenticated_client: AsyncClient): + """清理测试OAuth2客户端""" + client_ids = [] + + yield client_ids + + for client_id in client_ids: + try: + await authenticated_client.delete(f"/api/oauth2/clients/{client_id}") + except Exception: + pass + + @pytest.mark.asyncio + async def test_create_oauth2_client_success(self, authenticated_client, test_oauth2_client_data, cleanup_oauth2_client): + """测试创建OAuth2客户端成功""" + response = await authenticated_client.post("/api/oauth2/clients", json=test_oauth2_client_data) + + assert response.status_code == 201 + data = response.json() + assert "id" in data + assert data["clientId"] == test_oauth2_client_data["clientId"] + assert data["clientName"] == test_oauth2_client_data["clientName"] + assert "clientSecret" not in data or data["clientSecret"] != test_oauth2_client_data["clientSecret"] + + cleanup_oauth2_client.append(data["id"]) + + @pytest.mark.asyncio + async def test_get_oauth2_client_by_id_success(self, authenticated_client, test_oauth2_client_data, cleanup_oauth2_client): + """测试根据ID获取OAuth2客户端成功""" + create_response = await authenticated_client.post("/api/oauth2/clients", json=test_oauth2_client_data) + client_id = create_response.json()["id"] + + response = await authenticated_client.get(f"/api/oauth2/clients/{client_id}") + + assert response.status_code == 200 + data = response.json() + assert data["id"] == client_id + assert data["clientId"] == test_oauth2_client_data["clientId"] + + cleanup_oauth2_client.append(client_id) + + @pytest.mark.asyncio + async def test_get_oauth2_client_by_id_not_found(self, authenticated_client): + """测试获取不存在的OAuth2客户端""" + response = await authenticated_client.get("/api/oauth2/clients/999999") + + assert response.status_code == 404 + + @pytest.mark.asyncio + async def test_get_oauth2_client_by_client_id_success(self, authenticated_client, test_oauth2_client_data, cleanup_oauth2_client): + """测试根据clientId获取OAuth2客户端成功""" + create_response = await authenticated_client.post("/api/oauth2/clients", json=test_oauth2_client_data) + client_id = create_response.json()["id"] + + response = await authenticated_client.get(f"/api/oauth2/clients/client-id/{test_oauth2_client_data['clientId']}") + + assert response.status_code == 200 + data = response.json() + assert data["clientId"] == test_oauth2_client_data["clientId"] + + cleanup_oauth2_client.append(client_id) + + @pytest.mark.asyncio + async def test_get_all_oauth2_clients_success(self, authenticated_client): + """测试获取所有OAuth2客户端成功""" + response = await authenticated_client.get("/api/oauth2/clients") + + assert response.status_code == 200 + data = response.json() + assert isinstance(data, list) + + @pytest.mark.asyncio + async def test_update_oauth2_client_success(self, authenticated_client, test_oauth2_client_data, cleanup_oauth2_client): + """测试更新OAuth2客户端成功""" + create_response = await authenticated_client.post("/api/oauth2/clients", json=test_oauth2_client_data) + client_id = create_response.json()["id"] + + update_data = {"clientName": "Updated Client Name"} + response = await authenticated_client.put(f"/api/oauth2/clients/{client_id}", json=update_data) + + assert response.status_code == 200 + data = response.json() + assert data["clientName"] == "Updated Client Name" + + cleanup_oauth2_client.append(client_id) + + @pytest.mark.asyncio + async def test_delete_oauth2_client_success(self, authenticated_client, test_oauth2_client_data, cleanup_oauth2_client): + """测试删除OAuth2客户端成功""" + create_response = await authenticated_client.post("/api/oauth2/clients", json=test_oauth2_client_data) + client_id = create_response.json()["id"] + + response = await authenticated_client.delete(f"/api/oauth2/clients/{client_id}") + + assert response.status_code == 204 diff --git a/e2e_tests/tests/test_role.py b/e2e_tests/tests/test_role.py new file mode 100644 index 0000000..386d3a2 --- /dev/null +++ b/e2e_tests/tests/test_role.py @@ -0,0 +1,185 @@ +""" +角色管理测试用例 +""" + +import pytest +from api.role_api import RoleAPI + + +@pytest.mark.role +@pytest.mark.regression +class TestRole: + """角色管理测试类""" + + @pytest.mark.asyncio + async def test_create_role_success(self, authenticated_client, test_role_data, cleanup_role): + """测试创建角色成功""" + role_api = RoleAPI(authenticated_client) + response = await role_api.create_role(test_role_data) + + assert response.status_code == 201 + data = response.json() + assert "id" in data + assert data["name"] == test_role_data["name"] + assert data["description"] == test_role_data["description"] + assert data["permissions"] == test_role_data["permissions"] + + cleanup_role.append(data["id"]) + + @pytest.mark.asyncio + async def test_create_role_duplicate_name(self, authenticated_client, test_role_data, cleanup_role): + """测试创建重复角色名""" + role_api = RoleAPI(authenticated_client) + + create_response = await role_api.create_role(test_role_data) + role_id = create_response.json()["id"] + + response = await role_api.create_role(test_role_data) + + assert response.status_code in [400, 409] + + cleanup_role.append(role_id) + + @pytest.mark.asyncio + async def test_get_role_by_id_success(self, authenticated_client, test_role_data, cleanup_role): + """测试根据ID获取角色成功""" + role_api = RoleAPI(authenticated_client) + + create_response = await role_api.create_role(test_role_data) + role_id = create_response.json()["id"] + + response = await role_api.get_role_by_id(role_id) + + assert response.status_code == 200 + data = response.json() + assert data["id"] == role_id + assert data["name"] == test_role_data["name"] + + cleanup_role.append(role_id) + + @pytest.mark.asyncio + async def test_get_role_by_id_not_found(self, authenticated_client): + """测试获取不存在的角色""" + role_api = RoleAPI(authenticated_client) + response = await role_api.get_role_by_id(999999) + + assert response.status_code == 404 + + @pytest.mark.asyncio + async def test_get_role_by_name_success(self, authenticated_client, test_role_data, cleanup_role): + """测试根据名称获取角色成功""" + role_api = RoleAPI(authenticated_client) + + create_response = await role_api.create_role(test_role_data) + role_id = create_response.json()["id"] + + response = await role_api.get_role_by_name(test_role_data["name"]) + + assert response.status_code == 200 + data = response.json() + assert data["name"] == test_role_data["name"] + + cleanup_role.append(role_id) + + @pytest.mark.asyncio + async def test_get_all_roles_success(self, authenticated_client): + """测试获取所有角色成功""" + role_api = RoleAPI(authenticated_client) + response = await role_api.get_all_roles() + + assert response.status_code == 200 + data = response.json() + assert isinstance(data, list) + + @pytest.mark.asyncio + async def test_update_role_success(self, authenticated_client, test_role_data, cleanup_role): + """测试更新角色成功""" + role_api = RoleAPI(authenticated_client) + + create_response = await role_api.create_role(test_role_data) + role_id = create_response.json()["id"] + + update_data = {"description": "Updated description"} + response = await role_api.update_role(role_id, update_data) + + assert response.status_code == 200 + data = response.json() + assert data["description"] == "Updated description" + + cleanup_role.append(role_id) + + @pytest.mark.asyncio + async def test_delete_role_success(self, authenticated_client, test_role_data, cleanup_role): + """测试删除角色成功""" + role_api = RoleAPI(authenticated_client) + + create_response = await role_api.create_role(test_role_data) + role_id = create_response.json()["id"] + + response = await role_api.delete_role(role_id) + + assert response.status_code == 204 + + @pytest.mark.asyncio + async def test_logical_delete_role_success(self, authenticated_client, test_role_data, cleanup_role): + """测试逻辑删除角色成功""" + role_api = RoleAPI(authenticated_client) + + create_response = await role_api.create_role(test_role_data) + role_id = create_response.json()["id"] + + response = await role_api.logical_delete_role(role_id) + + assert response.status_code == 200 + + get_response = await role_api.get_role_by_id(role_id) + assert get_response.status_code == 404 + + get_deleted_response = await role_api.get_all_roles(include_deleted=True) + deleted_roles = get_deleted_response.json() + assert any(r["id"] == role_id for r in deleted_roles) + + cleanup_role.append(role_id) + + @pytest.mark.asyncio + async def test_restore_role_success(self, authenticated_client, test_role_data, cleanup_role): + """测试恢复角色成功""" + role_api = RoleAPI(authenticated_client) + + create_response = await role_api.create_role(test_role_data) + role_id = create_response.json()["id"] + + await role_api.logical_delete_role(role_id) + + response = await role_api.restore_role(role_id) + + assert response.status_code == 200 + + get_response = await role_api.get_role_by_id(role_id) + assert get_response.status_code == 200 + + cleanup_role.append(role_id) + + @pytest.mark.asyncio + async def test_check_name_exists_true(self, authenticated_client, test_role_data, cleanup_role): + """测试检查角色名存在-返回true""" + role_api = RoleAPI(authenticated_client) + + create_response = await role_api.create_role(test_role_data) + role_id = create_response.json()["id"] + + response = await role_api.check_name_exists(test_role_data["name"]) + + assert response.status_code == 200 + assert response.json() is True + + cleanup_role.append(role_id) + + @pytest.mark.asyncio + async def test_check_name_exists_false(self, authenticated_client): + """测试检查角色名存在-返回false""" + role_api = RoleAPI(authenticated_client) + response = await role_api.check_name_exists("NONEXISTENT_ROLE") + + assert response.status_code == 200 + assert response.json() is False diff --git a/e2e_tests/tests/test_user.py b/e2e_tests/tests/test_user.py new file mode 100644 index 0000000..3b6f44e --- /dev/null +++ b/e2e_tests/tests/test_user.py @@ -0,0 +1,193 @@ +""" +用户管理测试用例 +""" + +import pytest +from api.user_api import UserAPI +from config.settings import settings + + +@pytest.mark.user +@pytest.mark.regression +class TestUser: + """用户管理测试类""" + + @pytest.mark.asyncio + async def test_create_user_success(self, authenticated_client, test_user_data, cleanup_user): + """测试创建用户成功""" + user_api = UserAPI(authenticated_client) + response = await user_api.create_user(test_user_data) + + print(f"Response status: {response.status_code}") + print(f"Response text: {response.text}") + + assert response.status_code == 201 + data = response.json() + assert "id" in data + assert data["username"] == test_user_data["username"] + assert data["email"] == test_user_data["email"] + assert "password" not in data or data["password"] != test_user_data["password"] + + cleanup_user.append(data["id"]) + + @pytest.mark.asyncio + async def test_create_user_duplicate_username(self, authenticated_client, test_user_data, cleanup_user): + """测试创建重复用户名""" + user_api = UserAPI(authenticated_client) + + await user_api.create_user(test_user_data) + response = await user_api.create_user(test_user_data) + + assert response.status_code in [400, 409] + + @pytest.mark.asyncio + async def test_get_user_by_id_success(self, authenticated_client, test_user_data, cleanup_user): + """测试根据ID获取用户成功""" + user_api = UserAPI(authenticated_client) + + create_response = await user_api.create_user(test_user_data) + user_id = create_response.json()["id"] + + response = await user_api.get_user_by_id(user_id) + + assert response.status_code == 200 + data = response.json() + assert data["id"] == user_id + assert data["username"] == test_user_data["username"] + + cleanup_user.append(user_id) + + @pytest.mark.asyncio + async def test_get_user_by_id_not_found(self, authenticated_client): + """测试获取不存在的用户""" + user_api = UserAPI(authenticated_client) + response = await user_api.get_user_by_id(999999) + + assert response.status_code == 404 + + @pytest.mark.asyncio + async def test_get_all_users_success(self, authenticated_client): + """测试获取所有用户成功""" + user_api = UserAPI(authenticated_client) + response = await user_api.get_all_users() + + assert response.status_code == 200 + data = response.json() + assert isinstance(data, list) + + @pytest.mark.asyncio + async def test_update_user_success(self, authenticated_client, test_user_data, cleanup_user): + """测试更新用户成功""" + user_api = UserAPI(authenticated_client) + + create_response = await user_api.create_user(test_user_data) + user_id = create_response.json()["id"] + + update_data = {"email": "updated@example.com"} + response = await user_api.update_user(user_id, update_data) + + assert response.status_code == 200 + data = response.json() + assert data["email"] == "updated@example.com" + + cleanup_user.append(user_id) + + @pytest.mark.asyncio + async def test_delete_user_success(self, authenticated_client, test_user_data, cleanup_user): + """测试删除用户成功""" + user_api = UserAPI(authenticated_client) + + create_response = await user_api.create_user(test_user_data) + user_id = create_response.json()["id"] + + response = await user_api.delete_user(user_id) + + assert response.status_code == 204 + + @pytest.mark.asyncio + async def test_logical_delete_user_success(self, authenticated_client, test_user_data, cleanup_user): + """测试逻辑删除用户成功""" + user_api = UserAPI(authenticated_client) + + create_response = await user_api.create_user(test_user_data) + user_id = create_response.json()["id"] + + response = await user_api.logical_delete_user(user_id) + + assert response.status_code == 200 + + get_response = await user_api.get_user_by_id(user_id) + assert get_response.status_code == 404 + + get_deleted_response = await user_api.get_all_users(include_deleted=True) + deleted_users = get_deleted_response.json() + assert any(u["id"] == user_id for u in deleted_users) + + cleanup_user.append(user_id) + + @pytest.mark.asyncio + async def test_restore_user_success(self, authenticated_client, test_user_data, cleanup_user): + """测试恢复用户成功""" + user_api = UserAPI(authenticated_client) + + create_response = await user_api.create_user(test_user_data) + user_id = create_response.json()["id"] + + await user_api.logical_delete_user(user_id) + + response = await user_api.restore_user(user_id) + + assert response.status_code == 200 + + get_response = await user_api.get_user_by_id(user_id) + assert get_response.status_code == 200 + + cleanup_user.append(user_id) + + @pytest.mark.asyncio + async def test_check_username_exists_true(self, authenticated_client, test_user_data, cleanup_user): + """测试检查用户名存在-返回true""" + user_api = UserAPI(authenticated_client) + + create_response = await user_api.create_user(test_user_data) + user_id = create_response.json()["id"] + + response = await user_api.check_username_exists(test_user_data["username"]) + + assert response.status_code == 200 + assert response.json() is True + + cleanup_user.append(user_id) + + @pytest.mark.asyncio + async def test_check_username_exists_false(self, authenticated_client): + """测试检查用户名存在-返回false""" + user_api = UserAPI(authenticated_client) + response = await user_api.check_username_exists("nonexistent_user") + + assert response.status_code == 200 + assert response.json() is False + + @pytest.mark.asyncio + async def test_check_email_exists_true(self, authenticated_client, test_user_data, cleanup_user): + """测试检查邮箱存在-返回true""" + user_api = UserAPI(authenticated_client) + + create_response = await user_api.create_user(test_user_data) + user_id = create_response.json()["id"] + + response = await user_api.check_email_exists(test_user_data["email"]) + + assert response.status_code == 200 + assert response.json() is True + + cleanup_user.append(user_id) + + @pytest.mark.asyncio + async def test_check_email_exists_false(self, authenticated_client): + """测试检查邮箱存在-返回false""" + user_api = UserAPI(authenticated_client) + response = await user_api.check_email_exists("nonexistent@example.com") + + assert response.status_code == 200 + assert response.json() is False diff --git a/e2e_tests/utils/__init__.py b/e2e_tests/utils/__init__.py new file mode 100644 index 0000000..548e274 --- /dev/null +++ b/e2e_tests/utils/__init__.py @@ -0,0 +1,3 @@ +""" +工具模块 +""" diff --git a/e2e_tests/utils/assertions.py b/e2e_tests/utils/assertions.py new file mode 100644 index 0000000..8458a6f --- /dev/null +++ b/e2e_tests/utils/assertions.py @@ -0,0 +1,83 @@ +""" +断言工具 +""" + +from typing import Any, Dict, List +from httpx import Response + + +class Assertions: + """断言工具类""" + + @staticmethod + def assert_status_code(response: Response, expected_status: int): + """断言状态码""" + assert response.status_code == expected_status, \ + f"Expected status code {expected_status}, got {response.status_code}. Response: {response.text}" + + @staticmethod + def assert_response_contains(response: Response, key: str, value: Any = None): + """断言响应包含指定字段""" + data = response.json() + assert key in data, f"Response does not contain key '{key}'. Response: {data}" + if value is not None: + assert data[key] == value, \ + f"Expected {value} for key '{key}', got {data[key]}" + + @staticmethod + def assert_response_is_list(response: Response): + """断言响应是列表""" + data = response.json() + assert isinstance(data, list), f"Expected list, got {type(data)}. Response: {data}" + + @staticmethod + def assert_response_not_empty(response: Response): + """断言响应不为空""" + data = response.json() + assert data, f"Response is empty. Response: {data}" + + @staticmethod + def assert_response_field_type(response: Response, field: str, expected_type: type): + """断言响应字段类型""" + data = response.json() + assert field in data, f"Response does not contain field '{field}'" + assert isinstance(data[field], expected_type), \ + f"Expected field '{field}' to be {expected_type}, got {type(data[field])}" + + @staticmethod + def assert_response_fields_present(response: Response, fields: List[str]): + """断言响应包含所有指定字段""" + data = response.json() + missing_fields = [field for field in fields if field not in data] + assert not missing_fields, \ + f"Response is missing fields: {missing_fields}. Response: {data}" + + @staticmethod + def assert_response_field_length(response: Response, field: str, min_length: int = None, max_length: int = None): + """断言响应字段长度""" + data = response.json() + assert field in data, f"Response does not contain field '{field}'" + field_value = data[field] + + if isinstance(field_value, (str, list, dict)): + length = len(field_value) + if min_length is not None: + assert length >= min_length, \ + f"Field '{field}' length {length} is less than minimum {min_length}" + if max_length is not None: + assert length <= max_length, \ + f"Field '{field}' length {length} is greater than maximum {max_length}" + else: + raise AssertionError(f"Field '{field}' is not a string, list, or dict") + + @staticmethod + def assert_error_response(response: Response, expected_message: str = None): + """断言错误响应""" + Assertions.assert_status_code(response, 400) + if expected_message: + data = response.json() + assert expected_message in str(data), \ + f"Expected error message '{expected_message}' not found in response: {data}" + + +assertions = Assertions() diff --git a/e2e_tests/utils/data_generator.py b/e2e_tests/utils/data_generator.py new file mode 100644 index 0000000..16fd57d --- /dev/null +++ b/e2e_tests/utils/data_generator.py @@ -0,0 +1,72 @@ +""" +测试数据生成器 +""" + +import random +import string +from faker import Faker + + +class DataGenerator: + """测试数据生成器""" + + def __init__(self, locale: str = "zh_CN"): + self.faker = Faker(locale) + + def generate_username(self) -> str: + """生成用户名""" + return f"testuser_{''.join(random.choices(string.ascii_lowercase + string.digits, k=8))}" + + def generate_password(self, length: int = 12) -> str: + """生成密码""" + chars = string.ascii_letters + string.digits + "!@#$%^&*" + return ''.join(random.choices(chars, k=length)) + + def generate_email(self) -> str: + """生成邮箱""" + return self.faker.email() + + def generate_phone(self) -> str: + """生成手机号""" + return self.faker.phone_number() + + def generate_name(self) -> str: + """生成姓名""" + return self.faker.name() + + def generate_role_name(self) -> str: + """生成角色名""" + return f"ROLE_{''.join(random.choices(string.ascii_uppercase, k=6))}" + + def generate_dict_type(self) -> str: + """生成字典类型""" + return f"DICT_TYPE_{''.join(random.choices(string.ascii_uppercase, k=4))}" + + def generate_dict_code(self) -> str: + """生成字典编码""" + return f"CODE_{''.join(random.choices(string.ascii_uppercase + string.digits, k=6))}" + + def generate_url(self) -> str: + """生成URL""" + return self.faker.url() + + def generate_company_name(self) -> str: + """生成公司名""" + return self.faker.company() + + def generate_address(self) -> str: + """生成地址""" + return self.faker.address() + + def generate_description(self) -> str: + """生成描述""" + return self.faker.text(max_nb_chars=200) + + def generate_permissions(self) -> str: + """生成权限字符串""" + permissions = ["READ", "WRITE", "DELETE", "ADMIN", "MANAGE"] + selected = random.sample(permissions, random.randint(1, len(permissions))) + return ",".join(selected) + + +data_generator = DataGenerator() diff --git a/e2e_tests/utils/logger.py b/e2e_tests/utils/logger.py new file mode 100644 index 0000000..7ed0d6b --- /dev/null +++ b/e2e_tests/utils/logger.py @@ -0,0 +1,33 @@ +""" +日志工具 +""" + +import sys +from loguru import logger +from pathlib import Path + + +def setup_logger(log_file: str = "e2e_tests.log", log_level: str = "INFO"): + """配置日志""" + logger.remove() + + logger.add( + sys.stdout, + format="{time:YYYY-MM-DD HH:mm:ss} | {level: <8} | {name}:{function}:{line} - {message}", + level=log_level, + colorize=True + ) + + logger.add( + log_file, + format="{time:YYYY-MM-DD HH:mm:ss} | {level: <8} | {name}:{function}:{line} - {message}", + level=log_level, + rotation="10 MB", + retention="7 days", + compression="zip" + ) + + return logger + + +setup_logger() diff --git a/novalon-manage-api/manage-sys/pom.xml b/novalon-manage-api/manage-sys/pom.xml new file mode 100644 index 0000000..6ddde54 --- /dev/null +++ b/novalon-manage-api/manage-sys/pom.xml @@ -0,0 +1,96 @@ + + + 4.0.0 + + + cn.novalon.manage + novalon-manage-api + 1.0.0 + + + manage-sys + jar + + Manage Sys + System Management Module + + + + org.springframework.boot + spring-boot-starter-webflux + + + org.springframework.boot + spring-boot-starter-data-r2dbc + + + org.springframework.boot + spring-boot-starter-validation + + + org.springframework.boot + spring-boot-starter-actuator + + + org.springframework.boot + spring-boot-starter-security + + + org.springframework.security + spring-security-config + + + com.google.guava + guava + + + com.github.ben-manes.caffeine + caffeine + + + org.apache.commons + commons-lang3 + + + io.jsonwebtoken + jjwt-api + + + io.jsonwebtoken + jjwt-impl + runtime + + + io.jsonwebtoken + jjwt-jackson + runtime + + + org.postgresql + postgresql + + + org.postgresql + r2dbc-postgresql + + + org.flywaydb + flyway-core + + + org.flywaydb + flyway-database-postgresql + + + org.springdoc + springdoc-openapi-starter-webflux-ui + + + org.springframework.boot + spring-boot-starter-test + test + + + diff --git a/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/ManageSysApplication.java b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/ManageSysApplication.java new file mode 100644 index 0000000..9f1c48a --- /dev/null +++ b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/ManageSysApplication.java @@ -0,0 +1,11 @@ +package cn.novalon.manage.sys; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class ManageSysApplication { + public static void main(String[] args) { + SpringApplication.run(ManageSysApplication.class, args); + } +} diff --git a/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/config/SecurityConfig.java b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/config/SecurityConfig.java new file mode 100644 index 0000000..c98b6db --- /dev/null +++ b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/config/SecurityConfig.java @@ -0,0 +1,31 @@ +package cn.novalon.manage.sys.config; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity; +import org.springframework.security.config.web.server.ServerHttpSecurity; +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; +import org.springframework.security.crypto.password.PasswordEncoder; +import org.springframework.security.web.server.SecurityWebFilterChain; + +@Configuration +@EnableWebFluxSecurity +public class SecurityConfig { + + @Bean + public PasswordEncoder passwordEncoder() { + return new BCryptPasswordEncoder(); + } + + @Bean + public SecurityWebFilterChain securityWebFilterChain(ServerHttpSecurity http) { + return http + .csrf(ServerHttpSecurity.CsrfSpec::disable) + .authorizeExchange(exchanges -> exchanges + .pathMatchers("/api/auth/**").permitAll() + .pathMatchers("/api/public/**").permitAll() + .anyExchange().authenticated() + ) + .build(); + } +} diff --git a/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/config/SystemWebSocketHandler.java b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/config/SystemWebSocketHandler.java new file mode 100644 index 0000000..88a5d0c --- /dev/null +++ b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/config/SystemWebSocketHandler.java @@ -0,0 +1,54 @@ +package cn.novalon.manage.sys.config; + +import org.springframework.stereotype.Component; +import org.springframework.web.socket.CloseStatus; +import org.springframework.web.socket.TextMessage; +import org.springframework.web.socket.WebSocketSession; +import org.springframework.web.socket.handler.TextWebSocketHandler; + +import java.io.IOException; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +@Component +public class SystemWebSocketHandler extends TextWebSocketHandler { + + private final Map sessions = new ConcurrentHashMap<>(); + + @Override + public void afterConnectionEstablished(WebSocketSession session) throws Exception { + sessions.put(session.getId(), session); + } + + @Override + public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception { + sessions.remove(session.getId()); + } + + @Override + protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception { + // Handle incoming messages if needed + } + + public void sendMessageToUser(String userId, String message) { + sessions.values().forEach(session -> { + try { + if (session.isOpen()) { + session.sendMessage(new TextMessage(message)); + } + } catch (IOException e) { + } + }); + } + + public void broadcast(String message) { + sessions.values().forEach(session -> { + try { + if (session.isOpen()) { + session.sendMessage(new TextMessage(message)); + } + } catch (IOException e) { + } + }); + } +} diff --git a/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/config/WebSocketConfig.java b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/config/WebSocketConfig.java new file mode 100644 index 0000000..e6bb529 --- /dev/null +++ b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/config/WebSocketConfig.java @@ -0,0 +1,23 @@ +package cn.novalon.manage.sys.config; + +import org.springframework.context.annotation.Configuration; +import org.springframework.web.socket.config.annotation.EnableWebSocket; +import org.springframework.web.socket.config.annotation.WebSocketConfigurer; +import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry; + +@Configuration +@EnableWebSocket +public class WebSocketConfig implements WebSocketConfigurer { + + private final SystemWebSocketHandler webSocketHandler; + + public WebSocketConfig(SystemWebSocketHandler webSocketHandler) { + this.webSocketHandler = webSocketHandler; + } + + @Override + public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) { + registry.addHandler(webSocketHandler, "/ws") + .setAllowedOrigins("*"); + } +} diff --git a/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/core/domain/BaseDomain.java b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/core/domain/BaseDomain.java new file mode 100644 index 0000000..2845ad2 --- /dev/null +++ b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/core/domain/BaseDomain.java @@ -0,0 +1,43 @@ +package cn.novalon.manage.sys.core.domain; + +import java.time.LocalDateTime; + +public abstract class BaseDomain { + + private Long id; + private LocalDateTime createdAt; + private LocalDateTime updatedAt; + private LocalDateTime deletedAt; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public LocalDateTime getCreatedAt() { + return createdAt; + } + + public void setCreatedAt(LocalDateTime createdAt) { + this.createdAt = createdAt; + } + + public LocalDateTime getUpdatedAt() { + return updatedAt; + } + + public void setUpdatedAt(LocalDateTime updatedAt) { + this.updatedAt = updatedAt; + } + + public LocalDateTime getDeletedAt() { + return deletedAt; + } + + public void setDeletedAt(LocalDateTime deletedAt) { + this.deletedAt = deletedAt; + } +} diff --git a/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/core/domain/OperationLog.java b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/core/domain/OperationLog.java new file mode 100644 index 0000000..a812863 --- /dev/null +++ b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/core/domain/OperationLog.java @@ -0,0 +1,86 @@ +package cn.novalon.manage.sys.core.domain; + +public class OperationLog extends BaseDomain { + + private String username; + private String operation; + private String method; + private String params; + private String result; + private String ip; + private Long duration; + private String status; + private String errorMsg; + + public String getUsername() { + return username; + } + + public void setUsername(String username) { + this.username = username; + } + + public String getOperation() { + return operation; + } + + public void setOperation(String operation) { + this.operation = operation; + } + + public String getMethod() { + return method; + } + + public void setMethod(String method) { + this.method = method; + } + + public String getParams() { + return params; + } + + public void setParams(String params) { + this.params = params; + } + + public String getResult() { + return result; + } + + public void setResult(String result) { + this.result = result; + } + + public String getIp() { + return ip; + } + + public void setIp(String ip) { + this.ip = ip; + } + + public Long getDuration() { + return duration; + } + + public void setDuration(Long duration) { + this.duration = duration; + } + + public String getStatus() { + return status; + } + + public void setStatus(String status) { + this.status = status; + } + + public String getErrorMsg() { + return errorMsg; + } + + public void setErrorMsg(String errorMsg) { + this.errorMsg = errorMsg; + } +} diff --git a/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/core/domain/SysConfig.java b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/core/domain/SysConfig.java new file mode 100644 index 0000000..fa2cd57 --- /dev/null +++ b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/core/domain/SysConfig.java @@ -0,0 +1,35 @@ +package cn.novalon.manage.sys.core.domain; + +import java.time.LocalDateTime; + +public class SysConfig { + + private Long id; + private String configName; + private String configKey; + private String configValue; + private String configType; + private String createBy; + private String updateBy; + private LocalDateTime createdAt; + private LocalDateTime updatedAt; + + public Long getId() { return id; } + public void setId(Long id) { this.id = id; } + public String getConfigName() { return configName; } + public void setConfigName(String configName) { this.configName = configName; } + public String getConfigKey() { return configKey; } + public void setConfigKey(String configKey) { this.configKey = configKey; } + public String getConfigValue() { return configValue; } + public void setConfigValue(String configValue) { this.configValue = configValue; } + public String getConfigType() { return configType; } + public void setConfigType(String configType) { this.configType = configType; } + public String getCreateBy() { return createBy; } + public void setCreateBy(String createBy) { this.createBy = createBy; } + public String getUpdateBy() { return updateBy; } + public void setUpdateBy(String updateBy) { this.updateBy = updateBy; } + public LocalDateTime getCreatedAt() { return createdAt; } + public void setCreatedAt(LocalDateTime createdAt) { this.createdAt = createdAt; } + public LocalDateTime getUpdatedAt() { return updatedAt; } + public void setUpdatedAt(LocalDateTime updatedAt) { this.updatedAt = updatedAt; } +} diff --git a/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/core/domain/SysDictData.java b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/core/domain/SysDictData.java new file mode 100644 index 0000000..160de93 --- /dev/null +++ b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/core/domain/SysDictData.java @@ -0,0 +1,50 @@ +package cn.novalon.manage.sys.core.domain; + +import java.time.LocalDateTime; + +public class SysDictData { + + private Long id; + private Long dictTypeId; + private String dictLabel; + private String dictValue; + private Integer dictSort; + private String dictType; + private String cssClass; + private String listClass; + private String isDefault; + private String status; + private String createBy; + private String updateBy; + private LocalDateTime createdAt; + private LocalDateTime updatedAt; + + public Long getId() { return id; } + public void setId(Long id) { this.id = id; } + public Long getDictTypeId() { return dictTypeId; } + public void setDictTypeId(Long dictTypeId) { this.dictTypeId = dictTypeId; } + public String getDictLabel() { return dictLabel; } + public void setDictLabel(String dictLabel) { this.dictLabel = dictLabel; } + public String getDictValue() { return dictValue; } + public void setDictValue(String dictValue) { this.dictValue = dictValue; } + public Integer getDictSort() { return dictSort; } + public void setDictSort(Integer dictSort) { this.dictSort = dictSort; } + public String getDictType() { return dictType; } + public void setDictType(String dictType) { this.dictType = dictType; } + public String getCssClass() { return cssClass; } + public void setCssClass(String cssClass) { this.cssClass = cssClass; } + public String getListClass() { return listClass; } + public void setListClass(String listClass) { this.listClass = listClass; } + public String getIsDefault() { return isDefault; } + public void setIsDefault(String isDefault) { this.isDefault = isDefault; } + public String getStatus() { return status; } + public void setStatus(String status) { this.status = status; } + public String getCreateBy() { return createBy; } + public void setCreateBy(String createBy) { this.createBy = createBy; } + public String getUpdateBy() { return updateBy; } + public void setUpdateBy(String updateBy) { this.updateBy = updateBy; } + public LocalDateTime getCreatedAt() { return createdAt; } + public void setCreatedAt(LocalDateTime createdAt) { this.createdAt = createdAt; } + public LocalDateTime getUpdatedAt() { return updatedAt; } + public void setUpdatedAt(LocalDateTime updatedAt) { this.updatedAt = updatedAt; } +} diff --git a/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/core/domain/SysDictType.java b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/core/domain/SysDictType.java new file mode 100644 index 0000000..72aa0d2 --- /dev/null +++ b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/core/domain/SysDictType.java @@ -0,0 +1,35 @@ +package cn.novalon.manage.sys.core.domain; + +import java.time.LocalDateTime; + +public class SysDictType { + + private Long id; + private String dictName; + private String dictType; + private String status; + private String remark; + private String createBy; + private String updateBy; + private LocalDateTime createdAt; + private LocalDateTime updatedAt; + + public Long getId() { return id; } + public void setId(Long id) { this.id = id; } + public String getDictName() { return dictName; } + public void setDictName(String dictName) { this.dictName = dictName; } + public String getDictType() { return dictType; } + public void setDictType(String dictType) { this.dictType = dictType; } + public String getStatus() { return status; } + public void setStatus(String status) { this.status = status; } + public String getRemark() { return remark; } + public void setRemark(String remark) { this.remark = remark; } + public String getCreateBy() { return createBy; } + public void setCreateBy(String createBy) { this.createBy = createBy; } + public String getUpdateBy() { return updateBy; } + public void setUpdateBy(String updateBy) { this.updateBy = updateBy; } + public LocalDateTime getCreatedAt() { return createdAt; } + public void setCreatedAt(LocalDateTime createdAt) { this.createdAt = createdAt; } + public LocalDateTime getUpdatedAt() { return updatedAt; } + public void setUpdatedAt(LocalDateTime updatedAt) { this.updatedAt = updatedAt; } +} diff --git a/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/core/domain/SysExceptionLog.java b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/core/domain/SysExceptionLog.java new file mode 100644 index 0000000..8c060f0 --- /dev/null +++ b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/core/domain/SysExceptionLog.java @@ -0,0 +1,38 @@ +package cn.novalon.manage.sys.core.domain; + +import java.time.LocalDateTime; + +public class SysExceptionLog { + + private Long id; + private String username; + private String title; + private String exceptionName; + private String methodName; + private String methodParams; + private String exceptionMsg; + private String exceptionStack; + private String ip; + private LocalDateTime createTime; + + public Long getId() { return id; } + public void setId(Long id) { this.id = id; } + public String getUsername() { return username; } + public void setUsername(String username) { this.username = username; } + public String getTitle() { return title; } + public void setTitle(String title) { this.title = title; } + public String getExceptionName() { return exceptionName; } + public void setExceptionName(String exceptionName) { this.exceptionName = exceptionName; } + public String getMethodName() { return methodName; } + public void setMethodName(String methodName) { this.methodName = methodName; } + public String getMethodParams() { return methodParams; } + public void setMethodParams(String methodParams) { this.methodParams = methodParams; } + public String getExceptionMsg() { return exceptionMsg; } + public void setExceptionMsg(String exceptionMsg) { this.exceptionMsg = exceptionMsg; } + public String getExceptionStack() { return exceptionStack; } + public void setExceptionStack(String exceptionStack) { this.exceptionStack = exceptionStack; } + public String getIp() { return ip; } + public void setIp(String ip) { this.ip = ip; } + public LocalDateTime getCreateTime() { return createTime; } + public void setCreateTime(LocalDateTime createTime) { this.createTime = createTime; } +} diff --git a/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/core/domain/SysFile.java b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/core/domain/SysFile.java new file mode 100644 index 0000000..a9bb329 --- /dev/null +++ b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/core/domain/SysFile.java @@ -0,0 +1,32 @@ +package cn.novalon.manage.sys.core.domain; + +import java.time.LocalDateTime; + +public class SysFile { + + private Long id; + private String fileName; + private String filePath; + private String fileSize; + private String fileType; + private String storageType; + private String createBy; + private LocalDateTime createdAt; + + public Long getId() { return id; } + public void setId(Long id) { this.id = id; } + public String getFileName() { return fileName; } + public void setFileName(String fileName) { this.fileName = fileName; } + public String getFilePath() { return filePath; } + public void setFilePath(String filePath) { this.filePath = filePath; } + public String getFileSize() { return fileSize; } + public void setFileSize(String fileSize) { this.fileSize = fileSize; } + public String getFileType() { return fileType; } + public void setFileType(String fileType) { this.fileType = fileType; } + public String getStorageType() { return storageType; } + public void setStorageType(String storageType) { this.storageType = storageType; } + public String getCreateBy() { return createBy; } + public void setCreateBy(String createBy) { this.createBy = createBy; } + public LocalDateTime getCreatedAt() { return createdAt; } + public void setCreatedAt(LocalDateTime createdAt) { this.createdAt = createdAt; } +} diff --git a/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/core/domain/SysLoginLog.java b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/core/domain/SysLoginLog.java new file mode 100644 index 0000000..10cd230 --- /dev/null +++ b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/core/domain/SysLoginLog.java @@ -0,0 +1,35 @@ +package cn.novalon.manage.sys.core.domain; + +import java.time.LocalDateTime; + +public class SysLoginLog { + + private Long id; + private String username; + private String ip; + private String location; + private String browser; + private String os; + private String status; + private String message; + private LocalDateTime loginTime; + + public Long getId() { return id; } + public void setId(Long id) { this.id = id; } + public String getUsername() { return username; } + public void setUsername(String username) { this.username = username; } + public String getIp() { return ip; } + public void setIp(String ip) { this.ip = ip; } + public String getLocation() { return location; } + public void setLocation(String location) { this.location = location; } + public String getBrowser() { return browser; } + public void setBrowser(String browser) { this.browser = browser; } + public String getOs() { return os; } + public void setOs(String os) { this.os = os; } + public String getStatus() { return status; } + public void setStatus(String status) { this.status = status; } + public String getMessage() { return message; } + public void setMessage(String message) { this.message = message; } + public LocalDateTime getLoginTime() { return loginTime; } + public void setLoginTime(LocalDateTime loginTime) { this.loginTime = loginTime; } +} diff --git a/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/core/domain/SysMenu.java b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/core/domain/SysMenu.java new file mode 100644 index 0000000..7a795fe --- /dev/null +++ b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/core/domain/SysMenu.java @@ -0,0 +1,79 @@ +package cn.novalon.manage.sys.core.domain; + +import java.util.List; + +public class SysMenu extends BaseDomain { + + private String menuName; + private Long parentId; + private Integer orderNum; + private String menuType; + private String perms; + private String component; + private String status; + private List children; + + public String getMenuName() { + return menuName; + } + + public void setMenuName(String menuName) { + this.menuName = menuName; + } + + public Long getParentId() { + return parentId; + } + + public void setParentId(Long parentId) { + this.parentId = parentId; + } + + public Integer getOrderNum() { + return orderNum; + } + + public void setOrderNum(Integer orderNum) { + this.orderNum = orderNum; + } + + public String getMenuType() { + return menuType; + } + + public void setMenuType(String menuType) { + this.menuType = menuType; + } + + public String getPerms() { + return perms; + } + + public void setPerms(String perms) { + this.perms = perms; + } + + public String getComponent() { + return component; + } + + public void setComponent(String component) { + this.component = component; + } + + public String getStatus() { + return status; + } + + public void setStatus(String status) { + this.status = status; + } + + public List getChildren() { + return children; + } + + public void setChildren(List children) { + this.children = children; + } +} diff --git a/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/core/domain/SysNotice.java b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/core/domain/SysNotice.java new file mode 100644 index 0000000..fd7480b --- /dev/null +++ b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/core/domain/SysNotice.java @@ -0,0 +1,35 @@ +package cn.novalon.manage.sys.core.domain; + +import java.time.LocalDateTime; + +public class SysNotice { + + private Long id; + private String noticeTitle; + private String noticeType; + private String noticeContent; + private String status; + private String createBy; + private String updateBy; + private LocalDateTime createdAt; + private LocalDateTime updatedAt; + + public Long getId() { return id; } + public void setId(Long id) { this.id = id; } + public String getNoticeTitle() { return noticeTitle; } + public void setNoticeTitle(String noticeTitle) { this.noticeTitle = noticeTitle; } + public String getNoticeType() { return noticeType; } + public void setNoticeType(String noticeType) { this.noticeType = noticeType; } + public String getNoticeContent() { return noticeContent; } + public void setNoticeContent(String noticeContent) { this.noticeContent = noticeContent; } + public String getStatus() { return status; } + public void setStatus(String status) { this.status = status; } + public String getCreateBy() { return createBy; } + public void setCreateBy(String createBy) { this.createBy = createBy; } + public String getUpdateBy() { return updateBy; } + public void setUpdateBy(String updateBy) { this.updateBy = updateBy; } + public LocalDateTime getCreatedAt() { return createdAt; } + public void setCreatedAt(LocalDateTime createdAt) { this.createdAt = createdAt; } + public LocalDateTime getUpdatedAt() { return updatedAt; } + public void setUpdatedAt(LocalDateTime updatedAt) { this.updatedAt = updatedAt; } +} diff --git a/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/core/domain/SysRole.java b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/core/domain/SysRole.java new file mode 100644 index 0000000..233edda --- /dev/null +++ b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/core/domain/SysRole.java @@ -0,0 +1,41 @@ +package cn.novalon.manage.sys.core.domain; + +public class SysRole extends BaseDomain { + + private String roleName; + private String roleKey; + private Integer roleSort; + private Integer status; + + public String getRoleName() { + return roleName; + } + + public void setRoleName(String roleName) { + this.roleName = roleName; + } + + public String getRoleKey() { + return roleKey; + } + + public void setRoleKey(String roleKey) { + this.roleKey = roleKey; + } + + public Integer getRoleSort() { + return roleSort; + } + + public void setRoleSort(Integer roleSort) { + this.roleSort = roleSort; + } + + public Integer getStatus() { + return status; + } + + public void setStatus(Integer status) { + this.status = status; + } +} diff --git a/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/core/domain/SysUser.java b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/core/domain/SysUser.java new file mode 100644 index 0000000..1fc364e --- /dev/null +++ b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/core/domain/SysUser.java @@ -0,0 +1,50 @@ +package cn.novalon.manage.sys.core.domain; + +public class SysUser extends BaseDomain { + + private String username; + private String password; + private String email; + private Long roleId; + private Integer status; + + public String getUsername() { + return username; + } + + public void setUsername(String username) { + this.username = username; + } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } + + public String getEmail() { + return email; + } + + public void setEmail(String email) { + this.email = email; + } + + public Long getRoleId() { + return roleId; + } + + public void setRoleId(Long roleId) { + this.roleId = roleId; + } + + public Integer getStatus() { + return status; + } + + public void setStatus(Integer status) { + this.status = status; + } +} diff --git a/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/core/domain/SysUserMessage.java b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/core/domain/SysUserMessage.java new file mode 100644 index 0000000..4eebbe2 --- /dev/null +++ b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/core/domain/SysUserMessage.java @@ -0,0 +1,29 @@ +package cn.novalon.manage.sys.core.domain; + +import java.time.LocalDateTime; + +public class SysUserMessage { + + private Long id; + private Long userId; + private String title; + private String content; + private String messageType; + private String isRead; + private LocalDateTime createTime; + + public Long getId() { return id; } + public void setId(Long id) { this.id = id; } + public Long getUserId() { return userId; } + public void setUserId(Long userId) { this.userId = userId; } + public String getTitle() { return title; } + public void setTitle(String title) { this.title = title; } + public String getContent() { return content; } + public void setContent(String content) { this.content = content; } + public String getMessageType() { return messageType; } + public void setMessageType(String messageType) { this.messageType = messageType; } + public String getIsRead() { return isRead; } + public void setIsRead(String isRead) { this.isRead = isRead; } + public LocalDateTime getCreateTime() { return createTime; } + public void setCreateTime(LocalDateTime createTime) { this.createTime = createTime; } +} diff --git a/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/core/repository/IOperationLogRepository.java b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/core/repository/IOperationLogRepository.java new file mode 100644 index 0000000..53add00 --- /dev/null +++ b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/core/repository/IOperationLogRepository.java @@ -0,0 +1,18 @@ +package cn.novalon.manage.sys.core.repository; + +import cn.novalon.manage.sys.core.domain.OperationLog; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; + +public interface IOperationLogRepository { + + Mono findById(Long id); + + Mono save(OperationLog operationLog); + + Mono deleteById(Long id); + + Flux findAll(); + + Flux findByUsername(String username); +} diff --git a/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/core/repository/ISysMenuRepository.java b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/core/repository/ISysMenuRepository.java new file mode 100644 index 0000000..9ae903c --- /dev/null +++ b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/core/repository/ISysMenuRepository.java @@ -0,0 +1,18 @@ +package cn.novalon.manage.sys.core.repository; + +import cn.novalon.manage.sys.core.domain.SysMenu; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; + +public interface ISysMenuRepository { + + Mono findById(Long id); + + Flux findAll(); + + Flux findByParentId(Long parentId); + + Mono save(SysMenu sysMenu); + + Mono deleteById(Long id); +} diff --git a/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/core/repository/ISysRoleRepository.java b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/core/repository/ISysRoleRepository.java new file mode 100644 index 0000000..2000308 --- /dev/null +++ b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/core/repository/ISysRoleRepository.java @@ -0,0 +1,16 @@ +package cn.novalon.manage.sys.core.repository; + +import cn.novalon.manage.sys.core.domain.SysRole; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; + +public interface ISysRoleRepository { + + Mono findById(Long id); + + Mono save(SysRole sysRole); + + Mono deleteById(Long id); + + Flux findAll(); +} diff --git a/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/core/repository/ISysUserRepository.java b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/core/repository/ISysUserRepository.java new file mode 100644 index 0000000..bb71503 --- /dev/null +++ b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/core/repository/ISysUserRepository.java @@ -0,0 +1,18 @@ +package cn.novalon.manage.sys.core.repository; + +import cn.novalon.manage.sys.core.domain.SysUser; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; + +public interface ISysUserRepository { + + Mono findByUsername(String username); + + Mono findById(Long id); + + Mono save(SysUser sysUser); + + Mono deleteById(Long id); + + Flux findAll(); +} diff --git a/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/core/service/IOperationLogService.java b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/core/service/IOperationLogService.java new file mode 100644 index 0000000..3c515ee --- /dev/null +++ b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/core/service/IOperationLogService.java @@ -0,0 +1,11 @@ +package cn.novalon.manage.sys.core.service; + +import cn.novalon.manage.sys.core.domain.OperationLog; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; + +public interface IOperationLogService { + Mono save(OperationLog log); + Flux findAll(); + Flux findByUsername(String username); +} diff --git a/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/core/service/ISysConfigService.java b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/core/service/ISysConfigService.java new file mode 100644 index 0000000..e9924b0 --- /dev/null +++ b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/core/service/ISysConfigService.java @@ -0,0 +1,14 @@ +package cn.novalon.manage.sys.core.service; + +import cn.novalon.manage.sys.core.domain.SysConfig; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; + +public interface ISysConfigService { + Flux findAll(); + Mono findById(Long id); + Mono findByConfigKey(String configKey); + Mono save(SysConfig config); + Mono deleteById(Long id); + Mono getConfigValue(String configKey); +} diff --git a/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/core/service/ISysDictDataService.java b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/core/service/ISysDictDataService.java new file mode 100644 index 0000000..f229997 --- /dev/null +++ b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/core/service/ISysDictDataService.java @@ -0,0 +1,14 @@ +package cn.novalon.manage.sys.core.service; + +import cn.novalon.manage.sys.core.domain.SysDictData; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; + +public interface ISysDictDataService { + Flux findAll(); + Flux findByDictType(String dictType); + Flux findByDictTypeAndStatus(String dictType, String status); + Mono findById(Long id); + Mono save(SysDictData dictData); + Mono deleteById(Long id); +} diff --git a/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/core/service/ISysDictTypeService.java b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/core/service/ISysDictTypeService.java new file mode 100644 index 0000000..802fd01 --- /dev/null +++ b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/core/service/ISysDictTypeService.java @@ -0,0 +1,13 @@ +package cn.novalon.manage.sys.core.service; + +import cn.novalon.manage.sys.core.domain.SysDictType; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; + +public interface ISysDictTypeService { + Flux findAll(); + Mono findById(Long id); + Mono findByDictType(String dictType); + Mono save(SysDictType dictType); + Mono deleteById(Long id); +} diff --git a/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/core/service/ISysExceptionLogService.java b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/core/service/ISysExceptionLogService.java new file mode 100644 index 0000000..9b2e25f --- /dev/null +++ b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/core/service/ISysExceptionLogService.java @@ -0,0 +1,14 @@ +package cn.novalon.manage.sys.core.service; + +import cn.novalon.manage.sys.core.domain.SysExceptionLog; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; + +import java.time.LocalDateTime; + +public interface ISysExceptionLogService { + Flux findAll(); + Flux findByUsername(String username); + Flux findByCreateTimeBetween(LocalDateTime startTime, LocalDateTime endTime); + Mono save(SysExceptionLog exceptionLog); +} diff --git a/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/core/service/ISysFileService.java b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/core/service/ISysFileService.java new file mode 100644 index 0000000..7b47959 --- /dev/null +++ b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/core/service/ISysFileService.java @@ -0,0 +1,14 @@ +package cn.novalon.manage.sys.core.service; + +import cn.novalon.manage.sys.core.domain.SysFile; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; +import org.springframework.web.multipart.MultipartFile; + +public interface ISysFileService { + Flux findAll(); + Flux findByCreateBy(String createBy); + Mono findById(Long id); + Mono upload(MultipartFile file, String createBy); + Mono deleteById(Long id); +} diff --git a/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/core/service/ISysLoginLogService.java b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/core/service/ISysLoginLogService.java new file mode 100644 index 0000000..551b56c --- /dev/null +++ b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/core/service/ISysLoginLogService.java @@ -0,0 +1,14 @@ +package cn.novalon.manage.sys.core.service; + +import cn.novalon.manage.sys.core.domain.SysLoginLog; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; + +import java.time.LocalDateTime; + +public interface ISysLoginLogService { + Flux findAll(); + Flux findByUsername(String username); + Flux findByLoginTimeBetween(LocalDateTime startTime, LocalDateTime endTime); + Mono save(SysLoginLog loginLog); +} diff --git a/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/core/service/ISysMenuService.java b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/core/service/ISysMenuService.java new file mode 100644 index 0000000..1750028 --- /dev/null +++ b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/core/service/ISysMenuService.java @@ -0,0 +1,15 @@ +package cn.novalon.manage.sys.core.service; + +import cn.novalon.manage.sys.core.domain.SysMenu; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; + +public interface ISysMenuService { + Mono findById(Long id); + Flux findAll(); + Flux findByParentId(Long parentId); + Mono createMenu(SysMenu menu); + Mono updateMenu(SysMenu menu); + Mono deleteMenu(Long id); + Flux buildMenuTree(Flux menus); +} diff --git a/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/core/service/ISysNoticeService.java b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/core/service/ISysNoticeService.java new file mode 100644 index 0000000..1050438 --- /dev/null +++ b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/core/service/ISysNoticeService.java @@ -0,0 +1,13 @@ +package cn.novalon.manage.sys.core.service; + +import cn.novalon.manage.sys.core.domain.SysNotice; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; + +public interface ISysNoticeService { + Flux findAll(); + Flux findByStatus(String status); + Mono findById(Long id); + Mono save(SysNotice notice); + Mono deleteById(Long id); +} diff --git a/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/core/service/ISysRoleService.java b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/core/service/ISysRoleService.java new file mode 100644 index 0000000..0cf4c0e --- /dev/null +++ b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/core/service/ISysRoleService.java @@ -0,0 +1,13 @@ +package cn.novalon.manage.sys.core.service; + +import cn.novalon.manage.sys.core.domain.SysRole; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; + +public interface ISysRoleService { + Mono findById(Long id); + Flux findAll(); + Mono createRole(SysRole role); + Mono updateRole(SysRole role); + Mono deleteRole(Long id); +} diff --git a/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/core/service/ISysUserMessageService.java b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/core/service/ISysUserMessageService.java new file mode 100644 index 0000000..648a380 --- /dev/null +++ b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/core/service/ISysUserMessageService.java @@ -0,0 +1,13 @@ +package cn.novalon.manage.sys.core.service; + +import cn.novalon.manage.sys.core.domain.SysUserMessage; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; + +public interface ISysUserMessageService { + Flux findByUserId(Long userId); + Flux findByUserIdAndIsRead(Long userId, String isRead); + Mono countUnread(Long userId); + Mono save(SysUserMessage message); + Mono markAsRead(Long id); +} diff --git a/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/core/service/ISysUserService.java b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/core/service/ISysUserService.java new file mode 100644 index 0000000..71e9d13 --- /dev/null +++ b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/core/service/ISysUserService.java @@ -0,0 +1,13 @@ +package cn.novalon.manage.sys.core.service; + +import cn.novalon.manage.sys.core.domain.SysUser; +import reactor.core.publisher.Mono; + +public interface ISysUserService { + Mono findById(Long id); + Mono findByUsername(String username); + Mono createUser(SysUser user); + Mono updateUser(SysUser user); + Mono deleteUser(Long id); + Mono changePassword(Long userId, String oldPassword, String newPassword); +} diff --git a/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/core/service/impl/OperationLogService.java b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/core/service/impl/OperationLogService.java new file mode 100644 index 0000000..7dbe61e --- /dev/null +++ b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/core/service/impl/OperationLogService.java @@ -0,0 +1,36 @@ +package cn.novalon.manage.sys.core.service.impl; + +import cn.novalon.manage.sys.core.domain.OperationLog; +import cn.novalon.manage.sys.core.repository.IOperationLogRepository; +import cn.novalon.manage.sys.core.service.IOperationLogService; +import org.springframework.stereotype.Service; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; + +import java.time.LocalDateTime; + +@Service +public class OperationLogService implements IOperationLogService { + + private final IOperationLogRepository logRepository; + + public OperationLogService(IOperationLogRepository logRepository) { + this.logRepository = logRepository; + } + + @Override + public Mono save(OperationLog log) { + log.setCreatedAt(LocalDateTime.now()); + return logRepository.save(log); + } + + @Override + public Flux findAll() { + return logRepository.findAll(); + } + + @Override + public Flux findByUsername(String username) { + return logRepository.findByUsername(username); + } +} diff --git a/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/core/service/impl/SysConfigServiceImpl.java b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/core/service/impl/SysConfigServiceImpl.java new file mode 100644 index 0000000..047467f --- /dev/null +++ b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/core/service/impl/SysConfigServiceImpl.java @@ -0,0 +1,56 @@ +package cn.novalon.manage.sys.core.service.impl; + +import cn.novalon.manage.sys.core.domain.SysConfig; +import cn.novalon.manage.sys.core.service.ISysConfigService; +import cn.novalon.manage.sys.infrastructure.db.converter.SysConfigConverter; +import cn.novalon.manage.sys.infrastructure.db.dao.SysConfigDao; +import org.springframework.stereotype.Service; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; + +@Service +public class SysConfigServiceImpl implements ISysConfigService { + + private final SysConfigDao dao; + private final SysConfigConverter converter; + + public SysConfigServiceImpl(SysConfigDao dao, SysConfigConverter converter) { + this.dao = dao; + this.converter = converter; + } + + @Override + public Flux findAll() { + return dao.findByDeletedAtIsNull() + .map(converter::toDomain); + } + + @Override + public Mono findById(Long id) { + return dao.findById(id) + .map(converter::toDomain); + } + + @Override + public Mono findByConfigKey(String configKey) { + return dao.findByConfigKeyAndDeletedAtIsNull(configKey) + .map(converter::toDomain); + } + + @Override + public Mono save(SysConfig config) { + return dao.save(converter.toEntity(config)) + .map(converter::toDomain); + } + + @Override + public Mono deleteById(Long id) { + return dao.deleteByIdAndDeletedAtIsNull(id); + } + + @Override + public Mono getConfigValue(String configKey) { + return findByConfigKey(configKey) + .map(SysConfig::getConfigValue); + } +} diff --git a/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/core/service/impl/SysDictDataServiceImpl.java b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/core/service/impl/SysDictDataServiceImpl.java new file mode 100644 index 0000000..3da65a1 --- /dev/null +++ b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/core/service/impl/SysDictDataServiceImpl.java @@ -0,0 +1,56 @@ +package cn.novalon.manage.sys.core.service.impl; + +import cn.novalon.manage.sys.core.domain.SysDictData; +import cn.novalon.manage.sys.core.service.ISysDictDataService; +import cn.novalon.manage.sys.infrastructure.db.converter.SysDictDataConverter; +import cn.novalon.manage.sys.infrastructure.db.dao.SysDictDataDao; +import org.springframework.stereotype.Service; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; + +@Service +public class SysDictDataServiceImpl implements ISysDictDataService { + + private final SysDictDataDao dao; + private final SysDictDataConverter converter; + + public SysDictDataServiceImpl(SysDictDataDao dao, SysDictDataConverter converter) { + this.dao = dao; + this.converter = converter; + } + + @Override + public Flux findAll() { + return dao.findByDeletedAtIsNull() + .map(converter::toDomain); + } + + @Override + public Flux findByDictType(String dictType) { + return dao.findByDictTypeAndDeletedAtIsNull(dictType) + .map(converter::toDomain); + } + + @Override + public Flux findByDictTypeAndStatus(String dictType, String status) { + return dao.findByDictTypeAndStatusAndDeletedAtIsNull(dictType, status) + .map(converter::toDomain); + } + + @Override + public Mono findById(Long id) { + return dao.findById(id) + .map(converter::toDomain); + } + + @Override + public Mono save(SysDictData dictData) { + return dao.save(converter.toEntity(dictData)) + .map(converter::toDomain); + } + + @Override + public Mono deleteById(Long id) { + return dao.deleteByIdAndDeletedAtIsNull(id); + } +} diff --git a/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/core/service/impl/SysDictTypeServiceImpl.java b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/core/service/impl/SysDictTypeServiceImpl.java new file mode 100644 index 0000000..424dbfc --- /dev/null +++ b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/core/service/impl/SysDictTypeServiceImpl.java @@ -0,0 +1,50 @@ +package cn.novalon.manage.sys.core.service.impl; + +import cn.novalon.manage.sys.core.domain.SysDictType; +import cn.novalon.manage.sys.core.service.ISysDictTypeService; +import cn.novalon.manage.sys.infrastructure.db.converter.SysDictTypeConverter; +import cn.novalon.manage.sys.infrastructure.db.dao.SysDictTypeDao; +import org.springframework.stereotype.Service; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; + +@Service +public class SysDictTypeServiceImpl implements ISysDictTypeService { + + private final SysDictTypeDao dao; + private final SysDictTypeConverter converter; + + public SysDictTypeServiceImpl(SysDictTypeDao dao, SysDictTypeConverter converter) { + this.dao = dao; + this.converter = converter; + } + + @Override + public Flux findAll() { + return dao.findByDeletedAtIsNull() + .map(converter::toDomain); + } + + @Override + public Mono findById(Long id) { + return dao.findById(id) + .map(converter::toDomain); + } + + @Override + public Mono findByDictType(String dictType) { + return dao.findByDictTypeAndDeletedAtIsNull(dictType) + .map(converter::toDomain); + } + + @Override + public Mono save(SysDictType dictType) { + return dao.save(converter.toEntity(dictType)) + .map(converter::toDomain); + } + + @Override + public Mono deleteById(Long id) { + return dao.deleteByIdAndDeletedAtIsNull(id); + } +} diff --git a/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/core/service/impl/SysExceptionLogServiceImpl.java b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/core/service/impl/SysExceptionLogServiceImpl.java new file mode 100644 index 0000000..da815f5 --- /dev/null +++ b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/core/service/impl/SysExceptionLogServiceImpl.java @@ -0,0 +1,47 @@ +package cn.novalon.manage.sys.core.service.impl; + +import cn.novalon.manage.sys.core.domain.SysExceptionLog; +import cn.novalon.manage.sys.core.service.ISysExceptionLogService; +import cn.novalon.manage.sys.infrastructure.db.converter.SysExceptionLogConverter; +import cn.novalon.manage.sys.infrastructure.db.dao.SysExceptionLogDao; +import org.springframework.stereotype.Service; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; + +import java.time.LocalDateTime; + +@Service +public class SysExceptionLogServiceImpl implements ISysExceptionLogService { + + private final SysExceptionLogDao dao; + private final SysExceptionLogConverter converter; + + public SysExceptionLogServiceImpl(SysExceptionLogDao dao, SysExceptionLogConverter converter) { + this.dao = dao; + this.converter = converter; + } + + @Override + public Flux findAll() { + return dao.findAllByOrderByCreateTimeDesc() + .map(converter::toDomain); + } + + @Override + public Flux findByUsername(String username) { + return dao.findByUsernameOrderByCreateTimeDesc(username) + .map(converter::toDomain); + } + + @Override + public Flux findByCreateTimeBetween(LocalDateTime startTime, LocalDateTime endTime) { + return dao.findByCreateTimeBetweenOrderByCreateTimeDesc(startTime, endTime) + .map(converter::toDomain); + } + + @Override + public Mono save(SysExceptionLog exceptionLog) { + return dao.save(converter.toEntity(exceptionLog)) + .map(converter::toDomain); + } +} diff --git a/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/core/service/impl/SysFileServiceImpl.java b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/core/service/impl/SysFileServiceImpl.java new file mode 100644 index 0000000..d08cf51 --- /dev/null +++ b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/core/service/impl/SysFileServiceImpl.java @@ -0,0 +1,78 @@ +package cn.novalon.manage.sys.core.service.impl; + +import cn.novalon.manage.sys.core.domain.SysFile; +import cn.novalon.manage.sys.core.service.ISysFileService; +import cn.novalon.manage.sys.infrastructure.db.converter.SysFileConverter; +import cn.novalon.manage.sys.infrastructure.db.dao.SysFileDao; +import org.springframework.stereotype.Service; +import org.springframework.web.multipart.MultipartFile; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; + +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.time.LocalDateTime; +import java.util.UUID; + +@Service +public class SysFileServiceImpl implements ISysFileService { + + private final SysFileDao dao; + private final SysFileConverter converter; + private final Path uploadPath = Paths.get("./uploads"); + + public SysFileServiceImpl(SysFileDao dao, SysFileConverter converter) { + this.dao = dao; + this.converter = converter; + } + + @Override + public Flux findAll() { + return dao.findByDeletedAtIsNullOrderByCreatedAtDesc() + .map(converter::toDomain); + } + + @Override + public Flux findByCreateBy(String createBy) { + return dao.findByCreateByOrderByCreatedAtDesc(createBy) + .map(converter::toDomain); + } + + @Override + public Mono findById(Long id) { + return dao.findById(id) + .map(converter::toDomain); + } + + @Override + public Mono upload(MultipartFile file, String createBy) { + try { + if (!Files.exists(uploadPath)) { + Files.createDirectories(uploadPath); + } + String fileName = UUID.randomUUID() + "_" + file.getOriginalFilename(); + Path filePath = uploadPath.resolve(fileName); + Files.copy(file.getInputStream(), filePath); + + SysFile sysFile = new SysFile(); + sysFile.setFileName(file.getOriginalFilename()); + sysFile.setFilePath("/api/files/download/" + fileName); + sysFile.setFileSize(String.valueOf(file.getSize())); + sysFile.setFileType(file.getContentType()); + sysFile.setStorageType("local"); + sysFile.setCreateBy(createBy); + sysFile.setCreatedAt(LocalDateTime.now()); + + return dao.save(converter.toEntity(sysFile)) + .map(converter::toDomain); + } catch (Exception e) { + return Mono.error(new RuntimeException("文件上传失败: " + e.getMessage())); + } + } + + @Override + public Mono deleteById(Long id) { + return dao.deleteByIdAndDeletedAtIsNull(id); + } +} diff --git a/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/core/service/impl/SysLoginLogServiceImpl.java b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/core/service/impl/SysLoginLogServiceImpl.java new file mode 100644 index 0000000..c0f899b --- /dev/null +++ b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/core/service/impl/SysLoginLogServiceImpl.java @@ -0,0 +1,47 @@ +package cn.novalon.manage.sys.core.service.impl; + +import cn.novalon.manage.sys.core.domain.SysLoginLog; +import cn.novalon.manage.sys.core.service.ISysLoginLogService; +import cn.novalon.manage.sys.infrastructure.db.converter.SysLoginLogConverter; +import cn.novalon.manage.sys.infrastructure.db.dao.SysLoginLogDao; +import org.springframework.stereotype.Service; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; + +import java.time.LocalDateTime; + +@Service +public class SysLoginLogServiceImpl implements ISysLoginLogService { + + private final SysLoginLogDao dao; + private final SysLoginLogConverter converter; + + public SysLoginLogServiceImpl(SysLoginLogDao dao, SysLoginLogConverter converter) { + this.dao = dao; + this.converter = converter; + } + + @Override + public Flux findAll() { + return dao.findAllByOrderByLoginTimeDesc() + .map(converter::toDomain); + } + + @Override + public Flux findByUsername(String username) { + return dao.findByUsernameOrderByLoginTimeDesc(username) + .map(converter::toDomain); + } + + @Override + public Flux findByLoginTimeBetween(LocalDateTime startTime, LocalDateTime endTime) { + return dao.findByLoginTimeBetweenOrderByLoginTimeDesc(startTime, endTime) + .map(converter::toDomain); + } + + @Override + public Mono save(SysLoginLog loginLog) { + return dao.save(converter.toEntity(loginLog)) + .map(converter::toDomain); + } +} diff --git a/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/core/service/impl/SysMenuService.java b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/core/service/impl/SysMenuService.java new file mode 100644 index 0000000..233fe33 --- /dev/null +++ b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/core/service/impl/SysMenuService.java @@ -0,0 +1,69 @@ +package cn.novalon.manage.sys.core.service.impl; + +import cn.novalon.manage.sys.core.domain.SysMenu; +import cn.novalon.manage.sys.core.repository.ISysMenuRepository; +import cn.novalon.manage.sys.core.service.ISysMenuService; +import org.springframework.stereotype.Service; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; + +import java.time.LocalDateTime; +import java.util.List; +import java.util.stream.Collectors; + +@Service +public class SysMenuService implements ISysMenuService { + + private final ISysMenuRepository menuRepository; + + public SysMenuService(ISysMenuRepository menuRepository) { + this.menuRepository = menuRepository; + } + + @Override + public Mono findById(Long id) { + return menuRepository.findById(id); + } + + @Override + public Flux findAll() { + return menuRepository.findAll(); + } + + @Override + public Flux findByParentId(Long parentId) { + return menuRepository.findByParentId(parentId); + } + + @Override + public Mono createMenu(SysMenu menu) { + menu.setCreatedAt(LocalDateTime.now()); + menu.setStatus("0"); + return menuRepository.save(menu); + } + + @Override + public Mono updateMenu(SysMenu menu) { + menu.setUpdatedAt(LocalDateTime.now()); + return menuRepository.save(menu); + } + + @Override + public Mono deleteMenu(Long id) { + return menuRepository.deleteById(id); + } + + @Override + public Flux buildMenuTree(Flux menus) { + return menus.collectList() + .map(list -> buildTree(list, 0L)) + .flatMapMany(Flux::fromIterable); + } + + private List buildTree(List menus, Long parentId) { + return menus.stream() + .filter(m -> m.getParentId().equals(parentId)) + .peek(m -> m.setChildren(buildTree(menus, m.getId()))) + .collect(Collectors.toList()); + } +} diff --git a/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/core/service/impl/SysNoticeServiceImpl.java b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/core/service/impl/SysNoticeServiceImpl.java new file mode 100644 index 0000000..3a2d3a2 --- /dev/null +++ b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/core/service/impl/SysNoticeServiceImpl.java @@ -0,0 +1,50 @@ +package cn.novalon.manage.sys.core.service.impl; + +import cn.novalon.manage.sys.core.domain.SysNotice; +import cn.novalon.manage.sys.core.service.ISysNoticeService; +import cn.novalon.manage.sys.infrastructure.db.converter.SysNoticeConverter; +import cn.novalon.manage.sys.infrastructure.db.dao.SysNoticeDao; +import org.springframework.stereotype.Service; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; + +@Service +public class SysNoticeServiceImpl implements ISysNoticeService { + + private final SysNoticeDao dao; + private final SysNoticeConverter converter; + + public SysNoticeServiceImpl(SysNoticeDao dao, SysNoticeConverter converter) { + this.dao = dao; + this.converter = converter; + } + + @Override + public Flux findAll() { + return dao.findByDeletedAtIsNull() + .map(converter::toDomain); + } + + @Override + public Flux findByStatus(String status) { + return dao.findByStatusAndDeletedAtIsNull(status) + .map(converter::toDomain); + } + + @Override + public Mono findById(Long id) { + return dao.findById(id) + .map(converter::toDomain); + } + + @Override + public Mono save(SysNotice notice) { + return dao.save(converter.toEntity(notice)) + .map(converter::toDomain); + } + + @Override + public Mono deleteById(Long id) { + return dao.deleteByIdAndDeletedAtIsNull(id); + } +} diff --git a/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/core/service/impl/SysRoleService.java b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/core/service/impl/SysRoleService.java new file mode 100644 index 0000000..de5ddf3 --- /dev/null +++ b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/core/service/impl/SysRoleService.java @@ -0,0 +1,48 @@ +package cn.novalon.manage.sys.core.service.impl; + +import cn.novalon.manage.sys.core.domain.SysRole; +import cn.novalon.manage.sys.core.repository.ISysRoleRepository; +import cn.novalon.manage.sys.core.service.ISysRoleService; +import org.springframework.stereotype.Service; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; + +import java.time.LocalDateTime; + +@Service +public class SysRoleService implements ISysRoleService { + + private final ISysRoleRepository roleRepository; + + public SysRoleService(ISysRoleRepository roleRepository) { + this.roleRepository = roleRepository; + } + + @Override + public Mono findById(Long id) { + return roleRepository.findById(id); + } + + @Override + public Flux findAll() { + return roleRepository.findAll(); + } + + @Override + public Mono createRole(SysRole role) { + role.setCreatedAt(LocalDateTime.now()); + role.setStatus(1); + return roleRepository.save(role); + } + + @Override + public Mono updateRole(SysRole role) { + role.setUpdatedAt(LocalDateTime.now()); + return roleRepository.save(role); + } + + @Override + public Mono deleteRole(Long id) { + return roleRepository.deleteById(id); + } +} diff --git a/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/core/service/impl/SysUserMessageServiceImpl.java b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/core/service/impl/SysUserMessageServiceImpl.java new file mode 100644 index 0000000..fce71a3 --- /dev/null +++ b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/core/service/impl/SysUserMessageServiceImpl.java @@ -0,0 +1,54 @@ +package cn.novalon.manage.sys.core.service.impl; + +import cn.novalon.manage.sys.core.domain.SysUserMessage; +import cn.novalon.manage.sys.core.service.ISysUserMessageService; +import cn.novalon.manage.sys.infrastructure.db.converter.SysUserMessageConverter; +import cn.novalon.manage.sys.infrastructure.db.dao.SysUserMessageDao; +import org.springframework.stereotype.Service; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; + +@Service +public class SysUserMessageServiceImpl implements ISysUserMessageService { + + private final SysUserMessageDao dao; + private final SysUserMessageConverter converter; + + public SysUserMessageServiceImpl(SysUserMessageDao dao, SysUserMessageConverter converter) { + this.dao = dao; + this.converter = converter; + } + + @Override + public Flux findByUserId(Long userId) { + return dao.findByUserIdOrderByCreateTimeDesc(userId) + .map(converter::toDomain); + } + + @Override + public Flux findByUserIdAndIsRead(Long userId, String isRead) { + return dao.findByUserIdAndIsReadOrderByCreateTimeDesc(userId, isRead) + .map(converter::toDomain); + } + + @Override + public Mono countUnread(Long userId) { + return dao.countByUserIdAndIsRead(userId, "0"); + } + + @Override + public Mono save(SysUserMessage message) { + return dao.save(converter.toEntity(message)) + .map(converter::toDomain); + } + + @Override + public Mono markAsRead(Long id) { + return dao.findById(id) + .flatMap(entity -> { + entity.setIsRead("1"); + return dao.save(entity); + }) + .then(); + } +} diff --git a/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/core/service/impl/SysUserService.java b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/core/service/impl/SysUserService.java new file mode 100644 index 0000000..9f35c5f --- /dev/null +++ b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/core/service/impl/SysUserService.java @@ -0,0 +1,64 @@ +package cn.novalon.manage.sys.core.service.impl; + +import cn.novalon.manage.sys.core.domain.SysUser; +import cn.novalon.manage.sys.core.repository.ISysUserRepository; +import cn.novalon.manage.sys.core.service.ISysUserService; +import org.springframework.security.crypto.password.PasswordEncoder; +import org.springframework.stereotype.Service; +import reactor.core.publisher.Mono; + +import java.time.LocalDateTime; + +@Service +public class SysUserService implements ISysUserService { + + private final ISysUserRepository userRepository; + private final PasswordEncoder passwordEncoder; + + public SysUserService(ISysUserRepository userRepository, PasswordEncoder passwordEncoder) { + this.userRepository = userRepository; + this.passwordEncoder = passwordEncoder; + } + + @Override + public Mono findById(Long id) { + return userRepository.findById(id); + } + + @Override + public Mono findByUsername(String username) { + return userRepository.findByUsername(username); + } + + @Override + public Mono createUser(SysUser user) { + user.setPassword(passwordEncoder.encode(user.getPassword())); + user.setCreatedAt(LocalDateTime.now()); + user.setStatus(1); + return userRepository.save(user); + } + + @Override + public Mono updateUser(SysUser user) { + user.setUpdatedAt(LocalDateTime.now()); + return userRepository.save(user); + } + + @Override + public Mono deleteUser(Long id) { + return userRepository.deleteById(id); + } + + @Override + public Mono changePassword(Long userId, String oldPassword, String newPassword) { + return userRepository.findById(userId) + .flatMap(user -> { + if (!passwordEncoder.matches(oldPassword, user.getPassword())) { + return Mono.error(new RuntimeException("旧密码不正确")); + } + user.setPassword(passwordEncoder.encode(newPassword)); + user.setUpdatedAt(LocalDateTime.now()); + return userRepository.save(user); + }); + } +} diff --git a/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/dto/request/LoginRequest.java b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/dto/request/LoginRequest.java new file mode 100644 index 0000000..c1cddfd --- /dev/null +++ b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/dto/request/LoginRequest.java @@ -0,0 +1,28 @@ +package cn.novalon.manage.sys.dto.request; + +import jakarta.validation.constraints.NotBlank; + +public class LoginRequest { + + @NotBlank(message = "用户名不能为空") + private String username; + + @NotBlank(message = "密码不能为空") + private String password; + + public String getUsername() { + return username; + } + + public void setUsername(String username) { + this.username = username; + } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } +} diff --git a/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/dto/request/PasswordChangeRequest.java b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/dto/request/PasswordChangeRequest.java new file mode 100644 index 0000000..25a39d4 --- /dev/null +++ b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/dto/request/PasswordChangeRequest.java @@ -0,0 +1,28 @@ +package cn.novalon.manage.sys.dto.request; + +import jakarta.validation.constraints.NotBlank; + +public class PasswordChangeRequest { + + @NotBlank(message = "旧密码不能为空") + private String oldPassword; + + @NotBlank(message = "新密码不能为空") + private String newPassword; + + public String getOldPassword() { + return oldPassword; + } + + public void setOldPassword(String oldPassword) { + this.oldPassword = oldPassword; + } + + public String getNewPassword() { + return newPassword; + } + + public void setNewPassword(String newPassword) { + this.newPassword = newPassword; + } +} diff --git a/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/dto/request/UserRegisterRequest.java b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/dto/request/UserRegisterRequest.java new file mode 100644 index 0000000..c40a770 --- /dev/null +++ b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/dto/request/UserRegisterRequest.java @@ -0,0 +1,43 @@ +package cn.novalon.manage.sys.dto.request; + +import jakarta.validation.constraints.Email; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.Size; + +public class UserRegisterRequest { + + @NotBlank(message = "用户名不能为空") + @Size(min = 3, max = 50, message = "用户名长度必须在3-50之间") + private String username; + + @NotBlank(message = "密码不能为空") + @Size(min = 6, max = 100, message = "密码长度必须在6-100之间") + private String password; + + @Email(message = "邮箱格式不正确") + private String email; + + public String getUsername() { + return username; + } + + public void setUsername(String username) { + this.username = username; + } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } + + public String getEmail() { + return email; + } + + public void setEmail(String email) { + this.email = email; + } +} diff --git a/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/dto/request/UserUpdateRequest.java b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/dto/request/UserUpdateRequest.java new file mode 100644 index 0000000..b9f7346 --- /dev/null +++ b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/dto/request/UserUpdateRequest.java @@ -0,0 +1,37 @@ +package cn.novalon.manage.sys.dto.request; + +import jakarta.validation.constraints.Email; + +public class UserUpdateRequest { + + private String email; + + private Integer status; + + private Long roleId; + + @Email(message = "邮箱格式不正确") + public String getEmail() { + return email; + } + + public void setEmail(String email) { + this.email = email; + } + + public Integer getStatus() { + return status; + } + + public void setStatus(Integer status) { + this.status = status; + } + + public Long getRoleId() { + return roleId; + } + + public void setRoleId(Long roleId) { + this.roleId = roleId; + } +} diff --git a/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/dto/response/AuthResponse.java b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/dto/response/AuthResponse.java new file mode 100644 index 0000000..5641e9b --- /dev/null +++ b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/dto/response/AuthResponse.java @@ -0,0 +1,41 @@ +package cn.novalon.manage.sys.dto.response; + +public class AuthResponse { + + private String token; + private Long userId; + private String username; + + public AuthResponse() { + } + + public AuthResponse(String token, Long userId, String username) { + this.token = token; + this.userId = userId; + this.username = username; + } + + public String getToken() { + return token; + } + + public void setToken(String token) { + this.token = token; + } + + public Long getUserId() { + return userId; + } + + public void setUserId(Long userId) { + this.userId = userId; + } + + public String getUsername() { + return username; + } + + public void setUsername(String username) { + this.username = username; + } +} diff --git a/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/dto/response/UserResponse.java b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/dto/response/UserResponse.java new file mode 100644 index 0000000..de2d4c9 --- /dev/null +++ b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/dto/response/UserResponse.java @@ -0,0 +1,82 @@ +package cn.novalon.manage.sys.dto.response; + +import java.time.LocalDateTime; + +public class UserResponse { + + private Long id; + private String username; + private String email; + private Long roleId; + private Integer status; + private LocalDateTime createdAt; + private LocalDateTime updatedAt; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getUsername() { + return username; + } + + public void setUsername(String username) { + this.username = username; + } + + public String getEmail() { + return email; + } + + public void setEmail(String email) { + this.email = email; + } + + public Long getRoleId() { + return roleId; + } + + public void setRoleId(Long roleId) { + this.roleId = roleId; + } + + public Integer getStatus() { + return status; + } + + public void setStatus(Integer status) { + this.status = status; + } + + public LocalDateTime getCreatedAt() { + return createdAt; + } + + public void setCreatedAt(LocalDateTime createdAt) { + this.createdAt = createdAt; + } + + public LocalDateTime getUpdatedAt() { + return updatedAt; + } + + public void setUpdatedAt(LocalDateTime updatedAt) { + this.updatedAt = updatedAt; + } + + public static UserResponse fromDomain(cn.novalon.manage.sys.core.domain.SysUser user) { + UserResponse response = new UserResponse(); + response.setId(user.getId()); + response.setUsername(user.getUsername()); + response.setEmail(user.getEmail()); + response.setRoleId(user.getRoleId()); + response.setStatus(user.getStatus()); + response.setCreatedAt(user.getCreatedAt()); + response.setUpdatedAt(user.getUpdatedAt()); + return response; + } +} diff --git a/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/handler/GlobalExceptionHandler.java b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/handler/GlobalExceptionHandler.java new file mode 100644 index 0000000..8d180a5 --- /dev/null +++ b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/handler/GlobalExceptionHandler.java @@ -0,0 +1,78 @@ +package cn.novalon.manage.sys.handler; + +import cn.novalon.manage.sys.core.domain.SysExceptionLog; +import cn.novalon.manage.sys.core.service.ISysExceptionLogService; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.RestControllerAdvice; +import org.springframework.web.context.request.WebRequest; + +import java.time.LocalDateTime; +import java.util.HashMap; +import java.util.Map; + +@RestControllerAdvice +public class GlobalExceptionHandler { + + private static final Logger logger = LoggerFactory.getLogger(GlobalExceptionHandler.class); + + private final ISysExceptionLogService exceptionLogService; + + public GlobalExceptionHandler(ISysExceptionLogService exceptionLogService) { + this.exceptionLogService = exceptionLogService; + } + + @ExceptionHandler(Exception.class) + public ResponseEntity> handleException(Exception ex, WebRequest request) { + logger.error("Exception occurred: ", ex); + + SysExceptionLog exceptionLog = new SysExceptionLog(); + exceptionLog.setTitle("System Exception"); + exceptionLog.setExceptionName(ex.getClass().getSimpleName()); + exceptionLog.setExceptionMsg(ex.getMessage()); + exceptionLog.setMethodName(request.getDescription(false)); + exceptionLog.setIp(getClientIp(request)); + exceptionLog.setCreateTime(LocalDateTime.now()); + + StringBuilder stackTrace = new StringBuilder(); + for (StackTraceElement element : ex.getStackTrace()) { + stackTrace.append(element.toString()).append("\n"); + } + exceptionLog.setExceptionStack(stackTrace.toString()); + + exceptionLogService.save(exceptionLog).subscribe(); + + Map response = new HashMap<>(); + response.put("code", HttpStatus.INTERNAL_SERVER_ERROR.value()); + response.put("message", ex.getMessage()); + response.put("timestamp", LocalDateTime.now()); + + return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(response); + } + + @ExceptionHandler(IllegalArgumentException.class) + public ResponseEntity> handleIllegalArgumentException(IllegalArgumentException ex, WebRequest request) { + logger.warn("Illegal argument: ", ex); + + Map response = new HashMap<>(); + response.put("code", HttpStatus.BAD_REQUEST.value()); + response.put("message", ex.getMessage()); + response.put("timestamp", LocalDateTime.now()); + + return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(response); + } + + private String getClientIp(WebRequest request) { + String ip = request.getHeader("X-Forwarded-For"); + if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) { + ip = request.getHeader("X-Real-IP"); + } + if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) { + ip = "127.0.0.1"; + } + return ip; + } +} diff --git a/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/handler/auth/SysAuthHandler.java b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/handler/auth/SysAuthHandler.java new file mode 100644 index 0000000..360e997 --- /dev/null +++ b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/handler/auth/SysAuthHandler.java @@ -0,0 +1,59 @@ +package cn.novalon.manage.sys.handler.auth; + +import cn.novalon.manage.sys.dto.request.LoginRequest; +import cn.novalon.manage.sys.dto.request.UserRegisterRequest; +import cn.novalon.manage.sys.dto.response.AuthResponse; +import cn.novalon.manage.sys.security.JwtTokenProvider; +import cn.novalon.manage.sys.core.domain.SysUser; +import cn.novalon.manage.sys.core.service.ISysUserService; +import jakarta.validation.Valid; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.security.crypto.password.PasswordEncoder; +import org.springframework.web.bind.annotation.*; +import reactor.core.publisher.Mono; + +@RestController +@RequestMapping("/api/auth") +public class SysAuthHandler { + + private final ISysUserService userService; + private final PasswordEncoder passwordEncoder; + private final JwtTokenProvider jwtTokenProvider; + + public SysAuthHandler(ISysUserService userService, PasswordEncoder passwordEncoder, JwtTokenProvider jwtTokenProvider) { + this.userService = userService; + this.passwordEncoder = passwordEncoder; + this.jwtTokenProvider = jwtTokenProvider; + } + + @PostMapping("/login") + public Mono> login(@Valid @RequestBody LoginRequest request) { + return userService.findByUsername(request.getUsername()) + .filter(user -> passwordEncoder.matches(request.getPassword(), user.getPassword())) + .filter(user -> 1 == user.getStatus()) + .map(user -> { + String token = jwtTokenProvider.generateToken(user.getUsername(), user.getId()); + AuthResponse response = new AuthResponse(token, user.getId(), user.getUsername()); + return ResponseEntity.ok(response); + }) + .defaultIfEmpty(ResponseEntity.status(HttpStatus.UNAUTHORIZED).build()); + } + + @PostMapping("/register") + public Mono> register(@Valid @RequestBody UserRegisterRequest request) { + SysUser user = new SysUser(); + user.setUsername(request.getUsername()); + user.setPassword(request.getPassword()); + user.setEmail(request.getEmail()); + return userService.findByUsername(request.getUsername()) + .flatMap(existing -> Mono.>error(new RuntimeException("用户名已存在"))) + .switchIfEmpty(userService.createUser(user) + .map(u -> ResponseEntity.status(HttpStatus.CREATED).body(u))); + } + + @PostMapping("/logout") + public Mono> logout() { + return Mono.just(ResponseEntity.ok().build()); + } +} diff --git a/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/handler/sys/SysConfigHandler.java b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/handler/sys/SysConfigHandler.java new file mode 100644 index 0000000..eb41875 --- /dev/null +++ b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/handler/sys/SysConfigHandler.java @@ -0,0 +1,62 @@ +package cn.novalon.manage.sys.handler.sys; + +import cn.novalon.manage.sys.core.domain.SysConfig; +import cn.novalon.manage.sys.core.service.ISysConfigService; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; + +import java.time.LocalDateTime; + +@RestController +@RequestMapping("/api/config") +public class SysConfigHandler { + + private final ISysConfigService configService; + + public SysConfigHandler(ISysConfigService configService) { + this.configService = configService; + } + + @GetMapping + public Flux getAllConfigs() { + return configService.findAll(); + } + + @GetMapping("/{id}") + public Mono> getConfigById(@PathVariable Long id) { + return configService.findById(id) + .map(config -> ResponseEntity.ok(config)) + .defaultIfEmpty(ResponseEntity.notFound().build()); + } + + @GetMapping("/key/{configKey}") + public Mono> getConfigByKey(@PathVariable String configKey) { + return configService.findByConfigKey(configKey) + .map(config -> ResponseEntity.ok(config)) + .defaultIfEmpty(ResponseEntity.notFound().build()); + } + + @PostMapping + public Mono> createConfig(@RequestBody SysConfig config) { + config.setConfigType("N"); + config.setCreatedAt(LocalDateTime.now()); + return configService.save(config) + .map(saved -> ResponseEntity.ok(saved)); + } + + @PutMapping("/{id}") + public Mono> updateConfig(@PathVariable Long id, @RequestBody SysConfig config) { + config.setId(id); + config.setUpdatedAt(LocalDateTime.now()); + return configService.save(config) + .map(saved -> ResponseEntity.ok(saved)); + } + + @DeleteMapping("/{id}") + public Mono> deleteConfig(@PathVariable Long id) { + return configService.deleteById(id) + .then(Mono.just(ResponseEntity.noContent().build())); + } +} diff --git a/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/handler/sys/SysDictHandler.java b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/handler/sys/SysDictHandler.java new file mode 100644 index 0000000..8e2f810 --- /dev/null +++ b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/handler/sys/SysDictHandler.java @@ -0,0 +1,62 @@ +package cn.novalon.manage.sys.handler.sys; + +import cn.novalon.manage.sys.core.domain.SysDictType; +import cn.novalon.manage.sys.core.service.ISysDictTypeService; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; + +import java.time.LocalDateTime; + +@RestController +@RequestMapping("/api/dict") +public class SysDictHandler { + + private final ISysDictTypeService dictTypeService; + + public SysDictHandler(ISysDictTypeService dictTypeService) { + this.dictTypeService = dictTypeService; + } + + @GetMapping("/types") + public Flux getAllDictTypes() { + return dictTypeService.findAll(); + } + + @GetMapping("/types/{id}") + public Mono> getDictTypeById(@PathVariable Long id) { + return dictTypeService.findById(id) + .map(dictType -> ResponseEntity.ok(dictType)) + .defaultIfEmpty(ResponseEntity.notFound().build()); + } + + @GetMapping("/types/type/{dictType}") + public Mono> getDictTypeByDictType(@PathVariable String dictType) { + return dictTypeService.findByDictType(dictType) + .map(dictTypeResult -> ResponseEntity.ok(dictTypeResult)) + .defaultIfEmpty(ResponseEntity.notFound().build()); + } + + @PostMapping("/types") + public Mono> createDictType(@RequestBody SysDictType dictType) { + dictType.setStatus("0"); + dictType.setCreatedAt(LocalDateTime.now()); + return dictTypeService.save(dictType) + .map(saved -> ResponseEntity.ok(saved)); + } + + @PutMapping("/types/{id}") + public Mono> updateDictType(@PathVariable Long id, @RequestBody SysDictType dictType) { + dictType.setId(id); + dictType.setUpdatedAt(LocalDateTime.now()); + return dictTypeService.save(dictType) + .map(saved -> ResponseEntity.ok(saved)); + } + + @DeleteMapping("/types/{id}") + public Mono> deleteDictType(@PathVariable Long id) { + return dictTypeService.deleteById(id) + .then(Mono.just(ResponseEntity.noContent().build())); + } +} diff --git a/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/handler/sys/SysFileHandler.java b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/handler/sys/SysFileHandler.java new file mode 100644 index 0000000..b7c3229 --- /dev/null +++ b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/handler/sys/SysFileHandler.java @@ -0,0 +1,88 @@ +package cn.novalon.manage.sys.handler.sys; + +import cn.novalon.manage.sys.core.domain.SysFile; +import cn.novalon.manage.sys.core.service.ISysFileService; +import org.springframework.core.io.Resource; +import org.springframework.core.io.UrlResource; +import org.springframework.http.HttpHeaders; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; + +import java.net.MalformedURLException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; + +@RestController +@RequestMapping("/api/files") +public class SysFileHandler { + + private final ISysFileService fileService; + private final Path uploadPath = Paths.get("./uploads"); + + public SysFileHandler(ISysFileService fileService) { + this.fileService = fileService; + } + + @GetMapping + public Flux getAllFiles() { + return fileService.findAll(); + } + + @GetMapping("/{id}") + public Mono> getFileById(@PathVariable Long id) { + return fileService.findById(id) + .map(file -> ResponseEntity.ok(file)) + .defaultIfEmpty(ResponseEntity.notFound().build()); + } + + @PostMapping("/upload") + public Mono> uploadFile(@RequestParam("file") MultipartFile file, + @RequestParam(value = "createBy", required = false, defaultValue = "anonymous") String createBy) { + return fileService.upload(file, createBy) + .map(saved -> ResponseEntity.ok(saved)); + } + + @GetMapping("/download/{fileName}") + public Mono downloadFile(@PathVariable String fileName) throws MalformedURLException { + Path filePath = uploadPath.resolve(fileName); + Resource resource = new UrlResource(filePath.toUri()); + return Mono.just(resource); + } + + @GetMapping("/preview/{fileName}") + public Mono> previewFile(@PathVariable String fileName) throws MalformedURLException { + return Mono.fromCallable(() -> { + Path filePath = uploadPath.resolve(fileName); + byte[] data = Files.readAllBytes(filePath); + return data; + }).map(data -> { + String contentType = "application/octet-stream"; + try { + contentType = Files.probeContentType(uploadPath.resolve(fileName)); + } catch (Exception e) { + } + return ResponseEntity.ok() + .contentType(MediaType.parseMediaType(contentType)) + .body(data); + }); + } + + @DeleteMapping("/{id}") + public Mono> deleteFile(@PathVariable Long id) { + return fileService.findById(id) + .flatMap(file -> { + try { + String fileName = file.getFilePath().substring(file.getFilePath().lastIndexOf("/") + 1); + Files.deleteIfExists(uploadPath.resolve(fileName)); + } catch (Exception e) { + } + return fileService.deleteById(id); + }) + .then(Mono.just(ResponseEntity.noContent().build())); + } +} diff --git a/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/handler/sys/SysLogHandler.java b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/handler/sys/SysLogHandler.java new file mode 100644 index 0000000..7e05846 --- /dev/null +++ b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/handler/sys/SysLogHandler.java @@ -0,0 +1,77 @@ +package cn.novalon.manage.sys.handler.sys; + +import cn.novalon.manage.sys.core.domain.SysLoginLog; +import cn.novalon.manage.sys.core.domain.SysExceptionLog; +import cn.novalon.manage.sys.core.service.ISysLoginLogService; +import cn.novalon.manage.sys.core.service.ISysExceptionLogService; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; + +import java.time.LocalDateTime; + +@RestController +@RequestMapping("/api/logs") +public class SysLogHandler { + + private final ISysLoginLogService loginLogService; + private final ISysExceptionLogService exceptionLogService; + + public SysLogHandler(ISysLoginLogService loginLogService, ISysExceptionLogService exceptionLogService) { + this.loginLogService = loginLogService; + this.exceptionLogService = exceptionLogService; + } + + @GetMapping("/login") + public Flux getLoginLogs() { + return loginLogService.findAll(); + } + + @GetMapping("/login/{id}") + public Mono> getLoginLogById(@PathVariable Long id) { + return loginLogService.findAll() + .filter(log -> log.getId().equals(id)) + .next() + .map(log -> ResponseEntity.ok(log)) + .defaultIfEmpty(ResponseEntity.notFound().build()); + } + + @PostMapping("/login") + public Mono> createLoginLog(@RequestBody SysLoginLog log) { + log.setLoginTime(LocalDateTime.now()); + return loginLogService.save(log) + .map(saved -> ResponseEntity.ok(saved)); + } + + @GetMapping("/login/user/{username}") + public Flux getLoginLogsByUsername(@PathVariable String username) { + return loginLogService.findByUsername(username); + } + + @GetMapping("/exception") + public Flux getExceptionLogs() { + return exceptionLogService.findAll(); + } + + @GetMapping("/exception/{id}") + public Mono> getExceptionLogById(@PathVariable Long id) { + return exceptionLogService.findAll() + .filter(log -> log.getId().equals(id)) + .next() + .map(log -> ResponseEntity.ok(log)) + .defaultIfEmpty(ResponseEntity.notFound().build()); + } + + @GetMapping("/exception/user/{username}") + public Flux getExceptionLogsByUsername(@PathVariable String username) { + return exceptionLogService.findByUsername(username); + } + + @PostMapping("/exception") + public Mono> createExceptionLog(@RequestBody SysExceptionLog log) { + log.setCreateTime(LocalDateTime.now()); + return exceptionLogService.save(log) + .map(saved -> ResponseEntity.ok(saved)); + } +} diff --git a/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/handler/sys/SysMenuHandler.java b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/handler/sys/SysMenuHandler.java new file mode 100644 index 0000000..e458c92 --- /dev/null +++ b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/handler/sys/SysMenuHandler.java @@ -0,0 +1,56 @@ +package cn.novalon.manage.sys.handler.sys; + +import cn.novalon.manage.sys.core.domain.SysMenu; +import cn.novalon.manage.sys.core.service.ISysMenuService; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; + +@RestController +@RequestMapping("/api/menus") +public class SysMenuHandler { + + private final ISysMenuService menuService; + + public SysMenuHandler(ISysMenuService menuService) { + this.menuService = menuService; + } + + @GetMapping + public Flux getAllMenus() { + return menuService.findAll(); + } + + @GetMapping("/tree") + public Flux getMenuTree() { + return menuService.buildMenuTree(menuService.findAll()); + } + + @GetMapping("/{id}") + public Mono> getMenuById(@PathVariable Long id) { + return menuService.findById(id) + .map(ResponseEntity::ok) + .defaultIfEmpty(ResponseEntity.notFound().build()); + } + + @PostMapping + public Mono> createMenu(@RequestBody SysMenu menu) { + return menuService.createMenu(menu) + .map(m -> ResponseEntity.status(HttpStatus.CREATED).body(m)); + } + + @PutMapping("/{id}") + public Mono> updateMenu(@PathVariable Long id, @RequestBody SysMenu menu) { + menu.setId(id); + return menuService.updateMenu(menu) + .map(ResponseEntity::ok); + } + + @DeleteMapping("/{id}") + public Mono> deleteMenu(@PathVariable Long id) { + return menuService.deleteMenu(id) + .then(Mono.just(ResponseEntity.noContent().build())); + } +} diff --git a/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/handler/sys/SysMessageHandler.java b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/handler/sys/SysMessageHandler.java new file mode 100644 index 0000000..0d67f90 --- /dev/null +++ b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/handler/sys/SysMessageHandler.java @@ -0,0 +1,47 @@ +package cn.novalon.manage.sys.handler.sys; + +import cn.novalon.manage.sys.core.domain.SysUserMessage; +import cn.novalon.manage.sys.core.service.ISysUserMessageService; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; + +@RestController +@RequestMapping("/api/messages") +public class SysMessageHandler { + + private final ISysUserMessageService messageService; + + public SysMessageHandler(ISysUserMessageService messageService) { + this.messageService = messageService; + } + + @GetMapping("/user/{userId}") + public Flux getMessagesByUserId(@PathVariable Long userId) { + return messageService.findByUserId(userId); + } + + @GetMapping("/user/{userId}/unread") + public Mono getUnreadCount(@PathVariable Long userId) { + return messageService.countUnread(userId); + } + + @GetMapping("/user/{userId}/unread/list") + public Flux getUnreadMessages(@PathVariable Long userId) { + return messageService.findByUserIdAndIsRead(userId, "0"); + } + + @PostMapping + public Mono> createMessage(@RequestBody SysUserMessage message) { + message.setIsRead("0"); + return messageService.save(message) + .map(saved -> ResponseEntity.ok(saved)); + } + + @PutMapping("/{id}/read") + public Mono> markAsRead(@PathVariable Long id) { + return messageService.markAsRead(id) + .then(Mono.just(ResponseEntity.ok().build())); + } +} diff --git a/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/handler/sys/SysNoticeHandler.java b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/handler/sys/SysNoticeHandler.java new file mode 100644 index 0000000..0cd44a3 --- /dev/null +++ b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/handler/sys/SysNoticeHandler.java @@ -0,0 +1,60 @@ +package cn.novalon.manage.sys.handler.sys; + +import cn.novalon.manage.sys.core.domain.SysNotice; +import cn.novalon.manage.sys.core.service.ISysNoticeService; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; + +import java.time.LocalDateTime; + +@RestController +@RequestMapping("/api/notices") +public class SysNoticeHandler { + + private final ISysNoticeService noticeService; + + public SysNoticeHandler(ISysNoticeService noticeService) { + this.noticeService = noticeService; + } + + @GetMapping + public Flux getAllNotices() { + return noticeService.findAll(); + } + + @GetMapping("/{id}") + public Mono> getNoticeById(@PathVariable Long id) { + return noticeService.findById(id) + .map(notice -> ResponseEntity.ok(notice)) + .defaultIfEmpty(ResponseEntity.notFound().build()); + } + + @GetMapping("/status/{status}") + public Flux getNoticesByStatus(@PathVariable String status) { + return noticeService.findByStatus(status); + } + + @PostMapping + public Mono> createNotice(@RequestBody SysNotice notice) { + notice.setStatus("0"); + notice.setCreatedAt(LocalDateTime.now()); + return noticeService.save(notice) + .map(saved -> ResponseEntity.ok(saved)); + } + + @PutMapping("/{id}") + public Mono> updateNotice(@PathVariable Long id, @RequestBody SysNotice notice) { + notice.setId(id); + notice.setUpdatedAt(LocalDateTime.now()); + return noticeService.save(notice) + .map(saved -> ResponseEntity.ok(saved)); + } + + @DeleteMapping("/{id}") + public Mono> deleteNotice(@PathVariable Long id) { + return noticeService.deleteById(id) + .then(Mono.just(ResponseEntity.noContent().build())); + } +} diff --git a/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/handler/sys/SysRoleHandler.java b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/handler/sys/SysRoleHandler.java new file mode 100644 index 0000000..65ba0d0 --- /dev/null +++ b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/handler/sys/SysRoleHandler.java @@ -0,0 +1,51 @@ +package cn.novalon.manage.sys.handler.sys; + +import cn.novalon.manage.sys.core.domain.SysRole; +import cn.novalon.manage.sys.core.service.ISysRoleService; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; + +@RestController +@RequestMapping("/api/roles") +public class SysRoleHandler { + + private final ISysRoleService roleService; + + public SysRoleHandler(ISysRoleService roleService) { + this.roleService = roleService; + } + + @GetMapping + public Flux getAllRoles() { + return roleService.findAll(); + } + + @GetMapping("/{id}") + public Mono> getRoleById(@PathVariable Long id) { + return roleService.findById(id) + .map(ResponseEntity::ok) + .defaultIfEmpty(ResponseEntity.notFound().build()); + } + + @PostMapping + public Mono> createRole(@RequestBody SysRole role) { + return roleService.createRole(role) + .map(r -> ResponseEntity.status(HttpStatus.CREATED).body(r)); + } + + @PutMapping("/{id}") + public Mono> updateRole(@PathVariable Long id, @RequestBody SysRole role) { + role.setId(id); + return roleService.updateRole(role) + .map(ResponseEntity::ok); + } + + @DeleteMapping("/{id}") + public Mono> deleteRole(@PathVariable Long id) { + return roleService.deleteRole(id) + .then(Mono.just(ResponseEntity.noContent().build())); + } +} diff --git a/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/handler/user/SysUserHandler.java b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/handler/user/SysUserHandler.java new file mode 100644 index 0000000..b8f579a --- /dev/null +++ b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/handler/user/SysUserHandler.java @@ -0,0 +1,75 @@ +package cn.novalon.manage.sys.handler.user; + +import cn.novalon.manage.sys.core.domain.SysUser; +import cn.novalon.manage.sys.core.service.ISysUserService; +import cn.novalon.manage.sys.dto.request.PasswordChangeRequest; +import cn.novalon.manage.sys.dto.request.UserUpdateRequest; +import jakarta.validation.Valid; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; +import reactor.core.publisher.Mono; + +@RestController +@RequestMapping("/api/users") +public class SysUserHandler { + + private final ISysUserService userService; + + public SysUserHandler(ISysUserService userService) { + this.userService = userService; + } + + @GetMapping("/{id}") + public Mono> getUserById(@PathVariable Long id) { + return userService.findById(id) + .map(ResponseEntity::ok) + .defaultIfEmpty(ResponseEntity.notFound().build()); + } + + @GetMapping("/username/{username}") + public Mono> getUserByUsername(@PathVariable String username) { + return userService.findByUsername(username) + .map(ResponseEntity::ok) + .defaultIfEmpty(ResponseEntity.notFound().build()); + } + + @PostMapping + public Mono> createUser(@RequestBody SysUser user) { + return userService.createUser(user) + .map(u -> ResponseEntity.status(HttpStatus.CREATED).body(u)); + } + + @PutMapping("/{id}") + public Mono> updateUser(@PathVariable Long id, @Valid @RequestBody UserUpdateRequest request) { + return userService.findById(id) + .flatMap(existing -> { + if (request.getEmail() != null) { + existing.setEmail(request.getEmail()); + } + if (request.getStatus() != null) { + existing.setStatus(request.getStatus()); + } + if (request.getRoleId() != null) { + existing.setRoleId(request.getRoleId()); + } + return userService.updateUser(existing); + }) + .map(ResponseEntity::ok) + .defaultIfEmpty(ResponseEntity.notFound().build()); + } + + @DeleteMapping("/{id}") + public Mono> deleteUser(@PathVariable Long id) { + return userService.deleteUser(id) + .then(Mono.just(ResponseEntity.noContent().build())); + } + + @PostMapping("/{id}/password") + public Mono> changePassword( + @PathVariable Long id, + @Valid @RequestBody PasswordChangeRequest request) { + return userService.changePassword(id, request.getOldPassword(), request.getNewPassword()) + .map(ResponseEntity::ok); + } +} diff --git a/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/infrastructure/db/converter/OperationLogConverter.java b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/infrastructure/db/converter/OperationLogConverter.java new file mode 100644 index 0000000..189748d --- /dev/null +++ b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/infrastructure/db/converter/OperationLogConverter.java @@ -0,0 +1,49 @@ +package cn.novalon.manage.sys.infrastructure.db.converter; + +import cn.novalon.manage.sys.core.domain.OperationLog; +import cn.novalon.manage.sys.infrastructure.db.entity.OperationLogEntity; + +public class OperationLogConverter { + + public OperationLog toDomain(OperationLogEntity entity) { + if (entity == null) { + return null; + } + OperationLog domain = new OperationLog(); + domain.setId(entity.getId()); + domain.setUsername(entity.getUsername()); + domain.setOperation(entity.getOperation()); + domain.setMethod(entity.getMethod()); + domain.setParams(entity.getParams()); + domain.setResult(entity.getResult()); + domain.setIp(entity.getIp()); + domain.setDuration(entity.getDuration()); + domain.setStatus(entity.getStatus()); + domain.setErrorMsg(entity.getErrorMsg()); + domain.setCreatedAt(entity.getCreatedAt()); + domain.setUpdatedAt(entity.getUpdatedAt()); + domain.setDeletedAt(entity.getDeletedAt()); + return domain; + } + + public OperationLogEntity toEntity(OperationLog domain) { + if (domain == null) { + return null; + } + OperationLogEntity entity = new OperationLogEntity(); + entity.setId(domain.getId()); + entity.setUsername(domain.getUsername()); + entity.setOperation(domain.getOperation()); + entity.setMethod(domain.getMethod()); + entity.setParams(domain.getParams()); + entity.setResult(domain.getResult()); + entity.setIp(domain.getIp()); + entity.setDuration(domain.getDuration()); + entity.setStatus(domain.getStatus()); + entity.setErrorMsg(domain.getErrorMsg()); + entity.setCreatedAt(domain.getCreatedAt()); + entity.setUpdatedAt(domain.getUpdatedAt()); + entity.setDeletedAt(domain.getDeletedAt()); + return entity; + } +} diff --git a/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/infrastructure/db/converter/SysConfigConverter.java b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/infrastructure/db/converter/SysConfigConverter.java new file mode 100644 index 0000000..3122a45 --- /dev/null +++ b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/infrastructure/db/converter/SysConfigConverter.java @@ -0,0 +1,41 @@ +package cn.novalon.manage.sys.infrastructure.db.converter; + +import cn.novalon.manage.sys.core.domain.SysConfig; +import cn.novalon.manage.sys.infrastructure.db.entity.SysConfigEntity; + +public class SysConfigConverter { + + public SysConfig toDomain(SysConfigEntity entity) { + if (entity == null) { + return null; + } + SysConfig domain = new SysConfig(); + domain.setId(entity.getId()); + domain.setConfigName(entity.getConfigName()); + domain.setConfigKey(entity.getConfigKey()); + domain.setConfigValue(entity.getConfigValue()); + domain.setConfigType(entity.getConfigType()); + domain.setCreateBy(entity.getCreateBy()); + domain.setUpdateBy(entity.getUpdateBy()); + domain.setCreatedAt(entity.getCreatedAt()); + domain.setUpdatedAt(entity.getUpdatedAt()); + return domain; + } + + public SysConfigEntity toEntity(SysConfig domain) { + if (domain == null) { + return null; + } + SysConfigEntity entity = new SysConfigEntity(); + entity.setId(domain.getId()); + entity.setConfigName(domain.getConfigName()); + entity.setConfigKey(domain.getConfigKey()); + entity.setConfigValue(domain.getConfigValue()); + entity.setConfigType(domain.getConfigType()); + entity.setCreateBy(domain.getCreateBy()); + entity.setUpdateBy(domain.getUpdateBy()); + entity.setCreatedAt(domain.getCreatedAt()); + entity.setUpdatedAt(domain.getUpdatedAt()); + return entity; + } +} diff --git a/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/infrastructure/db/converter/SysDictDataConverter.java b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/infrastructure/db/converter/SysDictDataConverter.java new file mode 100644 index 0000000..1e915ff --- /dev/null +++ b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/infrastructure/db/converter/SysDictDataConverter.java @@ -0,0 +1,49 @@ +package cn.novalon.manage.sys.infrastructure.db.converter; + +import cn.novalon.manage.sys.core.domain.SysDictData; +import cn.novalon.manage.sys.infrastructure.db.entity.SysDictDataEntity; + +public class SysDictDataConverter { + + public SysDictData toDomain(SysDictDataEntity entity) { + if (entity == null) { + return null; + } + SysDictData domain = new SysDictData(); + domain.setId(entity.getId()); + domain.setDictSort(entity.getDictSort()); + domain.setDictLabel(entity.getDictLabel()); + domain.setDictValue(entity.getDictValue()); + domain.setDictType(entity.getDictType()); + domain.setCssClass(entity.getCssClass()); + domain.setListClass(entity.getListClass()); + domain.setIsDefault(entity.getIsDefault()); + domain.setStatus(entity.getStatus()); + domain.setCreateBy(entity.getCreateBy()); + domain.setUpdateBy(entity.getUpdateBy()); + domain.setCreatedAt(entity.getCreatedAt()); + domain.setUpdatedAt(entity.getUpdatedAt()); + return domain; + } + + public SysDictDataEntity toEntity(SysDictData domain) { + if (domain == null) { + return null; + } + SysDictDataEntity entity = new SysDictDataEntity(); + entity.setId(domain.getId()); + entity.setDictSort(domain.getDictSort()); + entity.setDictLabel(domain.getDictLabel()); + entity.setDictValue(domain.getDictValue()); + entity.setDictType(domain.getDictType()); + entity.setCssClass(domain.getCssClass()); + entity.setListClass(domain.getListClass()); + entity.setIsDefault(domain.getIsDefault()); + entity.setStatus(domain.getStatus()); + entity.setCreateBy(domain.getCreateBy()); + entity.setUpdateBy(domain.getUpdateBy()); + entity.setCreatedAt(domain.getCreatedAt()); + entity.setUpdatedAt(domain.getUpdatedAt()); + return entity; + } +} diff --git a/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/infrastructure/db/converter/SysDictTypeConverter.java b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/infrastructure/db/converter/SysDictTypeConverter.java new file mode 100644 index 0000000..50ccff6 --- /dev/null +++ b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/infrastructure/db/converter/SysDictTypeConverter.java @@ -0,0 +1,41 @@ +package cn.novalon.manage.sys.infrastructure.db.converter; + +import cn.novalon.manage.sys.core.domain.SysDictType; +import cn.novalon.manage.sys.infrastructure.db.entity.SysDictTypeEntity; + +public class SysDictTypeConverter { + + public SysDictType toDomain(SysDictTypeEntity entity) { + if (entity == null) { + return null; + } + SysDictType domain = new SysDictType(); + domain.setId(entity.getId()); + domain.setDictName(entity.getDictName()); + domain.setDictType(entity.getDictType()); + domain.setStatus(entity.getStatus()); + domain.setRemark(entity.getRemark()); + domain.setCreateBy(entity.getCreateBy()); + domain.setUpdateBy(entity.getUpdateBy()); + domain.setCreatedAt(entity.getCreatedAt()); + domain.setUpdatedAt(entity.getUpdatedAt()); + return domain; + } + + public SysDictTypeEntity toEntity(SysDictType domain) { + if (domain == null) { + return null; + } + SysDictTypeEntity entity = new SysDictTypeEntity(); + entity.setId(domain.getId()); + entity.setDictName(domain.getDictName()); + entity.setDictType(domain.getDictType()); + entity.setStatus(domain.getStatus()); + entity.setRemark(domain.getRemark()); + entity.setCreateBy(domain.getCreateBy()); + entity.setUpdateBy(domain.getUpdateBy()); + entity.setCreatedAt(domain.getCreatedAt()); + entity.setUpdatedAt(domain.getUpdatedAt()); + return entity; + } +} diff --git a/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/infrastructure/db/converter/SysExceptionLogConverter.java b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/infrastructure/db/converter/SysExceptionLogConverter.java new file mode 100644 index 0000000..5bb7137 --- /dev/null +++ b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/infrastructure/db/converter/SysExceptionLogConverter.java @@ -0,0 +1,43 @@ +package cn.novalon.manage.sys.infrastructure.db.converter; + +import cn.novalon.manage.sys.core.domain.SysExceptionLog; +import cn.novalon.manage.sys.infrastructure.db.entity.SysExceptionLogEntity; + +public class SysExceptionLogConverter { + + public SysExceptionLog toDomain(SysExceptionLogEntity entity) { + if (entity == null) { + return null; + } + SysExceptionLog domain = new SysExceptionLog(); + domain.setId(entity.getId()); + domain.setUsername(entity.getUsername()); + domain.setTitle(entity.getTitle()); + domain.setExceptionName(entity.getExceptionName()); + domain.setMethodName(entity.getMethodName()); + domain.setMethodParams(entity.getMethodParams()); + domain.setExceptionMsg(entity.getExceptionMsg()); + domain.setExceptionStack(entity.getExceptionStack()); + domain.setIp(entity.getIp()); + domain.setCreateTime(entity.getCreateTime()); + return domain; + } + + public SysExceptionLogEntity toEntity(SysExceptionLog domain) { + if (domain == null) { + return null; + } + SysExceptionLogEntity entity = new SysExceptionLogEntity(); + entity.setId(domain.getId()); + entity.setUsername(domain.getUsername()); + entity.setTitle(domain.getTitle()); + entity.setExceptionName(domain.getExceptionName()); + entity.setMethodName(domain.getMethodName()); + entity.setMethodParams(domain.getMethodParams()); + entity.setExceptionMsg(domain.getExceptionMsg()); + entity.setExceptionStack(domain.getExceptionStack()); + entity.setIp(domain.getIp()); + entity.setCreateTime(domain.getCreateTime()); + return entity; + } +} diff --git a/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/infrastructure/db/converter/SysFileConverter.java b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/infrastructure/db/converter/SysFileConverter.java new file mode 100644 index 0000000..b60647a --- /dev/null +++ b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/infrastructure/db/converter/SysFileConverter.java @@ -0,0 +1,39 @@ +package cn.novalon.manage.sys.infrastructure.db.converter; + +import cn.novalon.manage.sys.core.domain.SysFile; +import cn.novalon.manage.sys.infrastructure.db.entity.SysFileEntity; + +public class SysFileConverter { + + public SysFile toDomain(SysFileEntity entity) { + if (entity == null) { + return null; + } + SysFile domain = new SysFile(); + domain.setId(entity.getId()); + domain.setFileName(entity.getFileName()); + domain.setFilePath(entity.getFilePath()); + domain.setFileSize(entity.getFileSize()); + domain.setFileType(entity.getFileType()); + domain.setStorageType(entity.getStorageType()); + domain.setCreateBy(entity.getCreateBy()); + domain.setCreatedAt(entity.getCreatedAt()); + return domain; + } + + public SysFileEntity toEntity(SysFile domain) { + if (domain == null) { + return null; + } + SysFileEntity entity = new SysFileEntity(); + entity.setId(domain.getId()); + entity.setFileName(domain.getFileName()); + entity.setFilePath(domain.getFilePath()); + entity.setFileSize(domain.getFileSize()); + entity.setFileType(domain.getFileType()); + entity.setStorageType(domain.getStorageType()); + entity.setCreateBy(domain.getCreateBy()); + entity.setCreatedAt(domain.getCreatedAt()); + return entity; + } +} diff --git a/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/infrastructure/db/converter/SysLoginLogConverter.java b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/infrastructure/db/converter/SysLoginLogConverter.java new file mode 100644 index 0000000..9227273 --- /dev/null +++ b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/infrastructure/db/converter/SysLoginLogConverter.java @@ -0,0 +1,41 @@ +package cn.novalon.manage.sys.infrastructure.db.converter; + +import cn.novalon.manage.sys.core.domain.SysLoginLog; +import cn.novalon.manage.sys.infrastructure.db.entity.SysLoginLogEntity; + +public class SysLoginLogConverter { + + public SysLoginLog toDomain(SysLoginLogEntity entity) { + if (entity == null) { + return null; + } + SysLoginLog domain = new SysLoginLog(); + domain.setId(entity.getId()); + domain.setUsername(entity.getUsername()); + domain.setIp(entity.getIp()); + domain.setLocation(entity.getLocation()); + domain.setBrowser(entity.getBrowser()); + domain.setOs(entity.getOs()); + domain.setStatus(entity.getStatus()); + domain.setMessage(entity.getMessage()); + domain.setLoginTime(entity.getLoginTime()); + return domain; + } + + public SysLoginLogEntity toEntity(SysLoginLog domain) { + if (domain == null) { + return null; + } + SysLoginLogEntity entity = new SysLoginLogEntity(); + entity.setId(domain.getId()); + entity.setUsername(domain.getUsername()); + entity.setIp(domain.getIp()); + entity.setLocation(domain.getLocation()); + entity.setBrowser(domain.getBrowser()); + entity.setOs(domain.getOs()); + entity.setStatus(domain.getStatus()); + entity.setMessage(domain.getMessage()); + entity.setLoginTime(domain.getLoginTime()); + return entity; + } +} diff --git a/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/infrastructure/db/converter/SysMenuConverter.java b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/infrastructure/db/converter/SysMenuConverter.java new file mode 100644 index 0000000..e82c900 --- /dev/null +++ b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/infrastructure/db/converter/SysMenuConverter.java @@ -0,0 +1,45 @@ +package cn.novalon.manage.sys.infrastructure.db.converter; + +import cn.novalon.manage.sys.core.domain.SysMenu; +import cn.novalon.manage.sys.infrastructure.db.entity.SysMenuEntity; + +public class SysMenuConverter { + + public SysMenu toDomain(SysMenuEntity entity) { + if (entity == null) { + return null; + } + SysMenu domain = new SysMenu(); + domain.setId(entity.getId()); + domain.setMenuName(entity.getMenuName()); + domain.setParentId(entity.getParentId()); + domain.setOrderNum(entity.getOrderNum()); + domain.setMenuType(entity.getMenuType()); + domain.setPerms(entity.getPerms()); + domain.setComponent(entity.getComponent()); + domain.setStatus(entity.getStatus()); + domain.setCreatedAt(entity.getCreatedAt()); + domain.setUpdatedAt(entity.getUpdatedAt()); + domain.setDeletedAt(entity.getDeletedAt()); + return domain; + } + + public SysMenuEntity toEntity(SysMenu domain) { + if (domain == null) { + return null; + } + SysMenuEntity entity = new SysMenuEntity(); + entity.setId(domain.getId()); + entity.setMenuName(domain.getMenuName()); + entity.setParentId(domain.getParentId()); + entity.setOrderNum(domain.getOrderNum()); + entity.setMenuType(domain.getMenuType()); + entity.setPerms(domain.getPerms()); + entity.setComponent(domain.getComponent()); + entity.setStatus(domain.getStatus()); + entity.setCreatedAt(domain.getCreatedAt()); + entity.setUpdatedAt(domain.getUpdatedAt()); + entity.setDeletedAt(domain.getDeletedAt()); + return entity; + } +} diff --git a/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/infrastructure/db/converter/SysNoticeConverter.java b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/infrastructure/db/converter/SysNoticeConverter.java new file mode 100644 index 0000000..be40fb6 --- /dev/null +++ b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/infrastructure/db/converter/SysNoticeConverter.java @@ -0,0 +1,41 @@ +package cn.novalon.manage.sys.infrastructure.db.converter; + +import cn.novalon.manage.sys.core.domain.SysNotice; +import cn.novalon.manage.sys.infrastructure.db.entity.SysNoticeEntity; + +public class SysNoticeConverter { + + public SysNotice toDomain(SysNoticeEntity entity) { + if (entity == null) { + return null; + } + SysNotice domain = new SysNotice(); + domain.setId(entity.getId()); + domain.setNoticeTitle(entity.getNoticeTitle()); + domain.setNoticeType(entity.getNoticeType()); + domain.setNoticeContent(entity.getNoticeContent()); + domain.setStatus(entity.getStatus()); + domain.setCreateBy(entity.getCreateBy()); + domain.setUpdateBy(entity.getUpdateBy()); + domain.setCreatedAt(entity.getCreatedAt()); + domain.setUpdatedAt(entity.getUpdatedAt()); + return domain; + } + + public SysNoticeEntity toEntity(SysNotice domain) { + if (domain == null) { + return null; + } + SysNoticeEntity entity = new SysNoticeEntity(); + entity.setId(domain.getId()); + entity.setNoticeTitle(domain.getNoticeTitle()); + entity.setNoticeType(domain.getNoticeType()); + entity.setNoticeContent(domain.getNoticeContent()); + entity.setStatus(domain.getStatus()); + entity.setCreateBy(domain.getCreateBy()); + entity.setUpdateBy(domain.getUpdateBy()); + entity.setCreatedAt(domain.getCreatedAt()); + entity.setUpdatedAt(domain.getUpdatedAt()); + return entity; + } +} diff --git a/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/infrastructure/db/converter/SysRoleConverter.java b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/infrastructure/db/converter/SysRoleConverter.java new file mode 100644 index 0000000..8f6862d --- /dev/null +++ b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/infrastructure/db/converter/SysRoleConverter.java @@ -0,0 +1,39 @@ +package cn.novalon.manage.sys.infrastructure.db.converter; + +import cn.novalon.manage.sys.core.domain.SysRole; +import cn.novalon.manage.sys.infrastructure.db.entity.SysRoleEntity; + +public class SysRoleConverter { + + public SysRole toDomain(SysRoleEntity entity) { + if (entity == null) { + return null; + } + SysRole domain = new SysRole(); + domain.setId(entity.getId()); + domain.setRoleName(entity.getRoleName()); + domain.setRoleKey(entity.getRoleKey()); + domain.setRoleSort(entity.getRoleSort()); + domain.setStatus(entity.getStatus()); + domain.setCreatedAt(entity.getCreatedAt()); + domain.setUpdatedAt(entity.getUpdatedAt()); + domain.setDeletedAt(entity.getDeletedAt()); + return domain; + } + + public SysRoleEntity toEntity(SysRole domain) { + if (domain == null) { + return null; + } + SysRoleEntity entity = new SysRoleEntity(); + entity.setId(domain.getId()); + entity.setRoleName(domain.getRoleName()); + entity.setRoleKey(domain.getRoleKey()); + entity.setRoleSort(domain.getRoleSort()); + entity.setStatus(domain.getStatus()); + entity.setCreatedAt(domain.getCreatedAt()); + entity.setUpdatedAt(domain.getUpdatedAt()); + entity.setDeletedAt(domain.getDeletedAt()); + return entity; + } +} diff --git a/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/infrastructure/db/converter/SysUserConverter.java b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/infrastructure/db/converter/SysUserConverter.java new file mode 100644 index 0000000..914c8db --- /dev/null +++ b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/infrastructure/db/converter/SysUserConverter.java @@ -0,0 +1,41 @@ +package cn.novalon.manage.sys.infrastructure.db.converter; + +import cn.novalon.manage.sys.core.domain.SysUser; +import cn.novalon.manage.sys.infrastructure.db.entity.SysUserEntity; + +public class SysUserConverter { + + public SysUser toDomain(SysUserEntity entity) { + if (entity == null) { + return null; + } + SysUser domain = new SysUser(); + domain.setId(entity.getId()); + domain.setUsername(entity.getUsername()); + domain.setPassword(entity.getPassword()); + domain.setEmail(entity.getEmail()); + domain.setRoleId(entity.getRoleId()); + domain.setStatus(entity.getStatus()); + domain.setCreatedAt(entity.getCreatedAt()); + domain.setUpdatedAt(entity.getUpdatedAt()); + domain.setDeletedAt(entity.getDeletedAt()); + return domain; + } + + public SysUserEntity toEntity(SysUser domain) { + if (domain == null) { + return null; + } + SysUserEntity entity = new SysUserEntity(); + entity.setId(domain.getId()); + entity.setUsername(domain.getUsername()); + entity.setPassword(domain.getPassword()); + entity.setEmail(domain.getEmail()); + entity.setRoleId(domain.getRoleId()); + entity.setStatus(domain.getStatus()); + entity.setCreatedAt(domain.getCreatedAt()); + entity.setUpdatedAt(domain.getUpdatedAt()); + entity.setDeletedAt(domain.getDeletedAt()); + return entity; + } +} diff --git a/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/infrastructure/db/converter/SysUserMessageConverter.java b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/infrastructure/db/converter/SysUserMessageConverter.java new file mode 100644 index 0000000..79fb62c --- /dev/null +++ b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/infrastructure/db/converter/SysUserMessageConverter.java @@ -0,0 +1,37 @@ +package cn.novalon.manage.sys.infrastructure.db.converter; + +import cn.novalon.manage.sys.core.domain.SysUserMessage; +import cn.novalon.manage.sys.infrastructure.db.entity.SysUserMessageEntity; + +public class SysUserMessageConverter { + + public SysUserMessage toDomain(SysUserMessageEntity entity) { + if (entity == null) { + return null; + } + SysUserMessage domain = new SysUserMessage(); + domain.setId(entity.getId()); + domain.setUserId(entity.getUserId()); + domain.setTitle(entity.getTitle()); + domain.setContent(entity.getContent()); + domain.setMessageType(entity.getMessageType()); + domain.setIsRead(entity.getIsRead()); + domain.setCreateTime(entity.getCreateTime()); + return domain; + } + + public SysUserMessageEntity toEntity(SysUserMessage domain) { + if (domain == null) { + return null; + } + SysUserMessageEntity entity = new SysUserMessageEntity(); + entity.setId(domain.getId()); + entity.setUserId(domain.getUserId()); + entity.setTitle(domain.getTitle()); + entity.setContent(domain.getContent()); + entity.setMessageType(domain.getMessageType()); + entity.setIsRead(domain.getIsRead()); + entity.setCreateTime(domain.getCreateTime()); + return entity; + } +} diff --git a/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/infrastructure/db/dao/OperationLogDao.java b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/infrastructure/db/dao/OperationLogDao.java new file mode 100644 index 0000000..832b97c --- /dev/null +++ b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/infrastructure/db/dao/OperationLogDao.java @@ -0,0 +1,14 @@ +package cn.novalon.manage.sys.infrastructure.db.dao; + +import cn.novalon.manage.sys.infrastructure.db.entity.OperationLogEntity; +import org.springframework.data.r2dbc.repository.R2dbcRepository; +import org.springframework.stereotype.Repository; +import reactor.core.publisher.Flux; + +@Repository +public interface OperationLogDao extends R2dbcRepository { + + Flux findByUsernameAndDeletedAtIsNull(String username); + + Flux findByDeletedAtIsNull(); +} diff --git a/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/infrastructure/db/dao/SysConfigDao.java b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/infrastructure/db/dao/SysConfigDao.java new file mode 100644 index 0000000..894a99a --- /dev/null +++ b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/infrastructure/db/dao/SysConfigDao.java @@ -0,0 +1,17 @@ +package cn.novalon.manage.sys.infrastructure.db.dao; + +import cn.novalon.manage.sys.infrastructure.db.entity.SysConfigEntity; +import org.springframework.data.r2dbc.repository.R2dbcRepository; +import org.springframework.stereotype.Repository; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; + +@Repository +public interface SysConfigDao extends R2dbcRepository { + + Mono findByConfigKeyAndDeletedAtIsNull(String configKey); + + Flux findByDeletedAtIsNull(); + + Mono deleteByIdAndDeletedAtIsNull(Long id); +} diff --git a/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/infrastructure/db/dao/SysDictDataDao.java b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/infrastructure/db/dao/SysDictDataDao.java new file mode 100644 index 0000000..fc22e1f --- /dev/null +++ b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/infrastructure/db/dao/SysDictDataDao.java @@ -0,0 +1,19 @@ +package cn.novalon.manage.sys.infrastructure.db.dao; + +import cn.novalon.manage.sys.infrastructure.db.entity.SysDictDataEntity; +import org.springframework.data.r2dbc.repository.R2dbcRepository; +import org.springframework.stereotype.Repository; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; + +@Repository +public interface SysDictDataDao extends R2dbcRepository { + + Flux findByDictTypeAndStatusAndDeletedAtIsNull(String dictType, String status); + + Flux findByDictTypeAndDeletedAtIsNull(String dictType); + + Flux findByDeletedAtIsNull(); + + Mono deleteByIdAndDeletedAtIsNull(Long id); +} diff --git a/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/infrastructure/db/dao/SysDictTypeDao.java b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/infrastructure/db/dao/SysDictTypeDao.java new file mode 100644 index 0000000..c75f2e0 --- /dev/null +++ b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/infrastructure/db/dao/SysDictTypeDao.java @@ -0,0 +1,17 @@ +package cn.novalon.manage.sys.infrastructure.db.dao; + +import cn.novalon.manage.sys.infrastructure.db.entity.SysDictTypeEntity; +import org.springframework.data.r2dbc.repository.R2dbcRepository; +import org.springframework.stereotype.Repository; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; + +@Repository +public interface SysDictTypeDao extends R2dbcRepository { + + Mono findByDictTypeAndDeletedAtIsNull(String dictType); + + Flux findByDeletedAtIsNull(); + + Mono deleteByIdAndDeletedAtIsNull(Long id); +} diff --git a/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/infrastructure/db/dao/SysExceptionLogDao.java b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/infrastructure/db/dao/SysExceptionLogDao.java new file mode 100644 index 0000000..e5d691c --- /dev/null +++ b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/infrastructure/db/dao/SysExceptionLogDao.java @@ -0,0 +1,18 @@ +package cn.novalon.manage.sys.infrastructure.db.dao; + +import cn.novalon.manage.sys.infrastructure.db.entity.SysExceptionLogEntity; +import org.springframework.data.r2dbc.repository.R2dbcRepository; +import org.springframework.stereotype.Repository; +import reactor.core.publisher.Flux; + +import java.time.LocalDateTime; + +@Repository +public interface SysExceptionLogDao extends R2dbcRepository { + + Flux findByUsernameOrderByCreateTimeDesc(String username); + + Flux findByCreateTimeBetweenOrderByCreateTimeDesc(LocalDateTime startTime, LocalDateTime endTime); + + Flux findAllByOrderByCreateTimeDesc(); +} diff --git a/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/infrastructure/db/dao/SysFileDao.java b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/infrastructure/db/dao/SysFileDao.java new file mode 100644 index 0000000..cc12096 --- /dev/null +++ b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/infrastructure/db/dao/SysFileDao.java @@ -0,0 +1,17 @@ +package cn.novalon.manage.sys.infrastructure.db.dao; + +import cn.novalon.manage.sys.infrastructure.db.entity.SysFileEntity; +import org.springframework.data.r2dbc.repository.R2dbcRepository; +import org.springframework.stereotype.Repository; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; + +@Repository +public interface SysFileDao extends R2dbcRepository { + + Flux findByCreateByOrderByCreatedAtDesc(String createBy); + + Flux findByDeletedAtIsNullOrderByCreatedAtDesc(); + + Mono deleteByIdAndDeletedAtIsNull(Long id); +} diff --git a/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/infrastructure/db/dao/SysLoginLogDao.java b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/infrastructure/db/dao/SysLoginLogDao.java new file mode 100644 index 0000000..2d5fdfd --- /dev/null +++ b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/infrastructure/db/dao/SysLoginLogDao.java @@ -0,0 +1,18 @@ +package cn.novalon.manage.sys.infrastructure.db.dao; + +import cn.novalon.manage.sys.infrastructure.db.entity.SysLoginLogEntity; +import org.springframework.data.r2dbc.repository.R2dbcRepository; +import org.springframework.stereotype.Repository; +import reactor.core.publisher.Flux; + +import java.time.LocalDateTime; + +@Repository +public interface SysLoginLogDao extends R2dbcRepository { + + Flux findByUsernameOrderByLoginTimeDesc(String username); + + Flux findByLoginTimeBetweenOrderByLoginTimeDesc(LocalDateTime startTime, LocalDateTime endTime); + + Flux findAllByOrderByLoginTimeDesc(); +} diff --git a/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/infrastructure/db/dao/SysMenuDao.java b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/infrastructure/db/dao/SysMenuDao.java new file mode 100644 index 0000000..c3a68d4 --- /dev/null +++ b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/infrastructure/db/dao/SysMenuDao.java @@ -0,0 +1,17 @@ +package cn.novalon.manage.sys.infrastructure.db.dao; + +import cn.novalon.manage.sys.infrastructure.db.entity.SysMenuEntity; +import org.springframework.data.r2dbc.repository.R2dbcRepository; +import org.springframework.stereotype.Repository; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; + +@Repository +public interface SysMenuDao extends R2dbcRepository { + + Mono findByIdAndDeletedAtIsNull(Long id); + + Flux findByParentIdAndDeletedAtIsNull(Long parentId); + + Flux findByDeletedAtIsNull(); +} diff --git a/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/infrastructure/db/dao/SysNoticeDao.java b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/infrastructure/db/dao/SysNoticeDao.java new file mode 100644 index 0000000..3a9771c --- /dev/null +++ b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/infrastructure/db/dao/SysNoticeDao.java @@ -0,0 +1,17 @@ +package cn.novalon.manage.sys.infrastructure.db.dao; + +import cn.novalon.manage.sys.infrastructure.db.entity.SysNoticeEntity; +import org.springframework.data.r2dbc.repository.R2dbcRepository; +import org.springframework.stereotype.Repository; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; + +@Repository +public interface SysNoticeDao extends R2dbcRepository { + + Flux findByStatusAndDeletedAtIsNull(String status); + + Flux findByDeletedAtIsNull(); + + Mono deleteByIdAndDeletedAtIsNull(Long id); +} diff --git a/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/infrastructure/db/dao/SysRoleDao.java b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/infrastructure/db/dao/SysRoleDao.java new file mode 100644 index 0000000..973c68a --- /dev/null +++ b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/infrastructure/db/dao/SysRoleDao.java @@ -0,0 +1,15 @@ +package cn.novalon.manage.sys.infrastructure.db.dao; + +import cn.novalon.manage.sys.infrastructure.db.entity.SysRoleEntity; +import org.springframework.data.r2dbc.repository.R2dbcRepository; +import org.springframework.stereotype.Repository; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; + +@Repository +public interface SysRoleDao extends R2dbcRepository { + + Mono findByRoleKeyAndDeletedAtIsNull(String roleKey); + + Flux findByDeletedAtIsNull(); +} diff --git a/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/infrastructure/db/dao/SysUserDao.java b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/infrastructure/db/dao/SysUserDao.java new file mode 100644 index 0000000..6467fcc --- /dev/null +++ b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/infrastructure/db/dao/SysUserDao.java @@ -0,0 +1,15 @@ +package cn.novalon.manage.sys.infrastructure.db.dao; + +import cn.novalon.manage.sys.infrastructure.db.entity.SysUserEntity; +import org.springframework.data.r2dbc.repository.R2dbcRepository; +import org.springframework.stereotype.Repository; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; + +@Repository +public interface SysUserDao extends R2dbcRepository { + + Mono findByUsernameAndDeletedAtIsNull(String username); + + Flux findByDeletedAtIsNull(); +} diff --git a/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/infrastructure/db/dao/SysUserMessageDao.java b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/infrastructure/db/dao/SysUserMessageDao.java new file mode 100644 index 0000000..4694ef1 --- /dev/null +++ b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/infrastructure/db/dao/SysUserMessageDao.java @@ -0,0 +1,17 @@ +package cn.novalon.manage.sys.infrastructure.db.dao; + +import cn.novalon.manage.sys.infrastructure.db.entity.SysUserMessageEntity; +import org.springframework.data.r2dbc.repository.R2dbcRepository; +import org.springframework.stereotype.Repository; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; + +@Repository +public interface SysUserMessageDao extends R2dbcRepository { + + Flux findByUserIdAndIsReadOrderByCreateTimeDesc(Long userId, String isRead); + + Flux findByUserIdOrderByCreateTimeDesc(Long userId); + + Mono countByUserIdAndIsRead(Long userId, String isRead); +} diff --git a/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/infrastructure/db/entity/BaseEntity.java b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/infrastructure/db/entity/BaseEntity.java new file mode 100644 index 0000000..f82996d --- /dev/null +++ b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/infrastructure/db/entity/BaseEntity.java @@ -0,0 +1,57 @@ +package cn.novalon.manage.sys.infrastructure.db.entity; + +import org.springframework.data.annotation.CreatedDate; +import org.springframework.data.annotation.Id; +import org.springframework.data.annotation.LastModifiedDate; +import org.springframework.data.relational.core.mapping.Column; + +import java.time.LocalDateTime; + +public abstract class BaseEntity { + + @Id + private Long id; + + @CreatedDate + @Column("created_at") + private LocalDateTime createdAt; + + @LastModifiedDate + @Column("updated_at") + private LocalDateTime updatedAt; + + @Column("deleted_at") + private LocalDateTime deletedAt; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public LocalDateTime getCreatedAt() { + return createdAt; + } + + public void setCreatedAt(LocalDateTime createdAt) { + this.createdAt = createdAt; + } + + public LocalDateTime getUpdatedAt() { + return updatedAt; + } + + public void setUpdatedAt(LocalDateTime updatedAt) { + this.updatedAt = updatedAt; + } + + public LocalDateTime getDeletedAt() { + return deletedAt; + } + + public void setDeletedAt(LocalDateTime deletedAt) { + this.deletedAt = deletedAt; + } +} diff --git a/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/infrastructure/db/entity/OperationLogEntity.java b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/infrastructure/db/entity/OperationLogEntity.java new file mode 100644 index 0000000..176b763 --- /dev/null +++ b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/infrastructure/db/entity/OperationLogEntity.java @@ -0,0 +1,107 @@ +package cn.novalon.manage.sys.infrastructure.db.entity; + +import org.springframework.data.relational.core.mapping.Column; +import org.springframework.data.relational.core.mapping.Table; + +@Table("operation_log") +public class OperationLogEntity extends BaseEntity { + + @Column("username") + private String username; + + @Column("operation") + private String operation; + + @Column("method") + private String method; + + @Column("params") + private String params; + + @Column("result") + private String result; + + @Column("ip") + private String ip; + + @Column("duration") + private Long duration; + + @Column("status") + private String status; + + @Column("error_msg") + private String errorMsg; + + public String getUsername() { + return username; + } + + public void setUsername(String username) { + this.username = username; + } + + public String getOperation() { + return operation; + } + + public void setOperation(String operation) { + this.operation = operation; + } + + public String getMethod() { + return method; + } + + public void setMethod(String method) { + this.method = method; + } + + public String getParams() { + return params; + } + + public void setParams(String params) { + this.params = params; + } + + public String getResult() { + return result; + } + + public void setResult(String result) { + this.result = result; + } + + public String getIp() { + return ip; + } + + public void setIp(String ip) { + this.ip = ip; + } + + public Long getDuration() { + return duration; + } + + public void setDuration(Long duration) { + this.duration = duration; + } + + public String getStatus() { + return status; + } + + public void setStatus(String status) { + this.status = status; + } + + public String getErrorMsg() { + return errorMsg; + } + + public void setErrorMsg(String errorMsg) { + this.errorMsg = errorMsg; + } +} diff --git a/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/infrastructure/db/entity/SysConfigEntity.java b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/infrastructure/db/entity/SysConfigEntity.java new file mode 100644 index 0000000..5358bd1 --- /dev/null +++ b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/infrastructure/db/entity/SysConfigEntity.java @@ -0,0 +1,121 @@ +package cn.novalon.manage.sys.infrastructure.db.entity; + +import org.springframework.data.annotation.Id; +import org.springframework.data.relational.core.mapping.Column; +import org.springframework.data.relational.core.mapping.Table; + +import java.time.LocalDateTime; + +@Table("sys_config") +public class SysConfigEntity { + + @Id + private Long id; + + @Column("config_name") + private String configName; + + @Column("config_key") + private String configKey; + + @Column("config_value") + private String configValue; + + @Column("config_type") + private String configType; + + @Column("create_by") + private String createBy; + + @Column("update_by") + private String updateBy; + + @Column("created_at") + private LocalDateTime createdAt; + + @Column("updated_at") + private LocalDateTime updatedAt; + + @Column("deleted_at") + private LocalDateTime deletedAt; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getConfigName() { + return configName; + } + + public void setConfigName(String configName) { + this.configName = configName; + } + + public String getConfigKey() { + return configKey; + } + + public void setConfigKey(String configKey) { + this.configKey = configKey; + } + + public String getConfigValue() { + return configValue; + } + + public void setConfigValue(String configValue) { + this.configValue = configValue; + } + + public String getConfigType() { + return configType; + } + + public void setConfigType(String configType) { + this.configType = configType; + } + + public String getCreateBy() { + return createBy; + } + + public void setCreateBy(String createBy) { + this.createBy = createBy; + } + + public String getUpdateBy() { + return updateBy; + } + + public void setUpdateBy(String updateBy) { + this.updateBy = updateBy; + } + + public LocalDateTime getCreatedAt() { + return createdAt; + } + + public void setCreatedAt(LocalDateTime createdAt) { + this.createdAt = createdAt; + } + + public LocalDateTime getUpdatedAt() { + return updatedAt; + } + + public void setUpdatedAt(LocalDateTime updatedAt) { + this.updatedAt = updatedAt; + } + + public LocalDateTime getDeletedAt() { + return deletedAt; + } + + public void setDeletedAt(LocalDateTime deletedAt) { + this.deletedAt = deletedAt; + } +} diff --git a/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/infrastructure/db/entity/SysDictDataEntity.java b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/infrastructure/db/entity/SysDictDataEntity.java new file mode 100644 index 0000000..88a6938 --- /dev/null +++ b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/infrastructure/db/entity/SysDictDataEntity.java @@ -0,0 +1,165 @@ +package cn.novalon.manage.sys.infrastructure.db.entity; + +import org.springframework.data.annotation.Id; +import org.springframework.data.relational.core.mapping.Column; +import org.springframework.data.relational.core.mapping.Table; + +import java.time.LocalDateTime; + +@Table("sys_dict_data") +public class SysDictDataEntity { + + @Id + private Long id; + + @Column("dict_sort") + private Integer dictSort; + + @Column("dict_label") + private String dictLabel; + + @Column("dict_value") + private String dictValue; + + @Column("dict_type") + private String dictType; + + @Column("css_class") + private String cssClass; + + @Column("list_class") + private String listClass; + + @Column("is_default") + private String isDefault; + + @Column("status") + private String status; + + @Column("create_by") + private String createBy; + + @Column("update_by") + private String updateBy; + + @Column("created_at") + private LocalDateTime createdAt; + + @Column("updated_at") + private LocalDateTime updatedAt; + + @Column("deleted_at") + private LocalDateTime deletedAt; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public Integer getDictSort() { + return dictSort; + } + + public void setDictSort(Integer dictSort) { + this.dictSort = dictSort; + } + + public String getDictLabel() { + return dictLabel; + } + + public void setDictLabel(String dictLabel) { + this.dictLabel = dictLabel; + } + + public String getDictValue() { + return dictValue; + } + + public void setDictValue(String dictValue) { + this.dictValue = dictValue; + } + + public String getDictType() { + return dictType; + } + + public void setDictType(String dictType) { + this.dictType = dictType; + } + + public String getCssClass() { + return cssClass; + } + + public void setCssClass(String cssClass) { + this.cssClass = cssClass; + } + + public String getListClass() { + return listClass; + } + + public void setListClass(String listClass) { + this.listClass = listClass; + } + + public String getIsDefault() { + return isDefault; + } + + public void setIsDefault(String isDefault) { + this.isDefault = isDefault; + } + + public String getStatus() { + return status; + } + + public void setStatus(String status) { + this.status = status; + } + + public String getCreateBy() { + return createBy; + } + + public void setCreateBy(String createBy) { + this.createBy = createBy; + } + + public String getUpdateBy() { + return updateBy; + } + + public void setUpdateBy(String updateBy) { + this.updateBy = updateBy; + } + + public LocalDateTime getCreatedAt() { + return createdAt; + } + + public void setCreatedAt(LocalDateTime createdAt) { + this.createdAt = createdAt; + } + + public LocalDateTime getUpdatedAt() { + return updatedAt; + } + + public void setUpdatedAt(LocalDateTime updatedAt) { + this.updatedAt = updatedAt; + } + + public LocalDateTime getDeletedAt() { + return deletedAt; + } + + public void setDeletedAt(LocalDateTime deletedAt) { + this.deletedAt = deletedAt; + } +} diff --git a/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/infrastructure/db/entity/SysDictTypeEntity.java b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/infrastructure/db/entity/SysDictTypeEntity.java new file mode 100644 index 0000000..d2b9155 --- /dev/null +++ b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/infrastructure/db/entity/SysDictTypeEntity.java @@ -0,0 +1,121 @@ +package cn.novalon.manage.sys.infrastructure.db.entity; + +import org.springframework.data.annotation.Id; +import org.springframework.data.relational.core.mapping.Column; +import org.springframework.data.relational.core.mapping.Table; + +import java.time.LocalDateTime; + +@Table("sys_dict_type") +public class SysDictTypeEntity { + + @Id + private Long id; + + @Column("dict_name") + private String dictName; + + @Column("dict_type") + private String dictType; + + @Column("status") + private String status; + + @Column("remark") + private String remark; + + @Column("create_by") + private String createBy; + + @Column("update_by") + private String updateBy; + + @Column("created_at") + private LocalDateTime createdAt; + + @Column("updated_at") + private LocalDateTime updatedAt; + + @Column("deleted_at") + private LocalDateTime deletedAt; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getDictName() { + return dictName; + } + + public void setDictName(String dictName) { + this.dictName = dictName; + } + + public String getDictType() { + return dictType; + } + + public void setDictType(String dictType) { + this.dictType = dictType; + } + + public String getStatus() { + return status; + } + + public void setStatus(String status) { + this.status = status; + } + + public String getRemark() { + return remark; + } + + public void setRemark(String remark) { + this.remark = remark; + } + + public String getCreateBy() { + return createBy; + } + + public void setCreateBy(String createBy) { + this.createBy = createBy; + } + + public String getUpdateBy() { + return updateBy; + } + + public void setUpdateBy(String updateBy) { + this.updateBy = updateBy; + } + + public LocalDateTime getCreatedAt() { + return createdAt; + } + + public void setCreatedAt(LocalDateTime createdAt) { + this.createdAt = createdAt; + } + + public LocalDateTime getUpdatedAt() { + return updatedAt; + } + + public void setUpdatedAt(LocalDateTime updatedAt) { + this.updatedAt = updatedAt; + } + + public LocalDateTime getDeletedAt() { + return deletedAt; + } + + public void setDeletedAt(LocalDateTime deletedAt) { + this.deletedAt = deletedAt; + } +} diff --git a/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/infrastructure/db/entity/SysExceptionLogEntity.java b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/infrastructure/db/entity/SysExceptionLogEntity.java new file mode 100644 index 0000000..2bc9a21 --- /dev/null +++ b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/infrastructure/db/entity/SysExceptionLogEntity.java @@ -0,0 +1,121 @@ +package cn.novalon.manage.sys.infrastructure.db.entity; + +import org.springframework.data.annotation.Id; +import org.springframework.data.relational.core.mapping.Column; +import org.springframework.data.relational.core.mapping.Table; + +import java.time.LocalDateTime; + +@Table("sys_exception_log") +public class SysExceptionLogEntity { + + @Id + private Long id; + + @Column("username") + private String username; + + @Column("title") + private String title; + + @Column("exception_name") + private String exceptionName; + + @Column("method_name") + private String methodName; + + @Column("method_params") + private String methodParams; + + @Column("exception_msg") + private String exceptionMsg; + + @Column("exception_stack") + private String exceptionStack; + + @Column("ip") + private String ip; + + @Column("create_time") + private LocalDateTime createTime; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getUsername() { + return username; + } + + public void setUsername(String username) { + this.username = username; + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public String getExceptionName() { + return exceptionName; + } + + public void setExceptionName(String exceptionName) { + this.exceptionName = exceptionName; + } + + public String getMethodName() { + return methodName; + } + + public void setMethodName(String methodName) { + this.methodName = methodName; + } + + public String getMethodParams() { + return methodParams; + } + + public void setMethodParams(String methodParams) { + this.methodParams = methodParams; + } + + public String getExceptionMsg() { + return exceptionMsg; + } + + public void setExceptionMsg(String exceptionMsg) { + this.exceptionMsg = exceptionMsg; + } + + public String getExceptionStack() { + return exceptionStack; + } + + public void setExceptionStack(String exceptionStack) { + this.exceptionStack = exceptionStack; + } + + public String getIp() { + return ip; + } + + public void setIp(String ip) { + this.ip = ip; + } + + public LocalDateTime getCreateTime() { + return createTime; + } + + public void setCreateTime(LocalDateTime createTime) { + this.createTime = createTime; + } +} diff --git a/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/infrastructure/db/entity/SysFileEntity.java b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/infrastructure/db/entity/SysFileEntity.java new file mode 100644 index 0000000..f30b3d4 --- /dev/null +++ b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/infrastructure/db/entity/SysFileEntity.java @@ -0,0 +1,110 @@ +package cn.novalon.manage.sys.infrastructure.db.entity; + +import org.springframework.data.annotation.Id; +import org.springframework.data.relational.core.mapping.Column; +import org.springframework.data.relational.core.mapping.Table; + +import java.time.LocalDateTime; + +@Table("sys_file") +public class SysFileEntity { + + @Id + private Long id; + + @Column("file_name") + private String fileName; + + @Column("file_path") + private String filePath; + + @Column("file_size") + private String fileSize; + + @Column("file_type") + private String fileType; + + @Column("storage_type") + private String storageType; + + @Column("create_by") + private String createBy; + + @Column("created_at") + private LocalDateTime createdAt; + + @Column("deleted_at") + private LocalDateTime deletedAt; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getFileName() { + return fileName; + } + + public void setFileName(String fileName) { + this.fileName = fileName; + } + + public String getFilePath() { + return filePath; + } + + public void setFilePath(String filePath) { + this.filePath = filePath; + } + + public String getFileSize() { + return fileSize; + } + + public void setFileSize(String fileSize) { + this.fileSize = fileSize; + } + + public String getFileType() { + return fileType; + } + + public void setFileType(String fileType) { + this.fileType = fileType; + } + + public String getStorageType() { + return storageType; + } + + public void setStorageType(String storageType) { + this.storageType = storageType; + } + + public String getCreateBy() { + return createBy; + } + + public void setCreateBy(String createBy) { + this.createBy = createBy; + } + + public LocalDateTime getCreatedAt() { + return createdAt; + } + + public void setCreatedAt(LocalDateTime createdAt) { + this.createdAt = createdAt; + } + + public LocalDateTime getDeletedAt() { + return deletedAt; + } + + public void setDeletedAt(LocalDateTime deletedAt) { + this.deletedAt = deletedAt; + } +} diff --git a/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/infrastructure/db/entity/SysLoginLogEntity.java b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/infrastructure/db/entity/SysLoginLogEntity.java new file mode 100644 index 0000000..2ca3754 --- /dev/null +++ b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/infrastructure/db/entity/SysLoginLogEntity.java @@ -0,0 +1,110 @@ +package cn.novalon.manage.sys.infrastructure.db.entity; + +import org.springframework.data.annotation.Id; +import org.springframework.data.relational.core.mapping.Column; +import org.springframework.data.relational.core.mapping.Table; + +import java.time.LocalDateTime; + +@Table("sys_login_log") +public class SysLoginLogEntity { + + @Id + private Long id; + + @Column("username") + private String username; + + @Column("ip") + private String ip; + + @Column("location") + private String location; + + @Column("browser") + private String browser; + + @Column("os") + private String os; + + @Column("status") + private String status; + + @Column("message") + private String message; + + @Column("login_time") + private LocalDateTime loginTime; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getUsername() { + return username; + } + + public void setUsername(String username) { + this.username = username; + } + + public String getIp() { + return ip; + } + + public void setIp(String ip) { + this.ip = ip; + } + + public String getLocation() { + return location; + } + + public void setLocation(String location) { + this.location = location; + } + + public String getBrowser() { + return browser; + } + + public void setBrowser(String browser) { + this.browser = browser; + } + + public String getOs() { + return os; + } + + public void setOs(String os) { + this.os = os; + } + + public String getStatus() { + return status; + } + + public void setStatus(String status) { + this.status = status; + } + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } + + public LocalDateTime getLoginTime() { + return loginTime; + } + + public void setLoginTime(LocalDateTime loginTime) { + this.loginTime = loginTime; + } +} diff --git a/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/infrastructure/db/entity/SysMenuEntity.java b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/infrastructure/db/entity/SysMenuEntity.java new file mode 100644 index 0000000..e29a1ef --- /dev/null +++ b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/infrastructure/db/entity/SysMenuEntity.java @@ -0,0 +1,85 @@ +package cn.novalon.manage.sys.infrastructure.db.entity; + +import org.springframework.data.relational.core.mapping.Column; +import org.springframework.data.relational.core.mapping.Table; + +@Table("sys_menu") +public class SysMenuEntity extends BaseEntity { + + @Column("menu_name") + private String menuName; + + @Column("parent_id") + private Long parentId; + + @Column("order_num") + private Integer orderNum; + + @Column("menu_type") + private String menuType; + + @Column("perms") + private String perms; + + @Column("component") + private String component; + + @Column("status") + private String status; + + public String getMenuName() { + return menuName; + } + + public void setMenuName(String menuName) { + this.menuName = menuName; + } + + public Long getParentId() { + return parentId; + } + + public void setParentId(Long parentId) { + this.parentId = parentId; + } + + public Integer getOrderNum() { + return orderNum; + } + + public void setOrderNum(Integer orderNum) { + this.orderNum = orderNum; + } + + public String getMenuType() { + return menuType; + } + + public void setMenuType(String menuType) { + this.menuType = menuType; + } + + public String getPerms() { + return perms; + } + + public void setPerms(String perms) { + this.perms = perms; + } + + public String getComponent() { + return component; + } + + public void setComponent(String component) { + this.component = component; + } + + public String getStatus() { + return status; + } + + public void setStatus(String status) { + this.status = status; + } +} diff --git a/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/infrastructure/db/entity/SysNoticeEntity.java b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/infrastructure/db/entity/SysNoticeEntity.java new file mode 100644 index 0000000..2de0d9d --- /dev/null +++ b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/infrastructure/db/entity/SysNoticeEntity.java @@ -0,0 +1,121 @@ +package cn.novalon.manage.sys.infrastructure.db.entity; + +import org.springframework.data.annotation.Id; +import org.springframework.data.relational.core.mapping.Column; +import org.springframework.data.relational.core.mapping.Table; + +import java.time.LocalDateTime; + +@Table("sys_notice") +public class SysNoticeEntity { + + @Id + private Long id; + + @Column("notice_title") + private String noticeTitle; + + @Column("notice_type") + private String noticeType; + + @Column("notice_content") + private String noticeContent; + + @Column("status") + private String status; + + @Column("create_by") + private String createBy; + + @Column("update_by") + private String updateBy; + + @Column("created_at") + private LocalDateTime createdAt; + + @Column("updated_at") + private LocalDateTime updatedAt; + + @Column("deleted_at") + private LocalDateTime deletedAt; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getNoticeTitle() { + return noticeTitle; + } + + public void setNoticeTitle(String noticeTitle) { + this.noticeTitle = noticeTitle; + } + + public String getNoticeType() { + return noticeType; + } + + public void setNoticeType(String noticeType) { + this.noticeType = noticeType; + } + + public String getNoticeContent() { + return noticeContent; + } + + public void setNoticeContent(String noticeContent) { + this.noticeContent = noticeContent; + } + + public String getStatus() { + return status; + } + + public void setStatus(String status) { + this.status = status; + } + + public String getCreateBy() { + return createBy; + } + + public void setCreateBy(String createBy) { + this.createBy = createBy; + } + + public String getUpdateBy() { + return updateBy; + } + + public void setUpdateBy(String updateBy) { + this.updateBy = updateBy; + } + + public LocalDateTime getCreatedAt() { + return createdAt; + } + + public void setCreatedAt(LocalDateTime createdAt) { + this.createdAt = createdAt; + } + + public LocalDateTime getUpdatedAt() { + return updatedAt; + } + + public void setUpdatedAt(LocalDateTime updatedAt) { + this.updatedAt = updatedAt; + } + + public LocalDateTime getDeletedAt() { + return deletedAt; + } + + public void setDeletedAt(LocalDateTime deletedAt) { + this.deletedAt = deletedAt; + } +} diff --git a/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/infrastructure/db/entity/SysRoleEntity.java b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/infrastructure/db/entity/SysRoleEntity.java new file mode 100644 index 0000000..ab7d360 --- /dev/null +++ b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/infrastructure/db/entity/SysRoleEntity.java @@ -0,0 +1,52 @@ +package cn.novalon.manage.sys.infrastructure.db.entity; + +import org.springframework.data.relational.core.mapping.Column; +import org.springframework.data.relational.core.mapping.Table; + +@Table("roles") +public class SysRoleEntity extends BaseEntity { + + @Column("role_name") + private String roleName; + + @Column("role_key") + private String roleKey; + + @Column("role_sort") + private Integer roleSort; + + @Column("status") + private Integer status; + + public String getRoleName() { + return roleName; + } + + public void setRoleName(String roleName) { + this.roleName = roleName; + } + + public String getRoleKey() { + return roleKey; + } + + public void setRoleKey(String roleKey) { + this.roleKey = roleKey; + } + + public Integer getRoleSort() { + return roleSort; + } + + public void setRoleSort(Integer roleSort) { + this.roleSort = roleSort; + } + + public Integer getStatus() { + return status; + } + + public void setStatus(Integer status) { + this.status = status; + } +} diff --git a/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/infrastructure/db/entity/SysUserEntity.java b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/infrastructure/db/entity/SysUserEntity.java new file mode 100644 index 0000000..ffaed9a --- /dev/null +++ b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/infrastructure/db/entity/SysUserEntity.java @@ -0,0 +1,63 @@ +package cn.novalon.manage.sys.infrastructure.db.entity; + +import org.springframework.data.relational.core.mapping.Column; +import org.springframework.data.relational.core.mapping.Table; + +@Table("users") +public class SysUserEntity extends BaseEntity { + + @Column("username") + private String username; + + @Column("password") + private String password; + + @Column("email") + private String email; + + @Column("role_id") + private Long roleId; + + @Column("status") + private Integer status; + + public String getUsername() { + return username; + } + + public void setUsername(String username) { + this.username = username; + } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } + + public String getEmail() { + return email; + } + + public void setEmail(String email) { + this.email = email; + } + + public Long getRoleId() { + return roleId; + } + + public void setRoleId(Long roleId) { + this.roleId = roleId; + } + + public Integer getStatus() { + return status; + } + + public void setStatus(Integer status) { + this.status = status; + } +} diff --git a/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/infrastructure/db/entity/SysUserMessageEntity.java b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/infrastructure/db/entity/SysUserMessageEntity.java new file mode 100644 index 0000000..f713494 --- /dev/null +++ b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/infrastructure/db/entity/SysUserMessageEntity.java @@ -0,0 +1,88 @@ +package cn.novalon.manage.sys.infrastructure.db.entity; + +import org.springframework.data.annotation.Id; +import org.springframework.data.relational.core.mapping.Column; +import org.springframework.data.relational.core.mapping.Table; + +import java.time.LocalDateTime; + +@Table("sys_user_message") +public class SysUserMessageEntity { + + @Id + private Long id; + + @Column("user_id") + private Long userId; + + @Column("title") + private String title; + + @Column("content") + private String content; + + @Column("message_type") + private String messageType; + + @Column("is_read") + private String isRead; + + @Column("create_time") + private LocalDateTime createTime; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public Long getUserId() { + return userId; + } + + public void setUserId(Long userId) { + this.userId = userId; + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public String getContent() { + return content; + } + + public void setContent(String content) { + this.content = content; + } + + public String getMessageType() { + return messageType; + } + + public void setMessageType(String messageType) { + this.messageType = messageType; + } + + public String getIsRead() { + return isRead; + } + + public void setIsRead(String isRead) { + this.isRead = isRead; + } + + public LocalDateTime getCreateTime() { + return createTime; + } + + public void setCreateTime(LocalDateTime createTime) { + this.createTime = createTime; + } +} diff --git a/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/infrastructure/db/repository/OperationLogRepository.java b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/infrastructure/db/repository/OperationLogRepository.java new file mode 100644 index 0000000..9f166a4 --- /dev/null +++ b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/infrastructure/db/repository/OperationLogRepository.java @@ -0,0 +1,57 @@ +package cn.novalon.manage.sys.infrastructure.db.repository; + +import cn.novalon.manage.sys.core.domain.OperationLog; +import cn.novalon.manage.sys.core.repository.IOperationLogRepository; +import cn.novalon.manage.sys.infrastructure.db.converter.OperationLogConverter; +import cn.novalon.manage.sys.infrastructure.db.dao.OperationLogDao; +import org.springframework.stereotype.Repository; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; + +import java.time.LocalDateTime; + +@Repository +public class OperationLogRepository implements IOperationLogRepository { + + private final OperationLogDao dao; + private final OperationLogConverter converter; + + public OperationLogRepository(OperationLogDao dao, OperationLogConverter converter) { + this.dao = dao; + this.converter = converter; + } + + @Override + public Mono findById(Long id) { + return dao.findById(id) + .map(converter::toDomain); + } + + @Override + public Mono save(OperationLog operationLog) { + return dao.save(converter.toEntity(operationLog)) + .map(converter::toDomain); + } + + @Override + public Mono deleteById(Long id) { + return dao.findById(id) + .flatMap(entity -> { + entity.setDeletedAt(LocalDateTime.now()); + return dao.save(entity); + }) + .then(); + } + + @Override + public Flux findAll() { + return dao.findByDeletedAtIsNull() + .map(converter::toDomain); + } + + @Override + public Flux findByUsername(String username) { + return dao.findByUsernameAndDeletedAtIsNull(username) + .map(converter::toDomain); + } +} diff --git a/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/infrastructure/db/repository/SysMenuRepository.java b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/infrastructure/db/repository/SysMenuRepository.java new file mode 100644 index 0000000..6e39b83 --- /dev/null +++ b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/infrastructure/db/repository/SysMenuRepository.java @@ -0,0 +1,57 @@ +package cn.novalon.manage.sys.infrastructure.db.repository; + +import cn.novalon.manage.sys.core.domain.SysMenu; +import cn.novalon.manage.sys.core.repository.ISysMenuRepository; +import cn.novalon.manage.sys.infrastructure.db.converter.SysMenuConverter; +import cn.novalon.manage.sys.infrastructure.db.dao.SysMenuDao; +import org.springframework.stereotype.Repository; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; + +import java.time.LocalDateTime; + +@Repository +public class SysMenuRepository implements ISysMenuRepository { + + private final SysMenuDao dao; + private final SysMenuConverter converter; + + public SysMenuRepository(SysMenuDao dao, SysMenuConverter converter) { + this.dao = dao; + this.converter = converter; + } + + @Override + public Mono findById(Long id) { + return dao.findByIdAndDeletedAtIsNull(id) + .map(converter::toDomain); + } + + @Override + public Flux findAll() { + return dao.findByDeletedAtIsNull() + .map(converter::toDomain); + } + + @Override + public Flux findByParentId(Long parentId) { + return dao.findByParentIdAndDeletedAtIsNull(parentId) + .map(converter::toDomain); + } + + @Override + public Mono save(SysMenu sysMenu) { + return dao.save(converter.toEntity(sysMenu)) + .map(converter::toDomain); + } + + @Override + public Mono deleteById(Long id) { + return dao.findByIdAndDeletedAtIsNull(id) + .flatMap(entity -> { + entity.setDeletedAt(LocalDateTime.now()); + return dao.save(entity); + }) + .then(); + } +} diff --git a/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/infrastructure/db/repository/SysRoleRepository.java b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/infrastructure/db/repository/SysRoleRepository.java new file mode 100644 index 0000000..48ff0b6 --- /dev/null +++ b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/infrastructure/db/repository/SysRoleRepository.java @@ -0,0 +1,51 @@ +package cn.novalon.manage.sys.infrastructure.db.repository; + +import cn.novalon.manage.sys.core.domain.SysRole; +import cn.novalon.manage.sys.core.repository.ISysRoleRepository; +import cn.novalon.manage.sys.infrastructure.db.converter.SysRoleConverter; +import cn.novalon.manage.sys.infrastructure.db.dao.SysRoleDao; +import org.springframework.stereotype.Repository; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; + +import java.time.LocalDateTime; + +@Repository +public class SysRoleRepository implements ISysRoleRepository { + + private final SysRoleDao dao; + private final SysRoleConverter converter; + + public SysRoleRepository(SysRoleDao dao, SysRoleConverter converter) { + this.dao = dao; + this.converter = converter; + } + + @Override + public Mono findById(Long id) { + return dao.findById(id) + .map(converter::toDomain); + } + + @Override + public Mono save(SysRole sysRole) { + return dao.save(converter.toEntity(sysRole)) + .map(converter::toDomain); + } + + @Override + public Mono deleteById(Long id) { + return dao.findById(id) + .flatMap(entity -> { + entity.setDeletedAt(LocalDateTime.now()); + return dao.save(entity); + }) + .then(); + } + + @Override + public Flux findAll() { + return dao.findByDeletedAtIsNull() + .map(converter::toDomain); + } +} diff --git a/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/infrastructure/db/repository/SysUserRepository.java b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/infrastructure/db/repository/SysUserRepository.java new file mode 100644 index 0000000..9d5ee4d --- /dev/null +++ b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/infrastructure/db/repository/SysUserRepository.java @@ -0,0 +1,57 @@ +package cn.novalon.manage.sys.infrastructure.db.repository; + +import cn.novalon.manage.sys.core.domain.SysUser; +import cn.novalon.manage.sys.core.repository.ISysUserRepository; +import cn.novalon.manage.sys.infrastructure.db.converter.SysUserConverter; +import cn.novalon.manage.sys.infrastructure.db.dao.SysUserDao; +import org.springframework.stereotype.Repository; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; + +import java.time.LocalDateTime; + +@Repository +public class SysUserRepository implements ISysUserRepository { + + private final SysUserDao dao; + private final SysUserConverter converter; + + public SysUserRepository(SysUserDao dao, SysUserConverter converter) { + this.dao = dao; + this.converter = converter; + } + + @Override + public Mono findByUsername(String username) { + return dao.findByUsernameAndDeletedAtIsNull(username) + .map(converter::toDomain); + } + + @Override + public Mono findById(Long id) { + return dao.findById(id) + .map(converter::toDomain); + } + + @Override + public Mono save(SysUser sysUser) { + return dao.save(converter.toEntity(sysUser)) + .map(converter::toDomain); + } + + @Override + public Mono deleteById(Long id) { + return dao.findById(id) + .flatMap(entity -> { + entity.setDeletedAt(LocalDateTime.now()); + return dao.save(entity); + }) + .then(); + } + + @Override + public Flux findAll() { + return dao.findByDeletedAtIsNull() + .map(converter::toDomain); + } +} diff --git a/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/security/JwtTokenProvider.java b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/security/JwtTokenProvider.java new file mode 100644 index 0000000..3adca6d --- /dev/null +++ b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/security/JwtTokenProvider.java @@ -0,0 +1,66 @@ +package cn.novalon.manage.sys.security; + +import io.jsonwebtoken.Claims; +import io.jsonwebtoken.Jwts; +import io.jsonwebtoken.security.Keys; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; + +import javax.crypto.SecretKey; +import java.nio.charset.StandardCharsets; +import java.util.Date; +import java.util.HashMap; +import java.util.Map; + +@Component +public class JwtTokenProvider { + + @Value("${jwt.secret}") + private String jwtSecret; + + @Value("${jwt.expiration}") + private long jwtExpiration; + + private SecretKey getSigningKey() { + return Keys.hmacShaKeyFor(jwtSecret.getBytes(StandardCharsets.UTF_8)); + } + + public String generateToken(String username, Long userId) { + Map claims = new HashMap<>(); + claims.put("userId", userId); + claims.put("username", username); + + return Jwts.builder() + .setClaims(claims) + .setSubject(username) + .setIssuedAt(new Date()) + .setExpiration(new Date(System.currentTimeMillis() + jwtExpiration)) + .signWith(getSigningKey()) + .compact(); + } + + public Claims getClaimsFromToken(String token) { + return Jwts.parserBuilder() + .setSigningKey(getSigningKey()) + .build() + .parseClaimsJws(token) + .getBody(); + } + + public String getUsernameFromToken(String token) { + return getClaimsFromToken(token).getSubject(); + } + + public Long getUserIdFromToken(String token) { + return getClaimsFromToken(token).get("userId", Long.class); + } + + public boolean validateToken(String token) { + try { + getClaimsFromToken(token); + return true; + } catch (Exception e) { + return false; + } + } +} diff --git a/novalon-manage-api/manage-sys/src/main/resources/application.yml b/novalon-manage-api/manage-sys/src/main/resources/application.yml new file mode 100644 index 0000000..a8ea9c0 --- /dev/null +++ b/novalon-manage-api/manage-sys/src/main/resources/application.yml @@ -0,0 +1,25 @@ +server: + port: 8080 + +spring: + application: + name: novalon-manage-api + datasource: + url: jdbc:postgresql://localhost:55432/manage_system + username: postgres + password: postgres + driver-class-name: org.postgresql.Driver + r2dbc: + url: r2dbc:pool:postgresql://localhost:55432/manage_system + username: postgres + password: postgres + flyway: + enabled: false + +jwt: + secret: novalon-manage-secret-key-change-in-production + expiration: 86400000 + +logging: + level: + cn.novalon.manage: DEBUG diff --git a/novalon-manage-api/manage-sys/target/classes/application.yml b/novalon-manage-api/manage-sys/target/classes/application.yml new file mode 100644 index 0000000..a8ea9c0 --- /dev/null +++ b/novalon-manage-api/manage-sys/target/classes/application.yml @@ -0,0 +1,25 @@ +server: + port: 8080 + +spring: + application: + name: novalon-manage-api + datasource: + url: jdbc:postgresql://localhost:55432/manage_system + username: postgres + password: postgres + driver-class-name: org.postgresql.Driver + r2dbc: + url: r2dbc:pool:postgresql://localhost:55432/manage_system + username: postgres + password: postgres + flyway: + enabled: false + +jwt: + secret: novalon-manage-secret-key-change-in-production + expiration: 86400000 + +logging: + level: + cn.novalon.manage: DEBUG diff --git a/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/ManageSysApplication.class b/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/ManageSysApplication.class new file mode 100644 index 0000000..c1c405f Binary files /dev/null and b/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/ManageSysApplication.class differ diff --git a/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/config/SecurityConfig.class b/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/config/SecurityConfig.class new file mode 100644 index 0000000..efbba7e Binary files /dev/null and b/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/config/SecurityConfig.class differ diff --git a/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/config/SystemWebSocketHandler.class b/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/config/SystemWebSocketHandler.class new file mode 100644 index 0000000..f1da4a4 Binary files /dev/null and b/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/config/SystemWebSocketHandler.class differ diff --git a/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/config/WebSocketConfig.class b/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/config/WebSocketConfig.class new file mode 100644 index 0000000..86d8e48 Binary files /dev/null and b/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/config/WebSocketConfig.class differ diff --git a/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/core/domain/BaseDomain.class b/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/core/domain/BaseDomain.class new file mode 100644 index 0000000..374c4b1 Binary files /dev/null and b/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/core/domain/BaseDomain.class differ diff --git a/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/core/domain/OperationLog.class b/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/core/domain/OperationLog.class new file mode 100644 index 0000000..ba256e0 Binary files /dev/null and b/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/core/domain/OperationLog.class differ diff --git a/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/core/domain/SysConfig.class b/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/core/domain/SysConfig.class new file mode 100644 index 0000000..a325a79 Binary files /dev/null and b/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/core/domain/SysConfig.class differ diff --git a/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/core/domain/SysDictData.class b/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/core/domain/SysDictData.class new file mode 100644 index 0000000..555e3f4 Binary files /dev/null and b/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/core/domain/SysDictData.class differ diff --git a/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/core/domain/SysDictType.class b/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/core/domain/SysDictType.class new file mode 100644 index 0000000..ac687d9 Binary files /dev/null and b/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/core/domain/SysDictType.class differ diff --git a/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/core/domain/SysExceptionLog.class b/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/core/domain/SysExceptionLog.class new file mode 100644 index 0000000..8f72432 Binary files /dev/null and b/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/core/domain/SysExceptionLog.class differ diff --git a/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/core/domain/SysFile.class b/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/core/domain/SysFile.class new file mode 100644 index 0000000..ecf4eeb Binary files /dev/null and b/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/core/domain/SysFile.class differ diff --git a/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/core/domain/SysLoginLog.class b/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/core/domain/SysLoginLog.class new file mode 100644 index 0000000..6554ffb Binary files /dev/null and b/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/core/domain/SysLoginLog.class differ diff --git a/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/core/domain/SysMenu.class b/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/core/domain/SysMenu.class new file mode 100644 index 0000000..8560f06 Binary files /dev/null and b/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/core/domain/SysMenu.class differ diff --git a/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/core/domain/SysNotice.class b/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/core/domain/SysNotice.class new file mode 100644 index 0000000..ad09311 Binary files /dev/null and b/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/core/domain/SysNotice.class differ diff --git a/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/core/domain/SysRole.class b/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/core/domain/SysRole.class new file mode 100644 index 0000000..21883f9 Binary files /dev/null and b/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/core/domain/SysRole.class differ diff --git a/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/core/domain/SysUser.class b/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/core/domain/SysUser.class new file mode 100644 index 0000000..32e97d1 Binary files /dev/null and b/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/core/domain/SysUser.class differ diff --git a/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/core/domain/SysUserMessage.class b/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/core/domain/SysUserMessage.class new file mode 100644 index 0000000..58d223f Binary files /dev/null and b/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/core/domain/SysUserMessage.class differ diff --git a/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/core/repository/IOperationLogRepository.class b/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/core/repository/IOperationLogRepository.class new file mode 100644 index 0000000..947e26c Binary files /dev/null and b/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/core/repository/IOperationLogRepository.class differ diff --git a/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/core/repository/ISysMenuRepository.class b/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/core/repository/ISysMenuRepository.class new file mode 100644 index 0000000..5a4d53a Binary files /dev/null and b/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/core/repository/ISysMenuRepository.class differ diff --git a/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/core/repository/ISysRoleRepository.class b/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/core/repository/ISysRoleRepository.class new file mode 100644 index 0000000..5912211 Binary files /dev/null and b/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/core/repository/ISysRoleRepository.class differ diff --git a/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/core/repository/ISysUserRepository.class b/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/core/repository/ISysUserRepository.class new file mode 100644 index 0000000..8e286ce Binary files /dev/null and b/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/core/repository/ISysUserRepository.class differ diff --git a/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/core/service/IOperationLogService.class b/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/core/service/IOperationLogService.class new file mode 100644 index 0000000..0eca9bf Binary files /dev/null and b/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/core/service/IOperationLogService.class differ diff --git a/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/core/service/ISysConfigService.class b/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/core/service/ISysConfigService.class new file mode 100644 index 0000000..a4c969f Binary files /dev/null and b/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/core/service/ISysConfigService.class differ diff --git a/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/core/service/ISysDictDataService.class b/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/core/service/ISysDictDataService.class new file mode 100644 index 0000000..451d84c Binary files /dev/null and b/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/core/service/ISysDictDataService.class differ diff --git a/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/core/service/ISysDictTypeService.class b/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/core/service/ISysDictTypeService.class new file mode 100644 index 0000000..9ffaef2 Binary files /dev/null and b/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/core/service/ISysDictTypeService.class differ diff --git a/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/core/service/ISysExceptionLogService.class b/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/core/service/ISysExceptionLogService.class new file mode 100644 index 0000000..68bdb48 Binary files /dev/null and b/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/core/service/ISysExceptionLogService.class differ diff --git a/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/core/service/ISysFileService.class b/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/core/service/ISysFileService.class new file mode 100644 index 0000000..58ea07c Binary files /dev/null and b/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/core/service/ISysFileService.class differ diff --git a/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/core/service/ISysLoginLogService.class b/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/core/service/ISysLoginLogService.class new file mode 100644 index 0000000..7642cb6 Binary files /dev/null and b/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/core/service/ISysLoginLogService.class differ diff --git a/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/core/service/ISysMenuService.class b/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/core/service/ISysMenuService.class new file mode 100644 index 0000000..abd9cd0 Binary files /dev/null and b/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/core/service/ISysMenuService.class differ diff --git a/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/core/service/ISysNoticeService.class b/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/core/service/ISysNoticeService.class new file mode 100644 index 0000000..77144bb Binary files /dev/null and b/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/core/service/ISysNoticeService.class differ diff --git a/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/core/service/ISysRoleService.class b/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/core/service/ISysRoleService.class new file mode 100644 index 0000000..70bf88a Binary files /dev/null and b/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/core/service/ISysRoleService.class differ diff --git a/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/core/service/ISysUserMessageService.class b/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/core/service/ISysUserMessageService.class new file mode 100644 index 0000000..6340b7d Binary files /dev/null and b/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/core/service/ISysUserMessageService.class differ diff --git a/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/core/service/ISysUserService.class b/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/core/service/ISysUserService.class new file mode 100644 index 0000000..7aee1b8 Binary files /dev/null and b/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/core/service/ISysUserService.class differ diff --git a/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/core/service/impl/OperationLogService.class b/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/core/service/impl/OperationLogService.class new file mode 100644 index 0000000..3fba473 Binary files /dev/null and b/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/core/service/impl/OperationLogService.class differ diff --git a/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/core/service/impl/SysConfigServiceImpl.class b/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/core/service/impl/SysConfigServiceImpl.class new file mode 100644 index 0000000..bcd02d1 Binary files /dev/null and b/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/core/service/impl/SysConfigServiceImpl.class differ diff --git a/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/core/service/impl/SysDictDataServiceImpl.class b/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/core/service/impl/SysDictDataServiceImpl.class new file mode 100644 index 0000000..47b591b Binary files /dev/null and b/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/core/service/impl/SysDictDataServiceImpl.class differ diff --git a/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/core/service/impl/SysDictTypeServiceImpl.class b/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/core/service/impl/SysDictTypeServiceImpl.class new file mode 100644 index 0000000..104d7a9 Binary files /dev/null and b/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/core/service/impl/SysDictTypeServiceImpl.class differ diff --git a/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/core/service/impl/SysExceptionLogServiceImpl.class b/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/core/service/impl/SysExceptionLogServiceImpl.class new file mode 100644 index 0000000..7b8ca80 Binary files /dev/null and b/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/core/service/impl/SysExceptionLogServiceImpl.class differ diff --git a/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/core/service/impl/SysFileServiceImpl.class b/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/core/service/impl/SysFileServiceImpl.class new file mode 100644 index 0000000..7fd6f7b Binary files /dev/null and b/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/core/service/impl/SysFileServiceImpl.class differ diff --git a/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/core/service/impl/SysLoginLogServiceImpl.class b/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/core/service/impl/SysLoginLogServiceImpl.class new file mode 100644 index 0000000..bff675b Binary files /dev/null and b/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/core/service/impl/SysLoginLogServiceImpl.class differ diff --git a/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/core/service/impl/SysMenuService.class b/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/core/service/impl/SysMenuService.class new file mode 100644 index 0000000..079baab Binary files /dev/null and b/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/core/service/impl/SysMenuService.class differ diff --git a/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/core/service/impl/SysNoticeServiceImpl.class b/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/core/service/impl/SysNoticeServiceImpl.class new file mode 100644 index 0000000..6a13a2a Binary files /dev/null and b/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/core/service/impl/SysNoticeServiceImpl.class differ diff --git a/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/core/service/impl/SysRoleService.class b/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/core/service/impl/SysRoleService.class new file mode 100644 index 0000000..bd29273 Binary files /dev/null and b/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/core/service/impl/SysRoleService.class differ diff --git a/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/core/service/impl/SysUserMessageServiceImpl.class b/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/core/service/impl/SysUserMessageServiceImpl.class new file mode 100644 index 0000000..962a4ac Binary files /dev/null and b/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/core/service/impl/SysUserMessageServiceImpl.class differ diff --git a/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/core/service/impl/SysUserService.class b/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/core/service/impl/SysUserService.class new file mode 100644 index 0000000..0c2cfa2 Binary files /dev/null and b/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/core/service/impl/SysUserService.class differ diff --git a/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/dto/request/LoginRequest.class b/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/dto/request/LoginRequest.class new file mode 100644 index 0000000..dc66ac9 Binary files /dev/null and b/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/dto/request/LoginRequest.class differ diff --git a/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/dto/request/PasswordChangeRequest.class b/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/dto/request/PasswordChangeRequest.class new file mode 100644 index 0000000..147b4ea Binary files /dev/null and b/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/dto/request/PasswordChangeRequest.class differ diff --git a/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/dto/request/UserRegisterRequest.class b/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/dto/request/UserRegisterRequest.class new file mode 100644 index 0000000..7f793be Binary files /dev/null and b/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/dto/request/UserRegisterRequest.class differ diff --git a/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/dto/request/UserUpdateRequest.class b/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/dto/request/UserUpdateRequest.class new file mode 100644 index 0000000..ffc401b Binary files /dev/null and b/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/dto/request/UserUpdateRequest.class differ diff --git a/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/dto/response/AuthResponse.class b/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/dto/response/AuthResponse.class new file mode 100644 index 0000000..bad7cab Binary files /dev/null and b/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/dto/response/AuthResponse.class differ diff --git a/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/dto/response/UserResponse.class b/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/dto/response/UserResponse.class new file mode 100644 index 0000000..3256482 Binary files /dev/null and b/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/dto/response/UserResponse.class differ diff --git a/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/handler/GlobalExceptionHandler.class b/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/handler/GlobalExceptionHandler.class new file mode 100644 index 0000000..a839da3 Binary files /dev/null and b/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/handler/GlobalExceptionHandler.class differ diff --git a/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/handler/auth/SysAuthHandler.class b/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/handler/auth/SysAuthHandler.class new file mode 100644 index 0000000..fdbded3 Binary files /dev/null and b/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/handler/auth/SysAuthHandler.class differ diff --git a/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/handler/sys/SysConfigHandler.class b/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/handler/sys/SysConfigHandler.class new file mode 100644 index 0000000..dce0b87 Binary files /dev/null and b/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/handler/sys/SysConfigHandler.class differ diff --git a/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/handler/sys/SysDictHandler.class b/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/handler/sys/SysDictHandler.class new file mode 100644 index 0000000..aa481da Binary files /dev/null and b/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/handler/sys/SysDictHandler.class differ diff --git a/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/handler/sys/SysFileHandler.class b/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/handler/sys/SysFileHandler.class new file mode 100644 index 0000000..5ba3e0b Binary files /dev/null and b/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/handler/sys/SysFileHandler.class differ diff --git a/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/handler/sys/SysLogHandler.class b/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/handler/sys/SysLogHandler.class new file mode 100644 index 0000000..d6703c7 Binary files /dev/null and b/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/handler/sys/SysLogHandler.class differ diff --git a/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/handler/sys/SysMenuHandler.class b/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/handler/sys/SysMenuHandler.class new file mode 100644 index 0000000..8b370ff Binary files /dev/null and b/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/handler/sys/SysMenuHandler.class differ diff --git a/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/handler/sys/SysMessageHandler.class b/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/handler/sys/SysMessageHandler.class new file mode 100644 index 0000000..63ed3b3 Binary files /dev/null and b/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/handler/sys/SysMessageHandler.class differ diff --git a/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/handler/sys/SysNoticeHandler.class b/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/handler/sys/SysNoticeHandler.class new file mode 100644 index 0000000..8c56574 Binary files /dev/null and b/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/handler/sys/SysNoticeHandler.class differ diff --git a/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/handler/sys/SysRoleHandler.class b/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/handler/sys/SysRoleHandler.class new file mode 100644 index 0000000..7b7802f Binary files /dev/null and b/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/handler/sys/SysRoleHandler.class differ diff --git a/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/handler/user/SysUserHandler.class b/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/handler/user/SysUserHandler.class new file mode 100644 index 0000000..acad8a1 Binary files /dev/null and b/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/handler/user/SysUserHandler.class differ diff --git a/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/infrastructure/db/converter/OperationLogConverter.class b/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/infrastructure/db/converter/OperationLogConverter.class new file mode 100644 index 0000000..2e26150 Binary files /dev/null and b/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/infrastructure/db/converter/OperationLogConverter.class differ diff --git a/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/infrastructure/db/converter/SysConfigConverter.class b/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/infrastructure/db/converter/SysConfigConverter.class new file mode 100644 index 0000000..9f149de Binary files /dev/null and b/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/infrastructure/db/converter/SysConfigConverter.class differ diff --git a/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/infrastructure/db/converter/SysDictDataConverter.class b/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/infrastructure/db/converter/SysDictDataConverter.class new file mode 100644 index 0000000..d8fd7f6 Binary files /dev/null and b/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/infrastructure/db/converter/SysDictDataConverter.class differ diff --git a/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/infrastructure/db/converter/SysDictTypeConverter.class b/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/infrastructure/db/converter/SysDictTypeConverter.class new file mode 100644 index 0000000..387da0f Binary files /dev/null and b/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/infrastructure/db/converter/SysDictTypeConverter.class differ diff --git a/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/infrastructure/db/converter/SysExceptionLogConverter.class b/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/infrastructure/db/converter/SysExceptionLogConverter.class new file mode 100644 index 0000000..95e3075 Binary files /dev/null and b/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/infrastructure/db/converter/SysExceptionLogConverter.class differ diff --git a/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/infrastructure/db/converter/SysFileConverter.class b/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/infrastructure/db/converter/SysFileConverter.class new file mode 100644 index 0000000..e2f2dea Binary files /dev/null and b/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/infrastructure/db/converter/SysFileConverter.class differ diff --git a/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/infrastructure/db/converter/SysLoginLogConverter.class b/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/infrastructure/db/converter/SysLoginLogConverter.class new file mode 100644 index 0000000..31dbfad Binary files /dev/null and b/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/infrastructure/db/converter/SysLoginLogConverter.class differ diff --git a/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/infrastructure/db/converter/SysMenuConverter.class b/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/infrastructure/db/converter/SysMenuConverter.class new file mode 100644 index 0000000..a2a3123 Binary files /dev/null and b/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/infrastructure/db/converter/SysMenuConverter.class differ diff --git a/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/infrastructure/db/converter/SysNoticeConverter.class b/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/infrastructure/db/converter/SysNoticeConverter.class new file mode 100644 index 0000000..79a7431 Binary files /dev/null and b/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/infrastructure/db/converter/SysNoticeConverter.class differ diff --git a/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/infrastructure/db/converter/SysRoleConverter.class b/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/infrastructure/db/converter/SysRoleConverter.class new file mode 100644 index 0000000..34348ec Binary files /dev/null and b/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/infrastructure/db/converter/SysRoleConverter.class differ diff --git a/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/infrastructure/db/converter/SysUserConverter.class b/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/infrastructure/db/converter/SysUserConverter.class new file mode 100644 index 0000000..712d1cd Binary files /dev/null and b/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/infrastructure/db/converter/SysUserConverter.class differ diff --git a/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/infrastructure/db/converter/SysUserMessageConverter.class b/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/infrastructure/db/converter/SysUserMessageConverter.class new file mode 100644 index 0000000..8a3fe48 Binary files /dev/null and b/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/infrastructure/db/converter/SysUserMessageConverter.class differ diff --git a/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/infrastructure/db/dao/OperationLogDao.class b/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/infrastructure/db/dao/OperationLogDao.class new file mode 100644 index 0000000..62f692d Binary files /dev/null and b/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/infrastructure/db/dao/OperationLogDao.class differ diff --git a/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/infrastructure/db/dao/SysConfigDao.class b/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/infrastructure/db/dao/SysConfigDao.class new file mode 100644 index 0000000..bce344f Binary files /dev/null and b/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/infrastructure/db/dao/SysConfigDao.class differ diff --git a/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/infrastructure/db/dao/SysDictDataDao.class b/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/infrastructure/db/dao/SysDictDataDao.class new file mode 100644 index 0000000..5239a6a Binary files /dev/null and b/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/infrastructure/db/dao/SysDictDataDao.class differ diff --git a/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/infrastructure/db/dao/SysDictTypeDao.class b/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/infrastructure/db/dao/SysDictTypeDao.class new file mode 100644 index 0000000..fccfa94 Binary files /dev/null and b/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/infrastructure/db/dao/SysDictTypeDao.class differ diff --git a/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/infrastructure/db/dao/SysExceptionLogDao.class b/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/infrastructure/db/dao/SysExceptionLogDao.class new file mode 100644 index 0000000..10bef35 Binary files /dev/null and b/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/infrastructure/db/dao/SysExceptionLogDao.class differ diff --git a/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/infrastructure/db/dao/SysFileDao.class b/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/infrastructure/db/dao/SysFileDao.class new file mode 100644 index 0000000..256158a Binary files /dev/null and b/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/infrastructure/db/dao/SysFileDao.class differ diff --git a/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/infrastructure/db/dao/SysLoginLogDao.class b/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/infrastructure/db/dao/SysLoginLogDao.class new file mode 100644 index 0000000..bdaa6b8 Binary files /dev/null and b/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/infrastructure/db/dao/SysLoginLogDao.class differ diff --git a/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/infrastructure/db/dao/SysMenuDao.class b/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/infrastructure/db/dao/SysMenuDao.class new file mode 100644 index 0000000..b845dd1 Binary files /dev/null and b/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/infrastructure/db/dao/SysMenuDao.class differ diff --git a/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/infrastructure/db/dao/SysNoticeDao.class b/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/infrastructure/db/dao/SysNoticeDao.class new file mode 100644 index 0000000..6c25a3f Binary files /dev/null and b/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/infrastructure/db/dao/SysNoticeDao.class differ diff --git a/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/infrastructure/db/dao/SysRoleDao.class b/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/infrastructure/db/dao/SysRoleDao.class new file mode 100644 index 0000000..c775f4b Binary files /dev/null and b/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/infrastructure/db/dao/SysRoleDao.class differ diff --git a/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/infrastructure/db/dao/SysUserDao.class b/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/infrastructure/db/dao/SysUserDao.class new file mode 100644 index 0000000..752b789 Binary files /dev/null and b/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/infrastructure/db/dao/SysUserDao.class differ diff --git a/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/infrastructure/db/dao/SysUserMessageDao.class b/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/infrastructure/db/dao/SysUserMessageDao.class new file mode 100644 index 0000000..2785f4d Binary files /dev/null and b/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/infrastructure/db/dao/SysUserMessageDao.class differ diff --git a/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/infrastructure/db/entity/BaseEntity.class b/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/infrastructure/db/entity/BaseEntity.class new file mode 100644 index 0000000..70c8e9c Binary files /dev/null and b/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/infrastructure/db/entity/BaseEntity.class differ diff --git a/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/infrastructure/db/entity/OperationLogEntity.class b/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/infrastructure/db/entity/OperationLogEntity.class new file mode 100644 index 0000000..21fbf4b Binary files /dev/null and b/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/infrastructure/db/entity/OperationLogEntity.class differ diff --git a/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/infrastructure/db/entity/SysConfigEntity.class b/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/infrastructure/db/entity/SysConfigEntity.class new file mode 100644 index 0000000..5499aae Binary files /dev/null and b/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/infrastructure/db/entity/SysConfigEntity.class differ diff --git a/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/infrastructure/db/entity/SysDictDataEntity.class b/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/infrastructure/db/entity/SysDictDataEntity.class new file mode 100644 index 0000000..41123a3 Binary files /dev/null and b/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/infrastructure/db/entity/SysDictDataEntity.class differ diff --git a/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/infrastructure/db/entity/SysDictTypeEntity.class b/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/infrastructure/db/entity/SysDictTypeEntity.class new file mode 100644 index 0000000..49bf039 Binary files /dev/null and b/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/infrastructure/db/entity/SysDictTypeEntity.class differ diff --git a/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/infrastructure/db/entity/SysExceptionLogEntity.class b/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/infrastructure/db/entity/SysExceptionLogEntity.class new file mode 100644 index 0000000..b0bf354 Binary files /dev/null and b/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/infrastructure/db/entity/SysExceptionLogEntity.class differ diff --git a/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/infrastructure/db/entity/SysFileEntity.class b/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/infrastructure/db/entity/SysFileEntity.class new file mode 100644 index 0000000..028d1c9 Binary files /dev/null and b/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/infrastructure/db/entity/SysFileEntity.class differ diff --git a/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/infrastructure/db/entity/SysLoginLogEntity.class b/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/infrastructure/db/entity/SysLoginLogEntity.class new file mode 100644 index 0000000..df0d2ab Binary files /dev/null and b/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/infrastructure/db/entity/SysLoginLogEntity.class differ diff --git a/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/infrastructure/db/entity/SysMenuEntity.class b/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/infrastructure/db/entity/SysMenuEntity.class new file mode 100644 index 0000000..ed46735 Binary files /dev/null and b/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/infrastructure/db/entity/SysMenuEntity.class differ diff --git a/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/infrastructure/db/entity/SysNoticeEntity.class b/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/infrastructure/db/entity/SysNoticeEntity.class new file mode 100644 index 0000000..576b19d Binary files /dev/null and b/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/infrastructure/db/entity/SysNoticeEntity.class differ diff --git a/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/infrastructure/db/entity/SysRoleEntity.class b/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/infrastructure/db/entity/SysRoleEntity.class new file mode 100644 index 0000000..01e9a50 Binary files /dev/null and b/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/infrastructure/db/entity/SysRoleEntity.class differ diff --git a/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/infrastructure/db/entity/SysUserEntity.class b/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/infrastructure/db/entity/SysUserEntity.class new file mode 100644 index 0000000..55b9cb2 Binary files /dev/null and b/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/infrastructure/db/entity/SysUserEntity.class differ diff --git a/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/infrastructure/db/entity/SysUserMessageEntity.class b/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/infrastructure/db/entity/SysUserMessageEntity.class new file mode 100644 index 0000000..65c884c Binary files /dev/null and b/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/infrastructure/db/entity/SysUserMessageEntity.class differ diff --git a/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/infrastructure/db/repository/OperationLogRepository.class b/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/infrastructure/db/repository/OperationLogRepository.class new file mode 100644 index 0000000..d58d3a9 Binary files /dev/null and b/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/infrastructure/db/repository/OperationLogRepository.class differ diff --git a/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/infrastructure/db/repository/SysMenuRepository.class b/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/infrastructure/db/repository/SysMenuRepository.class new file mode 100644 index 0000000..9b5427c Binary files /dev/null and b/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/infrastructure/db/repository/SysMenuRepository.class differ diff --git a/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/infrastructure/db/repository/SysRoleRepository.class b/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/infrastructure/db/repository/SysRoleRepository.class new file mode 100644 index 0000000..3bc1dfe Binary files /dev/null and b/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/infrastructure/db/repository/SysRoleRepository.class differ diff --git a/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/infrastructure/db/repository/SysUserRepository.class b/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/infrastructure/db/repository/SysUserRepository.class new file mode 100644 index 0000000..c375c90 Binary files /dev/null and b/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/infrastructure/db/repository/SysUserRepository.class differ diff --git a/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/security/JwtTokenProvider.class b/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/security/JwtTokenProvider.class new file mode 100644 index 0000000..fed7b02 Binary files /dev/null and b/novalon-manage-api/manage-sys/target/classes/cn/novalon/manage/sys/security/JwtTokenProvider.class differ diff --git a/novalon-manage-api/manage-sys/target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst b/novalon-manage-api/manage-sys/target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst new file mode 100644 index 0000000..cec3e6f --- /dev/null +++ b/novalon-manage-api/manage-sys/target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst @@ -0,0 +1,22 @@ +cn/novalon/manage/sys/core/domain/SysUser.class +cn/novalon/manage/sys/core/domain/SysFile.class +cn/novalon/manage/sys/core/domain/SysNotice.class +cn/novalon/manage/sys/core/service/IOperationLogService.class +cn/novalon/manage/sys/core/repository/ISysMenuRepository.class +cn/novalon/manage/sys/core/service/ISysUserService.class +cn/novalon/manage/sys/core/service/ISysMenuService.class +cn/novalon/manage/sys/core/domain/SysLoginLog.class +cn/novalon/manage/sys/core/domain/SysDictData.class +cn/novalon/manage/sys/core/repository/ISysUserRepository.class +cn/novalon/manage/sys/core/domain/SysDictType.class +cn/novalon/manage/sys/core/domain/SysRole.class +cn/novalon/manage/sys/core/domain/BaseDomain.class +cn/novalon/manage/sys/core/repository/IOperationLogRepository.class +cn/novalon/manage/sys/core/domain/SysConfig.class +cn/novalon/manage/sys/core/repository/ISysRoleRepository.class +cn/novalon/manage/sys/config/SecurityConfig.class +cn/novalon/manage/sys/ManageSysApplication.class +cn/novalon/manage/sys/core/service/ISysRoleService.class +cn/novalon/manage/sys/core/domain/OperationLog.class +cn/novalon/manage/sys/security/JwtTokenProvider.class +cn/novalon/manage/sys/core/domain/SysMenu.class diff --git a/novalon-manage-api/manage-sys/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst b/novalon-manage-api/manage-sys/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst new file mode 100644 index 0000000..76793c0 --- /dev/null +++ b/novalon-manage-api/manage-sys/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst @@ -0,0 +1,58 @@ +/Users/zhangxiang/Codes/Novalon/novalon-manage-system/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/ManageSysApplication.java +/Users/zhangxiang/Codes/Novalon/novalon-manage-system/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/config/SecurityConfig.java +/Users/zhangxiang/Codes/Novalon/novalon-manage-system/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/core/domain/BaseDomain.java +/Users/zhangxiang/Codes/Novalon/novalon-manage-system/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/core/domain/OperationLog.java +/Users/zhangxiang/Codes/Novalon/novalon-manage-system/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/core/domain/SysConfig.java +/Users/zhangxiang/Codes/Novalon/novalon-manage-system/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/core/domain/SysDictData.java +/Users/zhangxiang/Codes/Novalon/novalon-manage-system/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/core/domain/SysDictType.java +/Users/zhangxiang/Codes/Novalon/novalon-manage-system/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/core/domain/SysFile.java +/Users/zhangxiang/Codes/Novalon/novalon-manage-system/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/core/domain/SysLoginLog.java +/Users/zhangxiang/Codes/Novalon/novalon-manage-system/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/core/domain/SysMenu.java +/Users/zhangxiang/Codes/Novalon/novalon-manage-system/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/core/domain/SysNotice.java +/Users/zhangxiang/Codes/Novalon/novalon-manage-system/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/core/domain/SysRole.java +/Users/zhangxiang/Codes/Novalon/novalon-manage-system/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/core/domain/SysUser.java +/Users/zhangxiang/Codes/Novalon/novalon-manage-system/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/core/repository/IOperationLogRepository.java +/Users/zhangxiang/Codes/Novalon/novalon-manage-system/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/core/repository/ISysMenuRepository.java +/Users/zhangxiang/Codes/Novalon/novalon-manage-system/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/core/repository/ISysRoleRepository.java +/Users/zhangxiang/Codes/Novalon/novalon-manage-system/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/core/repository/ISysUserRepository.java +/Users/zhangxiang/Codes/Novalon/novalon-manage-system/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/core/service/IOperationLogService.java +/Users/zhangxiang/Codes/Novalon/novalon-manage-system/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/core/service/ISysMenuService.java +/Users/zhangxiang/Codes/Novalon/novalon-manage-system/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/core/service/ISysRoleService.java +/Users/zhangxiang/Codes/Novalon/novalon-manage-system/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/core/service/ISysUserService.java +/Users/zhangxiang/Codes/Novalon/novalon-manage-system/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/core/service/impl/OperationLogService.java +/Users/zhangxiang/Codes/Novalon/novalon-manage-system/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/core/service/impl/SysMenuService.java +/Users/zhangxiang/Codes/Novalon/novalon-manage-system/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/core/service/impl/SysRoleService.java +/Users/zhangxiang/Codes/Novalon/novalon-manage-system/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/core/service/impl/SysUserService.java +/Users/zhangxiang/Codes/Novalon/novalon-manage-system/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/dto/request/LoginRequest.java +/Users/zhangxiang/Codes/Novalon/novalon-manage-system/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/dto/request/PasswordChangeRequest.java +/Users/zhangxiang/Codes/Novalon/novalon-manage-system/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/dto/request/UserRegisterRequest.java +/Users/zhangxiang/Codes/Novalon/novalon-manage-system/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/dto/request/UserUpdateRequest.java +/Users/zhangxiang/Codes/Novalon/novalon-manage-system/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/dto/response/AuthResponse.java +/Users/zhangxiang/Codes/Novalon/novalon-manage-system/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/dto/response/UserResponse.java +/Users/zhangxiang/Codes/Novalon/novalon-manage-system/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/handler/auth/SysAuthHandler.java +/Users/zhangxiang/Codes/Novalon/novalon-manage-system/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/handler/sys/SysConfigHandler.java +/Users/zhangxiang/Codes/Novalon/novalon-manage-system/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/handler/sys/SysDictHandler.java +/Users/zhangxiang/Codes/Novalon/novalon-manage-system/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/handler/sys/SysFileHandler.java +/Users/zhangxiang/Codes/Novalon/novalon-manage-system/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/handler/sys/SysLogHandler.java +/Users/zhangxiang/Codes/Novalon/novalon-manage-system/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/handler/sys/SysMenuHandler.java +/Users/zhangxiang/Codes/Novalon/novalon-manage-system/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/handler/sys/SysNoticeHandler.java +/Users/zhangxiang/Codes/Novalon/novalon-manage-system/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/handler/sys/SysRoleHandler.java +/Users/zhangxiang/Codes/Novalon/novalon-manage-system/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/handler/user/SysUserHandler.java +/Users/zhangxiang/Codes/Novalon/novalon-manage-system/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/infrastructure/db/converter/OperationLogConverter.java +/Users/zhangxiang/Codes/Novalon/novalon-manage-system/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/infrastructure/db/converter/SysMenuConverter.java +/Users/zhangxiang/Codes/Novalon/novalon-manage-system/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/infrastructure/db/converter/SysRoleConverter.java +/Users/zhangxiang/Codes/Novalon/novalon-manage-system/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/infrastructure/db/converter/SysUserConverter.java +/Users/zhangxiang/Codes/Novalon/novalon-manage-system/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/infrastructure/db/dao/OperationLogDao.java +/Users/zhangxiang/Codes/Novalon/novalon-manage-system/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/infrastructure/db/dao/SysMenuDao.java +/Users/zhangxiang/Codes/Novalon/novalon-manage-system/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/infrastructure/db/dao/SysRoleDao.java +/Users/zhangxiang/Codes/Novalon/novalon-manage-system/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/infrastructure/db/dao/SysUserDao.java +/Users/zhangxiang/Codes/Novalon/novalon-manage-system/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/infrastructure/db/entity/BaseEntity.java +/Users/zhangxiang/Codes/Novalon/novalon-manage-system/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/infrastructure/db/entity/OperationLogEntity.java +/Users/zhangxiang/Codes/Novalon/novalon-manage-system/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/infrastructure/db/entity/SysMenuEntity.java +/Users/zhangxiang/Codes/Novalon/novalon-manage-system/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/infrastructure/db/entity/SysRoleEntity.java +/Users/zhangxiang/Codes/Novalon/novalon-manage-system/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/infrastructure/db/entity/SysUserEntity.java +/Users/zhangxiang/Codes/Novalon/novalon-manage-system/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/infrastructure/db/repository/OperationLogRepository.java +/Users/zhangxiang/Codes/Novalon/novalon-manage-system/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/infrastructure/db/repository/SysMenuRepository.java +/Users/zhangxiang/Codes/Novalon/novalon-manage-system/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/infrastructure/db/repository/SysRoleRepository.java +/Users/zhangxiang/Codes/Novalon/novalon-manage-system/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/infrastructure/db/repository/SysUserRepository.java +/Users/zhangxiang/Codes/Novalon/novalon-manage-system/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/security/JwtTokenProvider.java diff --git a/novalon-manage-api/pom.xml b/novalon-manage-api/pom.xml new file mode 100644 index 0000000..a414732 --- /dev/null +++ b/novalon-manage-api/pom.xml @@ -0,0 +1,162 @@ + + + 4.0.0 + + + org.springframework.boot + spring-boot-starter-parent + 3.4.1 + + + + cn.novalon.manage + novalon-manage-api + 1.0.0 + pom + + Novalon Manage API + Novalon Enterprise Management System API + + + 21 + 21 + 21 + UTF-8 + 3.4.1 + + + + manage-sys + + + + + + org.springframework.boot + spring-boot-starter-webflux + ${spring-boot.version} + + + org.springframework.boot + spring-boot-starter-aop + ${spring-boot.version} + + + org.springframework.boot + spring-boot-starter-validation + ${spring-boot.version} + + + org.springframework.boot + spring-boot-starter-actuator + ${spring-boot.version} + + + org.springframework.security + spring-security-crypto + 6.5.0 + + + org.springframework.security + spring-security-config + 6.5.0 + + + org.springframework.boot + spring-boot-starter-data-r2dbc + ${spring-boot.version} + + + org.postgresql + r2dbc-postgresql + 1.0.0.RELEASE + + + com.google.guava + guava + 33.3.1-jre + + + com.github.ben-manes.caffeine + caffeine + 3.1.8 + + + org.apache.commons + commons-lang3 + 3.17.0 + + + io.jsonwebtoken + jjwt-api + 0.11.5 + + + io.jsonwebtoken + jjwt-impl + 0.11.5 + runtime + + + io.jsonwebtoken + jjwt-jackson + 0.11.5 + runtime + + + org.postgresql + postgresql + 42.7.4 + + + org.flywaydb + flyway-core + 11.0.1 + + + org.flywaydb + flyway-database-postgresql + 11.0.1 + + + org.springdoc + springdoc-openapi-starter-webflux-ui + 2.8.13 + + + org.jacoco + jacoco-maven-plugin + 0.8.12 + + + + + + + org.springframework.boot + spring-boot-starter-test + test + + + org.projectlombok + lombok + true + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.13.0 + + ${java.version} + ${java.version} + + + + + diff --git a/novalon-manage-web/package.json b/novalon-manage-web/package.json new file mode 100644 index 0000000..1074ff3 --- /dev/null +++ b/novalon-manage-web/package.json @@ -0,0 +1,49 @@ +{ + "name": "novalon-manage-web", + "version": "1.0.0", + "description": "Novalon Enterprise Management System Frontend", + "type": "module", + "scripts": { + "dev": "vite", + "dev:local": "vite --mode development-local", + "dev:test": "vite --mode test", + "build": "vue-tsc && vite build", + "build:test": "vue-tsc && vite build --mode test", + "build:prod": "vue-tsc && vite build --mode production", + "preview": "vite preview", + "test": "vitest --run", + "test:ui": "vitest --ui", + "test:e2e": "playwright test", + "lint": "eslint . --ext .vue,.js,.jsx,.cjs,.mjs,.ts,.tsx --fix --ignore-path .gitignore", + "format": "prettier --write src/" + }, + "dependencies": { + "ant-design-vue": "^4.2.6", + "axios": "^1.6.2", + "dayjs": "^1.11.10", + "pinia": "^3.0.4", + "vue": "^3.5.26", + "vue-i18n": "^9.8.0", + "vue-router": "^4.6.4" + }, + "devDependencies": { + "@playwright/test": "^1.40.1", + "@types/node": "^20.10.0", + "@typescript-eslint/eslint-plugin": "^6.18.1", + "@typescript-eslint/parser": "^6.18.1", + "@vitejs/plugin-vue": "^6.0.3", + "@vitest/ui": "^4.0.16", + "@vue/test-utils": "^2.4.3", + "autoprefixer": "^10.4.23", + "eslint": "^8.56.0", + "eslint-plugin-vue": "^9.19.2", + "jsdom": "^27.4.0", + "postcss": "^8.5.6", + "prettier": "^3.1.1", + "tailwindcss": "^4.1.18", + "typescript": "^5.9.3", + "vite": "^7.3.1", + "vitest": "^4.0.16", + "vue-tsc": "^3.2.2" + } +} diff --git a/novalon-manage-web/src/App.vue b/novalon-manage-web/src/App.vue new file mode 100644 index 0000000..c0a868b --- /dev/null +++ b/novalon-manage-web/src/App.vue @@ -0,0 +1,12 @@ + + + diff --git a/novalon-manage-web/src/layouts/DefaultLayout.vue b/novalon-manage-web/src/layouts/DefaultLayout.vue new file mode 100644 index 0000000..da4f76b --- /dev/null +++ b/novalon-manage-web/src/layouts/DefaultLayout.vue @@ -0,0 +1,137 @@ + + + + + diff --git a/novalon-manage-web/src/main.ts b/novalon-manage-web/src/main.ts new file mode 100644 index 0000000..d493205 --- /dev/null +++ b/novalon-manage-web/src/main.ts @@ -0,0 +1,18 @@ +import { createApp } from 'vue' +import { createPinia } from 'pinia' +import Antd from 'ant-design-vue' +import router from './router' +import i18n from './i18n' +import App from './App.vue' +import 'ant-design-vue/dist/reset.css' +import './styles/index.scss' + +const app = createApp(App) +const pinia = createPinia() + +app.use(pinia) +app.use(router) +app.use(i18n) +app.use(Antd) + +app.mount('#app') diff --git a/novalon-manage-web/src/router/index.ts b/novalon-manage-web/src/router/index.ts new file mode 100644 index 0000000..e45857a --- /dev/null +++ b/novalon-manage-web/src/router/index.ts @@ -0,0 +1,44 @@ +import { createRouter, createWebHistory } from 'vue-router' +import type { RouteRecordRaw } from 'vue-router' + +const routes: RouteRecordRaw[] = [ + { + path: '/login', + name: 'Login', + component: () => import('@/views/system/Login.vue') + }, + { + path: '/', + component: () => import('@/layouts/DefaultLayout.vue'), + redirect: '/dashboard', + children: [ + { + path: 'dashboard', + name: 'Dashboard', + component: () => import('@/views/system/Dashboard.vue') + }, + { + path: 'users', + name: 'UserManagement', + component: () => import('@/views/system/UserManagement.vue') + }, + { + path: 'roles', + name: 'RoleManagement', + component: () => import('@/views/system/RoleManagement.vue') + }, + { + path: 'menus', + name: 'MenuManagement', + component: () => import('@/views/system/MenuManagement.vue') + } + ] + } +] + +const router = createRouter({ + history: createWebHistory(), + routes +}) + +export default router diff --git a/novalon-manage-web/src/utils/request.ts b/novalon-manage-web/src/utils/request.ts new file mode 100644 index 0000000..cccfa5f --- /dev/null +++ b/novalon-manage-web/src/utils/request.ts @@ -0,0 +1,30 @@ +import axios from 'axios' + +const request = axios.create({ + baseURL: '/api', + timeout: 10000 +}) + +request.interceptors.request.use( + (config) => { + const token = localStorage.getItem('token') + if (token) { + config.headers.Authorization = `Bearer ${token}` + } + return config + }, + (error) => Promise.reject(error) +) + +request.interceptors.response.use( + (response) => response.data, + (error) => { + if (error.response?.status === 401) { + localStorage.removeItem('token') + window.location.href = '/login' + } + return Promise.reject(error) + } +) + +export default request diff --git a/novalon-manage-web/src/views/audit/LoginLog.vue b/novalon-manage-web/src/views/audit/LoginLog.vue new file mode 100644 index 0000000..6d335bd --- /dev/null +++ b/novalon-manage-web/src/views/audit/LoginLog.vue @@ -0,0 +1,49 @@ + + + + + diff --git a/novalon-manage-web/src/views/audit/OperationLog.vue b/novalon-manage-web/src/views/audit/OperationLog.vue new file mode 100644 index 0000000..50fc149 --- /dev/null +++ b/novalon-manage-web/src/views/audit/OperationLog.vue @@ -0,0 +1,49 @@ + + + + + diff --git a/novalon-manage-web/src/views/config/ConfigManagement.vue b/novalon-manage-web/src/views/config/ConfigManagement.vue new file mode 100644 index 0000000..521b567 --- /dev/null +++ b/novalon-manage-web/src/views/config/ConfigManagement.vue @@ -0,0 +1,115 @@ + + + + + diff --git a/novalon-manage-web/src/views/config/DictManagement.vue b/novalon-manage-web/src/views/config/DictManagement.vue new file mode 100644 index 0000000..e346aa8 --- /dev/null +++ b/novalon-manage-web/src/views/config/DictManagement.vue @@ -0,0 +1,121 @@ + + + + + diff --git a/novalon-manage-web/src/views/file/FileManagement.vue b/novalon-manage-web/src/views/file/FileManagement.vue new file mode 100644 index 0000000..0bbc5c4 --- /dev/null +++ b/novalon-manage-web/src/views/file/FileManagement.vue @@ -0,0 +1,118 @@ + + + + + diff --git a/novalon-manage-web/src/views/notify/NoticeManagement.vue b/novalon-manage-web/src/views/notify/NoticeManagement.vue new file mode 100644 index 0000000..260e475 --- /dev/null +++ b/novalon-manage-web/src/views/notify/NoticeManagement.vue @@ -0,0 +1,129 @@ + + + + + diff --git a/novalon-manage-web/src/views/system/Dashboard.vue b/novalon-manage-web/src/views/system/Dashboard.vue new file mode 100644 index 0000000..fe24a61 --- /dev/null +++ b/novalon-manage-web/src/views/system/Dashboard.vue @@ -0,0 +1,68 @@ + + + + + diff --git a/novalon-manage-web/src/views/system/Login.vue b/novalon-manage-web/src/views/system/Login.vue new file mode 100644 index 0000000..3fbcf56 --- /dev/null +++ b/novalon-manage-web/src/views/system/Login.vue @@ -0,0 +1,78 @@ + + + + + diff --git a/novalon-manage-web/src/views/system/MenuManagement.vue b/novalon-manage-web/src/views/system/MenuManagement.vue new file mode 100644 index 0000000..5810967 --- /dev/null +++ b/novalon-manage-web/src/views/system/MenuManagement.vue @@ -0,0 +1,148 @@ + + + + + diff --git a/novalon-manage-web/src/views/system/RoleManagement.vue b/novalon-manage-web/src/views/system/RoleManagement.vue new file mode 100644 index 0000000..28574fd --- /dev/null +++ b/novalon-manage-web/src/views/system/RoleManagement.vue @@ -0,0 +1,122 @@ + + + + + diff --git a/novalon-manage-web/src/views/system/UserManagement.vue b/novalon-manage-web/src/views/system/UserManagement.vue new file mode 100644 index 0000000..713c53c --- /dev/null +++ b/novalon-manage-web/src/views/system/UserManagement.vue @@ -0,0 +1,173 @@ + + + + + diff --git a/novalon-manage-web/vite.config.ts b/novalon-manage-web/vite.config.ts new file mode 100644 index 0000000..45f9089 --- /dev/null +++ b/novalon-manage-web/vite.config.ts @@ -0,0 +1,21 @@ +import { defineConfig } from 'vite' +import vue from '@vitejs/plugin-vue' +import path from 'path' + +export default defineConfig({ + plugins: [vue()], + resolve: { + alias: { + '@': path.resolve(__dirname, 'src') + } + }, + server: { + port: 3000, + proxy: { + '/api': { + target: 'http://localhost:8080', + changeOrigin: true + } + } + } +})