init: test-backend 初始化,基于 ghb-base [AI: Claude Code]
This commit is contained in:
parent
062b2293ef
commit
b3bd04aa59
|
|
@ -0,0 +1,217 @@
|
||||||
|
# 02 — 后端规则
|
||||||
|
|
||||||
|
> **适用**:所有后端 AI 开发任务。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 分层不变式
|
||||||
|
|
||||||
|
```
|
||||||
|
Controller → 参数校验 + 调 Service + 返回统一格式
|
||||||
|
禁止:写业务逻辑、直接调 Mapper、处理事务
|
||||||
|
|
||||||
|
Service → 业务逻辑 + 事务管理
|
||||||
|
禁止:处理 HTTP 请求/响应、直接操作 Request/Response
|
||||||
|
|
||||||
|
Mapper → 数据访问(MyBatis-Plus BaseMapper)
|
||||||
|
禁止:写业务逻辑、调用其他 Mapper
|
||||||
|
|
||||||
|
Entity → 数据映射(@TableName 对应表名)
|
||||||
|
禁止:写业务方法、放非持久化字段(放 DTO/VO)
|
||||||
|
```
|
||||||
|
|
||||||
|
### 包结构
|
||||||
|
|
||||||
|
```
|
||||||
|
com.ghb.base/
|
||||||
|
├── system/ # 系统模块(不改)
|
||||||
|
│ ├── entity/ SysUser, SysRole, SysMenu...
|
||||||
|
│ ├── controller/
|
||||||
|
│ └── service/
|
||||||
|
└── business/ # 业务模块 ← 你的代码放这里
|
||||||
|
├── entity/ # 继承 JeecgBoot 的 BaseEntity
|
||||||
|
├── controller/ # 继承 JeecgController
|
||||||
|
├── service/ # impl/ 继承 ServiceImpl
|
||||||
|
├── mapper/ # 继承 BaseMapper
|
||||||
|
│ └── xml/ # MyBatis XML(复杂查询才需要)
|
||||||
|
└── vo/ # 请求/响应 DTO (*VO, *Request, *ImportRow)
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 命名规则
|
||||||
|
|
||||||
|
| 元素 | 规则 | 示例(正确 → 错误) |
|
||||||
|
|------|------|---------------------|
|
||||||
|
| **类名** | 大驼峰,名词 | `TaskController` `OrderService` `UserMapper` |
|
||||||
|
| **方法名** | 小驼峰,动词开头 | `getById()` `saveTask()` `listByStatus()` |
|
||||||
|
| **变量** | 小驼峰,有意义 | `taskList` `userId` → ❌ `list` `id` `data` |
|
||||||
|
| **包名** | 全小写,点分隔 | `com.xxx.server.controller` |
|
||||||
|
| **Entity** | 大驼峰,对应表名 | 表 `task_apply` → 类 `TaskApply` |
|
||||||
|
| **DTO** | 大驼峰,后缀 DTO/VO/Request | `TaskCreateRequest` `UserListVO` |
|
||||||
|
| **常量** | 全大写,下划线分隔 | `MAX_RETRY_COUNT` `DEFAULT_PAGE_SIZE` |
|
||||||
|
| **SQL 表名** | 小写,下划线分隔 | `task_apply` `user_profile` |
|
||||||
|
| **SQL 字段** | 小写,下划线分隔 | `create_time` `task_id` `del_flag` |
|
||||||
|
| **URL 路径** | 小写,短横线或斜杠 | `/app/task/list` → ❌ `/app/Task/GetList` |
|
||||||
|
| **配置文件** | kebab-case 或小写 | `application-prod.yml` |
|
||||||
|
|
||||||
|
### 长度控制
|
||||||
|
|
||||||
|
类名、方法名、表名不要过长。超过 3 个单词或 30 个字符时,用通用缩写。
|
||||||
|
|
||||||
|
**前缀也要缩**:模块前缀用一个单词,别堆多个词。
|
||||||
|
|
||||||
|
| 完整 | 缩写 | JeecgBoot 实际案例 |
|
||||||
|
|------|------|-------------------|
|
||||||
|
| Department | Dept | `SysDepartRolePermission` → `SysDeptRolePerm` |
|
||||||
|
| Permission | Perm | 同上 |
|
||||||
|
| Announcement | Notice | `SysAnnouncementSend` → `SysNoticeSend` |
|
||||||
|
| Enterprise | Ent | `WechatEnterprise` → `WxEnt` |
|
||||||
|
| Message | Msg | `SysMessageTemplate` → `SysMsgTemplate` |
|
||||||
|
|
||||||
|
```java
|
||||||
|
// ❌ JeecgBoot 原版 — 太长
|
||||||
|
SysDepartRolePermissionServiceImpl // 35 字符
|
||||||
|
SysAnnouncementSendServiceImpl // 30 字符
|
||||||
|
ThirdAppWechatEnterpriseServiceImpl // 35 字符
|
||||||
|
|
||||||
|
// ✅ 缩写后
|
||||||
|
SysDeptRolePermServiceImpl // 26 字符
|
||||||
|
SysNoticeSendServiceImpl // 25 字符
|
||||||
|
ThirdAppWxEntServiceImpl // 27 字符
|
||||||
|
```
|
||||||
|
|
||||||
|
**原则**:优先用全称,超长再缩写。缩写必须一眼能认出含义,不自造别人看不懂的缩写。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 注释规则
|
||||||
|
|
||||||
|
| 位置 | 要求 | 示例 |
|
||||||
|
|------|------|------|
|
||||||
|
| **类/接口** | 必须有 Javadoc,说明职责 | `/** 任务管理 Controller,处理任务的增删改查 */` |
|
||||||
|
| **公共方法** | 必须有 Javadoc,说明入参/返回/异常 | `/** @param taskId 任务ID @return 任务详情 @throws 无 */` |
|
||||||
|
| **复杂逻辑** | 行内注释说明"为什么这么做" | `// 先查缓存再查库,避免击穿` |
|
||||||
|
| **常量** | 必须有注释说明含义 | `/** 最大重试次数 */` |
|
||||||
|
| **TODO/FIXME** | 必须有负责人和日期 | `// TODO(yaoshuli 2026-06) 后续改为配置项` |
|
||||||
|
| **禁止** | ❌ 注释写"做了什么"(代码本身已说明) | `// 查询任务列表` ← 删掉 |
|
||||||
|
| **禁止** | ❌ 注释掉的旧代码 | 直接删,Git 有历史 |
|
||||||
|
| **禁止** | ❌ 无意义注释 | `// 定义一个变量` `// 返回结果` |
|
||||||
|
| **禁止** | ❌ Controller 方法加 Javadoc 说"这是xxx接口" | 写业务含义,不写技术废话 |
|
||||||
|
|
||||||
|
### 注释示例
|
||||||
|
|
||||||
|
```java
|
||||||
|
/** 任务服务,负责任务的创建、分配、状态流转 */
|
||||||
|
@Service
|
||||||
|
public class TaskServiceImpl implements TaskService {
|
||||||
|
|
||||||
|
/** 单次批量操作上限 */
|
||||||
|
private static final int BATCH_LIMIT = 100;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据状态和截止时间查询待处理任务。
|
||||||
|
* 先查 Redis 缓存,未命中再查 MySQL。
|
||||||
|
*
|
||||||
|
* @param status 任务状态,不能为 null
|
||||||
|
* @param deadline 截止时间,只查此时间之前的任务
|
||||||
|
* @return 任务列表,可能为空
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public List<Task> listPending(String status, LocalDateTime deadline) {
|
||||||
|
// 缓存 key: pending:{status}
|
||||||
|
String cacheKey = "pending:" + status;
|
||||||
|
List<Task> cached = cacheService.get(cacheKey);
|
||||||
|
if (cached != null) return cached;
|
||||||
|
|
||||||
|
// 查库(这里用复合索引 idx_status_deadline)
|
||||||
|
List<Task> tasks = taskMapper.selectByStatusBefore(status, deadline);
|
||||||
|
cacheService.set(cacheKey, tasks, 300);
|
||||||
|
return tasks;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## 新增功能标准步骤
|
||||||
|
|
||||||
|
```
|
||||||
|
1. 建表 SQL → [项目数据库脚本目录]
|
||||||
|
2. Entity → 表映射
|
||||||
|
3. Mapper → 继承 BaseMapper
|
||||||
|
4. Service 接口+实现 → 业务逻辑
|
||||||
|
5. Controller → 接口暴露
|
||||||
|
6. 编译验证 → 构建通过
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## CRUD 模板(填空式)
|
||||||
|
|
||||||
|
```java
|
||||||
|
// ===== 分页列表 =====
|
||||||
|
@GetMapping("/list")
|
||||||
|
public Result<IPage<Xxx>> list(@RequestParam(defaultValue = "1") int page,
|
||||||
|
@RequestParam(defaultValue = "10") int size) {
|
||||||
|
Page<Xxx> p = new Page<>(page, size);
|
||||||
|
// [填空] 构建查询条件
|
||||||
|
return Result.ok(service.page(p, wrapper));
|
||||||
|
}
|
||||||
|
|
||||||
|
// ===== 详情 =====
|
||||||
|
@GetMapping("/{id}")
|
||||||
|
public Result<Xxx> detail(@PathVariable Long id) {
|
||||||
|
Xxx entity = service.getById(id);
|
||||||
|
if (entity == null) return Result.error("[资源]不存在");
|
||||||
|
return Result.ok(entity);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ===== 新增 =====
|
||||||
|
@PostMapping
|
||||||
|
public Result<?> create(@RequestBody @Valid XxxDto dto) {
|
||||||
|
// [填空] DTO → Entity 转换
|
||||||
|
service.save(entity);
|
||||||
|
return Result.ok();
|
||||||
|
}
|
||||||
|
|
||||||
|
// ===== 更新 =====
|
||||||
|
@PutMapping("/{id}")
|
||||||
|
public Result<?> update(@PathVariable Long id, @RequestBody @Valid XxxDto dto) {
|
||||||
|
Xxx entity = service.getById(id);
|
||||||
|
if (entity == null) return Result.error("[资源]不存在");
|
||||||
|
// [填空] 字段更新
|
||||||
|
service.updateById(entity);
|
||||||
|
return Result.ok();
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 禁止清单
|
||||||
|
|
||||||
|
| 类别 | ❌ 禁止 |
|
||||||
|
|------|--------|
|
||||||
|
| **分层** | Controller 里写 if/else 业务判断 |
|
||||||
|
| **分层** | Controller 直接调 Mapper/Repository |
|
||||||
|
| **分层** | Entity 里写业务方法 |
|
||||||
|
| **数据** | SQL/查询条件字符串拼接 |
|
||||||
|
| **数据** | 查不到不判空,直接返回可能 NPE |
|
||||||
|
| **数据** | `selectOne` / `getOne` 不做唯一性约束 |
|
||||||
|
| **输入** | 入参不校验(该用 `@Valid` 的地方手撸 if) |
|
||||||
|
| **输出** | 返回裸对象、裸字符串、自造格式 |
|
||||||
|
| **值** | 代码里硬编码魔法数字、魔法字符串 |
|
||||||
|
| **事务** | 该加事务的地方漏加 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 检查表
|
||||||
|
|
||||||
|
每完成一个后端任务,逐项自检:
|
||||||
|
|
||||||
|
- [ ] 编译通过(`mvn compile` / `go build` / 对应构建命令)
|
||||||
|
- [ ] 所有返回值是统一格式,无裸返回
|
||||||
|
- [ ] 分页接口格式正确(`list/total/pages/current/size`)
|
||||||
|
- [ ] Controller 方法体不超过 20 行(超过说明写了业务逻辑)
|
||||||
|
- [ ] 查不到/null 路径有明确的 `fail` 返回
|
||||||
|
- [ ] 改了接口 → 已 grep 同步所有前端调用方
|
||||||
|
- [ ] 新增/改字段 → 已更新数据库脚本
|
||||||
|
- [ ] 无禁止清单中的违规项
|
||||||
|
|
@ -0,0 +1,108 @@
|
||||||
|
# 01 — 接口契约
|
||||||
|
|
||||||
|
> **这是前后端共享的唯一真相来源。** 修改本文件 = 修改协议,必须同步更新所有端。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 契约生命周期(任务拆分时决定)
|
||||||
|
|
||||||
|
契约由**任务拆分时先开工的那一端**负责起草。这是任务产出物之一,不是额外工作。
|
||||||
|
|
||||||
|
```
|
||||||
|
任务拆分阶段:
|
||||||
|
┌─ 任务A:后端-用户管理CRUD ──→ 产出:接口契约(后端起草)
|
||||||
|
│ + 后端代码
|
||||||
|
│
|
||||||
|
└─ 任务B:前端-用户管理页面 ──→ 拿到契约后对接
|
||||||
|
|
||||||
|
反过来:
|
||||||
|
┌─ 任务A:前端-首页改版 ──→ 产出:接口契约(前端起草)
|
||||||
|
│ + 前端页面
|
||||||
|
│
|
||||||
|
└─ 任务B:后端-首页数据接口 ──→ 按契约实现
|
||||||
|
```
|
||||||
|
|
||||||
|
**铁律**:
|
||||||
|
- 拆分任务时明确标注:**本任务包含接口契约起草**
|
||||||
|
- 契约随任务一起交付,不单独走审批
|
||||||
|
- 后开工的一方拿到契约后,发现问题直接跟起草方沟通修改
|
||||||
|
- 联调时对照本文件,不一致的以本文件为准
|
||||||
|
|
||||||
|
### 分仓库时契约放哪
|
||||||
|
|
||||||
|
```
|
||||||
|
Monorepo(推荐): 分仓库:
|
||||||
|
项目根/ 后端仓库/ 前端仓库/
|
||||||
|
└── rules/ ├── rules/ ├── rules/
|
||||||
|
└── 01-接口契约.md │ └── 01-接口契约.md │ └── 01-接口契约.md
|
||||||
|
← git submodule 引用同一份 →
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 返回格式(不变式)
|
||||||
|
|
||||||
|
```json
|
||||||
|
// ✅ 唯一正确格式
|
||||||
|
{ "code": 200, "message": "success", "data": { ... } }
|
||||||
|
{ "code": 500, "message": "错误原因", "data": null }
|
||||||
|
|
||||||
|
// ❌ 永远不许出现
|
||||||
|
return data; // 裸对象
|
||||||
|
return "ok"; // 裸字符串
|
||||||
|
{ "success": true, "result": {...} } // 自造格式
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 分页格式(不变式)
|
||||||
|
|
||||||
|
```json
|
||||||
|
{ "list": [...], "total": 100, "pages": 10, "current": 1, "size": 10 }
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 接口命名约定
|
||||||
|
|
||||||
|
| 前缀 | 用途 | 示例 |
|
||||||
|
|------|------|------|
|
||||||
|
| `/admin/**` | 管理后台 | `/admin/user/list` |
|
||||||
|
| `/app/**` | 移动端/H5/小程序 | `/app/task/list` |
|
||||||
|
| `/auth/**` | 登录注册(共享) | `/auth/login` |
|
||||||
|
| `/open/**` | 对外开放接口 | `/open/callback` |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 状态值映射表
|
||||||
|
|
||||||
|
**← 改这里 = 改协议,必须同步后端 + 所有前端。**
|
||||||
|
|
||||||
|
| 含义 | 后端值 | 前端显示 | 前端 CSS 类 |
|
||||||
|
|------|--------|----------|------------|
|
||||||
|
| [状态1] | [值] | [文字] | [class] |
|
||||||
|
| [状态2] | [值] | [文字] | [class] |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 字段名桥接表
|
||||||
|
|
||||||
|
同一个概念在不同端字段名不同时,在此登记:
|
||||||
|
|
||||||
|
| 概念 | 后端字段 | 前端A字段 | 前端B字段 |
|
||||||
|
|------|----------|-----------|-----------|
|
||||||
|
| | | | |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 契约同步铁律
|
||||||
|
|
||||||
|
```
|
||||||
|
改后端接口 → grep 所有前端 → 逐个同步 → 两端都通过才算完成
|
||||||
|
|
||||||
|
步骤:
|
||||||
|
1. 改之前:grep -r "接口路径" 所有前端目录/
|
||||||
|
2. 改后端 → 编译通过
|
||||||
|
3. 逐个改前端 → 构建通过
|
||||||
|
4. 更新本文件的映射表(如有新增状态值/字段差异)
|
||||||
|
```
|
||||||
|
|
@ -0,0 +1,175 @@
|
||||||
|
# 04 — 数据库表设计规则
|
||||||
|
|
||||||
|
> **适用**:所有涉及建表、改表、索引设计的 AI 开发任务。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 命名规则
|
||||||
|
|
||||||
|
| 元素 | 规则 | 示例(正确 → 错误) |
|
||||||
|
| -------- | ------------- | -------------------------------------------------------- |
|
||||||
|
| **表名** | 小写,下划线分隔,单数名词 | `task_apply` → ❌ `TaskApply` `task_applies` |
|
||||||
|
| **字段名** | 小写,下划线分隔 | `create_time` `task_id` → ❌ `createdAt` `taskId` |
|
||||||
|
| **主键** | 统一用 `id` | `id` → ❌ `task_id` `pk_id` |
|
||||||
|
| **外键** | `关联表名_id` | `task_id` `user_id` → ❌ `tid` `uid` |
|
||||||
|
| **布尔字段** | `del_flag` 或明确业务含义的 `is_` 前缀 | `del_flag` `is_active` → ❌ `deleted` `status` |
|
||||||
|
| **时间字段** | `_time` 后缀 | `create_time` `update_time` → ❌ `created_at` `updateTime` |
|
||||||
|
| **金额字段** | `_amount` 后缀 | `reward_amount` → ❌ `reward` `price` |
|
||||||
|
| **索引名** | `idx_表名_字段` | `idx_task_status` → ❌ `index1` `task_status_idx` |
|
||||||
|
| **唯一索引** | `uk_表名_字段` | `uk_user_phone` → ❌ `uq_phone` |
|
||||||
|
| **关联表** | 两表名用下划线连接 | `task_apply` `user_role` → ❌ `apply_task` |
|
||||||
|
|
||||||
|
### 长度控制
|
||||||
|
|
||||||
|
表名超过 3 个单词或 30 个字符时缩写。前缀也要缩成一个单词。
|
||||||
|
|
||||||
|
| 完整 | 缩写 | JeecgBoot 实际案例 |
|
||||||
|
|------|------|-------------------|
|
||||||
|
| department | dept | `sys_depart_role_permission` → `sys_dept_role_perm` |
|
||||||
|
| permission | perm | 同上 |
|
||||||
|
| announcement | notice | `sys_announcement_send` → `sys_notice_send` |
|
||||||
|
| message | msg | `sys_message_template` → `sys_msg_template` |
|
||||||
|
|
||||||
|
```sql
|
||||||
|
-- ❌ JeecgBoot 原版 — 太长
|
||||||
|
sys_depart_role_permission -- 26 字符
|
||||||
|
sys_permission_data_rule -- 24 字符
|
||||||
|
|
||||||
|
-- ✅ 缩写后
|
||||||
|
sys_dept_role_perm -- 19 字符
|
||||||
|
sys_perm_data_rule -- 20 字符
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 字段类型规范
|
||||||
|
|
||||||
|
| 场景 | 类型 | 说明 |
|
||||||
|
|------|------|------|
|
||||||
|
| 主键 | `BIGINT` 自增 或 `VARCHAR(32)` | 推荐 BIGINT 自增;分布式用雪花ID |
|
||||||
|
| 短文本 | `VARCHAR(N)` | 姓名(50)、标题(200)、URL(500) |
|
||||||
|
| 长文本 | `TEXT` / `LONGTEXT` | 文章、JSON、描述 |
|
||||||
|
| 金额 | `DECIMAL(12,2)` | **禁止**用 FLOAT/DOUBLE |
|
||||||
|
| 状态/类型 | `VARCHAR(20)` 或 `TINYINT` | 枚举值,必须有注释说明 |
|
||||||
|
| 布尔 | `TINYINT(1)` | 0=否 1=是,注释必须写清含义 |
|
||||||
|
| 时间 | `DATETIME` | **禁止**用 TIMESTAMP(2038 问题) |
|
||||||
|
| 日期 | `DATE` | 生日、截止日期 |
|
||||||
|
| 数量 | `INT` 或 `BIGINT` | |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 每张表必须有的字段
|
||||||
|
|
||||||
|
```sql
|
||||||
|
CREATE TABLE xxx (
|
||||||
|
id BIGINT PRIMARY KEY AUTO_INCREMENT COMMENT '主键',
|
||||||
|
-- [业务字段]
|
||||||
|
create_by VARCHAR(32) NULL DEFAULT NULL COMMENT '创建人',
|
||||||
|
create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||||||
|
update_by VARCHAR(32) NULL DEFAULT NULL COMMENT '更新人',
|
||||||
|
update_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||||||
|
del_flag TINYINT(1) NOT NULL DEFAULT 0 COMMENT '逻辑删除:0-正常 1-已删除',
|
||||||
|
INDEX idx_xxx_create_time (create_time)
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='表说明';
|
||||||
|
```
|
||||||
|
|
||||||
|
**强制要求**:
|
||||||
|
- `create_by` — 创建人,建议保留;系统自动填充时可为空
|
||||||
|
- `create_time` — 创建时间,必须有
|
||||||
|
- `update_by` — 更新人,建议保留;系统自动填充时可为空
|
||||||
|
- `update_time` — 更新时间,必须有(`ON UPDATE CURRENT_TIMESTAMP` 自动更新)
|
||||||
|
- `del_flag` — 逻辑删除标记,除非明确不需要软删除
|
||||||
|
- 每张表必须有 `COMMENT`
|
||||||
|
- 引擎统一 `InnoDB`,字符集 `utf8mb4`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 索引规则
|
||||||
|
|
||||||
|
| 规则 | 说明 |
|
||||||
|
|------|------|
|
||||||
|
| **主键** | 每张表必须有,推荐自增 BIGINT |
|
||||||
|
| **外键** | 必须加索引(MySQL 自动加,但显式声明更清晰) |
|
||||||
|
| **查询条件** | WHERE 条件字段必须加索引 |
|
||||||
|
| **排序字段** | ORDER BY 字段考虑加索引 |
|
||||||
|
| **联合索引** | 遵循最左前缀原则,区分度高的在前 |
|
||||||
|
| **唯一约束** | 业务唯一字段必须加唯一索引 |
|
||||||
|
| **禁止** | ❌ 不加索引的 WHERE / JOIN / ORDER BY |
|
||||||
|
| **禁止** | ❌ 在大字段(TEXT/BLOB)上建索引 |
|
||||||
|
| **禁止** | ❌ 过多索引(单表建议 ≤ 5 个) |
|
||||||
|
|
||||||
|
### 索引命名
|
||||||
|
|
||||||
|
```sql
|
||||||
|
INDEX idx_表名_字段 -- 普通索引
|
||||||
|
UNIQUE uk_表名_字段 -- 唯一索引
|
||||||
|
INDEX idx_表名_字段1_字段2 -- 联合索引
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 字段约束规则
|
||||||
|
|
||||||
|
| 规则 | 示例 |
|
||||||
|
|------|------|
|
||||||
|
| 主键 | `PRIMARY KEY` 或 `NOT NULL AUTO_INCREMENT` |
|
||||||
|
| 非空 | 业务必填字段 `NOT NULL` |
|
||||||
|
| 默认值 | 有默认值的字段 `DEFAULT xxx`,**禁止**依赖代码设默认值 |
|
||||||
|
| 唯一 | 业务唯一字段 `UNIQUE` |
|
||||||
|
| 外键 | 尽量用逻辑外键(代码维护),**不推荐**物理外键(`FOREIGN KEY`) |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 禁止清单
|
||||||
|
|
||||||
|
| ❌ 禁止 | 原因 |
|
||||||
|
|---------|------|
|
||||||
|
| 表名/字段名用大写或驼峰 | 跨平台兼容 |
|
||||||
|
| 金额用 FLOAT/DOUBLE | 精度丢失 |
|
||||||
|
| 时间用 TIMESTAMP | 2038 年溢出 |
|
||||||
|
| 用物理外键 | 分库分表/数据迁移困难 |
|
||||||
|
| 不加注释 | 无人知道字段含义 |
|
||||||
|
| 字符串代替布尔 | 空间浪费,索引效率低 |
|
||||||
|
| 大表无索引 | 性能灾难 |
|
||||||
|
| 字段用 NULL 代替默认值 | 查询需额外处理 `IS NULL` |
|
||||||
|
| 在代码里设默认值 | 数据一致性依赖应用层 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 修改表规则
|
||||||
|
|
||||||
|
```sql
|
||||||
|
-- ✅ 正确:显式命名约束
|
||||||
|
ALTER TABLE task ADD COLUMN priority TINYINT NOT NULL DEFAULT 0 COMMENT '优先级:0-普通 1-紧急';
|
||||||
|
ALTER TABLE task ADD INDEX idx_task_priority (priority);
|
||||||
|
|
||||||
|
-- ❌ 禁止:不写 COMMENT
|
||||||
|
ALTER TABLE task ADD COLUMN priority TINYINT;
|
||||||
|
|
||||||
|
-- ❌ 禁止:不写默认值导致存量数据为 NULL
|
||||||
|
ALTER TABLE task ADD COLUMN priority TINYINT NOT NULL;
|
||||||
|
```
|
||||||
|
|
||||||
|
**修改表必须**:
|
||||||
|
- 新字段有 `COMMENT`
|
||||||
|
- 非空字段有 `DEFAULT`
|
||||||
|
- 考虑对存量数据的影响
|
||||||
|
- 附带回滚 SQL
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 检查表
|
||||||
|
|
||||||
|
每涉及建表/改表,逐项自检:
|
||||||
|
|
||||||
|
- [ ] 表名、字段名全小写+下划线
|
||||||
|
- [ ] 有 `create_by` `create_time` `update_by` `update_time`
|
||||||
|
- [ ] 软删除字段 `del_flag`(如需要)
|
||||||
|
- [ ] 每张表有 `COMMENT`,每个字段有 `COMMENT`
|
||||||
|
- [ ] 金额用 `DECIMAL`,时间用 `DATETIME`
|
||||||
|
- [ ] 主键 + 外键 + WHERE 条件字段有索引
|
||||||
|
- [ ] 非空字段有 `NOT NULL DEFAULT`
|
||||||
|
- [ ] 无物理外键
|
||||||
|
- [ ] 索引命名 `idx_表名_字段` / `uk_表名_字段`
|
||||||
|
- [ ] 附带回滚 SQL
|
||||||
|
- [ ] 引擎 InnoDB,字符集 utf8mb4
|
||||||
|
|
@ -0,0 +1,44 @@
|
||||||
|
# 编码规范(字符编码)
|
||||||
|
|
||||||
|
> 本规则因一次事故而立:批量改包名时用了非 UTF-8 感知的脚本,把中文注释整成乱码(`鐗堟湰`=版本、`寰湇鍔`=微服务),且引入 BOM。以下为硬性约束。
|
||||||
|
|
||||||
|
## 不变式(违反即 Bug)
|
||||||
|
|
||||||
|
1. **所有源码/配置/文本文件一律 UTF-8 编码**:`.java` `.xml` `.yml` `.yaml` `.properties` `.sql` `.md` `.vue` `.ts` `.js` `.json` 等。
|
||||||
|
2. **禁止 BOM**:UTF-8 文件不得带 BOM(`EF BB BF`)。BOM 会让 XML/YAML 解析、shell 脚本、diff 出错。
|
||||||
|
3. **禁止 GBK / GB2312 / GB18030 / Latin1 落盘**:任何环节(编辑器、脚本、终端重定向)都不得以非 UTF-8 写文件。
|
||||||
|
4. **禁止用非 UTF-8 感知的工具批量改写文本**:如必须批量替换,工具必须显式按 UTF-8 读、UTF-8 写(Python 用 `io.open(p, encoding='utf-8')`;`sed`/`grep` 在 UTF-8 locale 下运行)。
|
||||||
|
5. **换行**:统一 LF(`\n`),`.gitattributes` 固化,避免 CRLF 混入触发整文件 diff。
|
||||||
|
|
||||||
|
## 构建/工程配置(必须存在)
|
||||||
|
|
||||||
|
- **Maven**:父 pom 设
|
||||||
|
```xml
|
||||||
|
<properties>
|
||||||
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
|
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
|
||||||
|
</properties>
|
||||||
|
```
|
||||||
|
- **`.editorconfig`**(后端仓库和前端仓库根目录各一个 `.editorconfig` 文件):
|
||||||
|
```
|
||||||
|
root = true
|
||||||
|
[*]
|
||||||
|
charset = utf-8
|
||||||
|
end_of_line = lf
|
||||||
|
insert_final_newline = true
|
||||||
|
```
|
||||||
|
- **前端**:Vite/Node 默认 UTF-8,源文件保持 UTF-8 无 BOM 即可。
|
||||||
|
- **Windows 终端**:PowerShell 默认输出可能是 GBK;**不要用 `>`/`>>` 重定向把含中文的内容写进源文件**(会按当前代码页编码)。要写文件用 UTF-8 感知的程序,不要靠 shell 重定向。
|
||||||
|
|
||||||
|
## 处理已损坏文件(mojibake 还原)
|
||||||
|
|
||||||
|
经典双重编码(UTF-8 被当 GBK 再存 UTF-8)可逆转:`坏文本.encode('gbk').decode('utf-8')`。
|
||||||
|
但若 mojibake 中已出现 `?`(0x3F),该字节已丢失、不可逆,只能按上下文重写注释。
|
||||||
|
|
||||||
|
## 检查表(提交前)
|
||||||
|
|
||||||
|
- [ ] 新增/修改的文本文件是 UTF-8 无 BOM(`file *.xml` 或编辑器状态栏确认)
|
||||||
|
- [ ] 没有出现 `鐗堟湰`/`寰湇`/`锛` 这类乱码片段
|
||||||
|
- [ ] 仓库根有 `.editorconfig`(charset=utf-8)
|
||||||
|
- [ ] 父 pom 有 `project.build.sourceEncoding=UTF-8`
|
||||||
|
- [ ] 批量文本替换用的是 UTF-8 感知工具,不是裸 `>` 重定向
|
||||||
|
|
@ -0,0 +1,199 @@
|
||||||
|
# 03 — 前端规则
|
||||||
|
|
||||||
|
> **适用**:所有前端 AI 开发任务(Web / H5 / 小程序)。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 样式铁律
|
||||||
|
|
||||||
|
**禁止在组件文件中硬编码**:颜色值(`#xxx` / `rgb()`)、字号(`px` / `rpx` / `rem`)、间距(`margin` / `padding` 数值)、圆角(`border-radius` 数值)。
|
||||||
|
|
||||||
|
所有样式必须来自:
|
||||||
|
1. **Design Token 文件** → 变量(`$color-primary`)
|
||||||
|
2. **全局 CSS 类** → 语义类(`.text-h1` `.card` `.gap-2`)
|
||||||
|
3. **UI 框架内置类** → Tailwind / Ant Design 等
|
||||||
|
|
||||||
|
```vue
|
||||||
|
<!-- ❌ 禁止 -->
|
||||||
|
<style scoped>
|
||||||
|
.title { color: #333; font-size: 32rpx; margin: 20rpx; }
|
||||||
|
|
||||||
|
<!-- ✅ 正确 -->
|
||||||
|
<style scoped>
|
||||||
|
.title { color: $color-gray-800; @extend .text-h2; margin: $space-3; }
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 命名规则
|
||||||
|
|
||||||
|
| 元素 | 规则 | 示例(正确 → 错误) |
|
||||||
|
|------|------|---------------------|
|
||||||
|
| **组件文件** | 短横线分隔(kebab-case) | `task-card.vue` → ❌ `TaskCard.vue` |
|
||||||
|
| **页面文件** | 小写或短横线 | `task-detail.vue` `index.vue` |
|
||||||
|
| **组件 name** | 大驼峰(PascalCase) | `TaskCard` `UserAvatar` |
|
||||||
|
| **CSS 类名** | 短横线分隔 | `.task-card` `.btn-primary` → ❌ `.taskCard` |
|
||||||
|
| **JS 变量** | 小驼峰 | `taskList` `userName` → ❌ `task_list` |
|
||||||
|
| **JS 常量** | 全大写,下划线分隔 | `MAX_PAGE_SIZE` `API_BASE_URL` |
|
||||||
|
| **JS 函数** | 小驼峰,动词开头 | `fetchTasks()` `handleSubmit()` |
|
||||||
|
| **API 方法** | 小驼峰,动词+名词 | `taskApi.list()` `taskApi.create()` |
|
||||||
|
| **路由路径** | 小写,短横线 | `/task-detail` → ❌ `/taskDetail` |
|
||||||
|
| **文件目录** | 小写或短横线 | `task-hall/` `user-center/` |
|
||||||
|
| **静态资源** | 短横线分隔 | `icon-phone.svg` `bg-home.jpg` |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 注释规则
|
||||||
|
|
||||||
|
| 位置 | 要求 | 示例 |
|
||||||
|
|------|------|------|
|
||||||
|
| **组件** | 顶部注释说明用途和 Props | `<!-- 任务卡片组件,用于列表展示 -->` |
|
||||||
|
| **复杂逻辑** | 行内注释说明"为什么" | `// 先查本地缓存,未命中再请求接口` |
|
||||||
|
| **计算属性** | 注释说明计算依据 | `// 根据任务状态和截止时间计算紧急程度` |
|
||||||
|
| **API 方法** | JSDoc 说明入参/返回 | `@param {Object} params @returns {Promise<{list,total}>}` |
|
||||||
|
| **TODO/FIXME** | 负责人+日期 | `// TODO(yaoshuli 2026-06) 待产品确认逻辑` |
|
||||||
|
| **禁止** | ❌ 注释写"做了什么" | `<!-- 循环渲染列表 -->` ← 删掉 |
|
||||||
|
| **禁止** | ❌ 注释掉的旧代码/旧模板 | 直接删,Git 有历史 |
|
||||||
|
| **禁止** | ❌ 无意义分隔注释 | `// ========== 数据获取 ==========` |
|
||||||
|
|
||||||
|
```vue
|
||||||
|
<!--
|
||||||
|
任务详情页面
|
||||||
|
- 展示任务基本信息、报名列表、结算记录
|
||||||
|
- 支持接单、提交、结算等操作
|
||||||
|
-->
|
||||||
|
<template>
|
||||||
|
<app-layout>
|
||||||
|
<!-- 任务信息卡片 -->
|
||||||
|
<m-card>
|
||||||
|
...
|
||||||
|
</m-card>
|
||||||
|
|
||||||
|
<!-- 仅管理员可见 -->
|
||||||
|
<m-card v-if="isAdmin">
|
||||||
|
...
|
||||||
|
</m-card>
|
||||||
|
</app-layout>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
/**
|
||||||
|
* 提交任务成果。
|
||||||
|
* 提交成功后自动刷新列表并发送通知。
|
||||||
|
*
|
||||||
|
* @param {string} taskId - 任务ID
|
||||||
|
* @param {Object} payload - 提交内容 { files, remark }
|
||||||
|
* @returns {Promise<void>}
|
||||||
|
*/
|
||||||
|
const handleSubmit = async (taskId, payload) => {
|
||||||
|
// 先本地校验,避免无效请求
|
||||||
|
if (!payload.files.length) return;
|
||||||
|
|
||||||
|
await taskApi.submit(taskId, payload);
|
||||||
|
// TODO(yaoshuli 2026-06) 成功后应跳转到提交记录页
|
||||||
|
router.push('/task-list');
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 组件使用铁律
|
||||||
|
|
||||||
|
| 场景 | ✅ 必须用 | ❌ 禁止 |
|
||||||
|
|------|----------|---------|
|
||||||
|
| 页面外壳 | 项目统一布局组件 | 自己写页头/侧栏/底栏/TabBar |
|
||||||
|
| 图标 | 项目统一图标组件 | 裸 `<img>` / emoji / Unicode |
|
||||||
|
| 按钮 | 项目统一按钮组件 | 自己写 button 样式 |
|
||||||
|
| 卡片 | 项目统一卡片组件 | 裸露 div+手写圆角阴影 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## API 调用铁律
|
||||||
|
|
||||||
|
**所有 HTTP 请求走统一封装**,禁止组件内直调原生 API。
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
// ✅ 正确:走项目统一封装
|
||||||
|
import { taskApi } from '@/services/task';
|
||||||
|
const res = await taskApi.list({ page: 1, size: 20 });
|
||||||
|
|
||||||
|
// ❌ 禁止
|
||||||
|
fetch('/api/task/list').then(...)
|
||||||
|
axios.get('/api/task/list')
|
||||||
|
uni.request({ url: '/api/task/list' })
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 新增页面模板(填空式)
|
||||||
|
|
||||||
|
```vue
|
||||||
|
<template>
|
||||||
|
<app-layout>
|
||||||
|
<!-- [填空] 页面内容 -->
|
||||||
|
<view v-if="loading">加载中...</view>
|
||||||
|
<view v-else-if="list.length === 0" class="empty-state">
|
||||||
|
<text>暂无数据</text>
|
||||||
|
</view>
|
||||||
|
<view v-else>
|
||||||
|
<!-- [填空] 数据展示 -->
|
||||||
|
</view>
|
||||||
|
</app-layout>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { ref, onMounted } from 'vue';
|
||||||
|
// [填空] import API 方法
|
||||||
|
|
||||||
|
const list = ref([]);
|
||||||
|
const loading = ref(false);
|
||||||
|
|
||||||
|
const fetchData = async () => {
|
||||||
|
loading.value = true;
|
||||||
|
try {
|
||||||
|
const res = await [API方法]({ page: 1, size: 20 });
|
||||||
|
list.value = res.list;
|
||||||
|
} finally {
|
||||||
|
loading.value = false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
onMounted(() => fetchData());
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
// ⚠️ 不得超过 100 行,超过说明在造轮子
|
||||||
|
</style>
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 禁止清单
|
||||||
|
|
||||||
|
| 类别 | ❌ 禁止 |
|
||||||
|
|------|--------|
|
||||||
|
| **样式** | 硬编码颜色/字号/间距/圆角 |
|
||||||
|
| **样式** | 在 scoped 中定义全局重置 |
|
||||||
|
| **样式** | scoped 超过 100 行 |
|
||||||
|
| **组件** | 自己写布局外壳(页头/侧栏/TabBar) |
|
||||||
|
| **组件** | 裸用 `<img>` 代替图标组件 |
|
||||||
|
| **网络** | 直调 `fetch` / `axios` / `uni.request` |
|
||||||
|
| **网络** | 不处理错误态 |
|
||||||
|
| **状态** | 无加载态/空态 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 检查表
|
||||||
|
|
||||||
|
每完成一个前端任务,逐项自检:
|
||||||
|
|
||||||
|
- [ ] 使用项目统一布局组件
|
||||||
|
- [ ] 无硬编码颜色/字号/间距/圆角
|
||||||
|
- [ ] 图标全部走统一图标组件
|
||||||
|
- [ ] API 调用走统一封装,无裸调
|
||||||
|
- [ ] 页面/组件有加载态 + 空态 + 错误态
|
||||||
|
- [ ] 关键操作有 loading 态(防重复点击)
|
||||||
|
- [ ] `<style scoped>` 不超过 100 行
|
||||||
|
- [ ] PC/移动端均正常(如项目需响应式)
|
||||||
|
- [ ] 无禁止清单中的违规项
|
||||||
|
|
@ -0,0 +1,246 @@
|
||||||
|
# 05 — Git 协作规则
|
||||||
|
|
||||||
|
> **适用**:所有 AI 和人工开发任务。分支怎么拉、什么时候合、冲突怎么处理。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 分支模型
|
||||||
|
|
||||||
|
```
|
||||||
|
master ──────────────────────────────────────────→ 生产
|
||||||
|
│
|
||||||
|
└── test ──────────────────────────────────────→ 测试主线
|
||||||
|
└── dev ──────────────────────────────────────→ 开发主线
|
||||||
|
│
|
||||||
|
├── feature/任务编号-简短描述 → 新功能
|
||||||
|
├── bugfix/任务编号-简短描述 → Bug修复
|
||||||
|
└── hotfix/任务编号-简短描述 (从 master 拉) → 紧急修复
|
||||||
|
```
|
||||||
|
|
||||||
|
### 什么时候从哪拉
|
||||||
|
|
||||||
|
| 场景 | 从哪拉 | 合回哪 |
|
||||||
|
|------|--------|--------|
|
||||||
|
| 新功能 | `dev` | `dev` |
|
||||||
|
| Bug 修复 | `dev` | `dev` |
|
||||||
|
| 紧急线上修复 | `master` | `master` + `dev`(两边都要合) |
|
||||||
|
|
||||||
|
### 分支命名
|
||||||
|
|
||||||
|
```
|
||||||
|
feature/2688-用户批量导入 ← 禅道任务号 + 功能描述
|
||||||
|
bugfix/2690-任务列表分页错误
|
||||||
|
hotfix/2691-登录验证码绕过
|
||||||
|
|
||||||
|
禁止:
|
||||||
|
feature/xxx ← 没任务号
|
||||||
|
zhangsan-test ← 没意义
|
||||||
|
dev-backup-20260603 ← 备份不是分支
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 日常操作
|
||||||
|
|
||||||
|
### 开始一个新任务
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 1. 切到 dev,拉最新
|
||||||
|
git checkout dev
|
||||||
|
git pull origin dev
|
||||||
|
|
||||||
|
# 2. 从 dev 拉分支
|
||||||
|
git checkout -b feature/任务号-功能描述
|
||||||
|
|
||||||
|
# 3. 开发...
|
||||||
|
|
||||||
|
# 4. 定期提交(不要攒到最后一次性交)
|
||||||
|
git add .
|
||||||
|
git commit -m "feat: xxx"
|
||||||
|
|
||||||
|
# 5. 推送到远程(每天至少推一次,防止本地丢失)
|
||||||
|
git push origin feature/任务号-功能描述
|
||||||
|
```
|
||||||
|
|
||||||
|
### 合并回 dev
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 1. 确保本地 dev 最新
|
||||||
|
git checkout dev
|
||||||
|
git pull origin dev
|
||||||
|
|
||||||
|
# 2. 切回自己的分支,rebase dev(让历史干净)
|
||||||
|
git checkout feature/任务号-功能描述
|
||||||
|
git rebase dev
|
||||||
|
|
||||||
|
# 如果有冲突:
|
||||||
|
# - 逐个文件解决冲突
|
||||||
|
# - git add <解决的文件>
|
||||||
|
# - git rebase --continue
|
||||||
|
# - 直到完成
|
||||||
|
|
||||||
|
# 3. 推 rebase 后的分支(需要 --force-with-lease,不是 --force)
|
||||||
|
git push --force-with-lease origin feature/任务号-功能描述
|
||||||
|
|
||||||
|
# 4. 到 Git 平台提 PR/MR 到 dev
|
||||||
|
# PR 标题:feat: 用户管理增加批量导入
|
||||||
|
# PR 描述:改了什么、怎么测试
|
||||||
|
```
|
||||||
|
|
||||||
|
### 冲突处理
|
||||||
|
|
||||||
|
```
|
||||||
|
1. git status 看哪些文件冲突
|
||||||
|
2. 打开冲突文件,找到 <<<<<<< ======= >>>>>>> 标记
|
||||||
|
3. 逐行确认保留哪边的代码
|
||||||
|
4. 删掉标记符号
|
||||||
|
5. git add <文件>
|
||||||
|
6. git rebase --continue 或 git merge --continue
|
||||||
|
7. 编译验证
|
||||||
|
```
|
||||||
|
|
||||||
|
**常见错误**:看到冲突整块接受一边,把别人的代码覆盖了。必须逐行看。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## AI 开发特殊规则
|
||||||
|
|
||||||
|
### AI 提交必须标注
|
||||||
|
|
||||||
|
```
|
||||||
|
feat: 用户管理增加批量导入 [AI: Claude Code]
|
||||||
|
|
||||||
|
- 新增 UserBatchImportController
|
||||||
|
- 新增 UserImportService
|
||||||
|
- 新增 import_batch 表
|
||||||
|
- 前端增加导入按钮和上传弹窗
|
||||||
|
```
|
||||||
|
|
||||||
|
**为什么**:review 时知道这是 AI 写的,检查更仔细(尤其是边界条件和安全性)。
|
||||||
|
|
||||||
|
### AI 解决冲突
|
||||||
|
|
||||||
|
AI 遇到冲突时,不能自己决定保留哪边。必须:
|
||||||
|
1. 列出冲突内容和两边来源
|
||||||
|
2. 让人类决定
|
||||||
|
3. 人类确认后再继续
|
||||||
|
|
||||||
|
### AI 禁止操作
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# ❌ AI 绝对禁止
|
||||||
|
git push --force origin dev # 强制推共享分支
|
||||||
|
git push --force origin master # 同上
|
||||||
|
git reset --hard HEAD~10 && git push -f # 回退远程历史
|
||||||
|
git commit --amend && git push -f # 修改已推送的 commit
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Commit 格式
|
||||||
|
|
||||||
|
```
|
||||||
|
<type>: <简短描述> [来源标注]
|
||||||
|
|
||||||
|
类型:
|
||||||
|
feat: 新功能
|
||||||
|
fix: Bug 修复
|
||||||
|
refactor: 重构(不改功能)
|
||||||
|
style: 格式调整
|
||||||
|
docs: 文档
|
||||||
|
test: 测试
|
||||||
|
chore: 构建/依赖/工具
|
||||||
|
|
||||||
|
来源标注(AI 写的必须加):
|
||||||
|
[AI: Claude Code]
|
||||||
|
[AI: Kimi]
|
||||||
|
[AI: Codex]
|
||||||
|
|
||||||
|
正确示例:
|
||||||
|
feat: 用户管理增加批量导入 [AI: Claude Code]
|
||||||
|
fix: 任务列表分页总数计算错误
|
||||||
|
refactor: 提取公共校验逻辑到 BaseService
|
||||||
|
chore: 升级 Spring Boot 到 3.5.6
|
||||||
|
|
||||||
|
禁止示例:
|
||||||
|
update ← 无意义
|
||||||
|
fix bug ← 不知道修的哪个 bug
|
||||||
|
修改 ← 中文且无具体内容
|
||||||
|
WIP / temp / test ← 临时提交应该 squash 掉
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## PR / MR 规范
|
||||||
|
|
||||||
|
### PR 必须包含
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
## 改了什么
|
||||||
|
简要描述改动内容
|
||||||
|
|
||||||
|
## 关联任务
|
||||||
|
禅道 #2688 / 需求文档链接
|
||||||
|
|
||||||
|
## 测试方式
|
||||||
|
- [ ] 本地编译通过
|
||||||
|
- [ ] 接口测试通过
|
||||||
|
- [ ] 前端页面正常
|
||||||
|
|
||||||
|
## 契约变更
|
||||||
|
- [ ] 无接口变更
|
||||||
|
- [ ] 有接口变更 → 已更新 contract/ 目录 → 已通知前端
|
||||||
|
```
|
||||||
|
|
||||||
|
### Review 规则
|
||||||
|
|
||||||
|
- 至少一人 approve 才能合
|
||||||
|
- AI 生成的代码必须至少一人 review
|
||||||
|
- 改动超过 500 行 → 拆分 PR
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## .gitignore 必备
|
||||||
|
|
||||||
|
```
|
||||||
|
# Java
|
||||||
|
target/
|
||||||
|
*.class
|
||||||
|
*.jar
|
||||||
|
*.war
|
||||||
|
|
||||||
|
# IDE
|
||||||
|
.idea/
|
||||||
|
*.iml
|
||||||
|
.vscode/
|
||||||
|
.settings/
|
||||||
|
.project
|
||||||
|
.classpath
|
||||||
|
|
||||||
|
# 前端
|
||||||
|
node_modules/
|
||||||
|
dist/
|
||||||
|
.env.local
|
||||||
|
|
||||||
|
# 系统
|
||||||
|
.DS_Store
|
||||||
|
Thumbs.db
|
||||||
|
|
||||||
|
# 敏感信息
|
||||||
|
*.pem
|
||||||
|
*.key
|
||||||
|
application-prod.yml (如果有密码)
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 检查表
|
||||||
|
|
||||||
|
- [ ] 分支从正确的源头拉(功能/Bug → dev,紧急 → master)
|
||||||
|
- [ ] 分支名包含任务号
|
||||||
|
- [ ] commit message 有意义
|
||||||
|
- [ ] AI 提交标注了来源
|
||||||
|
- [ ] push 前 rebase 了 dev
|
||||||
|
- [ ] 没用 `--force` 推共享分支
|
||||||
|
- [ ] 冲突逐行解决,没整块覆盖
|
||||||
|
- [ ] PR 有描述和测试说明
|
||||||
|
|
@ -0,0 +1,125 @@
|
||||||
|
# 06 — 安全与日志规则
|
||||||
|
|
||||||
|
> **适用**:所有后端开发任务。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 安全规则
|
||||||
|
|
||||||
|
### 认证检查(不变式)
|
||||||
|
|
||||||
|
每个需要登录的接口必须通过 Shiro 认证。JeecgBoot 默认全局拦截。
|
||||||
|
|
||||||
|
```java
|
||||||
|
// JeecgBoot 认证机制:
|
||||||
|
// 1. 所有 /sys/** /admin/** 默认需要登录
|
||||||
|
// 2. 白名单在 application.yml 配置
|
||||||
|
// 3. 权限注解:@RequiresPermissions / @RequiresRoles
|
||||||
|
|
||||||
|
// ✅ 接口加权限
|
||||||
|
@RequiresPermissions("user:add")
|
||||||
|
@PostMapping("/add")
|
||||||
|
public Result<?> add(...) { ... }
|
||||||
|
|
||||||
|
// ❌ 不要为了调试临时关认证
|
||||||
|
// ❌ 不要把需要认证的路径加到 shiro.excludeUrls
|
||||||
|
```
|
||||||
|
|
||||||
|
### 数据权限(租户隔离)
|
||||||
|
|
||||||
|
JeecgBoot 已通过 MyBatis-Plus 拦截器自动注入 tenant_id,**但如果手写 SQL 必须手动加**。
|
||||||
|
|
||||||
|
```java
|
||||||
|
// ✅ 用 MyBatis-Plus 自动处理
|
||||||
|
taskService.list(new LambdaQueryWrapper<Task>().eq(Task::getStatus, "pending"));
|
||||||
|
|
||||||
|
// ❌ 手写 SQL 忘了加租户 → 租户A 看到租户B 的数据
|
||||||
|
@Select("SELECT * FROM task WHERE status = #{status}")
|
||||||
|
|
||||||
|
// ✅ 手写 SQL 正确写法
|
||||||
|
@Select("SELECT * FROM task WHERE status = #{status} AND tenant_id = #{tenantId}")
|
||||||
|
```
|
||||||
|
|
||||||
|
### 敏感信息保护
|
||||||
|
|
||||||
|
```java
|
||||||
|
// ✅ 密码字段不返回
|
||||||
|
@Entity
|
||||||
|
public class SysUser {
|
||||||
|
@JsonIgnore // ← 关键
|
||||||
|
private String password;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ✅ 手机号脱敏返回(VO 层处理)
|
||||||
|
userVO.setPhone(phone.replaceAll("(\\d{3})\\d{4}(\\d{4})", "$1****$2"));
|
||||||
|
```
|
||||||
|
|
||||||
|
### 文件上传安全
|
||||||
|
|
||||||
|
```java
|
||||||
|
// ✅ 必须校验(JeecgBoot 已内置部分,确认开启)
|
||||||
|
- 文件类型白名单:只允许 jpg/png/pdf/doc/xlsx
|
||||||
|
- 文件大小上限:单文件 ≤ 10MB
|
||||||
|
- 文件名处理:用 UUID 重命名,防路径穿越
|
||||||
|
- 存储路径:不暴露原始文件名给前端
|
||||||
|
```
|
||||||
|
|
||||||
|
### 接口防刷
|
||||||
|
|
||||||
|
```java
|
||||||
|
// ✅ 敏感接口(登录/短信/支付)加限流
|
||||||
|
// JeecgBoot 使用 Sentinel 或自定义注解
|
||||||
|
@RateLimiter(count = 5, time = 60) // 60秒内最多5次
|
||||||
|
@PostMapping("/send-sms")
|
||||||
|
public Result<?> sendSms(...) { ... }
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 日志规则
|
||||||
|
|
||||||
|
### 日志级别
|
||||||
|
|
||||||
|
| 级别 | 场景 |
|
||||||
|
|------|------|
|
||||||
|
| ERROR | 数据库连不上、第三方接口失败、业务异常需要人工介入 |
|
||||||
|
| WARN | 降级处理、重试成功、配置缺失但有默认值 |
|
||||||
|
| INFO | 用户登录、任务创建、状态变更、定时任务执行 |
|
||||||
|
| DEBUG | 开发调试用,不入生产 |
|
||||||
|
|
||||||
|
### 日志内容
|
||||||
|
|
||||||
|
```java
|
||||||
|
// ✅ 关键操作
|
||||||
|
log.info("任务状态变更 taskId={} from={} to={} operator={}", taskId, oldStatus, newStatus, userId);
|
||||||
|
|
||||||
|
// ✅ 异常
|
||||||
|
log.error("调用第三方接口失败 url={}", url, e); // 最后一个参数是异常对象
|
||||||
|
|
||||||
|
// ❌ 不要这样
|
||||||
|
log.info("进来了");
|
||||||
|
log.info("user=" + user.toString()); // 可能打印密码
|
||||||
|
System.out.println("debug: " + xxx); // 永远不
|
||||||
|
```
|
||||||
|
|
||||||
|
### 禁止
|
||||||
|
|
||||||
|
| ❌ | 原因 |
|
||||||
|
|----|------|
|
||||||
|
| 循环里打 INFO | 日志爆炸 |
|
||||||
|
| 打印完整大对象 | 刷屏且可能泄露敏感数据 |
|
||||||
|
| 用 System.out.println | 不入日志文件 |
|
||||||
|
| 用 e.printStackTrace() | 不入日志框架 |
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 检查表
|
||||||
|
|
||||||
|
- [ ] 新接口需要认证(不在白名单中)
|
||||||
|
- [ ] 手写 SQL 加了租户隔离
|
||||||
|
- [ ] 敏感字段不返回给前端
|
||||||
|
- [ ] 文件上传有类型/大小校验
|
||||||
|
- [ ] 关键操作有 INFO 日志
|
||||||
|
- [ ] 异常有 ERROR 日志(带栈)
|
||||||
|
- [ ] 无硬编码密码/密钥
|
||||||
|
|
@ -0,0 +1,146 @@
|
||||||
|
# 07 — 测试与错误处理规则
|
||||||
|
|
||||||
|
> **适用**:所有后端开发任务。AI 最容易忽略的两件事:写测试、统一错误码。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 测试规则
|
||||||
|
|
||||||
|
### 必须写测试的场景
|
||||||
|
|
||||||
|
| 场景 | 测试类型 | 要求 |
|
||||||
|
|------|----------|------|
|
||||||
|
| 新增 Service 方法 | 单元测试 | 必须 |
|
||||||
|
| 新增 Controller 接口 | 集成测试 | 必须 |
|
||||||
|
| 涉及金额计算 | 单元测试 | 必须(多组边界值) |
|
||||||
|
| 涉及状态流转 | 单元测试 | 必须(覆盖所有状态路径) |
|
||||||
|
| 涉及外部接口调用 | 集成测试 | 必须(Mock 外部依赖) |
|
||||||
|
| 修 Bug | 回归测试 | 必须(防止复现) |
|
||||||
|
| 简单 CRUD | 可选 | 不强制 |
|
||||||
|
|
||||||
|
### AI 测试规则
|
||||||
|
|
||||||
|
**AI 完成任务后,必须同时交付测试代码。** 禁止说"功能写好了但测试你自己补"。
|
||||||
|
|
||||||
|
```java
|
||||||
|
// ✅ AI 必须产出完整测试
|
||||||
|
@SpringBootTest
|
||||||
|
class TaskServiceTest {
|
||||||
|
@Autowired
|
||||||
|
private TaskService taskService;
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void shouldCreateTask() { ... }
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void shouldNotCreateTaskWithoutTitle() { ... }
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void shouldCalculateRewardCorrectly() { ... }
|
||||||
|
}
|
||||||
|
|
||||||
|
// ❌ AI 不能这样
|
||||||
|
// "功能已完成,测试代码未编写,建议后续补充"
|
||||||
|
```
|
||||||
|
|
||||||
|
### 测试命名
|
||||||
|
|
||||||
|
```
|
||||||
|
方法名_场景_预期结果
|
||||||
|
|
||||||
|
shouldCreateTask_whenValidInput
|
||||||
|
shouldNotCreateTask_whenTitleIsEmpty
|
||||||
|
shouldCalculateReward_whenDiscountApplied
|
||||||
|
shouldReturnFail_whenTaskNotFound
|
||||||
|
```
|
||||||
|
|
||||||
|
### 禁止
|
||||||
|
|
||||||
|
- 测试只测正常路径,不测异常路径
|
||||||
|
- 测试依赖执行顺序(每个测试必须独立)
|
||||||
|
- 测试里有 `Thread.sleep()`(用 Awaitility)
|
||||||
|
- 测试代码复制粘贴业务代码(测了个寂寞)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 错误处理规则
|
||||||
|
|
||||||
|
### 返回格式(不变式)
|
||||||
|
|
||||||
|
```java
|
||||||
|
// ✅ 统一返回
|
||||||
|
Result.ok(data) // 成功
|
||||||
|
Result.error("原因") // 业务失败(用户可见)
|
||||||
|
Result.error("系统错误") // 系统异常(用户不可见,只记录日志)
|
||||||
|
|
||||||
|
// JSON 格式
|
||||||
|
{ "code": 200, "message": "success", "data": {...} } // 成功
|
||||||
|
{ "code": 500, "message": "任务不存在", "data": null } // 业务失败
|
||||||
|
{ "code": 500, "message": "系统繁忙,请稍后重试", "data": null } // 系统异常
|
||||||
|
```
|
||||||
|
|
||||||
|
### 什么情况返回什么
|
||||||
|
|
||||||
|
```java
|
||||||
|
// 查不到 → 业务失败
|
||||||
|
if (task == null) return Result.error("任务不存在");
|
||||||
|
|
||||||
|
// 参数不合法 → 业务失败
|
||||||
|
if (page < 1) return Result.error("页码必须大于0");
|
||||||
|
|
||||||
|
// 没权限 → 业务失败
|
||||||
|
if (!hasPermission) return Result.error("无权操作");
|
||||||
|
|
||||||
|
// 数据库连接失败 → 系统异常(全局异常处理器统一捕获)
|
||||||
|
// 第三方接口超时 → 系统异常(记录日志 + 返回通用错误)
|
||||||
|
// 不需要手动 try-catch 每个地方,用全局异常处理器统一处理
|
||||||
|
```
|
||||||
|
|
||||||
|
### 全局异常处理器
|
||||||
|
|
||||||
|
```java
|
||||||
|
@RestControllerAdvice
|
||||||
|
public class GlobalExceptionHandler {
|
||||||
|
|
||||||
|
@ExceptionHandler(BusinessException.class)
|
||||||
|
public Result<?> handleBusiness(BusinessException e) {
|
||||||
|
log.warn("业务异常: {}", e.getMessage());
|
||||||
|
return Result.error(e.getMessage()); // 用户可见
|
||||||
|
}
|
||||||
|
|
||||||
|
@ExceptionHandler(Exception.class)
|
||||||
|
public Result<?> handleException(Exception e) {
|
||||||
|
log.error("系统异常", e);
|
||||||
|
return Result.error("系统繁忙,请稍后重试"); // 用户不可见原文
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 禁止
|
||||||
|
|
||||||
|
| ❌ | ✅ |
|
||||||
|
|----|-----|
|
||||||
|
| `return Result.error(e.getMessage())` 把栈打印给用户 | `return Result.error("任务不存在")` |
|
||||||
|
| 每个方法都 try-catch 一遍 | 全局异常处理器统一处理 |
|
||||||
|
| 异常被吞掉 `catch(Exception e) {}` | 至少打日志 `log.error("xxx", e)` |
|
||||||
|
| `return null` 让前端爆 NPE | `return Result.error("原因")` |
|
||||||
|
| 成功和失败都用 code=200 | 失败用 code=500 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 检查表
|
||||||
|
|
||||||
|
### 测试
|
||||||
|
|
||||||
|
- [ ] 新增的非 CRUD 方法有测试
|
||||||
|
- [ ] 测试覆盖了异常路径(不是只测正常路径)
|
||||||
|
- [ ] 金额计算有边界值测试
|
||||||
|
- [ ] AI 交付包含测试代码
|
||||||
|
|
||||||
|
### 错误处理
|
||||||
|
|
||||||
|
- [ ] 错误信息用户能看懂(不是技术术语)
|
||||||
|
- [ ] 系统异常不暴露内部信息给用户
|
||||||
|
- [ ] 查不到/null 有明确 fail 返回
|
||||||
|
- [ ] 没有空 catch 块
|
||||||
|
- [ ] 没有 `return null` 代替错误返回
|
||||||
|
|
@ -0,0 +1,57 @@
|
||||||
|
# Git
|
||||||
|
.git/
|
||||||
|
.gitignore
|
||||||
|
.gitmodules
|
||||||
|
|
||||||
|
# SVN
|
||||||
|
.svn/
|
||||||
|
|
||||||
|
# IntelliJ IDEA
|
||||||
|
.idea/
|
||||||
|
*.iml
|
||||||
|
*.iws
|
||||||
|
*.ipr
|
||||||
|
out/
|
||||||
|
|
||||||
|
# Eclipse
|
||||||
|
.classpath
|
||||||
|
.project
|
||||||
|
.settings/
|
||||||
|
|
||||||
|
# VS Code
|
||||||
|
.vscode/
|
||||||
|
|
||||||
|
# Maven / Gradle build output
|
||||||
|
target/
|
||||||
|
build/
|
||||||
|
!.mvn/wrapper/maven-wrapper.jar
|
||||||
|
|
||||||
|
# OS files
|
||||||
|
.DS_Store
|
||||||
|
Thumbs.db
|
||||||
|
desktop.ini
|
||||||
|
|
||||||
|
# Logs
|
||||||
|
*.log
|
||||||
|
logs/
|
||||||
|
|
||||||
|
# Node (frontend artifacts if any)
|
||||||
|
node_modules/
|
||||||
|
dist/
|
||||||
|
|
||||||
|
# Docker volumes / data
|
||||||
|
docker/data/
|
||||||
|
|
||||||
|
# Compiled classes
|
||||||
|
*.class
|
||||||
|
|
||||||
|
# Custom
|
||||||
|
*.qqy
|
||||||
|
代码修改.log
|
||||||
|
代码修改日志
|
||||||
|
*.zip
|
||||||
|
backup/
|
||||||
|
.history/
|
||||||
|
.cursor/
|
||||||
|
doc/
|
||||||
|
docs/
|
||||||
|
|
@ -0,0 +1,121 @@
|
||||||
|
# ghb-base — AI 开发总纲
|
||||||
|
|
||||||
|
> coverage: 聚合版,可直接粘贴到 Kimi / DeepSeek / GPT 等无自动加载的 AI 对话中。自动加载工具(Claude Code / Cursor / Codex / Copilot / Windsurf)会从对应入口文件读取。
|
||||||
|
>
|
||||||
|
> 所有 AI 编码助手首先读本文件。读完本文件后,必须继续读取 `.claude/` 目录下的全部规则文件,再开始编写代码。
|
||||||
|
|
||||||
|
## 项目信息
|
||||||
|
|
||||||
|
- **名称**:ghb-base(基于 JeecgBoot 3.9.2 精简)
|
||||||
|
- **技术栈**:Spring Boot 3.5.5 / Java 17 / MyBatis-Plus / Shiro+JWT / MySQL / Redis
|
||||||
|
- **包名**:`com.ghb.base` | 数据库:`ghb_base` | 上下文路径:`/ghb`
|
||||||
|
- **前端**:Vue 3 + Vite + Ant Design Vue + TypeScript
|
||||||
|
|
||||||
|
## 模块
|
||||||
|
|
||||||
|
```
|
||||||
|
ghb-base-parent/
|
||||||
|
├── ghb-base-core/ # 核心框架(不改)
|
||||||
|
├── ghb-module-system/ # 租户/用户/角色/菜单/字典/日志(不改)
|
||||||
|
├── ghb-module-business/ # 业务代码 ← 写这里
|
||||||
|
└── ghb-server-cloud/ # 微服务(网关/Nacos/监控)
|
||||||
|
```
|
||||||
|
|
||||||
|
## 必读规则(全部读完再写代码)
|
||||||
|
|
||||||
|
1. `.claude/contract.md` — 返回格式 · 分页 · 状态值 · 契约生命周期 · 同步铁律
|
||||||
|
2. `.claude/backend.md` — 分层 · 命名 · 注释 · CRUD 模板 · 禁止清单 · 检查表
|
||||||
|
3. `.claude/frontend.md` — 样式 · 命名 · 注释 · 组件铁律 · 页面模板 · 检查表
|
||||||
|
4. `.claude/database.md` — 表设计 · 字段类型 · 索引 · 必有字段 · 检查表
|
||||||
|
5. `.claude/git.md` — 分支命名 · commit 格式 · AI 提交标注 · 禁止操作
|
||||||
|
6. `.claude/security.md` — 认证 · 数据权限 · 敏感信息 · 文件上传 · 日志
|
||||||
|
7. `.claude/testing.md` — 测试要求 · 错误码 · 全局异常处理 · 检查表
|
||||||
|
8. `.claude/encoding.md` — 字符编码(UTF-8 无 BOM · 禁 GBK · 批量改写须 UTF-8 感知)
|
||||||
|
|
||||||
|
## 接口契约
|
||||||
|
|
||||||
|
契约文件在 `contract/` 目录(独立 git 仓库,前后端 submodule 引用)。修改接口前必须先更新契约。
|
||||||
|
|
||||||
|
## 环境要求
|
||||||
|
|
||||||
|
- JDK 17+
|
||||||
|
- Maven 3.8+
|
||||||
|
- MySQL 8.0+
|
||||||
|
- Redis 6.0+
|
||||||
|
- Node.js 18+ / pnpm
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 后端启动
|
||||||
|
cd test-module-system/test-system-start
|
||||||
|
mvn spring-boot:run -Pdev
|
||||||
|
|
||||||
|
# 前端启动
|
||||||
|
cd ghb-frontend
|
||||||
|
pnpm install
|
||||||
|
pnpm dev
|
||||||
|
```
|
||||||
|
|
||||||
|
## 多工具兼容
|
||||||
|
|
||||||
|
| 工具 | 入口文件 | 操作 |
|
||||||
|
|------|----------|------|
|
||||||
|
| Claude Code | `CLAUDE.md` | 自动加载,无需操作 |
|
||||||
|
| Cursor | `.cursorrules` | 自动加载,无需操作 |
|
||||||
|
| Codex / OpenCode | `AGENTS.md` | 自动加载,无需操作 |
|
||||||
|
| GitHub Copilot | `.github/copilot-instructions.md` | 自动加载,无需操作 |
|
||||||
|
| Windsurf | `.windsurfrules` | 自动加载(把 CLAUDE.md 复制一份改名为 .windsurfrules) |
|
||||||
|
| **Kimi / DeepSeek / GPT** | 无自动 | **手动粘贴**:把本文件 + `.claude/` 全部内容一次性贴到对话开头 |
|
||||||
|
| **人工开发** | 无自动 | 阅读 `开发规范-人工版.md`(同级目录) |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 审查机制 — 怎么检查代码是否合规
|
||||||
|
|
||||||
|
### 自动化检查(提交前自动跑)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 后端代码检查
|
||||||
|
mvn checkstyle:check # Java 代码风格
|
||||||
|
mvn test # 单元测试
|
||||||
|
|
||||||
|
# 前端代码检查
|
||||||
|
pnpm lint # ESLint
|
||||||
|
pnpm stylelint # 样式检查
|
||||||
|
|
||||||
|
# 数据库 SQL 检查
|
||||||
|
# 人工 review:金额字段是不是 DECIMAL、有没有 COMMENT、有没有 create_time
|
||||||
|
```
|
||||||
|
|
||||||
|
### AI 产出专项检查
|
||||||
|
|
||||||
|
| 检查项 | 怎么查 | 不合格的表现 |
|
||||||
|
|--------|--------|-------------|
|
||||||
|
| 返回值是否包装 | `grep -r "return [^R]" --include="*.java" | grep -v Result` | 出现裸 `return data;` |
|
||||||
|
| 手写 SQL 是否带租户 | `grep -r "@Select" --include="*.java"` | SQL 里没有 `tenant_id` |
|
||||||
|
| Controller 是否写了业务逻辑 | 人工 review Controller 方法体 | 超过 20 行或有 `if/else` 嵌套 |
|
||||||
|
| Commit 是否标注 AI | `git log --oneline -20` | 没有 `[AI: xxx]` 标记 |
|
||||||
|
| 是否包含测试 | `git diff --stat` 看是否有测试文件 | 新功能没测试类 |
|
||||||
|
|
||||||
|
### PR Review 必查清单
|
||||||
|
|
||||||
|
```
|
||||||
|
□ 接口变更 → contract/ 目录有对应更新
|
||||||
|
□ 返回格式 → 全部用 Result 包装
|
||||||
|
□ 手写 SQL → 有 tenant_id 条件
|
||||||
|
□ 新增表 → 有 create_time / update_time / COMMENT
|
||||||
|
□ 金额字段 → 类型是 DECIMAL
|
||||||
|
□ 硬编码 → 无魔法数字、无裸色值、无裸字号
|
||||||
|
□ Commit → 格式正确,AI 代码有标注
|
||||||
|
□ 测试 → 新功能有测试代码
|
||||||
|
```
|
||||||
|
|
||||||
|
### 常见违规信号
|
||||||
|
|
||||||
|
| 信号 | 可能的问题 |
|
||||||
|
|------|-----------|
|
||||||
|
| `return data;`(裸返回) | 没读规则 |
|
||||||
|
| `@Select("SELECT * FROM xxx WHERE ...")` 缺 tenant_id | 数据泄露风险 |
|
||||||
|
| 类名超过 35 字符 | 没缩写 |
|
||||||
|
| `color: #` 硬编码 | 没读前端规则 |
|
||||||
|
| `git commit -m "update"` | 没读 Git 规则 |
|
||||||
|
| Controller 超过 100 行 | 业务逻辑泄漏到接口层 |
|
||||||
|
|
@ -0,0 +1,10 @@
|
||||||
|
.git
|
||||||
|
deploy
|
||||||
|
*.md
|
||||||
|
.github
|
||||||
|
.claude
|
||||||
|
.cursorrules
|
||||||
|
.windsurfrules
|
||||||
|
.idea
|
||||||
|
.vscode
|
||||||
|
*.iml
|
||||||
|
|
@ -0,0 +1,12 @@
|
||||||
|
root = true
|
||||||
|
|
||||||
|
[*]
|
||||||
|
charset = utf-8
|
||||||
|
end_of_line = lf
|
||||||
|
insert_final_newline = true
|
||||||
|
trim_trailing_whitespace = true
|
||||||
|
indent_style = space
|
||||||
|
indent_size = 4
|
||||||
|
|
||||||
|
[*.md]
|
||||||
|
trim_trailing_whitespace = false
|
||||||
|
|
@ -0,0 +1,121 @@
|
||||||
|
# ghb-base — AI 开发总纲
|
||||||
|
|
||||||
|
> coverage: 聚合版,可直接粘贴到 Kimi / DeepSeek / GPT 等无自动加载的 AI 对话中。自动加载工具(Claude Code / Cursor / Codex / Copilot / Windsurf)会从对应入口文件读取。
|
||||||
|
>
|
||||||
|
> 所有 AI 编码助手首先读本文件。读完本文件后,必须继续读取 `.claude/` 目录下的全部规则文件,再开始编写代码。
|
||||||
|
|
||||||
|
## 项目信息
|
||||||
|
|
||||||
|
- **名称**:ghb-base(基于 JeecgBoot 3.9.2 精简)
|
||||||
|
- **技术栈**:Spring Boot 3.5.5 / Java 17 / MyBatis-Plus / Shiro+JWT / MySQL / Redis
|
||||||
|
- **包名**:`com.ghb.base` | 数据库:`ghb_base` | 上下文路径:`/ghb`
|
||||||
|
- **前端**:Vue 3 + Vite + Ant Design Vue + TypeScript
|
||||||
|
|
||||||
|
## 模块
|
||||||
|
|
||||||
|
```
|
||||||
|
ghb-base-parent/
|
||||||
|
├── ghb-base-core/ # 核心框架(不改)
|
||||||
|
├── ghb-module-system/ # 租户/用户/角色/菜单/字典/日志(不改)
|
||||||
|
├── ghb-module-business/ # 业务代码 ← 写这里
|
||||||
|
└── ghb-server-cloud/ # 微服务(网关/Nacos/监控)
|
||||||
|
```
|
||||||
|
|
||||||
|
## 必读规则(全部读完再写代码)
|
||||||
|
|
||||||
|
1. `.claude/contract.md` — 返回格式 · 分页 · 状态值 · 契约生命周期 · 同步铁律
|
||||||
|
2. `.claude/backend.md` — 分层 · 命名 · 注释 · CRUD 模板 · 禁止清单 · 检查表
|
||||||
|
3. `.claude/frontend.md` — 样式 · 命名 · 注释 · 组件铁律 · 页面模板 · 检查表
|
||||||
|
4. `.claude/database.md` — 表设计 · 字段类型 · 索引 · 必有字段 · 检查表
|
||||||
|
5. `.claude/git.md` — 分支命名 · commit 格式 · AI 提交标注 · 禁止操作
|
||||||
|
6. `.claude/security.md` — 认证 · 数据权限 · 敏感信息 · 文件上传 · 日志
|
||||||
|
7. `.claude/testing.md` — 测试要求 · 错误码 · 全局异常处理 · 检查表
|
||||||
|
8. `.claude/encoding.md` — 字符编码(UTF-8 无 BOM · 禁 GBK · 批量改写须 UTF-8 感知)
|
||||||
|
|
||||||
|
## 接口契约
|
||||||
|
|
||||||
|
契约文件在 `contract/` 目录(独立 git 仓库,前后端 submodule 引用)。修改接口前必须先更新契约。
|
||||||
|
|
||||||
|
## 环境要求
|
||||||
|
|
||||||
|
- JDK 17+
|
||||||
|
- Maven 3.8+
|
||||||
|
- MySQL 8.0+
|
||||||
|
- Redis 6.0+
|
||||||
|
- Node.js 18+ / pnpm
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 后端启动
|
||||||
|
cd test-module-system/test-system-start
|
||||||
|
mvn spring-boot:run -Pdev
|
||||||
|
|
||||||
|
# 前端启动
|
||||||
|
cd ghb-frontend
|
||||||
|
pnpm install
|
||||||
|
pnpm dev
|
||||||
|
```
|
||||||
|
|
||||||
|
## 多工具兼容
|
||||||
|
|
||||||
|
| 工具 | 入口文件 | 操作 |
|
||||||
|
|------|----------|------|
|
||||||
|
| Claude Code | `CLAUDE.md` | 自动加载,无需操作 |
|
||||||
|
| Cursor | `.cursorrules` | 自动加载,无需操作 |
|
||||||
|
| Codex / OpenCode | `AGENTS.md` | 自动加载,无需操作 |
|
||||||
|
| GitHub Copilot | `.github/copilot-instructions.md` | 自动加载,无需操作 |
|
||||||
|
| Windsurf | `.windsurfrules` | 自动加载(把 CLAUDE.md 复制一份改名为 .windsurfrules) |
|
||||||
|
| **Kimi / DeepSeek / GPT** | 无自动 | **手动粘贴**:把本文件 + `.claude/` 全部内容一次性贴到对话开头 |
|
||||||
|
| **人工开发** | 无自动 | 阅读 `开发规范-人工版.md`(同级目录) |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 审查机制 — 怎么检查代码是否合规
|
||||||
|
|
||||||
|
### 自动化检查(提交前自动跑)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 后端代码检查
|
||||||
|
mvn checkstyle:check # Java 代码风格
|
||||||
|
mvn test # 单元测试
|
||||||
|
|
||||||
|
# 前端代码检查
|
||||||
|
pnpm lint # ESLint
|
||||||
|
pnpm stylelint # 样式检查
|
||||||
|
|
||||||
|
# 数据库 SQL 检查
|
||||||
|
# 人工 review:金额字段是不是 DECIMAL、有没有 COMMENT、有没有 create_time
|
||||||
|
```
|
||||||
|
|
||||||
|
### AI 产出专项检查
|
||||||
|
|
||||||
|
| 检查项 | 怎么查 | 不合格的表现 |
|
||||||
|
|--------|--------|-------------|
|
||||||
|
| 返回值是否包装 | `grep -r "return [^R]" --include="*.java" | grep -v Result` | 出现裸 `return data;` |
|
||||||
|
| 手写 SQL 是否带租户 | `grep -r "@Select" --include="*.java"` | SQL 里没有 `tenant_id` |
|
||||||
|
| Controller 是否写了业务逻辑 | 人工 review Controller 方法体 | 超过 20 行或有 `if/else` 嵌套 |
|
||||||
|
| Commit 是否标注 AI | `git log --oneline -20` | 没有 `[AI: xxx]` 标记 |
|
||||||
|
| 是否包含测试 | `git diff --stat` 看是否有测试文件 | 新功能没测试类 |
|
||||||
|
|
||||||
|
### PR Review 必查清单
|
||||||
|
|
||||||
|
```
|
||||||
|
□ 接口变更 → contract/ 目录有对应更新
|
||||||
|
□ 返回格式 → 全部用 Result 包装
|
||||||
|
□ 手写 SQL → 有 tenant_id 条件
|
||||||
|
□ 新增表 → 有 create_time / update_time / COMMENT
|
||||||
|
□ 金额字段 → 类型是 DECIMAL
|
||||||
|
□ 硬编码 → 无魔法数字、无裸色值、无裸字号
|
||||||
|
□ Commit → 格式正确,AI 代码有标注
|
||||||
|
□ 测试 → 新功能有测试代码
|
||||||
|
```
|
||||||
|
|
||||||
|
### 常见违规信号
|
||||||
|
|
||||||
|
| 信号 | 可能的问题 |
|
||||||
|
|------|-----------|
|
||||||
|
| `return data;`(裸返回) | 没读规则 |
|
||||||
|
| `@Select("SELECT * FROM xxx WHERE ...")` 缺 tenant_id | 数据泄露风险 |
|
||||||
|
| 类名超过 35 字符 | 没缩写 |
|
||||||
|
| `color: #` 硬编码 | 没读前端规则 |
|
||||||
|
| `git commit -m "update"` | 没读 Git 规则 |
|
||||||
|
| Controller 超过 100 行 | 业务逻辑泄漏到接口层 |
|
||||||
|
|
@ -0,0 +1,33 @@
|
||||||
|
# 依赖与构建产物
|
||||||
|
**/node_modules/
|
||||||
|
**/dist/
|
||||||
|
**/target/
|
||||||
|
**/logs/
|
||||||
|
**/.cache/
|
||||||
|
**/docs/tasks/
|
||||||
|
**/docs/tasks/**
|
||||||
|
**/.eslintcache
|
||||||
|
|
||||||
|
# IDE / 编辑器
|
||||||
|
.idea/
|
||||||
|
**/*.iml
|
||||||
|
.vscode/
|
||||||
|
.history/
|
||||||
|
*.suo
|
||||||
|
*.sw?
|
||||||
|
|
||||||
|
# 独立子仓库(接口契约按规则单独管理,不并入主仓库)
|
||||||
|
|
||||||
|
# 本地环境与日志
|
||||||
|
**/.env.local
|
||||||
|
**/.env.*.local
|
||||||
|
**/*-debug.log*
|
||||||
|
**/docs/tasks/**
|
||||||
|
rebel.xml
|
||||||
|
derby.log
|
||||||
|
|
||||||
|
# 系统
|
||||||
|
.DS_Store
|
||||||
|
Thumbs.db
|
||||||
|
os_del.cmd
|
||||||
|
os_del_doc.cmd
|
||||||
|
|
@ -0,0 +1,121 @@
|
||||||
|
# ghb-base — AI 开发总纲
|
||||||
|
|
||||||
|
> coverage: 聚合版,可直接粘贴到 Kimi / DeepSeek / GPT 等无自动加载的 AI 对话中。自动加载工具(Claude Code / Cursor / Codex / Copilot / Windsurf)会从对应入口文件读取。
|
||||||
|
>
|
||||||
|
> 所有 AI 编码助手首先读本文件。读完本文件后,必须继续读取 `.claude/` 目录下的全部规则文件,再开始编写代码。
|
||||||
|
|
||||||
|
## 项目信息
|
||||||
|
|
||||||
|
- **名称**:ghb-base(基于 JeecgBoot 3.9.2 精简)
|
||||||
|
- **技术栈**:Spring Boot 3.5.5 / Java 17 / MyBatis-Plus / Shiro+JWT / MySQL / Redis
|
||||||
|
- **包名**:`com.ghb.base` | 数据库:`ghb_base` | 上下文路径:`/ghb`
|
||||||
|
- **前端**:Vue 3 + Vite + Ant Design Vue + TypeScript
|
||||||
|
|
||||||
|
## 模块
|
||||||
|
|
||||||
|
```
|
||||||
|
ghb-base-parent/
|
||||||
|
├── ghb-base-core/ # 核心框架(不改)
|
||||||
|
├── ghb-module-system/ # 租户/用户/角色/菜单/字典/日志(不改)
|
||||||
|
├── ghb-module-business/ # 业务代码 ← 写这里
|
||||||
|
└── ghb-server-cloud/ # 微服务(网关/Nacos/监控)
|
||||||
|
```
|
||||||
|
|
||||||
|
## 必读规则(全部读完再写代码)
|
||||||
|
|
||||||
|
1. `.claude/contract.md` — 返回格式 · 分页 · 状态值 · 契约生命周期 · 同步铁律
|
||||||
|
2. `.claude/backend.md` — 分层 · 命名 · 注释 · CRUD 模板 · 禁止清单 · 检查表
|
||||||
|
3. `.claude/frontend.md` — 样式 · 命名 · 注释 · 组件铁律 · 页面模板 · 检查表
|
||||||
|
4. `.claude/database.md` — 表设计 · 字段类型 · 索引 · 必有字段 · 检查表
|
||||||
|
5. `.claude/git.md` — 分支命名 · commit 格式 · AI 提交标注 · 禁止操作
|
||||||
|
6. `.claude/security.md` — 认证 · 数据权限 · 敏感信息 · 文件上传 · 日志
|
||||||
|
7. `.claude/testing.md` — 测试要求 · 错误码 · 全局异常处理 · 检查表
|
||||||
|
8. `.claude/encoding.md` — 字符编码(UTF-8 无 BOM · 禁 GBK · 批量改写须 UTF-8 感知)
|
||||||
|
|
||||||
|
## 接口契约
|
||||||
|
|
||||||
|
契约文件在 `contract/` 目录(独立 git 仓库,前后端 submodule 引用)。修改接口前必须先更新契约。
|
||||||
|
|
||||||
|
## 环境要求
|
||||||
|
|
||||||
|
- JDK 17+
|
||||||
|
- Maven 3.8+
|
||||||
|
- MySQL 8.0+
|
||||||
|
- Redis 6.0+
|
||||||
|
- Node.js 18+ / pnpm
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 后端启动
|
||||||
|
cd test-module-system/test-system-start
|
||||||
|
mvn spring-boot:run -Pdev
|
||||||
|
|
||||||
|
# 前端启动
|
||||||
|
cd ghb-frontend
|
||||||
|
pnpm install
|
||||||
|
pnpm dev
|
||||||
|
```
|
||||||
|
|
||||||
|
## 多工具兼容
|
||||||
|
|
||||||
|
| 工具 | 入口文件 | 操作 |
|
||||||
|
|------|----------|------|
|
||||||
|
| Claude Code | `CLAUDE.md` | 自动加载,无需操作 |
|
||||||
|
| Cursor | `.cursorrules` | 自动加载,无需操作 |
|
||||||
|
| Codex / OpenCode | `AGENTS.md` | 自动加载,无需操作 |
|
||||||
|
| GitHub Copilot | `.github/copilot-instructions.md` | 自动加载,无需操作 |
|
||||||
|
| Windsurf | `.windsurfrules` | 自动加载(把 CLAUDE.md 复制一份改名为 .windsurfrules) |
|
||||||
|
| **Kimi / DeepSeek / GPT** | 无自动 | **手动粘贴**:把本文件 + `.claude/` 全部内容一次性贴到对话开头 |
|
||||||
|
| **人工开发** | 无自动 | 阅读 `开发规范-人工版.md`(同级目录) |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 审查机制 — 怎么检查代码是否合规
|
||||||
|
|
||||||
|
### 自动化检查(提交前自动跑)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 后端代码检查
|
||||||
|
mvn checkstyle:check # Java 代码风格
|
||||||
|
mvn test # 单元测试
|
||||||
|
|
||||||
|
# 前端代码检查
|
||||||
|
pnpm lint # ESLint
|
||||||
|
pnpm stylelint # 样式检查
|
||||||
|
|
||||||
|
# 数据库 SQL 检查
|
||||||
|
# 人工 review:金额字段是不是 DECIMAL、有没有 COMMENT、有没有 create_time
|
||||||
|
```
|
||||||
|
|
||||||
|
### AI 产出专项检查
|
||||||
|
|
||||||
|
| 检查项 | 怎么查 | 不合格的表现 |
|
||||||
|
|--------|--------|-------------|
|
||||||
|
| 返回值是否包装 | `grep -r "return [^R]" --include="*.java" | grep -v Result` | 出现裸 `return data;` |
|
||||||
|
| 手写 SQL 是否带租户 | `grep -r "@Select" --include="*.java"` | SQL 里没有 `tenant_id` |
|
||||||
|
| Controller 是否写了业务逻辑 | 人工 review Controller 方法体 | 超过 20 行或有 `if/else` 嵌套 |
|
||||||
|
| Commit 是否标注 AI | `git log --oneline -20` | 没有 `[AI: xxx]` 标记 |
|
||||||
|
| 是否包含测试 | `git diff --stat` 看是否有测试文件 | 新功能没测试类 |
|
||||||
|
|
||||||
|
### PR Review 必查清单
|
||||||
|
|
||||||
|
```
|
||||||
|
□ 接口变更 → contract/ 目录有对应更新
|
||||||
|
□ 返回格式 → 全部用 Result 包装
|
||||||
|
□ 手写 SQL → 有 tenant_id 条件
|
||||||
|
□ 新增表 → 有 create_time / update_time / COMMENT
|
||||||
|
□ 金额字段 → 类型是 DECIMAL
|
||||||
|
□ 硬编码 → 无魔法数字、无裸色值、无裸字号
|
||||||
|
□ Commit → 格式正确,AI 代码有标注
|
||||||
|
□ 测试 → 新功能有测试代码
|
||||||
|
```
|
||||||
|
|
||||||
|
### 常见违规信号
|
||||||
|
|
||||||
|
| 信号 | 可能的问题 |
|
||||||
|
|------|-----------|
|
||||||
|
| `return data;`(裸返回) | 没读规则 |
|
||||||
|
| `@Select("SELECT * FROM xxx WHERE ...")` 缺 tenant_id | 数据泄露风险 |
|
||||||
|
| 类名超过 35 字符 | 没缩写 |
|
||||||
|
| `color: #` 硬编码 | 没读前端规则 |
|
||||||
|
| `git commit -m "update"` | 没读 Git 规则 |
|
||||||
|
| Controller 超过 100 行 | 业务逻辑泄漏到接口层 |
|
||||||
|
|
@ -0,0 +1,121 @@
|
||||||
|
# ghb-base — AI 开发总纲
|
||||||
|
|
||||||
|
> coverage: 聚合版,可直接粘贴到 Kimi / DeepSeek / GPT 等无自动加载的 AI 对话中。自动加载工具(Claude Code / Cursor / Codex / Copilot / Windsurf)会从对应入口文件读取。
|
||||||
|
>
|
||||||
|
> 所有 AI 编码助手首先读本文件。读完本文件后,必须继续读取 `.claude/` 目录下的全部规则文件,再开始编写代码。
|
||||||
|
|
||||||
|
## 项目信息
|
||||||
|
|
||||||
|
- **名称**:ghb-base(基于 JeecgBoot 3.9.2 精简)
|
||||||
|
- **技术栈**:Spring Boot 3.5.5 / Java 17 / MyBatis-Plus / Shiro+JWT / MySQL / Redis
|
||||||
|
- **包名**:`com.ghb.base` | 数据库:`ghb_base` | 上下文路径:`/ghb`
|
||||||
|
- **前端**:Vue 3 + Vite + Ant Design Vue + TypeScript
|
||||||
|
|
||||||
|
## 模块
|
||||||
|
|
||||||
|
```
|
||||||
|
ghb-base-parent/
|
||||||
|
├── ghb-base-core/ # 核心框架(不改)
|
||||||
|
├── ghb-module-system/ # 租户/用户/角色/菜单/字典/日志(不改)
|
||||||
|
├── ghb-module-business/ # 业务代码 ← 写这里
|
||||||
|
└── ghb-server-cloud/ # 微服务(网关/Nacos/监控)
|
||||||
|
```
|
||||||
|
|
||||||
|
## 必读规则(全部读完再写代码)
|
||||||
|
|
||||||
|
1. `.claude/contract.md` — 返回格式 · 分页 · 状态值 · 契约生命周期 · 同步铁律
|
||||||
|
2. `.claude/backend.md` — 分层 · 命名 · 注释 · CRUD 模板 · 禁止清单 · 检查表
|
||||||
|
3. `.claude/frontend.md` — 样式 · 命名 · 注释 · 组件铁律 · 页面模板 · 检查表
|
||||||
|
4. `.claude/database.md` — 表设计 · 字段类型 · 索引 · 必有字段 · 检查表
|
||||||
|
5. `.claude/git.md` — 分支命名 · commit 格式 · AI 提交标注 · 禁止操作
|
||||||
|
6. `.claude/security.md` — 认证 · 数据权限 · 敏感信息 · 文件上传 · 日志
|
||||||
|
7. `.claude/testing.md` — 测试要求 · 错误码 · 全局异常处理 · 检查表
|
||||||
|
8. `.claude/encoding.md` — 字符编码(UTF-8 无 BOM · 禁 GBK · 批量改写须 UTF-8 感知)
|
||||||
|
|
||||||
|
## 接口契约
|
||||||
|
|
||||||
|
契约文件在 `contract/` 目录(独立 git 仓库,前后端 submodule 引用)。修改接口前必须先更新契约。
|
||||||
|
|
||||||
|
## 环境要求
|
||||||
|
|
||||||
|
- JDK 17+
|
||||||
|
- Maven 3.8+
|
||||||
|
- MySQL 8.0+
|
||||||
|
- Redis 6.0+
|
||||||
|
- Node.js 18+ / pnpm
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 后端启动
|
||||||
|
cd test-module-system/test-system-start
|
||||||
|
mvn spring-boot:run -Pdev
|
||||||
|
|
||||||
|
# 前端启动
|
||||||
|
cd ghb-frontend
|
||||||
|
pnpm install
|
||||||
|
pnpm dev
|
||||||
|
```
|
||||||
|
|
||||||
|
## 多工具兼容
|
||||||
|
|
||||||
|
| 工具 | 入口文件 | 操作 |
|
||||||
|
|------|----------|------|
|
||||||
|
| Claude Code | `CLAUDE.md` | 自动加载,无需操作 |
|
||||||
|
| Cursor | `.cursorrules` | 自动加载,无需操作 |
|
||||||
|
| Codex / OpenCode | `AGENTS.md` | 自动加载,无需操作 |
|
||||||
|
| GitHub Copilot | `.github/copilot-instructions.md` | 自动加载,无需操作 |
|
||||||
|
| Windsurf | `.windsurfrules` | 自动加载(把 CLAUDE.md 复制一份改名为 .windsurfrules) |
|
||||||
|
| **Kimi / DeepSeek / GPT** | 无自动 | **手动粘贴**:把本文件 + `.claude/` 全部内容一次性贴到对话开头 |
|
||||||
|
| **人工开发** | 无自动 | 阅读 `开发规范-人工版.md`(同级目录) |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 审查机制 — 怎么检查代码是否合规
|
||||||
|
|
||||||
|
### 自动化检查(提交前自动跑)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 后端代码检查
|
||||||
|
mvn checkstyle:check # Java 代码风格
|
||||||
|
mvn test # 单元测试
|
||||||
|
|
||||||
|
# 前端代码检查
|
||||||
|
pnpm lint # ESLint
|
||||||
|
pnpm stylelint # 样式检查
|
||||||
|
|
||||||
|
# 数据库 SQL 检查
|
||||||
|
# 人工 review:金额字段是不是 DECIMAL、有没有 COMMENT、有没有 create_time/update_time/del_flag
|
||||||
|
```
|
||||||
|
|
||||||
|
### AI 产出专项检查
|
||||||
|
|
||||||
|
| 检查项 | 怎么查 | 不合格的表现 |
|
||||||
|
|--------|--------|-------------|
|
||||||
|
| 返回值是否包装 | `grep -r "return [^R]" --include="*.java" | grep -v Result` | 出现裸 `return data;` |
|
||||||
|
| 手写 SQL 是否带租户 | `grep -r "@Select" --include="*.java"` | SQL 里没有 `tenant_id` |
|
||||||
|
| Controller 是否写了业务逻辑 | 人工 review Controller 方法体 | 超过 20 行或有 `if/else` 嵌套 |
|
||||||
|
| Commit 是否标注 AI | `git log --oneline -20` | 没有 `[AI: xxx]` 标记 |
|
||||||
|
| 是否包含测试 | `git diff --stat` 看是否有测试文件 | 新功能没测试类 |
|
||||||
|
|
||||||
|
### PR Review 必查清单
|
||||||
|
|
||||||
|
```
|
||||||
|
□ 接口变更 → contract/ 目录有对应更新
|
||||||
|
□ 返回格式 → 全部用 Result 包装
|
||||||
|
□ 手写 SQL → 有 tenant_id 条件
|
||||||
|
□ 新增表 → 有 create_time / update_time / del_flag / COMMENT
|
||||||
|
□ 金额字段 → 类型是 DECIMAL
|
||||||
|
□ 硬编码 → 无魔法数字、无裸色值、无裸字号
|
||||||
|
□ Commit → 格式正确,AI 代码有标注
|
||||||
|
□ 测试 → 新功能有测试代码
|
||||||
|
```
|
||||||
|
|
||||||
|
### 常见违规信号
|
||||||
|
|
||||||
|
| 信号 | 可能的问题 |
|
||||||
|
|------|-----------|
|
||||||
|
| `return data;`(裸返回) | 没读规则 |
|
||||||
|
| `@Select("SELECT * FROM xxx WHERE ...")` 缺 tenant_id | 数据泄露风险 |
|
||||||
|
| 类名超过 35 字符 | 没缩写 |
|
||||||
|
| `color: #` 硬编码 | 没读前端规则 |
|
||||||
|
| `git commit -m "update"` | 没读 Git 规则 |
|
||||||
|
| Controller 超过 100 行 | 业务逻辑泄漏到接口层 |
|
||||||
|
|
@ -0,0 +1,119 @@
|
||||||
|
# ghb-base — AI 开发总纲
|
||||||
|
|
||||||
|
> 所有 AI 编码助手首先读本文件。读完本文件后,必须继续读取 `.claude/` 目录下的全部规则文件,再开始编写代码。
|
||||||
|
|
||||||
|
## 项目信息
|
||||||
|
|
||||||
|
- **名称**:ghb-base(基于 JeecgBoot 3.9.2 精简)
|
||||||
|
- **技术栈**:Spring Boot 3.5.5 / Java 17 / MyBatis-Plus / Shiro+JWT / MySQL / Redis
|
||||||
|
- **包名**:`com.ghb.base` | 数据库:`ghb_base` | 上下文路径:`/ghb`
|
||||||
|
- **前端**:Vue 3 + Vite + Ant Design Vue + TypeScript
|
||||||
|
|
||||||
|
## 模块
|
||||||
|
|
||||||
|
```
|
||||||
|
ghb-base-parent/
|
||||||
|
├── ghb-base-core/ # 核心框架(不改)
|
||||||
|
├── ghb-module-system/ # 租户/用户/角色/菜单/字典/日志(不改)
|
||||||
|
├── ghb-module-business/ # 业务代码 ← 写这里
|
||||||
|
└── ghb-server-cloud/ # 微服务(网关/Nacos/监控)
|
||||||
|
```
|
||||||
|
|
||||||
|
## 必读规则(全部读完再写代码)
|
||||||
|
|
||||||
|
1. `.claude/contract.md` — 返回格式 · 分页 · 状态值 · 契约生命周期 · 同步铁律
|
||||||
|
2. `.claude/backend.md` — 分层 · 命名 · 注释 · CRUD 模板 · 禁止清单 · 检查表
|
||||||
|
3. `.claude/frontend.md` — 样式 · 命名 · 注释 · 组件铁律 · 页面模板 · 检查表
|
||||||
|
4. `.claude/database.md` — 表设计 · 字段类型 · 索引 · 必有字段 · 检查表
|
||||||
|
5. `.claude/git.md` — 分支命名 · commit 格式 · AI 提交标注 · 禁止操作
|
||||||
|
6. `.claude/security.md` — 认证 · 数据权限 · 敏感信息 · 文件上传 · 日志
|
||||||
|
7. `.claude/testing.md` — 测试要求 · 错误码 · 全局异常处理 · 检查表
|
||||||
|
8. `.claude/encoding.md` — 字符编码(一律 UTF-8 无 BOM · 禁 GBK · 批量改写须 UTF-8 感知 · mojibake 还原)
|
||||||
|
|
||||||
|
## 接口契约
|
||||||
|
|
||||||
|
契约文件在 `contract/` 目录(独立 git 仓库,前后端 submodule 引用)。修改接口前必须先更新契约。
|
||||||
|
|
||||||
|
## 环境要求
|
||||||
|
|
||||||
|
- JDK 17+
|
||||||
|
- Maven 3.8+
|
||||||
|
- MySQL 8.0+
|
||||||
|
- Redis 6.0+
|
||||||
|
- Node.js 18+ / pnpm
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 后端启动
|
||||||
|
cd test-module-system/test-system-start
|
||||||
|
mvn spring-boot:run -Pdev
|
||||||
|
|
||||||
|
# 前端启动
|
||||||
|
cd ghb-frontend
|
||||||
|
pnpm install
|
||||||
|
pnpm dev
|
||||||
|
```
|
||||||
|
|
||||||
|
## 多工具兼容
|
||||||
|
|
||||||
|
| 工具 | 入口文件 | 操作 |
|
||||||
|
|------|----------|------|
|
||||||
|
| Claude Code | `CLAUDE.md` | 自动加载,无需操作 |
|
||||||
|
| Cursor | `.cursorrules` | 自动加载,无需操作 |
|
||||||
|
| Codex / OpenCode | `AGENTS.md` | 自动加载,无需操作 |
|
||||||
|
| GitHub Copilot | `.github/copilot-instructions.md` | 自动加载,无需操作 |
|
||||||
|
| Windsurf | `.windsurfrules` | 自动加载(把 CLAUDE.md 复制一份改名为 .windsurfrules) |
|
||||||
|
| **Kimi / DeepSeek / GPT** | 无自动 | **手动粘贴**:把本文件 + `.claude/` 全部内容一次性贴到对话开头 |
|
||||||
|
| **人工开发** | 无自动 | 阅读 `开发规范-人工版.md`(同级目录) |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 审查机制 — 怎么检查代码是否合规
|
||||||
|
|
||||||
|
### 自动化检查(提交前自动跑)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 后端代码检查
|
||||||
|
mvn checkstyle:check # Java 代码风格
|
||||||
|
mvn test # 单元测试
|
||||||
|
|
||||||
|
# 前端代码检查
|
||||||
|
pnpm lint # ESLint
|
||||||
|
pnpm stylelint # 样式检查
|
||||||
|
|
||||||
|
# 数据库 SQL 检查
|
||||||
|
# 人工 review:金额字段是不是 DECIMAL、有没有 COMMENT、有没有 create_time
|
||||||
|
```
|
||||||
|
|
||||||
|
### AI 产出专项检查
|
||||||
|
|
||||||
|
| 检查项 | 怎么查 | 不合格的表现 |
|
||||||
|
|--------|--------|-------------|
|
||||||
|
| 返回值是否包装 | `grep -r "return [^R]" --include="*.java" | grep -v Result` | 出现裸 `return data;` |
|
||||||
|
| 手写 SQL 是否带租户 | `grep -r "@Select" --include="*.java"` | SQL 里没有 `tenant_id` |
|
||||||
|
| Controller 是否写了业务逻辑 | 人工 review Controller 方法体 | 超过 20 行或有 `if/else` 嵌套 |
|
||||||
|
| Commit 是否标注 AI | `git log --oneline -20` | 没有 `[AI: xxx]` 标记 |
|
||||||
|
| 是否包含测试 | `git diff --stat` 看是否有测试文件 | 新功能没测试类 |
|
||||||
|
|
||||||
|
### PR Review 必查清单
|
||||||
|
|
||||||
|
```
|
||||||
|
□ 接口变更 → contract/ 目录有对应更新
|
||||||
|
□ 返回格式 → 全部用 Result 包装
|
||||||
|
□ 手写 SQL → 有 tenant_id 条件
|
||||||
|
□ 新增表 → 有 create_time / update_time / COMMENT
|
||||||
|
□ 金额字段 → 类型是 DECIMAL
|
||||||
|
□ 硬编码 → 无魔法数字、无裸色值、无裸字号
|
||||||
|
□ Commit → 格式正确,AI 代码有标注
|
||||||
|
□ 测试 → 新功能有测试代码
|
||||||
|
```
|
||||||
|
|
||||||
|
### 常见违规信号
|
||||||
|
|
||||||
|
| 信号 | 可能的问题 |
|
||||||
|
|------|-----------|
|
||||||
|
| `return data;`(裸返回) | 没读规则 |
|
||||||
|
| `@Select("SELECT * FROM xxx WHERE ...")` 缺 tenant_id | 数据泄露风险 |
|
||||||
|
| 类名超过 35 字符 | 没缩写 |
|
||||||
|
| `color: #` 硬编码 | 没读前端规则 |
|
||||||
|
| `git commit -m "update"` | 没读 Git 规则 |
|
||||||
|
| Controller 超过 100 行 | 业务逻辑泄漏到接口层 |
|
||||||
|
|
@ -0,0 +1,52 @@
|
||||||
|
# ============================================
|
||||||
|
# 后端 Docker 镜像 — 多阶段构建
|
||||||
|
# Stage 1: Maven 编译(不污染宿主)
|
||||||
|
# Stage 2: JRE 运行(精简镜像)
|
||||||
|
# ============================================
|
||||||
|
|
||||||
|
# ---- Stage 1: 编译 ----
|
||||||
|
FROM maven:3.9-eclipse-temurin-17 AS builder
|
||||||
|
|
||||||
|
WORKDIR /build
|
||||||
|
|
||||||
|
# 先复制 pom.xml,利用 Docker 缓存加速依赖下载
|
||||||
|
COPY pom.xml ./
|
||||||
|
COPY test-base-core/pom.xml test-base-core/
|
||||||
|
COPY test-module-system/pom.xml test-module-system/
|
||||||
|
COPY test-module-system/test-system-api/pom.xml test-module-system/test-system-api/
|
||||||
|
COPY test-module-system/test-system-biz/pom.xml test-module-system/test-system-biz/
|
||||||
|
COPY test-module-system/test-system-start/pom.xml test-module-system/test-system-start/
|
||||||
|
COPY test-module-business/pom.xml test-module-business/
|
||||||
|
|
||||||
|
# 下载依赖(这一层在 pom 不变时会被缓存)
|
||||||
|
RUN mvn dependency:go-offline -B || true
|
||||||
|
|
||||||
|
# 复制全部源码
|
||||||
|
COPY . .
|
||||||
|
|
||||||
|
# 编译打包(跳过测试)
|
||||||
|
RUN mvn package -Dmaven.test.skip=true -T 1C
|
||||||
|
|
||||||
|
# ---- Stage 2: 运行 ----
|
||||||
|
FROM eclipse-temurin:17-jre
|
||||||
|
|
||||||
|
LABEL maintainer="ghb-base deploy"
|
||||||
|
|
||||||
|
# 时区(Debian 系)
|
||||||
|
ENV TZ=Asia/Shanghai
|
||||||
|
RUN ln -sf /usr/share/zoneinfo/$TZ /etc/localtime
|
||||||
|
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
# 从编译阶段复制 fat jar
|
||||||
|
COPY --from=builder /build/test-module-system/test-system-start/target/*.jar app.jar
|
||||||
|
|
||||||
|
# 上传文件目录
|
||||||
|
RUN mkdir -p /opt/upFiles
|
||||||
|
|
||||||
|
EXPOSE 8081
|
||||||
|
|
||||||
|
# JVM 参数可通过环境变量 JAVA_OPTS 覆盖
|
||||||
|
ENV JAVA_OPTS="-Xms512m -Xmx512m"
|
||||||
|
|
||||||
|
ENTRYPOINT ["sh", "-c", "java $JAVA_OPTS -jar app.jar"]
|
||||||
|
|
@ -0,0 +1,213 @@
|
||||||
|
Apache License
|
||||||
|
Version 2.0, January 2004
|
||||||
|
http://www.apache.org/licenses/
|
||||||
|
|
||||||
|
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||||
|
|
||||||
|
1. Definitions.
|
||||||
|
|
||||||
|
"License" shall mean the terms and conditions for use, reproduction,
|
||||||
|
and distribution as defined by Sections 1 through 9 of this document.
|
||||||
|
|
||||||
|
"Licensor" shall mean the copyright owner or entity authorized by
|
||||||
|
the copyright owner that is granting the License.
|
||||||
|
|
||||||
|
"Legal Entity" shall mean the union of the acting entity and all
|
||||||
|
other entities that control, are controlled by, or are under common
|
||||||
|
control with that entity. For the purposes of this definition,
|
||||||
|
"control" means (i) the power, direct or indirect, to cause the
|
||||||
|
direction or management of such entity, whether by contract or
|
||||||
|
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||||
|
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||||
|
|
||||||
|
"You" (or "Your") shall mean an individual or Legal Entity
|
||||||
|
exercising permissions granted by this License.
|
||||||
|
|
||||||
|
"Source" form shall mean the preferred form for making modifications,
|
||||||
|
including but not limited to software source code, documentation
|
||||||
|
source, and configuration files.
|
||||||
|
|
||||||
|
"Object" form shall mean any form resulting from mechanical
|
||||||
|
transformation or translation of a Source form, including but
|
||||||
|
not limited to compiled object code, generated documentation,
|
||||||
|
and conversions to other media types.
|
||||||
|
|
||||||
|
"Work" shall mean the work of authorship, whether in Source or
|
||||||
|
Object form, made available under the License, as indicated by a
|
||||||
|
copyright notice that is included in or attached to the work
|
||||||
|
(an example is provided in the Appendix below).
|
||||||
|
|
||||||
|
"Derivative Works" shall mean any work, whether in Source or Object
|
||||||
|
form, that is based on (or derived from) the Work and for which the
|
||||||
|
editorial revisions, annotations, elaborations, or other modifications
|
||||||
|
represent, as a whole, an original work of authorship. For the purposes
|
||||||
|
of this License, Derivative Works shall not include works that remain
|
||||||
|
separable from, or merely link (or bind by name) to the interfaces of,
|
||||||
|
the Work and Derivative Works thereof.
|
||||||
|
|
||||||
|
"Contribution" shall mean any work of authorship, including
|
||||||
|
the original version of the Work and any modifications or additions
|
||||||
|
to that Work or Derivative Works thereof, that is intentionally
|
||||||
|
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||||
|
or by an individual or Legal Entity authorized to submit on behalf of
|
||||||
|
the copyright owner. For the purposes of this definition, "submitted"
|
||||||
|
means any form of electronic, verbal, or written communication sent
|
||||||
|
to the Licensor or its representatives, including but not limited to
|
||||||
|
communication on electronic mailing lists, source code control systems,
|
||||||
|
and issue tracking systems that are managed by, or on behalf of, the
|
||||||
|
Licensor for the purpose of discussing and improving the Work, but
|
||||||
|
excluding communication that is conspicuously marked or otherwise
|
||||||
|
designated in writing by the copyright owner as "Not a Contribution."
|
||||||
|
|
||||||
|
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||||
|
on behalf of whom a Contribution has been received by Licensor and
|
||||||
|
subsequently incorporated within the Work.
|
||||||
|
|
||||||
|
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||||
|
this License, each Contributor hereby grants to You a perpetual,
|
||||||
|
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||||
|
copyright license to reproduce, prepare Derivative Works of,
|
||||||
|
publicly display, publicly perform, sublicense, and distribute the
|
||||||
|
Work and such Derivative Works in Source or Object form.
|
||||||
|
|
||||||
|
3. Grant of Patent License. Subject to the terms and conditions of
|
||||||
|
this License, each Contributor hereby grants to You a perpetual,
|
||||||
|
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||||
|
(except as stated in this section) patent license to make, have made,
|
||||||
|
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||||
|
where such license applies only to those patent claims licensable
|
||||||
|
by such Contributor that are necessarily infringed by their
|
||||||
|
Contribution(s) alone or by combination of their Contribution(s)
|
||||||
|
with the Work to which such Contribution(s) was submitted. If You
|
||||||
|
institute patent litigation against any entity (including a
|
||||||
|
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||||
|
or a Contribution incorporated within the Work constitutes direct
|
||||||
|
or contributory patent infringement, then any patent licenses
|
||||||
|
granted to You under this License for that Work shall terminate
|
||||||
|
as of the date such litigation is filed.
|
||||||
|
|
||||||
|
4. Redistribution. You may reproduce and distribute copies of the
|
||||||
|
Work or Derivative Works thereof in any medium, with or without
|
||||||
|
modifications, and in Source or Object form, provided that You
|
||||||
|
meet the following conditions:
|
||||||
|
|
||||||
|
(a) You must give any other recipients of the Work or
|
||||||
|
Derivative Works a copy of this License; and
|
||||||
|
|
||||||
|
(b) You must cause any modified files to carry prominent notices
|
||||||
|
stating that You changed the files; and
|
||||||
|
|
||||||
|
(c) You must retain, in the Source form of any Derivative Works
|
||||||
|
that You distribute, all copyright, patent, trademark, and
|
||||||
|
attribution notices from the Source form of the Work,
|
||||||
|
excluding those notices that do not pertain to any part of
|
||||||
|
the Derivative Works; and
|
||||||
|
|
||||||
|
(d) If the Work includes a "NOTICE" text file as part of its
|
||||||
|
distribution, then any Derivative Works that You distribute must
|
||||||
|
include a readable copy of the attribution notices contained
|
||||||
|
within such NOTICE file, excluding those notices that do not
|
||||||
|
pertain to any part of the Derivative Works, in at least one
|
||||||
|
of the following places: within a NOTICE text file distributed
|
||||||
|
as part of the Derivative Works; within the Source form or
|
||||||
|
documentation, if provided along with the Derivative Works; or,
|
||||||
|
within a display generated by the Derivative Works, if and
|
||||||
|
wherever such third-party notices normally appear. The contents
|
||||||
|
of the NOTICE file are for informational purposes only and
|
||||||
|
do not modify the License. You may add Your own attribution
|
||||||
|
notices within Derivative Works that You distribute, alongside
|
||||||
|
or as an addendum to the NOTICE text from the Work, provided
|
||||||
|
that such additional attribution notices cannot be construed
|
||||||
|
as modifying the License.
|
||||||
|
|
||||||
|
You may add Your own copyright statement to Your modifications and
|
||||||
|
may provide additional or different license terms and conditions
|
||||||
|
for use, reproduction, or distribution of Your modifications, or
|
||||||
|
for any such Derivative Works as a whole, provided Your use,
|
||||||
|
reproduction, and distribution of the Work otherwise complies with
|
||||||
|
the conditions stated in this License.
|
||||||
|
|
||||||
|
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||||
|
any Contribution intentionally submitted for inclusion in the Work
|
||||||
|
by You to the Licensor shall be under the terms and conditions of
|
||||||
|
this License, without any additional terms or conditions.
|
||||||
|
Notwithstanding the above, nothing herein shall supersede or modify
|
||||||
|
the terms of any separate license agreement you may have executed
|
||||||
|
with Licensor regarding such Contributions.
|
||||||
|
|
||||||
|
6. Trademarks. This License does not grant permission to use the trade
|
||||||
|
names, trademarks, service marks, or product names of the Licensor,
|
||||||
|
except as required for reasonable and customary use in describing the
|
||||||
|
origin of the Work and reproducing the content of the NOTICE file.
|
||||||
|
|
||||||
|
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||||
|
agreed to in writing, Licensor provides the Work (and each
|
||||||
|
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||||
|
implied, including, without limitation, any warranties or conditions
|
||||||
|
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||||
|
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||||
|
appropriateness of using or redistributing the Work and assume any
|
||||||
|
risks associated with Your exercise of permissions under this License.
|
||||||
|
|
||||||
|
8. Limitation of Liability. In no event and under no legal theory,
|
||||||
|
whether in tort (including negligence), contract, or otherwise,
|
||||||
|
unless required by applicable law (such as deliberate and grossly
|
||||||
|
negligent acts) or agreed to in writing, shall any Contributor be
|
||||||
|
liable to You for damages, including any direct, indirect, special,
|
||||||
|
incidental, or consequential damages of any character arising as a
|
||||||
|
result of this License or out of the use or inability to use the
|
||||||
|
Work (including but not limited to damages for loss of goodwill,
|
||||||
|
work stoppage, computer failure or malfunction, or any and all
|
||||||
|
other commercial damages or losses), even if such Contributor
|
||||||
|
has been advised of the possibility of such damages.
|
||||||
|
|
||||||
|
9. Accepting Warranty or Additional Liability. While redistributing
|
||||||
|
the Work or Derivative Works thereof, You may choose to offer,
|
||||||
|
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||||
|
or other liability obligations and/or rights consistent with this
|
||||||
|
License. However, in accepting such obligations, You may act only
|
||||||
|
on Your own behalf and on Your sole responsibility, not on behalf
|
||||||
|
of any other Contributor, and only if You agree to indemnify,
|
||||||
|
defend, and hold each Contributor harmless for any liability
|
||||||
|
incurred by, or claims asserted against, such Contributor by reason
|
||||||
|
of your accepting any such warranty or additional liability.
|
||||||
|
|
||||||
|
END OF TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
APPENDIX: How to apply the Apache License to your work.
|
||||||
|
|
||||||
|
To apply the Apache License to your work, attach the following
|
||||||
|
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||||
|
replaced with your own identifying information. (Don't include
|
||||||
|
the brackets!) The text should be enclosed in the appropriate
|
||||||
|
comment syntax for the file format. We also recommend that a
|
||||||
|
file or class name and description of purpose be included on the
|
||||||
|
same "printed page" as the copyright notice for easier
|
||||||
|
identification within third-party archives.
|
||||||
|
|
||||||
|
Copyright (c) 2019 <a href="http://www.jeecg.com">Jeecg Boot</a> All rights reserved.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
|
||||||
|
In any case, you must not make any such use of this software as to develop software which may be considered competitive with this software.
|
||||||
|
|
||||||
|
JeecgBoot 是由 北京国炬信息技术有限公司 发行的软件。 总部位于北京,地址:中国·北京·朝阳区科荟前街1号院奥林佳泰大厦。邮箱:jeecgos@163.com
|
||||||
|
本软件受适用的国家软件著作权法(包括国际条约)和开源协议 双重保护许可。
|
||||||
|
|
||||||
|
开源协议中文释意如下:
|
||||||
|
1.JeecgBoot开源版本无任何限制,在遵循本开源协议条款下,允许商用使用,不会造成侵权行为。
|
||||||
|
2.允许基于本平台软件开展业务系统开发。
|
||||||
|
3.在任何情况下,您不得使用本软件开发可能被认为与本软件竞争的软件。
|
||||||
|
|
||||||
|
最终解释权归:http://www.jeecg.com
|
||||||
|
|
@ -0,0 +1,44 @@
|
||||||
|
# ghb-base 后端(jeecg-boot)
|
||||||
|
|
||||||
|
> 这是 **ghb-base 基础框架**的后端。以后每个新系统都基于本框架开发——业务代码只写在 `ghb-module-business`,框架层(core/system)不改。
|
||||||
|
> 基于 JeecgBoot 3.9.2 精简。
|
||||||
|
|
||||||
|
## 技术栈
|
||||||
|
- Spring Boot 3.5.5 / Java **17**
|
||||||
|
- MyBatis-Plus / Shiro + JWT / MySQL 8 / Redis 6
|
||||||
|
- 包名 `com.ghb.base` | 数据库 `ghb_base` | 上下文路径 `/ghb`
|
||||||
|
|
||||||
|
## 环境要求
|
||||||
|
- JDK 17+、Maven 3.8+、MySQL 8.0+、Redis 6.0+
|
||||||
|
|
||||||
|
## 第一次启动
|
||||||
|
1. 建库 `ghb_base`,导入初始化脚本:`../ghb_base_init.sql`(在 base 根目录)
|
||||||
|
2. 改连接:`ghb-module-system/ghb-system-start/src/main/resources/application-dev.yml`(MySQL、Redis 地址)
|
||||||
|
3. 启动:
|
||||||
|
```bash
|
||||||
|
cd ghb-module-system/ghb-system-start
|
||||||
|
mvn spring-boot:run -Pdev
|
||||||
|
```
|
||||||
|
主类 `com.ghb.base.GhbSystemApplication`,端口 **8080**,访问前缀 `/ghb`(如 `http://localhost:8080/ghb`)。
|
||||||
|
|
||||||
|
## 模块结构(哪能改哪不能改)
|
||||||
|
```
|
||||||
|
jeecg-boot/
|
||||||
|
├── ghb-base-core/ 核心框架 ← 不改
|
||||||
|
├── ghb-module-system/ 租户/用户/角色/菜单/字典/日志 ← 不改
|
||||||
|
│ └── ghb-system-start/ 启动模块(含 application*.yml)
|
||||||
|
├── ghb-module-business/ 业务代码 ← 写这里
|
||||||
|
└── ghb-server-cloud/ 微服务(网关/Nacos/监控)
|
||||||
|
```
|
||||||
|
|
||||||
|
## 新人必读(开始写代码前全部读完)
|
||||||
|
1. **`CLAUDE.md`**(本目录)/ base 根 `../CLAUDE.md` — AI 开发总纲
|
||||||
|
2. **`../.claude/`** 下全部规则:`contract.md`(契约/返回格式/同步铁律)、`backend.md`(分层/命名/CRUD 模板/检查表)、`database.md`、`git.md`、`security.md`、`testing.md`
|
||||||
|
3. **`../contract/`** — 接口契约(独立 git submodule)。**改接口前必须先更新契约。**
|
||||||
|
|
||||||
|
## 铁律速记(详见 .claude/)
|
||||||
|
- 返回一律 `Result` 包装,禁止裸 `return data;`
|
||||||
|
- Controller 只做参数校验 + 调 Service + 返回,方法体别超 20 行、别写 if/else 业务
|
||||||
|
- 手写 `@Select` SQL 必须带 `tenant_id` 条件(多租户,否则数据泄露)
|
||||||
|
- 新增表必须有 `create_time`/`update_time`/`del_flag`/`COMMENT`,金额字段用 `DECIMAL`
|
||||||
|
- commit 要带 `[AI: xxx]` 标注;改 entity/controller 后重新打包重启
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
FROM mysql:8.0
|
||||||
|
|
||||||
|
ENV TZ=Asia/Shanghai
|
||||||
|
|
||||||
|
RUN ln -sf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
|
||||||
|
|
||||||
|
COPY ./tables_nacos.sql /docker-entrypoint-initdb.d
|
||||||
|
|
||||||
|
COPY ./ghb_base_init.sql /docker-entrypoint-initdb.d
|
||||||
|
|
||||||
|
COPY ./tables_xxl_job.sql /docker-entrypoint-initdb.d
|
||||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
|
@ -0,0 +1,360 @@
|
||||||
|
#
|
||||||
|
# XXL-JOB v2.4.0
|
||||||
|
# Copyright (c) 2015-present, xuxueli.
|
||||||
|
|
||||||
|
CREATE database if NOT EXISTS `xxl_job` default character set utf8mb4 collate utf8mb4_general_ci;
|
||||||
|
use `xxl_job`;
|
||||||
|
|
||||||
|
/*
|
||||||
|
Navicat Premium Data Transfer
|
||||||
|
|
||||||
|
Source Server : mysql5.7
|
||||||
|
Source Server Type : MySQL
|
||||||
|
Source Server Version : 50738 (5.7.38)
|
||||||
|
Source Host : 127.0.0.1:3306
|
||||||
|
Source Schema : xxl_job
|
||||||
|
|
||||||
|
Target Server Type : MySQL
|
||||||
|
Target Server Version : 50738 (5.7.38)
|
||||||
|
File Encoding : 65001
|
||||||
|
|
||||||
|
Date: 10/02/2025 13:49:31
|
||||||
|
*/
|
||||||
|
|
||||||
|
SET NAMES utf8mb4;
|
||||||
|
SET FOREIGN_KEY_CHECKS = 0;
|
||||||
|
|
||||||
|
-- ----------------------------
|
||||||
|
-- Table structure for xxl_job_group
|
||||||
|
-- ----------------------------
|
||||||
|
DROP TABLE IF EXISTS `xxl_job_group`;
|
||||||
|
CREATE TABLE `xxl_job_group` (
|
||||||
|
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||||
|
`app_name` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '执行器AppName',
|
||||||
|
`title` varchar(12) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '执行器名称',
|
||||||
|
`address_type` tinyint(4) NOT NULL DEFAULT 0 COMMENT '执行器地址类型:0=自动注册、1=手动录入',
|
||||||
|
`address_list` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT '执行器地址列表,多地址逗号分隔',
|
||||||
|
`update_time` datetime NULL DEFAULT NULL,
|
||||||
|
PRIMARY KEY (`id`) USING BTREE
|
||||||
|
) ENGINE = InnoDB AUTO_INCREMENT = 4 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic;
|
||||||
|
|
||||||
|
-- ----------------------------
|
||||||
|
-- Records of xxl_job_group
|
||||||
|
-- ----------------------------
|
||||||
|
INSERT INTO `xxl_job_group` VALUES (1, 'xxl-job-executor-sample', '示例执行器', 0, NULL, '2025-02-10 13:49:04');
|
||||||
|
INSERT INTO `xxl_job_group` VALUES (2, 'jeecg-demo', '测试Demo模块', 0, NULL, '2025-02-10 13:49:04');
|
||||||
|
INSERT INTO `xxl_job_group` VALUES (3, 'jeecg-system', '系统System模块', 0, NULL, '2025-02-10 13:49:04');
|
||||||
|
|
||||||
|
-- ----------------------------
|
||||||
|
-- Table structure for xxl_job_info
|
||||||
|
-- ----------------------------
|
||||||
|
DROP TABLE IF EXISTS `xxl_job_info`;
|
||||||
|
CREATE TABLE `xxl_job_info` (
|
||||||
|
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||||
|
`job_group` int(11) NOT NULL COMMENT '执行器主键ID',
|
||||||
|
`job_desc` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
|
||||||
|
`add_time` datetime NULL DEFAULT NULL,
|
||||||
|
`update_time` datetime NULL DEFAULT NULL,
|
||||||
|
`author` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '作者',
|
||||||
|
`alarm_email` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '报警邮件',
|
||||||
|
`schedule_type` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT 'NONE' COMMENT '调度类型',
|
||||||
|
`schedule_conf` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '调度配置,值含义取决于调度类型',
|
||||||
|
`misfire_strategy` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT 'DO_NOTHING' COMMENT '调度过期策略',
|
||||||
|
`executor_route_strategy` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '执行器路由策略',
|
||||||
|
`executor_handler` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '执行器任务handler',
|
||||||
|
`executor_param` varchar(512) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '执行器任务参数',
|
||||||
|
`executor_block_strategy` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '阻塞处理策略',
|
||||||
|
`executor_timeout` int(11) NOT NULL DEFAULT 0 COMMENT '任务执行超时时间,单位秒',
|
||||||
|
`executor_fail_retry_count` int(11) NOT NULL DEFAULT 0 COMMENT '失败重试次数',
|
||||||
|
`glue_type` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT 'GLUE类型',
|
||||||
|
`glue_source` mediumtext CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT 'GLUE源代码',
|
||||||
|
`glue_remark` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT 'GLUE备注',
|
||||||
|
`glue_updatetime` datetime NULL DEFAULT NULL COMMENT 'GLUE更新时间',
|
||||||
|
`child_jobid` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '子任务ID,多个逗号分隔',
|
||||||
|
`trigger_status` tinyint(4) NOT NULL DEFAULT 0 COMMENT '调度状态:0-停止,1-运行',
|
||||||
|
`trigger_last_time` bigint(13) NOT NULL DEFAULT 0 COMMENT '上次调度时间',
|
||||||
|
`trigger_next_time` bigint(13) NOT NULL DEFAULT 0 COMMENT '下次调度时间',
|
||||||
|
PRIMARY KEY (`id`) USING BTREE
|
||||||
|
) ENGINE = InnoDB AUTO_INCREMENT = 3 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic;
|
||||||
|
|
||||||
|
-- ----------------------------
|
||||||
|
-- Records of xxl_job_info
|
||||||
|
-- ----------------------------
|
||||||
|
INSERT INTO `xxl_job_info` VALUES (1, 1, '测试任务1', '2018-11-03 22:21:31', '2024-08-21 22:30:30', 'XXL', '', 'CRON', '0 0 0 * * ? *', 'DO_NOTHING', 'FIRST', 'demoJob', '', 'SERIAL_EXECUTION', 0, 0, 'BEAN', '', 'GLUE代码初始化', '2018-11-03 22:21:31', '', 1, 1729353600000, 1739203200000);
|
||||||
|
INSERT INTO `xxl_job_info` VALUES (2, 3, '测试jeecg xxljob', '2024-08-21 22:41:10', '2024-08-21 22:41:30', 'JEECG', '', 'CRON', '* * * * * ?', 'DO_NOTHING', 'FIRST', 'demoJob', '', 'SERIAL_EXECUTION', 0, 0, 'BEAN', '', 'GLUE代码初始化', '2024-08-21 22:41:10', '', 1, 1739166572000, 1739166573000);
|
||||||
|
|
||||||
|
-- ----------------------------
|
||||||
|
-- Table structure for xxl_job_lock
|
||||||
|
-- ----------------------------
|
||||||
|
DROP TABLE IF EXISTS `xxl_job_lock`;
|
||||||
|
CREATE TABLE `xxl_job_lock` (
|
||||||
|
`lock_name` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '锁名称',
|
||||||
|
PRIMARY KEY (`lock_name`) USING BTREE
|
||||||
|
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic;
|
||||||
|
|
||||||
|
-- ----------------------------
|
||||||
|
-- Records of xxl_job_lock
|
||||||
|
-- ----------------------------
|
||||||
|
INSERT INTO `xxl_job_lock` VALUES ('schedule_lock');
|
||||||
|
|
||||||
|
-- ----------------------------
|
||||||
|
-- Table structure for xxl_job_log
|
||||||
|
-- ----------------------------
|
||||||
|
DROP TABLE IF EXISTS `xxl_job_log`;
|
||||||
|
CREATE TABLE `xxl_job_log` (
|
||||||
|
`id` bigint(20) NOT NULL AUTO_INCREMENT,
|
||||||
|
`job_group` int(11) NOT NULL COMMENT '执行器主键ID',
|
||||||
|
`job_id` int(11) NOT NULL COMMENT '任务,主键ID',
|
||||||
|
`executor_address` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '执行器地址,本次执行的地址',
|
||||||
|
`executor_handler` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '执行器任务handler',
|
||||||
|
`executor_param` varchar(512) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '执行器任务参数',
|
||||||
|
`executor_sharding_param` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '执行器任务分片参数,格式如 1/2',
|
||||||
|
`executor_fail_retry_count` int(11) NOT NULL DEFAULT 0 COMMENT '失败重试次数',
|
||||||
|
`trigger_time` datetime NULL DEFAULT NULL COMMENT '调度-时间',
|
||||||
|
`trigger_code` int(11) NOT NULL COMMENT '调度-结果',
|
||||||
|
`trigger_msg` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT '调度-日志',
|
||||||
|
`handle_time` datetime NULL DEFAULT NULL COMMENT '执行-时间',
|
||||||
|
`handle_code` int(11) NOT NULL COMMENT '执行-状态',
|
||||||
|
`handle_msg` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT '执行-日志',
|
||||||
|
`alarm_status` tinyint(4) NOT NULL DEFAULT 0 COMMENT '告警状态:0-默认、1-无需告警、2-告警成功、3-告警失败',
|
||||||
|
PRIMARY KEY (`id`) USING BTREE,
|
||||||
|
INDEX `I_trigger_time`(`trigger_time`) USING BTREE,
|
||||||
|
INDEX `I_handle_code`(`handle_code`) USING BTREE
|
||||||
|
) ENGINE = InnoDB AUTO_INCREMENT = 6761 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic;
|
||||||
|
|
||||||
|
-- ----------------------------
|
||||||
|
-- Records of xxl_job_log
|
||||||
|
-- ----------------------------
|
||||||
|
INSERT INTO `xxl_job_log` VALUES (6618, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:47:09', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
|
||||||
|
INSERT INTO `xxl_job_log` VALUES (6619, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:47:10', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
|
||||||
|
INSERT INTO `xxl_job_log` VALUES (6620, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:47:11', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
|
||||||
|
INSERT INTO `xxl_job_log` VALUES (6621, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:47:12', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
|
||||||
|
INSERT INTO `xxl_job_log` VALUES (6622, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:47:13', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
|
||||||
|
INSERT INTO `xxl_job_log` VALUES (6623, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:47:14', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
|
||||||
|
INSERT INTO `xxl_job_log` VALUES (6624, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:47:15', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
|
||||||
|
INSERT INTO `xxl_job_log` VALUES (6625, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:47:16', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
|
||||||
|
INSERT INTO `xxl_job_log` VALUES (6626, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:47:17', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
|
||||||
|
INSERT INTO `xxl_job_log` VALUES (6627, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:47:18', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
|
||||||
|
INSERT INTO `xxl_job_log` VALUES (6628, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:47:19', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
|
||||||
|
INSERT INTO `xxl_job_log` VALUES (6629, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:47:20', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
|
||||||
|
INSERT INTO `xxl_job_log` VALUES (6630, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:47:21', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
|
||||||
|
INSERT INTO `xxl_job_log` VALUES (6631, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:47:22', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
|
||||||
|
INSERT INTO `xxl_job_log` VALUES (6632, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:47:23', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
|
||||||
|
INSERT INTO `xxl_job_log` VALUES (6633, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:47:24', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
|
||||||
|
INSERT INTO `xxl_job_log` VALUES (6634, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:47:25', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
|
||||||
|
INSERT INTO `xxl_job_log` VALUES (6635, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:47:26', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
|
||||||
|
INSERT INTO `xxl_job_log` VALUES (6636, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:47:27', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
|
||||||
|
INSERT INTO `xxl_job_log` VALUES (6637, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:47:28', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
|
||||||
|
INSERT INTO `xxl_job_log` VALUES (6638, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:47:29', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
|
||||||
|
INSERT INTO `xxl_job_log` VALUES (6639, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:47:30', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
|
||||||
|
INSERT INTO `xxl_job_log` VALUES (6640, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:47:31', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
|
||||||
|
INSERT INTO `xxl_job_log` VALUES (6641, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:47:32', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
|
||||||
|
INSERT INTO `xxl_job_log` VALUES (6642, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:47:33', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
|
||||||
|
INSERT INTO `xxl_job_log` VALUES (6643, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:47:34', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
|
||||||
|
INSERT INTO `xxl_job_log` VALUES (6644, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:47:35', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
|
||||||
|
INSERT INTO `xxl_job_log` VALUES (6645, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:47:36', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
|
||||||
|
INSERT INTO `xxl_job_log` VALUES (6646, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:47:37', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
|
||||||
|
INSERT INTO `xxl_job_log` VALUES (6647, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:47:38', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
|
||||||
|
INSERT INTO `xxl_job_log` VALUES (6648, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:47:39', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
|
||||||
|
INSERT INTO `xxl_job_log` VALUES (6649, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:47:40', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
|
||||||
|
INSERT INTO `xxl_job_log` VALUES (6650, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:47:41', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
|
||||||
|
INSERT INTO `xxl_job_log` VALUES (6651, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:47:42', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
|
||||||
|
INSERT INTO `xxl_job_log` VALUES (6652, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:47:43', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
|
||||||
|
INSERT INTO `xxl_job_log` VALUES (6653, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:47:44', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
|
||||||
|
INSERT INTO `xxl_job_log` VALUES (6654, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:47:45', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
|
||||||
|
INSERT INTO `xxl_job_log` VALUES (6655, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:47:46', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
|
||||||
|
INSERT INTO `xxl_job_log` VALUES (6656, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:47:47', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
|
||||||
|
INSERT INTO `xxl_job_log` VALUES (6657, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:47:48', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
|
||||||
|
INSERT INTO `xxl_job_log` VALUES (6658, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:47:49', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
|
||||||
|
INSERT INTO `xxl_job_log` VALUES (6659, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:47:50', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
|
||||||
|
INSERT INTO `xxl_job_log` VALUES (6660, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:47:51', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
|
||||||
|
INSERT INTO `xxl_job_log` VALUES (6661, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:47:52', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
|
||||||
|
INSERT INTO `xxl_job_log` VALUES (6662, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:47:53', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
|
||||||
|
INSERT INTO `xxl_job_log` VALUES (6663, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:47:54', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
|
||||||
|
INSERT INTO `xxl_job_log` VALUES (6664, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:47:55', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
|
||||||
|
INSERT INTO `xxl_job_log` VALUES (6665, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:47:56', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
|
||||||
|
INSERT INTO `xxl_job_log` VALUES (6666, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:47:57', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
|
||||||
|
INSERT INTO `xxl_job_log` VALUES (6667, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:47:58', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
|
||||||
|
INSERT INTO `xxl_job_log` VALUES (6668, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:47:59', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
|
||||||
|
INSERT INTO `xxl_job_log` VALUES (6669, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:48:00', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
|
||||||
|
INSERT INTO `xxl_job_log` VALUES (6670, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:48:01', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
|
||||||
|
INSERT INTO `xxl_job_log` VALUES (6671, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:48:02', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
|
||||||
|
INSERT INTO `xxl_job_log` VALUES (6672, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:48:03', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
|
||||||
|
INSERT INTO `xxl_job_log` VALUES (6673, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:48:04', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
|
||||||
|
INSERT INTO `xxl_job_log` VALUES (6674, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:48:05', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
|
||||||
|
INSERT INTO `xxl_job_log` VALUES (6675, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:48:06', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
|
||||||
|
INSERT INTO `xxl_job_log` VALUES (6676, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:48:07', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
|
||||||
|
INSERT INTO `xxl_job_log` VALUES (6677, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:48:08', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
|
||||||
|
INSERT INTO `xxl_job_log` VALUES (6678, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:48:09', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
|
||||||
|
INSERT INTO `xxl_job_log` VALUES (6679, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:48:10', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
|
||||||
|
INSERT INTO `xxl_job_log` VALUES (6680, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:48:11', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
|
||||||
|
INSERT INTO `xxl_job_log` VALUES (6681, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:48:12', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
|
||||||
|
INSERT INTO `xxl_job_log` VALUES (6682, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:48:13', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
|
||||||
|
INSERT INTO `xxl_job_log` VALUES (6683, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:48:14', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
|
||||||
|
INSERT INTO `xxl_job_log` VALUES (6684, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:48:15', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
|
||||||
|
INSERT INTO `xxl_job_log` VALUES (6685, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:48:16', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
|
||||||
|
INSERT INTO `xxl_job_log` VALUES (6686, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:48:17', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
|
||||||
|
INSERT INTO `xxl_job_log` VALUES (6687, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:48:18', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
|
||||||
|
INSERT INTO `xxl_job_log` VALUES (6688, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:48:19', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
|
||||||
|
INSERT INTO `xxl_job_log` VALUES (6689, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:48:20', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
|
||||||
|
INSERT INTO `xxl_job_log` VALUES (6690, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:48:21', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
|
||||||
|
INSERT INTO `xxl_job_log` VALUES (6691, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:48:22', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
|
||||||
|
INSERT INTO `xxl_job_log` VALUES (6692, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:48:23', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
|
||||||
|
INSERT INTO `xxl_job_log` VALUES (6693, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:48:24', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
|
||||||
|
INSERT INTO `xxl_job_log` VALUES (6694, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:48:25', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
|
||||||
|
INSERT INTO `xxl_job_log` VALUES (6695, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:48:26', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
|
||||||
|
INSERT INTO `xxl_job_log` VALUES (6696, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:48:27', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
|
||||||
|
INSERT INTO `xxl_job_log` VALUES (6697, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:48:28', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
|
||||||
|
INSERT INTO `xxl_job_log` VALUES (6698, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:48:29', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
|
||||||
|
INSERT INTO `xxl_job_log` VALUES (6699, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:48:30', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
|
||||||
|
INSERT INTO `xxl_job_log` VALUES (6700, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:48:31', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
|
||||||
|
INSERT INTO `xxl_job_log` VALUES (6701, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:48:32', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
|
||||||
|
INSERT INTO `xxl_job_log` VALUES (6702, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:48:33', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
|
||||||
|
INSERT INTO `xxl_job_log` VALUES (6703, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:48:34', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
|
||||||
|
INSERT INTO `xxl_job_log` VALUES (6704, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:48:35', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
|
||||||
|
INSERT INTO `xxl_job_log` VALUES (6705, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:48:36', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
|
||||||
|
INSERT INTO `xxl_job_log` VALUES (6706, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:48:37', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
|
||||||
|
INSERT INTO `xxl_job_log` VALUES (6707, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:48:38', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
|
||||||
|
INSERT INTO `xxl_job_log` VALUES (6708, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:48:39', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
|
||||||
|
INSERT INTO `xxl_job_log` VALUES (6709, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:48:40', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
|
||||||
|
INSERT INTO `xxl_job_log` VALUES (6710, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:48:41', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
|
||||||
|
INSERT INTO `xxl_job_log` VALUES (6711, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:48:42', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
|
||||||
|
INSERT INTO `xxl_job_log` VALUES (6712, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:48:43', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
|
||||||
|
INSERT INTO `xxl_job_log` VALUES (6713, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:48:44', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
|
||||||
|
INSERT INTO `xxl_job_log` VALUES (6714, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:48:45', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
|
||||||
|
INSERT INTO `xxl_job_log` VALUES (6715, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:48:46', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
|
||||||
|
INSERT INTO `xxl_job_log` VALUES (6716, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:48:47', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
|
||||||
|
INSERT INTO `xxl_job_log` VALUES (6717, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:48:48', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
|
||||||
|
INSERT INTO `xxl_job_log` VALUES (6718, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:48:49', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
|
||||||
|
INSERT INTO `xxl_job_log` VALUES (6719, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:48:50', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
|
||||||
|
INSERT INTO `xxl_job_log` VALUES (6720, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:48:51', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
|
||||||
|
INSERT INTO `xxl_job_log` VALUES (6721, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:48:52', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
|
||||||
|
INSERT INTO `xxl_job_log` VALUES (6722, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:48:53', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
|
||||||
|
INSERT INTO `xxl_job_log` VALUES (6723, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:48:54', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
|
||||||
|
INSERT INTO `xxl_job_log` VALUES (6724, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:48:55', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
|
||||||
|
INSERT INTO `xxl_job_log` VALUES (6725, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:48:56', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
|
||||||
|
INSERT INTO `xxl_job_log` VALUES (6726, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:48:57', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
|
||||||
|
INSERT INTO `xxl_job_log` VALUES (6727, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:48:58', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
|
||||||
|
INSERT INTO `xxl_job_log` VALUES (6728, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:48:59', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
|
||||||
|
INSERT INTO `xxl_job_log` VALUES (6729, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:49:00', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
|
||||||
|
INSERT INTO `xxl_job_log` VALUES (6730, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:49:01', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
|
||||||
|
INSERT INTO `xxl_job_log` VALUES (6731, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:49:02', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
|
||||||
|
INSERT INTO `xxl_job_log` VALUES (6732, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:49:03', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
|
||||||
|
INSERT INTO `xxl_job_log` VALUES (6733, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:49:04', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
|
||||||
|
INSERT INTO `xxl_job_log` VALUES (6734, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:49:05', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
|
||||||
|
INSERT INTO `xxl_job_log` VALUES (6735, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:49:06', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
|
||||||
|
INSERT INTO `xxl_job_log` VALUES (6736, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:49:07', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
|
||||||
|
INSERT INTO `xxl_job_log` VALUES (6737, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:49:08', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
|
||||||
|
INSERT INTO `xxl_job_log` VALUES (6738, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:49:09', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
|
||||||
|
INSERT INTO `xxl_job_log` VALUES (6739, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:49:10', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
|
||||||
|
INSERT INTO `xxl_job_log` VALUES (6740, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:49:11', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
|
||||||
|
INSERT INTO `xxl_job_log` VALUES (6741, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:49:12', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
|
||||||
|
INSERT INTO `xxl_job_log` VALUES (6742, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:49:13', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
|
||||||
|
INSERT INTO `xxl_job_log` VALUES (6743, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:49:14', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
|
||||||
|
INSERT INTO `xxl_job_log` VALUES (6744, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:49:15', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
|
||||||
|
INSERT INTO `xxl_job_log` VALUES (6745, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:49:16', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
|
||||||
|
INSERT INTO `xxl_job_log` VALUES (6746, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:49:17', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
|
||||||
|
INSERT INTO `xxl_job_log` VALUES (6747, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:49:18', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
|
||||||
|
INSERT INTO `xxl_job_log` VALUES (6748, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:49:19', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
|
||||||
|
INSERT INTO `xxl_job_log` VALUES (6749, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:49:20', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
|
||||||
|
INSERT INTO `xxl_job_log` VALUES (6750, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:49:21', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
|
||||||
|
INSERT INTO `xxl_job_log` VALUES (6751, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:49:22', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
|
||||||
|
INSERT INTO `xxl_job_log` VALUES (6752, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:49:23', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
|
||||||
|
INSERT INTO `xxl_job_log` VALUES (6753, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:49:24', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
|
||||||
|
INSERT INTO `xxl_job_log` VALUES (6754, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:49:25', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 0);
|
||||||
|
INSERT INTO `xxl_job_log` VALUES (6755, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:49:26', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 0);
|
||||||
|
INSERT INTO `xxl_job_log` VALUES (6756, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:49:27', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 0);
|
||||||
|
INSERT INTO `xxl_job_log` VALUES (6757, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:49:28', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 0);
|
||||||
|
INSERT INTO `xxl_job_log` VALUES (6758, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:49:29', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 0);
|
||||||
|
INSERT INTO `xxl_job_log` VALUES (6759, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:49:30', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 0);
|
||||||
|
INSERT INTO `xxl_job_log` VALUES (6760, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:49:31', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 0);
|
||||||
|
|
||||||
|
-- ----------------------------
|
||||||
|
-- Table structure for xxl_job_log_report
|
||||||
|
-- ----------------------------
|
||||||
|
DROP TABLE IF EXISTS `xxl_job_log_report`;
|
||||||
|
CREATE TABLE `xxl_job_log_report` (
|
||||||
|
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||||
|
`trigger_day` datetime NULL DEFAULT NULL COMMENT '调度-时间',
|
||||||
|
`running_count` int(11) NOT NULL DEFAULT 0 COMMENT '运行中-日志数量',
|
||||||
|
`suc_count` int(11) NOT NULL DEFAULT 0 COMMENT '执行成功-日志数量',
|
||||||
|
`fail_count` int(11) NOT NULL DEFAULT 0 COMMENT '执行失败-日志数量',
|
||||||
|
`update_time` datetime NULL DEFAULT NULL,
|
||||||
|
PRIMARY KEY (`id`) USING BTREE,
|
||||||
|
UNIQUE INDEX `i_trigger_day`(`trigger_day`) USING BTREE
|
||||||
|
) ENGINE = InnoDB AUTO_INCREMENT = 13 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic;
|
||||||
|
|
||||||
|
-- ----------------------------
|
||||||
|
-- Records of xxl_job_log_report
|
||||||
|
-- ----------------------------
|
||||||
|
INSERT INTO `xxl_job_log_report` VALUES (1, '2024-08-21 00:00:00', 70, 0, 5, NULL);
|
||||||
|
INSERT INTO `xxl_job_log_report` VALUES (2, '2024-08-20 00:00:00', 0, 0, 0, NULL);
|
||||||
|
INSERT INTO `xxl_job_log_report` VALUES (3, '2024-08-19 00:00:00', 0, 0, 0, NULL);
|
||||||
|
INSERT INTO `xxl_job_log_report` VALUES (4, '2024-09-10 00:00:00', 0, 0, 56, NULL);
|
||||||
|
INSERT INTO `xxl_job_log_report` VALUES (5, '2024-09-09 00:00:00', 0, 0, 0, NULL);
|
||||||
|
INSERT INTO `xxl_job_log_report` VALUES (6, '2024-09-08 00:00:00', 0, 0, 0, NULL);
|
||||||
|
INSERT INTO `xxl_job_log_report` VALUES (7, '2024-10-19 00:00:00', 0, 0, 6391, NULL);
|
||||||
|
INSERT INTO `xxl_job_log_report` VALUES (8, '2024-10-18 00:00:00', 0, 0, 0, NULL);
|
||||||
|
INSERT INTO `xxl_job_log_report` VALUES (9, '2024-10-17 00:00:00', 0, 0, 0, NULL);
|
||||||
|
INSERT INTO `xxl_job_log_report` VALUES (10, '2025-02-10 00:00:00', 0, 0, 116, NULL);
|
||||||
|
INSERT INTO `xxl_job_log_report` VALUES (11, '2025-02-09 00:00:00', 0, 0, 0, NULL);
|
||||||
|
INSERT INTO `xxl_job_log_report` VALUES (12, '2025-02-08 00:00:00', 0, 0, 0, NULL);
|
||||||
|
|
||||||
|
-- ----------------------------
|
||||||
|
-- Table structure for xxl_job_logglue
|
||||||
|
-- ----------------------------
|
||||||
|
DROP TABLE IF EXISTS `xxl_job_logglue`;
|
||||||
|
CREATE TABLE `xxl_job_logglue` (
|
||||||
|
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||||
|
`job_id` int(11) NOT NULL COMMENT '任务,主键ID',
|
||||||
|
`glue_type` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT 'GLUE类型',
|
||||||
|
`glue_source` mediumtext CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT 'GLUE源代码',
|
||||||
|
`glue_remark` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT 'GLUE备注',
|
||||||
|
`add_time` datetime NULL DEFAULT NULL,
|
||||||
|
`update_time` datetime NULL DEFAULT NULL,
|
||||||
|
PRIMARY KEY (`id`) USING BTREE
|
||||||
|
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic;
|
||||||
|
|
||||||
|
-- ----------------------------
|
||||||
|
-- Records of xxl_job_logglue
|
||||||
|
-- ----------------------------
|
||||||
|
|
||||||
|
-- ----------------------------
|
||||||
|
-- Table structure for xxl_job_registry
|
||||||
|
-- ----------------------------
|
||||||
|
DROP TABLE IF EXISTS `xxl_job_registry`;
|
||||||
|
CREATE TABLE `xxl_job_registry` (
|
||||||
|
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||||
|
`registry_group` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
|
||||||
|
`registry_key` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
|
||||||
|
`registry_value` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
|
||||||
|
`update_time` datetime NULL DEFAULT NULL,
|
||||||
|
PRIMARY KEY (`id`) USING BTREE,
|
||||||
|
INDEX `i_g_k_v`(`registry_group`, `registry_key`, `registry_value`) USING BTREE
|
||||||
|
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic;
|
||||||
|
|
||||||
|
-- ----------------------------
|
||||||
|
-- Records of xxl_job_registry
|
||||||
|
-- ----------------------------
|
||||||
|
|
||||||
|
-- ----------------------------
|
||||||
|
-- Table structure for xxl_job_user
|
||||||
|
-- ----------------------------
|
||||||
|
DROP TABLE IF EXISTS `xxl_job_user`;
|
||||||
|
CREATE TABLE `xxl_job_user` (
|
||||||
|
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||||
|
`username` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '账号',
|
||||||
|
`password` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '密码',
|
||||||
|
`role` tinyint(4) NOT NULL COMMENT '角色:0-普通用户、1-管理员',
|
||||||
|
`permission` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '权限:执行器ID列表,多个逗号分割',
|
||||||
|
PRIMARY KEY (`id`) USING BTREE,
|
||||||
|
UNIQUE INDEX `i_username`(`username`) USING BTREE
|
||||||
|
) ENGINE = InnoDB AUTO_INCREMENT = 2 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic;
|
||||||
|
|
||||||
|
-- ----------------------------
|
||||||
|
-- Records of xxl_job_user
|
||||||
|
-- ----------------------------
|
||||||
|
INSERT INTO `xxl_job_user` VALUES (1, 'admin', 'e10adc3949ba59abbe56e057f20f883e', 1, NULL);
|
||||||
|
|
||||||
|
SET FOREIGN_KEY_CHECKS = 1;
|
||||||
|
|
||||||
File diff suppressed because one or more lines are too long
|
|
@ -0,0 +1,5 @@
|
||||||
|
oracle导出编码: export NLS_LANG=AMERICAN_AMERICA.ZHS16GBK
|
||||||
|
|
||||||
|
导出用户: jeecgbootos
|
||||||
|
|
||||||
|
导入命令: imp scott/tiger@orcl file=jeecgboot-oracle11g.dmp
|
||||||
|
|
@ -0,0 +1,39 @@
|
||||||
|
# JeecgBoot 数据库支持与转库说明
|
||||||
|
|
||||||
|
JeecgBoot 平台支持以下数据库,默认只提供 MySQL 脚本,其他数据库可参考 [Navicat 工具 mysql 转库 oracle 步骤](https://my.oschina.net/jeecg/blog/4905722)自行转换,其他数据库转换类似。
|
||||||
|
|
||||||
|
| 数据库 | 支持 |
|
||||||
|
|--------|------|
|
||||||
|
| MySQL | √ |
|
||||||
|
| Oracle 11g | √ |
|
||||||
|
| SQL Server 2017 | √ |
|
||||||
|
| PostgreSQL | √ |
|
||||||
|
| MariaDB | √ |
|
||||||
|
| 达梦(DM) | √ |
|
||||||
|
| 人大金仓(KingbaseES) | √ |
|
||||||
|
| TiDB | √ |
|
||||||
|
| Kingbase8 | √ |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 一、Navicat 工具 MySQL 迁移 Oracle
|
||||||
|
|
||||||
|
1. 使用 Navicat 工具连接源数据库 MySQL(用户名 jeecg-m)和目标数据库 Oracle(用户名 jeecg-o)
|
||||||
|
|
||||||
|
2. 使用 Navicat 的数据传输功能将 jeecg-m 拷贝到 jeecg-o
|
||||||
|
|
||||||
|
(1)选中源数据库,右键,点击"数据传输"
|
||||||
|
|
||||||
|
(2)在常规选项卡上选择源数据库,并勾选数据库对象;选择目标,连接,数据库名,模式
|
||||||
|
|
||||||
|
(3)在高级选项卡中,勾选**转换对象名为大写**,其他选项处勾选"遇到错误继续"
|
||||||
|
|
||||||
|
(4)表选项的**外键限制要勾掉**,由于在转换过程中每个表是单独写入数据,如果保持外键限制,会导致有外键的表写入失败。外键请在迁移后手动补充。
|
||||||
|
|
||||||
|
(5)点击开始按钮,在信息日志选项卡中会打出日志,完成后,记录下出错的表,出错的表需要后续使用其他工具迁移。
|
||||||
|
|
||||||
|
## 二、特殊表处理
|
||||||
|
|
||||||
|
定时任务的表 `qrtz_*`,通过 Navicat 转的表还是有问题,需要删除相关表,手工执行下原始初始化脚本。
|
||||||
|
|
||||||
|
quartz 初始化脚本下载:[quartz-2.2.3-distribution.tar.gz](http://pan.baidu.com/s/1WrmZdUuAPg3iBwJ-LoHWyg?pwd=8mdz)(百度网盘),找到自己需要的数据库类型脚本即可。
|
||||||
|
|
@ -0,0 +1,23 @@
|
||||||
|
# 版本升级方法
|
||||||
|
|
||||||
|
> JeecgBoot属于平台级产品,每次升级改动较大,目前做不到平滑升级。
|
||||||
|
|
||||||
|
### 增量升级方案
|
||||||
|
|
||||||
|
#### 1.代码合并
|
||||||
|
本地通过svn或git做好主干,在分支上做业务开发,jeecg每次版本发布,可以手工覆盖主干的代码,对比合并代码;
|
||||||
|
|
||||||
|
#### 2.数据库升级
|
||||||
|
- 从3.6.2+版本增加flyway自动升级数据库机制,支持 mysql5.7、mysql8;
|
||||||
|
- 其他库请手工执行SQL, 目录: `jeecg-module-system\jeecg-system-start\src\main\resources\flyway\sql\mysql`
|
||||||
|
> 注意: 升级sql只提供mysql版本;如果有权限升级, 还需要手工角色授权,退出重新登录才好使。
|
||||||
|
|
||||||
|
#### 3.其他数据库脚本说明
|
||||||
|
原先官方默认提供oracle和SqlServer的脚本,但是维护成本太高,未提供脚本的数据库,可以参考下面的文档自己转
|
||||||
|
https://my.oschina.net/jeecg/blog/4905722
|
||||||
|
(注意:定时任务的表qrtz_*,需要删掉用原始的脚本重新执行一下)
|
||||||
|
quartz-2.2.3-distribution.tar.gz放到百度网盘中,大家自己下载,执行所需数据库脚本
|
||||||
|
https://pan.baidu.com/s/1WrmZdUuAPg3iBwJ-LoHWyg?pwd=8mdz
|
||||||
|
|
||||||
|
#### 4.兼容问题
|
||||||
|
每次发版,会针对不兼容地方重点说明。
|
||||||
|
|
@ -0,0 +1,79 @@
|
||||||
|
# ============================================
|
||||||
|
# 部署配置模板 — 复制为 .env 后修改
|
||||||
|
# 快速开始: bash deploy.sh init(交互式生成)
|
||||||
|
# 手动配置: cp .env.example .env && vim .env
|
||||||
|
# ============================================
|
||||||
|
|
||||||
|
# 部署架构: 1=单体 3=SpringCloud
|
||||||
|
DEPLOY_MODE=1
|
||||||
|
COMPOSE_FILE=docker-compose.yml
|
||||||
|
|
||||||
|
# 应用
|
||||||
|
APP_NAME=test
|
||||||
|
APP_PORT=8008
|
||||||
|
JAVA_OPTS="-Xms512m -Xmx512m"
|
||||||
|
|
||||||
|
# 数据库
|
||||||
|
DB_NAME=test_base
|
||||||
|
|
||||||
|
# 网络
|
||||||
|
NETWORK_NAME=ghb-net
|
||||||
|
|
||||||
|
# ---- 中间件策略 ----
|
||||||
|
# docker = Docker 一起安装 | external = 连接外部服务 | none = 不使用(仅 MinIO)
|
||||||
|
MYSQL_MODE=docker
|
||||||
|
REDIS_MODE=docker
|
||||||
|
MINIO_MODE=none
|
||||||
|
|
||||||
|
# ---- MySQL(docker 模式) ----
|
||||||
|
MYSQL_PORT=3306
|
||||||
|
MYSQL_ROOT_PASSWORD=ChangeMe123
|
||||||
|
# ---- MySQL(external 模式) ----
|
||||||
|
# MYSQL_HOST=127.0.0.1
|
||||||
|
# MYSQL_USER=root
|
||||||
|
# MYSQL_PASS='ChangeMe123'
|
||||||
|
# MYSQL_URL='jdbc:mysql://127.0.0.1:3306/test_base?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true'
|
||||||
|
|
||||||
|
# ---- Redis(docker 模式) ----
|
||||||
|
REDIS_PORT=6379
|
||||||
|
REDIS_PASS=''
|
||||||
|
# ---- Redis(external 模式) ----
|
||||||
|
# REDIS_HOST=127.0.0.1
|
||||||
|
# REDIS_DB=0
|
||||||
|
|
||||||
|
# ---- MinIO(docker 模式) ----
|
||||||
|
# MINIO_HOST=minio
|
||||||
|
# MINIO_PORT=9000
|
||||||
|
# MINIO_CONSOLE_PORT=9001
|
||||||
|
# MINIO_ACCESS_KEY=minioadmin
|
||||||
|
# MINIO_SECRET_KEY=minioadmin
|
||||||
|
# MINIO_BUCKET=ghb-base
|
||||||
|
# MINIO_ENDPOINT=http://minio:9000
|
||||||
|
# ---- MinIO(external 模式) ----
|
||||||
|
# MINIO_HOST=127.0.0.1
|
||||||
|
# MINIO_PORT=9000
|
||||||
|
# MINIO_ACCESS_KEY=minioadmin
|
||||||
|
# MINIO_SECRET_KEY=minioadmin
|
||||||
|
# MINIO_BUCKET=ghb-base
|
||||||
|
# MINIO_ENDPOINT=http://127.0.0.1:9000
|
||||||
|
|
||||||
|
# ---- Spring Cloud(仅 DEPLOY_MODE=3) ----
|
||||||
|
# NACOS_PORT=8848
|
||||||
|
# GATEWAY_PORT=9999
|
||||||
|
# SYSTEM_PORT=7001
|
||||||
|
|
||||||
|
# 数据库初始化(仅 external MySQL,true 时启动前自动建表)
|
||||||
|
DB_INIT=false
|
||||||
|
|
||||||
|
# 跳过连通性检查(true 时不检查外接服务是否可达)
|
||||||
|
SKIP_CONNECTIVITY_CHECK=false
|
||||||
|
|
||||||
|
# 上传方式: local(本地) / minio(MinIO)
|
||||||
|
JEECG_UPLOAD_TYPE=local
|
||||||
|
|
||||||
|
# ---- 前端集成(可选) ----
|
||||||
|
FRONTEND_ENABLED=false
|
||||||
|
# FRONTEND_PORT=80
|
||||||
|
|
||||||
|
# JWT 密钥(自动生成或手动填写)
|
||||||
|
JWT_SECRET='your-jwt-secret-here'
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
.env
|
||||||
|
|
@ -0,0 +1,177 @@
|
||||||
|
# 后端 Docker 部署
|
||||||
|
|
||||||
|
## 部署架构
|
||||||
|
|
||||||
|
| 架构 | compose 文件 | 说明 |
|
||||||
|
|------|-------------|------|
|
||||||
|
| 单体 | `docker-compose.yml` | 一个 App 容器 |
|
||||||
|
| Spring Cloud | `docker-compose.cloud.yml` | Nacos + Gateway + System |
|
||||||
|
|
||||||
|
中间件(MySQL / Redis / MinIO)**独立选择**,不绑定架构:
|
||||||
|
|
||||||
|
| 中间件 | 选项 | 说明 |
|
||||||
|
|--------|------|------|
|
||||||
|
| MySQL | `docker` / `external` | Docker 安装 or 连接外部服务 |
|
||||||
|
| Redis | `docker` / `external` | Docker 安装 or 连接外部服务 |
|
||||||
|
| MinIO | `docker` / `external` / `none` | Docker 安装 / 外部 / 不使用 |
|
||||||
|
|
||||||
|
## 前置条件
|
||||||
|
|
||||||
|
- Docker + Docker Compose
|
||||||
|
- **外部 MySQL 场景**:需提前建好 `nacos` 和 `ghb_base` 两个库(见下文)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 快速开始
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd deploy
|
||||||
|
|
||||||
|
# 1. 交互式配置
|
||||||
|
bash deploy.sh init
|
||||||
|
|
||||||
|
# 2. 编译镜像(首次 10-20 分钟)
|
||||||
|
bash deploy.sh build
|
||||||
|
|
||||||
|
# 3. 启动
|
||||||
|
bash deploy.sh start
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 完整步骤(Spring Cloud + 外部 MySQL/Redis)
|
||||||
|
|
||||||
|
### 第一步:初始化数据库
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Nacos 内部存储库(必须)
|
||||||
|
mysql -h <MySQL地址> -u root -p < db/tables_nacos.sql
|
||||||
|
|
||||||
|
# 业务库
|
||||||
|
mysql -h <MySQL地址> -u root -p -e "CREATE DATABASE IF NOT EXISTS ghb_base DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;"
|
||||||
|
mysql -h <MySQL地址> -u root -p ghb_base < db/ghb_base_init.sql
|
||||||
|
```
|
||||||
|
|
||||||
|
### 第二步:交互式配置
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd deploy
|
||||||
|
bash deploy.sh init
|
||||||
|
```
|
||||||
|
|
||||||
|
按提示填写:
|
||||||
|
|
||||||
|
```
|
||||||
|
部署架构: 2. Spring Cloud
|
||||||
|
MySQL: 2. 连接外部服务 → 10.13.13.1:3306
|
||||||
|
Redis: 2. 连接外部服务 → 10.13.13.1:56379
|
||||||
|
MinIO: 3. 不使用
|
||||||
|
外接数据库是否已建表? Y
|
||||||
|
是否集成前端? Y(需先 pnpm build)
|
||||||
|
```
|
||||||
|
|
||||||
|
### 第三步:编译 + 启动
|
||||||
|
|
||||||
|
```bash
|
||||||
|
bash deploy.sh build && bash deploy.sh start
|
||||||
|
```
|
||||||
|
|
||||||
|
`start` 在 Spring Cloud 模式下自动执行:
|
||||||
|
|
||||||
|
```
|
||||||
|
Phase 1: 启动 Nacos → 等待健康检查 → 无配置则自动导入
|
||||||
|
Phase 2: 启动 System → Gateway
|
||||||
|
```
|
||||||
|
|
||||||
|
### 第四步:验证
|
||||||
|
|
||||||
|
| 服务 | 地址 |
|
||||||
|
|------|------|
|
||||||
|
| Nacos | `http://localhost:8848/nacos` |
|
||||||
|
| Gateway 文档 | `http://localhost:9999/doc.html` |
|
||||||
|
| System 文档 | `http://localhost:7001/doc.html` |
|
||||||
|
| 前端 | `http://localhost:3001`(如启用) |
|
||||||
|
|
||||||
|
Nacos 服务列表应有 `jeecg-gateway`、`jeecg-system`。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 架构链路
|
||||||
|
|
||||||
|
```
|
||||||
|
前端 :3001
|
||||||
|
↓
|
||||||
|
Gateway :9999 ──┐
|
||||||
|
↓ │ ghb-net(Docker 内部网络)
|
||||||
|
System :7001 ────┤
|
||||||
|
↓ │
|
||||||
|
Nacos :8848 ─────┘ ← init-nacos.sh 自动推送配置
|
||||||
|
↓
|
||||||
|
外部 MySQL / Redis ← Nacos 配置中地址已被替换
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Nacos 配置原理
|
||||||
|
|
||||||
|
`deploy/nacos/config/*.yaml` 模板中用占位符,`init-nacos.sh` 运行时从 `.env` 读取实际值替换后推送到 Nacos:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
# 模板(nacos/config/jeecg-dev.yaml)
|
||||||
|
url: jdbc:mysql://${MYSQL_HOST}:${MYSQL_PORT}/${DB_NAME}?...
|
||||||
|
host: ${REDIS_HOST}
|
||||||
|
port: ${REDIS_PORT}
|
||||||
|
|
||||||
|
# ↓ init-nacos.sh 替换后推送到 Nacos ↓
|
||||||
|
|
||||||
|
# Nacos 中实际配置
|
||||||
|
url: jdbc:mysql://10.13.13.1:3306/ghb_base?...
|
||||||
|
host: 10.13.13.1
|
||||||
|
port: 56379
|
||||||
|
```
|
||||||
|
|
||||||
|
服务启动时从 Nacos 拉取配置,自动连到外部 MySQL/Redis。
|
||||||
|
|
||||||
|
### 数据库要求
|
||||||
|
|
||||||
|
| 库 | 用途 | 谁建 | SQL |
|
||||||
|
|----|------|------|-----|
|
||||||
|
| `nacos` | Nacos 内部存储 | **手动** | `db/tables_nacos.sql` |
|
||||||
|
| `ghb_base` | 业务数据 | 手动 or `deploy.sh init-db` | `db/ghb_base_init.sql` |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 命令速查
|
||||||
|
|
||||||
|
| 命令 | 作用 |
|
||||||
|
|------|------|
|
||||||
|
| `bash deploy.sh init` | 交互式生成 .env |
|
||||||
|
| `bash deploy.sh start` | 停旧容器 → 启动(不编译) |
|
||||||
|
| `bash deploy.sh build` | 编译镜像 |
|
||||||
|
| `bash deploy.sh rebuild [分支]` | 拉代码 + 编译 + 启动 |
|
||||||
|
| `bash deploy.sh stop` | 停止所有容器 |
|
||||||
|
| `bash deploy.sh logs` | 查看日志 |
|
||||||
|
| `bash deploy.sh status` | 容器状态 |
|
||||||
|
| `bash deploy.sh config` | 查看配置 |
|
||||||
|
| `bash deploy.sh init-db` | 初始化外部业务数据库 |
|
||||||
|
| `bash deploy.sh init-nacos` | 强制重新导入 Nacos 配置 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 目录结构
|
||||||
|
|
||||||
|
```
|
||||||
|
deploy/
|
||||||
|
├── deploy.sh # 主脚本
|
||||||
|
├── init-nacos.sh # Nacos 配置导入
|
||||||
|
├── .env # 实际配置(gitignore)
|
||||||
|
├── docker-compose.yml # 单体编排
|
||||||
|
├── docker-compose.cloud.yml # Spring Cloud 编排
|
||||||
|
├── config/
|
||||||
|
│ └── application-prod.yml # 单体外部配置
|
||||||
|
└── nacos/config/
|
||||||
|
├── jeecg.yaml # 公共配置
|
||||||
|
├── jeecg-dev.yaml # 环境配置(含占位符)
|
||||||
|
├── jeecg-gateway-dev.yaml # 网关配置
|
||||||
|
└── jeecg-gateway-router.json # 路由表
|
||||||
|
```
|
||||||
|
|
@ -0,0 +1,43 @@
|
||||||
|
server:
|
||||||
|
port: 8081
|
||||||
|
servlet:
|
||||||
|
context-path: /test
|
||||||
|
|
||||||
|
spring:
|
||||||
|
datasource:
|
||||||
|
dynamic:
|
||||||
|
datasource:
|
||||||
|
master:
|
||||||
|
url: ${MYSQL_URL}
|
||||||
|
username: ${MYSQL_USER}
|
||||||
|
password: ${MYSQL_PASS}
|
||||||
|
driver-class-name: com.mysql.cj.jdbc.Driver
|
||||||
|
data:
|
||||||
|
redis:
|
||||||
|
host: ${REDIS_HOST}
|
||||||
|
port: ${REDIS_PORT:6379}
|
||||||
|
password: ${REDIS_PASS}
|
||||||
|
database: ${REDIS_DB:0}
|
||||||
|
flyway:
|
||||||
|
enabled: false
|
||||||
|
|
||||||
|
app:
|
||||||
|
jwt:
|
||||||
|
secret: ${JWT_SECRET:defaultSecretPleaseChangeMe}
|
||||||
|
|
||||||
|
knife4j:
|
||||||
|
enable: true
|
||||||
|
|
||||||
|
# ==== MinIO(可选,MINIO_ENABLED=true 时生效)====
|
||||||
|
jeecg:
|
||||||
|
uploadType: ${JEECG_UPLOAD_TYPE:local}
|
||||||
|
minio:
|
||||||
|
minio_url: ${MINIO_ENDPOINT:http://127.0.0.1:9000}
|
||||||
|
minio_name: ${MINIO_ACCESS_KEY:minioadmin}
|
||||||
|
minio_pass: ${MINIO_SECRET_KEY:minioadmin}
|
||||||
|
bucketName: ${MINIO_BUCKET:ghb-base}
|
||||||
|
|
||||||
|
logging:
|
||||||
|
level:
|
||||||
|
root: INFO
|
||||||
|
com.ghb: INFO
|
||||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,201 @@
|
||||||
|
# ============================================
|
||||||
|
# Spring Cloud 微服务编排
|
||||||
|
# Nacos + Gateway + System + MySQL + Redis + MinIO(可选)
|
||||||
|
# 中间件通过 profiles 按需启用:
|
||||||
|
# --profile mysql → Docker MySQL(external 时不激活)
|
||||||
|
# --profile redis → Docker Redis(external 时不激活)
|
||||||
|
# --profile minio → Docker MinIO
|
||||||
|
# --profile frontend → 前端 Nginx
|
||||||
|
# 启动顺序由 deploy.sh 控制
|
||||||
|
# Demo 服务默认注释,按需取消
|
||||||
|
# ============================================
|
||||||
|
services:
|
||||||
|
mysql:
|
||||||
|
build: ../db
|
||||||
|
image: ${APP_NAME}-mysql:latest
|
||||||
|
container_name: ${APP_NAME}-mysql
|
||||||
|
restart: unless-stopped
|
||||||
|
ports:
|
||||||
|
- "0.0.0.0:${MYSQL_PORT:-3306}:3306"
|
||||||
|
environment:
|
||||||
|
MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
|
||||||
|
MYSQL_DATABASE: ${DB_NAME}
|
||||||
|
TZ: Asia/Shanghai
|
||||||
|
command: --lower_case_table_names=1
|
||||||
|
volumes:
|
||||||
|
- mysql-data:/var/lib/mysql
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD", "mysqladmin", "ping", "-h", "localhost", "-u", "root", "-p${MYSQL_ROOT_PASSWORD}"]
|
||||||
|
interval: 10s
|
||||||
|
timeout: 5s
|
||||||
|
retries: 10
|
||||||
|
start_period: 60s
|
||||||
|
profiles:
|
||||||
|
- mysql
|
||||||
|
networks:
|
||||||
|
- default
|
||||||
|
|
||||||
|
redis:
|
||||||
|
image: redis:7-alpine
|
||||||
|
container_name: ${APP_NAME}-redis
|
||||||
|
restart: unless-stopped
|
||||||
|
ports:
|
||||||
|
- "0.0.0.0:${REDIS_HOST_PORT:-6379}:6379"
|
||||||
|
command: redis-server --appendonly yes ${REDIS_PASS:+--requirepass $REDIS_PASS}
|
||||||
|
volumes:
|
||||||
|
- redis-data:/data
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD", "redis-cli", "ping"]
|
||||||
|
interval: 10s
|
||||||
|
timeout: 5s
|
||||||
|
retries: 5
|
||||||
|
profiles:
|
||||||
|
- redis
|
||||||
|
networks:
|
||||||
|
- default
|
||||||
|
|
||||||
|
# MinIO 文件存储(可选,通过 --profile minio 启用)
|
||||||
|
minio:
|
||||||
|
image: minio/minio:RELEASE.2025-04-08T15-41-24Z
|
||||||
|
container_name: ${APP_NAME}-minio
|
||||||
|
restart: unless-stopped
|
||||||
|
ports:
|
||||||
|
- "${MINIO_PORT:-9000}:9000"
|
||||||
|
- "${MINIO_CONSOLE_PORT:-9001}:9001"
|
||||||
|
environment:
|
||||||
|
MINIO_ROOT_USER: ${MINIO_ACCESS_KEY:-minioadmin}
|
||||||
|
MINIO_ROOT_PASSWORD: ${MINIO_SECRET_KEY:-minioadmin}
|
||||||
|
command: server /data --console-address ":9001"
|
||||||
|
volumes:
|
||||||
|
- minio-data:/data
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD", "curl", "-f", "http://localhost:9000/minio/health/live"]
|
||||||
|
interval: 30s
|
||||||
|
timeout: 10s
|
||||||
|
retries: 3
|
||||||
|
profiles:
|
||||||
|
- minio
|
||||||
|
networks:
|
||||||
|
- default
|
||||||
|
|
||||||
|
nacos:
|
||||||
|
build:
|
||||||
|
context: ..
|
||||||
|
dockerfile: ghb-server-cloud/ghb-cloud-nacos/Dockerfile
|
||||||
|
image: ${APP_NAME}-nacos:latest
|
||||||
|
container_name: ${APP_NAME}-nacos
|
||||||
|
restart: unless-stopped
|
||||||
|
ports:
|
||||||
|
- "0.0.0.0:${NACOS_PORT:-8848}:8848"
|
||||||
|
environment:
|
||||||
|
MYSQL_HOST: ${MYSQL_HOST:-mysql}
|
||||||
|
MYSQL_PORT: "${MYSQL_PORT:-3306}"
|
||||||
|
MYSQL_DB: nacos
|
||||||
|
MYSQL_USER: ${MYSQL_USER:-root}
|
||||||
|
MYSQL_PWD: ${MYSQL_PASS:-${MYSQL_ROOT_PASSWORD}}
|
||||||
|
JAVA_OPTS: "-Xms512m -Xmx512m"
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD", "curl", "-f", "http://localhost:8848/nacos/v1/console/health/liveness"]
|
||||||
|
interval: 15s
|
||||||
|
timeout: 10s
|
||||||
|
retries: 20
|
||||||
|
start_period: 90s
|
||||||
|
networks:
|
||||||
|
- default
|
||||||
|
|
||||||
|
system:
|
||||||
|
build:
|
||||||
|
context: ..
|
||||||
|
dockerfile: ghb-server-cloud/ghb-system-cloud-start/Dockerfile
|
||||||
|
image: ${APP_NAME}-system-cloud:latest
|
||||||
|
container_name: ${APP_NAME}-system-cloud
|
||||||
|
restart: unless-stopped
|
||||||
|
ports:
|
||||||
|
- "0.0.0.0:${SYSTEM_PORT:-7001}:7001"
|
||||||
|
env_file:
|
||||||
|
- .env
|
||||||
|
environment:
|
||||||
|
SPRING_PROFILES_ACTIVE: dev
|
||||||
|
SPRING_CLOUD_NACOS_DISCOVERY_SERVER-ADDR: nacos:8848
|
||||||
|
SPRING_CLOUD_NACOS_CONFIG_SERVER-ADDR: nacos:8848
|
||||||
|
volumes:
|
||||||
|
- /opt/upFiles:/opt/upFiles
|
||||||
|
depends_on:
|
||||||
|
nacos:
|
||||||
|
condition: service_healthy
|
||||||
|
networks:
|
||||||
|
- default
|
||||||
|
|
||||||
|
gateway:
|
||||||
|
build:
|
||||||
|
context: ..
|
||||||
|
dockerfile: ghb-server-cloud/ghb-cloud-gateway/Dockerfile
|
||||||
|
image: ${APP_NAME}-gateway:latest
|
||||||
|
container_name: ${APP_NAME}-gateway
|
||||||
|
restart: unless-stopped
|
||||||
|
ports:
|
||||||
|
- "0.0.0.0:${GATEWAY_PORT:-9999}:9999"
|
||||||
|
env_file:
|
||||||
|
- .env
|
||||||
|
environment:
|
||||||
|
SPRING_PROFILES_ACTIVE: dev
|
||||||
|
SPRING_CLOUD_NACOS_DISCOVERY_SERVER-ADDR: nacos:8848
|
||||||
|
SPRING_CLOUD_NACOS_CONFIG_SERVER-ADDR: nacos:8848
|
||||||
|
depends_on:
|
||||||
|
nacos:
|
||||||
|
condition: service_healthy
|
||||||
|
system:
|
||||||
|
condition: service_started
|
||||||
|
networks:
|
||||||
|
- default
|
||||||
|
|
||||||
|
# 前端(可选,通过 --profile frontend 启用)
|
||||||
|
# 启用前需先在 ghb-frontend 目录执行 pnpm build 生成 dist/
|
||||||
|
frontend:
|
||||||
|
build:
|
||||||
|
context: ../../ghb-frontend
|
||||||
|
dockerfile: deploy/Dockerfile
|
||||||
|
image: ${APP_NAME}-frontend:latest
|
||||||
|
container_name: ${APP_NAME}-frontend
|
||||||
|
restart: unless-stopped
|
||||||
|
ports:
|
||||||
|
- "${FRONTEND_PORT:-80}:80"
|
||||||
|
environment:
|
||||||
|
BACKEND_PROXY: http://${APP_NAME}-gateway:${GATEWAY_PORT:-9999}
|
||||||
|
depends_on:
|
||||||
|
- gateway
|
||||||
|
profiles:
|
||||||
|
- frontend
|
||||||
|
networks:
|
||||||
|
- default
|
||||||
|
|
||||||
|
# Demo 服务(默认不启用,需要时取消注释)
|
||||||
|
#demo:
|
||||||
|
# build:
|
||||||
|
# context: ..
|
||||||
|
# dockerfile: ghb-server-cloud/ghb-demo-cloud-start/Dockerfile
|
||||||
|
# image: ${APP_NAME}-demo-cloud:latest
|
||||||
|
# container_name: ${APP_NAME}-demo-cloud
|
||||||
|
# restart: unless-stopped
|
||||||
|
# ports:
|
||||||
|
# - "0.0.0.0:${DEMO_PORT:-7002}:7002"
|
||||||
|
# env_file:
|
||||||
|
# - .env
|
||||||
|
# environment:
|
||||||
|
# SPRING_PROFILES_ACTIVE: dev
|
||||||
|
# SPRING_CLOUD_NACOS_DISCOVERY_SERVER-ADDR: nacos:8848
|
||||||
|
# SPRING_CLOUD_NACOS_CONFIG_SERVER-ADDR: nacos:8848
|
||||||
|
# depends_on:
|
||||||
|
# nacos:
|
||||||
|
# condition: service_healthy
|
||||||
|
# networks:
|
||||||
|
# - default
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
mysql-data:
|
||||||
|
redis-data:
|
||||||
|
minio-data:
|
||||||
|
|
||||||
|
networks:
|
||||||
|
default:
|
||||||
|
name: ${NETWORK_NAME:-ghb-net}
|
||||||
|
|
@ -0,0 +1,123 @@
|
||||||
|
# ============================================
|
||||||
|
# 单体部署编排
|
||||||
|
# 中间件通过 profiles 按需启用:
|
||||||
|
# --profile mysql → Docker MySQL
|
||||||
|
# --profile redis → Docker Redis
|
||||||
|
# --profile minio → Docker MinIO
|
||||||
|
# --profile frontend → 前端 Nginx
|
||||||
|
# 启动顺序由 deploy.sh 控制,app 不写 depends_on
|
||||||
|
# ============================================
|
||||||
|
services:
|
||||||
|
mysql:
|
||||||
|
build: ../db
|
||||||
|
image: ${APP_NAME}-mysql:latest
|
||||||
|
container_name: ${APP_NAME}-mysql
|
||||||
|
restart: unless-stopped
|
||||||
|
ports:
|
||||||
|
- "${MYSQL_PORT:-3306}:3306"
|
||||||
|
environment:
|
||||||
|
MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
|
||||||
|
MYSQL_DATABASE: ${DB_NAME}
|
||||||
|
TZ: Asia/Shanghai
|
||||||
|
command: --lower_case_table_names=1
|
||||||
|
volumes:
|
||||||
|
- mysql-data:/var/lib/mysql
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD", "mysqladmin", "ping", "-h", "localhost", "-u", "root", "-p${MYSQL_ROOT_PASSWORD}"]
|
||||||
|
interval: 10s
|
||||||
|
timeout: 5s
|
||||||
|
retries: 10
|
||||||
|
start_period: 60s
|
||||||
|
profiles:
|
||||||
|
- mysql
|
||||||
|
networks:
|
||||||
|
- default
|
||||||
|
|
||||||
|
redis:
|
||||||
|
image: redis:7-alpine
|
||||||
|
container_name: ${APP_NAME}-redis
|
||||||
|
restart: unless-stopped
|
||||||
|
ports:
|
||||||
|
- "0.0.0.0:${REDIS_HOST_PORT:-6379}:6379"
|
||||||
|
command: redis-server --appendonly yes ${REDIS_PASS:+--requirepass $REDIS_PASS}
|
||||||
|
volumes:
|
||||||
|
- redis-data:/data
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD", "redis-cli", "ping"]
|
||||||
|
interval: 10s
|
||||||
|
timeout: 5s
|
||||||
|
retries: 5
|
||||||
|
profiles:
|
||||||
|
- redis
|
||||||
|
networks:
|
||||||
|
- default
|
||||||
|
|
||||||
|
# MinIO 文件存储(可选,通过 --profile minio 启用)
|
||||||
|
minio:
|
||||||
|
image: minio/minio:RELEASE.2025-04-08T15-41-24Z
|
||||||
|
container_name: ${APP_NAME}-minio
|
||||||
|
restart: unless-stopped
|
||||||
|
ports:
|
||||||
|
- "${MINIO_PORT:-9000}:9000"
|
||||||
|
- "${MINIO_CONSOLE_PORT:-9001}:9001"
|
||||||
|
environment:
|
||||||
|
MINIO_ROOT_USER: ${MINIO_ACCESS_KEY:-minioadmin}
|
||||||
|
MINIO_ROOT_PASSWORD: ${MINIO_SECRET_KEY:-minioadmin}
|
||||||
|
command: server /data --console-address ":9001"
|
||||||
|
volumes:
|
||||||
|
- minio-data:/data
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD", "curl", "-f", "http://localhost:9000/minio/health/live"]
|
||||||
|
interval: 30s
|
||||||
|
timeout: 10s
|
||||||
|
retries: 3
|
||||||
|
profiles:
|
||||||
|
- minio
|
||||||
|
networks:
|
||||||
|
- default
|
||||||
|
|
||||||
|
app:
|
||||||
|
build:
|
||||||
|
context: ..
|
||||||
|
dockerfile: Dockerfile
|
||||||
|
image: ${APP_NAME}-backend:latest
|
||||||
|
container_name: ${APP_NAME}-backend
|
||||||
|
restart: unless-stopped
|
||||||
|
ports:
|
||||||
|
- "0.0.0.0:${APP_PORT}:8081"
|
||||||
|
env_file:
|
||||||
|
- .env
|
||||||
|
environment:
|
||||||
|
SPRING_PROFILES_ACTIVE: prod
|
||||||
|
volumes:
|
||||||
|
- ./config/application-prod.yml:/app/config/application-prod.yml:ro
|
||||||
|
- /opt/upFiles:/opt/upFiles
|
||||||
|
networks:
|
||||||
|
- default
|
||||||
|
|
||||||
|
# 前端(可选,通过 --profile frontend 启用)
|
||||||
|
# 启用前需先在 ghb-frontend 目录执行 pnpm build 生成 dist/
|
||||||
|
frontend:
|
||||||
|
build:
|
||||||
|
context: ../../ghb-frontend
|
||||||
|
dockerfile: deploy/Dockerfile
|
||||||
|
image: ${APP_NAME}-frontend:latest
|
||||||
|
container_name: ${APP_NAME}-frontend
|
||||||
|
restart: unless-stopped
|
||||||
|
ports:
|
||||||
|
- "${FRONTEND_PORT:-80}:80"
|
||||||
|
environment:
|
||||||
|
BACKEND_PROXY: http://${APP_NAME}-backend:8081/ghb
|
||||||
|
profiles:
|
||||||
|
- frontend
|
||||||
|
networks:
|
||||||
|
- default
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
mysql-data:
|
||||||
|
redis-data:
|
||||||
|
minio-data:
|
||||||
|
|
||||||
|
networks:
|
||||||
|
default:
|
||||||
|
name: ${NETWORK_NAME:-ghb-net}
|
||||||
|
|
@ -0,0 +1,177 @@
|
||||||
|
#!/bin/bash
|
||||||
|
# ============================================
|
||||||
|
# Nacos 配置初始化脚本
|
||||||
|
# 1. 等待 Nacos 就绪
|
||||||
|
# 2. 替换占位符 → 导入配置到 Nacos
|
||||||
|
#
|
||||||
|
# 用法:
|
||||||
|
# bash init-nacos.sh 首次导入(配置已存在则跳过)
|
||||||
|
# bash init-nacos.sh --force 强制覆盖已有配置
|
||||||
|
# ============================================
|
||||||
|
set -e
|
||||||
|
|
||||||
|
FORCE="${1:-}"
|
||||||
|
if [ "$FORCE" = "--force" ] || [ "$FORCE" = "-f" ]; then
|
||||||
|
FORCE=true
|
||||||
|
else
|
||||||
|
FORCE=false
|
||||||
|
fi
|
||||||
|
|
||||||
|
DIR="$(cd "$(dirname "$0")" && pwd)"
|
||||||
|
cd "$DIR"
|
||||||
|
|
||||||
|
NACOS_URL="${NACOS_URL:-http://localhost:8848}"
|
||||||
|
NACOS_USER="${NACOS_USER:-nacos}"
|
||||||
|
NACOS_PASS="${NACOS_PASS:-nacos}"
|
||||||
|
NAMESPACE="${NACOS_NAMESPACE:-springboot3}" # 默认与 Maven profile 保持一致
|
||||||
|
GROUP="${NACOS_GROUP:-DEFAULT_GROUP}"
|
||||||
|
CONFIG_DIR="${DIR}/nacos/config"
|
||||||
|
MAX_RETRIES=60
|
||||||
|
RETRY_INTERVAL=5
|
||||||
|
|
||||||
|
# ============================================
|
||||||
|
# 0. 加载 .env
|
||||||
|
# ============================================
|
||||||
|
if [ -f "${DIR}/.env" ]; then
|
||||||
|
set -a
|
||||||
|
source "${DIR}/.env"
|
||||||
|
set +a
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 默认值
|
||||||
|
MYSQL_HOST="${MYSQL_HOST:-mysql}"
|
||||||
|
MYSQL_PORT="${MYSQL_PORT:-3306}"
|
||||||
|
MYSQL_USER="${MYSQL_USER:-root}"
|
||||||
|
MYSQL_PASS="${MYSQL_PASS:-root}"
|
||||||
|
REDIS_HOST="${REDIS_HOST:-redis}"
|
||||||
|
REDIS_PORT="${REDIS_PORT:-6379}"
|
||||||
|
REDIS_PASS="${REDIS_PASS:-}"
|
||||||
|
DB_NAME="${DB_NAME:-ghb_base}"
|
||||||
|
MINIO_HOST="${MINIO_HOST:-minio}"
|
||||||
|
MINIO_PORT="${MINIO_PORT:-9000}"
|
||||||
|
MINIO_ACCESS_KEY="${MINIO_ACCESS_KEY:-minioadmin}"
|
||||||
|
MINIO_SECRET_KEY="${MINIO_SECRET_KEY:-minioadmin}"
|
||||||
|
MINIO_BUCKET_NAME="${MINIO_BUCKET_NAME:-ghb-base}"
|
||||||
|
|
||||||
|
# ============================================
|
||||||
|
# 1. 等待 Nacos 就绪
|
||||||
|
# ============================================
|
||||||
|
echo ">>> 等待 Nacos 就绪(${NACOS_URL})..."
|
||||||
|
for i in $(seq 1 $MAX_RETRIES); do
|
||||||
|
if curl -s "${NACOS_URL}/nacos/v1/console/health/liveness" | grep -q "OK"; then
|
||||||
|
echo "✅ Nacos 已就绪"
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
if [ "$i" -eq "$MAX_RETRIES" ]; then
|
||||||
|
echo "❌ Nacos 启动超时"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
echo " 等待中...(${i}/${MAX_RETRIES})"
|
||||||
|
sleep $RETRY_INTERVAL
|
||||||
|
done
|
||||||
|
|
||||||
|
# ============================================
|
||||||
|
# 2. 登录(如启用认证)
|
||||||
|
# ============================================
|
||||||
|
ACCESS_TOKEN=""
|
||||||
|
AUTH_CHECK=$(curl -s -o /dev/null -w "%{http_code}" "${NACOS_URL}/nacos/v1/auth/login" -X POST 2>/dev/null || echo "404")
|
||||||
|
if [ "$AUTH_CHECK" = "200" ]; then
|
||||||
|
echo ">>> Nacos 认证已启用,正在登录..."
|
||||||
|
TOKEN_RESP=$(curl -s -X POST "${NACOS_URL}/nacos/v1/auth/login" \
|
||||||
|
-d "username=${NACOS_USER}&password=${NACOS_PASS}")
|
||||||
|
ACCESS_TOKEN=$(echo "$TOKEN_RESP" | grep -o '"accessToken":"[^"]*"' | cut -d'"' -f4 || echo "")
|
||||||
|
if [ -n "$ACCESS_TOKEN" ]; then
|
||||||
|
echo "✅ 登录成功"
|
||||||
|
else
|
||||||
|
echo "⚠️ 登录失败,尝试无认证模式"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# ============================================
|
||||||
|
# 3. 检查配置是否已初始化
|
||||||
|
# ============================================
|
||||||
|
CHECK_DATA_ID="jeecg.yaml"
|
||||||
|
CHECK_RESP=$(curl -s "${NACOS_URL}/nacos/v1/cs/configs?dataId=${CHECK_DATA_ID}&group=${GROUP}&tenant=${NAMESPACE}")
|
||||||
|
if [ "$FORCE" = false ] && [ -n "$CHECK_RESP" ] && [ "$CHECK_RESP" != "config data not exist" ]; then
|
||||||
|
echo ">>> Nacos 配置已存在,跳过初始化"
|
||||||
|
echo " 如需强制覆盖,请执行: bash deploy.sh init-nacos --force"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "$FORCE" = true ]; then
|
||||||
|
echo ">>> --force:将覆盖已有配置"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# ============================================
|
||||||
|
# 4. 创建命名空间(如指定且非 public)
|
||||||
|
# ============================================
|
||||||
|
if [ -n "$NAMESPACE" ] && [ "$NAMESPACE" != "public" ]; then
|
||||||
|
echo ">>> 创建命名空间: ${NAMESPACE}"
|
||||||
|
TOKEN_PARAM=""
|
||||||
|
[ -n "$ACCESS_TOKEN" ] && TOKEN_PARAM="&accessToken=${ACCESS_TOKEN}"
|
||||||
|
curl -s -X POST "${NACOS_URL}/nacos/v1/namespace" \
|
||||||
|
-d "customNamespaceId=${NAMESPACE}&namespaceName=${NAMESPACE}${TOKEN_PARAM}" > /dev/null || true
|
||||||
|
fi
|
||||||
|
|
||||||
|
# ============================================
|
||||||
|
# 5. 导入配置
|
||||||
|
# ============================================
|
||||||
|
echo ">>> 开始导入 Nacos 配置..."
|
||||||
|
|
||||||
|
publish_config() {
|
||||||
|
local data_id="$1"
|
||||||
|
local type="$2"
|
||||||
|
local file="$3"
|
||||||
|
|
||||||
|
if [ ! -f "$file" ]; then
|
||||||
|
echo " ⚠️ 跳过(文件不存在): $file"
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 替换占位符 → 写入临时文件(避免 shell 特殊字符问题)
|
||||||
|
local tmpfile
|
||||||
|
tmpfile=$(mktemp)
|
||||||
|
sed \
|
||||||
|
-e "s|\${MYSQL_HOST}|${MYSQL_HOST}|g" \
|
||||||
|
-e "s|\${MYSQL_PORT}|${MYSQL_PORT}|g" \
|
||||||
|
-e "s|\${MYSQL_USER}|${MYSQL_USER}|g" \
|
||||||
|
-e "s|\${MYSQL_PASS}|${MYSQL_PASS}|g" \
|
||||||
|
-e "s|\${REDIS_HOST}|${REDIS_HOST}|g" \
|
||||||
|
-e "s|\${REDIS_PORT}|${REDIS_PORT}|g" \
|
||||||
|
-e "s|\${REDIS_PASS}|${REDIS_PASS}|g" \
|
||||||
|
-e "s|\${DB_NAME}|${DB_NAME}|g" \
|
||||||
|
-e "s|\${MINIO_HOST}|${MINIO_HOST}|g" \
|
||||||
|
-e "s|\${MINIO_PORT}|${MINIO_PORT}|g" \
|
||||||
|
-e "s|\${MINIO_ACCESS_KEY}|${MINIO_ACCESS_KEY}|g" \
|
||||||
|
-e "s|\${MINIO_SECRET_KEY}|${MINIO_SECRET_KEY}|g" \
|
||||||
|
-e "s|\${MINIO_BUCKET_NAME}|${MINIO_BUCKET_NAME}|g" \
|
||||||
|
"$file" > "$tmpfile"
|
||||||
|
|
||||||
|
local token_param=""
|
||||||
|
[ -n "$ACCESS_TOKEN" ] && token_param="&accessToken=${ACCESS_TOKEN}"
|
||||||
|
|
||||||
|
local http_code
|
||||||
|
http_code=$(curl -s -o /dev/null -w "%{http_code}" -X POST "${NACOS_URL}/nacos/v1/cs/configs" \
|
||||||
|
-d "tenant=${NAMESPACE}&dataId=${data_id}&group=${GROUP}&type=${type}${token_param}" \
|
||||||
|
--data-urlencode "content@${tmpfile}")
|
||||||
|
|
||||||
|
rm -f "$tmpfile"
|
||||||
|
|
||||||
|
if [ "$http_code" = "200" ]; then
|
||||||
|
echo " ✅ ${data_id}"
|
||||||
|
else
|
||||||
|
echo " ❌ ${data_id}(HTTP ${http_code})"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# yaml 配置
|
||||||
|
publish_config "jeecg.yaml" "yaml" "${CONFIG_DIR}/jeecg.yaml"
|
||||||
|
publish_config "jeecg-dev.yaml" "yaml" "${CONFIG_DIR}/jeecg-dev.yaml"
|
||||||
|
publish_config "jeecg-gateway-dev.yaml" "yaml" "${CONFIG_DIR}/jeecg-gateway-dev.yaml"
|
||||||
|
|
||||||
|
# json 配置(路由表)
|
||||||
|
publish_config "test-gateway-router" "json" "${CONFIG_DIR}/test-gateway-router.json"
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "✅ Nacos 配置初始化完成"
|
||||||
|
echo " Nacos 地址: ${NACOS_URL}/nacos"
|
||||||
|
|
@ -0,0 +1,147 @@
|
||||||
|
spring:
|
||||||
|
datasource:
|
||||||
|
druid:
|
||||||
|
stat-view-servlet:
|
||||||
|
enabled: true
|
||||||
|
loginUsername: admin
|
||||||
|
loginPassword: 123456
|
||||||
|
allow:
|
||||||
|
web-stat-filter:
|
||||||
|
enabled: true
|
||||||
|
dynamic:
|
||||||
|
druid:
|
||||||
|
initial-size: 5
|
||||||
|
min-idle: 5
|
||||||
|
maxActive: 20
|
||||||
|
maxWait: 60000
|
||||||
|
timeBetweenEvictionRunsMillis: 60000
|
||||||
|
minEvictableIdleTimeMillis: 300000
|
||||||
|
validationQuery: SELECT 1 FROM DUAL
|
||||||
|
testWhileIdle: true
|
||||||
|
testOnBorrow: false
|
||||||
|
testOnReturn: false
|
||||||
|
poolPreparedStatements: true
|
||||||
|
maxPoolPreparedStatementPerConnectionSize: 20
|
||||||
|
filters: stat,wall,slf4j
|
||||||
|
connectionProperties: druid.stat.mergeSql\=true;druid.stat.slowSqlMillis\=5000
|
||||||
|
datasource:
|
||||||
|
master:
|
||||||
|
url: jdbc:mysql://${MYSQL_HOST}:${MYSQL_PORT}/${DB_NAME}?characterEncoding=UTF-8&useUnicode=true&useSSL=false&tinyInt1isBit=false&allowPublicKeyRetrieval=true&serverTimezone=Asia/Shanghai
|
||||||
|
username: ${MYSQL_USER}
|
||||||
|
password: ${MYSQL_PASS}
|
||||||
|
driver-class-name: com.mysql.cj.jdbc.Driver
|
||||||
|
data:
|
||||||
|
redis:
|
||||||
|
database: 0
|
||||||
|
host: ${REDIS_HOST}
|
||||||
|
password: ${REDIS_PASS}
|
||||||
|
port: ${REDIS_PORT}
|
||||||
|
rabbitmq:
|
||||||
|
host: jeecg-boot-rabbitmq
|
||||||
|
username: guest
|
||||||
|
password: guest
|
||||||
|
port: 5672
|
||||||
|
publisher-confirms: true
|
||||||
|
publisher-returns: true
|
||||||
|
virtual-host: /
|
||||||
|
listener:
|
||||||
|
simple:
|
||||||
|
acknowledge-mode: manual
|
||||||
|
concurrency: 1
|
||||||
|
max-concurrency: 1
|
||||||
|
retry:
|
||||||
|
enabled: true
|
||||||
|
minidao:
|
||||||
|
base-package: org.jeecg.modules.jmreport.*,org.jeecg.modules.drag.*
|
||||||
|
ghb:
|
||||||
|
signatureSecret: dd05f1c54d63749eda95f9fa6d49v442a
|
||||||
|
signUrls: /sys/dict/getDictItems/*,/sys/dict/loadDict/*,/sys/dict/loadDictOrderByValue/*,/sys/dict/loadDictItem/*,/sys/dict/loadTreeData,/sys/api/queryTableDictItemsByCode,/sys/api/queryFilterTableDictInfo,/sys/api/queryTableDictByKeys,/sys/api/translateDictFromTable,/sys/api/translateDictFromTableByKeys
|
||||||
|
uploadType: local
|
||||||
|
domainUrl:
|
||||||
|
pc: http://localhost:3100
|
||||||
|
app: http://localhost:8051
|
||||||
|
path:
|
||||||
|
upload: /opt/upFiles
|
||||||
|
webapp: /opt/webapp
|
||||||
|
shiro:
|
||||||
|
excludeUrls: /test/jeecgDemo/demo3,/test/jeecgDemo/redisDemo/**,/category/**,/visual/**,/map/**,/jmreport/bigscreen2/**
|
||||||
|
oss:
|
||||||
|
endpoint: oss-cn-beijing.aliyuncs.com
|
||||||
|
accessKey: ??
|
||||||
|
secretKey: ??
|
||||||
|
bucketName: jeecgdev
|
||||||
|
staticDomain: ??
|
||||||
|
elasticsearch:
|
||||||
|
cluster-name: jeecg-ES
|
||||||
|
cluster-nodes: jeecg-boot-es:9200
|
||||||
|
check-enabled: false
|
||||||
|
file-view-domain: 127.0.0.1:8012
|
||||||
|
minio:
|
||||||
|
minio_url: http://${MINIO_HOST}:${MINIO_PORT}
|
||||||
|
minio_name: ${MINIO_ACCESS_KEY}
|
||||||
|
minio_pass: ${MINIO_SECRET_KEY}
|
||||||
|
bucketName: ${MINIO_BUCKET_NAME}
|
||||||
|
jmreport:
|
||||||
|
mode: dev
|
||||||
|
is_verify_token: false
|
||||||
|
verify_methods: remove,delete,save,add,update
|
||||||
|
wps:
|
||||||
|
domain: https://wwo.wps.cn/office/
|
||||||
|
appid: ??
|
||||||
|
appsecret: ??
|
||||||
|
xxljob:
|
||||||
|
enabled: false
|
||||||
|
adminAddresses: http://jeecg-boot-xxljob:9080/xxl-job-admin
|
||||||
|
appname: ${spring.application.name}
|
||||||
|
accessToken: ''
|
||||||
|
logPath: logs/jeecg/job/jobhandler/
|
||||||
|
logRetentionDays: 30
|
||||||
|
redisson:
|
||||||
|
address: ${REDIS_HOST}:${REDIS_PORT}
|
||||||
|
password: ${REDIS_PASS}
|
||||||
|
type: STANDALONE
|
||||||
|
enabled: true
|
||||||
|
logging:
|
||||||
|
level:
|
||||||
|
com.ghb.base.modules.system.mapper : info
|
||||||
|
cas:
|
||||||
|
prefixUrl: http://localhost:8888/cas
|
||||||
|
knife4j:
|
||||||
|
production: false
|
||||||
|
basic:
|
||||||
|
enable: false
|
||||||
|
username: jeecg
|
||||||
|
password: jeecg1314
|
||||||
|
justauth:
|
||||||
|
enabled: true
|
||||||
|
type:
|
||||||
|
GITHUB:
|
||||||
|
client-id: ??
|
||||||
|
client-secret: ??
|
||||||
|
redirect-uri: http://sso.test.com:8080/jeecg-boot/thirdLogin/github/callback
|
||||||
|
WECHAT_ENTERPRISE:
|
||||||
|
client-id: ??
|
||||||
|
client-secret: ??
|
||||||
|
redirect-uri: http://sso.test.com:8080/jeecg-boot/thirdLogin/wechat_enterprise/callback
|
||||||
|
agent-id: ??
|
||||||
|
DINGTALK:
|
||||||
|
client-id: ??
|
||||||
|
client-secret: ??
|
||||||
|
redirect-uri: http://sso.test.com:8080/jeecg-boot/thirdLogin/dingtalk/callback
|
||||||
|
cache:
|
||||||
|
type: default
|
||||||
|
prefix: 'demo::'
|
||||||
|
timeout: 1h
|
||||||
|
third-app:
|
||||||
|
enabled: false
|
||||||
|
type:
|
||||||
|
WECHAT_ENTERPRISE:
|
||||||
|
enabled: false
|
||||||
|
client-id: ??
|
||||||
|
client-secret: ??
|
||||||
|
agent-id: ??
|
||||||
|
DINGTALK:
|
||||||
|
enabled: false
|
||||||
|
client-id: ??
|
||||||
|
client-secret: ??
|
||||||
|
agent-id: ??
|
||||||
|
|
@ -0,0 +1,14 @@
|
||||||
|
ghb:
|
||||||
|
route:
|
||||||
|
config:
|
||||||
|
#type:database nacos yml
|
||||||
|
data-type: nacos
|
||||||
|
group: DEFAULT_GROUP
|
||||||
|
data-id: test-gateway-router
|
||||||
|
spring:
|
||||||
|
data:
|
||||||
|
redis:
|
||||||
|
database: 0
|
||||||
|
host: ${REDIS_HOST}
|
||||||
|
port: ${REDIS_PORT}
|
||||||
|
password: ${REDIS_PASS}
|
||||||
|
|
@ -0,0 +1,100 @@
|
||||||
|
server:
|
||||||
|
tomcat:
|
||||||
|
max-swallow-size: -1
|
||||||
|
error:
|
||||||
|
include-exception: true
|
||||||
|
include-stacktrace: ALWAYS
|
||||||
|
include-message: ALWAYS
|
||||||
|
compression:
|
||||||
|
enabled: true
|
||||||
|
min-response-size: 1024
|
||||||
|
mime-types: application/javascript,application/json,application/xml,text/html,text/xml,text/plain,text/css,image/*
|
||||||
|
management:
|
||||||
|
health:
|
||||||
|
mail:
|
||||||
|
enabled: false
|
||||||
|
endpoints:
|
||||||
|
web:
|
||||||
|
exposure:
|
||||||
|
include: "*"
|
||||||
|
health:
|
||||||
|
sensitive: true
|
||||||
|
endpoint:
|
||||||
|
health:
|
||||||
|
show-details: ALWAYS
|
||||||
|
spring:
|
||||||
|
servlet:
|
||||||
|
multipart:
|
||||||
|
max-file-size: 10MB
|
||||||
|
max-request-size: 10MB
|
||||||
|
mail:
|
||||||
|
host: smtp.163.com
|
||||||
|
username: jeecgos@163.com
|
||||||
|
password: ??
|
||||||
|
properties:
|
||||||
|
mail:
|
||||||
|
smtp:
|
||||||
|
auth: true
|
||||||
|
starttls:
|
||||||
|
enable: true
|
||||||
|
required: true
|
||||||
|
quartz:
|
||||||
|
job-store-type: jdbc
|
||||||
|
initialize-schema: embedded
|
||||||
|
auto-startup: false
|
||||||
|
startup-delay: 1s
|
||||||
|
overwrite-existing-jobs: true
|
||||||
|
properties:
|
||||||
|
org:
|
||||||
|
quartz:
|
||||||
|
scheduler:
|
||||||
|
instanceName: MyScheduler
|
||||||
|
instanceId: AUTO
|
||||||
|
jobStore:
|
||||||
|
class: org.springframework.scheduling.quartz.LocalDataSourceJobStore
|
||||||
|
driverDelegateClass: org.quartz.impl.jdbcjobstore.StdJDBCDelegate
|
||||||
|
tablePrefix: QRTZ_
|
||||||
|
isClustered: true
|
||||||
|
misfireThreshold: 12000
|
||||||
|
clusterCheckinInterval: 15000
|
||||||
|
threadPool:
|
||||||
|
class: org.quartz.simpl.SimpleThreadPool
|
||||||
|
threadCount: 10
|
||||||
|
threadPriority: 5
|
||||||
|
threadsInheritContextClassLoaderOfInitializingThread: true
|
||||||
|
jackson:
|
||||||
|
date-format: yyyy-MM-dd HH:mm:ss
|
||||||
|
time-zone: GMT+8
|
||||||
|
aop:
|
||||||
|
proxy-target-class: true
|
||||||
|
activiti:
|
||||||
|
check-process-definitions: false
|
||||||
|
async-executor-activate: false
|
||||||
|
job-executor-activate: false
|
||||||
|
jpa:
|
||||||
|
open-in-view: false
|
||||||
|
freemarker:
|
||||||
|
suffix: .ftl
|
||||||
|
content-type: text/html
|
||||||
|
charset: UTF-8
|
||||||
|
cache: false
|
||||||
|
prefer-file-system-access: false
|
||||||
|
template-loader-path:
|
||||||
|
- classpath:/templates
|
||||||
|
mvc:
|
||||||
|
static-path-pattern: /**
|
||||||
|
pathmatch:
|
||||||
|
matching-strategy: ant_path_matcher
|
||||||
|
resource:
|
||||||
|
static-locations: classpath:/static/,classpath:/public/
|
||||||
|
autoconfigure:
|
||||||
|
exclude: com.alibaba.druid.spring.boot3.autoconfigure.DruidDataSourceAutoConfigure
|
||||||
|
mybatis-plus:
|
||||||
|
mapper-locations: classpath*:org/jeecg/modules/**/xml/*Mapper.xml
|
||||||
|
global-config:
|
||||||
|
banner: false
|
||||||
|
db-config:
|
||||||
|
id-type: ASSIGN_ID
|
||||||
|
table-underline: true
|
||||||
|
configuration:
|
||||||
|
call-setters-on-nulls: true
|
||||||
|
|
@ -0,0 +1,52 @@
|
||||||
|
[{
|
||||||
|
"id": "test-system",
|
||||||
|
"order": 0,
|
||||||
|
"predicates": [{
|
||||||
|
"name": "Path",
|
||||||
|
"args": {
|
||||||
|
"_genkey_0": "/sys/**",
|
||||||
|
"_genkey_1": "/jmreport/**",
|
||||||
|
"_genkey_3": "/online/**",
|
||||||
|
"_genkey_4": "/generic/**"
|
||||||
|
}
|
||||||
|
}],
|
||||||
|
"filters": [],
|
||||||
|
"uri": "lb://test-system"
|
||||||
|
}, {
|
||||||
|
"id": "test-demo",
|
||||||
|
"order": 1,
|
||||||
|
"predicates": [{
|
||||||
|
"name": "Path",
|
||||||
|
"args": {
|
||||||
|
"_genkey_0": "/mock/**",
|
||||||
|
"_genkey_1": "/test/**",
|
||||||
|
"_genkey_2": "/bigscreen/template1/**",
|
||||||
|
"_genkey_3": "/bigscreen/template2/**"
|
||||||
|
}
|
||||||
|
}],
|
||||||
|
"filters": [],
|
||||||
|
"uri": "lb://test-demo"
|
||||||
|
}, {
|
||||||
|
"id": "test-system-websocket",
|
||||||
|
"order": 2,
|
||||||
|
"predicates": [{
|
||||||
|
"name": "Path",
|
||||||
|
"args": {
|
||||||
|
"_genkey_0": "/websocket/**",
|
||||||
|
"_genkey_1": "/newsWebsocket/**"
|
||||||
|
}
|
||||||
|
}],
|
||||||
|
"filters": [],
|
||||||
|
"uri": "lb:ws://test-system"
|
||||||
|
}, {
|
||||||
|
"id": "test-demo-websocket",
|
||||||
|
"order": 3,
|
||||||
|
"predicates": [{
|
||||||
|
"name": "Path",
|
||||||
|
"args": {
|
||||||
|
"_genkey_0": "/vxeSocket/**"
|
||||||
|
}
|
||||||
|
}],
|
||||||
|
"filters": [],
|
||||||
|
"uri": "lb:ws://test-demo"
|
||||||
|
}]
|
||||||
|
|
@ -0,0 +1,82 @@
|
||||||
|
version: '2'
|
||||||
|
services:
|
||||||
|
jeecg-boot-mysql:
|
||||||
|
build:
|
||||||
|
context: ./db
|
||||||
|
environment:
|
||||||
|
MYSQL_ROOT_PASSWORD: root
|
||||||
|
MYSQL_ROOT_HOST: '%'
|
||||||
|
TZ: Asia/Shanghai
|
||||||
|
restart: always
|
||||||
|
container_name: jeecg-boot-mysql
|
||||||
|
image: jeecg-boot-mysql
|
||||||
|
command:
|
||||||
|
--character-set-server=utf8mb4
|
||||||
|
--collation-server=utf8mb4_general_ci
|
||||||
|
--explicit_defaults_for_timestamp=true
|
||||||
|
--lower_case_table_names=1
|
||||||
|
--max_allowed_packet=128M
|
||||||
|
--default-authentication-plugin=caching_sha2_password
|
||||||
|
ports:
|
||||||
|
- 13306:3306
|
||||||
|
networks:
|
||||||
|
- jeecg-boot
|
||||||
|
|
||||||
|
jeecg-boot-redis:
|
||||||
|
image: registry.cn-hangzhou.aliyuncs.com/jeecgdocker/redis:5.0
|
||||||
|
# ports:
|
||||||
|
# - 6379:6379
|
||||||
|
restart: always
|
||||||
|
hostname: jeecg-boot-redis
|
||||||
|
container_name: jeecg-boot-redis
|
||||||
|
networks:
|
||||||
|
- jeecg-boot
|
||||||
|
|
||||||
|
jeecg-boot-pgvector:
|
||||||
|
image: registry.cn-hangzhou.aliyuncs.com/jeecgdocker/pgvector
|
||||||
|
container_name: jeecg-boot-pgvector
|
||||||
|
environment:
|
||||||
|
POSTGRES_USER: postgres
|
||||||
|
POSTGRES_PASSWORD: postgres
|
||||||
|
POSTGRES_DB: vector_db
|
||||||
|
# ports:
|
||||||
|
# - 5432:5432
|
||||||
|
restart: always
|
||||||
|
networks:
|
||||||
|
- jeecg-boot
|
||||||
|
|
||||||
|
# jeecg-boot-rabbitmq:
|
||||||
|
# image: rabbitmq:3.7.7-management
|
||||||
|
## ports:
|
||||||
|
## - 5672:5672
|
||||||
|
## - 15672:15672
|
||||||
|
# restart: always
|
||||||
|
# container_name: jeecg-boot-rabbitmq
|
||||||
|
# hostname: jeecg-boot-rabbitmq
|
||||||
|
# environment:
|
||||||
|
# RABBITMQ_DEFAULT_USER: guest
|
||||||
|
# RABBITMQ_DEFAULT_PASS: guest
|
||||||
|
# networks:
|
||||||
|
# - jeecg-boot
|
||||||
|
|
||||||
|
jeecg-boot-system:
|
||||||
|
build:
|
||||||
|
context: ./jeecg-module-system/test-system-start
|
||||||
|
restart: on-failure
|
||||||
|
mac_address: 02:42:ac:11:00:02
|
||||||
|
depends_on:
|
||||||
|
- jeecg-boot-mysql
|
||||||
|
- jeecg-boot-redis
|
||||||
|
container_name: jeecg-boot-system
|
||||||
|
image: jeecg-boot-system
|
||||||
|
hostname: jeecg-boot-system
|
||||||
|
ports:
|
||||||
|
- 8080:8080
|
||||||
|
networks:
|
||||||
|
- jeecg-boot
|
||||||
|
volumes:
|
||||||
|
- ./config:/jeecg-boot/config
|
||||||
|
|
||||||
|
networks:
|
||||||
|
jeecg-boot:
|
||||||
|
name: jeecg_boot
|
||||||
|
|
@ -0,0 +1,757 @@
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
<groupId>com.ghb</groupId>
|
||||||
|
<artifactId>test-base-parent</artifactId>
|
||||||
|
<version>3.9.2</version>
|
||||||
|
<packaging>pom</packaging>
|
||||||
|
<name>test-base ${project.version}</name>
|
||||||
|
|
||||||
|
<developers>
|
||||||
|
<developer>
|
||||||
|
<name>北京国炬信息技术有限公司</name>
|
||||||
|
<email>jeecgos@163.com</email>
|
||||||
|
<url>http://www.guojusoft.com</url>
|
||||||
|
</developer>
|
||||||
|
</developers>
|
||||||
|
|
||||||
|
<scm>
|
||||||
|
<connection>http://www.jeecg.com</connection>
|
||||||
|
<developerConnection>http://guojusoft.com</developerConnection>
|
||||||
|
<url>http://www.jeecg.com/vip</url>
|
||||||
|
</scm>
|
||||||
|
|
||||||
|
<parent>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-parent</artifactId>
|
||||||
|
<version>3.5.5</version>
|
||||||
|
<relativePath/>
|
||||||
|
</parent>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<jeecgboot.version>3.9.2</jeecgboot.version>
|
||||||
|
<!-- JDK 版本支持 17、21、24、25 -->
|
||||||
|
<java.version>17</java.version>
|
||||||
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
|
|
||||||
|
<!-- 微服务 -->
|
||||||
|
<spring-cloud.version>2025.0.0</spring-cloud.version>
|
||||||
|
<spring-cloud-alibaba.version>2023.0.3.3</spring-cloud-alibaba.version>
|
||||||
|
<alibaba.nacos.version>2.0.4</alibaba.nacos.version>
|
||||||
|
|
||||||
|
<xxl-job-core.version>2.4.1</xxl-job-core.version>
|
||||||
|
<fastjson.version>2.0.57</fastjson.version>
|
||||||
|
<aviator.version>5.2.6</aviator.version>
|
||||||
|
<pegdown.version>1.6.0</pegdown.version>
|
||||||
|
<commonmark.version>0.17.0</commonmark.version>
|
||||||
|
<knife4j-spring-boot-starter.version>4.5.0</knife4j-spring-boot-starter.version>
|
||||||
|
<!-- 数据库驱动 -->
|
||||||
|
<postgresql.version>42.2.25</postgresql.version>
|
||||||
|
<ojdbc6.version>11.2.0.3</ojdbc6.version>
|
||||||
|
<sqljdbc4.version>12.6.1.jre8</sqljdbc4.version>
|
||||||
|
<mysql-connector-java.version>8.0.27</mysql-connector-java.version>
|
||||||
|
<hutool.version>5.8.25</hutool.version>
|
||||||
|
<!-- 国产数据库驱动 -->
|
||||||
|
<kingbase8.version>9.0.0</kingbase8.version>
|
||||||
|
<dm8.version>8.1.3.140</dm8.version>
|
||||||
|
|
||||||
|
<!-- 积木报表 -->
|
||||||
|
<jimureport-spring-boot-starter.version>2.3.4</jimureport-spring-boot-starter.version>
|
||||||
|
<jimubi-spring-boot-starter.version>2.3.2</jimubi-spring-boot-starter.version>
|
||||||
|
<minidao.version>1.10.20</minidao.version>
|
||||||
|
<autopoi-web.version>2.0.4</autopoi-web.version>
|
||||||
|
|
||||||
|
<!-- 持久层 -->
|
||||||
|
<mybatis-plus.version>3.5.12</mybatis-plus.version>
|
||||||
|
<dynamic-datasource-spring-boot-starter.version>4.3.1</dynamic-datasource-spring-boot-starter.version>
|
||||||
|
<druid.version>1.2.24</druid.version>
|
||||||
|
|
||||||
|
<commons-io.version>2.20.0</commons-io.version>
|
||||||
|
<commons-fileupload.version>1.5</commons-fileupload.version>
|
||||||
|
<commons.version>2.6</commons.version>
|
||||||
|
<aliyun-java-sdk-dysmsapi.version>2.1.0</aliyun-java-sdk-dysmsapi.version>
|
||||||
|
<aliyun.oss.version>3.17.3</aliyun.oss.version>
|
||||||
|
<tencentcloud-sdk-java-sms.version>3.1.407</tencentcloud-sdk-java-sms.version>
|
||||||
|
<!-- shiro -->
|
||||||
|
<shiro.version>2.0.5</shiro.version>
|
||||||
|
<shiro-redis.version>3.2.3</shiro-redis.version>
|
||||||
|
<java-jwt.version>4.5.0</java-jwt.version>
|
||||||
|
<codegenerate.version>1.5.6</codegenerate.version>
|
||||||
|
<minio.version>8.5.7</minio.version>
|
||||||
|
<justauth-spring-boot-starter.version>1.4.0</justauth-spring-boot-starter.version>
|
||||||
|
<dom4j.version>1.6.1</dom4j.version>
|
||||||
|
<qiniu-java-sdk.version>7.4.0</qiniu-java-sdk.version>
|
||||||
|
<jedis.version>3.8.0</jedis.version>
|
||||||
|
<baidu-java-sdk.version>4.16.19</baidu-java-sdk.version>
|
||||||
|
</properties>
|
||||||
|
|
||||||
|
<modules>
|
||||||
|
<module>test-base-core</module>
|
||||||
|
<module>test-module-system</module>
|
||||||
|
<module>test-module-business</module>
|
||||||
|
</modules>
|
||||||
|
|
||||||
|
<repositories>
|
||||||
|
<repository>
|
||||||
|
<id>aliyun</id>
|
||||||
|
<name>aliyun Repository</name>
|
||||||
|
<url>https://maven.aliyun.com/repository/public</url>
|
||||||
|
<snapshots>
|
||||||
|
<enabled>false</enabled>
|
||||||
|
</snapshots>
|
||||||
|
</repository>
|
||||||
|
<repository>
|
||||||
|
<id>jeecg</id>
|
||||||
|
<name>jeecg Repository</name>
|
||||||
|
<url>https://maven.jeecg.org/nexus/content/repositories/jeecg</url>
|
||||||
|
<snapshots>
|
||||||
|
<enabled>false</enabled>
|
||||||
|
</snapshots>
|
||||||
|
</repository>
|
||||||
|
<repository>
|
||||||
|
<id>jeecg-snapshots</id>
|
||||||
|
<name>jeecg-snapshots Repository</name>
|
||||||
|
<url>https://oss.sonatype.org/content/repositories/snapshots</url>
|
||||||
|
<releases>
|
||||||
|
<enabled>false</enabled>
|
||||||
|
</releases>
|
||||||
|
<snapshots>
|
||||||
|
<enabled>true</enabled>
|
||||||
|
</snapshots>
|
||||||
|
</repository>
|
||||||
|
</repositories>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-test</artifactId>
|
||||||
|
<scope>test</scope>
|
||||||
|
<exclusions>
|
||||||
|
<exclusion>
|
||||||
|
<artifactId>asm</artifactId>
|
||||||
|
<groupId>org.ow2.asm</groupId>
|
||||||
|
</exclusion>
|
||||||
|
</exclusions>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.junit.platform</groupId>
|
||||||
|
<artifactId>junit-platform-launcher</artifactId>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
<!-- Lombok -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.projectlombok</groupId>
|
||||||
|
<artifactId>lombok</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<!-- json -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.alibaba</groupId>
|
||||||
|
<artifactId>fastjson</artifactId>
|
||||||
|
<version>${fastjson.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<!-- markdown -->
|
||||||
|
<!--<dependency>
|
||||||
|
<groupId>org.pegdown</groupId>
|
||||||
|
<artifactId>pegdown</artifactId>
|
||||||
|
<version>${pegdown.version}</version>
|
||||||
|
</dependency>-->
|
||||||
|
<!--markdown 解析 https://github.com/commonmark/commonmark-java -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.commonmark</groupId>
|
||||||
|
<artifactId>commonmark</artifactId>
|
||||||
|
<version>${commonmark.version}</version>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
<dependencyManagement>
|
||||||
|
<dependencies>
|
||||||
|
<!-- spring-cloud-->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.cloud</groupId>
|
||||||
|
<artifactId>spring-cloud-dependencies</artifactId>
|
||||||
|
<version>${spring-cloud.version}</version>
|
||||||
|
<type>pom</type>
|
||||||
|
<scope>import</scope>
|
||||||
|
</dependency>
|
||||||
|
<!-- spring-cloud-alibaba -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.alibaba.cloud</groupId>
|
||||||
|
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
|
||||||
|
<version>${spring-cloud-alibaba.version}</version>
|
||||||
|
<type>pom</type>
|
||||||
|
<scope>import</scope>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- system 模块-->
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.ghb</groupId>
|
||||||
|
<artifactId>test-system-biz</artifactId>
|
||||||
|
<version>${jeecgboot.version}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- business 模块-->
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.ghb</groupId>
|
||||||
|
<artifactId>test-module-business</artifactId>
|
||||||
|
<version>${jeecgboot.version}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- jeecg tools -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.jeecgframework.boot3</groupId>
|
||||||
|
<artifactId>jeecg-boot-common</artifactId>
|
||||||
|
<version>${jeecgboot.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<!-- jeecg core -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.ghb</groupId>
|
||||||
|
<artifactId>test-base-core</artifactId>
|
||||||
|
<version>${jeecgboot.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<!-- system 单体 api -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.ghb</groupId>
|
||||||
|
<artifactId>test-system-local-api</artifactId>
|
||||||
|
<version>${jeecgboot.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<!-- system 微服务 api -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.ghb</groupId>
|
||||||
|
<artifactId>test-system-cloud-api</artifactId>
|
||||||
|
<version>${jeecgboot.version}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- 微服务启动依赖 -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.jeecgframework.boot3</groupId>
|
||||||
|
<artifactId>jeecg-boot-starter-cloud</artifactId>
|
||||||
|
<version>${jeecgboot.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<!-- xxl-job -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.jeecgframework.boot3</groupId>
|
||||||
|
<artifactId>jeecg-boot-starter-job</artifactId>
|
||||||
|
<version>3.9.2</version>
|
||||||
|
</dependency>
|
||||||
|
<!--redis分布式锁-->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.jeecgframework.boot3</groupId>
|
||||||
|
<artifactId>jeecg-boot-starter-lock</artifactId>
|
||||||
|
<version>${jeecgboot.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<!--rabbitmq消息队列-->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.jeecgframework.boot3</groupId>
|
||||||
|
<artifactId>jeecg-boot-starter-rabbitmq</artifactId>
|
||||||
|
<version>${jeecgboot.version}</version>
|
||||||
|
<exclusions>
|
||||||
|
<exclusion>
|
||||||
|
<groupId>joda-time</groupId>
|
||||||
|
<artifactId>joda-time</artifactId>
|
||||||
|
</exclusion>
|
||||||
|
</exclusions>
|
||||||
|
</dependency>
|
||||||
|
<!--rocketmq-->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.jeecgframework.boot3</groupId>
|
||||||
|
<artifactId>jeecg-boot-starter-rocketmq</artifactId>
|
||||||
|
<version>${jeecgboot.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<!--分库分表shardingsphere-->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.jeecgframework.boot3</groupId>
|
||||||
|
<artifactId>jeecg-boot-starter-shardingsphere</artifactId>
|
||||||
|
<version>3.9.2</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.jeecgframework.boot3</groupId>
|
||||||
|
<artifactId>jeecg-boot-starter-shardingsphere-nacos</artifactId>
|
||||||
|
<version>3.9.2</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.hibernate</groupId>
|
||||||
|
<artifactId>hibernate-core</artifactId>
|
||||||
|
<version>5.6.7.Final</version>
|
||||||
|
<exclusions>
|
||||||
|
<exclusion>
|
||||||
|
<groupId>commons-collections</groupId>
|
||||||
|
<artifactId>commons-collections</artifactId>
|
||||||
|
</exclusion>
|
||||||
|
</exclusions>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.jeecgframework.boot3</groupId>
|
||||||
|
<artifactId>jeecg-online</artifactId>
|
||||||
|
<version>3.9.2-beta</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!--mongon db-->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.jeecgframework.boot3</groupId>
|
||||||
|
<artifactId>jeecg-boot-starter-mongon</artifactId>
|
||||||
|
<version>${jeecgboot.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<!--人大金仓驱动 版本号V008R006C005B0013 -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.jeecgframework</groupId>
|
||||||
|
<artifactId>kingbase8</artifactId>
|
||||||
|
<version>9.0.0</version>
|
||||||
|
<scope>runtime</scope>
|
||||||
|
</dependency>
|
||||||
|
<!-- 达梦8 数据库最新驱动 版本号 -3-26-2023.07.26-197096-20046-ENT -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.dameng</groupId>
|
||||||
|
<artifactId>DmJdbcDriver18</artifactId>
|
||||||
|
<version>${dm8.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.dameng</groupId>
|
||||||
|
<artifactId>DmDialect-for-hibernate5.0</artifactId>
|
||||||
|
<version>${dm8.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<!-- 七牛云SDK -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.qiniu</groupId>
|
||||||
|
<artifactId>qiniu-java-sdk</artifactId>
|
||||||
|
<version>${qiniu-java-sdk.version}</version>
|
||||||
|
<exclusions>
|
||||||
|
<exclusion>
|
||||||
|
<artifactId>okhttp</artifactId>
|
||||||
|
<groupId>com.squareup.okhttp3</groupId>
|
||||||
|
</exclusion>
|
||||||
|
</exclusions>
|
||||||
|
</dependency>
|
||||||
|
<!-- 百度SDK(OCR) -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.baidu.aip</groupId>
|
||||||
|
<artifactId>java-sdk</artifactId>
|
||||||
|
<version>${baidu-java-sdk.version}</version>
|
||||||
|
<exclusions>
|
||||||
|
<exclusion>
|
||||||
|
<groupId>org.slf4j</groupId>
|
||||||
|
<artifactId>slf4j-simple</artifactId>
|
||||||
|
</exclusion>
|
||||||
|
</exclusions>
|
||||||
|
</dependency>
|
||||||
|
<!-- dom4j -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>dom4j</groupId>
|
||||||
|
<artifactId>dom4j</artifactId>
|
||||||
|
<version>${dom4j.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<!-- update-begin-author:chenrui -date:20240104 for:[issue/5723]指定jaxb-runtime版本 -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.glassfish.jaxb</groupId>
|
||||||
|
<artifactId>jaxb-runtime</artifactId>
|
||||||
|
<version>2.3.3</version>
|
||||||
|
</dependency>
|
||||||
|
<!-- update-end-author:chenrui -date:20240104 for:[issue/5723]指定jaxb-runtime版本 -->
|
||||||
|
|
||||||
|
<!-- fileupload -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>commons-fileupload</groupId>
|
||||||
|
<artifactId>commons-fileupload</artifactId>
|
||||||
|
<version>${commons-fileupload.version}</version>
|
||||||
|
<exclusions>
|
||||||
|
<exclusion>
|
||||||
|
<artifactId>commons-io</artifactId>
|
||||||
|
<groupId>commons-io</groupId>
|
||||||
|
</exclusion>
|
||||||
|
</exclusions>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- justauth 第三方登录 -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.xkcoding.justauth</groupId>
|
||||||
|
<artifactId>justauth-spring-boot-starter</artifactId>
|
||||||
|
<version>${justauth-spring-boot-starter.version}</version>
|
||||||
|
<exclusions>
|
||||||
|
<exclusion>
|
||||||
|
<artifactId>hutool-core</artifactId>
|
||||||
|
<groupId>cn.hutool</groupId>
|
||||||
|
</exclusion>
|
||||||
|
<exclusion>
|
||||||
|
<artifactId>fastjson</artifactId>
|
||||||
|
<groupId>com.alibaba</groupId>
|
||||||
|
</exclusion>
|
||||||
|
</exclusions>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.squareup.okhttp3</groupId>
|
||||||
|
<artifactId>okhttp</artifactId>
|
||||||
|
<version>4.4.1</version>
|
||||||
|
</dependency>
|
||||||
|
<!-- hutool 工具类 -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>cn.hutool</groupId>
|
||||||
|
<artifactId>hutool-core</artifactId>
|
||||||
|
<version>${hutool.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>cn.hutool</groupId>
|
||||||
|
<artifactId>hutool-crypto</artifactId>
|
||||||
|
<version>${hutool.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<!--minio-->
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.minio</groupId>
|
||||||
|
<artifactId>minio</artifactId>
|
||||||
|
<version>${minio.version}</version>
|
||||||
|
<exclusions>
|
||||||
|
<exclusion>
|
||||||
|
<artifactId>okio</artifactId>
|
||||||
|
<groupId>com.squareup.okio</groupId>
|
||||||
|
</exclusion>
|
||||||
|
<exclusion>
|
||||||
|
<artifactId>okhttp</artifactId>
|
||||||
|
<groupId>com.squareup.okhttp3</groupId>
|
||||||
|
</exclusion>
|
||||||
|
</exclusions>
|
||||||
|
</dependency>
|
||||||
|
<!-- 企业微信和钉钉 SDK -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.jeecgframework</groupId>
|
||||||
|
<artifactId>weixin4j</artifactId>
|
||||||
|
<version>2.0.4</version>
|
||||||
|
<exclusions>
|
||||||
|
<exclusion>
|
||||||
|
<artifactId>commons-beanutils</artifactId>
|
||||||
|
<groupId>commons-beanutils</groupId>
|
||||||
|
</exclusion>
|
||||||
|
<exclusion>
|
||||||
|
<artifactId>commons-lang</artifactId>
|
||||||
|
<groupId>commons-lang</groupId>
|
||||||
|
</exclusion>
|
||||||
|
<exclusion>
|
||||||
|
<artifactId>commons-collections</artifactId>
|
||||||
|
<groupId>commons-collections</groupId>
|
||||||
|
</exclusion>
|
||||||
|
<exclusion>
|
||||||
|
<artifactId>commons-logging</artifactId>
|
||||||
|
<groupId>commons-logging</groupId>
|
||||||
|
</exclusion>
|
||||||
|
<exclusion>
|
||||||
|
<artifactId>commons-io</artifactId>
|
||||||
|
<groupId>commons-io</groupId>
|
||||||
|
</exclusion>
|
||||||
|
</exclusions>
|
||||||
|
</dependency>
|
||||||
|
<!-- minidao -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.jeecgframework.boot3</groupId>
|
||||||
|
<artifactId>minidao-spring-boot-starter-jsqlparser-4.9</artifactId>
|
||||||
|
<version>${minidao.version}</version>
|
||||||
|
<exclusions>
|
||||||
|
<exclusion>
|
||||||
|
<artifactId>druid</artifactId>
|
||||||
|
<groupId>com.alibaba</groupId>
|
||||||
|
</exclusion>
|
||||||
|
</exclusions>
|
||||||
|
</dependency>
|
||||||
|
<!-- 积木报表 -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.jeecgframework.jimureport</groupId>
|
||||||
|
<artifactId>jimureport-spring-boot3-starter</artifactId>
|
||||||
|
<version>${jimureport-spring-boot-starter.version}</version>
|
||||||
|
<exclusions>
|
||||||
|
<exclusion>
|
||||||
|
<groupId>commons-io</groupId>
|
||||||
|
<artifactId>commons-io</artifactId>
|
||||||
|
</exclusion>
|
||||||
|
<exclusion>
|
||||||
|
<groupId>com.alibaba</groupId>
|
||||||
|
<artifactId>fastjson</artifactId>
|
||||||
|
</exclusion>
|
||||||
|
<exclusion>
|
||||||
|
<artifactId>commons-lang</artifactId>
|
||||||
|
<groupId>commons-lang</groupId>
|
||||||
|
</exclusion>
|
||||||
|
<exclusion>
|
||||||
|
<artifactId>checker-qual</artifactId>
|
||||||
|
<groupId>org.checkerframework</groupId>
|
||||||
|
</exclusion>
|
||||||
|
<exclusion>
|
||||||
|
<artifactId>druid</artifactId>
|
||||||
|
<groupId>com.alibaba</groupId>
|
||||||
|
</exclusion>
|
||||||
|
<exclusion>
|
||||||
|
<artifactId>jsqlparser</artifactId>
|
||||||
|
<groupId>com.github.jsqlparser</groupId>
|
||||||
|
</exclusion>
|
||||||
|
<exclusion>
|
||||||
|
<groupId>io.minio</groupId>
|
||||||
|
<artifactId>minio</artifactId>
|
||||||
|
</exclusion>
|
||||||
|
<exclusion>
|
||||||
|
<groupId>org.apache.poi</groupId>
|
||||||
|
<artifactId>ooxml-schemas</artifactId>
|
||||||
|
</exclusion>
|
||||||
|
</exclusions>
|
||||||
|
</dependency>
|
||||||
|
<!-- AutoPoi Excel 工具类 -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.jeecgframework</groupId>
|
||||||
|
<artifactId>autopoi-spring-boot-3-starter</artifactId>
|
||||||
|
<version>${autopoi-web.version}</version>
|
||||||
|
<exclusions>
|
||||||
|
<exclusion>
|
||||||
|
<groupId>commons-codec</groupId>
|
||||||
|
<artifactId>commons-codec</artifactId>
|
||||||
|
</exclusion>
|
||||||
|
<exclusion>
|
||||||
|
<artifactId>xercesImpl</artifactId>
|
||||||
|
<groupId>xerces</groupId>
|
||||||
|
</exclusion>
|
||||||
|
<exclusion>
|
||||||
|
<artifactId>guava</artifactId>
|
||||||
|
<groupId>com.google.guava</groupId>
|
||||||
|
</exclusion>
|
||||||
|
<exclusion>
|
||||||
|
<groupId>commons-io</groupId>
|
||||||
|
<artifactId>commons-io</artifactId>
|
||||||
|
</exclusion>
|
||||||
|
</exclusions>
|
||||||
|
</dependency>
|
||||||
|
<!-- mongo、redis 和文件数据集支持包,按需引入 -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.jeecgframework.jimureport</groupId>
|
||||||
|
<artifactId>jimureport-nosql-starter3</artifactId>
|
||||||
|
<version>2.3.0</version>
|
||||||
|
<exclusions>
|
||||||
|
<exclusion>
|
||||||
|
<groupId>org.apache.calcite</groupId>
|
||||||
|
<artifactId>calcite-elasticsearch</artifactId>
|
||||||
|
</exclusion>
|
||||||
|
<exclusion>
|
||||||
|
<groupId>org.apache.commons</groupId>
|
||||||
|
<artifactId>commons-text</artifactId>
|
||||||
|
</exclusion>
|
||||||
|
<exclusion>
|
||||||
|
<groupId>org.apache.httpcomponents</groupId>
|
||||||
|
<artifactId>httpclient</artifactId>
|
||||||
|
</exclusion>
|
||||||
|
</exclusions>
|
||||||
|
</dependency>
|
||||||
|
<!-- 后台导出接口 Echart 图表支持包,按需引入 -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.jeecgframework.jimureport</groupId>
|
||||||
|
<artifactId>jimureport-echarts-starter</artifactId>
|
||||||
|
<version>2.3.0</version>
|
||||||
|
</dependency>
|
||||||
|
<!-- 积木BI 大屏和仪表盘 -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.jeecgframework.jimureport</groupId>
|
||||||
|
<artifactId>jimubi-spring-boot3-starter</artifactId>
|
||||||
|
<version>${jimubi-spring-boot-starter.version}</version>
|
||||||
|
<exclusions>
|
||||||
|
<exclusion>
|
||||||
|
<groupId>com.github.jsqlparser</groupId>
|
||||||
|
<artifactId>jsqlparser</artifactId>
|
||||||
|
</exclusion>
|
||||||
|
</exclusions>
|
||||||
|
</dependency>
|
||||||
|
<!-- chatgpt -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.jeecgframework.boot3</groupId>
|
||||||
|
<artifactId>jeecg-boot-starter-ai</artifactId>
|
||||||
|
<version>3.9.2.4</version>
|
||||||
|
</dependency>
|
||||||
|
<!-- flyway 支持 mysql5.7+、MariaDB10.3.16 -->
|
||||||
|
<!-- mysql5.6,需要把版本号改成 9.2.1 -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.flywaydb</groupId>
|
||||||
|
<artifactId>flyway-core</artifactId>
|
||||||
|
<version>7.15.0</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.commons</groupId>
|
||||||
|
<artifactId>commons-compress</artifactId>
|
||||||
|
<version>1.27.1</version>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
</dependencyManagement>
|
||||||
|
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<!-- 指定JDK编译版本 -->
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-compiler-plugin</artifactId>
|
||||||
|
<configuration>
|
||||||
|
<source>${java.version}</source>
|
||||||
|
<target>${java.version}</target>
|
||||||
|
<encoding>UTF-8</encoding>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
<!-- 打包跳过测试 -->
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-surefire-plugin</artifactId>
|
||||||
|
<configuration>
|
||||||
|
<skipTests>false</skipTests>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
<!-- 避免font文件的二进制文件格式压缩破坏 -->
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-resources-plugin</artifactId>
|
||||||
|
<version>3.3.1</version>
|
||||||
|
<configuration>
|
||||||
|
<encoding>UTF-8</encoding>
|
||||||
|
<nonFilteredFileExtensions>
|
||||||
|
<!-- 常见的二进制文件类型 -->
|
||||||
|
<nonFilteredFileExtension>woff</nonFilteredFileExtension>
|
||||||
|
<nonFilteredFileExtension>woff2</nonFilteredFileExtension>
|
||||||
|
<nonFilteredFileExtension>eot</nonFilteredFileExtension>
|
||||||
|
<nonFilteredFileExtension>ttf</nonFilteredFileExtension>
|
||||||
|
<nonFilteredFileExtension>svg</nonFilteredFileExtension>
|
||||||
|
<nonFilteredFileExtension>glb</nonFilteredFileExtension>
|
||||||
|
<nonFilteredFileExtension>wasm</nonFilteredFileExtension>
|
||||||
|
<nonFilteredFileExtension>ico</nonFilteredFileExtension>
|
||||||
|
<nonFilteredFileExtension>swf</nonFilteredFileExtension>
|
||||||
|
<nonFilteredFileExtension>mp3</nonFilteredFileExtension>
|
||||||
|
<nonFilteredFileExtension>mp4</nonFilteredFileExtension>
|
||||||
|
<nonFilteredFileExtension>jpg</nonFilteredFileExtension>
|
||||||
|
<nonFilteredFileExtension>png</nonFilteredFileExtension>
|
||||||
|
<nonFilteredFileExtension>gif</nonFilteredFileExtension>
|
||||||
|
<nonFilteredFileExtension>pdf</nonFilteredFileExtension>
|
||||||
|
<nonFilteredFileExtension>bcmap</nonFilteredFileExtension>
|
||||||
|
<nonFilteredFileExtension>cmap</nonFilteredFileExtension>
|
||||||
|
<nonFilteredFileExtension>cur</nonFilteredFileExtension>
|
||||||
|
<nonFilteredFileExtension>zip</nonFilteredFileExtension>
|
||||||
|
</nonFilteredFileExtensions>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
<resources>
|
||||||
|
<resource>
|
||||||
|
<directory>src/main/resources</directory>
|
||||||
|
<filtering>true</filtering>
|
||||||
|
</resource>
|
||||||
|
<resource>
|
||||||
|
<directory>src/main/java</directory>
|
||||||
|
<includes>
|
||||||
|
<include>**/*.xml</include>
|
||||||
|
<include>**/*.json</include>
|
||||||
|
<include>**/*.ftl</include>
|
||||||
|
</includes>
|
||||||
|
</resource>
|
||||||
|
</resources>
|
||||||
|
</build>
|
||||||
|
|
||||||
|
<distributionManagement>
|
||||||
|
<repository>
|
||||||
|
<id>jeecg</id>
|
||||||
|
<name>jeecg Repository</name>
|
||||||
|
<url>http://maven.jeecg.com:8090/nexus/content/repositories/jeecg</url>
|
||||||
|
</repository>
|
||||||
|
<snapshotRepository>
|
||||||
|
<id>jeecg-snapshots</id>
|
||||||
|
<name>jeecg Snapshot Repository</name>
|
||||||
|
<url>http://maven.jeecg.com:8090/nexus/content/repositories/snapshots/</url>
|
||||||
|
</snapshotRepository>
|
||||||
|
</distributionManagement>
|
||||||
|
|
||||||
|
<!-- 环境 -->
|
||||||
|
<profiles>
|
||||||
|
<!-- 开发 -->
|
||||||
|
<profile>
|
||||||
|
<id>dev</id>
|
||||||
|
<activation>
|
||||||
|
<!-- 默认激活配置 -->
|
||||||
|
<activeByDefault>true</activeByDefault>
|
||||||
|
</activation>
|
||||||
|
<properties>
|
||||||
|
<!-- 当前环境 -->
|
||||||
|
<profile.name>dev</profile.name>
|
||||||
|
<!--Nacos服务地址-->
|
||||||
|
<config.server-addr>test-nacos:8848</config.server-addr>
|
||||||
|
<!-- Nacos 配置中心命名空间,用于支持多环境(这里必须使用ID,不能使用名称,默认为空) -->
|
||||||
|
<config.namespace>springboot3</config.namespace>
|
||||||
|
<!--Nacos配置分组名称-->
|
||||||
|
<config.group>DEFAULT_GROUP</config.group>
|
||||||
|
<!-- Nacos 用户名 -->
|
||||||
|
<config.username></config.username>
|
||||||
|
<!-- Nacos 密码 -->
|
||||||
|
<config.password></config.password>
|
||||||
|
</properties>
|
||||||
|
</profile>
|
||||||
|
<!-- 测试 Nacos 开启鉴权、设置分组和命名空间
|
||||||
|
<profile>
|
||||||
|
<id>dev</id>
|
||||||
|
<properties>
|
||||||
|
<profile.name>dev</profile.name>
|
||||||
|
<config.server-addr>test-nacos:8848</config.server-addr>
|
||||||
|
<config.namespace>ac14ab82-51f8-4f0c-aa5b-25fb8384bfb6</config.namespace>
|
||||||
|
<config.group>JEECGDEV_GROUP</config.group>
|
||||||
|
<config.username>nacos</config.username>
|
||||||
|
<config.password>nacos</config.password>
|
||||||
|
</properties>
|
||||||
|
</profile> -->
|
||||||
|
<!-- 测试 -->
|
||||||
|
<profile>
|
||||||
|
<id>test</id>
|
||||||
|
<properties>
|
||||||
|
<!-- 当前环境 -->
|
||||||
|
<profile.name>test</profile.name>
|
||||||
|
<!--Nacos服务地址-->
|
||||||
|
<config.server-addr>test-nacos:8848</config.server-addr>
|
||||||
|
<!-- Nacos配置中心命名空间,用于支持多环境(这里必须使用ID,不能使用名称,默认为空) -->
|
||||||
|
<config.namespace>springboot3</config.namespace>
|
||||||
|
<!--Nacos配置分组名称-->
|
||||||
|
<config.group>DEFAULT_GROUP</config.group>
|
||||||
|
<!-- Nacos用户名 -->
|
||||||
|
<config.username></config.username>
|
||||||
|
<!--Nacos密码-->
|
||||||
|
<config.password></config.password>
|
||||||
|
</properties>
|
||||||
|
</profile>
|
||||||
|
<!-- docker 打包用 -->
|
||||||
|
<profile>
|
||||||
|
<id>docker</id>
|
||||||
|
<properties>
|
||||||
|
<!-- 当前环境 -->
|
||||||
|
<profile.name>docker</profile.name>
|
||||||
|
<!--Nacos服务地址-->
|
||||||
|
<config.server-addr>test-nacos:8848</config.server-addr>
|
||||||
|
<!-- Nacos配置中心命名空间,用于支持多环境(这里必须使用ID,不能使用名称,默认为空) -->
|
||||||
|
<config.namespace>springboot3</config.namespace>
|
||||||
|
<!--Nacos配置分组名称-->
|
||||||
|
<config.group>DEFAULT_GROUP</config.group>
|
||||||
|
<!-- Nacos用户名 -->
|
||||||
|
<config.username></config.username>
|
||||||
|
<!--Nacos密码-->
|
||||||
|
<config.password></config.password>
|
||||||
|
</properties>
|
||||||
|
</profile>
|
||||||
|
<!-- 生产 -->
|
||||||
|
<profile>
|
||||||
|
<id>prod</id>
|
||||||
|
<properties>
|
||||||
|
<!-- 当前环境 -->
|
||||||
|
<profile.name>prod</profile.name>
|
||||||
|
<!--Nacos服务地址-->
|
||||||
|
<config.server-addr>test-nacos:8848</config.server-addr>
|
||||||
|
<!-- Nacos配置中心命名空间,用于支持多环境(这里必须使用ID,不能使用名称,默认为空) -->
|
||||||
|
<config.namespace>springboot3</config.namespace>
|
||||||
|
<!--Nacos配置分组名称-->
|
||||||
|
<config.group>DEFAULT_GROUP</config.group>
|
||||||
|
<!-- Nacos用户名 -->
|
||||||
|
<config.username></config.username>
|
||||||
|
<!--Nacos密码-->
|
||||||
|
<config.password></config.password>
|
||||||
|
</properties>
|
||||||
|
</profile>
|
||||||
|
<!-- SpringCloud 运行环境 -->
|
||||||
|
<profile>
|
||||||
|
<id>SpringCloud</id>
|
||||||
|
<activation>
|
||||||
|
<!-- 默认激活配置 -->
|
||||||
|
<activeByDefault>false</activeByDefault>
|
||||||
|
</activation>
|
||||||
|
<modules>
|
||||||
|
<!-- 微服务模块 -->
|
||||||
|
<module>test-server-cloud</module>
|
||||||
|
</modules>
|
||||||
|
</profile>
|
||||||
|
</profiles>
|
||||||
|
</project>
|
||||||
|
|
@ -0,0 +1,750 @@
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
<groupId>com.ghb</groupId>
|
||||||
|
<artifactId>ghb-base-parent</artifactId>
|
||||||
|
<version>3.9.2</version>
|
||||||
|
<packaging>pom</packaging>
|
||||||
|
<name>ghb-base ${project.version}</name>
|
||||||
|
|
||||||
|
<developers>
|
||||||
|
<developer>
|
||||||
|
<name>北京国炬信息技术有限公司</name>
|
||||||
|
<email>jeecgos@163.com</email>
|
||||||
|
<url>http://www.guojusoft.com</url>
|
||||||
|
</developer>
|
||||||
|
</developers>
|
||||||
|
|
||||||
|
<scm>
|
||||||
|
<connection>http://www.jeecg.com</connection>
|
||||||
|
<developerConnection>http://guojusoft.com</developerConnection>
|
||||||
|
<url>http://www.jeecg.com/vip</url>
|
||||||
|
</scm>
|
||||||
|
|
||||||
|
<parent>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-parent</artifactId>
|
||||||
|
<version>3.5.5</version>
|
||||||
|
<relativePath/>
|
||||||
|
</parent>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<jeecgboot.version>3.9.2</jeecgboot.version>
|
||||||
|
<!-- JDK鐗堟湰鏀寔17銆?1銆?4銆?5 -->
|
||||||
|
<java.version>17</java.version>
|
||||||
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
|
|
||||||
|
<!-- 寰湇鍔?-->
|
||||||
|
<spring-cloud.version>2025.0.0</spring-cloud.version>
|
||||||
|
<spring-cloud-alibaba.version>2023.0.3.3</spring-cloud-alibaba.version>
|
||||||
|
<alibaba.nacos.version>2.0.4</alibaba.nacos.version>
|
||||||
|
|
||||||
|
<xxl-job-core.version>2.4.1</xxl-job-core.version>
|
||||||
|
<fastjson.version>2.0.57</fastjson.version>
|
||||||
|
<aviator.version>5.2.6</aviator.version>
|
||||||
|
<pegdown.version>1.6.0</pegdown.version>
|
||||||
|
<commonmark.version>0.17.0</commonmark.version>
|
||||||
|
<knife4j-spring-boot-starter.version>4.5.0</knife4j-spring-boot-starter.version>
|
||||||
|
<!-- 鏁版嵁搴撻┍鍔?-->
|
||||||
|
<postgresql.version>42.2.25</postgresql.version>
|
||||||
|
<ojdbc6.version>11.2.0.3</ojdbc6.version>
|
||||||
|
<sqljdbc4.version>12.6.1.jre8</sqljdbc4.version>
|
||||||
|
<mysql-connector-java.version>8.0.27</mysql-connector-java.version>
|
||||||
|
<hutool.version>5.8.25</hutool.version>
|
||||||
|
<!-- 鍥戒骇鏁版嵁搴撻┍鍔?-->
|
||||||
|
<kingbase8.version>9.0.0</kingbase8.version>
|
||||||
|
<dm8.version>8.1.3.140</dm8.version>
|
||||||
|
|
||||||
|
<!-- 绉湪鎶ヨ〃-->
|
||||||
|
<jimureport-spring-boot-starter.version>2.3.4</jimureport-spring-boot-starter.version>
|
||||||
|
<jimubi-spring-boot-starter.version>2.3.2</jimubi-spring-boot-starter.version>
|
||||||
|
<minidao.version>1.10.20</minidao.version>
|
||||||
|
<autopoi-web.version>2.0.4</autopoi-web.version>
|
||||||
|
|
||||||
|
<!-- 鎸佷箙灞?-->
|
||||||
|
<mybatis-plus.version>3.5.12</mybatis-plus.version>
|
||||||
|
<dynamic-datasource-spring-boot-starter.version>4.3.1</dynamic-datasource-spring-boot-starter.version>
|
||||||
|
<druid.version>1.2.24</druid.version>
|
||||||
|
|
||||||
|
<commons-io.version>2.20.0</commons-io.version>
|
||||||
|
<commons-fileupload.version>1.5</commons-fileupload.version>
|
||||||
|
<commons.version>2.6</commons.version>
|
||||||
|
<aliyun-java-sdk-dysmsapi.version>2.1.0</aliyun-java-sdk-dysmsapi.version>
|
||||||
|
<aliyun.oss.version>3.17.3</aliyun.oss.version>
|
||||||
|
<tencentcloud-sdk-java-sms.version>3.1.407</tencentcloud-sdk-java-sms.version>
|
||||||
|
<!-- shiro -->
|
||||||
|
<shiro.version>2.0.5</shiro.version>
|
||||||
|
<shiro-redis.version>3.2.3</shiro-redis.version>
|
||||||
|
<java-jwt.version>4.5.0</java-jwt.version>
|
||||||
|
<codegenerate.version>1.5.6</codegenerate.version>
|
||||||
|
<minio.version>8.5.7</minio.version>
|
||||||
|
<justauth-spring-boot-starter.version>1.4.0</justauth-spring-boot-starter.version>
|
||||||
|
<dom4j.version>1.6.1</dom4j.version>
|
||||||
|
<qiniu-java-sdk.version>7.4.0</qiniu-java-sdk.version>
|
||||||
|
<jedis.version>3.8.0</jedis.version>
|
||||||
|
<baidu-java-sdk.version>4.16.19</baidu-java-sdk.version>
|
||||||
|
</properties>
|
||||||
|
|
||||||
|
<modules>
|
||||||
|
<module>ghb-base-core</module>
|
||||||
|
<module>ghb-module-system</module>
|
||||||
|
<module>ghb-module-business</module>
|
||||||
|
</modules>
|
||||||
|
|
||||||
|
<repositories>
|
||||||
|
<repository>
|
||||||
|
<id>aliyun</id>
|
||||||
|
<name>aliyun Repository</name>
|
||||||
|
<url>https://maven.aliyun.com/repository/public</url>
|
||||||
|
<snapshots>
|
||||||
|
<enabled>false</enabled>
|
||||||
|
</snapshots>
|
||||||
|
</repository>
|
||||||
|
<repository>
|
||||||
|
<id>jeecg</id>
|
||||||
|
<name>jeecg Repository</name>
|
||||||
|
<url>https://maven.jeecg.org/nexus/content/repositories/jeecg</url>
|
||||||
|
<snapshots>
|
||||||
|
<enabled>false</enabled>
|
||||||
|
</snapshots>
|
||||||
|
</repository>
|
||||||
|
<repository>
|
||||||
|
<id>jeecg-snapshots</id>
|
||||||
|
<name>jeecg-snapshots Repository</name>
|
||||||
|
<url>https://oss.sonatype.org/content/repositories/snapshots</url>
|
||||||
|
<releases>
|
||||||
|
<enabled>false</enabled>
|
||||||
|
</releases>
|
||||||
|
<snapshots>
|
||||||
|
<enabled>true</enabled>
|
||||||
|
</snapshots>
|
||||||
|
</repository>
|
||||||
|
</repositories>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-test</artifactId>
|
||||||
|
<scope>test</scope>
|
||||||
|
<exclusions>
|
||||||
|
<exclusion>
|
||||||
|
<artifactId>asm</artifactId>
|
||||||
|
<groupId>org.ow2.asm</groupId>
|
||||||
|
</exclusion>
|
||||||
|
</exclusions>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.junit.platform</groupId>
|
||||||
|
<artifactId>junit-platform-launcher</artifactId>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
<!-- Lombok -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.projectlombok</groupId>
|
||||||
|
<artifactId>lombok</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<!-- json -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.alibaba</groupId>
|
||||||
|
<artifactId>fastjson</artifactId>
|
||||||
|
<version>${fastjson.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<!-- markdown -->
|
||||||
|
<!--<dependency>
|
||||||
|
<groupId>org.pegdown</groupId>
|
||||||
|
<artifactId>pegdown</artifactId>
|
||||||
|
<version>${pegdown.version}</version>
|
||||||
|
</dependency>-->
|
||||||
|
<!--markdown 瑙f瀽 https://github.com/commonmark/commonmark-java -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.commonmark</groupId>
|
||||||
|
<artifactId>commonmark</artifactId>
|
||||||
|
<version>${commonmark.version}</version>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
<dependencyManagement>
|
||||||
|
<dependencies>
|
||||||
|
<!-- spring-cloud-->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.cloud</groupId>
|
||||||
|
<artifactId>spring-cloud-dependencies</artifactId>
|
||||||
|
<version>${spring-cloud.version}</version>
|
||||||
|
<type>pom</type>
|
||||||
|
<scope>import</scope>
|
||||||
|
</dependency>
|
||||||
|
<!-- spring-cloud-alibaba -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.alibaba.cloud</groupId>
|
||||||
|
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
|
||||||
|
<version>${spring-cloud-alibaba.version}</version>
|
||||||
|
<type>pom</type>
|
||||||
|
<scope>import</scope>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- system 妯″潡-->
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.ghb</groupId>
|
||||||
|
<artifactId>ghb-system-biz</artifactId>
|
||||||
|
<version>${jeecgboot.version}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- jeecg tools -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.jeecgframework.boot3</groupId>
|
||||||
|
<artifactId>jeecg-boot-common</artifactId>
|
||||||
|
<version>${jeecgboot.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<!-- jeecg core -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.ghb</groupId>
|
||||||
|
<artifactId>ghb-base-core</artifactId>
|
||||||
|
<version>${jeecgboot.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<!-- system 鍗曚綋 api -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.ghb</groupId>
|
||||||
|
<artifactId>ghb-system-local-api</artifactId>
|
||||||
|
<version>${jeecgboot.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<!-- system 寰湇鍔?api -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.ghb</groupId>
|
||||||
|
<artifactId>ghb-system-cloud-api</artifactId>
|
||||||
|
<version>${jeecgboot.version}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!--寰湇鍔″惎鍔ㄤ緷璧-->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.jeecgframework.boot3</groupId>
|
||||||
|
<artifactId>jeecg-boot-starter-cloud</artifactId>
|
||||||
|
<version>${jeecgboot.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<!-- xxl-job -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.jeecgframework.boot3</groupId>
|
||||||
|
<artifactId>jeecg-boot-starter-job</artifactId>
|
||||||
|
<version>3.9.2</version>
|
||||||
|
</dependency>
|
||||||
|
<!--redis鍒嗗竷寮忛攣-->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.jeecgframework.boot3</groupId>
|
||||||
|
<artifactId>jeecg-boot-starter-lock</artifactId>
|
||||||
|
<version>${jeecgboot.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<!--rabbitmq娑堟伅闃熷垪-->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.jeecgframework.boot3</groupId>
|
||||||
|
<artifactId>jeecg-boot-starter-rabbitmq</artifactId>
|
||||||
|
<version>${jeecgboot.version}</version>
|
||||||
|
<exclusions>
|
||||||
|
<exclusion>
|
||||||
|
<groupId>joda-time</groupId>
|
||||||
|
<artifactId>joda-time</artifactId>
|
||||||
|
</exclusion>
|
||||||
|
</exclusions>
|
||||||
|
</dependency>
|
||||||
|
<!--rocketmq-->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.jeecgframework.boot3</groupId>
|
||||||
|
<artifactId>jeecg-boot-starter-rocketmq</artifactId>
|
||||||
|
<version>${jeecgboot.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<!--鍒嗗簱鍒嗚〃shardingsphere-->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.jeecgframework.boot3</groupId>
|
||||||
|
<artifactId>jeecg-boot-starter-shardingsphere</artifactId>
|
||||||
|
<version>3.9.2</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.jeecgframework.boot3</groupId>
|
||||||
|
<artifactId>jeecg-boot-starter-shardingsphere-nacos</artifactId>
|
||||||
|
<version>3.9.2</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.hibernate</groupId>
|
||||||
|
<artifactId>hibernate-core</artifactId>
|
||||||
|
<version>5.6.7.Final</version>
|
||||||
|
<exclusions>
|
||||||
|
<exclusion>
|
||||||
|
<groupId>commons-collections</groupId>
|
||||||
|
<artifactId>commons-collections</artifactId>
|
||||||
|
</exclusion>
|
||||||
|
</exclusions>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.jeecgframework.boot3</groupId>
|
||||||
|
<artifactId>jeecg-online</artifactId>
|
||||||
|
<version>3.9.2-beta</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!--mongon db-->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.jeecgframework.boot3</groupId>
|
||||||
|
<artifactId>jeecg-boot-starter-mongon</artifactId>
|
||||||
|
<version>${jeecgboot.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<!--浜哄ぇ閲戜粨椹卞姩 鐗堟湰鍙稸008R006C005B0013 -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.jeecgframework</groupId>
|
||||||
|
<artifactId>kingbase8</artifactId>
|
||||||
|
<version>9.0.0</version>
|
||||||
|
<scope>runtime</scope>
|
||||||
|
</dependency>
|
||||||
|
<!--杈炬ⅵ8鏁版嵁搴撴渶鏂伴┍鍔?鐗堟湰鍙?-3-26-2023.07.26-197096-20046-ENT -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.dameng</groupId>
|
||||||
|
<artifactId>DmJdbcDriver18</artifactId>
|
||||||
|
<version>${dm8.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.dameng</groupId>
|
||||||
|
<artifactId>DmDialect-for-hibernate5.0</artifactId>
|
||||||
|
<version>${dm8.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<!-- 涓冪墰浜慡DK -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.qiniu</groupId>
|
||||||
|
<artifactId>qiniu-java-sdk</artifactId>
|
||||||
|
<version>${qiniu-java-sdk.version}</version>
|
||||||
|
<exclusions>
|
||||||
|
<exclusion>
|
||||||
|
<artifactId>okhttp</artifactId>
|
||||||
|
<groupId>com.squareup.okhttp3</groupId>
|
||||||
|
</exclusion>
|
||||||
|
</exclusions>
|
||||||
|
</dependency>
|
||||||
|
<!-- 鐧惧害SDK 锛圤CR锛?-->
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.baidu.aip</groupId>
|
||||||
|
<artifactId>java-sdk</artifactId>
|
||||||
|
<version>${baidu-java-sdk.version}</version>
|
||||||
|
<exclusions>
|
||||||
|
<exclusion>
|
||||||
|
<groupId>org.slf4j</groupId>
|
||||||
|
<artifactId>slf4j-simple</artifactId>
|
||||||
|
</exclusion>
|
||||||
|
</exclusions>
|
||||||
|
</dependency>
|
||||||
|
<!-- dom4j -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>dom4j</groupId>
|
||||||
|
<artifactId>dom4j</artifactId>
|
||||||
|
<version>${dom4j.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<!-- update-begin-author:chenrui -date:20240104 for锛歔issue/5723]鎸囧畾jaxb-runtime鐗堟湰 -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.glassfish.jaxb</groupId>
|
||||||
|
<artifactId>jaxb-runtime</artifactId>
|
||||||
|
<version>2.3.3</version>
|
||||||
|
</dependency>
|
||||||
|
<!-- update-end-author:chenrui -date:20240104 for锛歔issue/5723]鎸囧畾jaxb-runtime鐗堟湰 -->
|
||||||
|
|
||||||
|
<!-- fileupload -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>commons-fileupload</groupId>
|
||||||
|
<artifactId>commons-fileupload</artifactId>
|
||||||
|
<version>${commons-fileupload.version}</version>
|
||||||
|
<exclusions>
|
||||||
|
<exclusion>
|
||||||
|
<artifactId>commons-io</artifactId>
|
||||||
|
<groupId>commons-io</groupId>
|
||||||
|
</exclusion>
|
||||||
|
</exclusions>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- justauth绗笁鏂圭櫥褰? -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.xkcoding.justauth</groupId>
|
||||||
|
<artifactId>justauth-spring-boot-starter</artifactId>
|
||||||
|
<version>${justauth-spring-boot-starter.version}</version>
|
||||||
|
<exclusions>
|
||||||
|
<exclusion>
|
||||||
|
<artifactId>hutool-core</artifactId>
|
||||||
|
<groupId>cn.hutool</groupId>
|
||||||
|
</exclusion>
|
||||||
|
<exclusion>
|
||||||
|
<artifactId>fastjson</artifactId>
|
||||||
|
<groupId>com.alibaba</groupId>
|
||||||
|
</exclusion>
|
||||||
|
</exclusions>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.squareup.okhttp3</groupId>
|
||||||
|
<artifactId>okhttp</artifactId>
|
||||||
|
<version>4.4.1</version>
|
||||||
|
</dependency>
|
||||||
|
<!-- hutool宸ュ叿绫-->
|
||||||
|
<dependency>
|
||||||
|
<groupId>cn.hutool</groupId>
|
||||||
|
<artifactId>hutool-core</artifactId>
|
||||||
|
<version>${hutool.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>cn.hutool</groupId>
|
||||||
|
<artifactId>hutool-crypto</artifactId>
|
||||||
|
<version>${hutool.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<!--minio-->
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.minio</groupId>
|
||||||
|
<artifactId>minio</artifactId>
|
||||||
|
<version>${minio.version}</version>
|
||||||
|
<exclusions>
|
||||||
|
<exclusion>
|
||||||
|
<artifactId>okio</artifactId>
|
||||||
|
<groupId>com.squareup.okio</groupId>
|
||||||
|
</exclusion>
|
||||||
|
<exclusion>
|
||||||
|
<artifactId>okhttp</artifactId>
|
||||||
|
<groupId>com.squareup.okhttp3</groupId>
|
||||||
|
</exclusion>
|
||||||
|
</exclusions>
|
||||||
|
</dependency>
|
||||||
|
<!-- 浼佷笟寰俊鍜岄拤閽?SDK -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.jeecgframework</groupId>
|
||||||
|
<artifactId>weixin4j</artifactId>
|
||||||
|
<version>2.0.4</version>
|
||||||
|
<exclusions>
|
||||||
|
<exclusion>
|
||||||
|
<artifactId>commons-beanutils</artifactId>
|
||||||
|
<groupId>commons-beanutils</groupId>
|
||||||
|
</exclusion>
|
||||||
|
<exclusion>
|
||||||
|
<artifactId>commons-lang</artifactId>
|
||||||
|
<groupId>commons-lang</groupId>
|
||||||
|
</exclusion>
|
||||||
|
<exclusion>
|
||||||
|
<artifactId>commons-collections</artifactId>
|
||||||
|
<groupId>commons-collections</groupId>
|
||||||
|
</exclusion>
|
||||||
|
<exclusion>
|
||||||
|
<artifactId>commons-logging</artifactId>
|
||||||
|
<groupId>commons-logging</groupId>
|
||||||
|
</exclusion>
|
||||||
|
<exclusion>
|
||||||
|
<artifactId>commons-io</artifactId>
|
||||||
|
<groupId>commons-io</groupId>
|
||||||
|
</exclusion>
|
||||||
|
</exclusions>
|
||||||
|
</dependency>
|
||||||
|
<!-- minidao -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.jeecgframework.boot3</groupId>
|
||||||
|
<artifactId>minidao-spring-boot-starter-jsqlparser-4.9</artifactId>
|
||||||
|
<version>${minidao.version}</version>
|
||||||
|
<exclusions>
|
||||||
|
<exclusion>
|
||||||
|
<artifactId>druid</artifactId>
|
||||||
|
<groupId>com.alibaba</groupId>
|
||||||
|
</exclusion>
|
||||||
|
</exclusions>
|
||||||
|
</dependency>
|
||||||
|
<!-- 绉湪鎶ヨ〃-->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.jeecgframework.jimureport</groupId>
|
||||||
|
<artifactId>jimureport-spring-boot3-starter</artifactId>
|
||||||
|
<version>${jimureport-spring-boot-starter.version}</version>
|
||||||
|
<exclusions>
|
||||||
|
<exclusion>
|
||||||
|
<groupId>commons-io</groupId>
|
||||||
|
<artifactId>commons-io</artifactId>
|
||||||
|
</exclusion>
|
||||||
|
<exclusion>
|
||||||
|
<groupId>com.alibaba</groupId>
|
||||||
|
<artifactId>fastjson</artifactId>
|
||||||
|
</exclusion>
|
||||||
|
<exclusion>
|
||||||
|
<artifactId>commons-lang</artifactId>
|
||||||
|
<groupId>commons-lang</groupId>
|
||||||
|
</exclusion>
|
||||||
|
<exclusion>
|
||||||
|
<artifactId>checker-qual</artifactId>
|
||||||
|
<groupId>org.checkerframework</groupId>
|
||||||
|
</exclusion>
|
||||||
|
<exclusion>
|
||||||
|
<artifactId>druid</artifactId>
|
||||||
|
<groupId>com.alibaba</groupId>
|
||||||
|
</exclusion>
|
||||||
|
<exclusion>
|
||||||
|
<artifactId>jsqlparser</artifactId>
|
||||||
|
<groupId>com.github.jsqlparser</groupId>
|
||||||
|
</exclusion>
|
||||||
|
<exclusion>
|
||||||
|
<groupId>io.minio</groupId>
|
||||||
|
<artifactId>minio</artifactId>
|
||||||
|
</exclusion>
|
||||||
|
<exclusion>
|
||||||
|
<groupId>org.apache.poi</groupId>
|
||||||
|
<artifactId>ooxml-schemas</artifactId>
|
||||||
|
</exclusion>
|
||||||
|
</exclusions>
|
||||||
|
</dependency>
|
||||||
|
<!-- AutoPoi Excel宸ュ叿绫-->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.jeecgframework</groupId>
|
||||||
|
<artifactId>autopoi-spring-boot-3-starter</artifactId>
|
||||||
|
<version>${autopoi-web.version}</version>
|
||||||
|
<exclusions>
|
||||||
|
<exclusion>
|
||||||
|
<groupId>commons-codec</groupId>
|
||||||
|
<artifactId>commons-codec</artifactId>
|
||||||
|
</exclusion>
|
||||||
|
<exclusion>
|
||||||
|
<artifactId>xercesImpl</artifactId>
|
||||||
|
<groupId>xerces</groupId>
|
||||||
|
</exclusion>
|
||||||
|
<exclusion>
|
||||||
|
<artifactId>guava</artifactId>
|
||||||
|
<groupId>com.google.guava</groupId>
|
||||||
|
</exclusion>
|
||||||
|
<exclusion>
|
||||||
|
<groupId>commons-io</groupId>
|
||||||
|
<artifactId>commons-io</artifactId>
|
||||||
|
</exclusion>
|
||||||
|
</exclusions>
|
||||||
|
</dependency>
|
||||||
|
<!-- mongo銆乺edis鍜屾枃浠舵暟鎹泦鏀寔鍖咃紝鎸夐渶寮曞叆 -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.jeecgframework.jimureport</groupId>
|
||||||
|
<artifactId>jimureport-nosql-starter3</artifactId>
|
||||||
|
<version>2.3.0</version>
|
||||||
|
<exclusions>
|
||||||
|
<exclusion>
|
||||||
|
<groupId>org.apache.calcite</groupId>
|
||||||
|
<artifactId>calcite-elasticsearch</artifactId>
|
||||||
|
</exclusion>
|
||||||
|
<exclusion>
|
||||||
|
<groupId>org.apache.commons</groupId>
|
||||||
|
<artifactId>commons-text</artifactId>
|
||||||
|
</exclusion>
|
||||||
|
<exclusion>
|
||||||
|
<groupId>org.apache.httpcomponents</groupId>
|
||||||
|
<artifactId>httpclient</artifactId>
|
||||||
|
</exclusion>
|
||||||
|
</exclusions>
|
||||||
|
</dependency>
|
||||||
|
<!-- 鍚庡彴瀵煎嚭鎺ュ彛Echart鍥捐〃鏀寔鍖咃紝鎸夐渶寮曞叆 -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.jeecgframework.jimureport</groupId>
|
||||||
|
<artifactId>jimureport-echarts-starter</artifactId>
|
||||||
|
<version>2.3.0</version>
|
||||||
|
</dependency>
|
||||||
|
<!-- 绉湪BI澶у睆鍜屼华琛ㄧ洏 -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.jeecgframework.jimureport</groupId>
|
||||||
|
<artifactId>jimubi-spring-boot3-starter</artifactId>
|
||||||
|
<version>${jimubi-spring-boot-starter.version}</version>
|
||||||
|
<exclusions>
|
||||||
|
<exclusion>
|
||||||
|
<groupId>com.github.jsqlparser</groupId>
|
||||||
|
<artifactId>jsqlparser</artifactId>
|
||||||
|
</exclusion>
|
||||||
|
</exclusions>
|
||||||
|
</dependency>
|
||||||
|
<!-- chatgpt -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.jeecgframework.boot3</groupId>
|
||||||
|
<artifactId>jeecg-boot-starter-ai</artifactId>
|
||||||
|
<version>3.9.2.4</version>
|
||||||
|
</dependency>
|
||||||
|
<!--flyway 鏀寔 mysql5.7+銆丮ariaDB10.3.16-->
|
||||||
|
<!--mysql5.6锛岄渶瑕佹妸鐗堟湰鍙锋敼鎴?.2.1-->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.flywaydb</groupId>
|
||||||
|
<artifactId>flyway-core</artifactId>
|
||||||
|
<version>7.15.0</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.commons</groupId>
|
||||||
|
<artifactId>commons-compress</artifactId>
|
||||||
|
<version>1.27.1</version>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
</dependencyManagement>
|
||||||
|
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<!-- 鎸囧畾JDK缂栬瘧鐗堟湰 -->
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-compiler-plugin</artifactId>
|
||||||
|
<configuration>
|
||||||
|
<source>${java.version}</source>
|
||||||
|
<target>${java.version}</target>
|
||||||
|
<encoding>UTF-8</encoding>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
<!-- 鎵撳寘璺宠繃娴嬭瘯 -->
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-surefire-plugin</artifactId>
|
||||||
|
<configuration>
|
||||||
|
<skipTests>true</skipTests>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
<!-- 閬垮厤font鏂囦欢鐨勪簩杩涘埗鏂囦欢鏍煎紡鍘嬬缉鐮村潖 -->
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-resources-plugin</artifactId>
|
||||||
|
<version>3.3.1</version>
|
||||||
|
<configuration>
|
||||||
|
<encoding>UTF-8</encoding>
|
||||||
|
<nonFilteredFileExtensions>
|
||||||
|
<!-- 甯歌鐨勪簩杩涘埗鏂囦欢绫诲瀷 -->
|
||||||
|
<nonFilteredFileExtension>woff</nonFilteredFileExtension>
|
||||||
|
<nonFilteredFileExtension>woff2</nonFilteredFileExtension>
|
||||||
|
<nonFilteredFileExtension>eot</nonFilteredFileExtension>
|
||||||
|
<nonFilteredFileExtension>ttf</nonFilteredFileExtension>
|
||||||
|
<nonFilteredFileExtension>svg</nonFilteredFileExtension>
|
||||||
|
<nonFilteredFileExtension>glb</nonFilteredFileExtension>
|
||||||
|
<nonFilteredFileExtension>wasm</nonFilteredFileExtension>
|
||||||
|
<nonFilteredFileExtension>ico</nonFilteredFileExtension>
|
||||||
|
<nonFilteredFileExtension>swf</nonFilteredFileExtension>
|
||||||
|
<nonFilteredFileExtension>mp3</nonFilteredFileExtension>
|
||||||
|
<nonFilteredFileExtension>mp4</nonFilteredFileExtension>
|
||||||
|
<nonFilteredFileExtension>jpg</nonFilteredFileExtension>
|
||||||
|
<nonFilteredFileExtension>png</nonFilteredFileExtension>
|
||||||
|
<nonFilteredFileExtension>gif</nonFilteredFileExtension>
|
||||||
|
<nonFilteredFileExtension>pdf</nonFilteredFileExtension>
|
||||||
|
<nonFilteredFileExtension>bcmap</nonFilteredFileExtension>
|
||||||
|
<nonFilteredFileExtension>cmap</nonFilteredFileExtension>
|
||||||
|
<nonFilteredFileExtension>cur</nonFilteredFileExtension>
|
||||||
|
<nonFilteredFileExtension>zip</nonFilteredFileExtension>
|
||||||
|
</nonFilteredFileExtensions>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
<resources>
|
||||||
|
<resource>
|
||||||
|
<directory>src/main/resources</directory>
|
||||||
|
<filtering>true</filtering>
|
||||||
|
</resource>
|
||||||
|
<resource>
|
||||||
|
<directory>src/main/java</directory>
|
||||||
|
<includes>
|
||||||
|
<include>**/*.xml</include>
|
||||||
|
<include>**/*.json</include>
|
||||||
|
<include>**/*.ftl</include>
|
||||||
|
</includes>
|
||||||
|
</resource>
|
||||||
|
</resources>
|
||||||
|
</build>
|
||||||
|
|
||||||
|
<distributionManagement>
|
||||||
|
<repository>
|
||||||
|
<id>jeecg</id>
|
||||||
|
<name>jeecg Repository</name>
|
||||||
|
<url>http://maven.jeecg.com:8090/nexus/content/repositories/jeecg</url>
|
||||||
|
</repository>
|
||||||
|
<snapshotRepository>
|
||||||
|
<id>jeecg-snapshots</id>
|
||||||
|
<name>jeecg Snapshot Repository</name>
|
||||||
|
<url>http://maven.jeecg.com:8090/nexus/content/repositories/snapshots/</url>
|
||||||
|
</snapshotRepository>
|
||||||
|
</distributionManagement>
|
||||||
|
|
||||||
|
<!-- 鐜 -->
|
||||||
|
<profiles>
|
||||||
|
<!-- 寮€鍙?-->
|
||||||
|
<profile>
|
||||||
|
<id>dev</id>
|
||||||
|
<activation>
|
||||||
|
<!--榛樿婵€娲婚厤缃-->
|
||||||
|
<activeByDefault>true</activeByDefault>
|
||||||
|
</activation>
|
||||||
|
<properties>
|
||||||
|
<!--褰撳墠鐜-->
|
||||||
|
<profile.name>dev</profile.name>
|
||||||
|
<!--Nacos鏈嶅姟鍦板潃-->
|
||||||
|
<config.server-addr>ghb-nacos:8848</config.server-addr>
|
||||||
|
<!--Nacos閰嶇疆涓績鍛藉悕绌洪棿,鐢ㄤ簬鏀寔澶氱幆澧?杩欓噷蹇呴』浣跨敤ID锛屼笉鑳戒娇鐢ㄥ悕绉?榛樿涓虹┖-->
|
||||||
|
<config.namespace>springboot3</config.namespace>
|
||||||
|
<!--Nacos閰嶇疆鍒嗙粍鍚嶇О-->
|
||||||
|
<config.group>DEFAULT_GROUP</config.group>
|
||||||
|
<!--Nacos鐢ㄦ埛鍚-->
|
||||||
|
<config.username></config.username>
|
||||||
|
<!--Nacos瀵嗙爜-->
|
||||||
|
<config.password></config.password>
|
||||||
|
</properties>
|
||||||
|
</profile>
|
||||||
|
<!-- 娴嬭瘯Nacos寮€鍚壌鏉冦€佽缃垎缁勫拰鍛藉悕绌洪棿
|
||||||
|
<profile>
|
||||||
|
<id>dev</id>
|
||||||
|
<properties>
|
||||||
|
<profile.name>dev</profile.name>
|
||||||
|
<config.server-addr>ghb-nacos:8848</config.server-addr>
|
||||||
|
<config.namespace>ac14ab82-51f8-4f0c-aa5b-25fb8384bfb6</config.namespace>
|
||||||
|
<config.group>JEECGDEV_GROUP</config.group>
|
||||||
|
<config.username>nacos</config.username>
|
||||||
|
<config.password>nacos</config.password>
|
||||||
|
</properties>
|
||||||
|
</profile> -->
|
||||||
|
<!-- 娴嬭瘯 -->
|
||||||
|
<profile>
|
||||||
|
<id>test</id>
|
||||||
|
<properties>
|
||||||
|
<!--褰撳墠鐜-->
|
||||||
|
<profile.name>test</profile.name>
|
||||||
|
<!--Nacos鏈嶅姟鍦板潃-->
|
||||||
|
<config.server-addr>ghb-nacos:8848</config.server-addr>
|
||||||
|
<!--Nacos閰嶇疆涓績鍛藉悕绌洪棿,鐢ㄤ簬鏀寔澶氱幆澧?杩欓噷蹇呴』浣跨敤ID锛屼笉鑳戒娇鐢ㄥ悕绉?榛樿涓虹┖-->
|
||||||
|
<config.namespace>springboot3</config.namespace>
|
||||||
|
<!--Nacos閰嶇疆鍒嗙粍鍚嶇О-->
|
||||||
|
<config.group>DEFAULT_GROUP</config.group>
|
||||||
|
<!--Nacos鐢ㄦ埛鍚-->
|
||||||
|
<config.username></config.username>
|
||||||
|
<!--Nacos瀵嗙爜-->
|
||||||
|
<config.password></config.password>
|
||||||
|
</properties>
|
||||||
|
</profile>
|
||||||
|
<!-- docker鎵撳寘鐢?-->
|
||||||
|
<profile>
|
||||||
|
<id>docker</id>
|
||||||
|
<properties>
|
||||||
|
<!--褰撳墠鐜-->
|
||||||
|
<profile.name>docker</profile.name>
|
||||||
|
<!--Nacos鏈嶅姟鍦板潃-->
|
||||||
|
<config.server-addr>ghb-nacos:8848</config.server-addr>
|
||||||
|
<!--Nacos閰嶇疆涓績鍛藉悕绌洪棿,鐢ㄤ簬鏀寔澶氱幆澧?杩欓噷蹇呴』浣跨敤ID锛屼笉鑳戒娇鐢ㄥ悕绉?榛樿涓虹┖-->
|
||||||
|
<config.namespace>springboot3</config.namespace>
|
||||||
|
<!--Nacos閰嶇疆鍒嗙粍鍚嶇О-->
|
||||||
|
<config.group>DEFAULT_GROUP</config.group>
|
||||||
|
<!--Nacos鐢ㄦ埛鍚-->
|
||||||
|
<config.username></config.username>
|
||||||
|
<!--Nacos瀵嗙爜-->
|
||||||
|
<config.password></config.password>
|
||||||
|
</properties>
|
||||||
|
</profile>
|
||||||
|
<!-- 鐢熶骇 -->
|
||||||
|
<profile>
|
||||||
|
<id>prod</id>
|
||||||
|
<properties>
|
||||||
|
<!--褰撳墠鐜-->
|
||||||
|
<profile.name>prod</profile.name>
|
||||||
|
<!--Nacos鏈嶅姟鍦板潃-->
|
||||||
|
<config.server-addr>ghb-nacos:8848</config.server-addr>
|
||||||
|
<!--Nacos閰嶇疆涓績鍛藉悕绌洪棿,鐢ㄤ簬鏀寔澶氱幆澧?杩欓噷蹇呴』浣跨敤ID锛屼笉鑳戒娇鐢ㄥ悕绉?榛樿涓虹┖-->
|
||||||
|
<config.namespace>springboot3</config.namespace>
|
||||||
|
<!--Nacos閰嶇疆鍒嗙粍鍚嶇О-->
|
||||||
|
<config.group>DEFAULT_GROUP</config.group>
|
||||||
|
<!--Nacos鐢ㄦ埛鍚-->
|
||||||
|
<config.username></config.username>
|
||||||
|
<!--Nacos瀵嗙爜-->
|
||||||
|
<config.password></config.password>
|
||||||
|
</properties>
|
||||||
|
</profile>
|
||||||
|
<!-- SpringCloud杩愯鐜 -->
|
||||||
|
<profile>
|
||||||
|
<id>SpringCloud</id>
|
||||||
|
<activation>
|
||||||
|
<!--榛樿婵€娲婚厤缃-->
|
||||||
|
<activeByDefault>false</activeByDefault>
|
||||||
|
</activation>
|
||||||
|
<modules>
|
||||||
|
<!-- 寰湇鍔℃ā鍧?-->
|
||||||
|
<module>ghb-server-cloud</module>
|
||||||
|
</modules>
|
||||||
|
</profile>
|
||||||
|
</profiles>
|
||||||
|
</project>
|
||||||
|
|
@ -0,0 +1,405 @@
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<parent>
|
||||||
|
<groupId>com.ghb</groupId>
|
||||||
|
<artifactId>test-base-parent</artifactId>
|
||||||
|
<version>3.9.2</version>
|
||||||
|
</parent>
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
<artifactId>test-base-core</artifactId>
|
||||||
|
|
||||||
|
<repositories>
|
||||||
|
<repository>
|
||||||
|
<id>aliyun</id>
|
||||||
|
<name>aliyun Repository</name>
|
||||||
|
<url>https://maven.aliyun.com/repository/public</url>
|
||||||
|
<snapshots>
|
||||||
|
<enabled>false</enabled>
|
||||||
|
</snapshots>
|
||||||
|
</repository>
|
||||||
|
<repository>
|
||||||
|
<id>jeecg</id>
|
||||||
|
<name>jeecg Repository</name>
|
||||||
|
<url>https://maven.jeecg.org/nexus/content/repositories/jeecg</url>
|
||||||
|
<snapshots>
|
||||||
|
<enabled>false</enabled>
|
||||||
|
</snapshots>
|
||||||
|
</repository>
|
||||||
|
<repository>
|
||||||
|
<id>jeecg-snapshots</id>
|
||||||
|
<name>jeecg-snapshots Repository</name>
|
||||||
|
<url>https://oss.sonatype.org/content/repositories/snapshots</url>
|
||||||
|
<releases>
|
||||||
|
<enabled>false</enabled>
|
||||||
|
</releases>
|
||||||
|
<snapshots>
|
||||||
|
<enabled>true</enabled>
|
||||||
|
</snapshots>
|
||||||
|
</repository>
|
||||||
|
</repositories>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<!--jeecg-tools-->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.jeecgframework.boot3</groupId>
|
||||||
|
<artifactId>jeecg-boot-common</artifactId>
|
||||||
|
<exclusions>
|
||||||
|
<exclusion>
|
||||||
|
<groupId>commons-logging</groupId>
|
||||||
|
<artifactId>commons-logging</artifactId>
|
||||||
|
</exclusion>
|
||||||
|
</exclusions>
|
||||||
|
</dependency>
|
||||||
|
<!--集成springmvc框架并实现自动配置 -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-web</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<!-- websocket -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-websocket</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-mail</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-aop</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-actuator</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<!--springboot2.3+ 需引入validation对应的包-->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-validation</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<!--springboot2.6+解决metrics端点不显示jvm信息的问题-->
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.micrometer</groupId>
|
||||||
|
<artifactId>micrometer-registry-prometheus</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- commons -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>commons-io</groupId>
|
||||||
|
<artifactId>commons-io</artifactId>
|
||||||
|
<version>${commons-io.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>commons-lang</groupId>
|
||||||
|
<artifactId>commons-lang</artifactId>
|
||||||
|
<version>${commons.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<!-- freemarker -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-freemarker</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- mybatis-plus -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.baomidou</groupId>
|
||||||
|
<artifactId>mybatis-plus-spring-boot3-starter</artifactId>
|
||||||
|
<version>${mybatis-plus.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.baomidou</groupId>
|
||||||
|
<artifactId>mybatis-plus-jsqlparser-4.9</artifactId>
|
||||||
|
<version>${mybatis-plus.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<!-- minidao -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.jeecgframework.boot3</groupId>
|
||||||
|
<artifactId>minidao-spring-boot-starter-jsqlparser-4.9</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- druid -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.alibaba</groupId>
|
||||||
|
<artifactId>druid-spring-boot-3-starter</artifactId>
|
||||||
|
<version>${druid.version}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- 动态数据源 -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.baomidou</groupId>
|
||||||
|
<artifactId>dynamic-datasource-spring-boot3-starter</artifactId>
|
||||||
|
<version>${dynamic-datasource-spring-boot-starter.version}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- 数据库驱动 -->
|
||||||
|
<!--mysql-->
|
||||||
|
<dependency>
|
||||||
|
<groupId>mysql</groupId>
|
||||||
|
<artifactId>mysql-connector-java</artifactId>
|
||||||
|
<version>${mysql-connector-java.version}</version>
|
||||||
|
<scope>runtime</scope>
|
||||||
|
</dependency>
|
||||||
|
<!-- sqlserver-->
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.microsoft.sqlserver</groupId>
|
||||||
|
<artifactId>mssql-jdbc</artifactId>
|
||||||
|
<version>${sqljdbc4.version}</version>
|
||||||
|
<scope>runtime</scope>
|
||||||
|
</dependency>
|
||||||
|
<!-- oracle驱动 -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.oracle</groupId>
|
||||||
|
<artifactId>ojdbc6</artifactId>
|
||||||
|
<version>${ojdbc6.version}</version>
|
||||||
|
<scope>runtime</scope>
|
||||||
|
</dependency>
|
||||||
|
<!-- postgresql驱动 -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.postgresql</groupId>
|
||||||
|
<artifactId>postgresql</artifactId>
|
||||||
|
<version>${postgresql.version}</version>
|
||||||
|
<scope>runtime</scope>
|
||||||
|
</dependency>
|
||||||
|
<!--人大金仓驱动 版本号V008R006C005B0013 -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.jeecgframework</groupId>
|
||||||
|
<artifactId>kingbase8</artifactId>
|
||||||
|
<version>${kingbase8.version}</version>
|
||||||
|
<scope>runtime</scope>
|
||||||
|
</dependency>
|
||||||
|
<!--达梦数据库驱动 版本号1-3-26-2023.07.26-197096-20046-ENT -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.dameng</groupId>
|
||||||
|
<artifactId>DmJdbcDriver18</artifactId>
|
||||||
|
<version>${dm8.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.dameng</groupId>
|
||||||
|
<artifactId>DmDialect-for-hibernate5.0</artifactId>
|
||||||
|
<version>${dm8.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<!-- Quartz定时任务 -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-quartz</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!--JWT-->
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.auth0</groupId>
|
||||||
|
<artifactId>java-jwt</artifactId>
|
||||||
|
<version>${java-jwt.version}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!--shiro-->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.shiro</groupId>
|
||||||
|
<artifactId>shiro-spring-boot-starter</artifactId>
|
||||||
|
<classifier>jakarta</classifier>
|
||||||
|
<version>${shiro.version}</version>
|
||||||
|
<exclusions>
|
||||||
|
<exclusion>
|
||||||
|
<groupId>org.apache.shiro</groupId>
|
||||||
|
<artifactId>shiro-spring</artifactId>
|
||||||
|
</exclusion>
|
||||||
|
</exclusions>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.shiro</groupId>
|
||||||
|
<artifactId>shiro-spring</artifactId>
|
||||||
|
<classifier>jakarta</classifier>
|
||||||
|
<version>${shiro.version}</version>
|
||||||
|
<!-- 排除仍使用了javax.servlet的依赖 -->
|
||||||
|
<exclusions>
|
||||||
|
<exclusion>
|
||||||
|
<groupId>org.apache.shiro</groupId>
|
||||||
|
<artifactId>shiro-core</artifactId>
|
||||||
|
</exclusion>
|
||||||
|
<exclusion>
|
||||||
|
<groupId>org.apache.shiro</groupId>
|
||||||
|
<artifactId>shiro-web</artifactId>
|
||||||
|
</exclusion>
|
||||||
|
</exclusions>
|
||||||
|
</dependency>
|
||||||
|
<!-- 引入适配jakarta的依赖包 -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.shiro</groupId>
|
||||||
|
<artifactId>shiro-core</artifactId>
|
||||||
|
<classifier>jakarta</classifier>
|
||||||
|
<version>${shiro.version}</version>
|
||||||
|
<exclusions>
|
||||||
|
<exclusion>
|
||||||
|
<groupId>commons-beanutils</groupId>
|
||||||
|
<artifactId>commons-beanutils</artifactId>
|
||||||
|
</exclusion>
|
||||||
|
</exclusions>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.shiro</groupId>
|
||||||
|
<artifactId>shiro-web</artifactId>
|
||||||
|
<classifier>jakarta</classifier>
|
||||||
|
<version>${shiro.version}</version>
|
||||||
|
<exclusions>
|
||||||
|
<exclusion>
|
||||||
|
<groupId>org.apache.shiro</groupId>
|
||||||
|
<artifactId>shiro-core</artifactId>
|
||||||
|
</exclusion>
|
||||||
|
</exclusions>
|
||||||
|
</dependency>
|
||||||
|
<!-- shiro-redis -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.crazycake</groupId>
|
||||||
|
<artifactId>shiro-redis</artifactId>
|
||||||
|
<version>${shiro-redis.version}</version>
|
||||||
|
<exclusions>
|
||||||
|
<exclusion>
|
||||||
|
<groupId>org.apache.shiro</groupId>
|
||||||
|
<artifactId>shiro-core</artifactId>
|
||||||
|
</exclusion>
|
||||||
|
<exclusion>
|
||||||
|
<artifactId>checkstyle</artifactId>
|
||||||
|
<groupId>com.puppycrawl.tools</groupId>
|
||||||
|
</exclusion>
|
||||||
|
</exclusions>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.github.xiaoymin</groupId>
|
||||||
|
<artifactId>knife4j-openapi3-ui</artifactId>
|
||||||
|
<version>${knife4j-spring-boot-starter.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springdoc</groupId>
|
||||||
|
<artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
|
||||||
|
<version>2.7.0</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- 代码生成器 -->
|
||||||
|
<!-- 如下载失败,请参考此文档 https://help.jeecg.com/java/setup/maven.html -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.jeecgframework.boot</groupId>
|
||||||
|
<artifactId>codegenerate</artifactId>
|
||||||
|
<version>${codegenerate.version}</version>
|
||||||
|
<exclusions>
|
||||||
|
<exclusion>
|
||||||
|
<artifactId>commons-io</artifactId>
|
||||||
|
<groupId>commons-io</groupId>
|
||||||
|
</exclusion>
|
||||||
|
<exclusion>
|
||||||
|
<artifactId>mysql-connector-java</artifactId>
|
||||||
|
<groupId>mysql</groupId>
|
||||||
|
</exclusion>
|
||||||
|
</exclusions>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- AutoPoi Excel工具类-->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.jeecgframework</groupId>
|
||||||
|
<artifactId>autopoi-spring-boot-3-starter</artifactId>
|
||||||
|
<exclusions>
|
||||||
|
<exclusion>
|
||||||
|
<groupId>org.jeecgframework.jimureport</groupId>
|
||||||
|
<artifactId>jimureport-spring-boot-starter</artifactId>
|
||||||
|
</exclusion>
|
||||||
|
</exclusions>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>xerces</groupId>
|
||||||
|
<artifactId>xercesImpl</artifactId>
|
||||||
|
<version>2.12.2</version>
|
||||||
|
<optional>true</optional>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- minio文件存储服务 -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.minio</groupId>
|
||||||
|
<artifactId>minio</artifactId>
|
||||||
|
<exclusions>
|
||||||
|
<exclusion>
|
||||||
|
<artifactId>checker-qual</artifactId>
|
||||||
|
<groupId>org.checkerframework</groupId>
|
||||||
|
</exclusion>
|
||||||
|
<exclusion>
|
||||||
|
<groupId>com.google.errorprone</groupId>
|
||||||
|
<artifactId>error_prone_annotations</artifactId>
|
||||||
|
</exclusion>
|
||||||
|
<exclusion>
|
||||||
|
<groupId>org.apache.commons</groupId>
|
||||||
|
<artifactId>commons-compress</artifactId>
|
||||||
|
</exclusion>
|
||||||
|
</exclusions>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- 阿里云短信 -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.aliyun</groupId>
|
||||||
|
<artifactId>aliyun-java-sdk-dysmsapi</artifactId>
|
||||||
|
<version>${aliyun-java-sdk-dysmsapi.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<!-- aliyun oss -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.aliyun.oss</groupId>
|
||||||
|
<artifactId>aliyun-sdk-oss</artifactId>
|
||||||
|
<version>${aliyun.oss.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<!-- 第三方登录 -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.xkcoding.justauth</groupId>
|
||||||
|
<artifactId>justauth-spring-boot-starter</artifactId>
|
||||||
|
<exclusions>
|
||||||
|
<exclusion>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-autoconfigure</artifactId>
|
||||||
|
</exclusion>
|
||||||
|
<exclusion>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-configuration-processor</artifactId>
|
||||||
|
</exclusion>
|
||||||
|
</exclusions>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.squareup.okhttp3</groupId>
|
||||||
|
<artifactId>okhttp</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<!-- 解决okhttp引用了kotlin,应用启动有警告日志问题 -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.fasterxml.jackson.module</groupId>
|
||||||
|
<artifactId>jackson-module-kotlin</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>commons-fileupload</groupId>
|
||||||
|
<artifactId>commons-fileupload</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<!--加载hutool-->
|
||||||
|
<dependency>
|
||||||
|
<groupId>cn.hutool</groupId>
|
||||||
|
<artifactId>hutool-core</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>cn.hutool</groupId>
|
||||||
|
<artifactId>hutool-crypto</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<!-- chatgpt -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.jeecgframework.boot3</groupId>
|
||||||
|
<artifactId>jeecg-boot-starter-ai</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<!-- 腾讯云 -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.tencentcloudapi</groupId>
|
||||||
|
<artifactId>tencentcloud-sdk-java-sms</artifactId>
|
||||||
|
<version>${tencentcloud-sdk-java-sms.version}</version>
|
||||||
|
<exclusions>
|
||||||
|
<exclusion>
|
||||||
|
<groupId>javax.xml.bind</groupId>
|
||||||
|
<artifactId>jaxb-api</artifactId>
|
||||||
|
</exclusion>
|
||||||
|
<exclusion>
|
||||||
|
<groupId>com.squareup.okio</groupId>
|
||||||
|
<artifactId>okio</artifactId>
|
||||||
|
</exclusion>
|
||||||
|
</exclusions>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
</project>
|
||||||
|
|
@ -0,0 +1,145 @@
|
||||||
|
package com.ghb.base.common.api;
|
||||||
|
|
||||||
|
import com.ghb.base.common.system.vo.*;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 通用api
|
||||||
|
* @author: Ghb-boot
|
||||||
|
*/
|
||||||
|
public interface CommonAPI {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 1查询用户角色信息
|
||||||
|
* @param username
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
Set<String> queryUserRoles(String username);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 1查询用户角色信息
|
||||||
|
* @param userId
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
Set<String> queryUserRolesById(String userId);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 2查询用户权限信息
|
||||||
|
* @param userId
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
Set<String> queryUserAuths(String userId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 3根据 id 查询数据库中存储的 DynamicDataSourceModel
|
||||||
|
*
|
||||||
|
* @param dbSourceId
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
DynamicDataSourceModel getDynamicDbSourceById(String dbSourceId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 4根据 code 查询数据库中存储的 DynamicDataSourceModel
|
||||||
|
*
|
||||||
|
* @param dbSourceCode
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
DynamicDataSourceModel getDynamicDbSourceByCode(String dbSourceCode);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 5根据用户账号查询用户信息
|
||||||
|
* @param username
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public LoginUser getUserByName(String username);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 5根据用户账号查询用户Id
|
||||||
|
* @param username
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public String getUserIdByName(String username);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 6字典表的 翻译
|
||||||
|
* @param table
|
||||||
|
* @param text
|
||||||
|
* @param code
|
||||||
|
* @param key
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
String translateDictFromTable(String table, String text, String code, String key);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 7普通字典的翻译
|
||||||
|
* @param code
|
||||||
|
* @param key
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
String translateDict(String code, String key);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 8查询数据权限
|
||||||
|
* @param component 组件
|
||||||
|
* @param username 用户名
|
||||||
|
* @param requestPath 前段请求地址
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
List<SysPermissionDataRuleModel> queryPermissionDataRule(String component, String requestPath, String username);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 9查询用户信息
|
||||||
|
* @param username
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
SysUserCacheInfo getCacheUser(String username);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 10获取数据字典
|
||||||
|
* @param code
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public List<DictModel> queryDictItemsByCode(String code);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取有效的数据字典项
|
||||||
|
* @param code
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public List<DictModel> queryEnableDictItemsByCode(String code);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 13获取表数据字典
|
||||||
|
* @param tableFilterSql
|
||||||
|
* @param text
|
||||||
|
* @param code
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
List<DictModel> queryTableDictItemsByCode(String tableFilterSql, String text, String code);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 14 普通字典的翻译,根据多个dictCode和多条数据,多个以逗号分割
|
||||||
|
* @param dictCodes 例如:user_status,sex
|
||||||
|
* @param keys 例如:1,2,0
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
Map<String, List<DictModel>> translateManyDict(String dictCodes, String keys);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 15 字典表的 翻译,可批量
|
||||||
|
* @param table
|
||||||
|
* @param text
|
||||||
|
* @param code
|
||||||
|
* @param keys 多个用逗号分割
|
||||||
|
* @param dataSource 数据源
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
List<DictModel> translateDictFromTableByKeys(String table, String text, String code, String keys, String dataSource);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,42 @@
|
||||||
|
package com.ghb.base.common.api.dto;
|
||||||
|
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 调用AI流程入参
|
||||||
|
* for [QQYUN-13634]在baseapi里面封装方法,方便其他模块调用
|
||||||
|
* @author chenrui
|
||||||
|
* @date 2025/9/2 14:11
|
||||||
|
*/
|
||||||
|
@Builder
|
||||||
|
@AllArgsConstructor
|
||||||
|
@NoArgsConstructor
|
||||||
|
@Data
|
||||||
|
public class AiragFlowDTO implements Serializable {
|
||||||
|
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 7431775881170684867L;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 流程id
|
||||||
|
*/
|
||||||
|
private String flowId;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 输入参数
|
||||||
|
*/
|
||||||
|
private Map<String, Object> inputParams;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否流式返回
|
||||||
|
*/
|
||||||
|
private boolean isStream;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,48 @@
|
||||||
|
package com.ghb.base.common.api.dto;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 流程审批意见DTO
|
||||||
|
* @author scott
|
||||||
|
* @date 2025-01-29
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class ApprovalCommentDTO implements Serializable {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 任务ID
|
||||||
|
*/
|
||||||
|
private String taskId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 任务名称
|
||||||
|
*/
|
||||||
|
private String taskName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 审批人ID
|
||||||
|
*/
|
||||||
|
private String approverId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 审批人姓名
|
||||||
|
*/
|
||||||
|
private String approverName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 审批意见
|
||||||
|
*/
|
||||||
|
private String approvalComment;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 审批时间
|
||||||
|
*/
|
||||||
|
private Date approvalTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -0,0 +1,38 @@
|
||||||
|
package com.ghb.base.common.api.dto;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Author taoYan
|
||||||
|
* @Date 2022/7/26 14:44
|
||||||
|
**/
|
||||||
|
@Data
|
||||||
|
public class DataLogDTO {
|
||||||
|
|
||||||
|
private String tableName;
|
||||||
|
|
||||||
|
private String dataId;
|
||||||
|
|
||||||
|
private String content;
|
||||||
|
|
||||||
|
private String type;
|
||||||
|
|
||||||
|
private String createName;
|
||||||
|
|
||||||
|
public DataLogDTO(){
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public DataLogDTO(String tableName, String dataId, String content, String type) {
|
||||||
|
this.tableName = tableName;
|
||||||
|
this.dataId = dataId;
|
||||||
|
this.content = content;
|
||||||
|
this.type = type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public DataLogDTO(String tableName, String dataId, String type) {
|
||||||
|
this.tableName = tableName;
|
||||||
|
this.dataId = dataId;
|
||||||
|
this.type = type;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,31 @@
|
||||||
|
package com.ghb.base.common.api.dto;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import jakarta.servlet.http.HttpServletResponse;
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 文件下载
|
||||||
|
* cloud api 用到的接口传输对象
|
||||||
|
* @author: Ghb-boot
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class FileDownDTO implements Serializable {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 6749126258686446019L;
|
||||||
|
|
||||||
|
private String filePath;
|
||||||
|
private String uploadpath;
|
||||||
|
private String uploadType;
|
||||||
|
private HttpServletResponse response;
|
||||||
|
|
||||||
|
public FileDownDTO(){}
|
||||||
|
|
||||||
|
public FileDownDTO(String filePath, String uploadpath, String uploadType,HttpServletResponse response){
|
||||||
|
this.filePath = filePath;
|
||||||
|
this.uploadpath = uploadpath;
|
||||||
|
this.uploadType = uploadType;
|
||||||
|
this.response = response;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,56 @@
|
||||||
|
package com.ghb.base.common.api.dto;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 文件上传
|
||||||
|
* cloud api 用到的接口传输对象
|
||||||
|
* @author: Ghb-boot
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class FileUploadDTO implements Serializable {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = -4111953058578954386L;
|
||||||
|
|
||||||
|
private MultipartFile file;
|
||||||
|
|
||||||
|
private String bizPath;
|
||||||
|
|
||||||
|
private String uploadType;
|
||||||
|
|
||||||
|
private String customBucket;
|
||||||
|
|
||||||
|
public FileUploadDTO(){
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 简单上传 构造器1
|
||||||
|
* @param file
|
||||||
|
* @param bizPath
|
||||||
|
* @param uploadType
|
||||||
|
*/
|
||||||
|
public FileUploadDTO(MultipartFile file,String bizPath,String uploadType){
|
||||||
|
this.file = file;
|
||||||
|
this.bizPath = bizPath;
|
||||||
|
this.uploadType = uploadType;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 申明桶 文件上传 构造器2
|
||||||
|
* @param file
|
||||||
|
* @param bizPath
|
||||||
|
* @param uploadType
|
||||||
|
* @param customBucket
|
||||||
|
*/
|
||||||
|
public FileUploadDTO(MultipartFile file,String bizPath,String uploadType,String customBucket){
|
||||||
|
this.file = file;
|
||||||
|
this.bizPath = bizPath;
|
||||||
|
this.uploadType = uploadType;
|
||||||
|
this.customBucket = customBucket;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,80 @@
|
||||||
|
package com.ghb.base.common.api.dto;
|
||||||
|
import lombok.Data;
|
||||||
|
import com.ghb.base.common.aspect.annotation.Dict;
|
||||||
|
import com.ghb.base.common.system.vo.LoginUser;
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 日志对象
|
||||||
|
* cloud api 用到的接口传输对象
|
||||||
|
* @author: Ghb-boot
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class LogDTO implements Serializable {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 8482720462943906924L;
|
||||||
|
|
||||||
|
/**内容*/
|
||||||
|
private String logContent;
|
||||||
|
|
||||||
|
/**日志类型(0:操作日志;1:登录日志;2:定时任务) */
|
||||||
|
private Integer logType;
|
||||||
|
|
||||||
|
/**操作类型(1:添加;2:修改;3:删除;) */
|
||||||
|
private Integer operateType;
|
||||||
|
|
||||||
|
/**登录用户 */
|
||||||
|
private LoginUser loginUser;
|
||||||
|
|
||||||
|
private String id;
|
||||||
|
private String createBy;
|
||||||
|
private Date createTime;
|
||||||
|
private Long costTime;
|
||||||
|
private String ip;
|
||||||
|
|
||||||
|
/**请求参数 */
|
||||||
|
private String requestParam;
|
||||||
|
|
||||||
|
/**请求类型*/
|
||||||
|
private String requestType;
|
||||||
|
|
||||||
|
/**请求路径*/
|
||||||
|
private String requestUrl;
|
||||||
|
|
||||||
|
/**请求方法 */
|
||||||
|
private String method;
|
||||||
|
|
||||||
|
/**操作人用户名称*/
|
||||||
|
private String username;
|
||||||
|
|
||||||
|
/**操作人用户账户*/
|
||||||
|
private String userid;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 租户ID
|
||||||
|
*/
|
||||||
|
private Integer tenantId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 客户终端类型 pc:电脑端 app:手机端 h5:移动网页端
|
||||||
|
*/
|
||||||
|
private String clientType;
|
||||||
|
|
||||||
|
public LogDTO(){
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public LogDTO(String logContent, Integer logType, Integer operatetype){
|
||||||
|
this.logContent = logContent;
|
||||||
|
this.logType = logType;
|
||||||
|
this.operateType = operatetype;
|
||||||
|
}
|
||||||
|
|
||||||
|
public LogDTO(String logContent, Integer logType, Integer operatetype, LoginUser loginUser){
|
||||||
|
this.logContent = logContent;
|
||||||
|
this.logType = logType;
|
||||||
|
this.operateType = operatetype;
|
||||||
|
this.loginUser = loginUser;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,47 @@
|
||||||
|
package com.ghb.base.common.api.dto;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* online 拦截器权限判断
|
||||||
|
* cloud api 用到的接口传输对象
|
||||||
|
* @author: Ghb-boot
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class OnlineAuthDTO implements Serializable {
|
||||||
|
private static final long serialVersionUID = 1771827545416418203L;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户名
|
||||||
|
*/
|
||||||
|
private String username;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 可能的请求地址
|
||||||
|
*/
|
||||||
|
private List<String> possibleUrl;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* online开发的菜单地址
|
||||||
|
*/
|
||||||
|
private String onlineFormUrl;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* online工单的地址
|
||||||
|
*/
|
||||||
|
private String onlineWorkOrderUrl;
|
||||||
|
|
||||||
|
public OnlineAuthDTO(){
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public OnlineAuthDTO(String username, List<String> possibleUrl, String onlineFormUrl){
|
||||||
|
this.username = username;
|
||||||
|
this.possibleUrl = possibleUrl;
|
||||||
|
this.onlineFormUrl = onlineFormUrl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,55 @@
|
||||||
|
package com.ghb.base.common.api.dto;
|
||||||
|
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 移动端消息推送
|
||||||
|
* @author liusq
|
||||||
|
* @date 2025/11/12 14:11
|
||||||
|
*/
|
||||||
|
@Builder
|
||||||
|
@AllArgsConstructor
|
||||||
|
@NoArgsConstructor
|
||||||
|
@Data
|
||||||
|
public class PushMessageDTO implements Serializable {
|
||||||
|
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 7431775881170684867L;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 消息标题
|
||||||
|
*/
|
||||||
|
private String title;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 消息内容
|
||||||
|
*/
|
||||||
|
private String content;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 推送形式:all:全推送 single:单用户推送
|
||||||
|
*/
|
||||||
|
private String pushType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户名usernameList
|
||||||
|
*/
|
||||||
|
List<String> usernames;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户名idList
|
||||||
|
*/
|
||||||
|
List<String> userIds;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 消息附加参数
|
||||||
|
*/
|
||||||
|
Map<String,Object> payload;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,46 @@
|
||||||
|
package com.ghb.base.common.api.dto.message;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 带业务参数的消息
|
||||||
|
*
|
||||||
|
* @author: taoyan
|
||||||
|
* @date: 2022/8/17
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class BusMessageDTO extends MessageDTO implements Serializable {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 9104793287983367669L;
|
||||||
|
/**
|
||||||
|
* 业务类型
|
||||||
|
*/
|
||||||
|
private String busType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 业务id
|
||||||
|
*/
|
||||||
|
private String busId;
|
||||||
|
|
||||||
|
public BusMessageDTO(){
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构造 带业务参数的消息
|
||||||
|
* @param fromUser
|
||||||
|
* @param toUser
|
||||||
|
* @param title
|
||||||
|
* @param msgContent
|
||||||
|
* @param msgCategory
|
||||||
|
* @param busType
|
||||||
|
* @param busId
|
||||||
|
*/
|
||||||
|
public BusMessageDTO(String fromUser, String toUser, String title, String msgContent, String msgCategory, String busType, String busId){
|
||||||
|
super(fromUser, toUser, title, msgContent, msgCategory);
|
||||||
|
this.busId = busId;
|
||||||
|
this.busType = busType;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,46 @@
|
||||||
|
package com.ghb.base.common.api.dto.message;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 带业务参数的模板消息
|
||||||
|
* @author: Ghb-boot
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class BusTemplateMessageDTO extends TemplateMessageDTO implements Serializable {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = -4277810906346929459L;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 业务类型
|
||||||
|
*/
|
||||||
|
private String busType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 业务id
|
||||||
|
*/
|
||||||
|
private String busId;
|
||||||
|
|
||||||
|
public BusTemplateMessageDTO(){
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构造 带业务参数的模板消息
|
||||||
|
* @param fromUser
|
||||||
|
* @param toUser
|
||||||
|
* @param title
|
||||||
|
* @param templateParam
|
||||||
|
* @param templateCode
|
||||||
|
* @param busType
|
||||||
|
* @param busId
|
||||||
|
*/
|
||||||
|
public BusTemplateMessageDTO(String fromUser, String toUser, String title, Map<String, String> templateParam, String templateCode, String busType, String busId){
|
||||||
|
super(fromUser, toUser, title, templateParam, templateCode);
|
||||||
|
this.busId = busId;
|
||||||
|
this.busType = busType;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,134 @@
|
||||||
|
package com.ghb.base.common.api.dto.message;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
import com.ghb.base.common.constant.CommonConstant;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 普通消息
|
||||||
|
* @author: Ghb-boot
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class MessageDTO implements Serializable {
|
||||||
|
private static final long serialVersionUID = -5690444483968058442L;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 发送人(用户登录账户)
|
||||||
|
*/
|
||||||
|
protected String fromUser;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 发送给(用户登录账户)
|
||||||
|
*/
|
||||||
|
protected String toUser;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 发送给所有人
|
||||||
|
*/
|
||||||
|
protected Boolean toAll;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 消息主题
|
||||||
|
*/
|
||||||
|
protected String title;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 消息内容
|
||||||
|
*/
|
||||||
|
protected String content;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 消息类型 1:消息 2:系统消息
|
||||||
|
*/
|
||||||
|
protected String category;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 消息类型:com.ghb.base.common.constant.enums.MessageTypeEnum
|
||||||
|
* XT("system", "系统消息")
|
||||||
|
* YJ("email", "邮件消息")
|
||||||
|
* DD("dingtalk", "钉钉消息")
|
||||||
|
* QYWX("wechat_enterprise", "企业微信")
|
||||||
|
*/
|
||||||
|
protected String type;
|
||||||
|
|
||||||
|
|
||||||
|
//---【推送模板相关参数】-------------------------------------------------------------
|
||||||
|
/**
|
||||||
|
* 是否发送Markdown格式的消息
|
||||||
|
*/
|
||||||
|
protected boolean isMarkdown;
|
||||||
|
/**
|
||||||
|
* 模板消息对应的模板编码
|
||||||
|
*/
|
||||||
|
protected String templateCode;
|
||||||
|
/**
|
||||||
|
* 解析模板内容 对应的数据
|
||||||
|
*/
|
||||||
|
protected Map<String, Object> data;
|
||||||
|
//---【推送模板相关参数】-------------------------------------------------------------
|
||||||
|
|
||||||
|
//---【邮件相关参数】-------------------------------------------------------------
|
||||||
|
/**
|
||||||
|
* 邮件抄送人
|
||||||
|
*/
|
||||||
|
private String copyToUser;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 邮件推送地址
|
||||||
|
*/
|
||||||
|
protected Set<String> toEmailList;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 邮件抄送地址
|
||||||
|
*/
|
||||||
|
protected Set<String> ccEmailList;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否为定时任务推送email
|
||||||
|
*/
|
||||||
|
private Boolean isTimeJob = false;
|
||||||
|
|
||||||
|
//---【邮件相关参数】-------------------------------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 枚举:com.ghb.base.common.constant.enums.NoticeTypeEnum
|
||||||
|
* 通知类型(system:系统消息、file:知识库、flow:流程、plan:日程计划、meeting:会议)
|
||||||
|
*/
|
||||||
|
private String noticeType;
|
||||||
|
|
||||||
|
public MessageDTO(){
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构造器1 系统消息
|
||||||
|
*/
|
||||||
|
public MessageDTO(String fromUser,String toUser,String title, String content){
|
||||||
|
this.fromUser = fromUser;
|
||||||
|
this.toUser = toUser;
|
||||||
|
this.title = title;
|
||||||
|
this.content = content;
|
||||||
|
//默认 都是2系统消息
|
||||||
|
this.category = CommonConstant.MSG_CATEGORY_2;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构造器2 支持设置category 1:消息 2:系统消息
|
||||||
|
*/
|
||||||
|
public MessageDTO(String fromUser,String toUser,String title, String content, String category){
|
||||||
|
this.fromUser = fromUser;
|
||||||
|
this.toUser = toUser;
|
||||||
|
this.title = title;
|
||||||
|
this.content = content;
|
||||||
|
this.category = category;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isMarkdown() {
|
||||||
|
return this.isMarkdown;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setIsMarkdown(boolean isMarkdown) {
|
||||||
|
this.isMarkdown = isMarkdown;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,38 @@
|
||||||
|
package com.ghb.base.common.api.dto.message;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 消息模板dto
|
||||||
|
* @author: Ghb-boot
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class TemplateDTO implements Serializable {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 5848247133907528650L;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 模板编码
|
||||||
|
*/
|
||||||
|
protected String templateCode;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 模板参数
|
||||||
|
*/
|
||||||
|
protected Map<String, String> templateParam;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构造器 通过设置模板参数和模板编码 作为参数获取消息内容
|
||||||
|
*/
|
||||||
|
public TemplateDTO(String templateCode, Map<String, String> templateParam){
|
||||||
|
this.templateCode = templateCode;
|
||||||
|
this.templateParam = templateParam;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TemplateDTO(){
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,49 @@
|
||||||
|
package com.ghb.base.common.api.dto.message;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 模板消息
|
||||||
|
* @author: Ghb-boot
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class TemplateMessageDTO extends TemplateDTO implements Serializable {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 411137565170647585L;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 发送人(用户登录账户)
|
||||||
|
*/
|
||||||
|
protected String fromUser;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 发送给(用户登录账户)
|
||||||
|
*/
|
||||||
|
protected String toUser;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 消息主题
|
||||||
|
*/
|
||||||
|
protected String title;
|
||||||
|
|
||||||
|
|
||||||
|
public TemplateMessageDTO(){
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构造器1 发模板消息用
|
||||||
|
*/
|
||||||
|
public TemplateMessageDTO(String fromUser, String toUser,String title, Map<String, String> templateParam, String templateCode){
|
||||||
|
super(templateCode, templateParam);
|
||||||
|
this.fromUser = fromUser;
|
||||||
|
this.toUser = toUser;
|
||||||
|
this.title = title;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,177 @@
|
||||||
|
package com.ghb.base.common.api.vo;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import lombok.Data;
|
||||||
|
import com.ghb.base.common.constant.CommonConstant;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 接口返回数据格式
|
||||||
|
* @author scott
|
||||||
|
* @email Ghbos@163.com
|
||||||
|
* @date 2019年1月19日
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@Schema(description="接口返回对象")
|
||||||
|
public class Result<T> implements Serializable {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 成功标志
|
||||||
|
*/
|
||||||
|
@Schema(description = "成功标志")
|
||||||
|
private boolean success = true;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 返回处理消息
|
||||||
|
*/
|
||||||
|
@Schema(description = "返回处理消息")
|
||||||
|
private String message = "";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 返回代码
|
||||||
|
*/
|
||||||
|
@Schema(description = "返回代码")
|
||||||
|
private Integer code = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 返回数据对象 data
|
||||||
|
*/
|
||||||
|
@Schema(description = "返回数据对象")
|
||||||
|
private T result;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 时间戳
|
||||||
|
*/
|
||||||
|
@Schema(description = "时间戳")
|
||||||
|
private long timestamp = System.currentTimeMillis();
|
||||||
|
|
||||||
|
public Result() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 兼容VUE3版token失效不跳转登录页面
|
||||||
|
* @param code
|
||||||
|
* @param message
|
||||||
|
*/
|
||||||
|
public Result(Integer code, String message) {
|
||||||
|
this.code = code;
|
||||||
|
this.message = message;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Result<T> success(String message) {
|
||||||
|
this.message = message;
|
||||||
|
this.code = CommonConstant.SC_OK_200;
|
||||||
|
this.success = true;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static<T> Result<T> ok() {
|
||||||
|
Result<T> r = new Result<T>();
|
||||||
|
r.setSuccess(true);
|
||||||
|
r.setCode(CommonConstant.SC_OK_200);
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static<T> Result<T> ok(String msg) {
|
||||||
|
Result<T> r = new Result<T>();
|
||||||
|
r.setSuccess(true);
|
||||||
|
r.setCode(CommonConstant.SC_OK_200);
|
||||||
|
//Result OK(String msg)方法会造成兼容性问题 issues/I4IP3D
|
||||||
|
r.setResult((T) msg);
|
||||||
|
r.setMessage(msg);
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static<T> Result<T> ok(T data) {
|
||||||
|
Result<T> r = new Result<T>();
|
||||||
|
r.setSuccess(true);
|
||||||
|
r.setCode(CommonConstant.SC_OK_200);
|
||||||
|
r.setResult(data);
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static<T> Result<T> OK() {
|
||||||
|
Result<T> r = new Result<T>();
|
||||||
|
r.setSuccess(true);
|
||||||
|
r.setCode(CommonConstant.SC_OK_200);
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 此方法是为了兼容升级所创建
|
||||||
|
*
|
||||||
|
* @param msg
|
||||||
|
* @param <T>
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static<T> Result<T> OK(String msg) {
|
||||||
|
Result<T> r = new Result<T>();
|
||||||
|
r.setSuccess(true);
|
||||||
|
r.setCode(CommonConstant.SC_OK_200);
|
||||||
|
r.setMessage(msg);
|
||||||
|
//Result OK(String msg)方法会造成兼容性问题 issues/I4IP3D
|
||||||
|
r.setResult((T) msg);
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static<T> Result<T> OK(T data) {
|
||||||
|
Result<T> r = new Result<T>();
|
||||||
|
r.setSuccess(true);
|
||||||
|
r.setCode(CommonConstant.SC_OK_200);
|
||||||
|
r.setResult(data);
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static<T> Result<T> OK(String msg, T data) {
|
||||||
|
Result<T> r = new Result<T>();
|
||||||
|
r.setSuccess(true);
|
||||||
|
r.setCode(CommonConstant.SC_OK_200);
|
||||||
|
r.setMessage(msg);
|
||||||
|
r.setResult(data);
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static<T> Result<T> error(String msg, T data) {
|
||||||
|
Result<T> r = new Result<T>();
|
||||||
|
r.setSuccess(false);
|
||||||
|
r.setCode(CommonConstant.SC_INTERNAL_SERVER_ERROR_500);
|
||||||
|
r.setMessage(msg);
|
||||||
|
r.setResult(data);
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static<T> Result<T> error(String msg) {
|
||||||
|
return error(CommonConstant.SC_INTERNAL_SERVER_ERROR_500, msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static<T> Result<T> error(int code, String msg) {
|
||||||
|
Result<T> r = new Result<T>();
|
||||||
|
r.setCode(code);
|
||||||
|
r.setMessage(msg);
|
||||||
|
r.setSuccess(false);
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Result<T> error500(String message) {
|
||||||
|
this.message = message;
|
||||||
|
this.code = CommonConstant.SC_INTERNAL_SERVER_ERROR_500;
|
||||||
|
this.success = false;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 无权限访问返回结果
|
||||||
|
*/
|
||||||
|
public static<T> Result<T> noauth(String msg) {
|
||||||
|
return error(CommonConstant.SC_Ghb_NO_AUTHZ, msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
@JsonIgnore
|
||||||
|
private String onlTable;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,258 @@
|
||||||
|
package com.ghb.base.common.aspect;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson.JSONObject;
|
||||||
|
import com.alibaba.fastjson.serializer.PropertyFilter;
|
||||||
|
import org.apache.shiro.SecurityUtils;
|
||||||
|
import org.aspectj.lang.JoinPoint;
|
||||||
|
import org.aspectj.lang.ProceedingJoinPoint;
|
||||||
|
import org.aspectj.lang.annotation.Around;
|
||||||
|
import org.aspectj.lang.annotation.Aspect;
|
||||||
|
import org.aspectj.lang.annotation.Pointcut;
|
||||||
|
import org.aspectj.lang.reflect.MethodSignature;
|
||||||
|
import com.ghb.base.common.api.dto.LogDTO;
|
||||||
|
import com.ghb.base.common.api.vo.Result;
|
||||||
|
import com.ghb.base.common.aspect.annotation.AutoLog;
|
||||||
|
import com.ghb.base.common.constant.CommonConstant;
|
||||||
|
import com.ghb.base.common.constant.enums.ModuleType;
|
||||||
|
import com.ghb.base.common.constant.enums.OperateTypeEnum;
|
||||||
|
import com.ghb.base.modules.base.service.BaseCommonService;
|
||||||
|
import com.ghb.base.common.system.vo.LoginUser;
|
||||||
|
import com.ghb.base.common.util.IpUtils;
|
||||||
|
import com.ghb.base.common.util.SpringContextUtils;
|
||||||
|
import com.ghb.base.common.util.oConvertUtils;
|
||||||
|
import org.springframework.core.StandardReflectionParameterNameDiscoverer;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
import org.springframework.validation.BindingResult;
|
||||||
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
|
import jakarta.annotation.Resource;
|
||||||
|
import jakarta.servlet.ServletRequest;
|
||||||
|
import jakarta.servlet.ServletResponse;
|
||||||
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 系统日志,切面处理类
|
||||||
|
*
|
||||||
|
* @Author scott
|
||||||
|
* @email Ghbos@163.com
|
||||||
|
* @Date 2018年1月14日
|
||||||
|
*/
|
||||||
|
@Aspect
|
||||||
|
@Component
|
||||||
|
public class AutoLogAspect {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private BaseCommonService baseCommonService;
|
||||||
|
|
||||||
|
@Pointcut("@annotation(com.ghb.base.common.aspect.annotation.AutoLog)")
|
||||||
|
public void logPointCut() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Around("logPointCut()")
|
||||||
|
public Object around(ProceedingJoinPoint point) throws Throwable {
|
||||||
|
long beginTime = System.currentTimeMillis();
|
||||||
|
//执行方法
|
||||||
|
Object result = point.proceed();
|
||||||
|
//执行时长(毫秒)
|
||||||
|
long time = System.currentTimeMillis() - beginTime;
|
||||||
|
|
||||||
|
//保存日志
|
||||||
|
saveSysLog(point, time, result);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void saveSysLog(ProceedingJoinPoint joinPoint, long time, Object obj) {
|
||||||
|
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
|
||||||
|
Method method = signature.getMethod();
|
||||||
|
|
||||||
|
LogDTO dto = new LogDTO();
|
||||||
|
AutoLog syslog = method.getAnnotation(AutoLog.class);
|
||||||
|
if(syslog != null){
|
||||||
|
//update-begin-author:taoyan date:
|
||||||
|
String content = syslog.value();
|
||||||
|
if(syslog.module()== ModuleType.ONLINE){
|
||||||
|
content = getOnlineLogContent(obj, content);
|
||||||
|
}
|
||||||
|
//注解上的描述,操作日志内容
|
||||||
|
dto.setLogType(syslog.logType());
|
||||||
|
dto.setLogContent(content);
|
||||||
|
}
|
||||||
|
|
||||||
|
//请求的方法名
|
||||||
|
String className = joinPoint.getTarget().getClass().getName();
|
||||||
|
String methodName = signature.getName();
|
||||||
|
dto.setMethod(className + "." + methodName + "()");
|
||||||
|
|
||||||
|
|
||||||
|
//设置操作类型
|
||||||
|
if (CommonConstant.LOG_TYPE_2 == dto.getLogType()) {
|
||||||
|
dto.setOperateType(getOperateType(methodName, syslog.operateType()));
|
||||||
|
}
|
||||||
|
|
||||||
|
//获取request
|
||||||
|
HttpServletRequest request = SpringContextUtils.getHttpServletRequest();
|
||||||
|
//请求的参数
|
||||||
|
dto.setRequestParam(getReqestParams(request,joinPoint));
|
||||||
|
//设置IP地址
|
||||||
|
dto.setIp(IpUtils.getIpAddr(request));
|
||||||
|
//获取登录用户信息
|
||||||
|
LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
|
||||||
|
if(sysUser!=null){
|
||||||
|
dto.setUserid(sysUser.getUsername());
|
||||||
|
dto.setUsername(sysUser.getRealname());
|
||||||
|
|
||||||
|
}
|
||||||
|
//耗时
|
||||||
|
dto.setCostTime(time);
|
||||||
|
dto.setCreateTime(new Date());
|
||||||
|
//保存系统日志
|
||||||
|
baseCommonService.addLog(dto);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取操作类型
|
||||||
|
*/
|
||||||
|
private int getOperateType(String methodName,int operateType) {
|
||||||
|
if (operateType > 0) {
|
||||||
|
return operateType;
|
||||||
|
}
|
||||||
|
// 代码逻辑说明: 阿里云代码扫描规范(不允许任何魔法值出现在代码中)------------
|
||||||
|
return OperateTypeEnum.getTypeByMethodName(methodName);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Description: 获取请求参数
|
||||||
|
* @author: scott
|
||||||
|
* @date: 2020/4/16 0:10
|
||||||
|
* @param request: request
|
||||||
|
* @param joinPoint: joinPoint
|
||||||
|
* @Return: java.lang.String
|
||||||
|
*/
|
||||||
|
private String getReqestParams(HttpServletRequest request, JoinPoint joinPoint) {
|
||||||
|
String httpMethod = request.getMethod();
|
||||||
|
String params = "";
|
||||||
|
if (CommonConstant.HTTP_POST.equals(httpMethod) || CommonConstant.HTTP_PUT.equals(httpMethod) || CommonConstant.HTTP_PATCH.equals(httpMethod)) {
|
||||||
|
Object[] paramsArray = joinPoint.getArgs();
|
||||||
|
// java.lang.IllegalStateException: It is illegal to call this method if the current request is not in asynchronous mode (i.e. isAsyncStarted() returns false)
|
||||||
|
// https://my.oschina.net/mengzhang6/blog/2395893
|
||||||
|
Object[] arguments = new Object[paramsArray.length];
|
||||||
|
for (int i = 0; i < paramsArray.length; i++) {
|
||||||
|
if (paramsArray[i] instanceof BindingResult || paramsArray[i] instanceof ServletRequest || paramsArray[i] instanceof ServletResponse || paramsArray[i] instanceof MultipartFile || paramsArray[i] instanceof MultipartFile[]) {
|
||||||
|
//ServletRequest不能序列化,从入参里排除,否则报异常:java.lang.IllegalStateException: It is illegal to call this method if the current request is not in asynchronous mode (i.e. isAsyncStarted() returns false)
|
||||||
|
//ServletResponse不能序列化 从入参里排除,否则报异常:java.lang.IllegalStateException: getOutputStream() has already been called for this response
|
||||||
|
//MultipartFile和MultipartFile[]不能序列化,从入参里排除
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
arguments[i] = paramsArray[i];
|
||||||
|
}
|
||||||
|
// 代码逻辑说明: 日志数据太长的直接过滤掉
|
||||||
|
PropertyFilter profilter = new PropertyFilter() {
|
||||||
|
@Override
|
||||||
|
public boolean apply(Object o, String name, Object value) {
|
||||||
|
int length = 500;
|
||||||
|
if(value!=null && value.toString().length()>length){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if(value instanceof MultipartFile){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
params = JSONObject.toJSONString(arguments, profilter);
|
||||||
|
} else {
|
||||||
|
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
|
||||||
|
Method method = signature.getMethod();
|
||||||
|
// 请求的方法参数值
|
||||||
|
Object[] args = joinPoint.getArgs();
|
||||||
|
// 请求的方法参数名称
|
||||||
|
StandardReflectionParameterNameDiscoverer u= new StandardReflectionParameterNameDiscoverer();
|
||||||
|
String[] paramNames = u.getParameterNames(method);
|
||||||
|
if (args != null && paramNames != null) {
|
||||||
|
for (int i = 0; i < args.length; i++) {
|
||||||
|
params += " " + paramNames[i] + ": " + args[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return params;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* online日志内容拼接
|
||||||
|
* @param obj
|
||||||
|
* @param content
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private String getOnlineLogContent(Object obj, String content){
|
||||||
|
if (Result.class.isInstance(obj)){
|
||||||
|
Result res = (Result)obj;
|
||||||
|
String msg = res.getMessage();
|
||||||
|
String tableName = res.getOnlTable();
|
||||||
|
if(oConvertUtils.isNotEmpty(tableName)){
|
||||||
|
content+=",表名:"+tableName;
|
||||||
|
}
|
||||||
|
if(res.isSuccess()){
|
||||||
|
content+= ","+(oConvertUtils.isEmpty(msg)?"操作成功":msg);
|
||||||
|
}else{
|
||||||
|
content+= ","+(oConvertUtils.isEmpty(msg)?"操作失败":msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return content;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* private void saveSysLog(ProceedingJoinPoint joinPoint, long time, Object obj) {
|
||||||
|
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
|
||||||
|
Method method = signature.getMethod();
|
||||||
|
|
||||||
|
SysLog sysLog = new SysLog();
|
||||||
|
AutoLog syslog = method.getAnnotation(AutoLog.class);
|
||||||
|
if(syslog != null){
|
||||||
|
//update-begin-author:taoyan date:
|
||||||
|
String content = syslog.value();
|
||||||
|
if(syslog.module()== ModuleType.ONLINE){
|
||||||
|
content = getOnlineLogContent(obj, content);
|
||||||
|
}
|
||||||
|
//注解上的描述,操作日志内容
|
||||||
|
sysLog.setLogContent(content);
|
||||||
|
sysLog.setLogType(syslog.logType());
|
||||||
|
}
|
||||||
|
|
||||||
|
//请求的方法名
|
||||||
|
String className = joinPoint.getTarget().getClass().getName();
|
||||||
|
String methodName = signature.getName();
|
||||||
|
sysLog.setMethod(className + "." + methodName + "()");
|
||||||
|
|
||||||
|
|
||||||
|
//设置操作类型
|
||||||
|
if (sysLog.getLogType() == CommonConstant.LOG_TYPE_2) {
|
||||||
|
sysLog.setOperateType(getOperateType(methodName, syslog.operateType()));
|
||||||
|
}
|
||||||
|
|
||||||
|
//获取request
|
||||||
|
HttpServletRequest request = SpringContextUtils.getHttpServletRequest();
|
||||||
|
//请求的参数
|
||||||
|
sysLog.setRequestParam(getReqestParams(request,joinPoint));
|
||||||
|
|
||||||
|
//设置IP地址
|
||||||
|
sysLog.setIp(IPUtils.getIpAddr(request));
|
||||||
|
|
||||||
|
//获取登录用户信息
|
||||||
|
LoginUser sysUser = (LoginUser)SecurityUtils.getSubject().getPrincipal();
|
||||||
|
if(sysUser!=null){
|
||||||
|
sysLog.setUserid(sysUser.getUsername());
|
||||||
|
sysLog.setUsername(sysUser.getRealname());
|
||||||
|
|
||||||
|
}
|
||||||
|
//耗时
|
||||||
|
sysLog.setCostTime(time);
|
||||||
|
sysLog.setCreateTime(new Date());
|
||||||
|
//保存系统日志
|
||||||
|
sysLogService.save(sysLog);
|
||||||
|
}*/
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,466 @@
|
||||||
|
package com.ghb.base.common.aspect;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson.JSON;
|
||||||
|
import com.alibaba.fastjson.JSONObject;
|
||||||
|
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.aspectj.lang.ProceedingJoinPoint;
|
||||||
|
import org.aspectj.lang.annotation.Around;
|
||||||
|
import org.aspectj.lang.annotation.Aspect;
|
||||||
|
import org.aspectj.lang.annotation.Pointcut;
|
||||||
|
import com.ghb.base.common.api.CommonAPI;
|
||||||
|
import com.ghb.base.common.api.vo.Result;
|
||||||
|
import com.ghb.base.common.aspect.annotation.Dict;
|
||||||
|
import com.ghb.base.common.constant.CommonConstant;
|
||||||
|
import com.ghb.base.common.system.vo.DictModel;
|
||||||
|
import com.ghb.base.common.util.oConvertUtils;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.context.annotation.Lazy;
|
||||||
|
import org.springframework.data.redis.core.RedisTemplate;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
|
import java.beans.PropertyDescriptor;
|
||||||
|
import java.lang.reflect.Field;
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
import java.lang.reflect.Modifier;
|
||||||
|
import java.text.SimpleDateFormat;
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Description: 字典aop类
|
||||||
|
* @Author: dangzhenghui
|
||||||
|
* @Date: 2019-3-17 21:50
|
||||||
|
* @Version: 1.0
|
||||||
|
*/
|
||||||
|
@Aspect
|
||||||
|
@Component
|
||||||
|
@Slf4j
|
||||||
|
public class DictAspect {
|
||||||
|
@Lazy
|
||||||
|
@Autowired
|
||||||
|
private CommonAPI commonApi;
|
||||||
|
@Autowired
|
||||||
|
public RedisTemplate redisTemplate;
|
||||||
|
|
||||||
|
private static final String JAVA_UTIL_DATE = "java.util.Date";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 定义切点Pointcut
|
||||||
|
*/
|
||||||
|
@Pointcut("(@within(org.springframework.web.bind.annotation.RestController) || " +
|
||||||
|
"@within(org.springframework.stereotype.Controller) || @annotation(com.ghb.base.common.aspect.annotation.AutoDict)) " +
|
||||||
|
"&& execution(public com.ghb.base.common.api.vo.Result com.ghb.base..*.*(..))")
|
||||||
|
public void excudeService() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Around("excudeService()")
|
||||||
|
public Object doAround(ProceedingJoinPoint pjp) throws Throwable {
|
||||||
|
long time1=System.currentTimeMillis();
|
||||||
|
Object result = pjp.proceed();
|
||||||
|
long time2=System.currentTimeMillis();
|
||||||
|
log.debug("获取JSON数据 耗时:"+(time2-time1)+"ms");
|
||||||
|
long start=System.currentTimeMillis();
|
||||||
|
result=this.parseDictText(result);
|
||||||
|
long end=System.currentTimeMillis();
|
||||||
|
log.debug("注入字典到JSON数据 耗时"+(end-start)+"ms");
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 本方法针对返回对象为Result 的IPage的分页列表数据进行动态字典注入
|
||||||
|
* 字典注入实现 通过对实体类添加注解@dict 来标识需要的字典内容,字典分为单字典code即可 ,table字典 code table text配合使用与原来Ghb的用法相同
|
||||||
|
* 示例为SysUser 字段为sex 添加了注解@Dict(dicCode = "sex") 会在字典服务立马查出来对应的text 然后在请求list的时候将这个字典text,已字段名称加_dictText形式返回到前端
|
||||||
|
* 例输入当前返回值的就会多出一个sex_dictText字段
|
||||||
|
* {
|
||||||
|
* sex:1,
|
||||||
|
* sex_dictText:"男"
|
||||||
|
* }
|
||||||
|
* 前端直接取值sext_dictText在table里面无需再进行前端的字典转换了
|
||||||
|
* customRender:function (text) {
|
||||||
|
* if(text==1){
|
||||||
|
* return "男";
|
||||||
|
* }else if(text==2){
|
||||||
|
* return "女";
|
||||||
|
* }else{
|
||||||
|
* return text;
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
* 目前vue是这么进行字典渲染到table上的多了就很麻烦了 这个直接在服务端渲染完成前端可以直接用
|
||||||
|
* @param result
|
||||||
|
*/
|
||||||
|
private Object parseDictText(Object result) {
|
||||||
|
//if (result instanceof Result) {
|
||||||
|
if (true) {
|
||||||
|
if (((Result) result).getResult() instanceof IPage) {
|
||||||
|
List<JSONObject> items = new ArrayList<>();
|
||||||
|
|
||||||
|
//step.1 筛选出加了 Dict 注解的字段列表
|
||||||
|
List<Field> dictFieldList = new ArrayList<>();
|
||||||
|
// 字典数据列表, key = 字典code,value=数据列表
|
||||||
|
Map<String, List<String>> dataListMap = new HashMap<>(5);
|
||||||
|
//取出结果集
|
||||||
|
List<Object> records=((IPage) ((Result) result).getResult()).getRecords();
|
||||||
|
// 代码逻辑说明: 【VUEN-1230】 判断是否含有字典注解,没有注解返回-----
|
||||||
|
Boolean hasDict= checkHasDict(records);
|
||||||
|
if(!hasDict){
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
log.debug(" __ 进入字典翻译切面 DictAspect —— " );
|
||||||
|
for (Object record : records) {
|
||||||
|
//update-begin---author:scott ---date:2026-04-15 for:【issues/9543】改用反射直接读取字段构建 JSONObject,避免 ObjectMapper 对循环引用实体进行全量序列化导致 OOM;合并字典字段收集逻辑为同一次循环,避免对 getAllFields 遍历两遍;保留 【issues/#3629】@JsonFormat 的 Date 格式化兼容;保留 【issues/3303】字段顺序(LinkedHashMap)-----------
|
||||||
|
JSONObject item = new JSONObject(true);
|
||||||
|
for (Field field : oConvertUtils.getAllFields(record)) {
|
||||||
|
if (Modifier.isStatic(field.getModifiers())) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
//update-begin---author:scott ---date:2026-04-16 for:【issues/9543】优先通过 getter 方法读取字段值(兼容实体重写 getter 的场景),getter 不存在时 fallback 到直接读字段-----------
|
||||||
|
Object fieldValue = getFieldValue(record, field);
|
||||||
|
//update-end---author:scott ---date:2026-04-16 for:【issues/9543】优先通过 getter 方法读取字段值(兼容实体重写 getter 的场景),getter 不存在时 fallback 到直接读字段-----------
|
||||||
|
// 解决@JsonFormat注解解析不了的问题详见SysAnnouncement类的@JsonFormat
|
||||||
|
if (fieldValue instanceof Date) {
|
||||||
|
JsonFormat jsonFormat = field.getAnnotation(JsonFormat.class);
|
||||||
|
if (jsonFormat != null && oConvertUtils.isNotEmpty(jsonFormat.pattern())) {
|
||||||
|
fieldValue = new SimpleDateFormat(jsonFormat.pattern()).format((Date) fieldValue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
item.put(field.getName(), fieldValue);
|
||||||
|
|
||||||
|
// 遍历所有字段,把字典Code取出来,放到 map 里
|
||||||
|
String value = item.getString(field.getName());
|
||||||
|
if (oConvertUtils.isEmpty(value)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (field.getAnnotation(Dict.class) != null) {
|
||||||
|
if (!dictFieldList.contains(field)) {
|
||||||
|
dictFieldList.add(field);
|
||||||
|
}
|
||||||
|
String code = field.getAnnotation(Dict.class).dicCode();
|
||||||
|
String text = field.getAnnotation(Dict.class).dicText();
|
||||||
|
String table = field.getAnnotation(Dict.class).dictTable();
|
||||||
|
// 代码逻辑说明: [issues/#5643]解决分布式下表字典跨库无法查询问题------------
|
||||||
|
String dataSource = field.getAnnotation(Dict.class).ds();
|
||||||
|
List<String> dataList;
|
||||||
|
String dictCode = code;
|
||||||
|
if (!StringUtils.isEmpty(table)) {
|
||||||
|
// 代码逻辑说明: [issues/#5643]解决分布式下表字典跨库无法查询问题------------
|
||||||
|
dictCode = String.format("%s,%s,%s,%s", table, text, code, dataSource);
|
||||||
|
}
|
||||||
|
dataList = dataListMap.computeIfAbsent(dictCode, k -> new ArrayList<>());
|
||||||
|
this.listAddAllDeduplicate(dataList, Arrays.asList(value.split(",")));
|
||||||
|
}
|
||||||
|
//date类型默认转换string格式化日期
|
||||||
|
//if (JAVA_UTIL_DATE.equals(field.getType().getName())&&field.getAnnotation(JsonFormat.class)==null&&item.get(field.getName())!=null){
|
||||||
|
//SimpleDateFormat aDate=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
|
||||||
|
// item.put(field.getName(), aDate.format(new Date((Long) item.get(field.getName()))));
|
||||||
|
//}
|
||||||
|
}
|
||||||
|
//update-end---author:scott ---date:2026-04-15 for:【issues/9543】改用反射直接读取字段构建 JSONObject,避免 ObjectMapper 对循环引用实体进行全量序列化导致 OOM;合并字典字段收集逻辑为同一次循环,避免对 getAllFields 遍历两遍;保留 【issues/#3629】@JsonFormat 的 Date 格式化兼容;保留 【issues/3303】字段顺序(LinkedHashMap)-----------
|
||||||
|
items.add(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
//step.2 调用翻译方法,一次性翻译
|
||||||
|
Map<String, List<DictModel>> translText = this.translateAllDict(dataListMap);
|
||||||
|
|
||||||
|
//step.3 将翻译结果填充到返回结果里
|
||||||
|
for (JSONObject record : items) {
|
||||||
|
for (Field field : dictFieldList) {
|
||||||
|
String code = field.getAnnotation(Dict.class).dicCode();
|
||||||
|
String text = field.getAnnotation(Dict.class).dicText();
|
||||||
|
String table = field.getAnnotation(Dict.class).dictTable();
|
||||||
|
// 自定义的字典表数据源
|
||||||
|
String dataSource = field.getAnnotation(Dict.class).ds();
|
||||||
|
String fieldDictCode = code;
|
||||||
|
if (!StringUtils.isEmpty(table)) {
|
||||||
|
// 代码逻辑说明: [issues/#5643]解决分布式下表字典跨库无法查询问题------------
|
||||||
|
fieldDictCode = String.format("%s,%s,%s,%s", table, text, code, dataSource);
|
||||||
|
}
|
||||||
|
|
||||||
|
String value = record.getString(field.getName());
|
||||||
|
if (oConvertUtils.isNotEmpty(value)) {
|
||||||
|
List<DictModel> dictModels = translText.get(fieldDictCode);
|
||||||
|
if(dictModels==null || dictModels.size()==0){
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
String textValue = this.translDictText(dictModels, value);
|
||||||
|
log.debug(" 字典Val : " + textValue);
|
||||||
|
log.debug(" __翻译字典字段__ " + field.getName() + CommonConstant.DICT_TEXT_SUFFIX + ": " + textValue);
|
||||||
|
|
||||||
|
// TODO-sun 测试输出,待删
|
||||||
|
log.debug(" ---- dictCode: " + fieldDictCode);
|
||||||
|
log.debug(" ---- value: " + value);
|
||||||
|
log.debug(" ----- text: " + textValue);
|
||||||
|
log.debug(" ---- dictModels: " + JSON.toJSONString(dictModels));
|
||||||
|
|
||||||
|
record.put(field.getName() + CommonConstant.DICT_TEXT_SUFFIX, textValue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
((IPage) ((Result) result).getResult()).setRecords(items);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* list 去重添加
|
||||||
|
*/
|
||||||
|
private void listAddAllDeduplicate(List<String> dataList, List<String> addList) {
|
||||||
|
// 筛选出dataList中没有的数据
|
||||||
|
List<String> filterList = addList.stream().filter(i -> !dataList.contains(i)).collect(Collectors.toList());
|
||||||
|
dataList.addAll(filterList);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 一次性把所有的字典都翻译了
|
||||||
|
* 1. 所有的普通数据字典的所有数据只执行一次SQL
|
||||||
|
* 2. 表字典相同的所有数据只执行一次SQL
|
||||||
|
* @param dataListMap
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private Map<String, List<DictModel>> translateAllDict(Map<String, List<String>> dataListMap) {
|
||||||
|
// 翻译后的字典文本,key=dictCode
|
||||||
|
Map<String, List<DictModel>> translText = new HashMap<>(5);
|
||||||
|
// 需要翻译的数据(有些可以从redis缓存中获取,就不走数据库查询)
|
||||||
|
List<String> needTranslData = new ArrayList<>();
|
||||||
|
//step.1 先通过redis中获取缓存字典数据
|
||||||
|
for (String dictCode : dataListMap.keySet()) {
|
||||||
|
List<String> dataList = dataListMap.get(dictCode);
|
||||||
|
if (dataList.size() == 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// 表字典需要翻译的数据
|
||||||
|
List<String> needTranslDataTable = new ArrayList<>();
|
||||||
|
for (String s : dataList) {
|
||||||
|
String data = s.trim();
|
||||||
|
if (data.length() == 0) {
|
||||||
|
continue; //跳过循环
|
||||||
|
}
|
||||||
|
if (dictCode.contains(",")) {
|
||||||
|
String keyString = String.format("sys:cache:dictTable::SimpleKey [%s,%s]", dictCode, data);
|
||||||
|
if (redisTemplate.hasKey(keyString)) {
|
||||||
|
try {
|
||||||
|
String text = oConvertUtils.getString(redisTemplate.opsForValue().get(keyString));
|
||||||
|
List<DictModel> list = translText.computeIfAbsent(dictCode, k -> new ArrayList<>());
|
||||||
|
list.add(new DictModel(data, text));
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.warn(e.getMessage());
|
||||||
|
}
|
||||||
|
} else if (!needTranslDataTable.contains(data)) {
|
||||||
|
// 去重添加
|
||||||
|
needTranslDataTable.add(data);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
String keyString = String.format("sys:cache:dict::%s:%s", dictCode, data);
|
||||||
|
if (redisTemplate.hasKey(keyString)) {
|
||||||
|
try {
|
||||||
|
String text = oConvertUtils.getString(redisTemplate.opsForValue().get(keyString));
|
||||||
|
List<DictModel> list = translText.computeIfAbsent(dictCode, k -> new ArrayList<>());
|
||||||
|
list.add(new DictModel(data, text));
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.warn(e.getMessage());
|
||||||
|
}
|
||||||
|
} else if (!needTranslData.contains(data)) {
|
||||||
|
// 去重添加
|
||||||
|
needTranslData.add(data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
//step.2 调用数据库翻译表字典
|
||||||
|
if (needTranslDataTable.size() > 0) {
|
||||||
|
String[] arr = dictCode.split(",");
|
||||||
|
String table = arr[0], text = arr[1], code = arr[2];
|
||||||
|
String values = String.join(",", needTranslDataTable);
|
||||||
|
// 自定义的数据源
|
||||||
|
String dataSource = null;
|
||||||
|
if (arr.length > 3) {
|
||||||
|
dataSource = arr[3];
|
||||||
|
}
|
||||||
|
log.debug("translateDictFromTableByKeys.dictCode:" + dictCode);
|
||||||
|
log.debug("translateDictFromTableByKeys.values:" + values);
|
||||||
|
|
||||||
|
// 代码逻辑说明: 微服务下为空报错没有参数需要传递空字符串---
|
||||||
|
if(null == dataSource){
|
||||||
|
dataSource = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
List<DictModel> texts = commonApi.translateDictFromTableByKeys(table, text, code, values, dataSource);
|
||||||
|
log.debug("translateDictFromTableByKeys.result:" + texts);
|
||||||
|
List<DictModel> list = translText.computeIfAbsent(dictCode, k -> new ArrayList<>());
|
||||||
|
list.addAll(texts);
|
||||||
|
|
||||||
|
// 做 redis 缓存
|
||||||
|
for (DictModel dict : texts) {
|
||||||
|
String redisKey = String.format("sys:cache:dictTable::SimpleKey [%s,%s]", dictCode, dict.getValue());
|
||||||
|
try {
|
||||||
|
// 保留5分钟
|
||||||
|
redisTemplate.opsForValue().set(redisKey, dict.getText(), 300, TimeUnit.SECONDS);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.warn(e.getMessage(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//step.3 调用数据库进行翻译普通字典
|
||||||
|
if (needTranslData.size() > 0) {
|
||||||
|
List<String> dictCodeList = Arrays.asList(dataListMap.keySet().toArray(new String[]{}));
|
||||||
|
// 将不包含逗号的字典code筛选出来,因为带逗号的是表字典,而不是普通的数据字典
|
||||||
|
List<String> filterDictCodes = dictCodeList.stream().filter(key -> !key.contains(",")).collect(Collectors.toList());
|
||||||
|
String dictCodes = String.join(",", filterDictCodes);
|
||||||
|
String values = String.join(",", needTranslData);
|
||||||
|
log.debug("translateManyDict.dictCodes:" + dictCodes);
|
||||||
|
log.debug("translateManyDict.values:" + values);
|
||||||
|
Map<String, List<DictModel>> manyDict = commonApi.translateManyDict(dictCodes, values);
|
||||||
|
log.debug("translateManyDict.result:" + manyDict);
|
||||||
|
for (String dictCode : manyDict.keySet()) {
|
||||||
|
List<DictModel> list = translText.computeIfAbsent(dictCode, k -> new ArrayList<>());
|
||||||
|
List<DictModel> newList = manyDict.get(dictCode);
|
||||||
|
list.addAll(newList);
|
||||||
|
|
||||||
|
// 做 redis 缓存
|
||||||
|
for (DictModel dict : newList) {
|
||||||
|
String redisKey = String.format("sys:cache:dict::%s:%s", dictCode, dict.getValue());
|
||||||
|
try {
|
||||||
|
redisTemplate.opsForValue().set(redisKey, dict.getText());
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.warn(e.getMessage(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return translText;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 字典值替换文本
|
||||||
|
*
|
||||||
|
* @param dictModels
|
||||||
|
* @param values
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private String translDictText(List<DictModel> dictModels, String values) {
|
||||||
|
List<String> result = new ArrayList<>();
|
||||||
|
|
||||||
|
// 允许多个逗号分隔,允许传数组对象
|
||||||
|
String[] splitVal = values.split(",");
|
||||||
|
for (String val : splitVal) {
|
||||||
|
String dictText = val;
|
||||||
|
for (DictModel dict : dictModels) {
|
||||||
|
if (val.equals(dict.getValue())) {
|
||||||
|
dictText = dict.getText();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
result.add(dictText);
|
||||||
|
}
|
||||||
|
return String.join(",", result);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 翻译字典文本
|
||||||
|
* @param code
|
||||||
|
* @param text
|
||||||
|
* @param table
|
||||||
|
* @param key
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
|
private String translateDictValue(String code, String text, String table, String key) {
|
||||||
|
if(oConvertUtils.isEmpty(key)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
StringBuffer textValue=new StringBuffer();
|
||||||
|
String[] keys = key.split(",");
|
||||||
|
for (String k : keys) {
|
||||||
|
String tmpValue = null;
|
||||||
|
log.debug(" 字典 key : "+ k);
|
||||||
|
if (k.trim().length() == 0) {
|
||||||
|
continue; //跳过循环
|
||||||
|
}
|
||||||
|
// 代码逻辑说明: !56 优化微服务应用下存在表字段需要字典翻译时加载缓慢问题-----
|
||||||
|
if (!StringUtils.isEmpty(table)){
|
||||||
|
log.debug("--DictAspect------dicTable="+ table+" ,dicText= "+text+" ,dicCode="+code);
|
||||||
|
String keyString = String.format("sys:cache:dictTable::SimpleKey [%s,%s,%s,%s]",table,text,code,k.trim());
|
||||||
|
if (redisTemplate.hasKey(keyString)){
|
||||||
|
try {
|
||||||
|
tmpValue = oConvertUtils.getString(redisTemplate.opsForValue().get(keyString));
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.warn(e.getMessage());
|
||||||
|
}
|
||||||
|
}else {
|
||||||
|
tmpValue= commonApi.translateDictFromTable(table,text,code,k.trim());
|
||||||
|
}
|
||||||
|
}else {
|
||||||
|
String keyString = String.format("sys:cache:dict::%s:%s",code,k.trim());
|
||||||
|
if (redisTemplate.hasKey(keyString)){
|
||||||
|
try {
|
||||||
|
tmpValue = oConvertUtils.getString(redisTemplate.opsForValue().get(keyString));
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.warn(e.getMessage());
|
||||||
|
}
|
||||||
|
}else {
|
||||||
|
tmpValue = commonApi.translateDict(code, k.trim());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tmpValue != null) {
|
||||||
|
if (!"".equals(textValue.toString())) {
|
||||||
|
textValue.append(",");
|
||||||
|
}
|
||||||
|
textValue.append(tmpValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
return textValue.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
//update-begin---author:scott ---date:2026-04-16 for:【issues/9543】优先通过 getter 方法读取字段值(兼容实体重写 getter 的场景),getter 不存在时 fallback 到直接读字段-----------
|
||||||
|
/**
|
||||||
|
* 优先通过 PropertyDescriptor 获取 getter 方法读取字段值,兼容实体重写 getter 的场景;
|
||||||
|
* getter 不存在或调用异常时 fallback 到直接反射读字段。
|
||||||
|
*/
|
||||||
|
private Object getFieldValue(Object record, Field field) {
|
||||||
|
try {
|
||||||
|
PropertyDescriptor pd = new PropertyDescriptor(field.getName(), record.getClass());
|
||||||
|
Method readMethod = pd.getReadMethod();
|
||||||
|
if (readMethod != null) {
|
||||||
|
return readMethod.invoke(record);
|
||||||
|
}
|
||||||
|
} catch (Exception ignored) {
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
field.setAccessible(true);
|
||||||
|
return field.get(record);
|
||||||
|
} catch (IllegalAccessException e) {
|
||||||
|
log.error("反射读取字段失败: " + field.getName(), e);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//update-end---author:scott ---date:2026-04-16 for:【issues/9543】优先通过 getter 方法读取字段值(兼容实体重写 getter 的场景),getter 不存在时 fallback 到直接读字段-----------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 检测返回结果集中是否包含Dict注解
|
||||||
|
* @param records
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private Boolean checkHasDict(List<Object> records){
|
||||||
|
if(oConvertUtils.isNotEmpty(records) && records.size()>0){
|
||||||
|
for (Field field : oConvertUtils.getAllFields(records.get(0))) {
|
||||||
|
if (oConvertUtils.isNotEmpty(field.getAnnotation(Dict.class))) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,137 @@
|
||||||
|
package com.ghb.base.common.aspect;
|
||||||
|
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.aspectj.lang.ProceedingJoinPoint;
|
||||||
|
import org.aspectj.lang.annotation.Around;
|
||||||
|
import org.aspectj.lang.annotation.Aspect;
|
||||||
|
import org.aspectj.lang.annotation.Pointcut;
|
||||||
|
import org.aspectj.lang.reflect.MethodSignature;
|
||||||
|
import com.ghb.base.common.api.CommonAPI;
|
||||||
|
import com.ghb.base.common.aspect.annotation.PermissionData;
|
||||||
|
import com.ghb.base.common.constant.CommonConstant;
|
||||||
|
import com.ghb.base.common.constant.SymbolConstant;
|
||||||
|
import com.ghb.base.common.system.query.QueryRuleEnum;
|
||||||
|
import com.ghb.base.common.system.util.GhbDataAutorUtils;
|
||||||
|
import com.ghb.base.common.system.util.JwtUtil;
|
||||||
|
import com.ghb.base.common.system.vo.SysPermissionDataRuleModel;
|
||||||
|
import com.ghb.base.common.system.vo.SysUserCacheInfo;
|
||||||
|
import com.ghb.base.common.util.SpringContextUtils;
|
||||||
|
import com.ghb.base.common.util.oConvertUtils;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.context.annotation.Lazy;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 数据权限切面处理类
|
||||||
|
* 当被请求的方法有注解PermissionData时,会在往当前request中写入数据权限信息
|
||||||
|
* @Date 2019年4月10日
|
||||||
|
* @Version: 1.0
|
||||||
|
* @author: Ghb-boot
|
||||||
|
*/
|
||||||
|
@Aspect
|
||||||
|
@Component
|
||||||
|
@Slf4j
|
||||||
|
public class PermissionDataAspect {
|
||||||
|
@Lazy
|
||||||
|
@Autowired
|
||||||
|
private CommonAPI commonApi;
|
||||||
|
|
||||||
|
private static final String SPOT_DO = ".do";
|
||||||
|
|
||||||
|
@Pointcut("@annotation(com.ghb.base.common.aspect.annotation.PermissionData)")
|
||||||
|
public void pointCut() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Around("pointCut()")
|
||||||
|
public Object arround(ProceedingJoinPoint point) throws Throwable{
|
||||||
|
HttpServletRequest request = SpringContextUtils.getHttpServletRequest();
|
||||||
|
MethodSignature signature = (MethodSignature) point.getSignature();
|
||||||
|
Method method = signature.getMethod();
|
||||||
|
PermissionData pd = method.getAnnotation(PermissionData.class);
|
||||||
|
String component = pd.pageComponent();
|
||||||
|
String requestMethod = request.getMethod();
|
||||||
|
String requestPath = request.getRequestURI().substring(request.getContextPath().length());
|
||||||
|
requestPath = filterUrl(requestPath);
|
||||||
|
//先判断是否online报表请求
|
||||||
|
if(requestPath.indexOf(UrlMatchEnum.CGREPORT_DATA.getMatchUrl())>=0 || requestPath.indexOf(UrlMatchEnum.CGREPORT_ONLY_DATA.getMatchUrl())>=0){
|
||||||
|
// 获取地址栏参数
|
||||||
|
String urlParamString = request.getParameter(CommonConstant.ONL_REP_URL_PARAM_STR);
|
||||||
|
if(oConvertUtils.isNotEmpty(urlParamString)){
|
||||||
|
requestPath+="?"+urlParamString;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
log.debug("拦截请求 >> {} ; 请求类型 >> {} . ", requestPath, requestMethod);
|
||||||
|
String username = JwtUtil.getUserNameByToken(request);
|
||||||
|
//查询数据权限信息
|
||||||
|
//TODO 微服务情况下也得支持缓存机制
|
||||||
|
List<SysPermissionDataRuleModel> dataRules = commonApi.queryPermissionDataRule(component, requestPath, username);
|
||||||
|
if(dataRules!=null && dataRules.size()>0) {
|
||||||
|
//临时存储
|
||||||
|
GhbDataAutorUtils.installDataSearchConditon(request, dataRules);
|
||||||
|
//TODO 微服务情况下也得支持缓存机制
|
||||||
|
SysUserCacheInfo userinfo = commonApi.getCacheUser(username);
|
||||||
|
GhbDataAutorUtils.installUserInfo(request, userinfo);
|
||||||
|
}
|
||||||
|
return point.proceed();
|
||||||
|
}
|
||||||
|
|
||||||
|
private String filterUrl(String requestPath){
|
||||||
|
String url = "";
|
||||||
|
if(oConvertUtils.isNotEmpty(requestPath)){
|
||||||
|
url = requestPath.replace("\\", "/");
|
||||||
|
url = url.replace("//", "/");
|
||||||
|
if(url.indexOf(SymbolConstant.DOUBLE_SLASH)>=0){
|
||||||
|
url = filterUrl(url);
|
||||||
|
}
|
||||||
|
/*if(url.startsWith("/")){
|
||||||
|
url=url.substring(1);
|
||||||
|
}*/
|
||||||
|
}
|
||||||
|
return url;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取请求地址
|
||||||
|
* @param request
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
|
private String getJgAuthRequsetPath(HttpServletRequest request) {
|
||||||
|
String queryString = request.getQueryString();
|
||||||
|
String requestPath = request.getRequestURI();
|
||||||
|
if(oConvertUtils.isNotEmpty(queryString)){
|
||||||
|
requestPath += "?" + queryString;
|
||||||
|
}
|
||||||
|
// 去掉其他参数(保留一个参数) 例如:loginController.do?login
|
||||||
|
if (requestPath.indexOf(SymbolConstant.AND) > -1) {
|
||||||
|
requestPath = requestPath.substring(0, requestPath.indexOf("&"));
|
||||||
|
}
|
||||||
|
if(requestPath.indexOf(QueryRuleEnum.EQ.getValue())!=-1){
|
||||||
|
if(requestPath.indexOf(SPOT_DO)!=-1){
|
||||||
|
requestPath = requestPath.substring(0,requestPath.indexOf(".do")+3);
|
||||||
|
}else{
|
||||||
|
requestPath = requestPath.substring(0,requestPath.indexOf("?"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 去掉项目路径
|
||||||
|
requestPath = requestPath.substring(request.getContextPath().length() + 1);
|
||||||
|
return filterUrl(requestPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Deprecated
|
||||||
|
private boolean moHuContain(List<String> list,String key){
|
||||||
|
for(String str : list){
|
||||||
|
if(key.contains(str)){
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,68 @@
|
||||||
|
package com.ghb.base.common.aspect;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Author scott
|
||||||
|
* @Date 2020/1/14 13:36
|
||||||
|
* @Description: 请求URL与菜单路由URL转换规则(方便于采用菜单路由URL来配置数据权限规则)
|
||||||
|
*/
|
||||||
|
public enum UrlMatchEnum {
|
||||||
|
/**求URL与菜单路由URL转换规则 /online/cgform/api/getData/ */
|
||||||
|
CGFORM_DATA("/online/cgform/api/getData/", "/online/cgformList/"),
|
||||||
|
/**求URL与菜单路由URL转换规则 /online/cgform/api/exportXls/ */
|
||||||
|
CGFORM_EXCEL_DATA("/online/cgform/api/exportXls/", "/online/cgformList/"),
|
||||||
|
/**求URL与菜单路由URL转换规则 /online/cgform/api/getTreeData/ */
|
||||||
|
CGFORM_TREE_DATA("/online/cgform/api/getTreeData/", "/online/cgformList/"),
|
||||||
|
/**求URL与菜单路由URL转换规则 /online/cgreport/api/getColumnsAndData/ */
|
||||||
|
CGREPORT_DATA("/online/cgreport/api/getColumnsAndData/", "/online/cgreport/"),
|
||||||
|
/** 求URL与菜单路由URL转换规则/online/cgreport/api/getData/ 【vue3报表数据请求地址】 */
|
||||||
|
CGREPORT_ONLY_DATA("/online/cgreport/api/getData/", "/online/cgreport/"),
|
||||||
|
/**求URL与菜单路由URL转换规则 /online/cgreport/api/exportXls/ */
|
||||||
|
CGREPORT_EXCEL_DATA("/online/cgreport/api/exportXls/", "/online/cgreport/"),
|
||||||
|
/**求URL与菜单路由URL转换规则 /online/cgreport/api/exportManySheetXls/ */
|
||||||
|
CGREPORT_EXCEL_DATA2("/online/cgreport/api/exportManySheetXls/", "/online/cgreport/");
|
||||||
|
|
||||||
|
UrlMatchEnum(String url, String matchUrl) {
|
||||||
|
this.url = url;
|
||||||
|
this.matchUrl = matchUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Request 请求 URL前缀
|
||||||
|
*/
|
||||||
|
private String url;
|
||||||
|
/**
|
||||||
|
* 菜单路由 URL前缀 (对应菜单路径)
|
||||||
|
*/
|
||||||
|
private String matchUrl;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据req url 获取到菜单配置路径(前端页面路由URL)
|
||||||
|
*
|
||||||
|
* @param url
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static String getMatchResultByUrl(String url) {
|
||||||
|
//获取到枚举
|
||||||
|
UrlMatchEnum[] values = UrlMatchEnum.values();
|
||||||
|
//加强for循环进行遍历操作
|
||||||
|
for (UrlMatchEnum lr : values) {
|
||||||
|
//如果遍历获取的type和参数type一致
|
||||||
|
if (url.indexOf(lr.url) != -1) {
|
||||||
|
//返回type对象的desc
|
||||||
|
return url.replace(lr.url, lr.matchUrl);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getMatchUrl() {
|
||||||
|
return matchUrl;
|
||||||
|
}
|
||||||
|
// public static void main(String[] args) {
|
||||||
|
// /**
|
||||||
|
// * 比如request真实请求URL: /online/cgform/api/getData/81fcf7d8922d45069b0d5ba983612d3a
|
||||||
|
// * 转换匹配路由URL后(对应配置的菜单路径):/online/cgformList/81fcf7d8922d45069b0d5ba983612d3a
|
||||||
|
// */
|
||||||
|
// System.out.println(UrlMatchEnum.getMatchResultByUrl("/online/cgform/api/getData/81fcf7d8922d45069b0d5ba983612d3a"));
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,23 @@
|
||||||
|
package com.ghb.base.common.aspect.annotation;
|
||||||
|
|
||||||
|
import java.lang.annotation.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 通过此注解声明的接口,自动实现字典翻译
|
||||||
|
*
|
||||||
|
* @Author scott
|
||||||
|
* @email Ghbos@163.com
|
||||||
|
* @Date 2022年01月05日
|
||||||
|
*/
|
||||||
|
@Target(ElementType.METHOD)
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
@Documented
|
||||||
|
public @interface AutoDict {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 暂时无用
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
String value() default "";
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,46 @@
|
||||||
|
package com.ghb.base.common.aspect.annotation;
|
||||||
|
|
||||||
|
import com.ghb.base.common.constant.CommonConstant;
|
||||||
|
import com.ghb.base.common.constant.enums.ModuleType;
|
||||||
|
|
||||||
|
import java.lang.annotation.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 系统日志注解
|
||||||
|
*
|
||||||
|
* @Author scott
|
||||||
|
* @email Ghbos@163.com
|
||||||
|
* @Date 2019年1月14日
|
||||||
|
*/
|
||||||
|
@Target(ElementType.METHOD)
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
@Documented
|
||||||
|
public @interface AutoLog {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 日志内容
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
String value() default "";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 日志类型
|
||||||
|
*
|
||||||
|
* @return 0:操作日志;1:登录日志;2:定时任务;
|
||||||
|
*/
|
||||||
|
int logType() default CommonConstant.LOG_TYPE_2;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 操作日志类型
|
||||||
|
*
|
||||||
|
* @return (1查询,2添加,3修改,4删除)
|
||||||
|
*/
|
||||||
|
int operateType() default 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 模块类型 默认为common
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
ModuleType module() default ModuleType.COMMON;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,52 @@
|
||||||
|
package com.ghb.base.common.aspect.annotation;
|
||||||
|
|
||||||
|
import java.lang.annotation.ElementType;
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 字典注解
|
||||||
|
* @author: dangzhenghui
|
||||||
|
* @date: 2019年03月17日-下午9:37:16
|
||||||
|
*/
|
||||||
|
@Target(ElementType.FIELD)
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
public @interface Dict {
|
||||||
|
/**
|
||||||
|
* 方法描述: 数据code
|
||||||
|
* 作 者: dangzhenghui
|
||||||
|
* 日 期: 2019年03月17日-下午9:37:16
|
||||||
|
*
|
||||||
|
* @return 返回类型: String
|
||||||
|
*/
|
||||||
|
String dicCode();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 方法描述: 数据Text
|
||||||
|
* 作 者: dangzhenghui
|
||||||
|
* 日 期: 2019年03月17日-下午9:37:16
|
||||||
|
*
|
||||||
|
* @return 返回类型: String
|
||||||
|
*/
|
||||||
|
String dicText() default "";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 方法描述: 数据字典表
|
||||||
|
* 作 者: dangzhenghui
|
||||||
|
* 日 期: 2019年03月17日-下午9:37:16
|
||||||
|
*
|
||||||
|
* @return 返回类型: String
|
||||||
|
*/
|
||||||
|
String dictTable() default "";
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 方法描述: 数据字典表所在数据源名称
|
||||||
|
* 作 者: chenrui
|
||||||
|
* 日 期: 2023年12月20日-下午4:58
|
||||||
|
*
|
||||||
|
* @return 返回类型: String
|
||||||
|
*/
|
||||||
|
String ds() default "";
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,20 @@
|
||||||
|
package com.ghb.base.common.aspect.annotation;
|
||||||
|
|
||||||
|
import java.lang.annotation.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 动态table切换
|
||||||
|
*
|
||||||
|
* @author :zyf
|
||||||
|
* @date:2020-04-25
|
||||||
|
*/
|
||||||
|
@Target(ElementType.METHOD)
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
@Documented
|
||||||
|
public @interface DynamicTable {
|
||||||
|
/**
|
||||||
|
* 需要动态解析的表名
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
String value();
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,19 @@
|
||||||
|
package com.ghb.base.common.aspect.annotation;
|
||||||
|
|
||||||
|
import java.lang.annotation.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* online请求拦截专用注解
|
||||||
|
* @author: Ghb-boot
|
||||||
|
*/
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
@Target({ElementType.TYPE,ElementType.METHOD})
|
||||||
|
@Documented
|
||||||
|
public @interface OnlineAuth {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 请求关键字,在xxx/code之前的字符串
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
String value();
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,29 @@
|
||||||
|
package com.ghb.base.common.aspect.annotation;
|
||||||
|
|
||||||
|
import java.lang.annotation.Documented;
|
||||||
|
import java.lang.annotation.ElementType;
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 数据权限注解
|
||||||
|
* @Author taoyan
|
||||||
|
* @Date 2019年4月11日
|
||||||
|
*/
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
@Target({ElementType.TYPE,ElementType.METHOD})
|
||||||
|
@Documented
|
||||||
|
public @interface PermissionData {
|
||||||
|
/**
|
||||||
|
* 暂时没用
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
String value() default "";
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 配置菜单的组件路径,用于数据权限
|
||||||
|
*/
|
||||||
|
String pageComponent() default "";
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,744 @@
|
||||||
|
package com.ghb.base.common.constant;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Description: 通用常量
|
||||||
|
* @author: Ghb-boot
|
||||||
|
*/
|
||||||
|
public interface CommonConstant {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 正常状态
|
||||||
|
*/
|
||||||
|
Integer STATUS_NORMAL = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 禁用状态
|
||||||
|
*/
|
||||||
|
Integer STATUS_DISABLE = -1;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除标志
|
||||||
|
*/
|
||||||
|
Integer DEL_FLAG_1 = 1;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 未删除
|
||||||
|
*/
|
||||||
|
Integer DEL_FLAG_0 = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 系统日志类型: 登录
|
||||||
|
*/
|
||||||
|
int LOG_TYPE_1 = 1;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 系统日志类型: 操作
|
||||||
|
*/
|
||||||
|
int LOG_TYPE_2 = 2;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 系统日志类型: 租户操作日志
|
||||||
|
*/
|
||||||
|
int LOG_TYPE_3 = 3;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 系统日志类型: 异常
|
||||||
|
*/
|
||||||
|
int LOG_TYPE_4 = 4;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 操作日志类型: 查询
|
||||||
|
*/
|
||||||
|
int OPERATE_TYPE_1 = 1;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 操作日志类型: 添加
|
||||||
|
*/
|
||||||
|
int OPERATE_TYPE_2 = 2;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 操作日志类型: 更新
|
||||||
|
*/
|
||||||
|
int OPERATE_TYPE_3 = 3;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 操作日志类型: 删除
|
||||||
|
*/
|
||||||
|
int OPERATE_TYPE_4 = 4;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 操作日志类型: 倒入
|
||||||
|
*/
|
||||||
|
int OPERATE_TYPE_5 = 5;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 操作日志类型: 导出
|
||||||
|
*/
|
||||||
|
int OPERATE_TYPE_6 = 6;
|
||||||
|
|
||||||
|
|
||||||
|
/** {@code 500 Server Error} (HTTP/1.0 - RFC 1945) */
|
||||||
|
Integer SC_INTERNAL_SERVER_ERROR_500 = 500;
|
||||||
|
/** {@code 404 Not Found} (HTTP/1.0 - RFC 1945) */
|
||||||
|
Integer SC_INTERNAL_NOT_FOUND_404 = 404;
|
||||||
|
/** {@code 200 OK} (HTTP/1.0 - RFC 1945) */
|
||||||
|
Integer SC_OK_200 = 200;
|
||||||
|
|
||||||
|
/**访问权限认证未通过 510*/
|
||||||
|
Integer SC_Ghb_NO_AUTHZ=510;
|
||||||
|
|
||||||
|
/** 登录用户Shiro权限缓存KEY前缀 */
|
||||||
|
public static String PREFIX_USER_SHIRO_CACHE = "shiro:cache:com.ghb.base.config.shiro.ShiroRealm.authorizationCache:";
|
||||||
|
/** 登录用户Token令牌缓存KEY前缀 */
|
||||||
|
String PREFIX_USER_TOKEN = "prefix_user_token:";
|
||||||
|
/** 登录用户Token令牌作废提示信息,比如 “不允许同一账号多地同时登录,会往这个变量存提示信息” */
|
||||||
|
String PREFIX_USER_TOKEN_ERROR_MSG = "prefix_user_token:error:msg_";
|
||||||
|
|
||||||
|
/**============================== 【是否允许同一账号多地同时登录】登录客户端类型常量 ==============================*/
|
||||||
|
/** 客户端类型:PC端 */
|
||||||
|
String CLIENT_TYPE_PC = "PC";
|
||||||
|
/** 客户端类型:APP端 */
|
||||||
|
String CLIENT_TYPE_APP = "APP";
|
||||||
|
/** 客户端类型:手机号登录 */
|
||||||
|
String CLIENT_TYPE_PHONE = "PHONE";
|
||||||
|
String PREFIX_USER_TOKEN_PC = "prefix_user_token:single_login:pc:";
|
||||||
|
/** 单点登录:用户在APP端的Token缓存KEY前缀 (username -> token) */
|
||||||
|
String PREFIX_USER_TOKEN_APP = "prefix_user_token:single_login:app:";
|
||||||
|
/** 单点登录:用户在手机号登录的Token缓存KEY前缀 (username -> token) */
|
||||||
|
String PREFIX_USER_TOKEN_PHONE = "prefix_user_token:single_login:phone:";
|
||||||
|
/**============================== 【是否允许同一账号多地同时登录】登录客户端类型常量 ==============================*/
|
||||||
|
|
||||||
|
// /** Token缓存时间:3600秒即一小时 */
|
||||||
|
// int TOKEN_EXPIRE_TIME = 3600;
|
||||||
|
|
||||||
|
/** 登录二维码 */
|
||||||
|
String LOGIN_QRCODE_PRE = "QRCODELOGIN:";
|
||||||
|
String LOGIN_QRCODE = "LQ:";
|
||||||
|
/** 登录二维码token */
|
||||||
|
String LOGIN_QRCODE_TOKEN = "LQT:";
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 0:一级菜单
|
||||||
|
*/
|
||||||
|
Integer MENU_TYPE_0 = 0;
|
||||||
|
/**
|
||||||
|
* 1:子菜单
|
||||||
|
*/
|
||||||
|
Integer MENU_TYPE_1 = 1;
|
||||||
|
/**
|
||||||
|
* 2:按钮权限
|
||||||
|
*/
|
||||||
|
Integer MENU_TYPE_2 = 2;
|
||||||
|
|
||||||
|
/**通告对象类型(USER:指定用户,ALL:全体用户)*/
|
||||||
|
String MSG_TYPE_UESR = "USER";
|
||||||
|
String MSG_TYPE_ALL = "ALL";
|
||||||
|
|
||||||
|
/**发布状态(0未发布,1已发布,2已撤销)*/
|
||||||
|
String NO_SEND = "0";
|
||||||
|
String HAS_SEND = "1";
|
||||||
|
String HAS_CANCLE = "2";
|
||||||
|
|
||||||
|
/**阅读状态(0未读,1已读)*/
|
||||||
|
Integer HAS_READ_FLAG = 1;
|
||||||
|
Integer NO_READ_FLAG = 0;
|
||||||
|
|
||||||
|
/**优先级(L低,M中,H高)*/
|
||||||
|
String PRIORITY_L = "L";
|
||||||
|
String PRIORITY_M = "M";
|
||||||
|
String PRIORITY_H = "H";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 短信模板方式 0 .登录模板、1.注册模板、2.忘记密码模板
|
||||||
|
*/
|
||||||
|
String SMS_TPL_TYPE_0 = "0";
|
||||||
|
String SMS_TPL_TYPE_1 = "1";
|
||||||
|
String SMS_TPL_TYPE_2 = "2";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 状态(0无效1有效)
|
||||||
|
*/
|
||||||
|
String STATUS_0 = "0";
|
||||||
|
String STATUS_1 = "1";
|
||||||
|
Integer STATUS_0_INT = 0;
|
||||||
|
Integer STATUS_1_INT = 1;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 同步工作流引擎1同步0不同步
|
||||||
|
*/
|
||||||
|
Integer ACT_SYNC_1 = 1;
|
||||||
|
Integer ACT_SYNC_0 = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 消息类型1:通知公告2:系统消息
|
||||||
|
*/
|
||||||
|
String MSG_CATEGORY_1 = "1";
|
||||||
|
String MSG_CATEGORY_2 = "2";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否配置菜单的数据权限 1是0否
|
||||||
|
*/
|
||||||
|
Integer RULE_FLAG_0 = 0;
|
||||||
|
Integer RULE_FLAG_1 = 1;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否用户已被冻结 1正常(解冻) 2冻结 3离职
|
||||||
|
*/
|
||||||
|
Integer USER_UNFREEZE = 1;
|
||||||
|
Integer USER_FREEZE = 2;
|
||||||
|
Integer USER_QUIT = 3;
|
||||||
|
|
||||||
|
/**字典翻译文本后缀*/
|
||||||
|
String DICT_TEXT_SUFFIX = "_dictText";
|
||||||
|
/**字典翻译颜色后缀*/
|
||||||
|
String DICT_COLOR_SUFFIX = "_dictColor";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 表单设计器主表类型
|
||||||
|
*/
|
||||||
|
Integer DESIGN_FORM_TYPE_MAIN = 1;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 表单设计器子表表类型
|
||||||
|
*/
|
||||||
|
Integer DESIGN_FORM_TYPE_SUB = 2;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 表单设计器URL授权通过
|
||||||
|
*/
|
||||||
|
Integer DESIGN_FORM_URL_STATUS_PASSED = 1;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 表单设计器URL授权未通过
|
||||||
|
*/
|
||||||
|
Integer DESIGN_FORM_URL_STATUS_NOT_PASSED = 2;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 表单设计器新增 Flag
|
||||||
|
*/
|
||||||
|
String DESIGN_FORM_URL_TYPE_ADD = "add";
|
||||||
|
/**
|
||||||
|
* 表单设计器修改 Flag
|
||||||
|
*/
|
||||||
|
String DESIGN_FORM_URL_TYPE_EDIT = "edit";
|
||||||
|
/**
|
||||||
|
* 表单设计器详情 Flag
|
||||||
|
*/
|
||||||
|
String DESIGN_FORM_URL_TYPE_DETAIL = "detail";
|
||||||
|
/**
|
||||||
|
* 表单设计器复用数据 Flag
|
||||||
|
*/
|
||||||
|
String DESIGN_FORM_URL_TYPE_REUSE = "reuse";
|
||||||
|
/**
|
||||||
|
* 表单设计器编辑 Flag (已弃用)
|
||||||
|
*/
|
||||||
|
String DESIGN_FORM_URL_TYPE_VIEW = "view";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* online参数值设置(是:Y, 否:N)
|
||||||
|
*/
|
||||||
|
String ONLINE_PARAM_VAL_IS_TURE = "Y";
|
||||||
|
String ONLINE_PARAM_VAL_IS_FALSE = "N";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 文件上传类型(本地:local,Minio:minio,阿里云:alioss)
|
||||||
|
*/
|
||||||
|
String UPLOAD_TYPE_LOCAL = "local";
|
||||||
|
String UPLOAD_TYPE_MINIO = "minio";
|
||||||
|
String UPLOAD_TYPE_OSS = "alioss";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 文档上传自定义桶名称 (私有加密桶名)—— 知识库功能
|
||||||
|
*/
|
||||||
|
String UPLOAD_CUSTOM_BUCKET = "eoafile";
|
||||||
|
/**
|
||||||
|
* 文档上传自定义路径
|
||||||
|
*/
|
||||||
|
String UPLOAD_CUSTOM_PATH = "eoafile";
|
||||||
|
/**
|
||||||
|
* 文件外链接有效天数
|
||||||
|
*/
|
||||||
|
Integer UPLOAD_EFFECTIVE_DAYS = 1;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 员工身份 (1:普通员工 2:上级)
|
||||||
|
*/
|
||||||
|
Integer USER_IDENTITY_1 = 1;
|
||||||
|
Integer USER_IDENTITY_2 = 2;
|
||||||
|
|
||||||
|
/** sys_user 表 username 唯一键索引 */
|
||||||
|
String SQL_INDEX_UNIQ_SYS_USER_USERNAME = "uniq_sys_user_username";
|
||||||
|
/** sys_user 表 work_no 唯一键索引 */
|
||||||
|
String SQL_INDEX_UNIQ_SYS_USER_WORK_NO = "uniq_sys_user_work_no";
|
||||||
|
/** sys_user 表 phone 唯一键索引 */
|
||||||
|
String SQL_INDEX_UNIQ_SYS_USER_PHONE = "uniq_sys_user_phone";
|
||||||
|
/** 达梦数据库升提示。违反表[SYS_USER]唯一性约束 */
|
||||||
|
String SQL_INDEX_UNIQ_SYS_USER = "唯一性约束";
|
||||||
|
|
||||||
|
/** sys_user 表 email 唯一键索引 */
|
||||||
|
String SQL_INDEX_UNIQ_SYS_USER_EMAIL = "uniq_sys_user_email";
|
||||||
|
/** sys_quartz_job 表 job_class_name 唯一键索引 */
|
||||||
|
String SQL_INDEX_UNIQ_JOB_CLASS_NAME = "uniq_job_class_name";
|
||||||
|
/** sys_position 表 code 唯一键索引 */
|
||||||
|
String SQL_INDEX_UNIQ_CODE = "uniq_code";
|
||||||
|
/** sys_role 表 code 唯一键索引 */
|
||||||
|
String SQL_INDEX_UNIQ_SYS_ROLE_CODE = "uniq_sys_role_role_code";
|
||||||
|
/** sys_depart 表 code 唯一键索引 */
|
||||||
|
String SQL_INDEX_UNIQ_DEPART_ORG_CODE = "uniq_depart_org_code";
|
||||||
|
/** sys_category 表 code 唯一键索引 */
|
||||||
|
String SQL_INDEX_UNIQ_CATEGORY_CODE = "idx_sc_code";
|
||||||
|
/**
|
||||||
|
* 在线聊天 是否为默认分组
|
||||||
|
*/
|
||||||
|
String IM_DEFAULT_GROUP = "1";
|
||||||
|
/**
|
||||||
|
* 在线聊天 图片文件保存路径
|
||||||
|
*/
|
||||||
|
String IM_UPLOAD_CUSTOM_PATH = "biz/user_imgs";
|
||||||
|
/**
|
||||||
|
* 在线聊天 用户状态
|
||||||
|
*/
|
||||||
|
String IM_STATUS_ONLINE = "online";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 在线聊天 SOCKET消息类型
|
||||||
|
*/
|
||||||
|
String IM_SOCKET_TYPE = "chatMessage";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 在线聊天 是否开启默认添加好友 1是 0否
|
||||||
|
*/
|
||||||
|
String IM_DEFAULT_ADD_FRIEND = "1";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 在线聊天 用户好友缓存前缀
|
||||||
|
*/
|
||||||
|
String IM_PREFIX_USER_FRIEND_CACHE = "sys:cache:im:im_prefix_user_friend_";
|
||||||
|
/**
|
||||||
|
* 缓存用户id与用户名关系
|
||||||
|
*/
|
||||||
|
String SYS_USER_ID_MAPPING_CACHE = "sys:cache:user:id_mapping";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 系统角色管理员编码
|
||||||
|
*/
|
||||||
|
String SYS_ROLE_ADMIN = "admin";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 考勤补卡业务状态 (0:处理中)
|
||||||
|
*/
|
||||||
|
String SIGN_PATCH_BIZ_STATUS_0 = "0";
|
||||||
|
/**
|
||||||
|
* 考勤补卡业务状态 (1:同意 2:不同意)
|
||||||
|
*/
|
||||||
|
String SIGN_PATCH_BIZ_STATUS_1 = "1";
|
||||||
|
String SIGN_PATCH_BIZ_STATUS_2 = "2";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 公文文档上传自定义路径
|
||||||
|
*/
|
||||||
|
String UPLOAD_CUSTOM_PATH_OFFICIAL = "officialdoc";
|
||||||
|
/**
|
||||||
|
* 公文文档下载自定义路径
|
||||||
|
*/
|
||||||
|
String DOWNLOAD_CUSTOM_PATH_OFFICIAL = "officaldown";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* WPS存储值类别(1 code文号 2 text(WPS模板还是公文发文模板))
|
||||||
|
*/
|
||||||
|
String WPS_TYPE_1="1";
|
||||||
|
String WPS_TYPE_2="2";
|
||||||
|
|
||||||
|
|
||||||
|
/**===============================================================================================*/
|
||||||
|
/**
|
||||||
|
* ::非常重要::
|
||||||
|
* 注意:这四个常量值如果修改,需要与 Ghb-boot-starter/Ghb-boot-common/com.ghb.base.config.FeignConfig 类中的值保持一致。
|
||||||
|
*/
|
||||||
|
String X_ACCESS_TOKEN = "X-Access-Token";
|
||||||
|
String X_SIGN = "X-Sign";
|
||||||
|
String X_TIMESTAMP = "X-TIMESTAMP";
|
||||||
|
/** 租户请求头 更名为:X-Tenant-Id */
|
||||||
|
String TENANT_ID = "X-Tenant-Id";
|
||||||
|
/** 简流接口请求头,用于排除不支持的控件字段 */
|
||||||
|
String X_MiniFlowExclusionFieldMode = "X-Miniflowexclusionfieldmode";
|
||||||
|
/**===============================================================================================*/
|
||||||
|
|
||||||
|
String TOKEN_IS_INVALID_MSG = "Token失效,请重新登录!";
|
||||||
|
String X_FORWARDED_SCHEME = "X-Forwarded-Scheme";
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 微服务读取配置文件属性 服务地址
|
||||||
|
*/
|
||||||
|
String CLOUD_SERVER_KEY = "spring.cloud.nacos.discovery.server-addr";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 第三方登录 验证密码/创建用户 都需要设置一个操作码 防止被恶意调用
|
||||||
|
*/
|
||||||
|
String THIRD_LOGIN_CODE = "third_login_code";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 第三方APP同步方向:本地 --> 第三方APP
|
||||||
|
*/
|
||||||
|
String THIRD_SYNC_TO_APP = "SYNC_TO_APP";
|
||||||
|
/**
|
||||||
|
* 第三方APP同步方向:第三方APP --> 本地
|
||||||
|
*/
|
||||||
|
String THIRD_SYNC_TO_LOCAL = "SYNC_TO_LOCAL";
|
||||||
|
|
||||||
|
/** 系统通告消息状态:0=未发布 */
|
||||||
|
String ANNOUNCEMENT_SEND_STATUS_0 = "0";
|
||||||
|
/** 系统通告消息状态:1=已发布 */
|
||||||
|
String ANNOUNCEMENT_SEND_STATUS_1 = "1";
|
||||||
|
/** 系统通告消息状态:2=已撤销 */
|
||||||
|
String ANNOUNCEMENT_SEND_STATUS_2 = "2";
|
||||||
|
|
||||||
|
/**ONLINE 报表权限用 从request中获取地址栏后的参数*/
|
||||||
|
String ONL_REP_URL_PARAM_STR="onlRepUrlParamStr";
|
||||||
|
|
||||||
|
/**POST请求*/
|
||||||
|
String HTTP_POST = "POST";
|
||||||
|
|
||||||
|
/**PUT请求*/
|
||||||
|
String HTTP_PUT = "PUT";
|
||||||
|
|
||||||
|
/**PATCH请求*/
|
||||||
|
String HTTP_PATCH = "PATCH";
|
||||||
|
|
||||||
|
/**未知的*/
|
||||||
|
String UNKNOWN = "unknown";
|
||||||
|
|
||||||
|
/**字符串http*/
|
||||||
|
String STR_HTTP = "http";
|
||||||
|
|
||||||
|
/**String 类型的空值*/
|
||||||
|
String STRING_NULL = "null";
|
||||||
|
|
||||||
|
/**前端vue3版本Header参数名*/
|
||||||
|
String VERSION="X-Version";
|
||||||
|
|
||||||
|
String VERSION_V3 = "v3";
|
||||||
|
|
||||||
|
/**存储在线程变量里的动态表名*/
|
||||||
|
String DYNAMIC_TABLE_NAME="DYNAMIC_TABLE_NAME";
|
||||||
|
/**
|
||||||
|
* http:// http协议
|
||||||
|
*/
|
||||||
|
String HTTP_PROTOCOL = "http://";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* https:// https协议
|
||||||
|
*/
|
||||||
|
String HTTPS_PROTOCOL = "https://";
|
||||||
|
|
||||||
|
/** 部门表唯一key,id */
|
||||||
|
String DEPART_KEY_ID = "id";
|
||||||
|
/** 部门表唯一key,orgCode */
|
||||||
|
String DEPART_KEY_ORG_CODE = "orgCode";
|
||||||
|
|
||||||
|
/**======【消息推送相关】==============================================================================*/
|
||||||
|
/**
|
||||||
|
* 发消息 会传递一些信息到map
|
||||||
|
*/
|
||||||
|
String NOTICE_MSG_SUMMARY = "NOTICE_MSG_SUMMARY";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 发消息 会传递一个业务ID到map
|
||||||
|
*/
|
||||||
|
String NOTICE_MSG_BUS_ID = "NOTICE_MSG_BUS_ID";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 发消息 消息业务类型
|
||||||
|
*/
|
||||||
|
String NOTICE_MSG_BUS_TYPE = "NOTICE_MSG_BUS_TYPE";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 通知类型,用于区分来源 file 知识 flow 流程 plan 日程 system 系统消息
|
||||||
|
*/
|
||||||
|
String NOTICE_TYPE = "noticeType";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 邮箱消息中地址登录时地址后携带的token,需要替换成真实的token值
|
||||||
|
*/
|
||||||
|
String LOGIN_TOKEN = "{LOGIN_TOKEN}";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 模板消息中 跳转地址的对应的key
|
||||||
|
*/
|
||||||
|
String MSG_HREF_URL = "url";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* sys_data_log表的类型 用于区别评论区域的日志数据
|
||||||
|
*/
|
||||||
|
String DATA_LOG_TYPE_COMMENT = "comment";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* sys_data_log表的类型 老的数据比较 类型都设置为json
|
||||||
|
*/
|
||||||
|
String DATA_LOG_TYPE_JSON = "json";
|
||||||
|
|
||||||
|
/** 消息模板:markdown */
|
||||||
|
String MSG_TEMPLATE_TYPE_MD = "5";
|
||||||
|
/**========【消息推送相关】==========================================================================*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 短信验证码redis-key的前缀
|
||||||
|
*/
|
||||||
|
String PHONE_REDIS_KEY_PRE = "phone_msg";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是文件夹
|
||||||
|
*/
|
||||||
|
String IT_IS_FOLDER = "1";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 文件拥有者
|
||||||
|
*/
|
||||||
|
String FILE_OWNER = "owner";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 文件管理员
|
||||||
|
*/
|
||||||
|
String FILE_ADMIN = "admin";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 只允许编辑
|
||||||
|
*/
|
||||||
|
String FILE_EDITABLE = "editable";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 文件 只读
|
||||||
|
*/
|
||||||
|
String FILE_READONLY = "readonly";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 登录失败,用于记录失败次数的key
|
||||||
|
*/
|
||||||
|
String LOGIN_FAIL = "LOGIN_FAIL_";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 入职事件
|
||||||
|
*/
|
||||||
|
Integer BPM_USER_EVENT_ADD = 1;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 离职事件
|
||||||
|
*/
|
||||||
|
Integer BPM_USER_EVENT_LEVEL = 2;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户租户状态(正常/已通过审核的)
|
||||||
|
*/
|
||||||
|
String USER_TENANT_NORMAL = "1";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户租户状态(离职)
|
||||||
|
*/
|
||||||
|
String USER_TENANT_QUIT = "2";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户租户状态(审核中)
|
||||||
|
*/
|
||||||
|
String USER_TENANT_UNDER_REVIEW = "3";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户租户状态(拒绝)
|
||||||
|
*/
|
||||||
|
String USER_TENANT_REFUSE = "4";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户租户状态(邀请)
|
||||||
|
*/
|
||||||
|
String USER_TENANT_INVITE = "5";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 不是叶子节点
|
||||||
|
*/
|
||||||
|
Integer NOT_LEAF = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是叶子节点
|
||||||
|
*/
|
||||||
|
Integer IS_LEAF = 1;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 钉钉
|
||||||
|
*/
|
||||||
|
String DINGTALK = "DINGTALK";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 企业微信
|
||||||
|
*/
|
||||||
|
String WECHAT_ENTERPRISE = "WECHAT_ENTERPRISE";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 系统默认租户id 0
|
||||||
|
*/
|
||||||
|
Integer TENANT_ID_DEFAULT_VALUE = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 【low-app用】 应用级别的复制
|
||||||
|
*/
|
||||||
|
String COPY_LEVEL_APP = "app";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 【low-app用】 菜单级别的复制
|
||||||
|
*/
|
||||||
|
String COPY_LEVEL_MENU = "menu";
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 【low-app用】 应用备份
|
||||||
|
*/
|
||||||
|
String COPY_LEVEL_BAK = "backup";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 【low-app用】 从备份还原
|
||||||
|
*/
|
||||||
|
String COPY_LEVEL_COVER = "cover";
|
||||||
|
|
||||||
|
/** 【QQYUN-6034】关联字段变更历史值,缓存半个小时 */
|
||||||
|
String CACHE_REL_FIELD_OLD_VAL = "sys:cache:desform:relFieldOldVal:";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 排序类型:升序
|
||||||
|
*/
|
||||||
|
String ORDER_TYPE_ASC = "ASC";
|
||||||
|
/**
|
||||||
|
* 排序类型:降序
|
||||||
|
*/
|
||||||
|
String ORDER_TYPE_DESC = "DESC";
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 报表允许设计开发的角色
|
||||||
|
*/
|
||||||
|
public static String[] allowDevRoles = new String[]{"lowdeveloper", "admin"};
|
||||||
|
/**
|
||||||
|
* 【对应积木报表的常量】
|
||||||
|
* 数据隔离模式: 按照创建人隔离
|
||||||
|
*/
|
||||||
|
public static final String SAAS_MODE_CREATED = "created";
|
||||||
|
/**
|
||||||
|
* 【对应积木报表的常量】
|
||||||
|
* 数据隔离模式: 按照租户隔离
|
||||||
|
*/
|
||||||
|
public static final String SAAS_MODE_TENANT = "tenant";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 修改手机号短信验证码redis-key的前缀
|
||||||
|
*/
|
||||||
|
String CHANGE_PHONE_REDIS_KEY_PRE = "sys:cache:phone:change_phone_msg:";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 手机号短信验证码redis-key的前缀
|
||||||
|
*/
|
||||||
|
String LOG_OFF_PHONE_REDIS_KEY_PRE = "sys:cache:phone:qqy_log_off_user_msg:";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 缓存用户最后一次收到消息通知的时间 KEY
|
||||||
|
*/
|
||||||
|
String CACHE_KEY_USER_LAST_ANNOUNT_TIME_1HOUR = "sys:cache:userinfo:user_last_annount_time::%s";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 验证原手机号
|
||||||
|
*/
|
||||||
|
String VERIFY_ORIGINAL_PHONE = "verifyOriginalPhone";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 修改手机号
|
||||||
|
*/
|
||||||
|
String UPDATE_PHONE = "updatePhone";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 修改手机号验证码请求次数超出
|
||||||
|
*/
|
||||||
|
Integer PHONE_SMS_FAIL_CODE = 40002;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 自定义首页关联关系(ROLE:表示角色 USER:表示用户 DEFAULT:默认首页)
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
String HOME_RELATION_ROLE = "ROLE";
|
||||||
|
String HOME_RELATION_USER = "USER";
|
||||||
|
String HOME_RELATION_DEFAULT = "DEFAULT";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否置顶(0否 1是)
|
||||||
|
*/
|
||||||
|
Integer IZ_TOP_1 = 1;
|
||||||
|
Integer IZ_TOP_0 = 0;
|
||||||
|
|
||||||
|
|
||||||
|
//关注流程缓存前缀
|
||||||
|
String FLOW_FOCUS_NOTICE_PREFIX = "flow:runtimeData:focus:notice:";
|
||||||
|
//任务缓办时间缓存前缀
|
||||||
|
String FLOW_TASK_DELAY_PREFIX = "flow:runtimeData:task:delay:";
|
||||||
|
/**
|
||||||
|
* 用户代理类型:离职:quit 代理:agent
|
||||||
|
*/
|
||||||
|
String USER_AGENT_TYPE_QUIT = "quit";
|
||||||
|
String USER_AGENT_TYPE_AGENT = "agent";
|
||||||
|
/**
|
||||||
|
* 督办流程首节点任务taskKey
|
||||||
|
*/
|
||||||
|
String SUPERVISE_FIRST_TASK_KEY = "Task_1bhxpt0";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* wps模板预览数据缓存前缀
|
||||||
|
*/
|
||||||
|
String EOA_WPS_TEMPLATE_VIEW_DATA ="eoa:wps:templateViewData:";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* wps模板预览版本号缓存前缀
|
||||||
|
*/
|
||||||
|
String EOA_WPS_TEMPLATE_VIEW_VERSION ="eoa:wps:templateViewVersion:";
|
||||||
|
/**
|
||||||
|
* 表单设计器oa新增字段
|
||||||
|
* x_oa_timeout_date:逾期时间
|
||||||
|
* x_oa_archive_status:归档状态
|
||||||
|
*/
|
||||||
|
String X_OA_TIMEOUT_DATE ="x_oa_timeout_date";
|
||||||
|
String X_OA_ARCHIVE_STATUS ="x_oa_archive_status";
|
||||||
|
/**
|
||||||
|
* 流程状态
|
||||||
|
* 待提交: 1
|
||||||
|
* 处理中: 2
|
||||||
|
* 已完成: 3
|
||||||
|
* 已作废: 4
|
||||||
|
* 已挂起: 5
|
||||||
|
*/
|
||||||
|
String BPM_STATUS_1 ="1";
|
||||||
|
String BPM_STATUS_2 ="2";
|
||||||
|
String BPM_STATUS_3 ="3";
|
||||||
|
String BPM_STATUS_4 ="4";
|
||||||
|
String BPM_STATUS_5 ="5";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 默认租户产品包
|
||||||
|
*/
|
||||||
|
String TENANT_PACK_DEFAULT = "default";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 部门名称redisKey(全路径)
|
||||||
|
*/
|
||||||
|
String DEPART_NAME_REDIS_KEY_PRE = "sys:cache:departPathName:";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 默认用户排序值
|
||||||
|
*/
|
||||||
|
Integer DEFAULT_USER_SORT = 1000;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 发送短信方式:腾讯
|
||||||
|
*/
|
||||||
|
String SMS_SEND_TYPE_TENCENT = "tencent";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 发送短信方式:阿里云
|
||||||
|
*/
|
||||||
|
String SMS_SEND_TYPE_ALI_YUN = "aliyun";
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,48 @@
|
||||||
|
package com.ghb.base.common.constant;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 系统通告 - 发布状态
|
||||||
|
* @Author LeeShaoQing
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public interface CommonSendStatus {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 未发布
|
||||||
|
*/
|
||||||
|
public static final String UNPUBLISHED_STATUS_0 = "0";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 已发布
|
||||||
|
*/
|
||||||
|
public static final String PUBLISHED_STATUS_1 = "1";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 撤销
|
||||||
|
*/
|
||||||
|
public static final String REVOKE_STATUS_2 = "2";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* app端推送会话标识后缀
|
||||||
|
*/
|
||||||
|
public static final String APP_SESSION_SUFFIX = "_app";
|
||||||
|
|
||||||
|
|
||||||
|
/**-----【流程相关通知模板code】------------------------------------------------------------*/
|
||||||
|
/**流程催办——系统通知消息模板*/
|
||||||
|
public static final String TZMB_BPM_CUIBAN = "bpm_cuiban";
|
||||||
|
/**流程抄送——系统通知消息模板*/
|
||||||
|
public static final String TZMB_BPM_CC = "bpm_cc";
|
||||||
|
/**流程催办——邮件通知消息模板*/
|
||||||
|
public static final String TZMB_BPM_CUIBAN_EMAIL = "bpm_cuiban_email";
|
||||||
|
/**标准模板—系统消息通知*/
|
||||||
|
public static final String TZMB_SYS_TS_NOTE = "sys_ts_note";
|
||||||
|
/**流程超时提醒——系统通知消息模板*/
|
||||||
|
public static final String TZMB_BPM_CHAOSHI_TIP = "bpm_chaoshi_tip";
|
||||||
|
/**-----【流程相关通知模板code】-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 系统通知拓展参数(比如:用于流程抄送和催办通知,这里额外传递流程跳转页面所需要的路由参数)
|
||||||
|
*/
|
||||||
|
public static final String MSG_ABSTRACT_JSON = "msg_abstract";
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,196 @@
|
||||||
|
package com.ghb.base.common.constant;
|
||||||
|
/**
|
||||||
|
* 数据库上下文常量
|
||||||
|
* @author: Ghb-boot
|
||||||
|
*/
|
||||||
|
public interface DataBaseConstant {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 内置的系统变量键列表
|
||||||
|
*/
|
||||||
|
public static final String[] SYSTEM_KEYS = {
|
||||||
|
DataBaseConstant.SYS_ORG_CODE, DataBaseConstant.SYS_ORG_CODE_TABLE, DataBaseConstant.SYS_MULTI_ORG_CODE,
|
||||||
|
DataBaseConstant.SYS_MULTI_ORG_CODE_TABLE, DataBaseConstant.SYS_ORG_ID, DataBaseConstant.SYS_ORG_ID_TABLE,
|
||||||
|
DataBaseConstant.SYS_ROLE_CODE, DataBaseConstant.SYS_ROLE_CODE_TABLE, DataBaseConstant.SYS_USER_CODE,
|
||||||
|
DataBaseConstant.SYS_USER_CODE_TABLE, DataBaseConstant.SYS_USER_ID, DataBaseConstant.SYS_USER_ID_TABLE,
|
||||||
|
DataBaseConstant.SYS_USER_NAME, DataBaseConstant.SYS_USER_NAME_TABLE, DataBaseConstant.SYS_DATE,
|
||||||
|
DataBaseConstant.SYS_DATE_TABLE, DataBaseConstant.SYS_TIME, DataBaseConstant.SYS_TIME_TABLE,
|
||||||
|
DataBaseConstant.SYS_BASE_PATH
|
||||||
|
};
|
||||||
|
|
||||||
|
//*********数据库类型****************************************
|
||||||
|
|
||||||
|
/**MYSQL数据库*/
|
||||||
|
public static final String DB_TYPE_MYSQL = "MYSQL";
|
||||||
|
|
||||||
|
/** ORACLE*/
|
||||||
|
public static final String DB_TYPE_ORACLE = "ORACLE";
|
||||||
|
|
||||||
|
/**达梦数据库*/
|
||||||
|
public static final String DB_TYPE_DM = "DM";
|
||||||
|
|
||||||
|
/**postgreSQL达梦数据库*/
|
||||||
|
public static final String DB_TYPE_POSTGRESQL = "POSTGRESQL";
|
||||||
|
|
||||||
|
/**人大金仓数据库*/
|
||||||
|
public static final String DB_TYPE_KINGBASEES = "KINGBASEES";
|
||||||
|
|
||||||
|
/**sqlserver数据库*/
|
||||||
|
public static final String DB_TYPE_SQLSERVER = "SQLSERVER";
|
||||||
|
|
||||||
|
/**mariadb 数据库*/
|
||||||
|
public static final String DB_TYPE_MARIADB = "MARIADB";
|
||||||
|
|
||||||
|
/**DB2 数据库*/
|
||||||
|
public static final String DB_TYPE_DB2 = "DB2";
|
||||||
|
|
||||||
|
/**HSQL 数据库*/
|
||||||
|
public static final String DB_TYPE_HSQL = "HSQL";
|
||||||
|
|
||||||
|
// // 数据库类型,对应 database_type 字典
|
||||||
|
// public static final String DB_TYPE_MYSQL_NUM = "1";
|
||||||
|
// public static final String DB_TYPE_MYSQL7_NUM = "6";
|
||||||
|
// public static final String DB_TYPE_ORACLE_NUM = "2";
|
||||||
|
// public static final String DB_TYPE_SQLSERVER_NUM = "3";
|
||||||
|
// public static final String DB_TYPE_POSTGRESQL_NUM = "4";
|
||||||
|
// public static final String DB_TYPE_MARIADB_NUM = "5";
|
||||||
|
|
||||||
|
//*********系统上下文变量****************************************
|
||||||
|
/**
|
||||||
|
* 数据-所属机构编码
|
||||||
|
*/
|
||||||
|
public static final String SYS_ORG_CODE = "sysOrgCode";
|
||||||
|
/**
|
||||||
|
* 数据-所属机构编码
|
||||||
|
*/
|
||||||
|
public static final String SYS_ORG_CODE_TABLE = "sys_org_code";
|
||||||
|
/**
|
||||||
|
* 数据-所属机构编码
|
||||||
|
*/
|
||||||
|
public static final String SYS_MULTI_ORG_CODE = "sysMultiOrgCode";
|
||||||
|
/**
|
||||||
|
* 数据-所属机构编码
|
||||||
|
*/
|
||||||
|
public static final String SYS_MULTI_ORG_CODE_TABLE = "sys_multi_org_code";
|
||||||
|
/**
|
||||||
|
* 数据-所属机构ID
|
||||||
|
*/
|
||||||
|
public static final String SYS_ORG_ID = "sysOrgId";
|
||||||
|
/**
|
||||||
|
* 数据-所属机构ID
|
||||||
|
*/
|
||||||
|
public static final String SYS_ORG_ID_TABLE = "sys_org_id";
|
||||||
|
/**
|
||||||
|
* 数据-所属角色code(多个逗号分割)
|
||||||
|
*/
|
||||||
|
public static final String SYS_ROLE_CODE = "sysRoleCode";
|
||||||
|
/**
|
||||||
|
* 数据-所属角色code(多个逗号分割)
|
||||||
|
*/
|
||||||
|
public static final String SYS_ROLE_CODE_TABLE = "sys_role_code";
|
||||||
|
/**
|
||||||
|
* 数据-系统用户编码(对应登录用户账号)
|
||||||
|
*/
|
||||||
|
public static final String SYS_USER_CODE = "sysUserCode";
|
||||||
|
/**
|
||||||
|
* 数据-系统用户编码(对应登录用户账号)
|
||||||
|
*/
|
||||||
|
public static final String SYS_USER_CODE_TABLE = "sys_user_code";
|
||||||
|
/**
|
||||||
|
* 登录用户ID
|
||||||
|
*/
|
||||||
|
public static final String SYS_USER_ID = "sysUserId";
|
||||||
|
/**
|
||||||
|
* 登录用户ID
|
||||||
|
*/
|
||||||
|
public static final String SYS_USER_ID_TABLE = "sys_user_id";
|
||||||
|
/**
|
||||||
|
* 登录用户真实姓名
|
||||||
|
*/
|
||||||
|
public static final String SYS_USER_NAME = "sysUserName";
|
||||||
|
/**
|
||||||
|
* 登录用户真实姓名
|
||||||
|
*/
|
||||||
|
public static final String SYS_USER_NAME_TABLE = "sys_user_name";
|
||||||
|
/**
|
||||||
|
* 系统日期"yyyy-MM-dd"
|
||||||
|
*/
|
||||||
|
public static final String SYS_DATE = "sysDate";
|
||||||
|
/**
|
||||||
|
* 系统日期"yyyy-MM-dd"
|
||||||
|
*/
|
||||||
|
public static final String SYS_DATE_TABLE = "sys_date";
|
||||||
|
/**
|
||||||
|
* 系统时间"yyyy-MM-dd HH:mm"
|
||||||
|
*/
|
||||||
|
public static final String SYS_TIME = "sysTime";
|
||||||
|
/**
|
||||||
|
* 系统时间"yyyy-MM-dd HH:mm"
|
||||||
|
*/
|
||||||
|
public static final String SYS_TIME_TABLE = "sys_time";
|
||||||
|
/**
|
||||||
|
* 数据-所属机构编码
|
||||||
|
*/
|
||||||
|
public static final String SYS_BASE_PATH = "sys_base_path";
|
||||||
|
//*********系统上下文变量****************************************
|
||||||
|
|
||||||
|
|
||||||
|
//*********系统建表标准字段****************************************
|
||||||
|
/**
|
||||||
|
* 创建者登录名称
|
||||||
|
*/
|
||||||
|
public static final String CREATE_BY_TABLE = "create_by";
|
||||||
|
/**
|
||||||
|
* 创建者登录名称
|
||||||
|
*/
|
||||||
|
public static final String CREATE_BY = "createBy";
|
||||||
|
/**
|
||||||
|
* 创建日期时间
|
||||||
|
*/
|
||||||
|
public static final String CREATE_TIME_TABLE = "create_time";
|
||||||
|
/**
|
||||||
|
* 创建日期时间
|
||||||
|
*/
|
||||||
|
public static final String CREATE_TIME = "createTime";
|
||||||
|
/**
|
||||||
|
* 更新用户登录名称
|
||||||
|
*/
|
||||||
|
public static final String UPDATE_BY_TABLE = "update_by";
|
||||||
|
/**
|
||||||
|
* 更新用户登录名称
|
||||||
|
*/
|
||||||
|
public static final String UPDATE_BY = "updateBy";
|
||||||
|
/**
|
||||||
|
* 更新日期时间
|
||||||
|
*/
|
||||||
|
public static final String UPDATE_TIME = "updateTime";
|
||||||
|
/**
|
||||||
|
* 更新日期时间
|
||||||
|
*/
|
||||||
|
public static final String UPDATE_TIME_TABLE = "update_time";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 业务流程状态
|
||||||
|
*/
|
||||||
|
public static final String BPM_STATUS = "bpmStatus";
|
||||||
|
/**
|
||||||
|
* 业务流程状态
|
||||||
|
*/
|
||||||
|
public static final String BPM_STATUS_TABLE = "bpm_status";
|
||||||
|
//*********系统建表标准字段****************************************
|
||||||
|
|
||||||
|
/**
|
||||||
|
* sql语句 where
|
||||||
|
*/
|
||||||
|
String SQL_WHERE = "where";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* sql语句 asc
|
||||||
|
*/
|
||||||
|
String SQL_ASC = "asc";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* sqlserver数据库,中间有空格
|
||||||
|
*/
|
||||||
|
String DB_TYPE_SQL_SERVER_BLANK = "sql server";
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,16 @@
|
||||||
|
package com.ghb.base.common.constant;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 动态切换表配置常量
|
||||||
|
*
|
||||||
|
* @author: scott
|
||||||
|
* @date: 2022年04月25日 22:30
|
||||||
|
*/
|
||||||
|
public class DynamicTableConstant {
|
||||||
|
/**
|
||||||
|
* 角色首页配置表
|
||||||
|
* vue2表名: sys_role_index
|
||||||
|
* vue3表名: sys_role_index_vue3
|
||||||
|
*/
|
||||||
|
public static final String SYS_ROLE_INDEX = "sys_role_index";
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,25 @@
|
||||||
|
package com.ghb.base.common.constant;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 规则值生成 编码常量类
|
||||||
|
* @author: taoyan
|
||||||
|
* @date: 2020年04月02日
|
||||||
|
*/
|
||||||
|
public class FillRuleConstant {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 公文发文编码
|
||||||
|
*/
|
||||||
|
public static final String DOC_SEND = "doc_send_code";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 部门编码
|
||||||
|
*/
|
||||||
|
public static final String DEPART = "org_num_role";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 分类字典编码
|
||||||
|
*/
|
||||||
|
public static final String CATEGORY = "category_code_rule";
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,15 @@
|
||||||
|
package com.ghb.base.common.constant;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Description: 密码常量类
|
||||||
|
*
|
||||||
|
* @author: wangshuai
|
||||||
|
* @date: 2025/8/27 20:10
|
||||||
|
*/
|
||||||
|
public interface PasswordConstant {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 导入用户默认密码
|
||||||
|
*/
|
||||||
|
String DEFAULT_PASSWORD = "123456";
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,219 @@
|
||||||
|
package com.ghb.base.common.constant;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson.JSONObject;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import com.ghb.base.common.util.oConvertUtils;
|
||||||
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
|
import org.springframework.core.io.Resource;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Scanner;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Description: 省市区
|
||||||
|
* @author: Ghb-boot
|
||||||
|
*/
|
||||||
|
@Component("pca")
|
||||||
|
public class ProvinceCityArea {
|
||||||
|
List<Area> areaList;
|
||||||
|
|
||||||
|
public String getText(String code){
|
||||||
|
if(StringUtils.isNotBlank(code)){
|
||||||
|
this.initAreaList();
|
||||||
|
if(this.areaList!=null || this.areaList.size()>0){
|
||||||
|
List<String> ls = new ArrayList<String>();
|
||||||
|
getAreaByCode(code,ls);
|
||||||
|
return String.join("/",ls);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getCode(String text){
|
||||||
|
if(StringUtils.isNotBlank(text)){
|
||||||
|
this.initAreaList();
|
||||||
|
if(areaList!=null && areaList.size()>0){
|
||||||
|
for(int i=areaList.size()-1;i>=0;i--){
|
||||||
|
// 代码逻辑说明: VUEN-1088 online 导入 省市区导入后 导入数据错乱 北京市/市辖区/西城区-->山西省/晋城市/城区
|
||||||
|
String areaText = areaList.get(i).getText();
|
||||||
|
String cityText = areaList.get(i).getAheadText();
|
||||||
|
if(text.indexOf(areaText)>=0 && (cityText!=null && text.indexOf(cityText)>=0)){
|
||||||
|
return areaList.get(i).getId();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取省市区code,精准匹配
|
||||||
|
* @param texts 文本数组,省,市,区
|
||||||
|
* @return 返回 省市区的code
|
||||||
|
*/
|
||||||
|
public String[] getCode(String[] texts) {
|
||||||
|
if (texts == null || texts.length == 0) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
this.initAreaList();
|
||||||
|
if (areaList == null || areaList.size() == 0) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
String[] codes = new String[texts.length];
|
||||||
|
String code = null;
|
||||||
|
for (int i = 0; i < texts.length; i++) {
|
||||||
|
String text = texts[i];
|
||||||
|
Area area;
|
||||||
|
if (code == null) {
|
||||||
|
area = getAreaByText(text);
|
||||||
|
} else {
|
||||||
|
area = getAreaByPidAndText(code, text);
|
||||||
|
}
|
||||||
|
if (area != null) {
|
||||||
|
code = area.id;
|
||||||
|
codes[i] = code;
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return codes;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据text获取area
|
||||||
|
* @param text
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public Area getAreaByText(String text) {
|
||||||
|
for (Area area : areaList) {
|
||||||
|
if (text.equals(area.getText())) {
|
||||||
|
return area;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 通过pid获取 area 对象
|
||||||
|
* @param pCode 父级编码
|
||||||
|
* @param text
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public Area getAreaByPidAndText(String pCode, String text) {
|
||||||
|
this.initAreaList();
|
||||||
|
if (this.areaList != null && this.areaList.size() > 0) {
|
||||||
|
for (Area area : this.areaList) {
|
||||||
|
if (area.getPid().equals(pCode) && area.getText().equals(text)) {
|
||||||
|
return area;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void getAreaByCode(String code,List<String> ls){
|
||||||
|
for(Area area: areaList){
|
||||||
|
if(null != area && area.getId().equals(code)){
|
||||||
|
String pid = area.getPid();
|
||||||
|
ls.add(0,area.getText());
|
||||||
|
getAreaByCode(pid,ls);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initAreaList(){
|
||||||
|
//System.out.println("=====================");
|
||||||
|
if(this.areaList==null || this.areaList.size()==0){
|
||||||
|
this.areaList = new ArrayList<Area>();
|
||||||
|
try {
|
||||||
|
String jsonData = oConvertUtils.readStatic("classpath:static/pca.json");
|
||||||
|
JSONObject baseJson = JSONObject.parseObject(jsonData);
|
||||||
|
//第一层 省
|
||||||
|
JSONObject provinceJson = baseJson.getJSONObject("86");
|
||||||
|
for(String provinceKey: provinceJson.keySet()){
|
||||||
|
//System.out.println("===="+provinceKey);
|
||||||
|
Area province = new Area(provinceKey,provinceJson.getString(provinceKey),"86");
|
||||||
|
this.areaList.add(province);
|
||||||
|
//第二层 市
|
||||||
|
JSONObject cityJson = baseJson.getJSONObject(provinceKey);
|
||||||
|
for(String cityKey:cityJson.keySet()){
|
||||||
|
//System.out.println("-----"+cityKey);
|
||||||
|
Area city = new Area(cityKey,cityJson.getString(cityKey),provinceKey);
|
||||||
|
this.areaList.add(city);
|
||||||
|
//第三层 区
|
||||||
|
JSONObject areaJson = baseJson.getJSONObject(cityKey);
|
||||||
|
if(areaJson!=null){
|
||||||
|
for(String areaKey:areaJson.keySet()){
|
||||||
|
//System.out.println("········"+areaKey);
|
||||||
|
Area area = new Area(areaKey,areaJson.getString(areaKey),cityKey);
|
||||||
|
// 代码逻辑说明: VUEN-1088 online 导入 省市区导入后 导入数据错乱 北京市/市辖区/西城区-->山西省/晋城市/城区
|
||||||
|
area.setAheadText(cityJson.getString(cityKey));
|
||||||
|
this.areaList.add(area);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private String jsonRead(File file){
|
||||||
|
Scanner scanner = null;
|
||||||
|
StringBuilder buffer = new StringBuilder();
|
||||||
|
try {
|
||||||
|
scanner = new Scanner(file, "utf-8");
|
||||||
|
while (scanner.hasNextLine()) {
|
||||||
|
buffer.append(scanner.nextLine());
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
|
||||||
|
} finally {
|
||||||
|
if (scanner != null) {
|
||||||
|
scanner.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return buffer.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
class Area{
|
||||||
|
String id;
|
||||||
|
String text;
|
||||||
|
String pid;
|
||||||
|
// 用于存储上级文本数据,区的上级文本 是市的数据
|
||||||
|
String aheadText;
|
||||||
|
|
||||||
|
public Area(String id,String text,String pid){
|
||||||
|
this.id = id;
|
||||||
|
this.text = text;
|
||||||
|
this.pid = pid;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getText() {
|
||||||
|
return text;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPid() {
|
||||||
|
return pid;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getAheadText() {
|
||||||
|
return aheadText;
|
||||||
|
}
|
||||||
|
public void setAheadText(String aheadText) {
|
||||||
|
this.aheadText = aheadText;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,59 @@
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
* * Copyright (c) 2019-2020, 冷冷 (wangiegie@gmail.com).
|
||||||
|
* * <p>
|
||||||
|
* * Licensed under the GNU Lesser General Public License 3.0 (the "License");
|
||||||
|
* * you may not use this file except in compliance with the License.
|
||||||
|
* * You may obtain a copy of the License at
|
||||||
|
* * <p>
|
||||||
|
* * https://www.gnu.org/licenses/lgpl.html
|
||||||
|
* * <p>
|
||||||
|
* * Unless required by applicable law or agreed to in writing, software
|
||||||
|
* * distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* * See the License for the specific language governing permissions and
|
||||||
|
* * limitations under the License.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.ghb.base.common.constant;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author scott
|
||||||
|
* @date 2019年05月18日
|
||||||
|
* 服务名称
|
||||||
|
*/
|
||||||
|
public interface ServiceNameConstants {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 微服务名:系统管理模块
|
||||||
|
*/
|
||||||
|
String SERVICE_SYSTEM = "Ghb-system";
|
||||||
|
/**
|
||||||
|
* 微服务名: demo模块
|
||||||
|
*/
|
||||||
|
String SERVICE_DEMO = "Ghb-demo";
|
||||||
|
/**
|
||||||
|
* 微服务名:joa模块
|
||||||
|
*/
|
||||||
|
String SERVICE_JOA = "Ghb-joa";
|
||||||
|
|
||||||
|
// /**
|
||||||
|
// * 微服务名:online在线模块
|
||||||
|
// */
|
||||||
|
// String SERVICE_ONLINE = "Ghb-online";
|
||||||
|
// /**
|
||||||
|
// * 微服务名:OA模块
|
||||||
|
// */
|
||||||
|
// String SERVICE_EOA = "Ghb-eoa";
|
||||||
|
// /**
|
||||||
|
// * 微服务名:表单设计模块
|
||||||
|
// */
|
||||||
|
// String SERVICE_FORM = "Ghb-desform";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gateway通过header传递根路径 basePath
|
||||||
|
*/
|
||||||
|
String X_GATEWAY_BASE_PATH = "X_GATEWAY_BASE_PATH";
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,123 @@
|
||||||
|
package com.ghb.base.common.constant;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Description: 符号和特殊符号常用类
|
||||||
|
* @author: wangshuai
|
||||||
|
* @date: 2022年03月30日 17:44
|
||||||
|
*/
|
||||||
|
public class SymbolConstant {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 符号:点
|
||||||
|
*/
|
||||||
|
public static final String SPOT = ".";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 符号:双斜杠
|
||||||
|
*/
|
||||||
|
public static final String DOUBLE_BACKSLASH = "\\";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 符号:冒号
|
||||||
|
*/
|
||||||
|
public static final String COLON = ":";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 符号:逗号
|
||||||
|
*/
|
||||||
|
public static final String COMMA = ",";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 符号:左花括号 }
|
||||||
|
*/
|
||||||
|
public static final String LEFT_CURLY_BRACKET = "{";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 符号:右花括号 }
|
||||||
|
*/
|
||||||
|
public static final String RIGHT_CURLY_BRACKET = "}";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 符号:井号 #
|
||||||
|
*/
|
||||||
|
public static final String WELL_NUMBER = "#";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 符号:单斜杠
|
||||||
|
*/
|
||||||
|
public static final String SINGLE_SLASH = "/";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 符号:双斜杠
|
||||||
|
*/
|
||||||
|
public static final String DOUBLE_SLASH = "//";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 符号:感叹号
|
||||||
|
*/
|
||||||
|
public static final String EXCLAMATORY_MARK = "!";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 符号:下划线
|
||||||
|
*/
|
||||||
|
public static final String UNDERLINE = "_";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 符号:单引号
|
||||||
|
*/
|
||||||
|
public static final String SINGLE_QUOTATION_MARK = "'";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 符号:星号
|
||||||
|
*/
|
||||||
|
public static final String ASTERISK = "*";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 符号:百分号
|
||||||
|
*/
|
||||||
|
public static final String PERCENT_SIGN = "%";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 符号:美元 $
|
||||||
|
*/
|
||||||
|
public static final String DOLLAR = "$";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 符号:和 &
|
||||||
|
*/
|
||||||
|
public static final String AND = "&";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 符号:../
|
||||||
|
*/
|
||||||
|
public static final String SPOT_SINGLE_SLASH = "../";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 符号:..\\
|
||||||
|
*/
|
||||||
|
public static final String SPOT_DOUBLE_BACKSLASH = "..\\";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 系统变量前缀 #{
|
||||||
|
*/
|
||||||
|
public static final String SYS_VAR_PREFIX = "#{";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 符号 {{
|
||||||
|
*/
|
||||||
|
public static final String DOUBLE_LEFT_CURLY_BRACKET = "{{";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 符号:[
|
||||||
|
*/
|
||||||
|
public static final String SQUARE_BRACKETS_LEFT = "[";
|
||||||
|
/**
|
||||||
|
* 符号:]
|
||||||
|
*/
|
||||||
|
public static final String SQUARE_BRACKETS_RIGHT = "]";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 拼接字符串符号 分号 ;
|
||||||
|
*/
|
||||||
|
public static final String SEMICOLON = ";";
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,54 @@
|
||||||
|
package com.ghb.base.common.constant;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Description: TenantConstant
|
||||||
|
* @author: scott
|
||||||
|
* @date: 2022年08月29日 15:29
|
||||||
|
*/
|
||||||
|
public interface TenantConstant {
|
||||||
|
/*------【低代码应用参数】----------------------------------------------*/
|
||||||
|
/**
|
||||||
|
* header的lowAppId标识
|
||||||
|
*/
|
||||||
|
String X_LOW_APP_ID = "X-Low-App-ID";
|
||||||
|
/**
|
||||||
|
* 应用ID——实体字段
|
||||||
|
*/
|
||||||
|
String FIELD_LOW_APP_ID = "lowAppId";
|
||||||
|
/**
|
||||||
|
* 应用ID——表字段
|
||||||
|
*/
|
||||||
|
String DB_FIELD_LOW_APP_ID = "low_app_id";
|
||||||
|
/*------【低代码应用参数】---------------------------------------------*/
|
||||||
|
|
||||||
|
/*--------【租户参数】-----------------------------------------------*/
|
||||||
|
/**
|
||||||
|
* 租户ID(实体字段名 和 url参数名)
|
||||||
|
*/
|
||||||
|
String TENANT_ID = "tenantId";
|
||||||
|
/**
|
||||||
|
* 租户ID 数据库字段名
|
||||||
|
*/
|
||||||
|
String TENANT_ID_TABLE = "tenant_id";
|
||||||
|
/*-------【租户参数】-----------------------------------------------*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 超级管理员
|
||||||
|
*/
|
||||||
|
String SUPER_ADMIN = "superAdmin";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 组织账户管理员
|
||||||
|
*/
|
||||||
|
String ACCOUNT_ADMIN = "accountAdmin";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 组织应用管理员
|
||||||
|
*/
|
||||||
|
String APP_ADMIN = "appAdmin";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 增加SignatureCheck注解POST请求的URL
|
||||||
|
*/
|
||||||
|
String[] SIGNATURE_CHECK_POST_URL = { "/sys/tenant/joinTenantByHouseNumber", "/sys/tenant/invitationUser" };
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,31 @@
|
||||||
|
package com.ghb.base.common.constant;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* VXESocket 常量
|
||||||
|
* @author: Ghb-boot
|
||||||
|
*/
|
||||||
|
public class VxeSocketConst {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 消息类型
|
||||||
|
*/
|
||||||
|
public static final String TYPE = "type";
|
||||||
|
/**
|
||||||
|
* 消息数据
|
||||||
|
*/
|
||||||
|
public static final String DATA = "data";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 消息类型:心跳检测
|
||||||
|
*/
|
||||||
|
public static final String TYPE_HB = "heart_beat";
|
||||||
|
/**
|
||||||
|
* 消息类型:通用数据传递
|
||||||
|
*/
|
||||||
|
public static final String TYPE_CSD = "common_send_date";
|
||||||
|
/**
|
||||||
|
* 消息类型:更新vxe table数据
|
||||||
|
*/
|
||||||
|
public static final String TYPE_UVT = "update_vxe_table";
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,66 @@
|
||||||
|
package com.ghb.base.common.constant;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Description: Websocket常量类
|
||||||
|
* @author: taoyan
|
||||||
|
* @date: 2020年03月23日
|
||||||
|
*/
|
||||||
|
public class WebsocketConst {
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 消息json key:cmd
|
||||||
|
*/
|
||||||
|
public static final String MSG_CMD = "cmd";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 消息json key:msgId
|
||||||
|
*/
|
||||||
|
public static final String MSG_ID = "msgId";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 消息json key:msgTxt
|
||||||
|
*/
|
||||||
|
public static final String MSG_TXT = "msgTxt";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 消息json key:userId
|
||||||
|
*/
|
||||||
|
public static final String MSG_USER_ID = "userId";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 消息json key:chat
|
||||||
|
*/
|
||||||
|
public static final String MSG_CHAT = "chat";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 消息类型 heartcheck
|
||||||
|
*/
|
||||||
|
public static final String CMD_CHECK = "heartcheck";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 消息类型 user 用户消息
|
||||||
|
*/
|
||||||
|
public static final String CMD_USER = "user";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 消息类型 topic 系统通知
|
||||||
|
*/
|
||||||
|
public static final String CMD_TOPIC = "topic";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 消息类型 email
|
||||||
|
*/
|
||||||
|
public static final String CMD_EMAIL = "email";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 消息类型 meetingsign 会议签到
|
||||||
|
*/
|
||||||
|
public static final String CMD_SIGN = "sign";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 消息类型 新闻发布/取消
|
||||||
|
*/
|
||||||
|
public static final String NEWS_PUBLISH = "publish";
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,167 @@
|
||||||
|
package com.ghb.base.common.constant.enums;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* online表单枚举 代码生成器用到
|
||||||
|
* @author: Ghb-boot
|
||||||
|
*/
|
||||||
|
public enum CgformEnum {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 单表
|
||||||
|
*/
|
||||||
|
ONE(1, "one", "/Ghb/code-template-online", "default.one", "经典风格", new String[]{"vue3","vue","vue3Native"}),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 多表
|
||||||
|
*/
|
||||||
|
MANY(2, "many", "/Ghb/code-template-online", "default.onetomany", "经典风格" ,new String[]{"vue"}),
|
||||||
|
/**
|
||||||
|
* 多表(jvxe风格)
|
||||||
|
* */
|
||||||
|
JVXE_TABLE(2, "jvxe", "/Ghb/code-template-online", "jvxe.onetomany", "默认风格" ,new String[]{"vue3","vue","vue3Native"}),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 多表 (erp风格)
|
||||||
|
*/
|
||||||
|
ERP(2, "erp", "/Ghb/code-template-online", "erp.onetomany", "ERP风格" ,new String[]{"vue3","vue","vue3Native"}),
|
||||||
|
/**
|
||||||
|
* 多表(内嵌子表风格)
|
||||||
|
*/
|
||||||
|
INNER_TABLE(2, "innerTable", "/Ghb/code-template-online", "inner-table.onetomany", "内嵌子表风格" ,new String[]{"vue3","vue"}),
|
||||||
|
/**
|
||||||
|
* 多表(tab风格)
|
||||||
|
* */
|
||||||
|
TAB(2, "tab", "/Ghb/code-template-online", "tab.onetomany", "Tab风格" ,new String[]{"vue3","vue"}),
|
||||||
|
/**
|
||||||
|
* 树形列表
|
||||||
|
*/
|
||||||
|
TREE(3, "tree", "/Ghb/code-template-online", "default.tree", "树形列表" ,new String[]{"vue3","vue","vue3Native"});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 类型 1/单表 2/一对多 3/树
|
||||||
|
*/
|
||||||
|
int type;
|
||||||
|
/**
|
||||||
|
* 编码标识
|
||||||
|
*/
|
||||||
|
String code;
|
||||||
|
/**
|
||||||
|
* 代码生成器模板路径
|
||||||
|
*/
|
||||||
|
String templatePath;
|
||||||
|
/**
|
||||||
|
* 代码生成器模板路径
|
||||||
|
*/
|
||||||
|
String stylePath;
|
||||||
|
/**
|
||||||
|
* 模板风格名称
|
||||||
|
*/
|
||||||
|
String note;
|
||||||
|
/**
|
||||||
|
* 支持代码风格 vue3:vue3包装代码 vue3Native:vue3原生代码 vue:vue2代码
|
||||||
|
*/
|
||||||
|
String[] vueStyle;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构造器
|
||||||
|
*
|
||||||
|
* @param type 类型 1/单表 2/一对多 3/树
|
||||||
|
* @param code 模板编码
|
||||||
|
* @param templatePath 模板路径
|
||||||
|
* @param stylePath 模板子路径
|
||||||
|
* @param note
|
||||||
|
* @param vueStyle 支持代码风格
|
||||||
|
*/
|
||||||
|
CgformEnum(int type, String code, String templatePath, String stylePath, String note, String[] vueStyle) {
|
||||||
|
this.type = type;
|
||||||
|
this.code = code;
|
||||||
|
this.templatePath = templatePath;
|
||||||
|
this.stylePath = stylePath;
|
||||||
|
this.note = note;
|
||||||
|
this.vueStyle = vueStyle;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据code获取模板路径
|
||||||
|
*
|
||||||
|
* @param code
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static String getTemplatePathByConfig(String code) {
|
||||||
|
return getCgformEnumByConfig(code).templatePath;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public int getType() {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setType(int type) {
|
||||||
|
this.type = type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getTemplatePath() {
|
||||||
|
return templatePath;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTemplatePath(String templatePath) {
|
||||||
|
this.templatePath = templatePath;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getStylePath() {
|
||||||
|
return stylePath;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setStylePath(String stylePath) {
|
||||||
|
this.stylePath = stylePath;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String[] getVueStyle() {
|
||||||
|
return vueStyle;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setVueStyle(String[] vueStyle) {
|
||||||
|
this.vueStyle = vueStyle;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据code找枚举
|
||||||
|
*
|
||||||
|
* @param code
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static CgformEnum getCgformEnumByConfig(String code) {
|
||||||
|
for (CgformEnum e : CgformEnum.values()) {
|
||||||
|
if (e.code.equals(code)) {
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据类型找所有
|
||||||
|
*
|
||||||
|
* @param type
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static List<Map<String, Object>> getJspModelList(int type) {
|
||||||
|
List<Map<String, Object>> ls = new ArrayList<Map<String, Object>>();
|
||||||
|
for (CgformEnum e : CgformEnum.values()) {
|
||||||
|
if (e.type == type) {
|
||||||
|
Map<String, Object> map = new HashMap<String, Object>();
|
||||||
|
map.put("code", e.code);
|
||||||
|
map.put("note", e.note);
|
||||||
|
ls.add(map);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ls;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,23 @@
|
||||||
|
package com.ghb.base.common.constant.enums;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 客户终端类型
|
||||||
|
*/
|
||||||
|
public enum ClientTerminalTypeEnum {
|
||||||
|
|
||||||
|
PC("pc", "电脑终端"),
|
||||||
|
H5("h5", "移动网页端"),
|
||||||
|
APP("app", "手机app端");
|
||||||
|
|
||||||
|
private String key;
|
||||||
|
private String text;
|
||||||
|
|
||||||
|
ClientTerminalTypeEnum(String value, String text) {
|
||||||
|
this.key = value;
|
||||||
|
this.text = text;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getKey() {
|
||||||
|
return this.key;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,27 @@
|
||||||
|
package com.ghb.base.common.constant.enums;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 日期预设范围枚举
|
||||||
|
*/
|
||||||
|
public enum DateRangeEnum {
|
||||||
|
// 今天
|
||||||
|
TODAY,
|
||||||
|
// 昨天
|
||||||
|
YESTERDAY,
|
||||||
|
// 明天
|
||||||
|
TOMORROW,
|
||||||
|
// 本周
|
||||||
|
THIS_WEEK,
|
||||||
|
// 上周
|
||||||
|
LAST_WEEK,
|
||||||
|
// 下周
|
||||||
|
NEXT_WEEK,
|
||||||
|
// 过去七天
|
||||||
|
LAST_7_DAYS,
|
||||||
|
// 本月
|
||||||
|
THIS_MONTH,
|
||||||
|
// 上月
|
||||||
|
LAST_MONTH,
|
||||||
|
// 下月
|
||||||
|
NEXT_MONTH,
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,97 @@
|
||||||
|
package com.ghb.base.common.constant.enums;
|
||||||
|
|
||||||
|
import com.ghb.base.common.util.oConvertUtils;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Description: 部门类型枚举类
|
||||||
|
*
|
||||||
|
* @author: wangshuai
|
||||||
|
* @date: 2025/8/19 21:37
|
||||||
|
*/
|
||||||
|
public enum DepartCategoryEnum {
|
||||||
|
|
||||||
|
DEPART_CATEGORY_COMPANY("部门类型:公司","公司","1"),
|
||||||
|
DEPART_CATEGORY_DEPART("部门类型:部门","部门","2"),
|
||||||
|
DEPART_CATEGORY_POST("部门类型:岗位","岗位","3"),
|
||||||
|
DEPART_CATEGORY_SUB_COMPANY("部门类型:子公司","子公司","4");
|
||||||
|
|
||||||
|
DepartCategoryEnum(String described, String name, String value) {
|
||||||
|
this.value = value;
|
||||||
|
this.name = name;
|
||||||
|
this.described = described;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 描述
|
||||||
|
*/
|
||||||
|
private String described;
|
||||||
|
/**
|
||||||
|
* 值
|
||||||
|
*/
|
||||||
|
private String value;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 名称
|
||||||
|
*/
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
public String getDescribed() {
|
||||||
|
return described;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDescribed(String described) {
|
||||||
|
this.described = described;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getValue() {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setValue(String value) {
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据值获取名称
|
||||||
|
*
|
||||||
|
* @param value
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static String getNameByValue(String value){
|
||||||
|
if (oConvertUtils.isEmpty(value)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
for (DepartCategoryEnum val : values()) {
|
||||||
|
if (val.getValue().equals(value)) {
|
||||||
|
return val.getName();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据名称获取值
|
||||||
|
*
|
||||||
|
* @param name
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static String getValueByName(String name){
|
||||||
|
if (oConvertUtils.isEmpty(name)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
for (DepartCategoryEnum val : values()) {
|
||||||
|
if (val.getName().equals(name)) {
|
||||||
|
return val.getValue();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,75 @@
|
||||||
|
package com.ghb.base.common.constant.enums;
|
||||||
|
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Description: 短信枚举类
|
||||||
|
* @author: Ghb-boot
|
||||||
|
*/
|
||||||
|
public enum DySmsEnum {
|
||||||
|
|
||||||
|
/**登录短信模板编码*/
|
||||||
|
LOGIN_TEMPLATE_CODE("SMS_175435174","敲敲云","code"),
|
||||||
|
/**忘记密码短信模板编码*/
|
||||||
|
FORGET_PASSWORD_TEMPLATE_CODE("SMS_175435174","敲敲云","code"),
|
||||||
|
/**修改密码短信模板编码*/
|
||||||
|
CHANGE_PASSWORD_TEMPLATE_CODE("SMS_465391221","敲敲云","code"),
|
||||||
|
/**注册账号短信模板编码*/
|
||||||
|
REGISTER_TEMPLATE_CODE("SMS_175430166","敲敲云","code");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 短信模板编码
|
||||||
|
*/
|
||||||
|
private String templateCode;
|
||||||
|
/**
|
||||||
|
* 签名
|
||||||
|
*/
|
||||||
|
private String signName;
|
||||||
|
/**
|
||||||
|
* 短信模板必需的数据名称,多个key以逗号分隔,此处配置作为校验
|
||||||
|
*/
|
||||||
|
private String keys;
|
||||||
|
|
||||||
|
private DySmsEnum(String templateCode,String signName,String keys) {
|
||||||
|
this.templateCode = templateCode;
|
||||||
|
this.signName = signName;
|
||||||
|
this.keys = keys;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getTemplateCode() {
|
||||||
|
return templateCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTemplateCode(String templateCode) {
|
||||||
|
this.templateCode = templateCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getSignName() {
|
||||||
|
return signName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSignName(String signName) {
|
||||||
|
this.signName = signName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getKeys() {
|
||||||
|
return keys;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setKeys(String keys) {
|
||||||
|
this.keys = keys;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static DySmsEnum toEnum(String templateCode) {
|
||||||
|
if(StringUtils.isEmpty(templateCode)){
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
for(DySmsEnum item : DySmsEnum.values()) {
|
||||||
|
if(item.getTemplateCode().equals(templateCode)) {
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -0,0 +1,70 @@
|
||||||
|
package com.ghb.base.common.constant.enums;
|
||||||
|
|
||||||
|
import com.ghb.base.common.util.oConvertUtils;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 邮件html模板配置地址美剧
|
||||||
|
*
|
||||||
|
* @author: liusq
|
||||||
|
* @Date: 2023-10-13
|
||||||
|
*/
|
||||||
|
public enum EmailTemplateEnum {
|
||||||
|
/**
|
||||||
|
* 流程催办
|
||||||
|
*/
|
||||||
|
BPM_CUIBAN_EMAIL("bpm_cuiban_email", "/templates/email/bpm_cuiban_email.ftl"),
|
||||||
|
/**
|
||||||
|
* 流程抄送
|
||||||
|
*/
|
||||||
|
BPM_CC_EMAIL("bpm_cc_email", "/templates/email/bpm_cc_email.ftl"),
|
||||||
|
/**
|
||||||
|
* 流程新任务
|
||||||
|
*/
|
||||||
|
BPM_NEW_TASK_EMAIL("bpm_new_task_email", "/templates/email/bpm_new_task_email.ftl"),
|
||||||
|
/**
|
||||||
|
* 表单新增记录
|
||||||
|
*/
|
||||||
|
DESFORM_NEW_DATA_EMAIL("desform_new_data_email", "/templates/email/desform_new_data_email.ftl");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 模板名称
|
||||||
|
*/
|
||||||
|
private String name;
|
||||||
|
/**
|
||||||
|
* 模板地址
|
||||||
|
*/
|
||||||
|
private String url;
|
||||||
|
|
||||||
|
EmailTemplateEnum(String name, String url) {
|
||||||
|
this.name = name;
|
||||||
|
this.url = url;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getUrl() {
|
||||||
|
return url;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUrl(String url) {
|
||||||
|
this.url = url;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static EmailTemplateEnum getByName(String name) {
|
||||||
|
if (oConvertUtils.isEmpty(name)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
for (EmailTemplateEnum val : values()) {
|
||||||
|
if (val.getName().equals(name)) {
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,77 @@
|
||||||
|
package com.ghb.base.common.constant.enums;
|
||||||
|
|
||||||
|
import com.ghb.base.common.util.oConvertUtils;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 文件类型
|
||||||
|
*/
|
||||||
|
public enum FileTypeEnum {
|
||||||
|
// 文档类型(folder:文件夹 excel:excel doc:word pp:ppt image:图片 archive:其他文档 video:视频 voice:语音)
|
||||||
|
// FOLDER
|
||||||
|
xls(".xls","excel","excel"),
|
||||||
|
xlsx(".xlsx","excel","excel"),
|
||||||
|
doc(".doc","doc","word"),
|
||||||
|
docx(".docx","doc","word"),
|
||||||
|
ppt(".ppt","pp","ppt"),
|
||||||
|
pptx(".pptx","pp","ppt"),
|
||||||
|
gif(".gif","image","图片"),
|
||||||
|
jpg(".jpg","image","图片"),
|
||||||
|
jpeg(".jpeg","image","图片"),
|
||||||
|
png(".png","image","图片"),
|
||||||
|
txt(".txt","text","文本"),
|
||||||
|
avi(".avi","video","视频"),
|
||||||
|
mov(".mov","video","视频"),
|
||||||
|
rmvb(".rmvb","video","视频"),
|
||||||
|
rm(".rm","video","视频"),
|
||||||
|
flv(".flv","video","视频"),
|
||||||
|
mp4(".mp4","video","视频"),
|
||||||
|
zip(".zip","zip","压缩包"),
|
||||||
|
pdf(".pdf","pdf","pdf"),
|
||||||
|
mp3(".mp3","mp3","语音"),
|
||||||
|
wav(".wav","wav","语音");
|
||||||
|
|
||||||
|
private String type;
|
||||||
|
private String value;
|
||||||
|
private String text;
|
||||||
|
private FileTypeEnum(String type,String value,String text){
|
||||||
|
this.type = type;
|
||||||
|
this.value = value;
|
||||||
|
this.text = text;
|
||||||
|
}
|
||||||
|
public String getType() {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setType(String type) {
|
||||||
|
this.type = type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getValue() {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setValue(String value) {
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getText() {
|
||||||
|
return text;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setText(String text) {
|
||||||
|
this.text = text;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static FileTypeEnum getByType(String type){
|
||||||
|
if (oConvertUtils.isEmpty(type)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
for (FileTypeEnum val : values()) {
|
||||||
|
if (val.getType().equals(type)) {
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,98 @@
|
||||||
|
package com.ghb.base.common.constant.enums;
|
||||||
|
|
||||||
|
import com.ghb.base.common.system.annotation.EnumDict;
|
||||||
|
import com.ghb.base.common.system.vo.DictModel;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 消息类型
|
||||||
|
*
|
||||||
|
* @author: Ghb-boot
|
||||||
|
*/
|
||||||
|
@EnumDict("messageType")
|
||||||
|
public enum MessageTypeEnum {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 系统消息
|
||||||
|
*/
|
||||||
|
XT("system", "系统消息"),
|
||||||
|
/**
|
||||||
|
* 邮件消息
|
||||||
|
*/
|
||||||
|
YJ("email", "邮件消息"),
|
||||||
|
/**
|
||||||
|
* 钉钉消息
|
||||||
|
*/
|
||||||
|
DD("dingtalk", "钉钉消息"),
|
||||||
|
/**
|
||||||
|
* 企业微信
|
||||||
|
*/
|
||||||
|
QYWX("wechat_enterprise", "企业微信");
|
||||||
|
|
||||||
|
MessageTypeEnum(String type, String note) {
|
||||||
|
this.type = type;
|
||||||
|
this.note = note;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 消息类型
|
||||||
|
*/
|
||||||
|
String type;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 类型说明
|
||||||
|
*/
|
||||||
|
String note;
|
||||||
|
|
||||||
|
public String getNote() {
|
||||||
|
return note;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setNote(String note) {
|
||||||
|
this.note = note;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getType() {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setType(String type) {
|
||||||
|
this.type = type;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取字典数据
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static List<DictModel> getDictList() {
|
||||||
|
List<DictModel> list = new ArrayList<>();
|
||||||
|
DictModel dictModel = null;
|
||||||
|
for (MessageTypeEnum e : MessageTypeEnum.values()) {
|
||||||
|
dictModel = new DictModel();
|
||||||
|
dictModel.setValue(e.getType());
|
||||||
|
dictModel.setText(e.getNote());
|
||||||
|
list.add(dictModel);
|
||||||
|
}
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据type获取枚举
|
||||||
|
*
|
||||||
|
* @param type
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static MessageTypeEnum valueOfType(String type) {
|
||||||
|
for (MessageTypeEnum e : MessageTypeEnum.values()) {
|
||||||
|
if (e.getType().equals(type)) {
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,18 @@
|
||||||
|
package com.ghb.base.common.constant.enums;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 日志按模块分类
|
||||||
|
* @author: Ghb-boot
|
||||||
|
*/
|
||||||
|
public enum ModuleType {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 普通
|
||||||
|
*/
|
||||||
|
COMMON,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* online
|
||||||
|
*/
|
||||||
|
ONLINE;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,88 @@
|
||||||
|
package com.ghb.base.common.constant.enums;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Description: 文件类型枚举类
|
||||||
|
*
|
||||||
|
* @author: wangshuai
|
||||||
|
* @date: 2025/6/26 17:29
|
||||||
|
*/
|
||||||
|
public enum NoticeTypeEnum {
|
||||||
|
|
||||||
|
//VUE3专用
|
||||||
|
NOTICE_TYPE_FILE("知识库消息","file"),
|
||||||
|
NOTICE_TYPE_FLOW("工作流消息","flow"),
|
||||||
|
NOTICE_TYPE_PLAN("日程消息","plan"),
|
||||||
|
//暂时没用到
|
||||||
|
NOTICE_TYPE_MEETING("会议消息","meeting"),
|
||||||
|
NOTICE_TYPE_SYSTEM("系统消息","system"),
|
||||||
|
/**
|
||||||
|
* 协同工作
|
||||||
|
* for [JHHB-136]【vue3】协同工作系统消息需要添加一个类型
|
||||||
|
*/
|
||||||
|
NOTICE_TYPE_COLLABORATION("协同工作", "collab"),
|
||||||
|
/**
|
||||||
|
* 督办
|
||||||
|
*/
|
||||||
|
NOTICE_TYPE_SUPERVISE("督办管理", "supe"),
|
||||||
|
/**
|
||||||
|
* 考勤
|
||||||
|
*/
|
||||||
|
NOTICE_TYPE_ATTENDANCE("考勤消息", "attendance");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 文件类型名称
|
||||||
|
*/
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 文件类型值
|
||||||
|
*/
|
||||||
|
private String value;
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getValue() {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setValue(String value) {
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
NoticeTypeEnum(String name, String value) {
|
||||||
|
this.name = name;
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取聊天通知类型
|
||||||
|
*
|
||||||
|
* @param value
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static String getChatNoticeType(String value){
|
||||||
|
return value + "Notice";
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取通知名称
|
||||||
|
*
|
||||||
|
* @param value
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static String getNoticeNameByValue(String value){
|
||||||
|
value = value.replace("Notice","");
|
||||||
|
for (NoticeTypeEnum e : NoticeTypeEnum.values()) {
|
||||||
|
if (e.getValue().equals(value)) {
|
||||||
|
return e.getName();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return "系统消息";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,95 @@
|
||||||
|
package com.ghb.base.common.constant.enums;
|
||||||
|
|
||||||
|
import com.ghb.base.common.constant.CommonConstant;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Description: 操作类型
|
||||||
|
* @author: Ghb-boot
|
||||||
|
* @date: 2022/3/31 10:05
|
||||||
|
*/
|
||||||
|
public enum OperateTypeEnum {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 列表
|
||||||
|
*/
|
||||||
|
LIST(CommonConstant.OPERATE_TYPE_1, "list"),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 新增
|
||||||
|
*/
|
||||||
|
ADD(CommonConstant.OPERATE_TYPE_2, "add"),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 编辑
|
||||||
|
*/
|
||||||
|
EDIT(CommonConstant.OPERATE_TYPE_3, "edit"),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除
|
||||||
|
*/
|
||||||
|
DELETE(CommonConstant.OPERATE_TYPE_4, "delete"),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 导入
|
||||||
|
*/
|
||||||
|
IMPORT(CommonConstant.OPERATE_TYPE_5, "import"),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 导出
|
||||||
|
*/
|
||||||
|
EXPORT(CommonConstant.OPERATE_TYPE_6, "export");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 类型 1列表,2新增,3编辑,4删除,5导入,6导出
|
||||||
|
*/
|
||||||
|
int type;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 编码(请求方式)
|
||||||
|
*/
|
||||||
|
String code;
|
||||||
|
|
||||||
|
|
||||||
|
public int getType() {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setType(int type) {
|
||||||
|
this.type = type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getCode() {
|
||||||
|
return code;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCode(String code) {
|
||||||
|
this.code = code;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构造器
|
||||||
|
*
|
||||||
|
* @param type 类型
|
||||||
|
* @param code 编码(请求方式)
|
||||||
|
*/
|
||||||
|
OperateTypeEnum(int type, String code) {
|
||||||
|
this.type = type;
|
||||||
|
this.code = code;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据请求名称匹配
|
||||||
|
*
|
||||||
|
* @param methodName 请求名称
|
||||||
|
* @return Integer 类型
|
||||||
|
*/
|
||||||
|
public static Integer getTypeByMethodName(String methodName) {
|
||||||
|
for (OperateTypeEnum e : OperateTypeEnum.values()) {
|
||||||
|
if (methodName.startsWith(e.getCode())) {
|
||||||
|
return e.getType();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return CommonConstant.OPERATE_TYPE_1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,180 @@
|
||||||
|
package com.ghb.base.common.constant.enums;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 职级枚举类
|
||||||
|
*
|
||||||
|
* 注意:此枚举仅适用于天津临港控股OA项目,职级的名称和等级均为写死(需要与数据库配置一致)
|
||||||
|
* @date 2025-08-26
|
||||||
|
* @author scott
|
||||||
|
*/
|
||||||
|
public enum PositionLevelEnum {
|
||||||
|
|
||||||
|
// 领导层级(等级1-3)
|
||||||
|
CHAIRMAN("董事长", 1, PositionType.LEADER),
|
||||||
|
GENERAL_MANAGER("总经理", 2, PositionType.LEADER),
|
||||||
|
VICE_GENERAL_MANAGER("副总经理", 3, PositionType.LEADER),
|
||||||
|
|
||||||
|
// 职员层级(等级4-6)
|
||||||
|
MINISTER("部长", 4, PositionType.STAFF),
|
||||||
|
VICE_MINISTER("副部长", 5, PositionType.STAFF),
|
||||||
|
STAFF("职员", 6, PositionType.STAFF);
|
||||||
|
|
||||||
|
private final String name;
|
||||||
|
private final int level;
|
||||||
|
private final PositionType type;
|
||||||
|
|
||||||
|
PositionLevelEnum(String name, int level, PositionType type) {
|
||||||
|
this.name = name;
|
||||||
|
this.level = level;
|
||||||
|
this.type = type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getLevel() {
|
||||||
|
return level;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PositionType getType() {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 职级类型枚举
|
||||||
|
*/
|
||||||
|
public enum PositionType {
|
||||||
|
STAFF("职员层级"),
|
||||||
|
LEADER("领导层级");
|
||||||
|
|
||||||
|
private final String desc;
|
||||||
|
|
||||||
|
PositionType(String desc) {
|
||||||
|
this.desc = desc;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDesc() {
|
||||||
|
return desc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据职级名称获取枚举
|
||||||
|
* @param name 职级名称
|
||||||
|
* @return 职级枚举
|
||||||
|
*/
|
||||||
|
public static PositionLevelEnum getByName(String name) {
|
||||||
|
for (PositionLevelEnum position : values()) {
|
||||||
|
if (position.getName().equals(name)) {
|
||||||
|
return position;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据职级等级获取枚举
|
||||||
|
* @param level 职级等级
|
||||||
|
* @return 职级枚举
|
||||||
|
*/
|
||||||
|
public static PositionLevelEnum getByLevel(int level) {
|
||||||
|
for (PositionLevelEnum position : values()) {
|
||||||
|
if (position.getLevel() == level) {
|
||||||
|
return position;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据职级名称判断是否为职员层级
|
||||||
|
* @param name 职级名称
|
||||||
|
* @return true-职员层级,false-非职员层级
|
||||||
|
*/
|
||||||
|
public static boolean isStaffLevel(String name) {
|
||||||
|
PositionLevelEnum position = getByName(name);
|
||||||
|
return position != null && position.getType() == PositionType.STAFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据职级名称判断是否为领导层级
|
||||||
|
* @param name 职级名称
|
||||||
|
* @return true-领导层级,false-非领导层级
|
||||||
|
*/
|
||||||
|
public static boolean isLeaderLevel(String name) {
|
||||||
|
PositionLevelEnum position = getByName(name);
|
||||||
|
return position != null && position.getType() == PositionType.LEADER;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 比较两个职级的等级高低
|
||||||
|
* @param name1 职级名称1
|
||||||
|
* @param name2 职级名称2
|
||||||
|
* @return 正数表示name1等级更高,负数表示name2等级更高,0表示等级相同
|
||||||
|
*/
|
||||||
|
public static int compareLevel(String name1, String name2) {
|
||||||
|
PositionLevelEnum pos1 = getByName(name1);
|
||||||
|
PositionLevelEnum pos2 = getByName(name2);
|
||||||
|
|
||||||
|
if (pos1 == null || pos2 == null) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 等级数字越小代表职级越高
|
||||||
|
return pos2.getLevel() - pos1.getLevel();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 判断是否为更高等级
|
||||||
|
* @param currentName 当前职级名称
|
||||||
|
* @param targetName 目标职级名称
|
||||||
|
* @return true-目标职级更高,false-目标职级不高于当前职级
|
||||||
|
*/
|
||||||
|
public static boolean isHigherLevel(String currentName, String targetName) {
|
||||||
|
return compareLevel(targetName, currentName) > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取所有职员层级名称
|
||||||
|
* @return 职员层级名称列表
|
||||||
|
*/
|
||||||
|
public static List<String> getStaffLevelNames() {
|
||||||
|
return Arrays.asList(MINISTER.getName(), VICE_MINISTER.getName(), STAFF.getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取所有领导层级名称
|
||||||
|
* @return 领导层级名称列表
|
||||||
|
*/
|
||||||
|
public static List<String> getLeaderLevelNames() {
|
||||||
|
return Arrays.asList(CHAIRMAN.getName(), GENERAL_MANAGER.getName(), VICE_GENERAL_MANAGER.getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取所有职级名称(按等级排序)
|
||||||
|
* @return 所有职级名称列表
|
||||||
|
*/
|
||||||
|
public static List<String> getAllPositionNames() {
|
||||||
|
return Arrays.asList(
|
||||||
|
CHAIRMAN.getName(), GENERAL_MANAGER.getName(), VICE_GENERAL_MANAGER.getName(),
|
||||||
|
MINISTER.getName(), VICE_MINISTER.getName(), STAFF.getName()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取指定等级范围的职级
|
||||||
|
* @param minLevel 最小等级
|
||||||
|
* @param maxLevel 最大等级
|
||||||
|
* @return 职级名称列表
|
||||||
|
*/
|
||||||
|
public static List<String> getPositionsByLevelRange(int minLevel, int maxLevel) {
|
||||||
|
return Arrays.stream(values())
|
||||||
|
.filter(p -> p.getLevel() >= minLevel && p.getLevel() <= maxLevel)
|
||||||
|
.map(PositionLevelEnum::getName)
|
||||||
|
.collect(java.util.stream.Collectors.toList());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,97 @@
|
||||||
|
package com.ghb.base.common.constant.enums;
|
||||||
|
|
||||||
|
import com.ghb.base.common.util.oConvertUtils;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 首页自定义
|
||||||
|
* 通过角色编码与首页组件路径配置
|
||||||
|
* 枚举的顺序有权限高低权重作用(也就是配置多个角色,在前面的角色首页,会优先生效)
|
||||||
|
* @author: Ghb-boot
|
||||||
|
*/
|
||||||
|
public enum RoleIndexConfigEnum {
|
||||||
|
|
||||||
|
/**首页自定义 admin*/
|
||||||
|
// ADMIN("admin", "dashboard/Analysis"),
|
||||||
|
//TEST("test", "dashboard/IndexChart"),
|
||||||
|
/**首页自定义 hr*/
|
||||||
|
// HR("hr", "dashboard/IndexBdc");
|
||||||
|
|
||||||
|
//DM("dm", "dashboard/IndexTask"),
|
||||||
|
|
||||||
|
// 注:此值仅为防止报错,无任何实际意义
|
||||||
|
ROLE_INDEX_CONFIG_ENUM("RoleIndexConfigEnumDefault", "dashboard/Analysis");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 角色编码
|
||||||
|
*/
|
||||||
|
String roleCode;
|
||||||
|
/**
|
||||||
|
* 路由index
|
||||||
|
*/
|
||||||
|
String componentUrl;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构造器
|
||||||
|
*
|
||||||
|
* @param roleCode 角色编码
|
||||||
|
* @param componentUrl 首页组件路径(规则跟菜单配置一样)
|
||||||
|
*/
|
||||||
|
RoleIndexConfigEnum(String roleCode, String componentUrl) {
|
||||||
|
this.roleCode = roleCode;
|
||||||
|
this.componentUrl = componentUrl;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* 根据code找枚举
|
||||||
|
* @param roleCode 角色编码
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private static RoleIndexConfigEnum getEnumByCode(String roleCode) {
|
||||||
|
for (RoleIndexConfigEnum e : RoleIndexConfigEnum.values()) {
|
||||||
|
if (e.roleCode.equals(roleCode)) {
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* 根据code找index
|
||||||
|
* @param roleCode 角色编码
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private static String getIndexByCode(String roleCode) {
|
||||||
|
for (RoleIndexConfigEnum e : RoleIndexConfigEnum.values()) {
|
||||||
|
if (e.roleCode.equals(roleCode)) {
|
||||||
|
return e.componentUrl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getIndexByRoles(List<String> roles) {
|
||||||
|
String[] rolesArray = roles.toArray(new String[roles.size()]);
|
||||||
|
for (RoleIndexConfigEnum e : RoleIndexConfigEnum.values()) {
|
||||||
|
if (oConvertUtils.isIn(e.roleCode,rolesArray)){
|
||||||
|
return e.componentUrl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getRoleCode() {
|
||||||
|
return roleCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRoleCode(String roleCode) {
|
||||||
|
this.roleCode = roleCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getComponentUrl() {
|
||||||
|
return componentUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setComponentUrl(String componentUrl) {
|
||||||
|
this.componentUrl = componentUrl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,100 @@
|
||||||
|
package com.ghb.base.common.constant.enums;
|
||||||
|
|
||||||
|
import com.ghb.base.common.util.oConvertUtils;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 系统公告自定义跳转方式
|
||||||
|
* @author: Ghb-boot
|
||||||
|
*/
|
||||||
|
public enum SysAnnmentTypeEnum {
|
||||||
|
/**
|
||||||
|
* 邮件跳转组件
|
||||||
|
*/
|
||||||
|
EMAIL("email", "component", "modules/eoa/email/modals/EoaEmailInForm"),
|
||||||
|
/**
|
||||||
|
* 流程跳转到我的任务
|
||||||
|
*/
|
||||||
|
BPM("bpm", "url", "/bpm/task/MyTaskList"),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 流程抄送任务
|
||||||
|
*/
|
||||||
|
BPM_VIEW("bpm_cc", "url", "/bpm/task/MyTaskList"),
|
||||||
|
/**
|
||||||
|
* 邀请用户跳转到个人设置
|
||||||
|
*/
|
||||||
|
TENANT_INVITE("tenant_invite", "url", "/system/usersetting"),
|
||||||
|
/**
|
||||||
|
* 协同工作-待办通知
|
||||||
|
* for [JHHB-136]【vue3】协同工作系统消息需要添加一个类型
|
||||||
|
*/
|
||||||
|
EOA_CO_NOTIFY("eoa_co_notify", "url", "/collaboration/pending"),
|
||||||
|
/**
|
||||||
|
* 协同工作-催办通知
|
||||||
|
* for [JHHB-136]【vue3】协同工作系统消息需要添加一个类型
|
||||||
|
*/
|
||||||
|
EOA_CO_REMIND("eoa_co_remind", "url", "/collaboration/pending"),
|
||||||
|
/**
|
||||||
|
* 督办管理-催办
|
||||||
|
*/
|
||||||
|
EOA_SUP_REMIND("eoa_sup_remind", "url", "/superivse/list"),
|
||||||
|
/**
|
||||||
|
* 督办管理-通知
|
||||||
|
*/
|
||||||
|
EOA_SUP_NOTIFY("eoa_sup_notify", "url", "/superivse/list");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 业务类型(email:邮件 bpm:流程)
|
||||||
|
*/
|
||||||
|
private String type;
|
||||||
|
/**
|
||||||
|
* 打开方式 组件:component 路由:url
|
||||||
|
*/
|
||||||
|
private String openType;
|
||||||
|
/**
|
||||||
|
* 组件/路由 地址
|
||||||
|
*/
|
||||||
|
private String openPage;
|
||||||
|
|
||||||
|
SysAnnmentTypeEnum(String type, String openType, String openPage) {
|
||||||
|
this.type = type;
|
||||||
|
this.openType = openType;
|
||||||
|
this.openPage = openPage;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getType() {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setType(String type) {
|
||||||
|
this.type = type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getOpenType() {
|
||||||
|
return openType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setOpenType(String openType) {
|
||||||
|
this.openType = openType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getOpenPage() {
|
||||||
|
return openPage;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setOpenPage(String openPage) {
|
||||||
|
this.openPage = openPage;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static SysAnnmentTypeEnum getByType(String type) {
|
||||||
|
if (oConvertUtils.isEmpty(type)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
for (SysAnnmentTypeEnum val : values()) {
|
||||||
|
if (val.getType().equals(type)) {
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,86 @@
|
||||||
|
package com.ghb.base.common.constant.enums;
|
||||||
|
|
||||||
|
import com.ghb.base.common.util.oConvertUtils;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* UniPush 消息推送枚举
|
||||||
|
* @author: Ghb-boot
|
||||||
|
*/
|
||||||
|
public enum UniPushTypeEnum {
|
||||||
|
/**
|
||||||
|
* 聊天
|
||||||
|
*/
|
||||||
|
CHAT("chat", "聊天消息", "收到%s发来的聊天消息"),
|
||||||
|
/**
|
||||||
|
* 流程跳转到我的任务
|
||||||
|
*/
|
||||||
|
BPM("bpm_task", "待办任务", "收到%s待办任务"),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 流程抄送任务
|
||||||
|
*/
|
||||||
|
BPM_VIEW("bpm_cc", "知会任务", "收到%s知会任务"),
|
||||||
|
/**
|
||||||
|
* 系统消息
|
||||||
|
*/
|
||||||
|
SYS_MSG("system", "系统消息", "收到一条系统通告"),
|
||||||
|
/**
|
||||||
|
* 协同工作
|
||||||
|
*/
|
||||||
|
COLLABORATION_MSG("collaboration", "系统消息", "收到一条协同工作消息");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 业务类型(chat:聊天 bpm_task:流程 bpm_cc:流程抄送)
|
||||||
|
*/
|
||||||
|
private String type;
|
||||||
|
/**
|
||||||
|
* 消息标题
|
||||||
|
*/
|
||||||
|
private String title;
|
||||||
|
/**
|
||||||
|
* 消息内容
|
||||||
|
*/
|
||||||
|
private String content;
|
||||||
|
|
||||||
|
UniPushTypeEnum(String type, String title, String content) {
|
||||||
|
this.type = type;
|
||||||
|
this.title = title;
|
||||||
|
this.content = content;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getType() {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setType(String type) {
|
||||||
|
this.type = type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getTitle() {
|
||||||
|
return title ;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTitle(String openType) {
|
||||||
|
this.title = openType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getContent() {
|
||||||
|
return content;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setContent(String content) {
|
||||||
|
this.content = content;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static UniPushTypeEnum getByType(String type) {
|
||||||
|
if (oConvertUtils.isEmpty(type)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
for (UniPushTypeEnum val : values()) {
|
||||||
|
if (val.getType().equals(type)) {
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,75 @@
|
||||||
|
package com.ghb.base.common.constant.enums;
|
||||||
|
|
||||||
|
import com.ghb.base.common.system.annotation.EnumDict;
|
||||||
|
import com.ghb.base.common.system.vo.DictModel;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 消息跳转【vue3】
|
||||||
|
* @Author taoYan
|
||||||
|
* @Date 2022/8/19 20:41
|
||||||
|
**/
|
||||||
|
@EnumDict("messageHref")
|
||||||
|
public enum Vue3MessageHrefEnum {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 流程催办
|
||||||
|
*/
|
||||||
|
BPM("bpm", "/task/myHandleTaskInfo"),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 系统消息通知
|
||||||
|
*/
|
||||||
|
BPM_SYSTEM_MSG("bpm_msg_node", ""),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 流程抄送任务
|
||||||
|
*/
|
||||||
|
BPM_VIEW("bpm_cc", "/task/myHandleTaskInfo"),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 节点通知
|
||||||
|
*/
|
||||||
|
BPM_TASK("bpm_task", "/task/myHandleTaskInfo"),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 邮件消息
|
||||||
|
*/
|
||||||
|
EMAIL("email", "/eoa/email");
|
||||||
|
|
||||||
|
String busType;
|
||||||
|
|
||||||
|
String path;
|
||||||
|
|
||||||
|
Vue3MessageHrefEnum(String busType, String path) {
|
||||||
|
this.busType = busType;
|
||||||
|
this.path = path;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getBusType() {
|
||||||
|
return busType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPath() {
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取字典数据
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static List<DictModel> getDictList(){
|
||||||
|
List<DictModel> list = new ArrayList<>();
|
||||||
|
DictModel dictModel = null;
|
||||||
|
for(Vue3MessageHrefEnum e: Vue3MessageHrefEnum.values()){
|
||||||
|
dictModel = new DictModel();
|
||||||
|
dictModel.setValue(e.getBusType());
|
||||||
|
dictModel.setText(e.getPath());
|
||||||
|
list.add(dictModel);
|
||||||
|
}
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,87 @@
|
||||||
|
package com.ghb.base.common.desensitization;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.core.JsonGenerator;
|
||||||
|
import com.fasterxml.jackson.databind.BeanProperty;
|
||||||
|
import com.fasterxml.jackson.databind.JsonMappingException;
|
||||||
|
import com.fasterxml.jackson.databind.JsonSerializer;
|
||||||
|
import com.fasterxml.jackson.databind.SerializerProvider;
|
||||||
|
import com.fasterxml.jackson.databind.ser.ContextualSerializer;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import com.ghb.base.common.desensitization.annotation.Sensitive;
|
||||||
|
import com.ghb.base.common.desensitization.enums.SensitiveEnum;
|
||||||
|
import com.ghb.base.common.desensitization.util.SensitiveInfoUtil;
|
||||||
|
import com.ghb.base.common.util.encryption.AesEncryptUtil;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author eightmonth@qq.com
|
||||||
|
* @date 2024/6/19 10:43
|
||||||
|
*/
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
@Slf4j
|
||||||
|
public class SensitiveSerialize extends JsonSerializer<String> implements ContextualSerializer {
|
||||||
|
|
||||||
|
private SensitiveEnum type;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void serialize(String data, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
|
||||||
|
switch (type){
|
||||||
|
case ENCODE:
|
||||||
|
try {
|
||||||
|
jsonGenerator.writeString(AesEncryptUtil.encrypt(data));
|
||||||
|
} catch (Exception exception) {
|
||||||
|
log.error("数据加密错误", exception.getMessage());
|
||||||
|
jsonGenerator.writeString(data);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case CHINESE_NAME:
|
||||||
|
jsonGenerator.writeString(SensitiveInfoUtil.chineseName(data));
|
||||||
|
break;
|
||||||
|
case ID_CARD:
|
||||||
|
jsonGenerator.writeString(SensitiveInfoUtil.idCardNum(data));
|
||||||
|
break;
|
||||||
|
case FIXED_PHONE:
|
||||||
|
jsonGenerator.writeString(SensitiveInfoUtil.fixedPhone(data));
|
||||||
|
break;
|
||||||
|
case MOBILE_PHONE:
|
||||||
|
jsonGenerator.writeString(SensitiveInfoUtil.mobilePhone(data));
|
||||||
|
break;
|
||||||
|
case ADDRESS:
|
||||||
|
jsonGenerator.writeString(SensitiveInfoUtil.address(data, 3));
|
||||||
|
break;
|
||||||
|
case EMAIL:
|
||||||
|
jsonGenerator.writeString(SensitiveInfoUtil.email(data));
|
||||||
|
break;
|
||||||
|
case BANK_CARD:
|
||||||
|
jsonGenerator.writeString(SensitiveInfoUtil.bankCard(data));
|
||||||
|
break;
|
||||||
|
case CNAPS_CODE:
|
||||||
|
jsonGenerator.writeString(SensitiveInfoUtil.cnapsCode(data));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
jsonGenerator.writeString(data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JsonSerializer<?> createContextual(SerializerProvider serializerProvider, BeanProperty beanProperty) throws JsonMappingException {
|
||||||
|
if (beanProperty != null) {
|
||||||
|
if (Objects.equals(beanProperty.getType().getRawClass(), String.class)) {
|
||||||
|
Sensitive sensitive = beanProperty.getAnnotation(Sensitive.class);
|
||||||
|
if (sensitive == null) {
|
||||||
|
sensitive = beanProperty.getContextAnnotation(Sensitive.class);
|
||||||
|
}
|
||||||
|
if (sensitive != null) {
|
||||||
|
return new SensitiveSerialize(sensitive.type());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return serializerProvider.findValueSerializer(beanProperty.getType(), beanProperty);
|
||||||
|
}
|
||||||
|
return serializerProvider.findNullValueSerializer(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,26 @@
|
||||||
|
package com.ghb.base.common.desensitization.annotation;
|
||||||
|
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JacksonAnnotationsInside;
|
||||||
|
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
|
||||||
|
import com.ghb.base.common.desensitization.SensitiveSerialize;
|
||||||
|
import com.ghb.base.common.desensitization.enums.SensitiveEnum;
|
||||||
|
|
||||||
|
import java.lang.annotation.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 在字段上定义 标识字段存储的信息是敏感的
|
||||||
|
*/
|
||||||
|
@Documented
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
@Target(ElementType.FIELD)
|
||||||
|
@JacksonAnnotationsInside
|
||||||
|
@JsonSerialize(using = SensitiveSerialize.class)
|
||||||
|
public @interface Sensitive {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 不同类型处理不同
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
SensitiveEnum type() default SensitiveEnum.ENCODE;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,20 @@
|
||||||
|
package com.ghb.base.common.desensitization.annotation;
|
||||||
|
|
||||||
|
import java.lang.annotation.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 解密注解
|
||||||
|
*
|
||||||
|
* 在方法上定义 将方法返回对象中的敏感字段 解密,需要注意的是,如果没有加密过,解密会出问题,返回原字符串
|
||||||
|
*/
|
||||||
|
@Documented
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
@Target({ElementType.METHOD})
|
||||||
|
public @interface SensitiveDecode {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 指明需要脱敏的实体类class
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
Class entity() default Object.class;
|
||||||
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue