Compare commits

...
673 Commits
Author SHA1 Message Date
PIGCLOUD a6d0705e40 fix(upms): validate department switch authorization
Restrict department switching to the current user department list and reuse the localized access-denied message. Add regression coverage for valid switching and unauthorized or missing departments.

Refs #298

(cherry picked from commit b897c6a34f5f0ff3a4670eb9881e058b56de376d)
2026-11-06 15:19:40 +08:00
PIGCLOUD c0034f3799 Merge branch 'master' of github.com:pig-dev-team/pigx 2026-11-05 16:40:28 +08:00
PIGCLOUD db23fd2d0c feat(SysUserServiceImpl): 添加短信验证码校验逻辑,防止重复使用确保验证码一次性消费
- 更新用户注册和找回密码逻辑,使用新的验证码校验方法
- 添加 SysUserSmsCodeTests 测试类,验证验证码消费行为
2026-11-05 16:36:32 +08:00
PIGCLOUD fd5cd572a4 feat(SysRegisterController): 添加找回密码功能开关控制
- 在 SysRegisterController 中添加对找回密码功能的开关控制
- 如果系统已关闭找回密码功能,则返回失败信息
2026-11-05 16:36:04 +08:00
PIGCLOUD ab91447941 fix(flow): 转义 process.settings 列名,修复 jsqlparser 5.4 解析异常
jsqlparser 5.4 将 settings 视为关键字,TenantLineInnerInterceptor
解析含该列的 SQL 时抛出 ParseException。
2026-11-05 15:18:47 +08:00
PIGCLOUD e3440353ae fix(flow): 转义 process.settings 列名,修复 jsqlparser 5.4 解析异常
jsqlparser 5.4 将 settings 视为关键字,TenantLineInnerInterceptor
解析含该列的 SQL 时抛出 ParseException。
2026-11-05 15:18:43 +08:00
PIGCLOUD ff98dcc3fb chore(deps): 升级积木报表至 2.5.6.1 并覆盖 fastjson 版本 2026-11-05 13:05:57 +08:00
PIGCLOUD 467a1fea1b build(deps): 升级 MyBatis Plus 并适配新版 API
(cherry picked from commit 290764e739fa093eb8187ecd0f9a30062af95f8e)
2026-11-04 21:01:49 +08:00
PIGCLOUD 8d37e48d1f feat(flow): 删除旧的流程通知表和合并表的迁移脚本
- 删除了 `20261014_flow_first_batch.sql` 和 `20261014_flow_merge_tables.sql` 文件
- 更新 `FlowNoticeStatusEnum`,新增 REMOVING 状态
- 修改 `FlowNotice` 实体,确保在插入时保留 userId 值
- 在 `FlowDurableConfiguration` 中添加事务提交后撤销失效通知的逻辑
- 更新 `IFlowNoticeService` 接口,调整通知事件的处理逻辑
- 实现 `FlowNoticeServiceImpl` 中的通知撤销逻辑,确保不误删新通知
- 新增 `FlowMessageRemovalDTO` 数据传输对象,处理通知撤销请求
- 更新 `SysMessageService` 和 `SysMessageController`,支持内部调用撤销流程通知
- 添加 `SysMessageDeletionTests` 测试用例,验证撤销逻辑的正确性
2026-11-03 18:57:11 +08:00
PIGCLOUD 589d17f0d3 fix(db): 补齐国际化与导出权限并同步 Vue 生成模板 2026-11-03 16:50:12 +08:00
PIGCLOUD 5f4d9d6621 style(db): remove trailing blank line after flow sync 2026-11-03 15:24:25 +08:00
PIGCLOUD d6adbfa36e fix(build): upgrade Maven Surefire to 3.6.1
(cherry picked from commit 54dc3b330c245fc79428e4e216b66e405bd47e3f)
2026-11-03 15:22:56 +08:00
PIGCLOUD b003a1b444 fix(auth): 隔离验证码缓存并强制校验短信登录凭据
(cherry picked from commit 9468a3efae7c9b678d074697eced50a175bea1f6)
2026-11-03 14:56:26 +08:00
PIGCLOUD 0974a56294 feat(flow): 优化拒绝处理逻辑,支持多实例结束后重定向到发起人
- 更新 ApproveServiceTask 中拒绝处理逻辑,支持多实例结束后当前执行流尚未落库的情况
- 增加对 CommandContextUtil 的使用,确保执行流迁移的正确性
- 添加 ModelUtilMultiMatchTests 中的单元测试,验证拒绝到发起人的逻辑

(cherry picked from commit 9e37864b02b14a2c980b74e01e126b5d38d10b09)
2026-11-03 14:56:21 +08:00
PIGCLOUD 2f089f029f feat(flow): 条件分支支持多选(包容网关)
- 条件分支节点新增 multiMatch,开启后分叉与合并网关改为 InclusiveGateway,未开启保持排他网关
- 驳回到发起人时收回实例下全部执行流,修复并行、多选分支内驳回后兄弟分支残留导致汇聚异常
- 新增 H2 引擎测试覆盖命中多条、兜底、空分支、嵌套条件及分支内驳回

(cherry picked from commit b982714e1875632fde3338bc69f27052cad98a9d)
2026-11-03 14:56:21 +08:00
PIGCLOUD 93c52e41dc feat(flow): 添加打印模板导入逻辑
- 仅在导入流程时携带打印模板,编辑或复制时保留原模板

(cherry picked from commit ebb2cf463da55efa9ac64bc011ed7ffc8606578a)
2026-11-03 14:56:21 +08:00
PIGCLOUD 2053cc5766 feat(flow): 更新超时任务和通知扫描的延迟时间
- 将 scanReminders 和 scanNotices 方法的扫描延迟时间从 10000ms 修改为 60000ms
- 提高了超时任务和通知的处理频率,优化了系统性能

(cherry picked from commit 71c5177913e5eaf452f62387947be13a6f9cfcc6)
2026-11-03 14:56:21 +08:00
PIGCLOUD ddfc2b41d9 feat(flow): 支持节点 REST 表单权限解析
(cherry picked from commit 80459350acfcd41351497959884307dfa6bbf9c0)
2026-11-03 14:56:21 +08:00
PIGCLOUD 14cb5dfe0a feat(pigx-common): 更新 nacos 版本至 3.3.0
- 将 pigx-common 模块中的 nacos.client.version 更新至 3.3.0
- 将 pigx-register 模块中的 nacos.version 更新至 3.3.0

(cherry picked from commit a25fcc1dedd49b73808fd4c3345da220b2bc50d8)
2026-11-03 14:56:21 +08:00
PIGCLOUD f8742f5e69 fix(flow): 移除回调持久化重试并限制单次通知并发
(cherry picked from commit f7cd6724ee5e5a2fbb7a677f386e582ba9d92610)
2026-11-03 14:56:16 +08:00
PIGCLOUD e0d43f41a1 refactor(flow): migrate durable workspace services to MyBatis Plus
(cherry picked from commit 1b0f4b664cb310fe236dfb046bef9c8248543d71)
2026-11-03 14:56:16 +08:00
PIGCLOUD b04588ffae fix: 修复安全过滤链顺序并清理构建告警
(cherry picked from commit 7dfeb3b7ed6b44b12f72cc82aed92a38e9d39af0)
2026-11-03 14:55:55 +08:00
PIGCLOUD fbb5bd121c feat(api): 删除不再使用的 ConnectConstants、SysDeptRelation、CpUserExcelVo、RoleVO 和 SysSystemSmsConfigVO 类文件
- 移除 ConnectConstants 接口及其相关常量定义
- 删除 SysDeptRelation 类,涉及部门关系表的定义
- 移除 CpUserExcelVo 类,涉及企业微信用户导入的定义
- 删除 RoleVO 类,涉及角色表的定义
- 移除 SysSystemSmsConfigVO 类,涉及系统短信配置的定义

(cherry picked from commit 7ef91170320ae5920458b6e0d64c97e0c6422f62)
2026-11-03 14:55:48 +08:00
PIGCLOUD 72ac720fb6 feat(codegen): 删除不再使用的 GenConfig、TableEntity、SqlDto、PayErrorCodes 等类文件
- 移除冗余的代码文件以简化项目结构
- 清理旧的工具类和实体类,提升代码可维护性

(cherry picked from commit f6eb09a169a2a1bd52501b543018aef15f74e21e)
2026-11-03 14:55:43 +08:00
PIGCLOUD cf917b5988 feat(flow): 新增流程回调投递、草稿存储及流程可靠性服务
- 新增 FlowCallbackDelivery 类,实现 HTTP 回调的至少一次投递机制
- 新增 FlowDraftService 类,支持个人流程草稿的保存、读取和删除
- 新增 FlowReliabilityService 类,处理流程通知、催办与回调的持久化
- 删除 FlowWorkspaceTests 测试类,整合测试逻辑至其他模块

(cherry picked from commit 07c8ccc0e845d30dcfaeeb6d01c999460093c8ac)
2026-11-03 14:55:33 +08:00
PIGCLOUD d0aa3a7284 fix(flow): unify workflow notices and draft reliability
(cherry picked from commit 1632fbb83d24be1523e6fa809ed2ad0ca3e6cb0b)
2026-11-03 14:55:33 +08:00
PIGCLOUD 4f6e796c55 chore(deps): upgrade dynamic-datasource to 4.6.0
(cherry picked from commit 7ff6b91a41cda697f52c3560b4202dab0626e0f9)
2026-11-03 14:55:20 +08:00
PIGCLOUD 085235710b feat(flow): 持久化流程草稿提醒与可靠回调
(cherry picked from commit f6871bee7c5cddaaa5650a284ac3cc3fec16dd18)
2026-11-03 14:55:15 +08:00
PIGCLOUD 749931b53e fix(flow): 按发布版本隔离流程节点配置
(cherry picked from commit 86ae98ad5b29a6d20b7e44283549d7337bb961df)
2026-11-03 14:55:00 +08:00
PIGCLOUD a177f3073a feat(app-article, app-article-category, sys-post): 添加文章和分类拖拽排序功能
- 在 AppArticleController 和 AppArticleCategoryController 中新增排序接口
- 在 AppArticleService 和 AppArticleCategoryService 中添加排序方法
- 在 SysPostController 和 SysPostService 中实现岗位排序功能
- 所有排序功能支持按传入 ID 顺序调整,保留未选中记录位置

(cherry picked from commit 0ba00ddcaba9a042bf082c10230042ba0ecf84d2)
2026-11-03 14:54:51 +08:00
PIGCLOUD d927a5b984 feat(pom): 更新 aws.sdk.version 和 git.commit.version 依赖版本
- 将 aws.sdk.version 从 2.44.14 更新至 2.55.3
- 将 git.commit.version 从 4.9.9 更新至 10.0.1

(cherry picked from commit 9072124412e5961d5ff87adc8d3d8839704b5c05)
2026-11-03 14:54:45 +08:00
PIGCLOUD daad35902e feat(pigx-codegen): 新增JDBC URL安全校验器,防止危险参数注入
- 新增JdbcUrlSecurityValidator,支持MySQL、PostgreSQL、HighGo、SQL Server、Oracle、DB2、DM的JDBC URL危险参数检测
- 在GenDatasourceConfServiceImpl中保存数据源配置时进行安全校验,拒绝包含不安全参数的连接
- 新增GenDatasourceConfServiceImplTests测试用例,覆盖安全与安全的URL场景
- 更新AGENTS.md,调整构建命令描述

(cherry picked from commit cabe0775957e6274cf3c31760724a5ee87fdd743)
2026-11-03 14:54:37 +08:00
PIGCLOUD e4bda833bc docs(db): remove unavailable workflow migration reference 2026-11-03 14:51:50 +08:00
PIGCLOUD cbdd0e202c fix(xss): adapt safelist override to updated jsoup 2026-11-03 14:51:50 +08:00
PIGCLOUD ccdbde5229 fix(pigx-common-security): 修复内部请求校验可被伪造 IP 绕过的问题
- 改用 request.getRemoteAddr() 获取客户端地址,避免从可自定义的转发头提取 IP
- 仅放行 IPv4 回环地址,未携带内部标记的外部请求交由后续认证鉴权处理

(cherry picked from commit b5e5b837ef3e82c4d8231be0bcbd6641c3de7516)
2026-11-03 14:49:33 +08:00
PIGCLOUD 3b15ea4235 fix(auth): 限制表单登录仅使用密码认证
(cherry picked from commit d3c470a848b5369459cd2acc9662276ed52b0e15)
2026-11-03 14:49:32 +08:00
PIGCLOUD 3fd14644cd fix(sentinel): 脱敏数据访问异常并保留异常上报
(cherry picked from commit 194b2d10a8210e93874ad4d1789cf0a4fa4889bd)
2026-11-03 14:49:29 +08:00
PIGCLOUD 4471c363cb feat(controller): 为获取客户端详情和导出功能添加权限控制
- 在 getByClientId 方法上添加 @HasPermission 注解,限制访问权限
- 在 export 方法上添加 @HasPermission 注解,限制访问权限

(cherry picked from commit b84bbffd6e4e74c129d5d02bc2fa3809340dddb7)
2026-11-03 14:49:29 +08:00
PIGCLOUD c0a2b97679 feat(pom): 更新 Spring Boot 和 Spring Cloud 版本
- 将 spring-boot.version 更新至 4.1.2
- 将 spring-cloud.version 更新至 2025.1.4

(cherry picked from commit be2fcf39c253c81826a2bb6266b9de6516d22680)
2026-11-03 14:49:28 +08:00
PIGCLOUD 45250841a5 fix: 调整 sys_route_conf 表 route_id 字段长度为 64
- 将 route_id 字段由 varchar(30) 调整为 varchar(64),避免路由 ID 超长导致存储异常

(cherry picked from commit f681502a5badfbc6bf73ee3c34423241c3b14337)
2026-11-03 14:49:28 +08:00
PIGCLOUD 57877b951f fix(flow): 将查询索引维护到原有初始化 SQL
(cherry picked from commit 88f042d1812902938bdcc0186466e43cc99c13da)
2026-11-03 14:49:27 +08:00
PIGCLOUD 618a29be52 perf(flow): 补充工作流列表查询索引
(cherry picked from commit 51d9242b291efd0ee4f4de329f2e6ccf88389014)
2026-11-03 14:49:27 +08:00
PIGCLOUD 67608f76ba fix(dependabot): 禁止 IJPay 自动升级
(cherry picked from commit efd55dffa7b9e826d894862cb466cf8837ce4e95)
2026-11-03 14:49:24 +08:00
PIGCLOUD 22f55b8ba3 fix(db): 更新初始化脚本注释以指明用途
- 添加注释说明工作流新装/存量升级入口
- 确保初始化脚本不用于升级已有数据库

(cherry picked from commit e2a00ee9c1264d25be641089f3729cac60e0f37f)
2026-11-03 14:49:24 +08:00
PIGCLOUD 9d5ff9c022 fix(message): allow users to delete their own notifications
(cherry picked from commit ea051ea5d76ee9e553754f027e6d3c5ce3aec2b1)
2026-11-03 14:49:23 +08:00
PIGCLOUD ec93f78417 feat(dependabot): 增加对 IJPay 小版本升级的支持
- 更新 dependabot 配置,允许 IJPay 依赖的小版本升级
- 修改注释以反映对 LangChain4j 和 IJPay 的支持

(cherry picked from commit 1b3df5325a1ae6516572e8937c5a56031fcd22ad)
2026-11-03 14:49:23 +08:00
PIGCLOUD 65f184ace6 fix(upms): 保存网站配置时保留各终端验证码开关
移除网站验证码模式变更时对所有 OAuth 终端 captcha_flag 的批量同步,保留前端对默认登录终端的同步行为。

Refs: pig/pigx#7631
(cherry picked from commit 836c2ea5e22f9e9a88f60d8a699e4a66e88979b9)
2026-11-03 14:49:22 +08:00
PIGCLOUD ca84985d63 feat(pigx-mp-platform): 新增按wxUserId精确过滤微信消息查询
- 分页查询新增 wxUserId 精确匹配条件,字段为空时不参与过滤
- 更新接口注释,明确各过滤字段的匹配规则
- 新增 WxFansMsgControllerTests 单元测试,验证按公众号和粉丝维度过滤

(cherry picked from commit 66870cc38f44ccc6c116a09c5e5620ac4b43f9b3)
2026-11-03 14:49:20 +08:00
PIGCLOUD b8fda524f8 fix(pigx-codegen): 修改代码生成默认分支为 master
- 将默认分支从 202601 调整为 master,避免生成代码时指向不存在的分支

(cherry picked from commit 0a86a2d9d012198c55ae77a423396ce709498703)
2026-11-03 14:49:20 +08:00
dependabot[bot] dc663491b6 chore(deps): bump org.jsoup:jsoup in /pigx-common/pigx-common-bom
Bumps [org.jsoup:jsoup](https://github.com/jhy/jsoup) from 1.15.4 to 1.23.2.
- [Release notes](https://github.com/jhy/jsoup/releases)
- [Changelog](https://github.com/jhy/jsoup/blob/master/CHANGES.md)
- [Commits](https://github.com/jhy/jsoup/compare/jsoup-1.15.4...jsoup-1.23.2)

---
updated-dependencies:
- dependency-name: org.jsoup:jsoup
  dependency-version: 1.23.2
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
(cherry picked from commit 7e3fd60373145503a28dc998f44b9467d3d7edc4)
2026-11-03 14:49:19 +08:00
PIGCLOUD cca41756c8 chore(deps): upgrade hutool to 5.8.48
(cherry picked from commit cc59d9bf0736cdc75affb25c4e070808da9ae0fd)
2026-11-03 14:49:19 +08:00
PIGCLOUD cb08f11a5d feat(wx-account-fans): 添加粉丝导出功能及数据脱敏处理
- 新增 WxAccountFansExcelVO 类用于粉丝数据的 Excel 导出
- 在 WxAccountFansController 中实现导出接口,支持按条件筛选粉丝
- 更新 WxAccountFansServiceImpl 中的粉丝更新逻辑,确保数据同步至微信
- 对粉丝的 OpenID 进行脱敏处理,确保隐私安全

(cherry picked from commit a277413d3d7681407daca46bbb635f57a032b25f)
2026-11-03 14:49:18 +08:00
PIGCLOUD e63dc8678e feat(excel-converters): 增加 WRITE_INSTANCE 的文档注释
- 为 WRITE_INSTANCE 添加了详细的文档注释,说明其在未指定目标单元格类型时的用途和返回值。

(cherry picked from commit 8bcff3a8a1879eac50527c25bb99ddc4b35b757d)
2026-11-03 14:49:17 +08:00
PIGCLOUD abf10a2a19 feat(excel-converters): 增强内置转换器功能,添加 StringArrayConverter.WRITE_INSTANCE
- 注册 StringArrayConverter.WRITE_INSTANCE 到 Excel 写构造器
- 优化代码格式,保持一致性

(cherry picked from commit 3800300f7f101560674dacc6a0840e279b753a2e)
2026-11-03 14:49:17 +08:00
PIGCLOUD 1db9bdc636 feat(pom): 添加跳过测试的配置
- 在项目属性中添加 `<skipTests>true</skipTests>` 配置,以便在构建时跳过测试。

(cherry picked from commit 1f1126001d2177aac7a3990d42f6c048f701d536)
2026-11-03 14:49:16 +08:00
PIGCLOUD 60babcbc3d fix: 为 JDK 25+ 添加 Byte Buddy 版本覆盖 profile
- 新增 jdk25-byte-buddy profile,在 JDK 25 及以上环境显式指定
  Byte Buddy 版本为 1.18.11,避免 Sentinel BOM 引入的旧版不兼容

(cherry picked from commit 07a61ad7e3a4b5f1f6e166557bbc6a36638d485b)
2026-11-03 14:49:16 +08:00
PIGCLOUD 2bc231f1bf feat(idempotent): 更新 IdempotentAutoConfiguration 和 IdempotentAutoConfigurationTests
- 移除冗余代码,简化 KeyResolver 和 RedissonClient 的配置
- 增强对 Redis 集群和哨兵模式的支持
- 更新测试用例以验证新的配置逻辑

(cherry picked from commit 0064a36a79cbd17c287eef358def60ea58bc9fbd)
2026-11-03 14:49:14 +08:00
PIGCLOUD 464c6df5b8 feat(sql): 更新 chat2bi_table_meta 表结构,调整字符集为 utf8mb4_general_ci
- 修改 chat2bi_table_meta 表的字符集和排序规则为 utf8mb4_general_ci
- 确保数据源相关字段的字符集一致性
2026-09-23 08:38:49 +08:00
PIGCLOUD 7720ea8547 feat(sql): 新增 chat2bi_table_meta 表结构,支持多数据源表元数据管理
- 包含数据源类型、ID、Schema名、表名等字段
- 提供表注释和列定义的 JSON 格式存储
- 增加多租户支持和同步时间字段

(cherry picked from commit f911168762486715c2c061134416c229462744ed)
2026-09-22 23:06:45 +08:00
PIGCLOUD ee27036339 chore: 统一 PIGX 项目版本为 6.2.0 2026-09-22 22:17:22 +08:00
PIGCLOUD db60b48f6c feat(db): 删除用户社交身份表及相关迁移脚本
- 删除 `20260922_user_social.sql` 文件及其内容
- 更新 `README.md`,移除关于用户社交身份迁移的说明
- 删除 `2026-03-18-flow-withdraw-design.md` 和 `2026-03-19-flow-withdraw-resubmit-design.md` 文档,清理与撤回和重新提交流程相关的设计文档
2026-09-22 22:14:02 +08:00
PIGCLOUD 7712a1bb3c fix(db): 补齐旧社交凭据迁移及升级说明 2026-09-22 22:09:47 +08:00
PIGCLOUD 816a63f0c2 fix(db): 对齐商业版初始化与增量升级表结构
参考 ai-dev-next c0b8a966b 的非 AI 表定义,统一单体与分库结构及内置 OAuth 客户端默认授权。保留 AI 表、菜单与路由排除边界。
2026-09-22 22:09:46 +08:00
PIGCLOUD 545b0a4642 refactor(pigx-upms-biz): 重构租户菜单缓存清理逻辑
- 将缩进从4个空格统一替换为Tab,并调整链式调用换行格式
- 重构 updateTenant 方法中菜单缓存清理逻辑,移除 RedisUtils 依赖,改用 Spring Cache 的 Cache.evict 按角色ID清除缓存
- 移除未使用的 RedisUtils 导入,增加 Cache 导入
- 微调日志格式和数组字面量格式

(cherry picked from commit b368a80a83a7d7efb34a63cda26e4ad64e99dfd0)
2026-09-22 21:52:17 +08:00
PIGCLOUD 1dc58c60cf feat(pigx-upms-biz): 增加飞书用户身份绑定功能
- 在 SysUserMapper.xml 中添加对飞书用户的查询支持
- 新增 FeishuLoginHandlerTests 测试类,验证飞书登录处理逻辑
- 测试覆盖飞书身份的代码交换和用户信息查询功能

(cherry picked from commit 2a0796cce45efd4e0444b0e2a6ef0a9e530dd226)
2026-09-22 21:52:04 +08:00
PIGCLOUD 75ec99389c fix(flow): 保留撤回终止原因
(cherry picked from commit ca125bd0ec08472c02c04356a5c4dd22965e3c78)
2026-09-22 21:51:48 +08:00
PIGCLOUD b6681ed578 fix(flow): 修正拒绝结束状态
(cherry picked from commit 5158476c3ff652f6a97256497074ba9cbd448ff5)
2026-09-22 21:51:48 +08:00
PIGCLOUD 53e7a6c2eb feat: 更新配置文件,增加openfeign请求压缩最小请求大小限制
(cherry picked from commit 0d6f12a2b934abe67eb7952e22ca7cdeddbd848f)
2026-09-22 21:51:48 +08:00
PIGCLOUD a810bf8f0b refactor(codegen): 移除 vform 无用代码
(cherry picked from commit 1bf57b916a66d61c6cfe52fdba827bb3c748c296)
2026-09-22 21:51:23 +08:00
PIGCLOUD 840732c52d refactor(pigx-upms): 重构社交登录,社交凭据迁移至独立表并移除码云/开源中国支持
- 将微信、企微、钉钉等社交登录凭据从 sys_user 字段迁移至独立的 sys_user_social 表
- 删除 Gitee 和 OSC 登录处理器及相关常量、枚举和字典项
- 更新绑定/解绑逻辑,使用 sys_user_social Mapper 进行增删改查
- 修改用户查询 SQL,通过 JOIN sys_user_social 表按社交标识查询用户
- 企业微信导入时自动写入社交绑定关系,并处理社交标识冲突异常
- 新增查询当前用户已绑定社交类型接口

(cherry picked from commit 2181b3311d62f980aecd6e144dbe7bce4e8dd8d2)
2026-09-22 21:49:55 +08:00
PIGCLOUD 6a4b8b1f1d Revert "fix(flow): 修正拒绝结束状态"
This reverts commit 4023b142d1.
2026-09-22 21:44:11 +08:00
PIGCLOUD 3f4d1dbf6e feat(sql): 新增 SqlSortUtils 工具类,提供排序字段校验功能
- 实现 isValidColumn 方法,校验前端传入的排序字段是否合法
- 更新 SqlFilterArgumentResolver,使用 SqlSortUtils 进行排序字段校验

(cherry picked from commit 1833847cd835d9972c2237cb804f00fd8075d4e8)
2026-09-22 21:43:41 +08:00
PIGCLOUD 39ea9a6eae feat(idempotent): 增强幂等配置,支持 Redis 集群和哨兵模式
- 新增对 Redis 集群和哨兵模式的支持
- 更新 Redisson 客户端配置逻辑
- 添加 IdempotentAutoConfigurationTests 测试类,验证新配置的正确性

(cherry picked from commit b836af6dc0dfbe17b20740cfda9e417deae1967d)
2026-09-22 21:43:41 +08:00
PIGCLOUD c80d5bc44a upgrade(jimu): 升级依赖版本并清理Nacos配置中的冗余项
- 升级 jimu 版本从 2.5.0 至 2.5.2,fastjson 版本从 2.0.58 至 2.0.65
- 清理 Nacos 配置(pigx-codegen-dev、pigx-daemon-quartz-dev、pigx-mp-platform-dev、pigx-jimu-platform-dev)中多余的 resources 配置项

(cherry picked from commit ad1b4945b9c1624217eee10d331a91a5004970f5)
2026-09-22 21:43:40 +08:00
PIGCLOUD 50b68563a6 feat: 更新nacos版本至3.2.4以增强功能和稳定性
(cherry picked from commit 52745112879f562cc745b3a8ec65603437c018c4)
2026-09-22 21:43:40 +08:00
PIGCLOUD 2a6ce673f5 fix(param): 将前端注册开关的默认值修改为关闭
(cherry picked from commit 4b94ca3fd4d7e2a5c69afbeb18fff8d336459c9d)
2026-09-22 21:43:39 +08:00
PIGCLOUD 08c081304a feat: 支持 JDK 25+ 显式声明 Lombok 注解处理器
- 添加 `jdk25-annotation-processor` profile,解决 JDK 25+ 下注解处理器自动发现关闭的问题

(cherry picked from commit 852cb195aa36425b3f0c512727a4f04b01da410a)
2026-09-22 21:43:39 +08:00
PIGCLOUD bca999535c feat: 更新 Spring Boot 和 Spring Cloud 版本至 4.1.1 和 2025.1.3
(cherry picked from commit 2d0eb6822807eaff80a491ddcaa0e584c0c197d6)
2026-09-22 21:43:39 +08:00
PIGCLOUD d46af13a2e feat(auth): 优化图形验证码生成逻辑,新增自定义颜色支持
(cherry picked from commit af900df10d6e9df4b9812332f126c2e96474722e)
2026-09-22 21:43:38 +08:00
PIGCLOUD 4023b142d1 fix(flow): 修正拒绝结束状态
(cherry picked from commit 5158476c3ff652f6a97256497074ba9cbd448ff5)
2026-09-22 21:43:38 +08:00
PIGCLOUD 269d7fe5e4 fix(quartz): 增加 REST 任务 URL 白名单校验
(cherry picked from commit ad6cd0600641ce916a09efe6affb56db97ad6890)
2026-09-22 21:43:37 +08:00
PIGCLOUD 2edc478f73 fix(codegen): 拦截非法表名
(cherry picked from commit 4e441f50473a4c3c5222002f23de6afdb5c70588)
2026-09-22 21:43:36 +08:00
PIGCLOUD cbb68a0e5b Merge remote-tracking branch 'origin/dev' into dev 2026-09-22 21:30:00 +08:00
PIGCLOUD 9c63820b53 fix: 修复Nacos配置中never-refreshable和endpoint.restart.access配置项,防止数据源死循环
- 将`spring.cloud.refresh.never-refreshable`从`datasource`改为`dataSource`,避免动态刷新导致数据源循环依赖
- 将`management.endpoint.restart.access`从`unrestricted`改为`none`,限制重启端点访问
2026-08-12 23:23:31 +08:00
PIGCLOUD 4ed36c5559 fix(pigx-common-log): 修复Nacos配置修改导致数据源死循环的问题
- 移除 `excludeFields` 字段的 `@Value` 注解注入,改为直接初始化默认值列表,避免动态配置刷新引发循环依赖
2026-08-07 10:12:24 +08:00
PIGCLOUD c3b336aad4 fix(config): 更新配置文件内容,修复nacos 配置修改数据源陷入死循环而down 2026-08-06 17:42:41 +08:00
PIGCLOUD d46e42d51d chore(upms-tests): 删除多个测试文件以清理代码库 2026-08-03 08:30:05 +08:00
PIGCLOUD fe9ee4d1e6 fix(upms): 更新上传文件方法文档,增加路径校验说明 2026-08-03 08:28:06 +08:00
PIGCLOUD 0aaaee14fb fix(upms): 收紧客户端详情查询接口权限 2026-08-03 08:28:06 +08:00
PIGCLOUD a043c4f19e fix(upms): 收紧客户端详情查询接口权限
将 Feign 查询接口改为仅内部调用,并新增带权限的 /client/details 供管理端使用。
2026-08-03 08:27:40 +08:00
PIGCLOUD d1876914d2 fix(upms): 本地文件存储增加路径穿越防护
上传/读取/删除前校验路径位于存储根目录内,统一错误文案,并修复无扩展名时多余的点号。
2026-08-03 08:27:00 +08:00
PIGCLOUD 6248d60e62 refactor(pigx-monitor): 移除 fastjson 依赖,改用 hutool-json 处理 JSON 序列化与反序列化 2026-08-03 08:25:55 +08:00
PIGCLOUD 7461394f99 refactor(pigx-flow): 移除测试文件并禁用 JimuReport 模块
- 删除 `MultiInstanceHandlerTests`、`ProcessNodeRecordServiceImplTests`、`ProcessTaskControllerTests`、`TaskServiceDelegateParticipationTests`、`TaskServiceImplTests` 五个测试类
- 注释 `pigx-visual/pom.xml` 中的 `pigx-jimu-platform` 模块,并添加启用说明注释
2026-08-01 17:24:24 +08:00
PIGCLOUD 55df29df99 feat(pigx-boot): 报表表添加多sheet标识字段
- 在 `jimu_report` 表中新增 `is_multi_sheet` 字段,用于标识是否多sheet报表
- 更新已有数据记录的 `is_multi_sheet` 字段值
2026-08-01 16:56:44 +08:00
PIGCLOUD 0601ed01ed chore(flow): remove temporary add-sign docs 2026-08-01 13:32:20 +08:00
PIGCLOUD 2b6a4d2e85 feat(flow): support dynamic countersign add-sign 2026-08-01 13:32:20 +08:00
PIGCLOUD 5931a5d6d7 feat(upms): support umami analytics 2026-08-01 13:31:35 +08:00
PIGCLOUD 83ee6144b3 chore(menu): 统一导航授权名称 2026-08-01 12:59:24 +08:00
PIGCLOUD 08a82ee09c fix(boot): randomize MyBatis-Plus snowflake node IDs 2026-08-01 12:00:43 +08:00
PIGCLOUD 1dad386954 chore(gitignore): 移除对 docs 目录及其子目录的忽略规则 2026-08-01 12:00:03 +08:00
PIGCLOUD 02cfe26922 chore(deps): ignore MyBatis upgrades 2026-08-01 11:59:35 +08:00
PIGCLOUD 87911c87d0 fix app page empty state 2026-08-01 11:59:35 +08:00
PIGCLOUD 75f426deb3 fix(swagger): 使用相对地址避免跨域 2026-08-01 11:59:35 +08:00
PIGCLOUD 41f20b2db3 fix(data): 延迟初始化数据权限 Feign 客户端 2026-08-01 11:59:35 +08:00
PIGCLOUD d9130d4fbf fix(pigx-upms-api): 调整社交登录敏感字段脱敏策略,缩短掩码显示长度
- 将 SysSocialDetails 中 appId 和 appSecret 的 @Sensitive 脱敏长度从 4/4 和 9/9 统一调整为 2/2,增强敏感信息保护
2026-08-01 11:59:35 +08:00
PIGCLOUD ea6940378c feat(syslog): 增加对不同数据库的日志汇总查询支持 2026-08-01 11:59:35 +08:00
leng leng ce07c9dcb9 feat(area): 重构行政区划管理接口 (#72) 2026-08-01 11:59:35 +08:00
PIGCLOUD fb5e1bdf6e fix(sequence): 发号器自动建表兼容 PostgreSQL 等非 MySQL 方言
Table.from 推导的列缺少 originType,DDL 阶段无法按目标库转换类型,
PostgreSQL 下 DATETIME 原样输出导致建表失败(type "datetime" does not exist)。
补全 originType 使 anyline 方言别名转换(DATETIME -> TIMESTAMP)生效。

同时显式命名主键约束:anyline 随机生成的约束名约 16% 概率以数字开头,
未加引号时为 SQL 语法错误。

MySQL 差分验证建表行为不变;本地 PostgreSQL 实测建表成功。
2026-08-01 11:59:35 +08:00
PIGCLOUD 2ab4d66f28 fix(feign): 修复首次并发请求转换器竞态 2026-08-01 11:59:35 +08:00
PIGCLOUD d3afca673e fix(upms): aggregate log statistics in database (#7568) 2026-08-01 11:59:35 +08:00
PIGCLOUD 0a15577761 fix log multipart serialization 2026-08-01 11:59:35 +08:00
PIGCLOUD 2bc5fb5f24 feat(datasource): 支持通过 query-ds-enabled 关闭数据库配置表加载扩展数据源
新增 spring.datasource.druid.query-ds-enabled 配置项,默认开启;显式设为
false 时跳过从 gen_datasource_conf 表加载扩展数据源,便于不依赖该表的部署
场景关闭此行为。
2026-08-01 11:59:35 +08:00
PIGCLOUD 76ea7f45ac feat(pigx-upms-biz): 小程序登录支持手机号不存在时自动注册
- 当用户不存在且系统注册功能开启时,自动以手机号注册新用户并返回用户信息
- 初始密码使用10位随机数字,注册逻辑与SysRegisterController保持一致
2026-08-01 11:59:35 +08:00
PIGCLOUD 8062730ec3 fix sequence range update name condition 2026-08-01 11:59:35 +08:00
PIGCLOUD 15fb0df080 fix(upms): restrict user list by ids to inner calls 2026-08-01 11:59:35 +08:00
PIGCLOUD 1e74a8e4b2 fix(job): set default XXL-Job access token 2026-08-01 11:59:35 +08:00
PIGCLOUD 194e3e0f99 fix(service): 使用 JakartaMailUtil 替换 MailUtil 发送邮件 2026-08-01 11:59:35 +08:00
PIGCLOUD 4f79671c94 chore(deps): upgrade xxl-job to 3.4.2 2026-08-01 11:58:31 +08:00
PIGCLOUD 91b5d27347 upgrade(xxl-job): 升级 3.4.1 2026-08-01 11:58:10 +08:00
PIGCLOUD d6ef8e4e98 upgrade(xxl-job): 升级 3.4.1 2026-08-01 11:58:02 +08:00
PIGCLOUD 87489ed353 chore(deps): align non-AI platform with 6.1.0 2026-08-01 11:57:32 +08:00
PIGCLOUD e883e64a65 chore(deps): upgrade jasypt to 4.0.4 2026-08-01 11:53:16 +08:00
PIGCLOUD 00a4b30ecb chore(deps): upgrade spring boot admin to 4.1.1 2026-08-01 11:53:16 +08:00
PIGCLOUD 82743a0375 fix(pom): 升级 spring-boot-admin 版本至 4.1.0 2026-08-01 11:52:59 +08:00
PIGCLOUD a8437aacad fix: 升级 spring-cloud 版本至 2025.1.2
- 升级 spring-cloud 版本至 2025.1.2
2026-08-01 11:52:42 +08:00
PIGCLOUD 74fb06e3ea feat(deps): 升级 Spring Boot 4.1.0 并迁移 Redis 监听到 @RedisListener
- spring-boot.version 4.0.6 -> 4.1.0
- 共享容器 Bean 改名为 redisMessageListenerContainer,适配 Boot 4.1 按名称回退的自动配置
- ClientDetailsInitRunner/DynamicRouteInitRunner 移除 InitializingBean 手工注册,改用 @RedisListener
- WxMpInitConfigRunner 移除自定义 redisContainer Bean,改用 @RedisListener
- 注意:需配合 Nacos 共享配置关闭 spring.cloud.compatibility-verifier(SC 2025.1.1 官方仅声明兼容 Boot 4.0.x)
2026-08-01 11:52:42 +08:00
PIGCLOUD bdeba4ce3d fix(core): avoid replacing projecting jackson converter 2026-06-18 22:51:49 +08:00
PIGCLOUD a6af889ccf fix(upms): validate password reset result 2026-06-18 08:33:11 +08:00
PIGCLOUD 9236384ce6 refactor(pigx-register): 添加 hessian 依赖并移除 jraft-core 的排除配置 2026-06-15 13:26:47 +08:00
PIGCLOUD 53bf0dbcb1 fix(db): 将多个表的 tenant_id 字段长度从 10 增加到 64 2026-06-13 19:21:33 +08:00
PIGCLOUD dda210e91a fix: 修复 YungouosMergePayOrderHandler 中的参数传递问题 2026-06-13 19:21:19 +08:00
PIGCLOUD 783c688b6c fix(pigx-gateway):添加命名异步查询订阅服务配置 2026-06-13 19:21:13 +08:00
PIGCLOUD 2c2a9a3bd7 fix(config): 更新 pigx-daemon-elastic-job-dev.yml 配置,添加 XXL-Job 配置
(cherry picked from commit a0d855e01faf89aeb952718150f1220e351ec724)
2026-06-08 12:28:15 +08:00
PIGCLOUD d7c4ab10b3 fix(visual): align xxl_job schema with xxl-job 3.4.0 (add token, sha256 admin) 2026-06-08 11:20:24 +08:00
PIGCLOUD a5d3dff3fc fix(codegen): 加固 Velocity 模板渲染 2026-06-04 18:32:16 +08:00
PIGCLOUD d3966d64f5 chore(deps): 升级依赖版本 2026-06-04 17:20:20 +08:00
PIGCLOUD fef648a8cf refactor(pigx-upms-api): 将 SiteConfigDTO 迁移至 pigx-upms-api 模块
- 移动 SiteConfigDTO 类从 pigx-upms-biz 的 dto 包到 pigx-upms-api 的 api.dto 包
- 更新业务模块中所有对该类的 import 引用
2026-06-04 00:06:54 +08:00
PIGCLOUD 28c16ac730 fix: 默认关闭反调试保护功能
- 将 `SITE_ANTI_DEBUG_ENABLE` 参数默认值从 `1` 改为 `0`
2026-06-03 23:40:01 +08:00
PIGCLOUD b82721c293 feat(codegen): add generator path check
(cherry picked from commit 11dd892078e9b4f5dabf5df1d2c75d61df6823bd)
2026-06-03 20:58:01 +08:00
PIGCLOUD ace1e560f7 feat(pigx-xxl-job-admin): 新增 XXL-Job Admin 微服务配置 2026-06-03 12:59:08 +08:00
PIGCLOUD e3287e3d8a feat(pigx-common-bom): 新增 mybatis-spring-boot-starter 依赖管理
- 添加 mybatis-spring-boot-starter 依赖并配置版本属性 4.0.1
2026-06-03 12:59:05 +08:00
PIGCLOUD 778e795d9d chore: update version from 6.0.0-SNAPSHOT to 6.0.0 in pom.xml 2026-06-01 09:12:29 +08:00
PIGCLOUD 45c7ceec17 chore(pigx-register): 更新 nacos 版本从 3.2.1 到 3.2.2
- 升级 nacos 依赖版本至 3.2.2
2026-06-01 09:05:29 +08:00
PIGCLOUD 5d561bee33 feat(pigx-codegen): 支持实体生成到独立 api 模块
- 新增 DataModelConstants 定义 API_PATH、ENTITY_PATH 等实体路径常量
- 实现 setEntityModel 方法,自动识别 `-biz` 模块同级 `-api` 模块,将实体生成路径和包名切换到 api 模块
- 更新 gen_template.sql 代码生成模板,使用 entityClassName、entityPath 等动态变量替代硬编码包路径
- 扩展 isSpringBoot3 判断逻辑,兼容 SpringBoot 4.x 主版本
2026-05-28 15:57:50 +08:00
PIGCLOUD f172154800 feat(pigx-codegen): 支持实体生成到独立 api 模块
- 新增 DataModelConstants 定义 API_PATH、ENTITY_PATH 等实体路径常量
- 实现 setEntityModel 方法,自动识别 `-biz` 模块同级 `-api` 模块,将实体生成路径和包名切换到 api 模块
- 更新 gen_template.sql 代码生成模板,使用 entityClassName、entityPath 等动态变量替代硬编码包路径
- 扩展 isSpringBoot3 判断逻辑,兼容 SpringBoot 4.x 主版本
2026-05-28 14:41:17 +08:00
PIGCLOUD f3c0b2034c feat(pigx-upms-biz): 重构微信小程序登录,由 openid 改为手机号登录
- 修改 `MiniAppLoginHandler` 登录流程:使用前端 `getPhoneNumber` 返回的 code 换取手机号,并通过手机号获取用户信息;绑定逻辑改为写入手机号字段
- 引入微信接口调用凭证(access_token)的获取与 Redis 缓存机制,减少重复请求
- 新增 `SecurityConstants` 中 `MINI_APP_ACCESS_TOKEN_URL` 和 `MINI_APP_PHONE_NUMBER_URL` 常量
- 移除自动创建小程序用户逻辑,未绑定时直接返回 null
- 提取微信响应校验、缓存读取/写入、HTTP 请求等方法,便于单元测试覆盖
2026-05-28 14:41:15 +08:00
PIGCLOUD dd49790ceb refactor: 更新 XXL-Job Admin 配置
- 重写 `pigx-xxl-job-admin-dev.yml` 配置内容,增加 Web 服务、Actuator 监控、HikariCP 连接池、邮箱服务及 XXL-SSO 单点登录等详细配置
2026-05-26 07:41:17 +08:00
PIGCLOUD 3b6c63dd64 feat(pigx-register): 禁用Nacos AI扩展功能与广告展示
- 添加配置 `nacos.extension.ai.enabled=false` 关闭AI扩展功能
- 添加配置 `nacos.console.ad.enabled=false` 关闭控制台广告展示
2026-05-26 07:40:59 +08:00
PIGCLOUD b19c1c2f0f feat(docs): add behavioral guidelines for coding practices in AGENTS.md and CLAUDE.md 2026-05-13 09:46:38 +08:00
PIGCLOUD 21127c11b5 chore(db): sync non-ai database scripts 2026-05-25 17:31:39 +08:00
PIGCLOUD 5eff0d71df feat: add new models and update application structure for job scheduling 2026-05-01 23:59:12 +08:00
PIGCLOUD 124a2547dd refactor(xxl-job): replace xxl-job-admin for boot4 2026-05-25 17:31:39 +08:00
PIGCLOUD 3132cc3784 feat(pigx-upms-biz): 新增密码规则预设功能 2026-05-21 17:21:03 +08:00
PIGCLOUD 1b87ae9787 refactor(pigx-common-datasource): 重构数据源类型枚举,新增 AnyLine 解析适配器字段及插件状态查询 2026-05-24 18:49:20 +08:00
PIGCLOUD 0fca2924d4 refactor(pigx-common-data): 解耦 pigx-common-data 对 pigx-common-security 的依赖 2026-05-21 10:39:50 +08:00
PIGCLOUD 5ad4dfb711 refactor(pigx-common-security): 统一验证码校验逻辑并新增短信验证码前置校验 2026-05-20 23:24:23 +08:00
PIGCLOUD c796af6c5f refactor(pigx-common-oss): 将OSS操作从S3AsyncClient迁移至同步S3Client 2026-05-18 19:03:23 +08:00
PIGCLOUD 87a1ea1ae0 refactor(pigx-common-excel): 重构 Excel 模块,引入内置转换器注册机制并优化 Excel 读写流程 2026-05-18 15:56:20 +08:00
PIGCLOUD 1d9bfd866f feat(pigx-common-audit): 重构审计模块,支持通过主键自动获取对象进行比对 2026-05-18 14:19:08 +08:00
PIGCLOUD 836fc04a26 refactor(pigx-common-websocket): 优化 WebSocket 缓冲区配置并移除 Undertow 依赖 2026-05-14 14:13:54 +08:00
PIGCLOUD 5f3bff90e1 feat(pigx-flow-biz): 支持分组ID为空时查询所有未隐藏流程 2026-05-11 17:33:12 +08:00
PIGCLOUD 26efa7acbf feat(pigx-pay-platform): 支持微信支付 APIV3 回调与下单, 2026-05-11 11:19:16 +08:00
PIGCLOUD a1edbfcc6e feat(app): 重构APP模块支持TOB 添加角色底部导航管理功能,更新相关接口和实体 2026-05-10 10:57:59 +08:00
PIGCLOUD c48d5f753c feat(pigx-auth): 增加 SM4 国密算法支持并优化密码解密逻辑 2026-05-03 21:25:09 +08:00
PIGCLOUD 32c6e81b3a feat(encrypt): 优化解密逻辑,重构 AES 加解密实现,增加 SM4 密钥校验 2026-05-03 19:40:22 +08:00
PIGCLOUD 7613f72673 feat(pigx-common-core): 降级 Jackson 3 到 Jackson 2 并重构配置 2026-05-02 13:42:11 +08:00
PIGCLOUD e80b4f0b28 fix(feign): 修复 HttpMessageConverterCustomizer 的 UnsupportedOperationException 2026-05-01 22:14:18 +08:00
PIGCLOUD e88b2818fd chore(pom): update parent version to 6.0.0-SNAPSHOT and adjust dependencies fix: correct import paths for Spring Boot components and update Jackson configuration 2026-05-01 22:20:52 +08:00
PIGCLOUD f68327b857 ci: configure build and dependency automation 2026-04-30 16:06:54 +08:00
PIGCLOUD 66e55f3258 refactor(pigx-common-datasource): 简化动态数据源配置逻辑
- 移除 DEFAULT_QUERY_DS_SQL 常量定义
- 直接使用传入的 queryDsSql 参数,简化条件判断逻辑
- 优化构造函数参数初始化方式
2026-03-20 11:32:36 +08:00
PIGCLOUD 9d198266d7 fix(db): 更新 config_info 表中的配置内容和 MD5 值 2026-03-20 11:28:17 +08:00
PIGCLOUD fe64bf38c2 refactor(pigx-common-datasource): 重构动态数据源配置
- 移除 DruidDataSourceProperties 配置类,直接使用 DruidDataSourceWrapper
- 移除冗余的配置属性和创建逻辑,提升代码简洁性
2026-03-20 11:28:11 +08:00
PIGCLOUD f759865202 feat(pigx-flow-biz): 新增流程撤回功能
- 在 ITaskService 接口中添加 withdrawProcessInstance 方法用于撤回流程实例
- 实现 TaskServiceImpl 中的撤回逻辑,包括权限校验和流程状态更新
- 新增 terminateProcessInstance 私有方法统一处理流程终止和撤回操作
- 在 ProcessInstanceRecordVo 中添加撤回相关字段 canWithdraw 和 withdrawDisabledReason
- 优化 ProcessInstanceServiceImpl 查询逻辑,批量处理驳回状态和撤回状态判断
- 在 ProcessTaskController 中添加撤回流程实例的接口端点
- 定义流程撤回相关的常量,包括结束原因和执行人状态
2026-03-19 08:41:55 +08:00
PIGCLOUD b553787cfd docs(flow): add withdraw resubmit design 2026-03-19 08:39:53 +08:00
PIGCLOUD 2c70387ace docs(flow): add starter withdraw design 2026-03-18 23:57:10 +08:00
PIGCLOUD 9d6515d8fa fix(sql): 移除无用的AI菜单插入语句 2026-03-18 08:55:45 +08:00
PIGCLOUD c3f757e38c fix(db): 删除无用的 SQL 2026-03-09 11:20:07 +08:00
PIGCLOUD 61adedf902 fix(pigx-common-data): 添加 SQL 注入检查并移除自定义转义方法
- 在数据权限拦截器中添加 SQL 注入检查,使用 MyBatis-Plus 的 SqlInjectionUtils 工具类
- 移除原有的 escapeSql 自定义转义方法,直接使用原始 username 参数
- 在生成条件表达式和查询语句时增加注入检查逻辑,发现注入风险时返回空结果集
2026-03-09 10:46:07 +08:00
PIGCLOUD 0198431ffa docs(pigx-common-bom): 升级 spring-boot-admin 版本从 3.5.7 到 3.5.8 2026-03-08 18:03:20 +08:00
PIGCLOUD ed60e69d07 docs(pigx-common-bom): 清理过期的依赖项
- 移除 pigx-common-milvus、pigx-common-mcp、pigx-common-neo4j 依赖项
- 删除不再使用的分支合并设计文档文件
- 清理项目中的过期配置和文档
2026-03-08 18:02:14 +08:00
PIGCLOUD e646321d15 docs: 删除过期的分支合并设计文档
- 移除 2026-03-08-merge-aiflow-branch-design.md 文件
- 移除 2026-03-08-merge-aiflow-non-ai-plan.md 文件
- 清理不再使用的分支合并计划和实施方案
2026-03-08 17:57:17 +08:00
PIGCLOUD 40977fbc56 fix(pigx-flow-api): 修复 RemoteFlowApiFlowService 常量引用
将 FLOW_ENGINE_SERVER 改为 FLOW_SERVER 以匹配 ServiceNameConstants 中的定义。
2026-03-08 15:31:40 +08:00
PIGCLOUD 13b8984769 fix: 移除根 pom.xml 中的 pigx-aigc 模块引用和 pigx-boot 中的 aigc-biz 依赖
dev 分支不含 pigx-aigc 目录,移除对不存在模块的引用以确保编译通过。
2026-03-08 15:29:43 +08:00
PIGCLOUD cb8e426855 chore: 更新 boot 开发配置
从 2bb41b75f 提取非 AI 部分。application-dev.yml 添加 Redis database 配置。
2026-03-08 15:23:18 +08:00
PIGCLOUD 7e005eabd0 feat(pigx-upms-biz): 优化 SysTenantServiceImpl 租户处理逻辑
从 19b3e3ba3 提取非 AI 部分。
2026-03-08 15:20:44 +08:00
PIGCLOUD 7070b9f3d2 feat: 增强租户上下文处理 (非 AI 部分)
从 60b4aca0f 提取 db/0pigxx_boot.sql 和 pigx-boot/pom.xml 变更。
2026-03-08 15:19:28 +08:00
PIGCLOUD 57d1d03a6c feat(pigx-common-core): 更新 ServiceNameConstants 添加 AIGC 服务常量
从 b63758c9f 提取非 AI 文件部分。
2026-03-08 15:18:17 +08:00
PIGCLOUD 98656e4af3 chore: upgrade version to 5.12.0 (non-AI modules only)
Cherry-picked from 799188b31, excluding pigx-aigc and AI-related common modules.
2026-03-08 15:15:12 +08:00
PIGCLOUD 96361c21ec feat(pigx-flow-biz): 增加触发器异常终止处理,确保在事务外安全终止流程
- 在 TriggerServiceTask 中重构异常处理逻辑,将直接终止流程改为抛出特定异常
- 在 TaskServiceImpl 中增加触发器异常终止处理,确保在事务外安全终止流程
- 优化任务参数设置逻辑,提前获取 processInstanceId 确保终止流程可用
- 统一流程终止状态管理,使用 NodeStatusEnum.YZZ 表示已终止状态
- 调整代码格式,提高可读性和一致性

feat(pigx-flow-api): 扩展节点状态枚举

- 在 NodeStatusEnum 中新增 YZZ(9, "已终止") 状态,用于标识流程异常终止情况
2026-03-08 15:07:18 +08:00
PIGCLOUD cd2ec46f82 feat(pigx-flow-biz): 优化任务服务参数传递
- 将taskResultDto.getTaskNode()替换为node变量,简化参数设置逻辑
- 保持其他参数设置不变,提高代码可读性
2026-03-08 15:07:13 +08:00
PIGCLOUD 3acab393c4 feat(pigx-boot): 优化模块依赖配置 1.12.1
- 更新 langchain4j 相关依赖版本至 1.12.1
2026-03-08 15:07:09 +08:00
PIGCLOUD 410a869db2 feat(pigx-flow-biz): 新增流程打印模板功能
- 在 Process 实体类中新增 printTemplate 字段,用于存储 HTML 格式的打印模板
- 新增数据库表字段 print_template,支持流程定义的打印模板存储
- 在 ProcessController 中新增获取和保存打印模板的 REST API 接口
- 在 ProcessInstanceRecordVo 中新增 hasPrintTemplate 字段,标识流程是否配置打印模板
- 优化流程实例列表查询,批量检查打印模板配置状态
- 修复 ProcessInstanceServiceImpl 中重复设置 formData 的问题
2026-03-08 15:06:59 +08:00
PIGCLOUD 3c05364e12 feat(pigx-flow-biz): 实现触发器节点功能
- 在 ModelUtil 中新增 TRIGGER 节点类型处理逻辑,调用 buildTriggerNode 方法
- 重构 buildSimpleServiceTaskNode 通用方法,支持构建服务任务节点
- 新增 buildTriggerNode 方法,使用 TriggerServiceTask 处理触发器逻辑
- 新增 TriggerServiceTask 组件,支持调用外部 HTTP 接口并处理返回值映射
- 支持配置请求头、请求体和返回值映射到表单字段
- 提供异常处理机制,支持抛出异常或终止流程两种策略
2026-03-08 15:06:40 +08:00
PIGCLOUD 325f58996d feat(pigx-flow-biz): 实现触发器节点功能
- 在 NodeFormatUtil 中新增 TRIGGER 节点类型处理逻辑
- 重构 ModelUtil 中的 buildSimpleServiceTaskNode 通用方法,支持构建服务任务节点
- 新增 buildTriggerNode 方法,使用 TriggerServiceTask 处理触发器逻辑
- 新增 TriggerServiceTask 组件,支持调用外部 HTTP 接口并处理返回值映射
- 支持配置请求头、请求体和返回值映射到表单字段
- 提供异常处理机制,支持抛出异常或终止流程两种策略
2026-03-08 15:06:36 +08:00
PIGCLOUD b28d86cb59 feat(pigx-flow-api): 新增延时器节点支持
- 新增 TimerConfig 和 TimerDuration DTO 类,用于配置延时器参数
- 在 Node 类中增加 timerConfig 字段,支持延时器配置
- 新增 TIMER 节点类型枚举值

feat(pigx-flow-biz): 实现延时器节点功能

- 在 ModelUtil 中新增 buildTimerNode 方法,支持构建延时器节点
- 新增 TimerHandler 组件,处理表单字段日期格式转换
- 支持三种延时模式:固定时长、指定日期时间、表单字段日期
- 优化连线名称生成逻辑,避免重复设置
2026-03-08 15:06:17 +08:00
PIGCLOUD ecdbfaca68 feat(pigx-flow-biz): 优化流程创建逻辑
- 在创建流程时增加对空节点用户列表的检查,避免空指针异常
- 当 nodeUserList 为空时直接返回成功结果,跳过后续处理步骤
2026-03-08 15:06:12 +08:00
PIGCLOUD 1b27c695d8 feat(pigx-codegen): 优化数据源密码更新逻辑
- 密码为空时自动从数据库查询并解密原始密码用于连接校验
- 简化密码加密逻辑,移除冗余的条件判断
2026-03-08 15:06:08 +08:00
PIGCLOUD 650d791222 feat(pigx-flow-biz): 扩展抄送任务支持角色和岗位类型
- 在 CopyServiceTask 中新增对角色和岗位类型的抄送人员支持
- 新增 addUserIds 工具方法用于用户ID去重合并
- 优化表单数据处理逻辑,避免重复序列化操作
- 更新注释说明支持用户、部门、角色、岗位四种类型
2026-03-08 15:05:50 +08:00
PIGCLOUD ef13df4f79 feat: 优化文件上传配置,统一使用 undertow 服务器设置
- 在 server 配置中新增 undertow.max-http-post-size 参数
- 将 multipart 文件上传大小限制改为引用 undertow 服务器配置
- 保持文件上传大小限制为 100MB,提高配置一致性
2026-03-08 15:05:45 +08:00
PIGCLOUD 191efaad40 feat(pigx-boot): 添加可选模块依赖支持
- 新增 pigx-codegen、pigx-app-server-biz、pigx-daemon-quartz、pigx-flow-biz、pigx-mp-platform、pigx-pay-platform 等可选模块依赖
- 添加注释说明可选模块可根据 AI 能力需求进行删除以提升启动速度
2026-03-08 15:05:36 +08:00
PIGCLOUD 88d057f081 feat(pigx-flow-api): 为 BizFlowBaseDto 添加 ExcelIgnore 注解
- 在 BizFlowBaseDto 的 flowParamMap 字段上添加 @ExcelIgnore 注解
- 导入 cn.idev.excel.annotation.ExcelIgnore 包
2026-03-08 15:05:32 +08:00
PIGCLOUD d70d741e50 refactor: 升级 Spring Boot 版本至 3.5.11
- 更新 pom.xml 中 spring-boot.version 属性为 3.5.11
2026-03-08 15:05:28 +08:00
PIGCLOUD 2efe58556a refactor(pigx-upms-biz): 简化文件上传逻辑,简化文件名编码转换处理逻辑
- 移除 WebUtils 和 StandardCharsets 相关导入
- 删除微服务环境判断逻辑,直接使用 file.getOriginalFilename()
-
2026-03-08 15:03:34 +08:00
PIGCLOUD 583fca8611 fix(codegen): 修复生成模板导出参数的queryForm污染 2026-03-08 15:03:30 +08:00
PIGCLOUD d11856d3f0 refactor(pigx-common-core): 重命名异步任务执行器方法
- 将 applicationTaskExecutor 方法重命名为 applicationAsyncTaskExecutor
- 更新 AsyncSupportConfigurer 配置以使用新的方法名
- 保持线程池配置参数不变
2026-03-08 15:03:27 +08:00
PIGCLOUD 11b6faf6f8 feat(WebCommonConfiguration): 更新异步任务执行器配置,支持Flowable异步任务 2026-03-08 15:03:08 +08:00
PIGCLOUD 84041ed7ce feat(pigx-flow-api): 新增流程状态事件注册与校验功能
- 在FlowStatusEventPublisher中添加流程ID注册和校验方法,使用Redis Set存储已注册的flowId
- 更新FlowStatusEventAutoConfiguration,在启动时自动注册所有本地flowId到Redis
- 重构ProcessServiceImpl中的validateFlowId方法,改为通过Redis查询flowId注册状态
- 优化BpmOaLeaveServiceImpl中的流程参数设置逻辑,使用Dict构建root用户信息
2026-03-08 15:02:49 +08:00
PIGCLOUD 618f3ff1d5 feat(pigx-common-core): 优化WebCommonConfiguration配置类
- 添加@ConditionalOnWebApplication条件注解确保仅在Servlet环境下生效
- 重命名applicationTaskExecutor方法为applicationAsyncTaskExecutor以明确异步执行器用途
- 移除priorityHeaderInitBinder方法上的重复条件注解
- 更新configureAsyncSupport方法使用新的执行器名称
2026-03-08 15:02:45 +08:00
PIGCLOUD 2754607924 feat(pigx-flow-api): 新增流程状态事件发布订阅机制
- 新增 FlowStatusEventPublisher 用于发布流程状态变更事件到 Redis Channel
- 新增 FlowStatusEventListener 用于监听 Redis 消息并分发给匹配的事件服务
- 新增 IProcessInstanceStatusEventService 接口定义流程状态事件处理规范
- 新增 FlowStatusEventAutoConfiguration 自动配置类,实现事件发布者和监听器的 Bean 注册
- 重构 NodeTaskCompleteNotify 服务,使用事件发布机制替代直接调用事件服务
- 将 IProcessInstanceStatusEventService 接口移动到 flow-api 模块的 event 包下
- 在 pigx-flow-api 模块添加 spring-boot-starter-data-redis 依赖支持
- 更新相关服务的包引用和日期注释
2026-03-08 15:02:40 +08:00
PIGCLOUD d1858d5844 feat(pigx-flow-biz): 条件表达式新增角色和岗位选择器条件处理功能
- 新增SelectRoleNodeConditionStrategy类,处理角色选择器类型条件表达式
- 新增SelectPostNodeConditionStrategy类,处理岗位选择器类型条件表达式
- 在ExpressionHandler中新增roleCompare和postCompare方法,支持角色和岗位比较逻辑
- 更新SysUserService接口及实现,新增根据岗位ID列表获取用户ID列表功能
- 在SysUserController中新增根据岗位ID列表获取用户ID列表接口
- 更新RemoteUserService Feign客户端,新增岗位查询方法
- 更新相关文件版权信息和日期注释
- 删除无用的IProcessInstanceStatusEventService接口
- 在数据库中新增bpm_oa_leave请假申请表结构
2026-03-08 15:02:15 +08:00
PIGCLOUD b7631ddeaf feat(pigx-common-core): 增强Web配置支持异步任务处理
- 在WebCommonConfiguration中新增异步任务执行器配置
- 实现WebMvcConfigurer接口并配置AsyncSupportConfigurer
- 添加ThreadPoolTaskExecutor支持Spring MVC异步请求处理
- 通过TaskExecutionProperties配置线程池参数
2026-03-08 15:02:11 +08:00
PIGCLOUD e60a28a17e feat(pigx-upms-api): 新增站内消息/公告发送功能
- 新增MessageNoticeDTO用于站内消息/公告数据传输
- 在RemoteMessageService中添加sendNotice接口
- 在SysMessageService及其实现类中新增sendNotice方法
- 在SysMessageController中新增sendNotice接口并添加权限控制
- 完善消息保存逻辑,支持站内消息/公告的发送
2026-03-08 15:02:04 +08:00
PIGCLOUD 7015e4704c feat(pigx-boot): 在 Dockerfile 中添加中文字体支持
- 安装 wqy-microhei-fonts 以解决词云中文显示问题
- 清理 yum 缓存以优化镜像大小
2026-03-08 15:01:46 +08:00
PIGCLOUD 4868f0d213 fix(pigx-upms-biz): 修复租户用户移除时的租户切换问题
- 在removeTenantUser方法添加@Transactional注解确保事务性
- 增加用户当前租户检查逻辑
- 当用户当前租户是被移除租户时自动切换到其他可用租户
- 更新用户租户信息后清除用户缓存
2026-03-08 15:01:27 +08:00
PIGCLOUD a44319f898 feat(pigx-knowledge): 移除知识库路由配置
- 从 sys_route_conf 表中删除知识库模块的路由配置记录
2026-03-08 15:01:23 +08:00
PIGCLOUD 0187d93912 fix: 更新 spring-boot 版本至 3.5.10,修正 spring-boot-admin 版本至 3.5.7 2026-03-08 15:01:04 +08:00
PIGCLOUD c19c0f1ed4 feat(pigx-mp-platform): 重构 WxMpInitConfigRunner 类,添加详细文档注释
- 优化消息路由规则配置,支持多种微信事件处理
- 增加 Redis 监听机制,支持运行时动态重新加载配置
- 完善多租户支持,缓存 appid 与租户的映射关系
2026-03-08 15:00:56 +08:00
akhan 7e78541763 🐞 fix: 修复当不同租户appid重复时导致的mpservice初始化失败 2026-03-08 14:59:00 +08:00
PIGCLOUD 4d9093c851 fix(pigx-common-bom): 更新依赖版本
- 将 flowable.version 从 7.0.0 升级到 7.2.0
2026-03-08 14:58:55 +08:00
PIGCLOUD f312f1b229 fix(pigx-common-core): #7229 登录时调用 getUserInfo 获取用户权限,但此时租户上下文还没设置(或设置为默认租户 1),导致 findMenuByRoleId 查询的是错误租户的菜单数据。 @786556226 2026-03-08 14:58:51 +08:00
PIGCLOUD 70334d3c11 fix(pigx-common-bom): 更新MyBatis-Plus版本至3.5.16
- 将mybatis-plus.version从3.5.15升级到3.5.16
2026-03-08 14:58:45 +08:00
PIGCLOUD 23287b77ea fix(pigx-common-security): 添加token过期错误提示
- 在messages_en.properties中添加OAuth2ResourceOwnerBaseAuthenticationProvider.tokenExpired错误消息
2026-03-08 14:58:21 +08:00
PIGCLOUDandClaude Opus 4.5 d2f49723d6 feat(upms): 重构连接器导入功能,支持钉钉和企业微信Excel导入
- 优化钉钉部门同步逻辑,提取常量到 ConnectConstants
- 新增企业微信部门及用户Excel导入功能
- 实现钉钉部门和用户Excel导入功能
- 移除API同步功能,统一使用导入方式

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-03-08 14:58:10 +08:00
PIGCLOUD 31ad1fbeb8 fix(pigx-common-security): 修复用户密码修改时间处理逻辑
- 修改 PigxUserDetailsService 中密码修改时间的处理逻辑
- 当 passwordModifyTime 为 null 时使用 createTime 作为替代值
2026-03-08 14:57:45 +08:00
PIGCLOUD 27898142ac fix(pigx-common-datasource): 修正动态数据源查询中的 del_flag 参数值
- 将 JdbcDynamicDataSourceProvider 中的 del_flag 参数从 YES 改为 NO
- 确保查询未删除的数据源记录
2026-03-08 14:57:02 +08:00
PIGCLOUD bf2ed2f9f7 fix: 修复 sys_dict_item 表数据中新增的 NULL 字段
- 在 sys_dict_item 表的 INSERT 语句中新增了 NULL 字段
- 修改了 0pigxx_boot.sql、2pigxx.sql 和 9pigxx_ai.sql 三个数据库脚本文件
2026-03-08 14:56:37 +08:00
PIGCLOUD fefbc25f45 feat(pigx-upms-api): 为 SysDictItem 添加 listClass 字段用于标签类型
- 在 SysDictItem 实体类中新增 listClass 字段用于标签类型
- 更新数据库表结构,在 sys_dict_item 表中添加 list_class 列
2026-03-08 14:56:12 +08:00
PIGCLOUD 6fc0a3de36 feat(pigx-upms-biz): 增强区域树查询功能
- 在 SysAreaServiceImpl 中添加 areaType 过滤条件
- 重构查询条件构建逻辑,使用 LambdaQueryWrapper
- 保持原有 areaStatus 和 areaSort 排序条件
2026-03-08 14:56:08 +08:00
PIGCLOUD 2acdceac2a feat(i18n): set default locale to China for message sources 2026-03-08 14:56:04 +08:00
PIGCLOUD b59765f927 fix(ai-register-user): 跳过外部 AI 注册短信验证
- 添加 SecurityConstants 导入
- 使用 WebUtils 获取 请求头
- 当 header 为 FROM_IN 时跳过 短信验证
- 保持内部注册验证逻辑
2026-03-08 14:55:44 +08:00
PIGCLOUD 79dd2471ad docs: 添加 aiflow 分支非 AI 代码合并设计方案和实施计划 2026-03-08 14:53:45 +08:00
PIGCLOUD f56a63beba refactor(pigx-common-data): 重构数据权限拦截器实现,使用 JSqlParser 直接操作 AST 修改 WHERE 条件,避免子查询包装导致索引失效
- 支持复杂 SQL 解析失败时自动回退到子查询包装方案
- 优化表引用处理逻辑,优先使用别名限定列名
- 增加 SQL 注入防护,对字符串值进行转义处理
- 重构条件构建逻辑,支持 AND/OR 逻辑组合
- 完善日志记录和异常处理机制
2026-03-08 13:59:39 +08:00
202312111133 173bc6853d 更新 'pigx-common/pigx-common-data/src/main/java/com/pig4cloud/pigx/common/data/datascope/DataScopeInnerInterceptor.java'
这样修改之后sql会走索引,数据量大的时候不至于查询超时
2026-03-05 16:17:32 +08:00
PIGCLOUD b9268e4393 Merge branch 'dev' 2026-01-03 23:06:51 +08:00
PIGCLOUD c36ef5fdf5 refactor(copyright): 更新版权年份至 2026
- 统一更新所有源文件、LICENSE、pom.xml 等的版权年份至 2026
2026-01-03 22:55:26 +08:00
PIGCLOUD 25e16f5dd6 feat(upms): 优化密码验证逻辑,返回布尔值以指示验证结果 2026-01-03 11:30:51 +08:00
PIGCLOUD 7bdf9e1d8c feat(upms): 增强租户管理功能并优化用户租户信息处理
- 在UserInfo DTO中新增tenantName字段用于返回租户名称
- 重构SysTenantService.getOrUpdateTenant方法返回完整租户对象
- 更新用户登录逻辑以包含租户名称信息
- 修改默认租户名称为PIGX ADMIN
- 优化租户切换逻辑确保缓存一致性
2025-12-30 21:42:42 +08:00
PIGCLOUD 36620c05ad feat(upms): 移除DingTalk SDK中冲突的mail依赖
- 在pom.xml中为alibaba-dingtalk-service-sdk添加exclusions配置
- 排除javax.mail依赖以避免与其他模块的版本冲突
2025-12-30 21:41:49 +08:00
PIGCLOUD 85a1d609e3 feat(tenant): 添加租户上下文过滤器的描述和执行顺序 2025-12-30 14:49:47 +08:00
PIGCLOUD 13d17923e4 feat(upms): 增强短信验证码注册功能和安全机制
- 在RegisterUserDTO中新增短信验证码字段
- 用户注册时增加短信验证码校验逻辑
- 合并短信验证码发送接口为单一API
- 增加IP频率限制防止短信轰炸攻击
- 优化验证码校验失败的错误返回类型
2025-12-30 10:46:02 +08:00
PIGCLOUD e959811fa2 feat(codegen): 支持动态数据源切换功能
- 在GenTableController的export方法中添加DynamicDataSourceContextHolder支持
- 实现根据table参数动态切换数据源功能
2025-12-29 14:53:41 +08:00
PIGCLOUD 5a324b75c9 refactor(build): 移除多个模块中spring-boot-maven-plugin的CLASSIC配置
- 统一清理pigx-flow/pigx-app-server等模块的冗余loaderImplementation配置
- 简化各模块pom.xml中的spring-boot-maven-plugin配置项
2025-12-28 16:38:52 +08:00
PIGCLOUD 6743d8d7ab feat(version): 升级项目版本至5.11.0
- 更新所有模块的pom.xml中version字段
- 同步更新CLAUDE.md文档中的版本信息
2025-12-28 16:33:51 +08:00
PIGCLOUD bfd64bbd47 feat(pay): 升级yungouos-pay-sdk版本并优化依赖配置
- 将yungouos-pay-sdk版本从2.0.37升级至2.0.39
- 排除hutool-all依赖以避免与系统已有依赖冲突
- 在YungouosMergePayOrderHandler中新增pay参数配置
2025-12-28 11:28:02 +08:00
PIGCLOUD 77ebb4fe37 fix(pom): update spring-boot and dynamic-ds versions 2025-12-28 11:27:57 +08:00
PIGCLOUD aaab895655 fix(pom): 更新spring-cloud版本至2025.0.1 2025-12-28 11:27:21 +08:00
PIGCLOUD f30b32a28a feat(upms): 重构国际化消息和错误码模块化架构
- 移除全局ErrorCodes接口,按模块拆分Auth/Upms/App错误码定义
- 新增模块化i18n消息文件,支持多JAR包扫描加载机制
- 重构MsgUtils支持LocaleContextHolder动态区域解析
- 统一OAuthClientException异常处理支持错误码和描述参数
- 优化企业微信/钉钉同步错误消息国际化支持
2025-12-28 11:27:03 +08:00
PIGCLOUD 7911761653 refactor(RemoteUserService): 优化方法参数注解格式以提高可读性 2025-12-28 11:26:23 +08:00
PIGCLOUD 825b9a147b feat(data-permission): 新增数据权限逻辑组合模式支持
- 新增DataScopeLogicEnum枚举类定义AND/OR逻辑组合模式
- 在DataScope类中添加logicMode字段控制权限组合方式
- 修改DataScopeInnerInterceptor支持动态组合权限条件
- 默认保持OR逻辑以向后兼容现有功能
2025-12-28 11:25:42 +08:00
PIGCLOUD 16a7f9309f feat(flow): 新增驳回到发起人功能
- 在ModelUtil重构开始节点结构,添加root UserTask节点
- 新增RootTaskCreateListener处理驳回到发起人场景
- 新增RootTaskHandler解析发起人执行人
- 在ApproveServiceTask添加TO_START驳回处理逻辑
- 新增ProcessInstanceRecordVo包含驳回状态信息
- 在TaskService添加resubmitTask接口处理重新提交
- 在ProcessTaskController添加resubmitTask接口
2025-12-28 11:25:38 +08:00
PIGCLOUD 0ad5864476 feat(process): 新增流程ID有效性验证功能
- 在IProcessService接口添加validateFlowId方法声明
- 在ProcessServiceImpl实现流程ID验证逻辑
- 在ProcessController添加validateFlowId接口供前端调用
- 支持检查流程ID是否在IProcessInstanceStatusEventService实现类中注册
2025-12-28 11:25:36 +08:00
PIGCLOUD d6c1a0aad1 feat(task): completeTask时同步更新主表单数据
- 扩展queryTask接口支持选择主表单数据源
-
- 优化已完成任务的数据获取逻辑
- 保持原有节点快照数据作为备选方案
2025-12-28 11:25:33 +08:00
PIGCLOUD ab97082cd8 feat(menu): 优化removeMenuById方法实现递归删除子菜单 2025-12-28 11:25:26 +08:00
PIGCLOUD 65297a5574 feat(deps): 升级mybatis-plus至3.5.15版本 、升级hutool至5.8.42版本 2025-12-28 11:23:21 +08:00
PIGCLOUD 2716c65170 feat(oss): 优化OssTemplate 在afterPropertiesSet方法中禁用AWS v1弃用公告
- 统一调整代码缩进为4个空格提升可读性
-
- 保持原有功能逻辑不变
2025-12-28 11:21:56 +08:00
PIGCLOUD 87d1162c45 feat(build): 升级Spring Boot版本至3.5.8
- 更新pom.xml中的spring-boot.version属性至3.5.8版本
- 保持其他依赖版本不变
2025-12-28 11:21:41 +08:00
PIGCLOUD 4adc7b00de feat(auth): 重构FormIdentityLoginConfigurer的handler依赖结构
- 将SsoLogoutSuccessHandler移动到common-security模块中统一管理
- 使用TenantSavedRequestAwareAuthenticationSuccessHandler替代原有success handler
- 保持FormAuthenticationFailureHandler作为默认failure handler
2025-12-28 11:21:24 +08:00
PIGCLOUD f181712cf2 feat(pay): 增强支付回调接口的XSS防护功能
- 在aliCallbak和mergeCallbak接口中添加Content-Type和X-Content-Type-Options安全头
- 在mergeBuy接口中设置安全响应头防止XSS攻击
- 统一使用MediaType.TEXT_PLAIN作为响应内容类型
2025-12-28 11:21:20 +08:00
PIGCLOUD e1ac291a1e feat(auth): 增强XSS防护功能
- 在confirm.ftl模板中对principalName等变量添加?html转义
- 在login.ftl模板中对tenant.id和error变量添加防护处理
- 移除冗余的SsoLogoutSuccessHandler实现类
- 在PigxTokenEndpoint中添加XSS防护注释说明
2025-12-28 11:21:18 +08:00
PIGCLOUD 1268e9d604 refactor(pigx-common-sentinel): 添加hutool-extra依赖
- 新增hutool-extra工具库依赖以增强sentinel模块功能
2025-12-28 11:21:08 +08:00
PIGCLOUD 437970b926 feat(SentinelParser): 更新请求来源解析逻辑,基于客户端 IP 地址 2025-12-28 11:21:08 +08:00
pig666 5ce0abdcd6 Merge branch 'dev' of 202504296/pigx into dev 2025-11-18 16:58:17 +08:00
kukinghan 71a6f5c2d7 fix(sql): 修正参数查看菜单的操作标识为'sys_syspublicparam_view' 2025-11-18 16:23:50 +08:00
PIGCLOUD efd195ae37 feat(RemoteDataScopeService): 修改getRoleList参数类型为List<String>以支持字符串类型roleId
- 将getRoleList方法的roleIdList参数类型从List<Long>改为List<String>
- 保持getDescendantList方法的deptId参数类型仍为Long不变
2025-11-18 09:54:56 +08:00
PIGCLOUD 0b939f3d57 feat(gen-table): 批量代码生成支持复用单表的配置信息 2025-11-18 09:39:57 +08:00
PIGCLOUD 5123e3f116 feat(security): 新增单体一键 CORS跨域配置支持 security.cors.enabled
- 新增PigxBootCorsProperties配置类用于管理CORS跨域参数
- 在AuthorizationServer和ResourceServer中集成CORS配置逻辑
- 支持通过security.cors.enabled开关控制跨域功能
- 提供allowedOriginPatterns等细粒度跨域参数配置
2025-11-18 09:39:53 +08:00
PIGCLOUD 470f5e7fdb feat(db): 在sys_user表新增dept_id字段
- 添加主部门ID字段用于关联用户与部门关系
- 更新admin用户的初始化数据包含dept_id值
2025-11-18 09:39:46 +08:00
PIGCLOUD c88762a433 fix(SysUserDept): 修正用户ID和部门ID的Schema描述为正确的格式 2025-11-18 09:39:40 +08:00
PIGCLOUD 6d837c6f1c fix(ImageCodeEndpoint): 修改验证码类型为动态参数,支持多种验证码类型
fix(ValidateCodeFilter): 更新验证码校验逻辑,支持滑块和点击文字验证码
2025-11-18 09:39:37 +08:00
PIGCLOUD 1a8d0c0898 fix(SysDeptMapper): 移除查询结果的排序条件 2025-11-18 09:39:21 +08:00
PIGCLOUD c0112af189 fix(nacos): 更新nacos版本为3.1.0-bugfix以修复已知问题
(cherry picked from commit 99daf9db95)
2025-11-18 09:39:16 +08:00
PIGCLOUD 6de57dfab1 fix(upms): 修复用户登录失败次数缓存清理问题
- 在用户登录成功时清理对应的登录失败次数缓存
- 使用RedisUtils删除格式化的缓存key
- 防止因缓存残留导致用户被错误锁定
2025-11-18 09:39:05 +08:00
PIGCLOUD a25963323b feat(security): 增强OAuth2 token验证的用户状态检查
- 在PigxCustomOpaqueTokenIntrospector中增加用户账号状态检查逻辑
- 当用户账号被锁定或过期时拒绝访问并抛出InvalidBearerTokenException
- 完善账号异常状态的日志记录和错误处理机制
- 保持原有客户端信息注入功能不变
2025-11-18 09:38:55 +08:00
PIGCLOUD 15f28dcd35 feat(personal): 修改手机号,新增短信验证码校验功能
- 在UserDTO中增加验证码字段用于手机号修改校验
- 修改用户信息时增加短信验证码校验逻辑
- 新增验证码错误提示信息到i18n配置
- 扩展SysMessageService支持区分已注册/未注册手机号验证
2025-11-18 09:38:38 +08:00
PIGCLOUD 45146adec1 refactor(dependencies): 升级log4j2版本至2.25.2
- 更新log4j2依赖版本以修复潜在安全漏洞
- 保持与其他依赖版本的兼容性
2025-11-18 09:38:33 +08:00
PIGCLOUD 646859625b refactor(ConnectServiceImpl): 优化第三方API集成代码结构
- 提取DingTalk/WeChat API字段名为常量
- 统一语言代码为常量LANGUAGE_ZH_CN
- 优化JSON字段访问方式避免硬编码
- 重构企业微信配置获取逻辑
- 增强代码可读性与维护性
2025-11-18 09:38:28 +08:00
PIGCLOUD b7c4132765 feat(security): 优化Feign token传递逻辑
- 重构PigxOAuthRequestInterceptor的token获取流程
- 优先从Web请求中解析token,失败后从NonWebTokenContextHolder获取
- 增加Objects.nonNull检查确保request不为空
- 优化token传递逻辑,支持消息队列等非Web场景
2025-11-18 09:38:04 +08:00
PIGCLOUD 74110199e2 fix(login): 增加登录参数空值校验
- 在OscChinaLoginHandler中增加identify空值校验
- 在WeChatCPLoginHandler中增加userid空值校验
- 在CasLoginHandler中增加username空值校验
- 在MiniAppLoginHandler中增加openId空值校验
- 在SmsLoginHandler中增加identify空值校验
- 在GiteeLoginHandler中增加identify空值校验
- 在WeChatLoginHandler中增加openId空值校验
- 在DingTalkLoginHandler中增加openId空值校验
2025-11-18 09:37:57 +08:00
PIGCLOUD 6117c47d7c feat(user): 支持用户多部门关联及主部门切换功能
- 在SysUser实体类中新增deptId字段标识主部门
- 扩展UserDTO支持多部门ID列表传递
- 重构用户部门关联逻辑,支持设置主部门
- 新增获取用户部门列表和切换主部门接口
- 优化部门查询SQL确保主部门排序优先
- 调整用户详情查询逻辑适配多部门场景
2025-11-18 09:37:43 +08:00
PIGCLOUD 99daf9db95 fix(nacos): 更新nacos版本为3.1.0-bugfix以修复已知问题 2025-11-07 15:37:03 +08:00
PIGCLOUD 16dcbef197 feat(pom): 移除不再使用的pigx-common-milvus、pigx-common-mcp和pigx-common-neo4j依赖 2025-10-29 22:22:13 +08:00
PIGCLOUD dc3ad69a38 reset(build): 添加release参数支持JDK新特性编译,避免非Java25
- 在maven-compiler-plugin配置中新增release参数
- 移除过时的annotationProcessorPaths配置
- 保持与source参数一致的JDK版本兼容性
2025-10-28 16:45:00 +08:00
claudecode 92d9b403c0 feat(flowable): 升级Flowable版本至7.2.0并合并flow模块
- 将Flowable依赖版本从7.0.0升级至7.2.0
- 合并pigx-flow-engine-biz和pigx-flow-task-biz模块为pigx-flow-biz
- 简化pom.xml依赖配置结构
2025-10-26 22:37:03 +08:00
claudecode f4508ac412 feat(flowable): 升级Flowable版本至7.2.0并重构数据库工具类
- 将Flowable依赖版本从7.0.0升级至7.2.0
- 提取AbstractEngineConfiguration中的数据库类型映射逻辑到独立工具类DbUtil
- 新增DbUtil工具类封装数据库类型检测和映射功能
- 删除过时的AbstractEngineConfiguration实现类
2025-10-26 22:36:48 +08:00
claudecode 1bb0af7b52 feat(quartz): 新增Job安全验证机制
- 新增JobSecurityValidator类用于防止RCE漏洞
- 在SysJobServiceImpl中集成安全验证逻辑
- 为JavaClassTaskInvok和SpringBeanTaskInvok添加安全验证
- 在quartz-config.yml中新增安全验证开关配置
2025-10-26 21:32:32 +08:00
claudecode 99d295bfa8 feat(sys-token): 增强token管理功能并修复权限控制
- 为分页查询接口添加sys_token_del权限注解
- 修复删除接口的token参数命名不一致问题
- 统一代码缩进格式为4个空格
2025-10-26 21:32:24 +08:00
claudecode 6f9d41b624 feat(flow): 增加流程节点进行中状态展示功能
- 在ProcessInstanceServiceImpl中新增continueNodeSet处理逻辑
- 扩展NodeFormatUtil以支持JXZ状态节点展示
- 优化流程可视化展示效果,区分已完成和进行中节点
2025-10-26 21:32:12 +08:00
claudecode 14cdf670f2 feat(sys-token): 升级nacos版本至3.1.0
- 更新pigx-register模块的nacos依赖版本
- 保持注册配置中心功能与最新稳定版本兼容
2025-10-26 21:32:07 +08:00
徐晓伟 d67bee5476 🔧 支持 JDK 25 编译
(cherry picked from commit 9cea4f20c3)
2025-10-26 21:31:58 +08:00
claudecode 0674403268 feat(deps): 升级Nacos客户端版本以修复兼容性问题
- 添加nacos-client.version属性并设置为3.1.0
- 引入com.alibaba.nacos:nacos-client依赖项
- 解决Nacos相关issue ID2OA3的兼容性问题
2025-10-21 11:27:14 +08:00
claudecode 103f5e72b0 chore(dependencies): 更新依赖库版本
- 升级hutool工具库版本至5.8.41
- 更新spring-cloud-alibaba版本至2025.0.0.0

# Conflicts:
#	pigx-common/pigx-common-bom/pom.xml
2025-10-20 10:27:16 +08:00
claudecode dacdb83989 feat(quartz): 增强多租户定时任务处理逻辑
- 在getJobKey和getTriggerKey方法中增加TenantContextHolder的租户ID兜底逻辑
- 当SysJob中tenantId为空时自动使用当前线程上下文租户ID
- 优化方法注释使其更符合JavaDoc规范
2025-10-20 10:25:38 +08:00
claudecode d16d8bc18a feat(flow): 扩展流程发起人权限验证支持岗位类型
- 在NodeUserTypeEnum中新增POST类型以支持岗位权限验证
- 修改CombinationGroupServiceImpl中的权限验证逻辑,增加对岗位权限的检查
- 调整PigxUser结构以支持多部门、多角色、多岗位的存储
- 更新AssignUserLeaderStrategyImpl以适配用户的多部门信息
- 在SysDeptServiceImpl的getOrgTree方法中增加对岗位类型的支持
- 优化UserVO中集合属性的初始化以避免空指针异常
2025-10-17 15:42:09 +08:00
冷冷 7710baa92a feat(flow): 扩展流程发起人权限验证支持岗位类型
- 在NodeUserTypeEnum中新增POST类型以支持岗位权限验证
- 修改CombinationGroupServiceImpl中的权限验证逻辑,增加对岗位权限的检查
- 调整PigxUser结构以支持多部门、多角色、多岗位的存储
- 更新AssignUserLeaderStrategyImpl以适配用户的多部门信息
- 在SysDeptServiceImpl的getOrgTree方法中增加对岗位类型的支持
- 优化UserVO中集合属性的初始化以避免空指针异常
2025-10-17 14:55:50 +08:00
claudecode 883293cc2a feat(flow): FlowableUtils添加getFlowParamMap方法统一处理流程发起人参数
- BpmOaLeaveEntity继承BizFlowBaseDto以复用流程基础字段
- 新增BizFlowBaseDto作为流程基础数据传输对象
-
- 优化BpmOaLeaveServiceImpl流程启动逻辑,使用工具类简化代码
2025-10-17 08:56:09 +08:00
pigcloud ed6138b566 refactor(dependencies): 升级项目版本至5.10.0
- 统一更新所有模块的parent版本号
- 标准化pom.xml文件格式和缩进
- 保持依赖配置和模块结构的一致性
2025-10-10 12:53:02 +08:00
pigcloud 4b8775153b refactor(dependencies): 升级项目依赖版本
- 升级 Spring Boot 版本至 3.5.6
- 升级 Spring Boot Admin 版本至 3.5.5
- 升级 MyBatis Plus 相关依赖版本
- 升级 Hutool 工具库版本至 5.8.40
2025-10-10 12:50:39 +08:00
pigcloud f53e542100 ref(flow-biz) 合并 flow-task 、flow-engine 模块 2025-10-10 09:43:40 +08:00
PIGAI 38916dda25 feat(security): 新增单体架构下内部请求头安全过滤机制
- 添加PigxInnerHeaderRemoveFilter类用于防止前端伪造inner header
- 实现基于IP地址和FROM请求头的访问控制逻辑
- 在AutoConfiguration中注册过滤器配置
- 添加hutool-extra依赖支持IP地址工具类
2025-10-09 14:52:27 +08:00
冷冷 d8ddacd143 feat(register): 增加数据库连接池配置参数
- 添加connectionTimeout与validationTimeout配置项
- 提升数据库连接稳定性和超时控制能力
2025-10-09 14:52:19 +08:00
冷冷 e3f4200a39 feat(role-menu): add new role menu entry for ID 1105 2025-10-09 14:51:58 +08:00
冷冷 9ee99d4063 style(common-oss): 统一代码格式并优化路径分隔符处理
- 将代码缩进统一调整为4个空格
- 将硬编码路径分隔符替换为FileUtil.FILE_SEPARATOR
- 优化AmazonS3Client构建器的代码格式
- 移除冗余注释和空行
2025-10-09 14:51:42 +08:00
冷冷 b329b5c501 feat(pay): 优化微信支付URL构建逻辑
- 重构redirectUri构建方式,调整参数顺序提高可读性
- 简化URL拼接逻辑,移除不必要的条件判断
- 保持原有功能不变的情况下改进代码结构
2025-10-09 14:51:39 +08:00
冷冷 8c924da2dc feat(pay): 更新微信支付回调URL和重定向URI以支持微服务架构
- 修改WeChatMpPayOrderHandler中notify_url路径逻辑适配微服务环境
- 调整PayGoodsOrderController中redirect_uri构造方式支持微服务路由
- 使用WebUtils.isMicro()动态判断当前运行环境
- 统一支付模块在微服务和单体架构下的URL路径格式
2025-10-09 14:51:29 +08:00
PIG AI 02e60b3968 feat(security): 为关键接口添加权限控制注解
- 在SysPublicParamController等Controller的分页查询方法添加@HasPermission注解
- 新增sys_user_view等权限菜单项到数据库
- 更新角色菜单关联表以包含新增权限
- 修复渗透测试发现的权限控制缺失问题
2025-10-09 14:51:09 +08:00
PIG AI c6c76b3cbd feat(fix): 移除创建用户时自动关联租户的逻辑 #6864 5.9版本,通过excel表批量导入用户,前端提示“上传失败,数据格式不合法!”,刷新后发现只有1条导入。 2025-10-09 14:50:42 +08:00
lengleng 9c237c9921 feat(flow): 支持业务表单,提供业务表单示例 2025-10-09 14:50:28 +08:00
lengleng cd1854e498 feat(flow): 支持业务表单,提供业务表单示例 2025-10-09 14:50:27 +08:00
lengleng 0d5326ff77 fix(sys): 修复通讯录菜单路径错误
- 修正sys_menu表中通讯录菜单的路径为/biz/app/appContacts/index
- 同步更新0pigxx_boot.sql和2pigxx.sql中的相关记录
2025-10-09 14:49:53 +08:00
lengleng 0eaa4b6d11 feat(flow): 新增表达式分配用户策略支持
- 在Node DTO中添加assignExpress和assignExpressName字段
- 实现AssignExpressStrategyImpl表达式分配策略类
- 支持通过表达式动态计算任务执行人列表
- 优化NodeFormatUtil中的用户分配逻辑
- 更新ProcessInstanceConstant添加表达式分配类型常量
2025-10-09 14:48:42 +08:00
lengleng 79b27b6d7d feat(auth): 增强认证逻辑,支持密码过期校验及定时攻击保护机制 2025-10-09 14:48:11 +08:00
lengleng 2551ef2606 refactor(RedisUtils): 统一RedisTemplate泛型类型并优化代码格式
- 将所有RedisTemplate声明统一为<String, Object>类型提高类型安全
- 调整代码缩进格式为统一标准
- 移除冗余的Optional.ofNullable包装简化代码逻辑
- 保持原有Redis操作方法功能不变
2025-10-09 14:47:45 +08:00
lengleng a60127323e refactor(sequence): 优化Redis序列号生成器实现
- 使用Lombok的@Getter/@Setter简化stringRedisTemplate和stepStart字段访问
- 移除冗余的空字符串检查方法isEmpty
- 清理未使用的getter/setter方法减少代码量
- 保持原有核心序列号生成逻辑不变
2025-10-09 14:47:41 +08:00
lengleng 70855f8b5b fix(auth): 修复微信登录新用户插入用户表时返回信息报错问题#6809
- 在retrieveUser方法中添加对pigxUser.getTenantId()的非空检查
- 使用Objects.nonNull确保tenantId不为空时才设置TenantContextHolder
2025-08-05 14:54:22 +08:00
PIG AI f01440dd9e Merge branch 'master' of https://git.pig4cloud.com/pig/pigx 2025-07-16 22:52:24 +08:00
PIG AI f6798c1d21 fix(db): 移除用户表的phone和username唯一约束 2025-07-16 22:50:22 +08:00
PIG AI 1ef50a6d5b fix(upms): 调整User SQL条件顺序避免逻辑删除不生效问题 2025-07-16 22:49:16 +08:00
pig666 79841ced60 Merge branch 'master' of pig666/pigx into master
# PIG 系统功能更新记录

## 最新更新 (8分钟前) - 6a4b25b3d2
### 🐛 修复:菜单权限查询优化
- **提交类型**: fix
- **模块**: SysMenuMapper
- **内容**: 为 `listMenusByRoleId` 方法添加 `@InterceptorIgnore` 注解
- **目的**: 忽略 tenantLine 拦截器,避免菜单权限查询时的多租户干扰
- **影响**: 修复了角色菜单权限查询在多租户环境下的异常问题

```java
@InterceptorIgnore(tenantLine = "true")
List<SysMenu> listMenusByRoleId(@Param("roleId") Long roleId);
```

---

## 18小时前更新 - e1f5bf6325
### ✨ 功能增强:用户查询多租户过滤
- **提交类型**: feat
- **模块**: tenant
- **内容**: 在 `listTenantUser` 方法中增加 tenantId 过滤条件
- **目的**: 确保用户查询严格按照租户隔离
- **影响**: 提升了多租户环境下用户数据的安全性和准确性

```java
public List<SysUser> listTenantUser(Long tenantId) {
    return baseMapper.selectList(
        Wrappers.<SysUser>lambdaQuery()
            .eq(SysUser::getTenantId, tenantId)
            .eq(SysUser::getDelFlag, CommonConstants.STATUS_NORMAL)
    );
}
```

---

## 1天前更新 - 7be922ef0f
### ✨ 重大功能:多租户手机号管理重构
- **提交类型**: feat
- **模块**: tenant
- **主要功能**:
  1. **手机号唯一性校验**: 在多租户环境下确保手机号的唯一性
  2. **密码重置接口重构**: 支持多租户场景下的密码重置
  3. **短信验证码接口优化**: 增强多租户支持

#### 具体改进内容:

##### 1. 手机号唯一性校验
```java
/**
 * 校验手机号在当前租户下的唯一性
 */
public boolean validatePhoneUnique(String phone, Long tenantId, Long userId) {
    LambdaQueryWrapper<SysUser> wrapper = Wrappers.<SysUser>lambdaQuery()
        .eq(SysUser::getPhone, phone)
        .eq(SysUser::getTenantId, tenantId)
        .eq(SysUser::getDelFlag, CommonConstants.STATUS_NORMAL);

    if (userId != null) {
        wrapper.ne(SysUser::getUserId, userId);
    }

    return baseMapper.selectCount(wrapper) == 0;
}
```

##### 2. 密码重置接口重构
```java
/**
 * 多租户环境下的密码重置
 */
public R<Boolean> resetPassword(String phone, String newPassword, Long tenantId) {
    SysUser user = baseMapper.selectOne(
        Wrappers.<SysUser>lambdaQuery()
            .eq(SysUser::getPhone, phone)
            .eq(SysUser::getTenantId, tenantId)
            .eq(SysUser::getDelFlag, CommonConstants.STATUS_NORMAL)
    );

    if (user == null) {
        return R.failed("用户不存在");
    }

    // 重置密码逻辑
    user.setPassword(passwordEncoder.encode(newPassword));
    return R.ok(updateById(user));
}
```

##### 3. 短信验证码接口优化
```java
/**
 * 发送短信验证码(支持多租户)
 */
public R<Boolean> sendSmsCode(String phone, Long tenantId, String type) {
    // 验证手机号是否存在于当前租户
    boolean exists = baseMapper.exists(
        Wrappers.<SysUser>lambdaQuery()
            .eq(SysUser::getPhone, phone)
            .eq(SysUser::getTenantId, tenantId)
            .eq(SysUser::getDelFlag, CommonConstants.STATUS_NORMAL)
    );

    if (!exists) {
        return R.failed("手机号不存在");
    }

    // 发送短信验证码逻辑
    return smsService
2025-07-16 11:57:55 +08:00
PIG AI f9e960ea1f Merge remote-tracking branch 'origin/master' 2025-07-16 11:48:41 +08:00
PIG AI 6a4b25b3d2 fix(SysMenuMapper): 为listMenusByRoleId方法添加InterceptorIgnore注解忽略tenantLine拦截 2025-07-16 11:48:35 +08:00
PIG AI e1f5bf6325 feat(tenant): 在listTenantUser方法中增加tenantId过滤条件 2025-07-15 17:03:45 +08:00
PIG AI 7be922ef0f feat(tenant): 新增手机号唯一性校验逻辑,重构密码重置和短信验证码接口支持多租户
- 优化部门校验使用isEmpty()方法
- 在SysMessageServiceImpl中为短信发送添加租户隔离支持
2025-07-15 10:06:45 +08:00
PIG AI 2b64a4cfe1 Merge branch 'dev' 2025-07-09 21:18:27 +08:00
PIG AI 8d81533751 fix(security): 增强OAuth2 token管理功能, 确保删除操作后清理残留的username关联键 2025-07-09 21:18:15 +08:00
PIG AI 72e575bbbe feat(codegen): 更新默认分支配置为next
- 将PigxCodeGenDefaultProperties的默认branch值从master改为next
- 保持与项目最新开发分支策略同步
2025-07-09 21:18:14 +08:00
PIG AI fea0028126 Merge branch 'master' into dev 2025-07-09 21:16:32 +08:00
PIG AI 9649b980e5 fix(security): 增强OAuth2 token管理功能, 确保删除操作后清理残留的username关联键 2025-07-09 21:16:13 +08:00
PIG AI 651ff2c74e feat(codegen): 更新默认分支配置为next
- 将PigxCodeGenDefaultProperties的默认branch值从master改为next
- 保持与项目最新开发分支策略同步
2025-07-09 17:55:12 +08:00
PIG AI 6bdbb17dd3 fix(upms): 修复多租户环境下用户查询功能
- 在getUserListByUserName方法中增加TenantBroker.noneAs包装
- 在getUserListByIds方法中增加TenantBroker.noneAs包装
- 确保跨租户查询时能正确获取用户数据
2025-07-08 22:55:34 +08:00
PIG AI c855344c3c fix(quartz): 修复任务状态查询条件错误问题 fix: #6220 Quartz查询BUG 页面任务状态查询无效
- 修正SysJobController中getSysJobPage方法的jobStatus查询条件
- 将误用的jobGroup参数改为正确的jobStatus参数
- 确保任务状态筛选功能正常工作
2025-07-08 15:09:08 +08:00
PIG AI 0c11c4ffa9 refactor(ProcessInstanceServiceImpl): 优化流程实例结束逻辑
- 使用LambdaUpdateChainWrapper重构流程实例结束状态更新逻辑
- 将Optional条件判断改为更简洁的ifPresent方式
- 提高代码可读性与维护性

refactor(TaskServiceImpl): 增强流程终止功能

- 在停止流程实例后自动更新流程记录状态
- 添加YJS状态标记和结束
2025-07-08 11:59:36 +08:00
PIG AI 31cae49a17 refactor(SysUserMapper): 优化用户查询方法命名和SQL逻辑
- 将selectVoListByScope重命名为getUserVoListByScope以保持命名一致性
- 优化SQL查询条件顺序,将tenant_id条件前置
- 在用户列表查询中增加phone模糊查询条件
- 调整tenant_id IS NULL条件位置以提高查询效率
2025-07-07 11:49:18 +08:00
PIG AI f7c1dc402a fix(SysUserMapper): 优化数据权限条件
- 在getUserVosPage和selectVoListByScope查询中增加dept_id字段返回
- 统一SQL条件判断的缩进格式
- 保持模糊查询和精确查询条件的一致性
2025-07-07 11:30:20 +08:00
PIG AI 887c9c32e3 refactor(xxl-job): 升级xxl-job-admin 3.1.1 2025-07-07 10:53:57 +08:00
PIG AI fdc704d564 refactor(xxl-job): 升级xxl-job-admin 3.1.1 2025-07-07 10:53:44 +08:00
PIG AI fdc3ba87da refactor(xxl-job): 升级xxl-job-admin 3.1.1 2025-07-07 10:53:38 +08:00
PIG AI 2fc40ac21a refactor(xxl-job): 升级xxl-job-admin 3.1.1 2025-07-07 10:53:26 +08:00
PIG AI c9124d11c6 refactor(pigx-register): 移除冗余的maven-compiler-plugin配置 2025-07-07 09:32:08 +08:00
PIG AI 769d49a0d5 refactor(nacos): 更新nacos版本并添加maven-compiler-plugin配置
- 将nacos依赖版本从3.0.0升级至3.0.2.OEM版本
- 新增maven-compiler-plugin插件并启用parameters配置
2025-07-06 23:06:02 +08:00
PIG AI 23a464bb7f refactor(user): 使用RedisUtils替代StringRedisTemplate进行重置验证码缓存操作 2025-07-06 14:48:20 +08:00
PIG AI cb7e7222c4 feat(db): 更新测试数据和租户有效期
- 将sys_tenant表的有效期延长至2099-12-31
- 更新sys_user和app_user的联系电话为17338122125
- 保持其他用户信息和密码hash不变
2025-07-06 14:05:18 +08:00
PIG AI f0b83406be feat(upms): 新增ByteArrayMultipartFile工具类实现内存型文件上传
- 实现基于byte[]的MultipartFile接口适配RemoteFileService
- 提供两种构造方式支持直接byte[]或InputStream输入
- 包含完整文件属性(name/originalFilename/contentType)处理方法
- 内置空文件检查和文件大小计算能力
2025-07-05 15:27:31 +08:00
PIG AI a3951a0368 refactor(excel): 替换alibaba-excel为fastexcel依赖
- 将alibaba-excel相关import更新为cn.idev.excel
- 更新pom.xml中依赖为fastexcel 1.2.0
- 修改Excel相关注解及工具类的包路径
2025-07-05 14:58:12 +08:00
PIG AI 88da029a7e refactor(app-pom):统一依赖版本管理,将pigx-app-server-api的硬编码版本号替换为动态project.version变量 2025-07-05 09:23:46 +08:00
PIG AI d32b1af5e4 refactor(auth): 统一代码格式与优化注释风格
- 规范多个类中的代码缩进与空行格式
- 删除冗余注释与不必要的空行
- 统一catch代码块的花括号换行风格
- 优化方法注释的简洁性与一致性
- 调整部分类成员变量的声明顺序
2025-07-05 09:12:00 +08:00
PIG AI dc0e814522 refactor: 统一代码格式,优化注释风格 2025-07-05 09:11:13 +08:00
PIG AI bcfeec31bc feat(tenant): 新增租户信息自动校验与更新功能
- 在SysTenantService中新增getOrUpdateTenant方法实现租户状态自动校验
- 用户登录后自动检查并更新过期租户信息至有效租户
- 重构租户删除逻辑至removeTenant方法并统一缓存清理
- 将用户租户更新接口迁移至SysTenantController
- 优化用户信息查询时自动触发租户校验逻辑
2025-07-05 09:06:08 +08:00
PIG AI c0e9ed69be feat(auth): 优化登录失败次数统计逻辑
- 使用RedisUtils.increment替代原生Redis命令实现递增操作
- 简化代码结构并提升可读性
2025-07-05 09:00:34 +08:00
PIG AI 2d7d089fcd feat(auth): 优化租户过期验证逻辑并统一Redis key格式
- 修改登录失败/成功处理中的Redis key格式,移除tenantKeyStrResolver依赖
- 简化RedisUtils.execute调用方式,移除冗余的RedisCallback类型声明
- 在SysTenantServiceImpl中增加租户状态和时间有效性过滤
- 重构TenantContextHolderFilter的租户验证逻辑,增加remoteTenantService备用查询
- 调整租户无效时的HTTP状态码为426并优化响应内容类型
2025-07-04 16:41:06 +08:00
PIG AI 00efa97eef feat(cache): 在RedisUtils中增加increment方法并优化验证码缓存服务
- 新增RedisUtils.increment方法用于原子递增操作
- 重构CaptchaCacheServiceProvider使用RedisUtils替代直接stringRedisTemplate调用
- 统一Redis缓存操作工具类方法调用方式
2025-07-04 12:24:28 +08:00
PIG AI bf1e58fb71 feat(auth): 增加租户上下文支持
- 在retrieveUser方法中为PigxUser类型设置TenantContextHolder
- 确保用户认证时自动携带租户ID信息
2025-07-04 12:07:17 +08:00
PIG AI 32c7aec93d fix(mybatis): 修复匿名用户处理逻辑返回null值问题
- 修改AnonymousAuthenticationToken情况下的返回值为null
- 优化authentication对象存在性检查逻辑
2025-07-04 12:07:15 +08:00
PIG AI 809b17da68 feat(file): 增强文件下载功能与实体定义
- 使用SysFile.Fields常量替代硬编码字符串字段名
- 增加文件不存在时的日志警告与提前返回处理
- 为SysFile实体添加FieldNameConstants注解与Serial标记
- 优化文件下载响应头设置与异常处理逻辑
2025-07-04 12:07:06 +08:00
PIG AI c8edf16536 feat(security): 重构Redis存储的OAuth2授权服务
- 将PigxRedisOAuth2AuthorizationService迁移至common-security模块
- 使用RedisTemplate替代RedisUtils进行缓存操作
- 增加Jackson序列化支持RouteDefinitionVo
- 优化token存储逻辑与过期时间处理
- 统一授权服务与路由管理的Redis配置
2025-07-04 12:07:00 +08:00
PIG AI d392f2f03a feat(deps): 升级jimu.version从1.8.1到2.0.0以使用新功能
- 替换TinyPinyin依赖为io.github.biezhi版本2.0.3.RELEASE
- 移除无法从中央仓库下载的com.github.promeg版本
2025-07-04 12:06:49 +08:00
PIG AI 0be39ba180 feat(upms): 增加用户表唯一约束并优化用户查询逻辑
- 在user表增加phone和username字段的UNIQUE KEY约束
- 修改SysUserController的details接口查询逻辑
- 通过TenantBroker.noneAs实现跨租户查询用户信息
2025-07-04 12:06:38 +08:00
PIG AI 6dfa937f34 feat(tenant): 新增用户租户关联关系API
- 在SysTenantController中新增addUserTenant接口用于处理用户租户关联
- 完善SysTenantServiceImpl中用户岗位关联逻辑的空值检查
- 新增用户租户关联DTO参数校验和权限控制
2025-07-04 12:05:37 +08:00
PIG AI 21130253a4 feat(tenant): 重构租户用户关系管理
- 新增sys_tenant_user表用于存储租户与用户的多对多关系
- 移除SysTenantServiceImpl中初始化用户的冗余逻辑
- 调整数据库初始化脚本以适配新的用户租户关系模型
2025-07-04 12:05:00 +08:00
PIG AI b1646437bc feat(tenant): 完善用户注册时tenantId的自动填充逻辑
- 在RegisterUserDTO中新增tenantId字段用于接收前端传入的租户ID
- 修改SysUserServiceImpl中用户注册逻辑,支持自动继承当前登录用户的tenantId
- 调整SysUserMapper.xml查询条件,允许查询未分配tenantId的用户
2025-07-04 12:04:57 +08:00
PIG AI 886471f96a refactor(db): update gen_template_group records with new group_id values
- Changed group_id from specific large values to simplified values (1 and 2) for better clarity and consistency in the gen_template_group table inserts.
2025-07-04 12:04:32 +08:00
PIG AI 2db74fc7d6 feat(tenant): 重构用户关联表结构以支持多租户
- 移除sys_user表中的dept_id字段
- 在sys_user_post和sys_user_role表中新增tenant_id字段
- 新增sys_user_dept表存储用户部门关系
- 更新测试数据以适配新的表结构
2025-07-04 12:04:27 +08:00
PIG AI c8a8da7497 feat(tenant): 新增租户用户管理功能
- 在SysUserPost实体类中添加tenantId字段
- 新增SysTenantUserDTO用于租户用户数据传输
- 在SysTenantController中新增用户租户管理接口
- 实现租户用户的增删改查及分页查询功能
- 优化ValidateCodeFilter中的验证码校验逻辑
- 修复PigxUserDetailsService中空部门列表处理问题
2025-07-04 12:01:27 +08:00
PIG AI db332055ae refactor(user): 优化用户部门关系处理逻辑
- 简化SysUserDept的插入操作,直接使用insert方法替代复杂条件判断
- 移除冗余的exists查询和lambda表达式包装逻辑
2025-07-04 12:01:19 +08:00
PIG AI d3770993ce refactor(user): update user information retrieval to use UserDTO and improve method documentation 2025-07-04 11:58:50 +08:00
PIG AI 3a53fb5677 feat(redis): 添加Redis工具类,优化RedisTemplate配置 2025-07-04 11:57:22 +08:00
PIG AI 5058c07bff refactor(auth): 优化OAuth2认证模块文档与token查询逻辑
- 重构OAuth2ResourceOwnerBaseAuthenticationProvider的JavaDoc为中文文档
- 优化token查询接口的分页处理逻辑
- 使用TenantContextHolder替代tenantKeyStrResolver获取租户信息
- 简化token列表查询直接从Redis key解析基础信息
2025-07-04 11:56:36 +08:00
PIG AI 7205251977 feat(upms): ❕ 增强多租户支持,支持在线切换租户
- 新增SysTenantUser实体类及Mapper用于租户用户关系管理
- 新增SysUserDept实体类及Mapper实现用户多部门支持
- 重构用户信息查询逻辑,支持跨租户查询
- 优化部门管理,支持多租户下的部门树查询
- 扩展UserInfo DTO增加deptId字段
- 重构Redis授权服务,优化租户信息存储结构

# Conflicts:
#	pigx-upms/pigx-upms-biz/src/main/java/com/pig4cloud/pigx/admin/controller/SysTenantController.java
#	pigx-upms/pigx-upms-biz/src/main/java/com/pig4cloud/pigx/admin/service/SysUserService.java
2025-07-04 11:56:14 +08:00
PIG AI 8227768849 refactor(flow-engine): 增强多租户支持
- 在EngineProcessInstanceController中增加tenantId过滤条件
- 在EngineFlowController中为部署和启动流程添加tenantId参数
- 优化流程查询时增加tenantId条件检查
- 统一使用TenantContextHolder获取当前租户信息
2025-07-04 11:50:22 +08:00
PIG AI a970fe166a refactor(stream): 替换Collectors.toList()为toList()方法
- 优化代码简洁性,使用Java 16引入的Stream.toList()替代Collectors.toList()
- 统一代码风格,减少冗余代码
- 提升代码可读性,简化stream操作
2025-07-04 11:50:17 +08:00
PIG AI e2e73dffda feat(register): 添加logback日志配置并设置nacos日志级别
- 新增logback-spring.xml配置文件用于日志管理
- 设置nacos相关日志级别为OFF以减少干扰
- 配置console和file两种日志输出方式
- 在PigxNacosApplication中指定日志配置文件路径
2025-06-25 17:10:59 +08:00
PIG AI f7edba9801 feat(deps): 升级pigx-common-idempotent模块的redisson版本至3.50.0 2025-06-25 11:35:56 +08:00
PIG AI 24a685bc54 feat(config): 更新application-dev和pigx-gateway-dev配置
- 修改application-dev.yml的jasypt加密配置和redis host配置
- 更新pigx-gateway-dev.yml的路由配置和management端点权限
- 为所有配置添加public tenant_id字段
2025-06-24 10:43:03 +08:00
PIG AI b49e8bf736 feat(config): 更新日志级别和版本配置
- 将logback-spring.xml中的root日志级别从debug调整为INFO级别
- 更新docker-compose.yml中的使用说明版本至V5.9并移除version字段
- 升级pigx-app-server-api模块的pom.xml版本至5.9.0
2025-06-24 09:28:43 +08:00
PIG AI 946ca2ef38 revert(app): 移除无用注解和字段并调整代码格式
- 移除AppPageEntity中的@FieldNameConstants注解
- 删除PageTypeEnums中的WORKBENCH枚举项
- 调整AppArticleCollectEntity字段缩进格式
- 简化AppRole中的roleDesc字段描述并移除menuId字段
2025-06-24 09:28:23 +08:00
PIG AI de7e1fb4df feat(pom): 升级项目版本及依赖版本
- 将项目版本从5.8.0升级至5.9.0
- 升级spring-boot版本至3.5.3
- 升级spring-boot-admin版本至3.5.0
- 更新所有子模块的parent版本号
2025-06-24 09:00:07 +08:00
PIG AI 607f7a13eb revert(app): 移除无用注解和字段并调整代码格式
- 移除AppPageEntity中的@FieldNameConstants注解
- 删除PageTypeEnums中的WORKBENCH枚举项
- 调整AppArticleCollectEntity字段缩进格式
- 简化AppRole中的roleDesc字段描述并移除menuId字段
2025-06-24 08:57:25 +08:00
PIG AI 7d422b91ab feat(deps): 更新依赖库版本
- 升级captcha组件版本至1.4.0
- 移除不再需要的jaxb依赖库
- 清理pom.xml中过时的依赖配置
2025-06-23 16:20:26 +08:00
PIG AI 5978f87268 feat(auth): 更新captcha依赖库
- 将滑块验证码依赖从spring-boot-starter-captcha替换为captcha-spring-boot-starter
- 使用pig-mesh维护的新版本captcha组件
2025-06-23 16:20:13 +08:00
PIG AI 1e9c1bd054 feat(boot-config): 禁用Spring Cloud服务发现功能
- 在application.yml中设置spring.cloud.discovery.enabled为false
- 保持与原有nacos配置一致的禁用状态
2025-06-23 16:19:59 +08:00
PIG AI f796c87342 feat(codegen): 更新代码生成模板至V2025001版本 2025-06-23 16:19:59 +08:00
PIG AI 679aebdbb7 feat(codegen): 更新代码生成模板至V2025001版本 2025-06-23 16:19:59 +08:00
PIG AI 52e5be9442 feat(codegen): 新增分支配置支持并更新默认配置前缀
- 修改PREFIX为pigx.codegen以增强配置项命名空间隔离性
- 新增branch字段用于指定代码生成模板仓库的分支
- 更新GenTemplateServiceImpl中模板文件获取逻辑以支持多分支
- 默认分支设置为master保持向后兼容性
2025-06-23 16:19:58 +08:00
PIG AI 78874c1646 refactor(pom): 适配 springboot 3.5 & spring cloud 2025 2025-06-23 16:19:50 +08:00
PIG AI fe9151c2f2 feat(db-config): 更新mybatis-plus的where策略配置
- 将select-strategy修改为where-strategy以优化SQL查询条件生成逻辑
- 保持其他mybatis-plus配置不变
2025-06-23 16:18:32 +08:00
PIG AI 9601609eb2 feat(sse): 优化SSE模块配置与文档
- 重命名messageDistributor为sseMessageDistributor以明确功能定位
- 为SseEmitterEndpoint添加详细方法注释说明
- 优化RedisMessageDistributorConfiguration类结构与文档
- 更新SseEmitterMessageSender类文档与日期信息
- 为MessageDistributorTypeConstants添加类说明文档
2025-06-23 16:18:14 +08:00
PIG AI 718a587c19 feat(tenant): 增强租户状态检查逻辑
- 新增对租户有效期的检查,包括startTime和endTime验证
- 优化无效租户的响应方式,返回401状态码和JSON格式错误信息
- 使用JSONUtil和ContentType处理错误响应输出
- 添加@SneakyThrows注解处理潜在异常
2025-06-23 16:18:09 +08:00
PIG AI 6c8e257a1e fix(auth/templates): 修复模板中request.contextPath的空指针问题
- 在confirm.ftl和login.ftl模板中增加request对象判空逻辑
- 优化OAuth2授权和登录表单的action路径安全性
2025-06-23 16:17:05 +08:00
PIG AI 880652f62c fix(file): 修复文件查询时未使用主库读取导致的数据不一致问题
- 在SysFileServiceImpl中为selectOne方法添加false参数强制使用主库查询
- 优化SysFileController中getFile方法的参数注释说明
2025-06-23 16:16:44 +08:00
PIG AI 155a303bec feat(sys-file): 支持自定义文件名上传功能
- 在文件上传接口中增加fileName参数以支持自定义文件名
- 当未提供fileName时保持原有UUID生成逻辑
- 同步修改相关controller和feign接口的签名
- 完善相关方法的JavaDoc注释
2025-06-23 16:16:44 +08:00
PIG AI 8d0eb9c8fb feat(mybatis): 修改匿名用户处理逻辑以返回用户名
- 移除未使用的SecurityUtils import
- 当用户为AnonymousAuthenticationToken时返回authentication.getName()
- 保持原有非匿名用户处理逻辑不变
2025-06-23 16:16:39 +08:00
PIG AI 00fb8ce48b feat(file): 新增内部文件上传接口
- 在RemoteFileService中新增innerUpload方法并添加NoToken注解
- 在SysFileController中新增innerUpload接口方法并标记为Inner
- 支持通过微服务内部调用上传文件功能
2025-06-23 16:16:12 +08:00
PIG AI 64cdd035e1 feat(app): 新增工作台菜单权限过滤功能
- 在AppIndexServiceImpl中实现基于角色权限的菜单过滤
- 新增WORKBENCH页面类型枚举
- 为AppRole添加menuId字段存储权限菜单
- 扩展AppRoleService提供菜单查询接口
- 优化AppArticleCollectEntity增加image和visit字段
2025-06-23 16:15:39 +08:00
PIG AI 404d7bf6c2 feat(SysLogServiceImpl): 增加按title模糊查询日志功能
- 在SysLogServiceImpl中新增对title字段的模糊查询条件
- 当title参数非空时自动添加like查询条件
2025-06-23 16:15:24 +08:00
PIG AI 2ad48fb751 fix(pom): 回退druid版本至1.2.23
- 将druid依赖版本从1.2.24降级至1.2.23
- 解决与当前系统其他组件的兼容性问题https://github.com/alibaba/druid/issues/6263
2025-06-23 16:15:20 +08:00
PIG AI 560129fc06 feat(security): 优化oauth2.0 的自省端点
- 在PigxRemoteRegisteredClientRepository中实现findById方法
- 优化PigxRedisOAuth2AuthorizationService的token处理逻辑
- 修复findByToken方法中tokenType为null时的默认值处理
- 添加根据username清理token的功能扩展
2025-06-23 16:15:17 +08:00
PIG AI bcd0f82bcc refactor(pigx-register): 简化Nacos启动配置并移除冗余代码
- 删除ConfigConstants.java文件,其配置已迁移至application.properties
- 移除Spring Boot Admin相关配置,简化监控设置
- 重构PigxNacosApplication启动类,精简初始化逻辑
- 将standalone模式配置移至main方法直接设置
- 优化部署类型处理流程,保持核心功能不变
2025-06-23 16:14:58 +08:00
PIG AI 1b560e486b feat(codegen): 修改GeneratorController下载文件名为固定值
- 将动态生成的zip文件名改为固定code.zip
- 简化下载文件名逻辑,统一输出格式
2025-06-23 16:14:49 +08:00
冷冷 0a661a3dc3 chore(nacos.properties): 更新配置文件,优化注释和设置 2025-06-23 16:14:29 +08:00
冷冷 f3738c4e11 docs(pom): 更新Hutool依赖版本至5.8.38 2025-06-23 16:14:28 +08:00
冷冷 c3f6e68770 feat(sys-file): 增加对历史URL参数格式的兼容处理
- 新增对/admin/sys-file/local?fileName=xxx.png格式的兼容支持
- 使用HttpUtil解析URL中的fileName参数
- 当URL参数存在时优先使用参数中的fileName值
2025-06-23 16:09:57 +08:00
冷冷 be30534c40 feat(SysFileServiceImpl): 优化文件获取方法的注释和参数说明
- 更新getFile方法的注释使其更清晰表达功能意图
- 移除未使用的bucket参数以简化方法签名
- 添加对fileName和response参数的详细说明
2025-06-23 16:09:54 +08:00
冷冷 6912730e94 feat(RemoteFileService): 新增文件上传功能
- 在RemoteFileService接口中添加upload方法用于文件上传
- 支持MultipartFile类型参数和MULTIPART_FORM_DATA媒体类型
- 返回R对象包含文件存储路径信息
2025-06-23 16:09:34 +08:00
冷冷 d8e56129bc feat(NACOS): 新增Nacos配置常量与环境初始化逻辑
- 在ConfigConstants中新增AUTH_ENABLED等三个配置常量
- 将standalone模式设置移至initEnv方法统一管理
- 新增initEnv方法集中配置认证开关与日志参数
- 更新docker-compose暴露9848和18080端口
- 优化代码注释与日期格式
2025-06-23 16:09:22 +08:00
冷冷 4779be6cfd feat(flow-engine): 优化审批任务处理逻辑并增强代码可读性
- 重构ApproveServiceTask类,提取拒绝处理逻辑到独立方法
- 增加详细注释说明关键变量和流程逻辑
- 优化变量命名以提高代码可读性
- 实现更清晰的审批条件判断流程
- 支持根据配置将拒绝流程重定向到特定节点或结束节点
2025-06-23 16:09:22 +08:00
冷冷 298d09586d feat(flow-engine): 增强流程结束功能并记录完成原因
- 新增ProcessInstanceParamDto中paramMap参数的传递
- 在ProcessInstanceRecord表中添加finish_reason字段
- 根据approve_condition自动设置流程结束原因
- 重构endProcess方法以支持参数传递
2025-06-23 16:09:21 +08:00
冷冷 2b1742470c docs(pig-register): 更新Nacos相关配置文档
- 中文优化application.properties中的配置项注释
- 中文明确标注已禁用的监控指标配置
- 中文补充认证插件相关配置说明
- 中文调整部署类型和模糊监听配置描述
2025-06-23 16:08:50 +08:00
冷冷 d87172db05 feat(register): 更新Nacos版本至3.0.0, 请注意端口是 18080 2025-06-23 16:07:11 +08:00
冷冷 19a223695f refactor(core): 重构WebPriorityHeader相关配置类并优化结构
- 将PriorityHeaderConfiguration重命名为PriorityHeaderInitBinder以明确用途
- 合并RestTemplate配置至新创建的WebCommonConfiguration类
- 在WebCommonConfiguration中统一管理Web相关Bean配置
- 添加ConditionalOnWebApplication条件注解确保Servlet环境
2025-06-23 16:06:54 +08:00
冷冷 37035cbf27 refactor(core): 重构WebPriorityHeader相关配置类并优化结构
- 将PriorityHeaderConfiguration重命名为PriorityHeaderInitBinder以明确用途
- 合并RestTemplate配置至新创建的WebCommonConfiguration类
- 在WebCommonConfiguration中统一管理Web相关Bean配置
- 添加ConditionalOnWebApplication条件注解确保Servlet环境
2025-06-23 16:06:54 +08:00
冷冷 bf8b8805c8 feat(pigx-common-bom): 升级MyBatis-Plus相关依赖版本
feat(pigx-codegen): 修改GenTableColumnEntity字段更新策略

- 升级MyBatis-Plus版本至3.5.12
- 升级MyBatis-Plus-Join版本至1.5.3
- 修改fieldDict字段的更新策略为ALWAYS
2025-06-23 16:06:21 +08:00
冷冷 d0f89b7917 feat(flow-engine): 完善ApprovalCreateListener代码注释 2025-06-23 16:06:17 +08:00
冷冷 6b48ccf74a feat(flow-engine): 增加流程事件监听器的代码注释
- 新增对节点开始/完成事件的详细处理逻辑
- 完善多实例任务完成事件的处理机制
- 增加变量创建/更新/删除事件日志记录
- 优化流程开始/终止事件的处理流程
- 增强任务分配/完成事件的通知机制
- 统一事件处理参数构建方式
2025-06-23 16:06:14 +08:00
冷冷 b3834e3215 feat(common-sensitive): 新增URL参数脱敏功能及枚举类型(ai-dev)
1. 在DesensitizedUtils工具类中新增url()方法,实现URL参数脱敏功能
2. 在SensitiveTypeEnum枚举中新增QUERY_PARAM类型,关联新增的脱敏方法
3. 方法会将URL参数值统一替换为***以保护敏感信息
2025-06-23 16:06:08 +08:00
冷冷 dc37974c72 chore(deps): 更新Spring Boot版本至3.4.5并移除废弃依赖项
- 升级Spring Boot版本从3.4.3到3.4.5
- 移除不再使用的spring-authorization.version属性
- 清理pigx-common-security模块中冗余的版本号配置
2025-06-23 16:06:08 +08:00
冷冷 f1231ec841 chore(deps): 更新 deepseek 依赖版本至 1.4.7 2025-06-23 16:05:35 +08:00
冷冷 7f9e6105f8 feat(core): 添加PriorityHeaderConfiguration解决请求头冲突问题 2025-06-23 16:05:22 +08:00
冷冷 1700648c2e feat(flow): 新增流程实例详情接口并优化代码格式
- 增加查询流程实例记录的远程接口
- 统一和优化部分代码缩进与注释描述
- 修正“查询挖矿任务”为“查询我的任务”中文注释
2025-06-23 16:05:06 +08:00
冷冷 a5abaa4d2c chore(deps): 更新 deepseek 依赖版本至 1.4.6 2025-06-23 16:04:46 +08:00
冷冷 e78eb14898 chore(docker): 移除JVM内存配置参数并优化安全随机数设置 2025-06-23 16:04:38 +08:00
冷冷 8edb1458a0 feat(mybatis): 支持Oracle和PostgreSQL数据库的SQL表名提取功能 2025-06-23 16:04:25 +08:00
冷冷 7db8f47e39 fix(persistence): update SQL Server version and simplify order by clause in SysUserMapper 2025-06-23 16:04:06 +08:00
冷冷 7f79e077d1 feat(codegen): 修改数据源表和列查询接口返回完整对象
- 将`queryTableList`和`queryTableColumn`返回值从字符串列表改为完整的`Table`和`Column`对象
- 移除`GenDsConfController`的`@Inner`注解限制
2025-06-23 16:03:49 +08:00
冷冷 c303196fe7 feat(pay): 在YungouosMergePayOrderHandler中新增BizParams参数支持
在YungouosMergePayOrderHandler的nativePay方法中,新增了BizParams参数支持,以增强支付功能的灵活性。
2025-06-23 16:03:29 +08:00
冷冷 0422a35562 chore(deps): 更新 pigx-pay-platform 中的 yungouos 依赖版本至 2.0.37 避免和SMS4J 版本冲突无法推送短信 2025-06-23 16:03:26 +08:00
冷冷 96011a3663 fix(app): 移除短信验证码返回中的冗余信息
在 `AppMobileServiceImpl` 中,短信验证码接口的返回值移除了多余的 `code` 参数,简化了响应结构。
2025-06-23 16:03:05 +08:00
luolin 9b4590ccbb ♻️ Refactoring code.命名规范防止冲突 2025-06-23 16:02:56 +08:00
冷冷 47a4421cb3 refactor(mp): 重构粉丝信息处理逻辑,提取保存粉丝方法到 WxAccountFansService
本次提交提取了粉丝信息的保存逻辑到 `WxAccountFansService` 中,优化了代码复用性。具体改动包括:
- 在 `WxAccountFansService` 中新增 `saveFans` 方法,用于统一处理粉丝信息的保存。
- 在 `MsgHandler`、`SubscribeHandler` 和 `LocationHandler` 中调用 `saveFans` 方法,减少重复代码。
- 修正了部分代码格式问题,提升代码可读性。

该重构未引入新功能,仅优化了代码结构,提升了代码的可维护性。
2025-06-23 16:01:23 +08:00
冷冷 29de9b5732 fix(quartz-config): 添加缺失的auto-startup和overwrite-existing-jobs配置
在`quartz-config.yml`中添加了`auto-startup`和`overwrite-existing-jobs`配置项,确保Quartz调度器的默认行为与预期一致。
2025-06-23 16:01:10 +08:00
冷冷 d0a5e0f66b chore(docker): 调整 JAVA_OPTS 内存配置并减少启动等待时间
- 将 `JAVA_OPTS` 中的 `-Xms` 和 `-Xmx` 分别调整为 `2048m` 和 `4096m`
- 将 `CMD` 中的 `sleep` 时间从 `60` 秒减少到 `30` 秒
2025-06-23 16:01:10 +08:00
PIG AI 01724e788a Merge remote-tracking branch 'open/master' into dev 2025-06-23 16:00:07 +08:00
pig666 6764a33d1d Merge branch 'dev' of 202405031425/pigx into dev 2025-04-02 17:15:02 +08:00
pig666 daafcd9eea Merge branch '微信jssdk' of 202405031425/pigx into dev 2025-04-02 17:14:18 +08:00
akhan cee6524ffb ✨ feat: 微信JSSDK配置 2025-04-02 14:30:00 +08:00
akhan bf410db2eb ✨ feat: 微信JSSDK配置 2025-04-02 14:20:54 +08:00
akhan 2abb4faacf ✨ feat: 微信JSSDK配置 2025-04-01 14:53:49 +08:00
akhan cba22d4066 ✨ feat: 登录页新增找回密码功能 2025-03-28 11:18:34 +08:00
冷冷 b55f7fbe91 fix(xxl-job-admin): 修复XxlJobInfoMapper.xml中trigger_status的条件更新逻辑
#6315 5.8版本 xxl-job运行一次后自动停止
2025-03-19 18:26:36 +08:00
冷冷 86a3340802 fix(xxl-job-admin): 修复XxlJobInfoMapper.xml中trigger_status的条件更新逻辑
#6315 5.8版本 xxl-job运行一次后自动停止
2025-03-19 18:24:16 +08:00
冷冷 69d0589222 feat(ai-chat): 添加 AI 聊天功能及相关 DTO 和控制器
- 新增 `AiChatMessageDTO` 用于处理 AI 聊天消息
- 新增 `AiChatController` 提供 AI 聊天接口,支持普通聊天和网络搜索模式
- 在 `pom.xml` 中添加大模型相关依赖
2025-03-12 12:08:05 +08:00
冷冷 c536348d52 feat(ai-chat): 添加 AI 聊天功能及相关 DTO 和控制器
- 新增 `AiChatMessageDTO` 用于处理 AI 聊天消息
- 新增 `AiChatController` 提供 AI 聊天接口,支持普通聊天和网络搜索模式
- 在 `pom.xml` 中添加大模型相关依赖
2025-03-12 12:05:58 +08:00
pig666 b08b69c29b Merge branch 'dev' of 171829182/pigx into dev 2025-03-11 21:44:23 +08:00
冷冷 4978ab23f6 chore(config): 优化 application.yml 文件中的配置格式并启用 openfeign.okhttp
- 简化 `nacos`、`sentinel` 配置项的格式
- 启用 `openfeign.okhttp` 功能
- 删除多余的换行符,提升可读性
2025-03-11 21:27:15 +08:00
曼陀罗 a825de905a refactor(mybatis-plus): 将 selectBatchIds 方法替换为 selectByIds
- 在多个模块中,将 baseMapper.selectBatchIds 替换为 baseMapper.selectByIds- 在多个模块中,将 removeByDsId 中的 deleteBatchIds 替换为 deleteByIds- 在多个模块中,将 list 方法中的 in 条件的参数从数组转换为列表
2025-03-11 17:59:33 +08:00
冷冷 5b5aac37d0 feat(core): 在 WebUtils 中添加 isMicro 方法用于检测微服务环境
新增 `isMicro` 方法,通过 `SpringContextHolder` 获取应用上下文并检查 `security.micro` 属性,默认返回 `true`。
2025-03-10 23:40:00 +08:00
冷冷 e7bea5e221 refactor(xxl-job): 优化任务注册中心的时间处理逻辑,在 XxlJobRegistryMapper.xml 中,简化 SQL 查询条件,直接使用 expiredTime 参数。 2025-03-10 18:58:46 +08:00
冷冷 186505deac chore(deps): 更新 pigx-common-bom 中的 javers 版本至 7.8.0
此次提交将 `javers` 依赖版本从 `7.3.3` 升级至 `7.8.0`,以保持依赖的最新状态并可能修复已知问题或引入新功能。
2025-03-10 14:59:21 +08:00
冷冷 9f7f4c4564 feat(oss): 添加 skipMd5Check 配置项以支持跳过 MD5 检查
#6272 使用腾讯云存储COS ,图片不能正常下载的问题, Invalid base 16 character: '"'
2025-03-10 14:12:29 +08:00
冷冷 aef21008d9 chore(deps): 更新 pigx-common-bom/pom.xml 添加 swagger-annotations 依赖
此次提交在 `pigx-common-bom/pom.xml` 中添加了 `swagger-annotations` 依赖,版本号为 `${swagger.core.version}`。该变更属于项目配置维护的一部分,旨在确保项目的依赖完整性。
2025-03-10 10:46:31 +08:00
冷冷 675d068018 chore(deps): 更新 sms4j 依赖的 groupId 为 org.dromara.sms4j
将 `sms4j` 相关的依赖从 `io.github.pig-mesh.sms4j` 更新为 `org.dromara.sms4j`,确保依赖的准确性和一致性。
2025-03-09 20:53:49 +08:00
冷冷 3a8116b5ea chore(pom): update version from 5.7.0 to 5.8.0 across multiple modules 2025-03-09 20:47:25 +08:00
冷冷 fd44cc6042 refactor(pay-channel): 重构支付渠道查询逻辑并增加敏感信息脱敏处理 2025-03-08 17:13:34 +08:00
冷冷 a328d1c90e feat(sensitive): 新增 JSON 格式数据脱敏功能
在 `DesensitizedUtils` 类中新增 `json` 方法,支持对 JSON 数据进行脱敏处理。该方法允许根据指定的字段进行模糊或精确匹配,并对匹配的字段值进行脱敏处理。
2025-03-08 17:12:46 +08:00
冷冷 4ea3b805fe feat(pay): 在 YungouosMergePayOrderHandler 中提取并传递 key 参数
从支付渠道配置中提取 `key` 参数,并将其传递给 `MergePay.nativePay` 方法,以支持更灵活的支付配置。
2025-03-08 16:19:32 +08:00
冷冷 d0e54a7013 doc(sql): 适配 nacos 2.5 SQL 脚本有调整,需要加字段 2025-03-08 16:17:17 +08:00
冷冷 8c0d8c0284 chore(nacos): update nacos version to 2.5.0 and add tomcat dependencies 2025-03-08 13:28:56 +08:00
冷冷 312720fada feat(flow-task): 新增序列号组件 (依赖于后端赋值) 2025-03-07 23:02:22 +08:00
冷冷 af90a5c906 fix(upms): 发送短信记录日志表的请求参数 2025-03-07 18:18:42 +08:00
冷冷 8bc5f95291 fix(upms): 用户导出报错,升级 MyBatisPlus 的缘故 2025-03-07 18:18:23 +08:00
冷冷 32b5ecf6ed refactor(app): 底部tabbar 支持优先级排序 2025-03-07 18:18:05 +08:00
冷冷 d474799fa7 feat(encrypt-api): 支持全局请求报文加密
BREAKING CHANGE: 文档和用法完全和之前不一样,不需要耦合代码
2025-03-07 18:18:02 +08:00
冷冷 ecc0c8ac93 fix(mp): 微信公众号支持配置单个主菜单 2025-03-07 18:17:59 +08:00
冷冷 6b5dbb86cb chore(codegen): #6238 配置达梦数据源后,下载文档失败 2025-03-07 18:16:13 +08:00
冷冷 dbd552a42c feat(quartz): 新增任务配置校验功能#6109 【需求】定时任务维护增强判断,直接查询 SpringBean class 判断入参是否合法 2025-03-07 18:16:06 +08:00
冷冷 deddae63d5 refactor(auth): 移除不必要的日志依赖,简化 TenantSavedRequestAwareAuthenticationSuccessHandler 类 2025-03-07 18:14:03 +08:00
冷冷 3e016ecc4f Revert "refactor(common-oss): S3文件上传简化去掉byteinputstream"
This reverts commit a7f85b5824de208f5b692cf62a8f7caa16fea4ea.
2025-03-07 18:12:36 +08:00
冷冷 7a97f94557 chore(deps): 添加 deepseek-spring-boot-starter 依赖并更新 pigx-common-bom/pom.xml
在 `pigx-common-bom/pom.xml` 中添加了 `deepseek-spring-boot-starter` 依赖,版本为 `1.4.5`,并新增了 `pigx-common-milvus` 依赖。这些变更为项目引入了新的功能模块,支持 AI 相关的功能扩展。
2025-03-07 18:12:32 +08:00
冷冷 518720d325 refactor(sse): 优化 SseEmitterEndpoint 确保在 onCompletion、onTimeout 和 onError 时清理 SseEmitter。
同时,将 `SecurityUtils.getUser().getId()` 提取为局部变量 `userId`,减少重复代码。

在 `SseEmitterHolder` 中,修改了 `removeSseEmitter` 方法的参数类型和实现,使其直接通过 `SseEmitter` 对象进行删除,提升代码可读性和维护性。

此外,移除了 `SseEmitterMessageSender` 中未使用的 `ReflectUtil` 导入,保持代码简洁。
2025-03-07 18:12:23 +08:00
冷冷 818b4370d2 feat(upms): 新增列出 Hook 业务代码功能
在 `SysMessageServiceImpl`、`SysMessageController` 和 `SysMessageService` 中新增 `listHookBizCode` 方法,用于根据 `MessageHookDTO` 查询并列出符合条件的业务代码。
2025-03-07 18:11:37 +08:00
冷冷 4ed963af5d chore(bom): update springdoc and swagger.core versions 2025-03-07 18:11:29 +08:00
冷冷 ee2453934d fix(report): 在SecurityRequestFilter中添加从cookie中获取token的逻辑
- 当请求头中不存在token时,尝试从cookie中获取token,增强安全性和兼容性。
2025-03-07 18:11:12 +08:00
冷冷 597123ae6d feat(auth): 修改查询token的接口路径为/token/query-token 2025-03-07 18:11:09 +08:00
冷冷 a233aa5b5a refactor(upms-api): 优化 SysRouteConf 实体类的字段填充逻辑
在 `SysRouteConf` 实体类中,为 `createBy`、`updateBy`、`createTime`、`updateTime` 和 `delFlag` 字段添加了 `@TableField` 注解,以自动填充
2025-03-07 18:08:35 +08:00
冷冷 db2f4ffa71 refactor(pay): 优化支持回调链接根据架构自动适配 2025-03-07 18:08:35 +08:00
冷冷 ecad480ec7 chore(deps): 更新 sms4j 依赖的 groupId 和版本号
将 `sms4j` 依赖的 `groupId` 从 `org.dromara.sms4j` 更新为 `io.github.pig-mesh.sms4j`,并将版本号从 `3.3.3` 升级到 `3.3.4`。
2025-02-25 18:10:29 +08:00
冷冷 a285a86571 chore(deps): 更新 mybatis-plus 依赖版本至 3.5.10.1 2025-02-23 22:18:45 +08:00
冷冷 990824343d chore(deps): 更新 spring-boot 版本至 3.4.3
此次提交将 `spring-boot` 的依赖版本从 `3.4.2` 升级至 `3.4.3`,以保持依赖的最新状态。
2025-02-23 22:12:51 +08:00
冷冷 c485de19f2 chore(deps): 更新 hutool 和 spring-authorization 依赖版本
将 `hutool` 从 `5.8.34` 升级到 `5.8.36`,并将 `spring-authorization` 从 `1.4.1` 升级到 `1.4.2`,以获取最新的功能和修复。
2025-02-19 11:57:08 +08:00
冷冷 8afdafbea4 refactor(auth): 将 requestCache 字段修改为 final,增强类的不可变性 2025-02-18 22:18:46 +08:00
冷冷 3a5d7a9eb9 refactor(auth): 移除不必要的日志依赖,简化 TenantSavedRequestAwareAuthenticationSuccessHandler 类 2025-02-18 22:18:22 +08:00
冷冷 7f8626e04f feat: 更新 PigxTokenEndpoint 和相关模板,优化授权流程和界面 2025-02-18 22:17:42 +08:00
冷冷 cfae5e1c05 feat: 删除PigxBootSecurityServerConfiguration文件并优化授权服务器配置(jdk17-dev)
删除`PigxBootSecurityServerConfiguration`文件,将相关配置迁移至`AuthorizationServerConfiguration`。
优化`AuthorizationServerConfiguration`中的授权服务器安全策略,移除不必要的条件注解`@ConditionalOnProperty`。
修复`FormIdentityLoginConfigurer`中的表单登录处理URL,确保与授权服务器配置一致。
2025-02-18 20:25:11 +08:00
冷冷 a00f4f81a4 chore(deps): 更新 Spring Security 配置并引入 Lazy 注解 (jdk17-dev)
在 `AuthorizationServerConfiguration` 中移除 `DelegatingAuthenticationConverter` 的重复导入,并调整其位置。在 `PigxResourceServerConfiguration` 中引入 `@Lazy` 注解优化依赖注入,同时将 `PrePostTemplateDefaults` 替换为 `AnnotationTemplateExpressionDefaults`。
2025-02-18 19:41:57 +08:00
冷冷 03c3b96275 chore(deps): 更新 Spring Boot 和 Spring Cloud 版本 (jdk17-dev)
将 Spring Boot 版本从 3.3.6 更新至 3.4.2,Spring Cloud 版本从 2023.0.4 更新至 2024.0.0。同时更新了 Spring Boot Admin 和 Spring Authorization 版本。
2025-02-18 19:23:39 +08:00
冷冷 803cf33d1e refactor(core): xxl-job-admin 3.0 2025-02-17 17:29:12 +08:00
冷冷 cb131319be feat(upms): 单体模式下不执行路由初始化 2025-02-17 15:35:50 +08:00
冷冷 3e7df4cc61 feat(core): Add utility method to convert boolean to YesNoEnum code 2025-02-17 15:35:50 +08:00
冷冷 84a5f75776 doc(sql): 删除单体版本 sys_role_menu 无用的SQL 数据 2025-02-08 15:17:12 +08:00
冷冷 67150af00a doc(sql): app sql 调整 2025-02-08 15:17:09 +08:00
冷冷 d8c9f64079 fix(core): login token user_id set string type 2025-02-08 15:17:06 +08:00
冷冷 552d6feaf9 feat(flow): 适配 form-design 表单设计器 2025-02-04 15:23:00 +08:00
冷冷 7dab2a5121 doc(SQL): 增加敏感词类型 sensitive_type 字典 2025-02-04 14:13:46 +08:00
冷冷 0777db3cd2 doc(SQL): 更新阿里巴巴素材库图标,统一现有图标数据 2025-02-04 14:07:26 +08:00
冷冷 a63d66f291 feat(flow): 适配 form-design 表单设计器 2025-02-04 10:19:26 +08:00
冷冷 11d2262b8c feat(flow): 适配 form-design 表单设计器 2025-02-04 10:15:30 +08:00
冷冷 bba2e67f23 fix(xxl-job-admin): 执行器管理 OnLine 列表为空 2025-02-04 10:12:38 +08:00
冷冷 5332ee8ce3 refactor(common-datasource): 重构动态数据源,同支持 YAML + JDBC ,兼容Druid 标准配置 2025-02-04 10:12:34 +08:00
冷冷 08f9b493e0 refactor(common-oss): S3文件上传简化去掉byteinputstream 2025-02-04 10:11:56 +08:00
冷冷 ab86bce01c fix(flow): 获取部门主管的时候,提示用户凭证已过期
Closes #6183
2025-01-22 15:10:22 +08:00
冷冷 59c8d2a672 refactor(app): 底部tabbar 支持优先级排序 2025-01-16 11:18:02 +08:00
冷冷 7b1e95f5ff refactor(APP): APP 装修配置优化 2025-01-16 11:17:17 +08:00
冷冷 17a081edb8 upgrade(codegen): anyline 20250109 版本
fix Oracle 读取表的问题
2025-01-13 15:50:48 +08:00
冷冷 63318ae288 Merge branch 'jdk17' into jdk17-dev 2024-12-25 15:15:59 +08:00
冷冷 f6a8ba8c0e doc(no): 删除工单模板,无实际意义 2024-12-25 12:01:36 +08:00
冷冷 cc0f1cda67 feat(data): 支持通过参数跳过数据权限
用法:
DataScope dataScope = new DataScope();
dataScope.setSkip(true);
baseMapper.selectPageByScope(page, wrapper, dataScope);
2024-12-25 09:36:18 +08:00
冷冷 31f41db931 fix(upms): register user can not set roleId
特别重要的更新,涉及安全问题
2024-12-23 15:04:27 +08:00
冷冷 d249355f05 refactor(sentinel): 避免 sentinel 健康检查 强制检测 server 2024-12-16 14:19:56 +08:00
冷冷 75549547b5 refactor(社交登录): 前后端使用统一枚举,避免重复代码 2024-12-05 22:58:22 +08:00
冷冷 9415d82c28 🔖 V5.7.0 2024-12-05 12:23:43 +08:00
冷冷 a55f6d0bfb refactor(idempotent): 重构幂等切面,用原子性操作替换双检锁 2024-12-04 14:22:26 +08:00
冷冷 754d6428c4 upgrade(spring-cloud-alibaba): 2023.0.3.2 2024-12-03 10:30:33 +08:00
冷冷 a013b5196a refactor(security): 异常信息使用 messages_zh_CN.properties 国际化文件处理 2024-12-01 15:04:50 +08:00
冷冷 0a8586ef1e refactor(flowable): 审批节点增加任务转办按钮 2024-12-01 15:02:29 +08:00
冷冷 2999ed8e3a refactor(flowable): 审批节点增加任务转办按钮 2024-12-01 15:01:56 +08:00
冷冷 4f8a78661b upgrade(spring cloud): 2023.0.4 2024-11-29 09:37:03 +08:00
冷冷 8baef653f1 upgrade(all): 5.7.0-SNAPSHOT 2024-11-27 22:04:25 +08:00
冷冷 e77e2c5a4a refactor(security): 增加 satoken 通用配置属性 2024-11-27 20:11:57 +08:00
冷冷 bc305ca84a revert(codegen): 删除 sas oauth2 依赖,避免 satoken 单体 401 2024-11-27 20:10:33 +08:00
冷冷 062034a3a3 upgrade(jimu): 1.8.1 ,避免 CVE 2024-11-26 21:14:35 +08:00
冷冷 536be6fb15 refactor(data): 数据权限查询角色优化 2024-11-26 14:14:27 +08:00
冷冷 0d798c328f refactor(data): 数据权限查询角色优化 2024-11-26 14:06:11 +08:00
冷冷 9cf022c717 upgrade(all): core version upgrade 2024-11-25 09:59:14 +08:00
冷冷 2608b831ff fix(admin): 创建租户时默认的创建的租户角色
Closes #6071
2024-11-25 09:49:50 +08:00
冷冷 f3a03c1afa Merge remote-tracking branch 'gitee/jdk17-dev' into jdk17-dev 2024-11-24 18:06:03 +08:00
冷冷 3b7a66652a fix(log): 操作日志上面的统计图时间轴乱序
Closes #6004
2024-11-24 18:05:51 +08:00
冷冷 64e17420ef refactor(login): 优化短信发送日志级别&小程序登录异常判断 2024-11-24 18:05:00 +08:00
冷冷 eec245d4ad refactor(core): 优化默认查询SQL输出,quartz、工作流的SQL 不输出 2024-11-24 18:04:50 +08:00
冷冷 10e5234e34 refactor(core): 适配 mybatis-plus 3.5.9 2024-11-24 18:04:22 +08:00
冷冷 d9ed794fc3 refactor(app): 优化APP 模块登录用户名不匹配的日志 2024-11-24 17:43:30 +08:00
冷冷 4ff88571c7 doc(sequence): 维护相关驱动包依赖说明注释 2024-11-24 17:42:24 +08:00
冷冷 8d0faea641 fix(security): check-token token相关接口错误时返回不正确的json
Closes #5998
2024-11-24 17:42:14 +08:00
冷冷 c617a8b7e2 fix(log): 操作日志上面的统计图时间轴乱序
Closes #6004
2024-11-24 17:41:40 +08:00
冷冷 4c8ae51957 refactor(login): 优化短信发送日志级别&小程序登录异常判断 2024-11-24 17:41:29 +08:00
冷冷 2d999e325b refactor(flow): rename flow api feign api 2024-11-24 17:41:29 +08:00
冷冷 5d3eba85c4 refactor(flow): 优化flow api 方便业务侧无token 发起流程 2024-11-24 17:40:55 +08:00
冷冷 b62b13fdaf refactor(flow): 优化flow api 方便业务侧无token 发起流程 2024-11-24 17:40:17 +08:00
冷冷 bb1a78e859 upgrade(sas): 1.3.3. 2024-11-24 17:39:53 +08:00
冷冷 fb10c25c6f refactor(core): 适配 mybatis-plus 3.5.9 2024-11-24 17:39:10 +08:00
冷冷 f2384b2b73 upgrade(core): mybatis-plus、druid、 mybatis-plus-join、hutool
- 升级 mybatis-plus 至 3.5.9(原版本为 3.5.8)
- 升级 mybatis-plus-join 至 1.5.2(原版本为 1.4.13)
- 升级 druid 至 1.2.23

BREAKING CHANGE: mybatos-plus 3.5.9 让人头疼,不如叫他 3.6.0 很多不兼容性的内容,注意注意!!!
2024-11-24 17:39:10 +08:00
冷冷 f763512a6c refactor(core): 优化默认查询SQL输出,quartz、工作流的SQL 不输出 2024-11-24 17:38:55 +08:00
冷冷 61d08708b9 upgrade(xxl-job): 2.4.2 2024-11-24 17:38:40 +08:00
冷冷 52827cdbf9 upgrade(xxl-job): 2.4.2 2024-11-24 17:38:39 +08:00
冷冷 61121eb507 refactor(core): 调整 request.getParameterMap()等使用,兼容东方通等容器 2024-11-24 17:38:31 +08:00
冷冷 0d9461d036 refactor(report): 适配达梦 hibernate 6.1 & mybatis-plus 3.5.9 2024-11-24 17:38:18 +08:00
冷冷 6ca76a3016 upgrade(nacos): nacos 2.4.3 2024-11-24 17:38:11 +08:00
冷冷 0243e59041 feat(pay): 修改退款成功状态回调逻辑
- 更新 TradeStatusEnum.java:
  修改第22行,新增 TRADE_CLOSED 状态,关联 REFUND_SUCCESS。

- 更新 AlipayPayNotifyCallbackHandler.java:
  修改第123行,完善退款成功状态判断逻辑,
  如果 trade_status=TRADE_CLOSED 则设置订单状态为 REFUND_SUCCESS,
  否则设置为 TRADE_SUCCESS。

- 更新前端文件 src/views/biz/pay/order/index.vue:
  在第256行新增退款成功状态(label: '退款成功', value: '5'),
  以支持退款成功状态在前端的显示。
2024-11-24 17:38:09 +08:00
冷冷 9dd236e068 refactor(xxl): 重构代码 mapper.xml 支持达梦数据库 2024-11-22 11:35:39 +08:00
冷冷 075cda636a refactor(data): 业务代码里的规则,覆盖计算规则 2024-11-22 10:38:15 +08:00
冷冷 02dea27959 refactor(data): 支持多角色数据权限计算 2024-11-21 23:10:28 +08:00
冷冷 fddf156651 refactor(data): 支持多角色数据权限计算 2024-11-21 23:10:13 +08:00
pig666 59ebbb65de Merge branch 'jdk17-dev' of 673315837/pigx into jdk17-dev 2024-11-06 13:26:21 +08:00
673315837 3f82770353 CaptchaCacheServiceProvider添加接口的increment实现 2024-11-06 12:46:01 +08:00
冷冷 a99abf52a6 refactor(app): app-biz/pom.xml 增加默认的profile cloud 2024-09-13 11:06:06 +08:00
luolin 1e79c85b17 ♻️ Refactoring code.解决数据库存空串的情况 2024-09-10 23:00:13 +08:00
冷冷 e7e31200f2 fix(tenant): #5911 5.6 租户管理 套餐变更清理指定租户的菜单缓存 2024-09-10 23:00:10 +08:00
冷冷 a48e51eda9 fix(app): 导航栏编辑SQL报错 2024-09-08 16:34:03 +08:00
冷冷 4fbc5e6c14 doc(数据库): 字典表增加 【敏感词类型】 2024-09-04 17:18:05 +08:00
冷冷 0d8cde1e13 refactor(core): TenantContextHolderFilter 清空TTL 避免内存泄漏
Closes 5896
2024-09-03 16:23:50 +08:00
冷冷 fd6875763b refactor(websocket): 更换成ConcurrentWebSocketSessionDecorator非阻塞式的sendMessage发送 2024-09-03 11:31:17 +08:00
冷冷 2071195f7d fix(common-sensitive): 默认权限字符串修改为 no_mask 2024-09-01 14:13:43 +08:00
冷冷 9dc190df59 Merge branch 'jdk17-dev' of https://git.pig4cloud.com/pig/pigx into jdk17-dev 2024-08-28 17:40:29 +08:00
冷冷 17a7351e31 fix(app): 【紧急紧急】 APP登录序列化错误导致登录失败 2024-08-28 17:39:49 +08:00
pig666 eac1c8beaf Merge branch 'jdk17-dev' of 2422024617/pigx into jdk17-dev
~
2024-08-28 15:05:11 +08:00
X.Yang 5e5e36d1d4 fix(sql): 修复菜单配置错误导致文档扩展无法使用问题
- 文档扩展菜单 Path 由 http://pigx-gateway:9999/admin/doc.html 变更为 http://pigx-gateway:9999/doc.html
2024-08-28 11:34:02 +08:00
冷冷 350414563c Merge branch 'jdk17' into jdk17-dev 2024-08-27 13:14:34 +08:00
冷冷 43fed57a86 fix(代码生成): 数据库表、字段缓存元数据不更新
(cherry picked from commit 9a6751301d43b7314a32b0d3d5eb16e3020867bf)
2024-08-27 13:09:47 +08:00
冷冷 b87a0839e0 upgrade(version): 5.6.0 2024-08-26 23:48:40 +08:00
冷冷 89dd047167 upgrade(version): 5.6.0 2024-08-26 23:45:03 +08:00
冷冷 f4e0455376 refactor(common-job): 执行器access-token 字段属性变更,保持和官方配置一致 2024-08-23 11:54:13 +08:00
冷冷 62d0271af5 upgrade(core): spring boot 3.3.3 2024-08-23 11:27:43 +08:00
冷冷 d72fade7b0 refactor(sensitive): 增加 common-sensitive 2024-08-22 15:10:28 +08:00
冷冷 0e8858a338 Merge branch 'jdk17' of https://git.pig4cloud.com/pig/pigx into jdk17 2024-08-22 12:47:50 +08:00
冷冷 b5a33cbdd0 Merge branch 'refs/heads/jdk17-dev' into jdk17 2024-08-22 12:46:54 +08:00
冷冷 b560859f20 refactor(代码生成): 默认情况下不自动同步路由 2024-08-22 12:38:12 +08:00
冷冷 bc0debdbf2 refactor(sql): 增加 sys_route_manage 、 no_mask 权限按钮 2024-08-22 12:37:52 +08:00
冷冷 2e6a5831b3 fix(app): 修改app页面设置无法多租户无法使用问题 2024-08-21 15:32:17 +08:00
aeizzz f548079d23 fix(app): 修改app页面设置无法多租户无法使用问题 2024-08-21 15:32:17 +08:00
aeizzz b14c52403c feat(upms): 修正菜单获取更新为异步方式 2024-08-21 15:32:17 +08:00
aeizzz ee0e34eab3 feat(upms): 修正菜单获取更新为异步方式 2024-08-21 15:32:17 +08:00
冷冷 6671a4abf9 refactor(缓存): redistemplate / spring cache 使用 Json 序列化
sas 默认的缓存没有修改
2024-08-21 14:39:19 +08:00
冷冷 26f1f69a56 refactor(文件下载): 返回原始文件名,方便浏览器识别保存
注意文件名的header 字段需要使用 URLEncoder 避免错误
2024-08-21 13:40:27 +08:00
冷冷 e167095932 Merge remote-tracking branch 'origin/jdk17' into jdk17 2024-08-19 13:57:47 +08:00
冷冷 2a5e07f2d7 doc(sql): 增加敏感词菜单I18N 2024-08-19 13:56:17 +08:00
冷冷 80a335e93c feat(日志管理): 增加 Jackson json 日志脱敏工具类,如果日志入库中有敏感字段则进行删除 2024-08-18 23:51:36 +08:00
冷冷 f6e5aebfac feat(日志管理): 增加 Jackson json 日志脱敏工具类,如果日志入库中有敏感字段则进行删除 2024-08-18 23:43:44 +08:00
李世永 a2a9bf529f fix:#5728 第三方账号绑定后前端还是显示未绑定 2024-08-17 22:40:58 +08:00
冷冷 686c0c770f refactor(file): S3无需判断运行环境,均使用/作为路径分隔符
Closes 5845
2024-08-17 14:41:08 +08:00
冷冷 1a1e2be00f Merge branch 'jdk17-dev' of https://git.pig4cloud.com/pig/pigx into jdk17-dev 2024-08-17 14:38:48 +08:00
pig666 604a124ff6 Merge branch 'jdk17-dev' of 202211112327/pigx into jdk17-dev 2024-08-17 14:37:55 +08:00
liukuan f1aa2ff390 在编写代码或配置文件路径时,请确保使用正斜杠/来指定S3路径。即使你在Windows环境中使用S3客户端,也应该使用正斜杠/而不是反斜杠\。这是因为S3不支持反斜杠作为路径分隔符。 2024-08-17 13:42:45 +08:00
冷冷 ed6af29f8a upgrade(bom): up aviatorscript 5.4.3 2024-08-17 13:25:49 +08:00
冷冷 75bfcbdaca upgrade(excel): up easyexcel 4.0.2 2024-08-17 13:20:02 +08:00
冷冷 c01498f8d2 upgrade(common): hutool 5.3.1 , spring-boot-admin 3.3.3 2024-08-17 12:27:54 +08:00
冷冷 bb5e9cb555 upgrade(snapshot): 5.6.0-SNAPSHOT 2024-08-16 22:05:47 +08:00
冷冷 98205b3ead upgrade(nacos): nacos 2.4.1 2024-08-16 21:22:29 +08:00
冷冷 5c724900e3 refactor(代码生成): 适配anyline 2024-08-16 15:57:55 +08:00
冷冷 3c659c86bd refactor(common): security 增加配置项,如果设置 skipPublicUrl true 如果接口对外设置,即使携带token 也不鉴权 2024-08-16 15:28:22 +08:00
冷冷 d6fd5ad960 fix(flow): 代办任务根据流程名称查询失效 2024-08-16 15:28:19 +08:00
冷冷 d723fac0e2 upgrade(代码生成): 升级anyline 0808
听人劝后续固定使用版本,能用别动这个依赖版本
2024-08-16 15:28:17 +08:00
冷冷 5827c163c2 feat(租户管理): 状态过期,强制退出对应租户所有操作 2024-08-16 15:28:13 +08:00
冷冷 d5daf6b27d refactor(代码生成): anyline 切换数据库适配器不变,导致读取的数据库信息错误 2024-08-16 15:28:10 +08:00
冷冷 f2921c2102 fix(security): 安全问题,数字验证码增加参数校验避免伪造绕过 2024-08-16 15:28:04 +08:00
冷冷 4118d91756 refactor(codegen): 代码生成表格列表根据表的元数据(createTime/updateTime)进行排序,最新有更新的表放在最前 2024-08-16 15:27:55 +08:00
冷冷 f3ab8396bc upgrade(codegen): 达梦驱动升级至 8.1.3.140 2024-08-16 15:27:55 +08:00
冷冷 6f7c83feb8 refactor(代码生成): 支持根据表名和注释进行模糊查询
(cherry picked from commit 4e1f0afdba6fe12d7171b348687198272b834ac4)
2024-08-16 15:27:40 +08:00
冷冷 0e6be2eccc upgrade(bom): dynamic-datasource 4.3.1
(cherry picked from commit a3611fa8af3d0742af7607ca5f250a8adade5b28)
2024-08-16 15:27:28 +08:00
冷冷 95644e9b9a refactor(all): @PreAuthorize 使用 @HasPermisson 注解替换
(cherry picked from commit 19b5ec57ad000e6a3ae767626ae8deaad28c901f)
2024-08-16 15:27:23 +08:00
冷冷 4747aa1098 feat(core security): 适配 spring security 6.3 新增 @HasPermisson 注解
使用 @HasPermisson  替换 @PreAuthority(xxxx),简化接口上的注解

(cherry picked from commit 448e77607fec651d18bde97e3d5cc6734342e51a)
2024-08-16 15:27:20 +08:00
冷冷 1359415965 upgrade(core bom): springboot 3.3.2 &spring cloud 2023.0.3
- springboot 3.3.2
- spring cloud 2023.0.3
- spring cloud alibaba 2023.0.1.2
- spring boot admin 3.3.2
- hutool 5.8.29

(cherry picked from commit ba8fc7e8d3cfc15725db50e161e8db17d267df89)
2024-08-16 15:27:16 +08:00
冷冷 ad0c7b87b1 upgrade(core bom): springboot 3.3.2 &spring cloud 2023.0.3
- springboot 3.3.2
- spring cloud 2023.0.3
- spring cloud alibaba 2023.0.1.2
- spring boot admin 3.3.2
- hutool 5.8.29

(cherry picked from commit 58d41b40b36bc810b3c0ae56b39cf17bf328aeb0)
2024-08-16 15:27:16 +08:00
冷冷 1bf9ba0db6 refactor(SQL): 新增sys_system_config 表
原有的 站内信管理修改信息推送

(cherry picked from commit 6800f0a91029fec0deae730f41196b65af524072)
2024-08-16 15:27:10 +08:00
冷冷 ec0703d45d feat(upms): 新增短信、邮件、hook 发送和API 工具
(cherry picked from commit 9f61bc82799fb97e85237d2951cd1ebce8673328)
2024-08-16 15:27:08 +08:00
冷冷 7750314ac6 refactor(common-core): 新增通用配置 common-config , 简化 application配置
大部分情况下 common-config 一旦确定后续不修改,所以不需要写在 application 做一个简化

(cherry picked from commit 872fa03dce8e25f663e918c06e759ad49460c74e)
2024-08-16 15:26:56 +08:00
冷冷 c9d8c6a421 refactor(common-core): 新增通用配置 common-config , 简化 application配置
大部分情况下 common-config 一旦确定后续不修改,所以不需要写在 application 做一个简化

(cherry picked from commit 56f4b2fb915f3552e83ed4760772b13942ebd4d6)
2024-08-16 15:26:53 +08:00
冷冷 2ece806760 ♻️ Refactoring code. GroupVo.java --> GroupVO
(cherry picked from commit e5e6e35a5a2e21f5eabd6021bf10099ed6730cce)
2024-08-16 15:20:03 +08:00
冷冷 51a20ad898 ♻️ [工作流] 代办任务列表查询修改查询用户ID列表和去掉查询任务参数
(cherry picked from commit 84e0116e9bce2725dcd20274c4faf1872f7c86fe)
2024-08-16 15:19:32 +08:00
冷冷 a616bcc2de ♻️ [系统管理] RemoteUserService 增加 list 查询接口
(cherry picked from commit f56af224109f27bcf66a25c4f24f3c6ad3048d8c)
2024-08-16 15:19:23 +08:00
冷冷 4b2d55f339 ✨ #5779 【需求】审批部门负责人,自动根据发起人关联,不需要手动选择
(cherry picked from commit cc9e157f387cf183ecd6ca2d11a7d901a20f8bed)
2024-08-16 15:19:14 +08:00
冷冷 f8630da5af ♻️ 【工作流】 多人任务前端显示头像信息去重
(cherry picked from commit 81da50fbedb48a96e8a19250e8adf2170e50a4e9)
2024-08-16 15:19:08 +08:00
冷冷 97348c9e83 ⬆️ springboot 3.2.7
(cherry picked from commit c8e135ad46c224adb724d3346df2de7d4b2e2869)
2024-08-16 15:18:59 +08:00
冷冷 6d56f5e213 ✨ #5595 【需求】协同管理工作流支持流程节点执行回调
(cherry picked from commit b8de059c6f3e042b7fd1e91177ed36ba1e141f44)
2024-08-16 15:18:54 +08:00
冷冷 e9b77a8e09 ♻️ Refactoring code. 敏感词策略调整不验证数字
(cherry picked from commit e156735d7d6bb42e97b214ddcd3436314c2e5ab9)
2024-08-16 15:18:49 +08:00
冷冷 c2d4c438c4 🐳 Dockerfile 增加expose 9848 方便k8s自动发现端口
(cherry picked from commit 57bc59d97c514d073941e14956f686278396228e)
2024-08-16 15:18:41 +08:00
冷冷 1b822862bf ✨ Introducing new features. 【系统管理】敏感词维护管理
(cherry picked from commit 7be72d3fcb8a611e1a1bc6f7510c0a498d23aa97)
2024-08-16 15:18:35 +08:00
冷冷 20ef46292f ✨ Introducing new features. 文件上传入库文件hash值
(cherry picked from commit fc4778b5a75501283465f450ea49aade357bef9a)
2024-08-16 15:18:29 +08:00
冷冷 9a3c2ddf3f 🔧配置管理模块 增加应用模块名称
(cherry picked from commit e40db4813fce9951742caef99d69aa00bd36102f)
2024-08-16 15:18:20 +08:00
冷冷 e94b2f1d63 ✨ Introducing new features. 【系统管理】敏感词维护管理
(cherry picked from commit 85fbc6de0d50a9dc8869ed54c55155583fdc0709)
2024-08-16 15:18:11 +08:00
冷冷 08376e2cfe 🔧 【通用配置】 lombok.config 支持构造器配置属性自动复制
(cherry picked from commit af659449b08825460f9e8187c755217554533807)
2024-08-16 15:18:07 +08:00
冷冷 aedd2fe4c7 🐳 【docker-compose】基础redis 镜像修改为国内源
(cherry picked from commit b8f2a87afd253755c076d831905132a9fc84120c)
2024-08-16 15:17:35 +08:00
冷冷 03b3ecac55 ✨ Introducing new features. 文件上传入库文件hash值
(cherry picked from commit 37178bcadff8aa29b50e43fb1b24063457f893ec)
2024-08-16 15:17:30 +08:00
冷冷 ba15cf45cc 🔒重构bearer token 抽取过程,带token 就鉴权,即使是暴露的端点
(cherry picked from commit ffafe70bef3777664cc87edd1c58436763930ca3)
2024-08-16 15:17:26 +08:00
冷冷 cdac9cab16 ✨ 增加mybatis-plus乐观锁插件
(cherry picked from commit b3ab378edaa27685ca1f8f02f0b46ed84f1c1729)
2024-08-16 15:17:17 +08:00
冷冷 f650c2c743 🔒 对外输出严禁输出敏感字段 password
(cherry picked from commit 302553bbeb28016e5a11976461d73f8a6a3bd370)
2024-08-16 15:16:35 +08:00
冷冷 8c202a1938 ♻️ 代码生成数据源URL 长度调整为 text 类型存储
(cherry picked from commit bb34a81264055b9a46eae7481f7aba46a7f52de2)
2024-08-16 15:16:32 +08:00
冷冷 e96eaa2179 ✨ 新增 pigx-common-sensitive 脱敏模块
(cherry picked from commit 39899b1e8ff25ca1ac3708086c1ddb677fb56541)
2024-08-16 15:16:26 +08:00
冷冷 aba51bbdb8 ♻️ 增加 NoToken 注解方便对应 无token feign调用场景
(cherry picked from commit 2d78533a29c9c392f75d76cf202ae1daf8f7c77b)
2024-08-16 15:16:20 +08:00
冷冷 835d582b3b ✨ 支持根据角色动态脱敏指定数据属性
(cherry picked from commit 51541692ba7ee9ea5cf68f054f33c52133ca1a71)
2024-08-16 15:16:06 +08:00
冷冷 69aa10d54e ♻️重构 SysTenantServiceImpl 租户默认参数获取方式
(cherry picked from commit 612acdcca78bd5053f19ee9d784e1e9beb6ec9d2)
2024-08-16 15:15:55 +08:00
冷冷 148a2f54da ⬆️ git-commit-id-plugin 定制 git.properties 插件输出
(cherry picked from commit 031b12cc3f3d2d2b170c2bcc9fb3853576bcfe2e)
2024-08-16 15:15:35 +08:00
冷冷 a9b9475fa3 feat(日志管理): 增加 Jackson json 日志脱敏工具类,如果日志入库中有敏感字段则进行删除
(cherry picked from commit a7a5b33c1270e99b01a65307926e98f27c9da3fb)
2024-08-16 15:11:45 +08:00
冷冷 c80178148a feat(代码生成): 支持直接同步菜单、同步网关路由
(cherry picked from commit d61b38419bc70139e40ea6e5e5fe494c66eaaee2)
2024-08-16 15:11:28 +08:00
冷冷 04af734d83 refactor(common-idempotent): 幂等插件重构@Idempotent默认值
默认执行完后删除key

修改默认错误信息格式

(cherry picked from commit 62d2087eb002d6ac5163dd6d569b35ee72b765f0)
2024-08-16 15:11:17 +08:00
冷冷 2a1a7880f0 refactor(路由管理): 增加接口后端鉴权避免安全问题
(cherry picked from commit 82bba90dba8278759da799320aa341e11b0253a2)
2024-08-16 15:10:36 +08:00
冷冷 5d75b8294f feat(代码生成): 支持模板通过github 动态更新检查
(cherry picked from commit e449f424e2dec78c61a2e3a5984f06230b91fca8)
2024-08-16 15:09:58 +08:00
冷冷 9e5cbd4fb5 refactor(代码生成): 删除 config.json 配置,默认属性从配置文件中获取
json -> YAML

(cherry picked from commit 021e7435e294c874d1032d38411db17051ae75c5)
2024-08-16 15:09:45 +08:00
冷冷 860a3f72f5 refactor(代码生成): up anyline 8.7.2-jdk17-20240715
(cherry picked from commit 8f733f21c2b913b5be2154164d2b347a590415b2)
2024-08-16 15:09:32 +08:00
冷冷 c647864b9b refactor(代码生成): 优化代码下载的路径默认为 admin , up screw 0.0.6
(cherry picked from commit 582bbcabbea1e84ef4b33c78c0e8f54897106299)
2024-08-16 15:09:16 +08:00
冷冷 310b16ba7b refactor(菜单管理): 菜单名称重复导致菜单404
新增菜单名称去重

Closes #5753

(cherry picked from commit dc5895869f054d310f99093da6fa668a8a506f9c)
2024-08-16 15:08:48 +08:00
冷冷 abb033f560 refactor(代码生成): 默认的模块名为:admin
config.json 配置文件的默认模块名修改为 admin

(cherry picked from commit 520ee19fcd45d29e9a38b197417532d870de4531)
2024-08-16 15:08:28 +08:00
冷冷 2c77c3db7f style(行政区划): 新增去重判断 ,新增获取详细数据的接口
前端支持 validateExist 方法判断

(cherry picked from commit 557832d1dd69f362d41ef77a0b9c6320700758f8)
2024-08-16 15:07:51 +08:00
冷冷 2da674478e ✨[代码] 代码生成支持通过 git 动态更新 2024-07-13 17:38:46 +08:00
冷冷 69d54efdd4 ♻️ 代码生成支持动态添加字典 2024-07-13 17:37:58 +08:00
冷冷 7052b21a63 ♻️ Refactoring code. GroupVo.java --> GroupVO 2024-07-13 17:37:21 +08:00
冷冷 2e06c03e57 ♻️ 代码生成后端API调整
(cherry picked from commit a3b8798eb39537a32f89371a949a0a80b37110b9)
2024-06-20 16:52:53 +08:00
冷冷 b4db53891d 🐛 数据源模糊查询失败
(cherry picked from commit 818e19b102e21c4f60d15bedd6a4d48b3711851d)
2024-06-20 16:52:34 +08:00
冷冷 63032e672f ♻️ 支付模块 敏感参数脱敏
(cherry picked from commit 5cb7743455edf386161e17e3d409d5f3e6cc936e)
2024-06-20 16:51:42 +08:00
冷冷 1a10197b48 🐛 部门负责人编码和代码查询规则不一样
(cherry picked from commit 8d2417ad4578832caaa94bb2377b896fc6134b46)
2024-06-20 16:51:39 +08:00
冷冷 9fa8b13b6e 🐛 修复 GenDsConfController 下载数据源文档时no such field 错误 2024-06-13 22:44:19 +08:00
冷冷 68e97384e6 ⬆️ screw 0.0.4 增加连接池缓存 2024-06-13 17:24:38 +08:00
冷冷 50bf7c6ba0 ⬆️ screw 0.0.4 增加连接池缓存 2024-06-13 17:24:35 +08:00
冷冷 282c998b41 🔧 quartz-config.yml 默认关闭集群模式和扫描 2024-06-13 17:24:33 +08:00
冷冷 aa01420e46 ⬆️ mybatis-plus 3.5.7. hutool 5.8.28 mybatis-plus-join 1.4.13 2024-06-13 17:24:29 +08:00
冷冷 e61d526512 🔧 单体模式配置 sentinel 关闭 2024-06-12 15:37:04 +08:00
冷冷 d9e0c8cf34 🐛 #5731 任务管理,流程管理,表单设计中,拖拽文件,文件属性设置不生效,文件后缀MP4,rar等格式,文件大小,发布后不生效。 2024-06-12 15:36:17 +08:00
冷冷 04e65b00f7 🔧 修改quartz 线程池数量 2024-06-11 14:15:00 +08:00
冷冷 3e448f1093 ♻️基于 anyline 重构代码生成模块,更便捷的接入其他类型数据库 2024-06-10 15:53:18 +08:00
冷冷 8e32d61f58 ♻️基于 anyline 重构发号器模块,更便捷的接入其他类型数据库 2024-06-10 15:53:01 +08:00
冷冷 fdd7b72f2a 🐳 dockerfile base mirror use aliyun proxy 2024-06-10 15:52:38 +08:00
pig666 9843bd949d Merge branch 'jdk17-dev' of 202310181001/pigx into jdk17-dev 2024-06-10 15:41:06 +08:00
jackshenonly 22666e1ffa [fix]:去掉SSE发送器中过时的代码,以免导致异常 【because "sendFailed" is null】 2024-06-07 14:51:02 +08:00
jackshenonly 2d1f8cd6db 删除Sse Redis 分发器中的冗余代码 2024-06-06 10:03:43 +08:00
冷冷 45fc19a5b2 ✨ 调整日程管理相关的字段名称 适配 Oracle数据库 2024-05-31 14:54:08 +08:00
冷冷 3061a6ec6d ♻️ 优化省市区街道四级查询 2024-05-31 14:54:06 +08:00
冷冷 852be70ab9 🗃️ 重构部分字段SQL 适配Oracle 数据库 2024-05-30 14:54:03 +08:00
1720 changed files with 79412 additions and 75354 deletions

No files matched your search

+66
View File
@@ -0,0 +1,66 @@
version: 2
updates:
- package-ecosystem: maven
directory: /
schedule:
interval: weekly
day: monday
time: "09:00"
timezone: Asia/Shanghai
open-pull-requests-limit: 5
# 默认只自动处理 Maven patch 升级;LangChain4j 小版本升级也交给 Dependabot 自动建 PR。
allow:
- dependency-name: "*"
update-types:
- version-update:semver-patch
- dependency-name: "dev.langchain4j:*"
update-types:
- version-update:semver-minor
ignore:
# 完全忽略 IJPay 的所有升级。
- dependency-name: "com.github.javen205:IJPay-*"
# 完全忽略 MyBatis-Plus BOM 的所有升级。
- dependency-name: "com.baomidou:mybatis-plus-bom"
# 完全忽略 MyBatis-Plus-Join 的所有升级。
- dependency-name: "com.github.yulichang:mybatis-plus-join-*"
# major 升级涉及迁移风险,仍保留人工评估。
- dependency-name: "*"
update-types:
- version-update:semver-major
commit-message:
prefix: chore(deps)
groups:
# LangChain4j 单独分组,避免与普通 Maven patch 升级混在一个 PR。
langchain4j:
patterns:
- "dev.langchain4j:*"
update-types:
- patch
- minor
maven-dependencies:
patterns:
- "*"
exclude-patterns:
- "dev.langchain4j:*"
update-types:
- patch
- package-ecosystem: github-actions
directory: /
schedule:
interval: weekly
day: monday
time: "09:30"
timezone: Asia/Shanghai
open-pull-requests-limit: 3
ignore:
- dependency-name: "*"
update-types:
- version-update:semver-minor
- version-update:semver-major
commit-message:
prefix: ci(deps)
groups:
github-actions:
patterns:
- "*"
+74
View File
@@ -0,0 +1,74 @@
name: CI
on:
workflow_dispatch:
push:
pull_request:
permissions:
contents: read
jobs:
maven-build:
name: Maven build (Java ${{ matrix.java-version }})
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
java-version: ['17', '25']
steps:
- name: Checkout
uses: actions/checkout@v5
- name: Set up JDK ${{ matrix.java-version }}
uses: actions/setup-java@v5
with:
distribution: temurin
java-version: ${{ matrix.java-version }}
cache: maven
- name: Add JDK 25 annotation processor profile
if: matrix.java-version == '25'
run: |
python - <<'PY'
from pathlib import Path
pom = Path('pom.xml')
content = pom.read_text()
profile = '''\
<profile>
<id>jdk25-annotation-processor</id>
<activation>
<jdk>[25,)</jdk>
</activation>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<annotationProcessorPaths>
<path>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</path>
</annotationProcessorPaths>
</configuration>
</plugin>
</plugins>
</build>
</profile>
'''
marker = ' </profiles>'
if marker not in content:
raise SystemExit('Cannot find root pom.xml profiles section.')
if 'jdk25-annotation-processor' not in content:
content = content.replace(marker, profile + marker, 1)
pom.write_text(content)
PY
- name: Build with Maven
run: mvn -B -ntp clean install
+9
View File
@@ -58,6 +58,15 @@ Servers
.metadata
upload
gen_code
application-preview.yml
### node ###
node_modules
### claude code ###
.claude
docs
### test
aitest
.vectorex
-5
View File
@@ -1,5 +0,0 @@
# 构造器注入的时候自动复制字段上边的注解
lombok.copyableAnnotations += org.springframework.beans.factory.annotation.Value
lombok.copyableannotations += org.springframework.beans.factory.annotation.Qualifier
lombok.copyableannotations += org.springframework.context.annotation.Lazy
+63
View File
@@ -0,0 +1,63 @@
# Repository Guidelines
## Project Structure & Module Organization
pigx aggregates Spring Cloud services through the root `pom.xml`. Runtime services sit under dedicated folders:
`pigx-register` (service discovery/Nacos), `pigx-gateway` (edge routing), `pigx-auth` (OAuth2), `pigx-upms` (user &
permission), `pigx-flow` (workflow), `pigx-app-server`, and `pigx-visual` (monitoring plus
schedulers). Shared libraries and DTOs live in `pigx-common`. Sample SQL and Docker build contexts reside in `db/`,
while infra manifests live in `docker-compose.yml`. Every module uses the standard `src/main/java` and `src/test/java`
layout.
## Build, Test, and Development Commands
Focused Maven commands are allowed only for test execution. They must not be used to package, start, or restart
services.
## Testing Guidelines
Use `spring-boot-starter-test` (JUnit 5, AssertJ, Mockito) for unit and slice tests. Name classes `*Tests.java` and
colocate fixtures in `src/test/resources`. Target >70% line coverage on the service layer that guards authentication,
gateway filters, and approval flows. Before opening a PR, run the focused tests required by the change, then perform
the required runtime validation. Do not use `mvn verify` as a build shortcut unless the user explicitly requests it.
## Commit & Pull Request Guidelines
Follow the repo’s `type(scope): summary` history, e.g. `fix(upms): clear login failure cache` or
`feat(ai-voice): add speech transcription`. Each PR must describe the impact area, list affected modules, and reference
internal tickets or issues. Attach curl/Postman snippets or screenshots whenever UI or OpenAPI responses change. Rebase
on `ai-dev`, avoid committing generated artifacts, and call out schema/config updates explicitly.
## Security & Configuration Tips
Never commit environment secrets; rely on `docker-compose.yml` plus `.env` overrides ignored by Git. Keep `db/` seed
data sanitized, and drive end-to-end checks against `pigx-register` (ports 8848/9848) with `pigx-gateway` (9999) so
discovery behavior matches production.
## Behavioral Guidelines
The following four rules apply to all tasks and take precedence over other default behaviors.
### 1. Think Before Coding
- When requirements are ambiguous, ask first — never make silent assumptions
- If a simpler solution exists, say so explicitly rather than quietly picking a direction
- When something is unclear, surface the confusion instead of pushing forward with guesswork
### 2. Prefer Simplicity
- Use the minimum code needed to solve the current problem; add nothing unrequested
- Do not introduce abstractions for one-off code or design for hypothetical future needs
- Ask yourself: would a senior engineer call this over-engineered?
### 3. Surgical Changes
- Only touch what the task requires; do not refactor adjacent code as a side effect
- Do not alter style or structure unrelated to the current task
- Every changed line must trace directly to a stated requirement
### 4. Goal-Driven Execution
- Convert vague instructions into verifiable goals — prefer tests as the success criterion
- "Fix a bug" → write a failing test that reproduces it, then make it pass
- "Add validation" → write tests covering invalid inputs, then make them pass
+1 -1
View File
@@ -1,4 +1,4 @@
Copyright (c) 2018-2025, lengleng All rights reserved.
Copyright (c) 2018-2026, lengleng All rights reserved.
协议和授权
pigX并非一个开源软件,作者保留全部的权利。
+1 -1
View File
@@ -5,7 +5,7 @@ pigX 并非一个开源软件,作者保留全部的权利。
## 商业使用
- [商用请购买商业授权](https://pig4cloud.com)
- [使用对应的专属版本](https://pigx.vip/#/buy/form3)
- [使用对应的专属版本](https://pig4cloud.com/data/other/form3.html)
### 🚫禁止
+1316 -827
View File
File diff suppressed because it is too large. Load diff
+700 -467
View File
File diff suppressed because it is too large. Load diff
+158 -22
View File
@@ -1,8 +1,28 @@
-- 本文件仅用于初始化,不用于升级已有数据库。
USE pigxx_flow;
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
CREATE TABLE `bpm_oa_leave` (
`id` BIGINT NOT NULL COMMENT '主键',
`process_instance_id` VARCHAR(64) DEFAULT NULL COMMENT '流程实例编号',
`username` VARCHAR(255) NOT NULL COMMENT '申请人',
`leave_type` SMALLINT NOT NULL COMMENT '请假类型',
`leave_reason` VARCHAR(255) DEFAULT NULL COMMENT '请假原因',
`start_time` DATETIME(6) NOT NULL COMMENT '开始时间',
`end_time` DATETIME(6) NOT NULL COMMENT '结束时间',
`leave_day` SMALLINT NOT NULL COMMENT '请假天数',
`leave_status` SMALLINT DEFAULT NULL COMMENT '请假结果',
`create_by` VARCHAR(64) DEFAULT '' COMMENT '创建者',
`create_time` DATETIME(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) COMMENT '创建时间',
`update_by` VARCHAR(64) DEFAULT '' COMMENT '更新者',
`update_time` DATETIME(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6) COMMENT '更新时间',
`del_flag` CHAR(1) NOT NULL DEFAULT '0' COMMENT '是否删除',
`tenant_id` BIGINT NOT NULL DEFAULT 0 COMMENT '租户编号',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='请假申请表';
-- ----------------------------
-- Table structure for process
-- ----------------------------
@@ -17,20 +37,22 @@ CREATE TABLE `process` (
`logo` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '图标配置',
`settings` json DEFAULT NULL COMMENT '设置项',
`group_id` bigint NOT NULL COMMENT '分组ID',
`form_config` json NOT NULL COMMENT '表单设置信息',
`form_items` json NOT NULL COMMENT '表单设置内容',
`process` json NOT NULL COMMENT '流程设置内容',
`remark` varchar(125) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '备注',
`sort` int NOT NULL,
`is_hidden` tinyint(1) NOT NULL COMMENT '0 正常 1=隐藏',
`is_stop` tinyint(1) NOT NULL COMMENT '0 正常 1=停用 ',
`is_hidden` char(1) NOT NULL COMMENT '0 正常 1=隐藏',
`is_stop` char(1) NOT NULL COMMENT '0 正常 1=停用 ',
`admin_id` bigint DEFAULT NULL COMMENT '流程管理员',
`unique_id` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '唯一性id',
`admin_list` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '管理员',
`range_show` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '范围描述显示',
`print_template` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '打印模板',
`tenant_id` bigint(20) NOT NULL DEFAULT '0' COMMENT '所属租户id',
PRIMARY KEY (`id`) USING BTREE,
UNIQUE KEY `idx_form_id` (`flow_id`) USING BTREE,
KEY `idx_id` (`id`) USING BTREE
KEY `process_idx_id` (`id`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=182 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='流程定义数据';
@@ -41,8 +63,8 @@ DROP TABLE IF EXISTS `process_copy`;
CREATE TABLE `process_copy` (
`id` bigint NOT NULL COMMENT '用户id',
`del_flag` char(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT '0' COMMENT '删除标志',
`create_time` datetime NOT NULL COMMENT '创建时间',
`update_time` datetime NOT NULL COMMENT '更新时间',
`create_time` datetime COMMENT '创建时间',
`update_time` datetime COMMENT '更新时间',
`start_time` datetime NOT NULL COMMENT ' 流程发起时间',
`node_time` datetime NOT NULL COMMENT '当前节点时间',
`start_user_id` bigint NOT NULL COMMENT '发起人',
@@ -57,7 +79,7 @@ CREATE TABLE `process_copy` (
`user_id` bigint NOT NULL COMMENT '抄送人id',
`tenant_id` bigint(20) NOT NULL DEFAULT '0' COMMENT '所属租户id',
PRIMARY KEY (`id`) USING BTREE,
KEY `idx_id` (`id`) USING BTREE
KEY `copy_idx_id` (`id`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=74 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='流程抄送数据';
@@ -74,7 +96,7 @@ CREATE TABLE `process_group` (
`sort` int NOT NULL DEFAULT '0' COMMENT '排序',
`tenant_id` bigint(20) NOT NULL DEFAULT '0' COMMENT '所属租户id',
PRIMARY KEY (`id`) USING BTREE,
KEY `idx_id` (`id`) USING BTREE
KEY `group_idx_id` (`id`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=20 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='流程分组';
@@ -97,12 +119,13 @@ CREATE TABLE `process_instance_record` (
`group_id` bigint DEFAULT NULL COMMENT '组id',
`group_name` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '组名称',
`status` int DEFAULT '1' COMMENT '状态',
`finish_reason` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '结束原因',
`end_time` datetime DEFAULT NULL COMMENT '结束时间',
`parent_process_instance_id` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '上级流程实例id',
`tenant_id` bigint(20) NOT NULL DEFAULT '0' COMMENT '所属租户id',
PRIMARY KEY (`id`) USING BTREE,
KEY `idx_id` (`id`) USING BTREE,
KEY `idx_dep_id` (`user_id`) USING BTREE
KEY `record_idx_id` (`id`) USING BTREE,
KEY `record_idx_dep_id` (`user_id`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=366 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC COMMENT='流程记录';
@@ -113,14 +136,16 @@ DROP TABLE IF EXISTS `process_node_data`;
CREATE TABLE `process_node_data` (
`id` bigint NOT NULL COMMENT '用户id',
`del_flag` char(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT '0' COMMENT '删除标志',
`create_time` datetime NOT NULL COMMENT '创建时间',
`update_time` datetime NOT NULL COMMENT '更新时间',
`create_time` datetime COMMENT '创建时间',
`update_time` datetime COMMENT '更新时间',
`process_definition_id` varchar(64) DEFAULT NULL COMMENT '引擎流程定义ID,发布版本快照',
`flow_id` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '流程id',
`data` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '表单数据',
`node_id` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
`tenant_id` bigint(20) NOT NULL DEFAULT '0' COMMENT '所属租户id',
PRIMARY KEY (`id`) USING BTREE,
KEY `idx_id` (`id`) USING BTREE
UNIQUE KEY `uk_node_definition` (`tenant_id`,`process_definition_id`,`node_id`),
KEY `data_idx_id` (`id`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=1195 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC COMMENT='流程节点数据';
@@ -131,8 +156,8 @@ DROP TABLE IF EXISTS `process_node_record`;
CREATE TABLE `process_node_record` (
`id` bigint NOT NULL COMMENT '用户id',
`del_flag` char(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT '0' COMMENT '删除标志',
`create_time` datetime NOT NULL COMMENT '创建时间',
`update_time` datetime NOT NULL COMMENT '更新时间',
`create_time` datetime COMMENT '创建时间',
`update_time` datetime COMMENT '更新时间',
`flow_id` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '流程id',
`process_instance_id` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '流程实例id',
`data` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci COMMENT '表单数据',
@@ -145,7 +170,7 @@ CREATE TABLE `process_node_record` (
`execution_id` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '执行id',
`tenant_id` bigint(20) NOT NULL DEFAULT '0' COMMENT '所属租户id',
PRIMARY KEY (`id`) USING BTREE,
KEY `idx_id` (`id`) USING BTREE
KEY `node_idx_id` (`id`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=1435 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC COMMENT='流程节点记录';
@@ -156,13 +181,13 @@ DROP TABLE IF EXISTS `process_node_record_assign_user`;
CREATE TABLE `process_node_record_assign_user` (
`id` bigint NOT NULL COMMENT '用户id',
`del_flag` char(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT '0' COMMENT '删除标志',
`create_time` datetime NOT NULL COMMENT '创建时间',
`update_time` datetime NOT NULL COMMENT '更新时间',
`create_time` datetime COMMENT '创建时间',
`update_time` datetime COMMENT '更新时间',
`flow_id` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '流程id',
`process_instance_id` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '流程实例id',
`data` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci COMMENT '表单数据',
`node_id` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
`user_id` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT ' 用户id',
`user_id` bigint NOT NULL COMMENT ' 用户id',
`status` int NOT NULL COMMENT '节点状态',
`start_time` datetime NOT NULL COMMENT '开始时间',
`end_time` datetime DEFAULT NULL COMMENT '结束时间',
@@ -172,11 +197,55 @@ CREATE TABLE `process_node_record_assign_user` (
`node_name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT ' 节点名称',
`task_type` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '任务类型',
`local_data` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci COMMENT '表单本地数据',
`node_record_id` bigint NOT NULL COMMENT '本轮节点执行记录id',
`assignment_origin` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT 'ORIGINAL' COMMENT '分配来源 ORIGINAL/ADD_SIGN',
`initial_user_id` bigint NOT NULL COMMENT '本份待办最初分配用户id',
`add_sign_record_id` bigint DEFAULT NULL COMMENT '动态加签批次记录id',
`tenant_id` bigint(20) NOT NULL DEFAULT '0' COMMENT '所属租户id',
PRIMARY KEY (`id`) USING BTREE,
KEY `idx_id` (`id`) USING BTREE
UNIQUE KEY `uk_node_record_user` (`tenant_id`,`node_record_id`,`user_id`) USING BTREE,
KEY `user_idx_id` (`id`) USING BTREE,
KEY `idx_add_sign_record_id` (`add_sign_record_id`) USING BTREE,
KEY `idx_assign_tenant_instance_del` (`tenant_id`,`process_instance_id`,`del_flag`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=597 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC COMMENT='流程节点记录-执行人';
-- Flowable 列表查询索引:act_* 表由引擎初始化,不在本脚本中创建。
-- 首次启动完成后,在业务库手动执行以下 SQL 一次;已有同名索引时不要重复执行。
-- 待办:按审批人筛选、创建时间排序。
-- ALTER TABLE `act_ru_task`
-- ADD INDEX `idx_task_assignee_create` (`ASSIGNEE_`, `CREATE_TIME_`),
-- ALGORITHM=INPLACE, LOCK=NONE;
-- 已办:按审批人及结束时间查询、统计。
-- ALTER TABLE `act_hi_actinst`
-- ADD INDEX `idx_act_assignee_end` (`ASSIGNEE_`, `END_TIME_`),
-- ALGORITHM=INPLACE, LOCK=NONE;
-- ----------------------------
-- Table structure for process_task_add_sign_record
-- ----------------------------
DROP TABLE IF EXISTS `process_task_add_sign_record`;
CREATE TABLE `process_task_add_sign_record` (
`id` bigint NOT NULL COMMENT '主键id',
`del_flag` char(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT '0' COMMENT '删除标志',
`create_time` datetime COMMENT '创建时间',
`update_time` datetime COMMENT '更新时间',
`flow_id` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '流程id',
`process_instance_id` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '流程实例id',
`node_record_id` bigint NOT NULL COMMENT '本轮节点执行记录id',
`node_id` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '节点id',
`source_task_id` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '发起加签的任务id',
`added_by_user_id` bigint NOT NULL COMMENT '加签发起人id',
`reason` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '加签原因',
`target_user_ids` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '本批次目标用户快照',
`participant_user_ids_before` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '操作前参与人快照',
`participant_user_ids_after` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '操作后参与人快照',
`tenant_id` bigint(20) NOT NULL DEFAULT '0' COMMENT '所属租户id',
PRIMARY KEY (`id`) USING BTREE,
KEY `idx_add_sign_node_record` (`tenant_id`,`node_record_id`) USING BTREE,
KEY `idx_add_sign_process_instance` (`tenant_id`,`process_instance_id`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC COMMENT='流程动态加签批次记录';
-- ----------------------------
-- Table structure for process_starter
@@ -185,14 +254,81 @@ DROP TABLE IF EXISTS `process_starter`;
CREATE TABLE `process_starter` (
`id` bigint NOT NULL COMMENT '用户id',
`del_flag` char(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT '0' COMMENT '删除标志',
`create_time` datetime NOT NULL COMMENT '创建时间',
`update_time` datetime NOT NULL COMMENT '更新时间',
`create_time` datetime COMMENT '创建时间',
`update_time` datetime COMMENT '更新时间',
`type_id` bigint NOT NULL COMMENT '用户id或者部门id',
`type` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT ' 类型 user dept',
`process_id` bigint NOT NULL COMMENT '流程id',
`tenant_id` bigint(20) NOT NULL DEFAULT '0' COMMENT '所属租户id',
PRIMARY KEY (`id`) USING BTREE,
KEY `idx_id` (`id`) USING BTREE
KEY `starter_idx_id` (`id`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=217 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='流程发起人';
-- ----------------------------
-- Table structure for bmp_oa_leave
-- ----------------------------
DROP TABLE IF EXISTS `bmp_oa_leave`;
CREATE TABLE `bmp_oa_leave` (
`id` bigint NOT NULL COMMENT '请假表单主键',
`username` varchar(255) COLLATE utf8mb4_general_ci NOT NULL COMMENT '申请人',
`leave_type` int NOT NULL COMMENT '请假类型',
`leave_reason` varchar(255) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '请假原因',
`start_time` datetime NOT NULL COMMENT '开始时间',
`end_time` datetime NOT NULL COMMENT '结束时间',
`leave_day` int NOT NULL COMMENT '请假天数',
`leave_status` int DEFAULT NULL COMMENT '请假结果',
`process_instance_id` varchar(64) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '流程实例的编号',
`create_by` varchar(64) COLLATE utf8mb4_general_ci DEFAULT '' COMMENT '创建者',
`create_time` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) COMMENT '创建时间',
`update_by` varchar(64) COLLATE utf8mb4_general_ci DEFAULT '' COMMENT '更新者',
`update_time` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6) COMMENT '更新时间',
`del_flag` char(1) COLLATE utf8mb4_general_ci NOT NULL DEFAULT '0' COMMENT '是否删除',
`tenant_id` bigint NOT NULL DEFAULT '0' COMMENT '租户编号',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='请假表单';
-- ----------------------------
-- Table structure for flow_draft
-- ----------------------------
DROP TABLE IF EXISTS `flow_draft`;
CREATE TABLE `flow_draft` (
`id` varchar(36) COLLATE utf8mb4_general_ci NOT NULL COMMENT '草稿ID',
`tenant_id` bigint NOT NULL COMMENT '所属租户ID',
`user_id` bigint NOT NULL COMMENT '草稿所属用户ID',
`kind` varchar(16) COLLATE utf8mb4_general_ci NOT NULL COMMENT '草稿类型:DESIGN 流程设计,APPLICATION 申请',
`flow_id` varchar(64) COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '关联流程ID,未建立流程时为空串',
`title` varchar(200) COLLATE utf8mb4_general_ci NOT NULL COMMENT '草稿标题',
`payload` longtext COLLATE utf8mb4_general_ci NOT NULL COMMENT '草稿内容 JSON,最多 1 MB',
`revision` bigint NOT NULL COMMENT '乐观锁版本号',
`updated_at` timestamp(3) NOT NULL COMMENT '最后保存时间',
PRIMARY KEY (`id`),
KEY `idx_draft_owner` (`tenant_id`,`user_id`,`kind`,`updated_at`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='个人流程草稿';
-- ----------------------------
-- Table structure for flow_notice
-- ----------------------------
DROP TABLE IF EXISTS `flow_notice`;
CREATE TABLE `flow_notice` (
`id` varchar(36) COLLATE utf8mb4_general_ci NOT NULL COMMENT '通知事件ID',
`tenant_id` bigint NOT NULL COMMENT '所属租户ID',
`user_id` varchar(64) COLLATE utf8mb4_general_ci NOT NULL COMMENT '接收人ID,超时提醒到期前为空串',
`event_key` varchar(180) COLLATE utf8mb4_general_ci NOT NULL COMMENT '事件去重键',
`kind` varchar(16) COLLATE utf8mb4_general_ci NOT NULL COMMENT '通知类型:TODO 待办,URGE 催办,OVERDUE 超时提醒',
`title` varchar(200) COLLATE utf8mb4_general_ci NOT NULL COMMENT '通知标题',
`task_id` varchar(64) COLLATE utf8mb4_general_ci NOT NULL COMMENT '引擎任务ID',
`instance_id` varchar(64) COLLATE utf8mb4_general_ci NOT NULL COMMENT '引擎流程实例ID',
`created_at` timestamp(3) NOT NULL COMMENT '创建时间',
`status` varchar(16) COLLATE utf8mb4_general_ci NOT NULL DEFAULT 'SENT' COMMENT '状态:PENDING 待到期,READY 待投递,SENT 已投递,REMOVING 待撤销,CANCELLED 已取消,DISABLED 已停用',
`scheduled_at` timestamp(3) NULL DEFAULT NULL COMMENT '计划投递或到期时间',
`sent_at` timestamp(3) NULL DEFAULT NULL COMMENT '投递到统一站内信的时间',
`reminder_key` varchar(64) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '超时提醒任务ID,每个任务最多一条',
PRIMARY KEY (`id`),
UNIQUE KEY `uk_notice_event` (`tenant_id`,`user_id`,`event_key`),
UNIQUE KEY `uk_notice_reminder` (`tenant_id`,`reminder_key`),
KEY `idx_notice_owner` (`tenant_id`,`user_id`,`created_at`),
KEY `idx_notice_due` (`status`,`scheduled_at`),
KEY `idx_notice_task` (`tenant_id`,`task_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='流程通知事件';
SET FOREIGN_KEY_CHECKS = 1;
+136 -113
View File
@@ -8,9 +8,9 @@ SET FOREIGN_KEY_CHECKS = 0;
-- ----------------------------
DROP TABLE IF EXISTS `qrtz_blob_triggers`;
CREATE TABLE `qrtz_blob_triggers` (
`sched_name` varchar(120) CHARACTER SET utf8 NOT NULL,
`trigger_name` varchar(200) CHARACTER SET utf8 NOT NULL,
`trigger_group` varchar(200) CHARACTER SET utf8 NOT NULL,
`sched_name` varchar(120) CHARACTER SET utf8mb4 NOT NULL,
`trigger_name` varchar(200) CHARACTER SET utf8mb4 NOT NULL,
`trigger_group` varchar(200) CHARACTER SET utf8mb4 NOT NULL,
`blob_data` blob,
PRIMARY KEY (`sched_name`,`trigger_name`,`trigger_group`) USING BTREE,
CONSTRAINT `qrtz_blob_triggers_ibfk_1` FOREIGN KEY (`sched_name`, `trigger_name`, `trigger_group`) REFERENCES `qrtz_triggers` (`sched_name`, `trigger_name`, `trigger_group`) ON DELETE RESTRICT ON UPDATE RESTRICT
@@ -27,8 +27,8 @@ COMMIT;
-- ----------------------------
DROP TABLE IF EXISTS `qrtz_calendars`;
CREATE TABLE `qrtz_calendars` (
`sched_name` varchar(120) CHARACTER SET utf8 NOT NULL,
`calendar_name` varchar(200) CHARACTER SET utf8 NOT NULL,
`sched_name` varchar(120) CHARACTER SET utf8mb4 NOT NULL,
`calendar_name` varchar(200) CHARACTER SET utf8mb4 NOT NULL,
`calendar` blob NOT NULL,
PRIMARY KEY (`sched_name`,`calendar_name`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
@@ -44,11 +44,11 @@ COMMIT;
-- ----------------------------
DROP TABLE IF EXISTS `qrtz_cron_triggers`;
CREATE TABLE `qrtz_cron_triggers` (
`sched_name` varchar(120) CHARACTER SET utf8 NOT NULL,
`trigger_name` varchar(200) CHARACTER SET utf8 NOT NULL,
`trigger_group` varchar(200) CHARACTER SET utf8 NOT NULL,
`cron_expression` varchar(200) CHARACTER SET utf8 NOT NULL,
`time_zone_id` varchar(80) CHARACTER SET utf8 DEFAULT NULL,
`sched_name` varchar(120) CHARACTER SET utf8mb4 NOT NULL,
`trigger_name` varchar(200) CHARACTER SET utf8mb4 NOT NULL,
`trigger_group` varchar(200) CHARACTER SET utf8mb4 NOT NULL,
`cron_expression` varchar(200) CHARACTER SET utf8mb4 NOT NULL,
`time_zone_id` varchar(80) CHARACTER SET utf8mb4 DEFAULT NULL,
PRIMARY KEY (`sched_name`,`trigger_name`,`trigger_group`) USING BTREE,
CONSTRAINT `qrtz_cron_triggers_ibfk_1` FOREIGN KEY (`sched_name`, `trigger_name`, `trigger_group`) REFERENCES `qrtz_triggers` (`sched_name`, `trigger_name`, `trigger_group`) ON DELETE RESTRICT ON UPDATE RESTRICT
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
@@ -64,19 +64,19 @@ COMMIT;
-- ----------------------------
DROP TABLE IF EXISTS `qrtz_fired_triggers`;
CREATE TABLE `qrtz_fired_triggers` (
`sched_name` varchar(120) CHARACTER SET utf8 NOT NULL,
`entry_id` varchar(95) CHARACTER SET utf8 NOT NULL,
`trigger_name` varchar(200) CHARACTER SET utf8 NOT NULL,
`trigger_group` varchar(200) CHARACTER SET utf8 NOT NULL,
`instance_name` varchar(200) CHARACTER SET utf8 NOT NULL,
`sched_name` varchar(120) CHARACTER SET utf8mb4 NOT NULL,
`entry_id` varchar(95) CHARACTER SET utf8mb4 NOT NULL,
`trigger_name` varchar(200) CHARACTER SET utf8mb4 NOT NULL,
`trigger_group` varchar(200) CHARACTER SET utf8mb4 NOT NULL,
`instance_name` varchar(200) CHARACTER SET utf8mb4 NOT NULL,
`fired_time` bigint NOT NULL,
`sched_time` bigint NOT NULL,
`priority` int NOT NULL,
`state` varchar(16) CHARACTER SET utf8 NOT NULL,
`job_name` varchar(200) CHARACTER SET utf8 DEFAULT NULL,
`job_group` varchar(200) CHARACTER SET utf8 DEFAULT NULL,
`is_nonconcurrent` varchar(1) CHARACTER SET utf8 DEFAULT NULL,
`requests_recovery` varchar(1) CHARACTER SET utf8 DEFAULT NULL,
`state` varchar(16) CHARACTER SET utf8mb4 NOT NULL,
`job_name` varchar(200) CHARACTER SET utf8mb4 DEFAULT NULL,
`job_group` varchar(200) CHARACTER SET utf8mb4 DEFAULT NULL,
`is_nonconcurrent` varchar(1) CHARACTER SET utf8mb4 DEFAULT NULL,
`requests_recovery` varchar(1) CHARACTER SET utf8mb4 DEFAULT NULL,
PRIMARY KEY (`sched_name`,`entry_id`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
@@ -91,15 +91,15 @@ COMMIT;
-- ----------------------------
DROP TABLE IF EXISTS `qrtz_job_details`;
CREATE TABLE `qrtz_job_details` (
`sched_name` varchar(120) CHARACTER SET utf8 NOT NULL,
`job_name` varchar(200) CHARACTER SET utf8 NOT NULL,
`job_group` varchar(200) CHARACTER SET utf8 NOT NULL,
`description` varchar(250) CHARACTER SET utf8 DEFAULT NULL,
`job_class_name` varchar(250) CHARACTER SET utf8 NOT NULL,
`is_durable` varchar(1) CHARACTER SET utf8 NOT NULL,
`is_nonconcurrent` varchar(1) CHARACTER SET utf8 NOT NULL,
`is_update_data` varchar(1) CHARACTER SET utf8 NOT NULL,
`requests_recovery` varchar(1) CHARACTER SET utf8 NOT NULL,
`sched_name` varchar(120) CHARACTER SET utf8mb4 NOT NULL,
`job_name` varchar(200) CHARACTER SET utf8mb4 NOT NULL,
`job_group` varchar(200) CHARACTER SET utf8mb4 NOT NULL,
`description` varchar(250) CHARACTER SET utf8mb4 DEFAULT NULL,
`job_class_name` varchar(250) CHARACTER SET utf8mb4 NOT NULL,
`is_durable` varchar(1) CHARACTER SET utf8mb4 NOT NULL,
`is_nonconcurrent` varchar(1) CHARACTER SET utf8mb4 NOT NULL,
`is_update_data` varchar(1) CHARACTER SET utf8mb4 NOT NULL,
`requests_recovery` varchar(1) CHARACTER SET utf8mb4 NOT NULL,
`job_data` blob,
PRIMARY KEY (`sched_name`,`job_name`,`job_group`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
@@ -115,8 +115,8 @@ COMMIT;
-- ----------------------------
DROP TABLE IF EXISTS `qrtz_locks`;
CREATE TABLE `qrtz_locks` (
`sched_name` varchar(120) CHARACTER SET utf8 NOT NULL,
`lock_name` varchar(40) CHARACTER SET utf8 NOT NULL,
`sched_name` varchar(120) CHARACTER SET utf8mb4 NOT NULL,
`lock_name` varchar(40) CHARACTER SET utf8mb4 NOT NULL,
PRIMARY KEY (`sched_name`,`lock_name`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
@@ -131,8 +131,8 @@ COMMIT;
-- ----------------------------
DROP TABLE IF EXISTS `qrtz_paused_trigger_grps`;
CREATE TABLE `qrtz_paused_trigger_grps` (
`sched_name` varchar(120) CHARACTER SET utf8 NOT NULL,
`trigger_group` varchar(200) CHARACTER SET utf8 NOT NULL,
`sched_name` varchar(120) CHARACTER SET utf8mb4 NOT NULL,
`trigger_group` varchar(200) CHARACTER SET utf8mb4 NOT NULL,
PRIMARY KEY (`sched_name`,`trigger_group`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
@@ -147,8 +147,8 @@ COMMIT;
-- ----------------------------
DROP TABLE IF EXISTS `qrtz_scheduler_state`;
CREATE TABLE `qrtz_scheduler_state` (
`sched_name` varchar(120) CHARACTER SET utf8 NOT NULL,
`instance_name` varchar(200) CHARACTER SET utf8 NOT NULL,
`sched_name` varchar(120) CHARACTER SET utf8mb4 NOT NULL,
`instance_name` varchar(200) CHARACTER SET utf8mb4 NOT NULL,
`last_checkin_time` bigint NOT NULL,
`checkin_interval` bigint NOT NULL,
PRIMARY KEY (`sched_name`,`instance_name`) USING BTREE
@@ -165,9 +165,9 @@ COMMIT;
-- ----------------------------
DROP TABLE IF EXISTS `qrtz_simple_triggers`;
CREATE TABLE `qrtz_simple_triggers` (
`sched_name` varchar(120) CHARACTER SET utf8 NOT NULL,
`trigger_name` varchar(200) CHARACTER SET utf8 NOT NULL,
`trigger_group` varchar(200) CHARACTER SET utf8 NOT NULL,
`sched_name` varchar(120) CHARACTER SET utf8mb4 NOT NULL,
`trigger_name` varchar(200) CHARACTER SET utf8mb4 NOT NULL,
`trigger_group` varchar(200) CHARACTER SET utf8mb4 NOT NULL,
`repeat_count` bigint NOT NULL,
`repeat_interval` bigint NOT NULL,
`times_triggered` bigint NOT NULL,
@@ -186,20 +186,20 @@ COMMIT;
-- ----------------------------
DROP TABLE IF EXISTS `qrtz_simprop_triggers`;
CREATE TABLE `qrtz_simprop_triggers` (
`sched_name` varchar(120) CHARACTER SET utf8 NOT NULL,
`trigger_name` varchar(200) CHARACTER SET utf8 NOT NULL,
`trigger_group` varchar(200) CHARACTER SET utf8 NOT NULL,
`str_prop_1` varchar(512) CHARACTER SET utf8 DEFAULT NULL,
`str_prop_2` varchar(512) CHARACTER SET utf8 DEFAULT NULL,
`str_prop_3` varchar(512) CHARACTER SET utf8 DEFAULT NULL,
`sched_name` varchar(120) CHARACTER SET utf8mb4 NOT NULL,
`trigger_name` varchar(200) CHARACTER SET utf8mb4 NOT NULL,
`trigger_group` varchar(200) CHARACTER SET utf8mb4 NOT NULL,
`str_prop_1` varchar(512) CHARACTER SET utf8mb4 DEFAULT NULL,
`str_prop_2` varchar(512) CHARACTER SET utf8mb4 DEFAULT NULL,
`str_prop_3` varchar(512) CHARACTER SET utf8mb4 DEFAULT NULL,
`int_prop_1` int DEFAULT NULL,
`int_prop_2` int DEFAULT NULL,
`long_prop_1` bigint DEFAULT NULL,
`long_prop_2` bigint DEFAULT NULL,
`dec_prop_1` decimal(13,4) DEFAULT NULL,
`dec_prop_2` decimal(13,4) DEFAULT NULL,
`bool_prop_1` varchar(1) CHARACTER SET utf8 DEFAULT NULL,
`bool_prop_2` varchar(1) CHARACTER SET utf8 DEFAULT NULL,
`bool_prop_1` varchar(1) CHARACTER SET utf8mb4 DEFAULT NULL,
`bool_prop_2` varchar(1) CHARACTER SET utf8mb4 DEFAULT NULL,
PRIMARY KEY (`sched_name`,`trigger_name`,`trigger_group`) USING BTREE,
CONSTRAINT `QRTZ_SIMPROP_TRIGGERS_IBFK_1` FOREIGN KEY (`sched_name`, `trigger_name`, `trigger_group`) REFERENCES `qrtz_triggers` (`sched_name`, `trigger_name`, `trigger_group`) ON DELETE RESTRICT ON UPDATE RESTRICT
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
@@ -215,20 +215,20 @@ COMMIT;
-- ----------------------------
DROP TABLE IF EXISTS `qrtz_triggers`;
CREATE TABLE `qrtz_triggers` (
`sched_name` varchar(120) CHARACTER SET utf8 NOT NULL,
`trigger_name` varchar(200) CHARACTER SET utf8 NOT NULL,
`trigger_group` varchar(200) CHARACTER SET utf8 NOT NULL,
`job_name` varchar(200) CHARACTER SET utf8 NOT NULL,
`job_group` varchar(200) CHARACTER SET utf8 NOT NULL,
`description` varchar(250) CHARACTER SET utf8 DEFAULT NULL,
`sched_name` varchar(120) CHARACTER SET utf8mb4 NOT NULL,
`trigger_name` varchar(200) CHARACTER SET utf8mb4 NOT NULL,
`trigger_group` varchar(200) CHARACTER SET utf8mb4 NOT NULL,
`job_name` varchar(200) CHARACTER SET utf8mb4 NOT NULL,
`job_group` varchar(200) CHARACTER SET utf8mb4 NOT NULL,
`description` varchar(250) CHARACTER SET utf8mb4 DEFAULT NULL,
`next_fire_time` bigint DEFAULT NULL,
`prev_fire_time` bigint DEFAULT NULL,
`priority` int DEFAULT NULL,
`trigger_state` varchar(16) CHARACTER SET utf8 NOT NULL,
`trigger_type` varchar(8) CHARACTER SET utf8 NOT NULL,
`trigger_state` varchar(16) CHARACTER SET utf8mb4 NOT NULL,
`trigger_type` varchar(8) CHARACTER SET utf8mb4 NOT NULL,
`start_time` bigint NOT NULL,
`end_time` bigint DEFAULT NULL,
`calendar_name` varchar(200) CHARACTER SET utf8 DEFAULT NULL,
`calendar_name` varchar(200) CHARACTER SET utf8mb4 DEFAULT NULL,
`misfire_instr` smallint DEFAULT NULL,
`job_data` blob,
PRIMARY KEY (`sched_name`,`trigger_name`,`trigger_group`) USING BTREE,
@@ -262,9 +262,9 @@ CREATE TABLE `sys_job` (
`job_status` char(1) CHARACTER SET utf8mb4 DEFAULT '0' COMMENT '状态(1、未发布;2、运行中;3、暂停;4、删除;)',
`job_execute_status` char(1) CHARACTER SET utf8mb4 DEFAULT '0' COMMENT '状态(0正常 1异常)',
`create_by` varchar(64) CHARACTER SET utf8mb4 DEFAULT NULL COMMENT '创建者',
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_by` varchar(64) CHARACTER SET utf8mb4 DEFAULT '' COMMENT '更新者',
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '更新时间',
`update_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '更新时间',
`start_time` timestamp NULL DEFAULT NULL COMMENT '初次执行时间',
`previous_time` timestamp NULL DEFAULT NULL COMMENT '上次执行时间',
`next_time` timestamp NULL DEFAULT NULL COMMENT '下次执行时间',
@@ -286,24 +286,47 @@ DROP TABLE IF EXISTS `sys_job_log`;
CREATE TABLE `sys_job_log` (
`job_log_id` bigint NOT NULL COMMENT '任务日志ID',
`job_id` bigint NOT NULL COMMENT '任务id',
`job_name` varchar(64) CHARACTER SET utf8 DEFAULT NULL COMMENT '任务名称',
`job_group` varchar(64) CHARACTER SET utf8 DEFAULT NULL COMMENT '任务组名',
`job_order` char(1) CHARACTER SET utf8 DEFAULT NULL COMMENT '组内执行顺利,值越大执行优先级越高,最大值9,最小值1',
`job_type` char(1) CHARACTER SET utf8 NOT NULL DEFAULT '1' COMMENT '1、java类;2、spring bean名称;3、rest调用;4、jar调用;9其他',
`execute_path` varchar(500) CHARACTER SET utf8 DEFAULT NULL COMMENT 'job_type=3时,rest调用地址,仅支持post协议;job_type=4时,jar路径;其它值为空',
`class_name` varchar(500) CHARACTER SET utf8 DEFAULT NULL COMMENT 'job_type=1时,类完整路径;job_type=2时,spring bean名称;其它值为空',
`method_name` varchar(500) CHARACTER SET utf8 DEFAULT NULL COMMENT '任务方法',
`method_params_value` varchar(2000) CHARACTER SET utf8 DEFAULT NULL COMMENT '参数值',
`cron_expression` varchar(255) CHARACTER SET utf8 DEFAULT NULL COMMENT 'cron执行表达式',
`job_message` varchar(500) CHARACTER SET utf8 DEFAULT NULL COMMENT '日志信息',
`job_log_status` char(1) CHARACTER SET utf8 DEFAULT '0' COMMENT '执行状态(0正常 1失败)',
`execute_time` varchar(30) CHARACTER SET utf8 DEFAULT NULL COMMENT '执行时间',
`exception_info` varchar(2000) CHARACTER SET utf8 DEFAULT '' COMMENT '异常信息',
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`job_name` varchar(64) CHARACTER SET utf8mb4 DEFAULT NULL COMMENT '任务名称',
`job_group` varchar(64) CHARACTER SET utf8mb4 DEFAULT NULL COMMENT '任务组名',
`job_order` char(1) CHARACTER SET utf8mb4 DEFAULT NULL COMMENT '组内执行顺利,值越大执行优先级越高,最大值9,最小值1',
`job_type` char(1) CHARACTER SET utf8mb4 NOT NULL DEFAULT '1' COMMENT '1、java类;2、spring bean名称;3、rest调用;4、jar调用;9其他',
`execute_path` varchar(500) CHARACTER SET utf8mb4 DEFAULT NULL COMMENT 'job_type=3时,rest调用地址,仅支持post协议;job_type=4时,jar路径;其它值为空',
`class_name` varchar(500) CHARACTER SET utf8mb4 DEFAULT NULL COMMENT 'job_type=1时,类完整路径;job_type=2时,spring bean名称;其它值为空',
`method_name` varchar(500) CHARACTER SET utf8mb4 DEFAULT NULL COMMENT '任务方法',
`method_params_value` varchar(2000) CHARACTER SET utf8mb4 DEFAULT NULL COMMENT '参数值',
`cron_expression` varchar(255) CHARACTER SET utf8mb4 DEFAULT NULL COMMENT 'cron执行表达式',
`job_message` varchar(500) CHARACTER SET utf8mb4 DEFAULT NULL COMMENT '日志信息',
`job_log_status` char(1) CHARACTER SET utf8mb4 DEFAULT '0' COMMENT '执行状态(0正常 1失败)',
`execute_time` varchar(30) CHARACTER SET utf8mb4 DEFAULT NULL COMMENT '执行时间',
`exception_info` varchar(2000) CHARACTER SET utf8mb4 DEFAULT '' COMMENT '异常信息',
`scheduled_fire_time` datetime DEFAULT NULL COMMENT '计划触发时间',
`fire_instance_id` varchar(128) CHARACTER SET utf8mb4 DEFAULT NULL COMMENT 'Quartz触发实例ID',
`dedup_status` char(1) CHARACTER SET utf8mb4 DEFAULT '0' COMMENT '去重状态(0正常执行 1同一触发点重复 2任务运行中跳过)',
`create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`tenant_id` bigint NOT NULL DEFAULT '1' COMMENT '租户id',
PRIMARY KEY (`job_log_id`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='定时任务执行日志表';
CREATE TABLE `xxl_job_group` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`app_name` varchar(64) NOT NULL COMMENT '执行器AppName',
`title` varchar(64) NOT NULL COMMENT '执行器名称',
`address_type` tinyint(4) NOT NULL DEFAULT '0' COMMENT '执行器地址类型:0=自动注册、1=手动录入',
`address_list` text COMMENT '执行器地址列表,多地址逗号分隔',
`update_time` datetime DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE `xxl_job_registry` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`registry_group` varchar(50) NOT NULL,
`registry_key` varchar(255) NOT NULL,
`registry_value` varchar(255) NOT NULL,
`update_time` datetime DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `i_g_k_v` (`registry_group`,`registry_key`,`registry_value`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE `xxl_job_info` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`job_group` int(11) NOT NULL COMMENT '执行器主键ID',
@@ -316,8 +339,8 @@ CREATE TABLE `xxl_job_info` (
`schedule_conf` varchar(128) DEFAULT NULL COMMENT '调度配置,值含义取决于调度类型',
`misfire_strategy` varchar(50) NOT NULL DEFAULT 'DO_NOTHING' COMMENT '调度过期策略',
`executor_route_strategy` varchar(50) DEFAULT NULL COMMENT '执行器路由策略',
`executor_handler` varchar(255) DEFAULT NULL COMMENT '执行器任务handler',
`executor_param` varchar(512) DEFAULT NULL COMMENT '执行器任务参数',
`executor_handler` varchar(255) DEFAULT NULL COMMENT '任务handler',
`executor_param` text DEFAULT NULL COMMENT '任务参数',
`executor_block_strategy` varchar(50) DEFAULT NULL COMMENT '阻塞处理策略',
`executor_timeout` int(11) NOT NULL DEFAULT '0' COMMENT '任务执行超时时间,单位秒',
`executor_fail_retry_count` int(11) NOT NULL DEFAULT '0' COMMENT '失败重试次数',
@@ -332,14 +355,25 @@ CREATE TABLE `xxl_job_info` (
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE `xxl_job_logglue` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`job_id` int(11) NOT NULL COMMENT '任务,主键ID',
`glue_type` varchar(50) DEFAULT NULL COMMENT 'GLUE类型',
`glue_source` mediumtext COMMENT 'GLUE源代码',
`glue_remark` varchar(128) NOT NULL COMMENT 'GLUE备注',
`add_time` datetime DEFAULT NULL,
`update_time` datetime DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
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) DEFAULT NULL COMMENT '执行器地址,本次执行的地址',
`executor_handler` varchar(255) DEFAULT NULL COMMENT '执行器任务handler',
`executor_param` varchar(512) DEFAULT NULL COMMENT '执行器任务参数',
`executor_sharding_param` varchar(20) DEFAULT NULL COMMENT '执行器任务分片参数,格式如 1/2',
`executor_handler` varchar(255) DEFAULT NULL COMMENT '任务handler',
`executor_param` text DEFAULT NULL COMMENT '任务参数',
`executor_sharding_param` varchar(20) DEFAULT NULL COMMENT '任务分片参数,格式如 1/2',
`executor_fail_retry_count` int(11) NOT NULL DEFAULT '0' COMMENT '失败重试次数',
`trigger_time` datetime DEFAULT NULL COMMENT '调度-时间',
`trigger_code` int(11) NOT NULL COMMENT '调度-结果',
@@ -350,7 +384,9 @@ CREATE TABLE `xxl_job_log` (
`alarm_status` tinyint(4) NOT NULL DEFAULT '0' COMMENT '告警状态:0-默认、1-无需告警、2-告警成功、3-告警失败',
PRIMARY KEY (`id`),
KEY `I_trigger_time` (`trigger_time`),
KEY `I_handle_code` (`handle_code`)
KEY `I_handle_code` (`handle_code`),
KEY `I_jobgroup` (`job_group`),
KEY `I_jobid` (`job_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE `xxl_job_log_report` (
@@ -364,53 +400,40 @@ CREATE TABLE `xxl_job_log_report` (
UNIQUE KEY `i_trigger_day` (`trigger_day`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE `xxl_job_logglue` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`job_id` int(11) NOT NULL COMMENT '任务,主键ID',
`glue_type` varchar(50) DEFAULT NULL COMMENT 'GLUE类型',
`glue_source` mediumtext COMMENT 'GLUE源代码',
`glue_remark` varchar(128) NOT NULL COMMENT 'GLUE备注',
`add_time` datetime DEFAULT NULL,
`update_time` datetime DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE `xxl_job_registry` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`registry_group` varchar(50) NOT NULL,
`registry_key` varchar(255) NOT NULL,
`registry_value` varchar(255) NOT NULL,
`update_time` datetime DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `i_g_k_v` (`registry_group`,`registry_key`,`registry_value`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE `xxl_job_group` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`app_name` varchar(64) NOT NULL COMMENT '执行器AppName',
`title` varchar(12) NOT NULL COMMENT '执行器名称',
`address_type` tinyint(4) NOT NULL DEFAULT '0' COMMENT '执行器地址类型:0=自动注册、1=手动录入',
`address_list` text COMMENT '执行器地址列表,多地址逗号分隔',
`update_time` datetime DEFAULT NULL,
PRIMARY KEY (`id`)
CREATE TABLE `xxl_job_lock` (
`lock_name` varchar(50) NOT NULL COMMENT '锁名称',
PRIMARY KEY (`lock_name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE `xxl_job_user` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`username` varchar(50) NOT NULL COMMENT '账号',
`password` varchar(50) NOT NULL COMMENT '密码',
`password` varchar(100) NOT NULL COMMENT '密码加密信息',
`token` varchar(100) DEFAULT NULL COMMENT '登录token',
`role` tinyint(4) NOT NULL COMMENT '角色:0-普通用户、1-管理员',
`permission` varchar(255) DEFAULT NULL COMMENT '权限:执行器ID列表,多个逗号分割',
PRIMARY KEY (`id`),
UNIQUE KEY `i_username` (`username`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE `xxl_job_lock` (
`lock_name` varchar(50) NOT NULL COMMENT '锁名称',
PRIMARY KEY (`lock_name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
INSERT INTO `xxl_job_group`(`id`, `app_name`, `title`, `address_type`, `address_list`, `update_time`)
VALUES (1, 'pigx-daemon-elastic-job', 'PIGX定时任务执行器', 0, NULL, now());
INSERT INTO `xxl_job_user`(`id`, `username`, `password`, `role`, `permission`) VALUES (1, 'admin', 'e10adc3949ba59abbe56e057f20f883e', 1, NULL);
INSERT INTO `xxl_job_lock` ( `lock_name`) VALUES ( 'schedule_lock');
INSERT INTO `xxl_job_info`(`id`, `job_group`, `job_desc`, `add_time`, `update_time`, `author`, `alarm_email`,
`schedule_type`, `schedule_conf`, `misfire_strategy`, `executor_route_strategy`,
`executor_handler`, `executor_param`, `executor_block_strategy`, `executor_timeout`,
`executor_fail_retry_count`, `glue_type`, `glue_source`, `glue_remark`, `glue_updatetime`,
`child_jobid`)
VALUES (1, 1, '示例任务01', now(), now(), 'XXL', '', 'CRON', '0 0 0 * * ? *',
'DO_NOTHING', 'FIRST', 'demoJobHandler', '', 'SERIAL_EXECUTION', 0, 0, 'BEAN', '', 'GLUE代码初始化',
now(), '');
INSERT INTO `xxl_job_user`(`id`, `username`, `password`, `role`, `permission`)
VALUES (1, 'admin', '8d969eef6ecad3c29a3a629280e686cf0c3f5d5a86aff3ca12020c923adc6c92', 1, NULL);
INSERT INTO `xxl_job_lock` (`lock_name`)
VALUES ('schedule_lock');
commit;
SET FOREIGN_KEY_CHECKS = 1;
+10 -10
View File
@@ -73,10 +73,10 @@ DROP TABLE IF EXISTS `wx_account_tag`;
CREATE TABLE `wx_account_tag` (
`id` bigint(20) NOT NULL COMMENT '主键ID',
`tag` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '标签名称',
`create_by` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '创建人',
`update_by` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '修改人',
`create_time` datetime NOT NULL COMMENT '创建时间',
`update_time` datetime NOT NULL COMMENT '修改时间',
`create_by` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci COMMENT '创建人',
`update_by` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci COMMENT '修改人',
`create_time` datetime COMMENT '创建时间',
`update_time` datetime COMMENT '修改时间',
`del_flag` char(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '0' COMMENT '删除标记,0未删除,1已删除',
`tenant_id` bigint(20) NOT NULL COMMENT '租户ID',
`wx_account_id` bigint(20) NOT NULL COMMENT '微信公众号ID',
@@ -113,8 +113,8 @@ CREATE TABLE `wx_auto_reply` (
`rep_thumb_url` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '缩略图url',
`content` json DEFAULT NULL COMMENT '图文消息的内容',
`app_id` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '公众号ID',
`remark` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '备注',
`del_flag` char(1) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT '0' COMMENT '逻辑删除标记(0:显示;1:隐藏)',
`remark` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '备注',
`del_flag` char(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT '0' COMMENT '逻辑删除标记(0:显示;1:隐藏)',
`create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`tenant_id` bigint(20) DEFAULT NULL COMMENT '租户ID',
@@ -159,7 +159,7 @@ CREATE TABLE `wx_msg` (
`id` bigint(20) NOT NULL COMMENT '主键',
`app_name` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '公众号名称',
`app_logo` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '公众号logo',
`wx_user_id` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '微信用户ID',
`wx_user_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '微信用户ID',
`nick_name` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '微信用户昵称',
`headimg_url` varchar(1000) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '微信用户头像',
`type` char(2) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '消息分类(1、用户发给公众号;2、公众号发给用户;)',
@@ -177,11 +177,11 @@ CREATE TABLE `wx_msg` (
`rep_location_x` double DEFAULT NULL COMMENT '地理位置维度',
`rep_location_y` double DEFAULT NULL COMMENT '地理位置经度',
`rep_scale` double DEFAULT NULL COMMENT '地图缩放大小',
`read_flag` char(2) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT '1' COMMENT '已读标记(1:是;0:否)',
`read_flag` char(2) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT '1' COMMENT '已读标记(1:是;0:否)',
`app_id` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '公众号ID',
`open_id` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '微信唯一标识',
`remark` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '备注',
`del_flag` char(1) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT '0' COMMENT '逻辑删除标记(0:显示;1:隐藏)',
`remark` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '备注',
`del_flag` char(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT '0' COMMENT '逻辑删除标记(0:显示;1:隐藏)',
`create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`tenant_id` bigint(20) DEFAULT NULL COMMENT '租户ID',
+275 -169
View File
@@ -6,280 +6,386 @@ SET FOREIGN_KEY_CHECKS = 0;
-- Table structure for config_info
-- ----------------------------
DROP TABLE IF EXISTS `config_info`;
CREATE TABLE `config_info` (
`id` bigint NOT NULL AUTO_INCREMENT COMMENT 'id',
`data_id` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL COMMENT 'data_id',
`group_id` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT NULL,
`content` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL COMMENT 'content',
`md5` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT NULL COMMENT 'md5',
`gmt_create` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`gmt_modified` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '修改时间',
`src_user` text CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL COMMENT 'source user',
`src_ip` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT NULL COMMENT 'source ip',
`app_name` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT NULL,
`tenant_id` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT '' COMMENT '租户字段',
`c_desc` varchar(256) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT NULL,
`c_use` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT NULL,
`effect` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT NULL,
`type` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT NULL,
`c_schema` text CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL,
`encrypted_data_key` text CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL COMMENT '秘钥',
PRIMARY KEY (`id`) USING BTREE,
UNIQUE INDEX `uk_configinfo_datagrouptenant`(`data_id` ASC, `group_id` ASC, `tenant_id` ASC) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 21 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_bin COMMENT = 'config_info' ROW_FORMAT = Dynamic;
CREATE TABLE `config_info` (
`id` bigint NOT NULL AUTO_INCREMENT COMMENT 'id',
`data_id` varchar(255) COLLATE utf8_bin NOT NULL COMMENT 'data_id',
`group_id` varchar(128) COLLATE utf8_bin DEFAULT NULL COMMENT 'group_id',
`content` longtext COLLATE utf8_bin NOT NULL COMMENT 'content',
`md5` varchar(32) COLLATE utf8_bin DEFAULT NULL COMMENT 'md5',
`gmt_create` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`gmt_modified` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '修改时间',
`src_user` text COLLATE utf8_bin COMMENT 'source user',
`src_ip` varchar(50) COLLATE utf8_bin DEFAULT NULL COMMENT 'source ip',
`app_name` varchar(128) COLLATE utf8_bin DEFAULT NULL COMMENT 'app_name',
`tenant_id` varchar(128) COLLATE utf8_bin DEFAULT '' COMMENT '租户字段',
`c_desc` varchar(256) COLLATE utf8_bin DEFAULT NULL COMMENT 'configuration description',
`c_use` varchar(64) COLLATE utf8_bin DEFAULT NULL COMMENT 'configuration usage',
`effect` varchar(64) COLLATE utf8_bin DEFAULT NULL COMMENT '配置生效的描述',
`type` varchar(64) COLLATE utf8_bin DEFAULT NULL COMMENT '配置的类型',
`c_schema` text COLLATE utf8_bin COMMENT '配置的模式',
`encrypted_data_key` varchar(1024) COLLATE utf8_bin NOT NULL DEFAULT '' COMMENT '密钥',
PRIMARY KEY (`id`),
UNIQUE KEY `uk_configinfo_datagrouptenant` (`data_id`,`group_id`,`tenant_id`)
) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='config_info';
-- ----------------------------
-- Records of config_info
-- ----------------------------
BEGIN;
INSERT INTO `config_info` (`id`, `data_id`, `group_id`, `content`, `md5`, `gmt_create`, `gmt_modified`, `src_user`, `src_ip`, `app_name`, `tenant_id`, `c_desc`, `c_use`, `effect`, `type`, `c_schema`, `encrypted_data_key`) VALUES (1, 'application-dev.yml', 'DEFAULT_GROUP', '# 配置文件加密根密码\njasypt:\n encryptor:\n password: pigx\n algorithm: PBEWithMD5AndDES\n iv-generator-classname: org.jasypt.iv.NoIvGenerator\n\n\nspring:\n data:\n redis:\n host: pigx-redis\n servlet:\n multipart:\n max-file-size: 100MB\n max-request-size: 100MB\n cloud:\n sentinel:\n eager: true\n transport:\n dashboard: pigx-sentinel:5020\n openfeign:\n sentinel:\n enabled: true\n okhttp:\n enabled: true\n httpclient:\n enabled: false\n connection-timeout: 20000\n compression:\n request:\n enabled: true\n response:\n enabled: true\n\n# 端点对外暴露\nmanagement:\n endpoints:\n web:\n exposure:\n include: \'*\' \n endpoint:\n restart:\n enabled: true\n health:\n show-details: ALWAYS\n\n#开启灰度\ngray:\n rule:\n enabled: true\n\n# mybatis-plus 配置\nmybatis-plus:\n tenant-enable: ture\n mapper-locations: classpath:/mapper/*Mapper.xml\n global-config:\n capitalMode: true\n banner: false\n db-config:\n id-type: auto\n select-strategy: not_empty\n insert-strategy: not_empty\n update-strategy: not_null\n type-handlers-package: com.pig4cloud.pigx.common.data.handler\n configuration:\n jdbc-type-for-null: \'null\'\n call-setters-on-nulls: true\n shrink-whitespaces-in-sql: true\nmybatis-plus-join:\n banner: false #关闭连表查询组件banner', '90942d7d4856ccba068fe5847643737d', '2022-12-16 10:44:25', '2023-08-14 11:44:19', 'nacos', '127.0.0.1', '', '', '', '', '', 'yaml', '', '');
INSERT INTO `config_info` (`id`, `data_id`, `group_id`, `content`, `md5`, `gmt_create`, `gmt_modified`, `src_user`, `src_ip`, `app_name`, `tenant_id`, `c_desc`, `c_use`, `effect`, `type`, `c_schema`, `encrypted_data_key`) VALUES (2, 'pigx-auth-dev.yml', 'DEFAULT_GROUP', '# 数据源\nspring:\n freemarker:\n allow-request-override: false\n allow-session-override: false\n cache: true\n charset: UTF-8\n check-template-location: true\n content-type: text/html\n enabled: true\n expose-request-attributes: false\n expose-session-attributes: false\n expose-spring-macro-helpers: true\n prefer-file-system-access: true\n suffix: .ftl\n template-loader-path: classpath:/templates/\n\n# 前端登录验证码\nsecurity:\n encodeKey: \'pigxpigxpigxpigx\'\n# 验证码相关配置参考: http://t.cn/A647jEdu\naj:\n captcha:\n cache-type: redis\n water-mark: pig4cloud', 'bb6bd9b9e21afdec3d6c88636387df96', '2022-12-16 10:44:25', '2024-04-20 22:47:21', 'nacos', '0:0:0:0:0:0:0:1', '', '', '', '', '', 'yaml', '', '');
INSERT INTO `config_info` (`id`, `data_id`, `group_id`, `content`, `md5`, `gmt_create`, `gmt_modified`, `src_user`, `src_ip`, `app_name`, `tenant_id`, `c_desc`, `c_use`, `effect`, `type`, `c_schema`, `encrypted_data_key`) VALUES (3, 'pigx-codegen-dev.yml', 'DEFAULT_GROUP', '# 数据源\nspring:\n datasource:\n type: com.alibaba.druid.pool.DruidDataSource\n druid:\n driver-class-name: com.mysql.cj.jdbc.Driver\n username: ${MYSQL_USER:root}\n password: ${MYSQL_PWD:root}\n url: jdbc:mysql://${MYSQL_HOST:pigx-mysql}:${MYSQL_PORT:3306}/${MYSQL_DB:pigxx_codegen}?characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=GMT%2B8&allowMultiQueries=true&allowPublicKeyRetrieval=true\n resources:\n static-locations: classpath:/static/,classpath:/views/\n', 'ed6de06e34e2634c28a24e8a1db99b06', '2022-12-16 10:44:25', '2024-02-22 15:08:09', 'nacos', '0:0:0:0:0:0:0:1', '', '', '', '', '', 'yaml', '', '');
INSERT INTO `config_info` (`id`, `data_id`, `group_id`, `content`, `md5`, `gmt_create`, `gmt_modified`, `src_user`, `src_ip`, `app_name`, `tenant_id`, `c_desc`, `c_use`, `effect`, `type`, `c_schema`, `encrypted_data_key`) VALUES (4, 'pigx-daemon-elastic-job-dev.yml', 'DEFAULT_GROUP', '# 数据源\nspring:\n datasource:\n type: com.alibaba.druid.pool.DruidDataSource\n druid:\n driver-class-name: com.mysql.cj.jdbc.Driver\n username: ${MYSQL_USER:root}\n password: ${MYSQL_PWD:root}\n url: jdbc:mysql://${MYSQL_HOST:pigx-mysql}:${MYSQL_PORT:3306}/${MYSQL_DB:pigxx_job}?characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=GMT%2B8&allowMultiQueries=true&allowPublicKeyRetrieval=true', '09996f46e0b80d7b2aa320ef4cb31c82', '2022-12-16 10:44:25', '2023-04-07 14:14:50', 'nacos', '127.0.0.1', '', '', '', '', '', 'yaml', '', '');
INSERT INTO `config_info` (`id`, `data_id`, `group_id`, `content`, `md5`, `gmt_create`, `gmt_modified`, `src_user`, `src_ip`, `app_name`, `tenant_id`, `c_desc`, `c_use`, `effect`, `type`, `c_schema`, `encrypted_data_key`) VALUES (5, 'pigx-gateway-dev.yml', 'DEFAULT_GROUP', '# 固定路由转发配置 无修改\nspring:\n cloud:\n gateway:\n routes:\n - id: openapi\n uri: lb://pigx-gateway\n predicates:\n - Path=/v3/api-docs/**\n filters:\n - RewritePath=/v3/api-docs/(?<path>.*), /$\\{path}/$\\{path}/v3/api-docs\n\n# gateway 刷新端点\nmanagement:\n endpoint:\n gateway:\n enabled: true\n', 'd9454d877ff3d8bd3fd0d5be99810195', '2022-12-16 10:44:25', '2024-04-20 22:47:02', 'nacos', '0:0:0:0:0:0:0:1', '', '', '', '', '', 'yaml', '', '');
INSERT INTO `config_info` (`id`, `data_id`, `group_id`, `content`, `md5`, `gmt_create`, `gmt_modified`, `src_user`, `src_ip`, `app_name`, `tenant_id`, `c_desc`, `c_use`, `effect`, `type`, `c_schema`, `encrypted_data_key`) VALUES (6, 'pigx-monitor-dev.yml', 'DEFAULT_GROUP', 'spring:\n # 安全配置\n security:\n user:\n name: ENC(rZHA4LW5hHmhLAAzJoFNag==) # pigx\n password: ENC(bjeyh+Aeii3kHXkoo00ZUw==) # pigx\n autoconfigure:\n exclude: com.pig4cloud.pigx.common.core.config.JacksonConfiguration\n boot:\n admin:\n ui:\n title: \'pigx 服务状态监控\'\n brand: \'pigx 服务状态监控\'\n external-views:\n - label: \"SQL监控\"\n url: /druid/sql.html\n order: 2000\n iframe: true\nmanagement:\n endpoints:\n web:\n exposure:\n include: \'*\'\n endpoint:\n health:\n show-details: ALWAYS #显示详细信息\n\n\n# druid 监控的服务\nmonitor:\n applications:\n - pigx-upms-biz\n', '2bb39e4dee3f90d4186d1e42aa666d2a', '2022-12-16 10:44:25', '2023-04-07 14:12:09', 'nacos', '127.0.0.1', '', '', '', '', '', 'yaml', '', '');
INSERT INTO `config_info` (`id`, `data_id`, `group_id`, `content`, `md5`, `gmt_create`, `gmt_modified`, `src_user`, `src_ip`, `app_name`, `tenant_id`, `c_desc`, `c_use`, `effect`, `type`, `c_schema`, `encrypted_data_key`) VALUES (7, 'pigx-upms-biz-dev.yml', 'DEFAULT_GROUP', '## spring security 配置\nsecurity:\n oauth2:\n client:\n ignore-urls:\n - /druid/**\n\n# 数据源\nspring:\n autoconfigure:\n exclude: org.springframework.cloud.gateway.config.GatewayAutoConfiguration,org.springframework.cloud.gateway.config.GatewayClassPathWarningAutoConfiguration\n datasource:\n type: com.alibaba.druid.pool.DruidDataSource\n druid:\n driver-class-name: com.mysql.cj.jdbc.Driver\n username: ${MYSQL_USER:root}\n password: ${MYSQL_PWD:root}\n url: jdbc:mysql://${MYSQL_HOST:pigx-mysql}:${MYSQL_PORT:3306}/${MYSQL_DB:pigxx}?characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=GMT%2B8&allowMultiQueries=true&allowPublicKeyRetrieval=true\n stat-view-servlet:\n enabled: true\n allow: \"\"\n url-pattern: /druid/*\n #login-username: admin\n #login-password: admin\n filter:\n stat:\n enabled: true\n log-slow-sql: true\n slow-sql-millis: 10000\n merge-sql: false\n wall:\n config:\n multi-statement-allow: true\n\n# 本地文件系统\nfile:\n local:\n enable: true\n basePath: /Users/lengleng/Downloads/files', '28f2305c1cfb413dcc45a3d432ef7098', '2022-12-16 10:44:25', '2024-02-22 15:08:36', 'nacos', '0:0:0:0:0:0:0:1', '', '', '', '', '', 'yaml', '', '');
INSERT INTO `config_info` (`id`, `data_id`, `group_id`, `content`, `md5`, `gmt_create`, `gmt_modified`, `src_user`, `src_ip`, `app_name`, `tenant_id`, `c_desc`, `c_use`, `effect`, `type`, `c_schema`, `encrypted_data_key`) VALUES (8, 'pigx-daemon-quartz-dev.yml', 'DEFAULT_GROUP', '# 数据源\nspring:\n datasource:\n type: com.alibaba.druid.pool.DruidDataSource\n druid:\n driver-class-name: com.mysql.cj.jdbc.Driver\n username: ${MYSQL_USER:root}\n password: ${MYSQL_PWD:root}\n url: jdbc:mysql://${MYSQL_HOST:pigx-mysql}:${MYSQL_PORT:3306}/${MYSQL_DB:pigxx_job}?characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=GMT%2B8&allowMultiQueries=true&allowPublicKeyRetrieval=true\n resources:\n static-locations: classpath:/static/,classpath:/views/', '79619124a30cdb6e8bc1046aaa18d91c', '2022-12-16 10:44:25', '2024-04-19 21:49:00', 'nacos', '0:0:0:0:0:0:0:1', '', '', '', '', '', 'yaml', '', '');
INSERT INTO `config_info` (`id`, `data_id`, `group_id`, `content`, `md5`, `gmt_create`, `gmt_modified`, `src_user`, `src_ip`, `app_name`, `tenant_id`, `c_desc`, `c_use`, `effect`, `type`, `c_schema`, `encrypted_data_key`) VALUES (9, 'pigx-pay-platform-dev.yml', 'DEFAULT_GROUP', '# 数据源\nspring:\n datasource:\n type: com.alibaba.druid.pool.DruidDataSource\n druid:\n driver-class-name: com.mysql.cj.jdbc.Driver\n username: ${MYSQL_USER:root}\n password: ${MYSQL_PWD:root}\n url: jdbc:mysql://${MYSQL_HOST:pigx-mysql}:${MYSQL_PORT:3306}/${MYSQL_DB:pigxx_pay}?characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=GMT%2B8&allowMultiQueries=true&allowPublicKeyRetrieval=true\n freemarker:\n allow-request-override: false\n allow-session-override: false\n cache: true\n charset: UTF-8\n check-template-location: true\n content-type: text/html\n enabled: true\n expose-request-attributes: false\n expose-session-attributes: false\n expose-spring-macro-helpers: true\n prefer-file-system-access: true\n suffix: .ftl\n template-loader-path: classpath:/templates/\n# 租户表维护\npigx:\n pay:\n test: lengleng\n aliPayConfig:\n expire-time: 30\n return-url: http://pig4cloud.com\n notify-url: http://payx.yunjihuitong.com/pay/notify/ali/callbak\n wxPayConfig:\n notify-url: https://admin.pig4cloud.com/pay/notify/wx/callbak\n mergePayConfig:\n return-url: http://pig4cloud.com\n notify-url: http://wechat.pigx.top/pay/notify/merge/callbak\n xsequence: #发号器相关配置\n db:\n retry-times: 3\n table-name: pay_sequence', 'f4e5734a99f3c1f059071deac081b33d', '2022-12-16 10:44:25', '2024-02-22 15:09:08', 'nacos', '0:0:0:0:0:0:0:1', '', '', '', '', '', 'yaml', '', '');
INSERT INTO `config_info` (`id`, `data_id`, `group_id`, `content`, `md5`, `gmt_create`, `gmt_modified`, `src_user`, `src_ip`, `app_name`, `tenant_id`, `c_desc`, `c_use`, `effect`, `type`, `c_schema`, `encrypted_data_key`) VALUES (11, 'pigx-mp-platform-dev.yml', 'DEFAULT_GROUP', '# 数据源\nspring:\n datasource:\n type: com.alibaba.druid.pool.DruidDataSource\n druid:\n driver-class-name: com.mysql.cj.jdbc.Driver\n username: ${MYSQL_USER:root}\n password: ${MYSQL_PWD:root}\n url: jdbc:mysql://${MYSQL_HOST:pigx-mysql}:${MYSQL_PORT:3306}/${MYSQL_DB:pigxx_mp}?characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=GMT%2B8&allowMultiQueries=true&allowPublicKeyRetrieval=true\n resources:\n static-locations: classpath:/static/,classpath:/views/', 'd5936e0c352fb1fbe1d05f054f14c98a', '2022-12-16 10:44:25', '2024-02-22 15:09:20', 'nacos', '0:0:0:0:0:0:0:1', '', '', '', '', '', 'yaml', '', '');
INSERT INTO `config_info` (`id`, `data_id`, `group_id`, `content`, `md5`, `gmt_create`, `gmt_modified`, `src_user`, `src_ip`, `app_name`, `tenant_id`, `c_desc`, `c_use`, `effect`, `type`, `c_schema`, `encrypted_data_key`) VALUES (12, 'pigx-xxl-job-admin-dev.yml', 'DEFAULT_GROUP', '# xxl\nxxl:\n job:\n i18n: zh_CN\n logretentiondays: 30\n triggerpool:\n fast.max: 200\n slow.max: 200\n\n# mybatis\nmybatis:\n mapper-locations: classpath:/mybatis-mapper/*Mapper.xml\n\n# spring\nspring:\n datasource:\n type: com.alibaba.druid.pool.DruidDataSource\n druid:\n driver-class-name: com.mysql.cj.jdbc.Driver\n username: ${MYSQL_USER:root}\n password: ${MYSQL_PWD:root}\n url: jdbc:mysql://${MYSQL_HOST:pigx-mysql}:${MYSQL_PORT:3306}/${MYSQL_DB:pigxx_job}?characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=GMT%2B8&allowMultiQueries=true&allowPublicKeyRetrieval=true\n mvc:\n static-path-pattern: /static/**\n freemarker:\n suffix: .ftl\n request-context-attribute: request\n settings:\n number_format: 0.##########\n mail:\n host: smtp.mxhichina.com\n port: 465\n from: xxxx@gitee.wang\n username: xxxx@gitee.wang\n password: xxxx\n properties:\n mail:\n smtp:\n auth: true\n ssl.enable: true\n starttls.enable: false\n required: false\n\nmanagement:\n health:\n mail:\n enabled: false\n endpoints:\n web:\n exposure:\n include: \'*\'\n endpoint:\n health:\n show-details: ALWAYS', '6d70dce1f3ee48f261dce29bcfa99cbb', '2022-12-16 10:44:25', '2023-01-04 18:22:48', 'nacos', '127.0.0.1', '', '', '', '', '', 'yaml', '', '');
INSERT INTO `config_info` (`id`, `data_id`, `group_id`, `content`, `md5`, `gmt_create`, `gmt_modified`, `src_user`, `src_ip`, `app_name`, `tenant_id`, `c_desc`, `c_use`, `effect`, `type`, `c_schema`, `encrypted_data_key`) VALUES (13, 'pigx-report-platform-dev.yml', 'DEFAULT_GROUP', 'spring:\n datasource:\n type: com.alibaba.druid.pool.DruidDataSource\n druid:\n driver-class-name: com.mysql.cj.jdbc.Driver\n username: ${MYSQL_USER:root}\n password: ${MYSQL_PWD:root}\n url: jdbc:mysql://${MYSQL_HOST:pigx-mysql}:${MYSQL_PORT:3306}/${MYSQL_DB:pigxx_report}?characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=GMT%2B8&allowMultiQueries=true&allowPublicKeyRetrieval=true\n jpa:\n database-platform: org.hibernate.dialect.MySQL8Dialect\n\nsecurity:\n oauth2:\n client:\n ignore-urls:\n - /\n - /api/project/getData\n - /static/**\n - /api/project/get-file/*\n\n# 文件上传路径\ngv:\n img-path: /Users/lengleng/Downloads/img/\n', 'ce3fde4b4592cdd61feb2e443b2ddfe5', '2022-12-16 10:44:25', '2023-04-07 12:56:57', 'nacos', '127.0.0.1', '', '', '', '', '', 'yaml', '', '');
INSERT INTO `config_info` (`id`, `data_id`, `group_id`, `content`, `md5`, `gmt_create`, `gmt_modified`, `src_user`, `src_ip`, `app_name`, `tenant_id`, `c_desc`, `c_use`, `effect`, `type`, `c_schema`, `encrypted_data_key`) VALUES (14, 'pigx-jimu-platform-dev.yml', 'DEFAULT_GROUP', 'spring:\n #配置静态资源\n mvc:\n static-path-pattern: /**\n resource:\n static-locations: classpath:/static/\n #配置数据库\n datasource:\n type: com.alibaba.druid.pool.DruidDataSource\n druid:\n driver-class-name: com.mysql.cj.jdbc.Driver\n username: ${MYSQL_USER:root}\n password: ${MYSQL_PWD:root}\n url: jdbc:mysql://${MYSQL_HOST:pigx-mysql}:${MYSQL_PORT:3306}/${MYSQL_DB:pigxx_bi}?characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=GMT%2B8&allowMultiQueries=true&allowPublicKeyRetrieval=true\n \n#JimuReport[minidao配置]\nminidao :\n base-package: org.jeecg.modules.jmreport.desreport.dao*\n db-type: mysql\n#JimuReport[上传配置]\njeecg :\n jmreport:\n customPrePath: /api/jimu\n # 自动保存\n autoSave: true\n # 单位毫秒 默认5*60*1000 \n interval: 10000\n # local|minio|alioss\n uploadType: local\n # local\n path :\n #文件路径A\n upload: ~/jimu/data\n # alioss\n oss:\n endpoint: oss-cn-beijing.aliyuncs.com\n accessKey: ??\n secretKey: ??\n staticDomain: ??\n bucketName: ??\n # minio\n minio:\n minio_url: http://minio.jeecg.com\n minio_name: ??\n minio_pass: ??\n bucketName: ??\n#输出sql日志\nlogging:\n level:\n org.jeecg.modules.jmreport : debug', '66319da04963c4c7217f807bf1bd5f2d', '2022-12-16 10:44:25', '2024-01-30 20:44:36', 'nacos', '0:0:0:0:0:0:0:1', '', '', '', '', '', 'yaml', '', '');
INSERT INTO `config_info` (`id`, `data_id`, `group_id`, `content`, `md5`, `gmt_create`, `gmt_modified`, `src_user`, `src_ip`, `app_name`, `tenant_id`, `c_desc`, `c_use`, `effect`, `type`, `c_schema`, `encrypted_data_key`) VALUES (15, 'pigx-app-server-biz-dev.yml', 'DEFAULT_GROUP', '# 数据源\nspring:\n datasource:\n type: com.alibaba.druid.pool.DruidDataSource\n druid:\n driver-class-name: com.mysql.cj.jdbc.Driver\n username: ${MYSQL_USER:root}\n password: ${MYSQL_PWD:root}\n url: jdbc:mysql://${MYSQL_HOST:pigx-mysql}:${MYSQL_PORT:3306}/${MYSQL_DB:pigxx_app}?characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=GMT%2B8&allowMultiQueries=true&allowPublicKeyRetrieval=true', 'e4668a1854e92a5a666e83479ef7d26a', '2022-12-19 10:30:07', '2024-02-22 15:09:50', 'nacos', '0:0:0:0:0:0:0:1', '', '', '', '', '', 'yaml', '', '');
INSERT INTO `config_info` (`id`, `data_id`, `group_id`, `content`, `md5`, `gmt_create`, `gmt_modified`, `src_user`, `src_ip`, `app_name`, `tenant_id`, `c_desc`, `c_use`, `effect`, `type`, `c_schema`, `encrypted_data_key`) VALUES (16, 'pigx-flow-engine-biz-dev.yml', 'DEFAULT_GROUP', '# 数据源\nspring:\n datasource:\n type: com.alibaba.druid.pool.DruidDataSource\n druid:\n driver-class-name: com.mysql.cj.jdbc.Driver\n username: ${MYSQL_USER:root}\n password: ${MYSQL_PWD:root}\n url: jdbc:mysql://${MYSQL_HOST:pigx-mysql}:${MYSQL_PORT:3306}/${MYSQL_DB:pigxx_flow}?characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=GMT%2B8&allowMultiQueries=true&nullCatalogMeansCurrent=true', '233121e20445609e1ba378c3686ea7d5', '2023-07-28 13:41:32', '2023-07-28 13:43:36', 'nacos', '0:0:0:0:0:0:0:1', '', '', 'flowable 工作引擎', '', '', 'yaml', '', '');
INSERT INTO `config_info` (`id`, `data_id`, `group_id`, `content`, `md5`, `gmt_create`, `gmt_modified`, `src_user`, `src_ip`, `app_name`, `tenant_id`, `c_desc`, `c_use`, `effect`, `type`, `c_schema`, `encrypted_data_key`) VALUES (17, 'pigx-flow-task-biz-dev.yml', 'DEFAULT_GROUP', '# 数据源\nspring:\n datasource:\n type: com.alibaba.druid.pool.DruidDataSource\n druid:\n driver-class-name: com.mysql.cj.jdbc.Driver\n username: ${MYSQL_USER:root}\n password: ${MYSQL_PWD:root}\n url: jdbc:mysql://${MYSQL_HOST:pigx-mysql}:${MYSQL_PORT:3306}/${MYSQL_DB:pigxx_flow}?characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=GMT%2B8&allowMultiQueries=true&nullCatalogMeansCurrent=true', '233121e20445609e1ba378c3686ea7d5', '2023-07-28 13:44:25', '2024-02-22 15:09:34', 'nacos', '0:0:0:0:0:0:0:1', '', '', 'flowable 业务', '', '', 'yaml', '', '');
INSERT INTO `config_info` (`id`, `data_id`, `group_id`, `content`, `md5`, `gmt_create`, `gmt_modified`, `src_user`,
`src_ip`, `app_name`, `tenant_id`, `c_desc`, `c_use`, `effect`, `type`, `c_schema`,
`encrypted_data_key`)
VALUES (1, 'application-dev.yml', 'DEFAULT_GROUP',
'# 配置文件加密根密码\njasypt:\n encryptor:\n password: pigx\n algorithm: PBEWithMD5AndDES\n iv-generator-classname: org.jasypt.iv.NoIvGenerator\n\nspring:\n jackson:\n use-jackson2-defaults: true\n data:\n redis:\n host: pigx-redis\n servlet:\n multipart:\n max-file-size: 100MB\n max-request-size: 100MB\n cloud:\n refresh:\n never-refreshable: dataSource\n compatibility-verifier:\n enabled: false\n nacos:\n discovery:\n naming-async-query-subscribe-service: true\n sentinel:\n eager: true\n transport:\n dashboard: pigx-sentinel:5020\n openfeign:\n sentinel:\n enabled: true\n okhttp:\n enabled: true\n httpclient:\n enabled: false\n connection-timeout: 20000\n compression:\n request:\n min-request-size: 5120\n enabled: true\n response:\n enabled: true\n\n# 端点对外暴露\nmanagement:\n endpoints:\n web:\n exposure:\n include: \' *\' \n endpoint:\n restart:\n access: none\n health:\n show-details: ALWAYS\n\n#开启灰度\ngray:\n rule:\n enabled: true\n\n# liteflow配置\nliteflow:\n # 分支超时时间调整为 150 秒\n when-max-wait-time: 150000\n\n# mybatis-plus 配置\nmybatis-plus:\n mapper-locations: classpath:/mapper/*Mapper.xml\n global-config:\n capitalMode: true\n banner: false\n db-config:\n id-type: auto\n where-strategy: not_empty\n insert-strategy: not_empty\n update-strategy: not_null\n sequence:\n worker-id: ${random.int(1,31)}\n datacenter-id: ${random.int(1,31)}\n type-handlers-package: com.pig4cloud.pigx.common.data.handler\n configuration:\n jdbc-type-for-null: \'null\'\n call-setters-on-nulls: true\n shrink-whitespaces-in-sql: true\nmybatis-plus-join:\n banner: false #关闭连表查询组件banner',
'0dc3faa0d9871245282f6b7d4f2249c0', '2022-12-16 10:44:25', '2023-08-14 11:44:19', 'nacos', '127.0.0.1', '',
'public', '', '', '', 'yaml', '', '');
INSERT INTO `config_info` (`id`, `data_id`, `group_id`, `content`, `md5`, `gmt_create`, `gmt_modified`, `src_user`, `src_ip`, `app_name`, `tenant_id`, `c_desc`, `c_use`, `effect`, `type`, `c_schema`, `encrypted_data_key`) VALUES (2, 'pigx-auth-dev.yml', 'DEFAULT_GROUP', '# 数据源\nspring:\n freemarker:\n allow-request-override: false\n allow-session-override: false\n cache: true\n charset: UTF-8\n check-template-location: true\n content-type: text/html\n enabled: true\n expose-request-attributes: false\n expose-session-attributes: false\n expose-spring-macro-helpers: true\n prefer-file-system-access: true\n suffix: .ftl\n template-loader-path: classpath:/templates/\n\n# 前端登录验证码\nsecurity:\n encodeKey: \'pigxpigxpigxpigx\'\n# 验证码相关配置参考: http://t.cn/A647jEdu\naj:\n captcha:\n cache-type: redis\n water-mark: pig4cloud', 'bb6bd9b9e21afdec3d6c88636387df96', '2022-12-16 10:44:25', '2024-04-20 22:47:21', 'nacos', '127.0.0.1', '', 'public', '', '', '', 'yaml', '', '');
INSERT INTO `config_info` (`id`, `data_id`, `group_id`, `content`, `md5`, `gmt_create`, `gmt_modified`, `src_user`, `src_ip`, `app_name`, `tenant_id`, `c_desc`, `c_use`, `effect`, `type`, `c_schema`, `encrypted_data_key`) VALUES (3, 'pigx-codegen-dev.yml', 'DEFAULT_GROUP', '# 数据源\nspring:\n datasource:\n type: com.alibaba.druid.pool.DruidDataSource\n druid:\n driver-class-name: com.mysql.cj.jdbc.Driver\n username: ${MYSQL_USER:root}\n password: ${MYSQL_PWD:root}\n url: jdbc:mysql://${MYSQL_HOST:pigx-mysql}:${MYSQL_PORT:3306}/${MYSQL_DB:pigxx_codegen}?characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=GMT%2B8&allowMultiQueries=true&allowPublicKeyRetrieval=true\n', 'e9ca4622d920568cb5daf08145b63b1e', '2022-12-16 10:44:25', '2024-02-22 15:08:09', 'nacos', '127.0.0.1', '', 'public', '', '', '', 'yaml', '', '');
INSERT INTO `config_info` (`id`, `data_id`, `group_id`, `content`, `md5`, `gmt_create`, `gmt_modified`, `src_user`, `src_ip`, `app_name`, `tenant_id`, `c_desc`, `c_use`, `effect`, `type`, `c_schema`, `encrypted_data_key`) VALUES (4, 'pigx-daemon-elastic-job-dev.yml', 'DEFAULT_GROUP', '# 数据源\nspring:\n datasource:\n type: com.alibaba.druid.pool.DruidDataSource\n druid:\n driver-class-name: com.mysql.cj.jdbc.Driver\n username: ${MYSQL_USER:root}\n password: ${MYSQL_PWD:root}\n url: jdbc:mysql://${MYSQL_HOST:pigx-mysql}:${MYSQL_PORT:3306}/${MYSQL_DB:pigxx_job}?characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=GMT%2B8&allowMultiQueries=true&allowPublicKeyRetrieval=true\n\n# XXL-Job 配置\nxxl:\n job:\n accessToken: default_token', 'ac1b92ceacc451eac15942131e04c6dd', '2022-12-16 10:44:25', '2023-04-07 14:14:50', 'nacos', '127.0.0.1', '', 'public', '', '', '', 'yaml', '', '');
INSERT INTO `config_info` (`id`, `data_id`, `group_id`, `content`, `md5`, `gmt_create`, `gmt_modified`, `src_user`, `src_ip`, `app_name`, `tenant_id`, `c_desc`, `c_use`, `effect`, `type`, `c_schema`, `encrypted_data_key`) VALUES (5, 'pigx-gateway-dev.yml', 'DEFAULT_GROUP', '# 固定路由转发配置 无修改\nspring:\n cloud:\n gateway:\n server:\n webflux:\n routes:\n - id: openapi\n uri: lb://pigx-gateway\n predicates:\n - Path=/v3/api-docs/**\n filters:\n - RewritePath=/v3/api-docs/(?<path>.*), /$\\{path}/$\\{path}/v3/api-docs\n\n# gateway 刷新端点\nmanagement:\n endpoint:\n gateway:\n access: unrestricted\n', 'd9454d877ff3d8bd3fd0d5be99810195', '2022-12-16 10:44:25', '2024-04-20 22:47:02', 'nacos', '127.0.0.1', '', 'public', '', '', '', 'yaml', '', '');
INSERT INTO `config_info` (`id`, `data_id`, `group_id`, `content`, `md5`, `gmt_create`, `gmt_modified`, `src_user`, `src_ip`, `app_name`, `tenant_id`, `c_desc`, `c_use`, `effect`, `type`, `c_schema`, `encrypted_data_key`) VALUES (6, 'pigx-monitor-dev.yml', 'DEFAULT_GROUP', 'spring:\n # 安全配置\n security:\n user:\n name: ENC(rZHA4LW5hHmhLAAzJoFNag==) # pigx\n password: ENC(bjeyh+Aeii3kHXkoo00ZUw==) # pigx\n autoconfigure:\n exclude: com.pig4cloud.pigx.common.core.config.JacksonConfiguration\n boot:\n admin:\n ui:\n title: \'pigx 服务状态监控\'\n brand: \'pigx 服务状态监控\'\n external-views:\n - label: \"SQL监控\"\n url: /druid/sql.html\n order: 2000\n iframe: true\nmanagement:\n endpoints:\n web:\n exposure:\n include: \'*\'\n endpoint:\n health:\n show-details: ALWAYS #显示详细信息\n\n\n# druid 监控的服务\nmonitor:\n applications:\n - pigx-upms-biz\n', '2bb39e4dee3f90d4186d1e42aa666d2a', '2022-12-16 10:44:25', '2023-04-07 14:12:09', 'nacos', '127.0.0.1', '', 'public', '', '', '', 'yaml', '', '');
INSERT INTO `config_info` (`id`, `data_id`, `group_id`, `content`, `md5`, `gmt_create`, `gmt_modified`, `src_user`, `src_ip`, `app_name`, `tenant_id`, `c_desc`, `c_use`, `effect`, `type`, `c_schema`, `encrypted_data_key`) VALUES (7, 'pigx-upms-biz-dev.yml', 'DEFAULT_GROUP', '## spring security 配置\nsecurity:\n oauth2:\n client:\n ignore-urls:\n - /druid/**\n\n# 数据源\nspring:\n datasource:\n type: com.alibaba.druid.pool.DruidDataSource\n druid:\n driver-class-name: com.mysql.cj.jdbc.Driver\n username: ${MYSQL_USER:root}\n password: ${MYSQL_PWD:root}\n url: jdbc:mysql://${MYSQL_HOST:pigx-mysql}:${MYSQL_PORT:3306}/${MYSQL_DB:pigxx}?characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=GMT%2B8&allowMultiQueries=true&allowPublicKeyRetrieval=true\n stat-view-servlet:\n enabled: true\n allow: \"\"\n url-pattern: /druid/*\n #login-username: admin\n #login-password: admin\n filter:\n stat:\n enabled: true\n log-slow-sql: true\n slow-sql-millis: 10000\n merge-sql: false\n wall:\n config:\n multi-statement-allow: true\n\n# 本地文件系统\nfile:\n type: local\n local:\n basePath: /Users/lengleng/Downloads/files', '31570b7a880625228335b7f7e5aaa312', '2022-12-16 10:44:25', '2024-02-22 15:08:36', 'nacos', '127.0.0.1', '', 'public', '', '', '', 'yaml', '', '');
INSERT INTO `config_info` (`id`, `data_id`, `group_id`, `content`, `md5`, `gmt_create`, `gmt_modified`, `src_user`, `src_ip`, `app_name`, `tenant_id`, `c_desc`, `c_use`, `effect`, `type`, `c_schema`, `encrypted_data_key`) VALUES (8, 'pigx-daemon-quartz-dev.yml', 'DEFAULT_GROUP', '# 数据源\nspring:\n datasource:\n type: com.alibaba.druid.pool.DruidDataSource\n druid:\n driver-class-name: com.mysql.cj.jdbc.Driver\n username: ${MYSQL_USER:root}\n password: ${MYSQL_PWD:root}\n url: jdbc:mysql://${MYSQL_HOST:pigx-mysql}:${MYSQL_PORT:3306}/${MYSQL_DB:pigxx_job}?characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=GMT%2B8&allowMultiQueries=true&allowPublicKeyRetrieval=true\n', 'caa1a7ea301239a18e9a43699e43707e', '2022-12-16 10:44:25', '2024-04-19 21:49:00', 'nacos', '127.0.0.1', '', 'public', '', '', '', 'yaml', '', '');
INSERT INTO `config_info` (`id`, `data_id`, `group_id`, `content`, `md5`, `gmt_create`, `gmt_modified`, `src_user`, `src_ip`, `app_name`, `tenant_id`, `c_desc`, `c_use`, `effect`, `type`, `c_schema`, `encrypted_data_key`) VALUES (9, 'pigx-pay-platform-dev.yml', 'DEFAULT_GROUP', '# 数据源\nspring:\n datasource:\n type: com.alibaba.druid.pool.DruidDataSource\n druid:\n driver-class-name: com.mysql.cj.jdbc.Driver\n username: ${MYSQL_USER:root}\n password: ${MYSQL_PWD:root}\n url: jdbc:mysql://${MYSQL_HOST:pigx-mysql}:${MYSQL_PORT:3306}/${MYSQL_DB:pigxx_pay}?characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=GMT%2B8&allowMultiQueries=true&allowPublicKeyRetrieval=true\n freemarker:\n allow-request-override: false\n allow-session-override: false\n cache: true\n charset: UTF-8\n check-template-location: true\n content-type: text/html\n enabled: true\n expose-request-attributes: false\n expose-session-attributes: false\n expose-spring-macro-helpers: true\n prefer-file-system-access: true\n suffix: .ftl\n template-loader-path: classpath:/templates/\n# 租户表维护\npigx:\n pay:\n test: lengleng\n aliPayConfig:\n expire-time: 30\n return-url: http://pig4cloud.com\n notify-url: http://payx.yunjihuitong.com/pay/notify/ali/callbak\n wxPayConfig:\n notify-url: https://admin.pig4cloud.com/pay/notify/wx/callbak\n mergePayConfig:\n return-url: http://pig4cloud.com\n notify-url: http://wechat.pigx.top/pay/notify/merge/callbak\n xsequence: #发号器相关配置\n db:\n retry-times: 3\n table-name: pay_sequence', 'f4e5734a99f3c1f059071deac081b33d', '2022-12-16 10:44:25', '2024-02-22 15:09:08', 'nacos', '127.0.0.1', '', 'public', '', '', '', 'yaml', '', '');
INSERT INTO `config_info` (`id`, `data_id`, `group_id`, `content`, `md5`, `gmt_create`, `gmt_modified`, `src_user`, `src_ip`, `app_name`, `tenant_id`, `c_desc`, `c_use`, `effect`, `type`, `c_schema`, `encrypted_data_key`) VALUES (11, 'pigx-mp-platform-dev.yml', 'DEFAULT_GROUP', '# 数据源\nspring:\n datasource:\n type: com.alibaba.druid.pool.DruidDataSource\n druid:\n driver-class-name: com.mysql.cj.jdbc.Driver\n username: ${MYSQL_USER:root}\n password: ${MYSQL_PWD:root}\n url: jdbc:mysql://${MYSQL_HOST:pigx-mysql}:${MYSQL_PORT:3306}/${MYSQL_DB:pigxx_mp}?characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=GMT%2B8&allowMultiQueries=true&allowPublicKeyRetrieval=true\n', 'ae40865200e414d06d63d96f257f372e', '2022-12-16 10:44:25', '2024-02-22 15:09:20', 'nacos', '127.0.0.1', '', 'public', '', '', '', 'yaml', '', '');
INSERT INTO `config_info` (`id`, `data_id`, `group_id`, `content`, `md5`, `gmt_create`, `gmt_modified`, `src_user`, `src_ip`, `app_name`, `tenant_id`, `c_desc`, `c_use`, `effect`, `type`, `c_schema`, `encrypted_data_key`) VALUES (12, 'pigx-xxl-job-admin-dev.yml', 'DEFAULT_GROUP', '# XXL-Job Admin 微服务配置\n# Actuator 监控配置\nmanagement:\n endpoints:\n web:\n base-path: /actuator\n health:\n mail:\n enabled: false\n\n# Spring 配置\nspring:\n # MVC 配置\n mvc:\n servlet:\n load-on-startup: 0\n static-path-pattern: /static/**\n\n # 静态资源配置\n web:\n resources:\n static-locations: classpath:/static/\n\n # Freemarker 模板引擎配置\n freemarker:\n template-loader-path: classpath:/templates/\n suffix: .ftl\n charset: UTF-8\n request-context-attribute: request\n settings:\n number_format: 0.##########\n new_builtin_class_resolver: safer\n\n # 数据源配置\n datasource:\n type: com.alibaba.druid.pool.DruidDataSource\n druid:\n driver-class-name: com.mysql.cj.jdbc.Driver\n username: ${MYSQL_USER:root}\n password: ${MYSQL_PWD:root}\n url: jdbc:mysql://${MYSQL_HOST:pigx-mysql}:${MYSQL_PORT:3306}/${MYSQL_DB:pigxx_job}?characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=GMT%2B8&allowMultiQueries=true&allowPublicKeyRetrieval=true\n\n # 邮件服务配置\n mail:\n host: smtp.qq.com\n port: 25\n username: xxx@qq.com\n from: xxx@qq.com\n password: xxx\n properties:\n mail:\n smtp:\n auth: true\n starttls:\n enable: true\n required: true\n socketFactory:\n class: javax.net.ssl.SSLSocketFactory\n\n# MyBatis 配置\nmybatis:\n mapper-locations: classpath:/mapper/**/*Mapper.xml\n\n# XXL-Job 配置\nxxl:\n job:\n # 访问令牌\n accessToken: default_token\n # 超时时间(秒)\n timeout: 3\n # 国际化 (zh_CN, zh_TC, en)\n i18n: zh_CN\n # 触发器线程池最大线程数\n triggerpool:\n fast:\n max: 300\n slow:\n max: 200\n # 调度批次大小\n schedule:\n batchsize: 100\n # 日志保留天数\n logretentiondays: 30\n\n# XXL-SSO 单点登录配置\nxxl-sso:\n token:\n key: xxl_job_login_token\n timeout: 604800000\n client:\n excluded:\n paths:\n login:\n path: /auth/login', 'e4e88bd4e91599ae03854a8dfe491786', '2022-12-16 10:44:25', '2026-05-01 23:02:41', 'nacos', '127.0.0.1', '', 'public', '', '', '', 'yaml', '', '');
INSERT INTO `config_info` (`id`, `data_id`, `group_id`, `content`, `md5`, `gmt_create`, `gmt_modified`, `src_user`, `src_ip`, `app_name`, `tenant_id`, `c_desc`, `c_use`, `effect`, `type`, `c_schema`, `encrypted_data_key`) VALUES (13, 'pigx-report-platform-dev.yml', 'DEFAULT_GROUP', 'spring:\n datasource:\n type: com.alibaba.druid.pool.DruidDataSource\n druid:\n driver-class-name: com.mysql.cj.jdbc.Driver\n username: ${MYSQL_USER:root}\n password: ${MYSQL_PWD:root}\n url: jdbc:mysql://${MYSQL_HOST:pigx-mysql}:${MYSQL_PORT:3306}/${MYSQL_DB:pigxx_report}?characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=GMT%2B8&allowMultiQueries=true&allowPublicKeyRetrieval=true\n jpa:\n database-platform: org.hibernate.dialect.MySQLDialect\n\nsecurity:\n oauth2:\n client:\n ignore-urls:\n - /\n - /api/project/getData\n - /static/**\n - /api/project/get-file/*\n\n# 文件上传路径\ngv:\n img-path: /Users/lengleng/Downloads/img/\n', 'ce3fde4b4592cdd61feb2e443b2ddfe5', '2022-12-16 10:44:25', '2023-04-07 12:56:57', 'nacos', '127.0.0.1', '', 'public', '', '', '', 'yaml', '', '');
INSERT INTO `config_info` (`id`, `data_id`, `group_id`, `content`, `md5`, `gmt_create`, `gmt_modified`, `src_user`, `src_ip`, `app_name`, `tenant_id`, `c_desc`, `c_use`, `effect`, `type`, `c_schema`, `encrypted_data_key`) VALUES (14, 'pigx-jimu-platform-dev.yml', 'DEFAULT_GROUP', 'spring:\n #配置静态资源\n mvc:\n static-path-pattern: /**\n #配置数据库\n datasource:\n type: com.alibaba.druid.pool.DruidDataSource\n druid:\n driver-class-name: com.mysql.cj.jdbc.Driver\n username: ${MYSQL_USER:root}\n password: ${MYSQL_PWD:root}\n url: jdbc:mysql://${MYSQL_HOST:pigx-mysql}:${MYSQL_PORT:3306}/${MYSQL_DB:pigxx_bi}?characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=GMT%2B8&allowMultiQueries=true&allowPublicKeyRetrieval=true\n \n#JimuReport[minidao配置]\nminidao :\n base-package: org.jeecg.modules.jmreport.*,org.jeecg.modules.drag.*\n db-type: mysql\n#JimuReport[上传配置]\njeecg :\n jmreport:\n customPrePath: /api/jimu\n # 自动保存\n autoSave: true\n # 单位毫秒 默认5*60*1000 \n interval: 10000\n # local|minio|alioss\n uploadType: local\n # local\n path :\n #文件路径A\n upload: ~/jimu/data\n # alioss\n oss:\n endpoint: oss-cn-beijing.aliyuncs.com\n accessKey: ??\n secretKey: ??\n staticDomain: ??\n bucketName: ??\n # minio\n minio:\n minio_url: http://minio.jeecg.com\n minio_name: ??\n minio_pass: ??\n bucketName: ??\n#输出sql日志\nlogging:\n level:\n org.jeecg.modules.jmreport : debug', '898d86e9ae9110a0081f7d346487fe6a', '2022-12-16 10:44:25', '2024-01-30 20:44:36', 'nacos', '127.0.0.1', '', 'public', '', '', '', 'yaml', '', '');
INSERT INTO `config_info` (`id`, `data_id`, `group_id`, `content`, `md5`, `gmt_create`, `gmt_modified`, `src_user`, `src_ip`, `app_name`, `tenant_id`, `c_desc`, `c_use`, `effect`, `type`, `c_schema`, `encrypted_data_key`) VALUES (15, 'pigx-app-server-biz-dev.yml', 'DEFAULT_GROUP', '# 数据源\nspring:\n datasource:\n type: com.alibaba.druid.pool.DruidDataSource\n druid:\n driver-class-name: com.mysql.cj.jdbc.Driver\n username: ${MYSQL_USER:root}\n password: ${MYSQL_PWD:root}\n url: jdbc:mysql://${MYSQL_HOST:pigx-mysql}:${MYSQL_PORT:3306}/${MYSQL_DB:pigxx_app}?characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=GMT%2B8&allowMultiQueries=true&allowPublicKeyRetrieval=true', 'e4668a1854e92a5a666e83479ef7d26a', '2022-12-19 10:30:07', '2024-02-22 15:09:50', 'nacos', '127.0.0.1', '', 'public', '', '', '', 'yaml', '', '');
INSERT INTO `config_info` (`id`, `data_id`, `group_id`, `content`, `md5`, `gmt_create`, `gmt_modified`, `src_user`, `src_ip`, `app_name`, `tenant_id`, `c_desc`, `c_use`, `effect`, `type`, `c_schema`, `encrypted_data_key`) VALUES (16, 'pigx-flow-biz-dev.yml', 'DEFAULT_GROUP', '# 数据源\nspring:\n datasource:\n type: com.alibaba.druid.pool.DruidDataSource\n druid:\n driver-class-name: com.mysql.cj.jdbc.Driver\n username: ${MYSQL_USER:root}\n password: ${MYSQL_PWD:root}\n url: jdbc:mysql://${MYSQL_HOST:pigx-mysql}:${MYSQL_PORT:3306}/${MYSQL_DB:pigxx_flow}?characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=GMT%2B8&allowMultiQueries=true&nullCatalogMeansCurrent=true\n\n# flowable 配置\nflowable:\n variable-json-mapper: jackson2', '233121e20445609e1ba378c3686ea7d5', '2023-07-28 13:41:32', '2023-07-28 13:43:36', 'nacos', '127.0.0.1', '', 'public', 'flowable 工作引擎', '', '', 'yaml', '', '');
COMMIT;
-- ----------------------------
-- Table structure for config_info_aggr
-- ----------------------------
DROP TABLE IF EXISTS `config_info_aggr`;
CREATE TABLE `config_info_aggr` (
`id` bigint NOT NULL AUTO_INCREMENT COMMENT 'id',
`data_id` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL COMMENT 'data_id',
`group_id` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL COMMENT 'group_id',
`datum_id` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL COMMENT 'datum_id',
`content` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL COMMENT '内容',
`gmt_modified` datetime NOT NULL COMMENT '修改时间',
`app_name` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT NULL,
`tenant_id` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT '' COMMENT '租户字段',
PRIMARY KEY (`id`) USING BTREE,
UNIQUE INDEX `uk_configinfoaggr_datagrouptenantdatum`(`data_id` ASC, `group_id` ASC, `tenant_id` ASC, `datum_id` ASC) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_bin COMMENT = '增加租户字段' ROW_FORMAT = Dynamic;
-- ----------------------------
-- Records of config_info_aggr
-- ----------------------------
-- ----------------------------
-- Table structure for config_info_beta
-- ----------------------------
DROP TABLE IF EXISTS `config_info_beta`;
CREATE TABLE `config_info_beta` (
CREATE TABLE `config_info_beta` (
`id` bigint NOT NULL AUTO_INCREMENT COMMENT 'id',
`data_id` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL COMMENT 'data_id',
`group_id` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL COMMENT 'group_id',
`app_name` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT NULL COMMENT 'app_name',
`content` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL COMMENT 'content',
`beta_ips` varchar(1024) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT NULL COMMENT 'betaIps',
`md5` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT NULL COMMENT 'md5',
`data_id` varchar(255) COLLATE utf8_bin NOT NULL COMMENT 'data_id',
`group_id` varchar(128) COLLATE utf8_bin NOT NULL COMMENT 'group_id',
`app_name` varchar(128) COLLATE utf8_bin DEFAULT NULL COMMENT 'app_name',
`content` longtext COLLATE utf8_bin NOT NULL COMMENT 'content',
`beta_ips` varchar(1024) COLLATE utf8_bin DEFAULT NULL COMMENT 'betaIps',
`md5` varchar(32) COLLATE utf8_bin DEFAULT NULL COMMENT 'md5',
`gmt_create` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`gmt_modified` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '修改时间',
`src_user` text CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL COMMENT 'source user',
`src_ip` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT NULL COMMENT 'source ip',
`tenant_id` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT '' COMMENT '租户字段',
`encrypted_data_key` text CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL COMMENT '秘钥',
PRIMARY KEY (`id`) USING BTREE,
UNIQUE INDEX `uk_configinfobeta_datagrouptenant`(`data_id` ASC, `group_id` ASC, `tenant_id` ASC) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_bin COMMENT = 'config_info_beta' ROW_FORMAT = Dynamic;
`src_user` text COLLATE utf8_bin COMMENT 'source user',
`src_ip` varchar(50) COLLATE utf8_bin DEFAULT NULL COMMENT 'source ip',
`tenant_id` varchar(128) COLLATE utf8_bin DEFAULT '' COMMENT '租户字段',
`encrypted_data_key` varchar(1024) COLLATE utf8_bin NOT NULL DEFAULT '' COMMENT '密钥',
PRIMARY KEY (`id`),
UNIQUE KEY `uk_configinfobeta_datagrouptenant` (`data_id`,`group_id`,`tenant_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='config_info_beta';
-- ----------------------------
-- Records of config_info_beta
-- ----------------------------
BEGIN;
COMMIT;
-- ----------------------------
-- Table structure for config_info_gray
-- ----------------------------
DROP TABLE IF EXISTS `config_info_gray`;
CREATE TABLE `config_info_gray` (
`id` bigint unsigned NOT NULL AUTO_INCREMENT COMMENT 'id',
`data_id` varchar(255) NOT NULL COMMENT 'data_id',
`group_id` varchar(128) NOT NULL COMMENT 'group_id',
`content` longtext NOT NULL COMMENT 'content',
`md5` varchar(32) DEFAULT NULL COMMENT 'md5',
`src_user` text COMMENT 'src_user',
`src_ip` varchar(100) DEFAULT NULL COMMENT 'src_ip',
`gmt_create` datetime(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT 'gmt_create',
`gmt_modified` datetime(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT 'gmt_modified',
`app_name` varchar(128) DEFAULT NULL COMMENT 'app_name',
`tenant_id` varchar(128) DEFAULT '' COMMENT 'tenant_id',
`gray_name` varchar(128) NOT NULL COMMENT 'gray_name',
`gray_rule` text NOT NULL COMMENT 'gray_rule',
`encrypted_data_key` varchar(256) NOT NULL DEFAULT '' COMMENT 'encrypted_data_key',
PRIMARY KEY (`id`),
UNIQUE KEY `uk_configinfogray_datagrouptenantgray` (`data_id`,`group_id`,`tenant_id`,`gray_name`),
KEY `idx_dataid_gmt_modified` (`data_id`,`gmt_modified`),
KEY `idx_gmt_modified` (`gmt_modified`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='config_info_gray';
-- ----------------------------
-- Records of config_info_gray
-- ----------------------------
BEGIN;
COMMIT;
-- ----------------------------
-- Table structure for config_info_tag
-- ----------------------------
DROP TABLE IF EXISTS `config_info_tag`;
CREATE TABLE `config_info_tag` (
CREATE TABLE `config_info_tag` (
`id` bigint NOT NULL AUTO_INCREMENT COMMENT 'id',
`data_id` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL COMMENT 'data_id',
`group_id` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL COMMENT 'group_id',
`tenant_id` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT '' COMMENT 'tenant_id',
`tag_id` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL COMMENT 'tag_id',
`app_name` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT NULL COMMENT 'app_name',
`content` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL COMMENT 'content',
`md5` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT NULL COMMENT 'md5',
`data_id` varchar(255) COLLATE utf8_bin NOT NULL COMMENT 'data_id',
`group_id` varchar(128) COLLATE utf8_bin NOT NULL COMMENT 'group_id',
`tenant_id` varchar(128) COLLATE utf8_bin DEFAULT '' COMMENT 'tenant_id',
`tag_id` varchar(128) COLLATE utf8_bin NOT NULL COMMENT 'tag_id',
`app_name` varchar(128) COLLATE utf8_bin DEFAULT NULL COMMENT 'app_name',
`content` longtext COLLATE utf8_bin NOT NULL COMMENT 'content',
`md5` varchar(32) COLLATE utf8_bin DEFAULT NULL COMMENT 'md5',
`gmt_create` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`gmt_modified` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '修改时间',
`src_user` text CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL COMMENT 'source user',
`src_ip` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT NULL COMMENT 'source ip',
PRIMARY KEY (`id`) USING BTREE,
UNIQUE INDEX `uk_configinfotag_datagrouptenanttag`(`data_id` ASC, `group_id` ASC, `tenant_id` ASC, `tag_id` ASC) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_bin COMMENT = 'config_info_tag' ROW_FORMAT = Dynamic;
`src_user` text COLLATE utf8_bin COMMENT 'source user',
`src_ip` varchar(50) COLLATE utf8_bin DEFAULT NULL COMMENT 'source ip',
PRIMARY KEY (`id`),
UNIQUE KEY `uk_configinfotag_datagrouptenanttag` (`data_id`,`group_id`,`tenant_id`,`tag_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='config_info_tag';
-- ----------------------------
-- Records of config_info_tag
-- ----------------------------
BEGIN;
COMMIT;
-- ----------------------------
-- Table structure for config_tags_relation
-- ----------------------------
DROP TABLE IF EXISTS `config_tags_relation`;
CREATE TABLE `config_tags_relation` (
CREATE TABLE `config_tags_relation` (
`id` bigint NOT NULL COMMENT 'id',
`tag_name` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL COMMENT 'tag_name',
`tag_type` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT NULL COMMENT 'tag_type',
`data_id` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL COMMENT 'data_id',
`group_id` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL COMMENT 'group_id',
`tenant_id` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT '' COMMENT 'tenant_id',
`nid` bigint NOT NULL AUTO_INCREMENT,
PRIMARY KEY (`nid`) USING BTREE,
UNIQUE INDEX `uk_configtagrelation_configidtag`(`id` ASC, `tag_name` ASC, `tag_type` ASC) USING BTREE,
INDEX `idx_tenant_id`(`tenant_id` ASC) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_bin COMMENT = 'config_tag_relation' ROW_FORMAT = Dynamic;
`tag_name` varchar(128) COLLATE utf8_bin NOT NULL COMMENT 'tag_name',
`tag_type` varchar(64) COLLATE utf8_bin DEFAULT NULL COMMENT 'tag_type',
`data_id` varchar(255) COLLATE utf8_bin NOT NULL COMMENT 'data_id',
`group_id` varchar(128) COLLATE utf8_bin NOT NULL COMMENT 'group_id',
`tenant_id` varchar(128) COLLATE utf8_bin DEFAULT '' COMMENT 'tenant_id',
`nid` bigint NOT NULL AUTO_INCREMENT COMMENT 'nid, 自增长标识',
PRIMARY KEY (`nid`),
UNIQUE KEY `uk_configtagrelation_configidtag` (`id`,`tag_name`,`tag_type`),
KEY `idx_tenant_id` (`tenant_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='config_tag_relation';
-- ----------------------------
-- Records of config_tags_relation
-- ----------------------------
BEGIN;
COMMIT;
-- ----------------------------
-- Table structure for group_capacity
-- ----------------------------
DROP TABLE IF EXISTS `group_capacity`;
CREATE TABLE `group_capacity` (
`id` bigint UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主键ID',
`group_id` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL DEFAULT '' COMMENT 'Group ID,空字符表示整个集群',
`quota` int UNSIGNED NOT NULL DEFAULT 0 COMMENT '配额,0表示使用默认值',
`usage` int UNSIGNED NOT NULL DEFAULT 0 COMMENT '使用量',
`max_size` int UNSIGNED NOT NULL DEFAULT 0 COMMENT '单个配置大小上限,单位为字节,0表示使用默认值',
`max_aggr_count` int UNSIGNED NOT NULL DEFAULT 0 COMMENT '聚合子配置最大个数,,0表示使用默认值',
`max_aggr_size` int UNSIGNED NOT NULL DEFAULT 0 COMMENT '单个聚合数据的子配置大小上限,单位为字节,0表示使用默认值',
`max_history_count` int UNSIGNED NOT NULL DEFAULT 0 COMMENT '最大变更历史数量',
CREATE TABLE `group_capacity` (
`id` bigint unsigned NOT NULL AUTO_INCREMENT COMMENT '主键ID',
`group_id` varchar(128) COLLATE utf8_bin NOT NULL DEFAULT '' COMMENT 'Group ID,空字符表示整个集群',
`quota` int unsigned NOT NULL DEFAULT '0' COMMENT '配额,0表示使用默认值',
`usage` int unsigned NOT NULL DEFAULT '0' COMMENT '使用量',
`max_size` int unsigned NOT NULL DEFAULT '0' COMMENT '单个配置大小上限,单位为字节,0表示使用默认值',
`max_aggr_count` int unsigned NOT NULL DEFAULT '0' COMMENT '聚合子配置最大个数,,0表示使用默认值',
`max_aggr_size` int unsigned NOT NULL DEFAULT '0' COMMENT '单个聚合数据的子配置大小上限,单位为字节,0表示使用默认值',
`max_history_count` int unsigned NOT NULL DEFAULT '0' COMMENT '最大变更历史数量',
`gmt_create` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`gmt_modified` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '修改时间',
PRIMARY KEY (`id`) USING BTREE,
UNIQUE INDEX `uk_group_id`(`group_id` ASC) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_bin COMMENT = '集群、各Group容量信息表' ROW_FORMAT = Dynamic;
PRIMARY KEY (`id`),
UNIQUE KEY `uk_group_id` (`group_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='集群、各Group容量信息表';
-- ----------------------------
-- Records of group_capacity
-- ----------------------------
BEGIN;
COMMIT;
-- ----------------------------
-- Table structure for his_config_info
-- ----------------------------
DROP TABLE IF EXISTS `his_config_info`;
CREATE TABLE `his_config_info` (
`id` bigint UNSIGNED NOT NULL,
`nid` bigint UNSIGNED NOT NULL AUTO_INCREMENT,
`data_id` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL,
`group_id` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL,
`app_name` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT NULL COMMENT 'app_name',
`content` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL,
`md5` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT NULL,
`gmt_create` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
`gmt_modified` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
`src_user` text CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL,
`src_ip` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT NULL,
`op_type` char(10) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT NULL,
`tenant_id` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT '' COMMENT '租户字段',
`encrypted_data_key` text CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL COMMENT '秘钥',
PRIMARY KEY (`nid`) USING BTREE,
INDEX `idx_gmt_create`(`gmt_create` ASC) USING BTREE,
INDEX `idx_gmt_modified`(`gmt_modified` ASC) USING BTREE,
INDEX `idx_did`(`data_id` ASC) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 23 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_bin COMMENT = '多租户改造' ROW_FORMAT = Dynamic;
CREATE TABLE `his_config_info` (
`id` bigint unsigned NOT NULL COMMENT 'id',
`nid` bigint unsigned NOT NULL AUTO_INCREMENT COMMENT 'nid, 自增标识',
`data_id` varchar(255) COLLATE utf8_bin NOT NULL COMMENT 'data_id',
`group_id` varchar(128) COLLATE utf8_bin NOT NULL COMMENT 'group_id',
`app_name` varchar(128) COLLATE utf8_bin DEFAULT NULL COMMENT 'app_name',
`content` longtext COLLATE utf8_bin NOT NULL COMMENT 'content',
`md5` varchar(32) COLLATE utf8_bin DEFAULT NULL COMMENT 'md5',
`gmt_create` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`gmt_modified` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '修改时间',
`src_user` text COLLATE utf8_bin COMMENT 'source user',
`src_ip` varchar(50) COLLATE utf8_bin DEFAULT NULL COMMENT 'source ip',
`op_type` char(10) COLLATE utf8_bin DEFAULT NULL COMMENT 'operation type',
`tenant_id` varchar(128) COLLATE utf8_bin DEFAULT '' COMMENT '租户字段',
`encrypted_data_key` varchar(1024) COLLATE utf8_bin NOT NULL DEFAULT '' COMMENT '密钥',
`publish_type` varchar(50) COLLATE utf8_bin DEFAULT 'formal' COMMENT 'publish type gray or formal',
`gray_name` varchar(50) COLLATE utf8_bin DEFAULT NULL COMMENT 'gray name',
`ext_info` longtext COLLATE utf8_bin COMMENT 'ext info',
PRIMARY KEY (`nid`),
KEY `idx_gmt_create` (`gmt_create`),
KEY `idx_gmt_modified` (`gmt_modified`),
KEY `idx_did` (`data_id`)
) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='多租户改造';
-- ----------------------------
-- Table structure for permissions
-- ----------------------------
DROP TABLE IF EXISTS `permissions`;
CREATE TABLE `permissions` (
`role` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
`resource` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
`action` varchar(8) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
UNIQUE INDEX `uk_role_permission`(`role` ASC, `resource` ASC, `action` ASC) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic;
CREATE TABLE `permissions` (
`role` varchar(50) NOT NULL COMMENT 'role',
`resource` varchar(128) NOT NULL COMMENT 'resource',
`action` varchar(8) NOT NULL COMMENT 'action',
UNIQUE KEY `uk_role_permission` (`role`,`resource`,`action`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- ----------------------------
-- Records of permissions
-- ----------------------------
BEGIN;
COMMIT;
-- ----------------------------
-- Table structure for roles
-- ----------------------------
DROP TABLE IF EXISTS `roles`;
CREATE TABLE `roles` (
`username` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
`role` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
UNIQUE INDEX `idx_user_role`(`username` ASC, `role` ASC) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic;
CREATE TABLE `roles` (
`username` varchar(50) NOT NULL COMMENT 'username',
`role` varchar(50) NOT NULL COMMENT 'role',
UNIQUE KEY `idx_user_role` (`username`,`role`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- ----------------------------
-- Records of roles
-- ----------------------------
INSERT INTO `roles` VALUES ('nacos', 'ROLE_ADMIN');
BEGIN;
INSERT INTO `roles` (`username`, `role`) VALUES ('nacos', 'ROLE_ADMIN');
COMMIT;
-- ----------------------------
-- Table structure for tenant_capacity
-- ----------------------------
DROP TABLE IF EXISTS `tenant_capacity`;
CREATE TABLE `tenant_capacity` (
`id` bigint UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主键ID',
`tenant_id` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL DEFAULT '' COMMENT 'Tenant ID',
`quota` int UNSIGNED NOT NULL DEFAULT 0 COMMENT '配额,0表示使用默认值',
`usage` int UNSIGNED NOT NULL DEFAULT 0 COMMENT '使用量',
`max_size` int UNSIGNED NOT NULL DEFAULT 0 COMMENT '单个配置大小上限,单位为字节,0表示使用默认值',
`max_aggr_count` int UNSIGNED NOT NULL DEFAULT 0 COMMENT '聚合子配置最大个数',
`max_aggr_size` int UNSIGNED NOT NULL DEFAULT 0 COMMENT '单个聚合数据的子配置大小上限,单位为字节,0表示使用默认值',
`max_history_count` int UNSIGNED NOT NULL DEFAULT 0 COMMENT '最大变更历史数量',
CREATE TABLE `tenant_capacity` (
`id` bigint unsigned NOT NULL AUTO_INCREMENT COMMENT '主键ID',
`tenant_id` varchar(128) COLLATE utf8_bin NOT NULL DEFAULT '' COMMENT 'Tenant ID',
`quota` int unsigned NOT NULL DEFAULT '0' COMMENT '配额,0表示使用默认值',
`usage` int unsigned NOT NULL DEFAULT '0' COMMENT '使用量',
`max_size` int unsigned NOT NULL DEFAULT '0' COMMENT '单个配置大小上限,单位为字节,0表示使用默认值',
`max_aggr_count` int unsigned NOT NULL DEFAULT '0' COMMENT '聚合子配置最大个数',
`max_aggr_size` int unsigned NOT NULL DEFAULT '0' COMMENT '单个聚合数据的子配置大小上限,单位为字节,0表示使用默认值',
`max_history_count` int unsigned NOT NULL DEFAULT '0' COMMENT '最大变更历史数量',
`gmt_create` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`gmt_modified` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '修改时间',
PRIMARY KEY (`id`) USING BTREE,
UNIQUE INDEX `uk_tenant_id`(`tenant_id` ASC) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_bin COMMENT = '租户容量信息表' ROW_FORMAT = Dynamic;
PRIMARY KEY (`id`),
UNIQUE KEY `uk_tenant_id` (`tenant_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='租户容量信息表';
-- ----------------------------
-- Records of tenant_capacity
-- ----------------------------
BEGIN;
COMMIT;
-- ----------------------------
-- Table structure for tenant_info
-- ----------------------------
DROP TABLE IF EXISTS `tenant_info`;
CREATE TABLE `tenant_info` (
CREATE TABLE `tenant_info` (
`id` bigint NOT NULL AUTO_INCREMENT COMMENT 'id',
`kp` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL COMMENT 'kp',
`tenant_id` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT '' COMMENT 'tenant_id',
`tenant_name` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT '' COMMENT 'tenant_name',
`tenant_desc` varchar(256) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT NULL COMMENT 'tenant_desc',
`create_source` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT NULL COMMENT 'create_source',
`kp` varchar(128) COLLATE utf8_bin NOT NULL COMMENT 'kp',
`tenant_id` varchar(128) COLLATE utf8_bin DEFAULT '' COMMENT 'tenant_id',
`tenant_name` varchar(128) COLLATE utf8_bin DEFAULT '' COMMENT 'tenant_name',
`tenant_desc` varchar(256) COLLATE utf8_bin DEFAULT NULL COMMENT 'tenant_desc',
`create_source` varchar(32) COLLATE utf8_bin DEFAULT NULL COMMENT 'create_source',
`gmt_create` bigint NOT NULL COMMENT '创建时间',
`gmt_modified` bigint NOT NULL COMMENT '修改时间',
PRIMARY KEY (`id`) USING BTREE,
UNIQUE INDEX `uk_tenant_info_kptenantid`(`kp` ASC, `tenant_id` ASC) USING BTREE,
INDEX `idx_tenant_id`(`tenant_id` ASC) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_bin COMMENT = 'tenant_info' ROW_FORMAT = Dynamic;
PRIMARY KEY (`id`),
UNIQUE KEY `uk_tenant_info_kptenantid` (`kp`,`tenant_id`),
KEY `idx_tenant_id` (`tenant_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='tenant_info';
-- ----------------------------
-- Records of tenant_info
-- ----------------------------
BEGIN;
COMMIT;
-- ----------------------------
-- Table structure for users
-- ----------------------------
DROP TABLE IF EXISTS `users`;
CREATE TABLE `users` (
`username` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
`password` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
`enabled` tinyint(1) NOT NULL,
PRIMARY KEY (`username`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic;
CREATE TABLE `users` (
`username` varchar(50) NOT NULL COMMENT 'username',
`password` varchar(500) NOT NULL COMMENT 'password',
`enabled` tinyint(1) NOT NULL COMMENT 'enabled',
PRIMARY KEY (`username`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- ----------------------------
-- Records of users
-- ----------------------------
INSERT INTO `users` VALUES ('nacos', '$2a$10$EuWPZHzz32dJN7jexM34MOeYirDdFAZm2kuWj7VEOJhhZkDrxfvUu', 1);
BEGIN;
INSERT INTO `users` (`username`, `password`, `enabled`) VALUES ('nacos', '$2a$10$W6PKgRTzXUp6R/NY853Kn.nRaIcX3whIMTZ/WWkNqo2MTOeSBjKJq', 1);
COMMIT;
-- ----------------------------
-- Table structure for pipeline_execution
-- ----------------------------
DROP TABLE IF EXISTS `pipeline_execution`;
CREATE TABLE `pipeline_execution` (
`execution_id` varchar(64) NOT NULL COMMENT '执行ID',
`resource_type` varchar(32) NOT NULL COMMENT '资源类型',
`resource_name` varchar(256) NOT NULL COMMENT '资源名称',
`namespace_id` varchar(128) DEFAULT NULL COMMENT '命名空间ID',
`version` varchar(64) DEFAULT NULL COMMENT '版本',
`status` varchar(32) NOT NULL COMMENT '执行状态',
`pipeline` longtext NOT NULL COMMENT 'pipeline节点结果JSON',
`create_time` bigint(20) NOT NULL COMMENT '创建时间',
`update_time` bigint(20) NOT NULL COMMENT '修改时间',
PRIMARY KEY (`execution_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='AI资源发布审核Pipeline执行记录';
-- ----------------------------
-- Table structure for ai_resource
-- ----------------------------
DROP TABLE IF EXISTS `ai_resource`;
CREATE TABLE `ai_resource` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id',
`gmt_create` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`gmt_modified` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '修改时间',
`name` varchar(256) NOT NULL COMMENT '资源名称',
`type` varchar(32) NOT NULL COMMENT '资源类型',
`c_desc` varchar(2048) DEFAULT NULL COMMENT '资源描述',
`status` varchar(32) DEFAULT NULL COMMENT '资源状态',
`namespace_id` varchar(128) NOT NULL DEFAULT '' COMMENT '命名空间ID',
`biz_tags` varchar(1024) DEFAULT NULL COMMENT '业务标签',
`ext` longtext DEFAULT NULL COMMENT '扩展信息(JSON)',
`c_from` varchar(256) NOT NULL DEFAULT 'local' COMMENT '来源标识(导入/同步来源)',
`version_info` longtext DEFAULT NULL COMMENT '版本信息(JSON)',
`meta_version` bigint(20) NOT NULL DEFAULT 1 COMMENT '元数据版本(乐观锁)',
`scope` varchar(16) NOT NULL DEFAULT 'PRIVATE' COMMENT '可见性: PUBLIC/PRIVATE',
`owner` varchar(128) NOT NULL DEFAULT '' COMMENT '创建者用户名',
`download_count` bigint(20) NOT NULL DEFAULT 0 COMMENT '下载次数',
PRIMARY KEY (`id`),
UNIQUE KEY `uk_ai_resource_ns_name_type` (`namespace_id`,`name`,`type`,`c_from`),
KEY `idx_ai_resource_name` (`name`),
KEY `idx_ai_resource_type` (`type`),
KEY `idx_ai_resource_gmt_modified` (`gmt_modified`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='AI资源元数据表';
-- ----------------------------
-- Table structure for ai_resource_version
-- ----------------------------
DROP TABLE IF EXISTS `ai_resource_version`;
CREATE TABLE `ai_resource_version` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id',
`gmt_create` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`gmt_modified` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '修改时间',
`type` varchar(32) NOT NULL COMMENT '资源类型',
`author` varchar(128) DEFAULT NULL COMMENT '作者',
`name` varchar(256) NOT NULL COMMENT '资源名称',
`c_desc` varchar(2048) DEFAULT NULL COMMENT '版本描述',
`status` varchar(32) NOT NULL COMMENT '版本状态',
`version` varchar(64) NOT NULL COMMENT '版本号',
`namespace_id` varchar(128) NOT NULL DEFAULT '' COMMENT '命名空间ID',
`storage` longtext DEFAULT NULL COMMENT '存储信息(JSON)',
`publish_pipeline_info` longtext DEFAULT NULL COMMENT '发布流水线信息(JSON)',
`download_count` bigint(20) NOT NULL DEFAULT 0 COMMENT '下载次数',
PRIMARY KEY (`id`),
UNIQUE KEY `uk_ai_resource_ver_ns_name_type_ver` (`namespace_id`,`name`,`type`,`version`),
KEY `idx_ai_resource_ver_name` (`name`),
KEY `idx_ai_resource_ver_status` (`status`),
KEY `idx_ai_resource_ver_gmt_modified` (`gmt_modified`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='AI资源版本表';
SET FOREIGN_KEY_CHECKS = 1;
+9 -9
View File
@@ -19,8 +19,8 @@ CREATE TABLE `pay_channel` (
`param` mediumtext CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci COMMENT '参数',
`remark` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '备注',
`del_flag` char(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT '0' COMMENT '删除标志',
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`tenant_id` bigint(20) DEFAULT NULL COMMENT '租户ID',
`app_id` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '应用ID',
PRIMARY KEY (`id`) USING BTREE
@@ -45,8 +45,8 @@ CREATE TABLE `pay_goods_order` (
`status` varchar(4) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '0' COMMENT '订单状态:订单生成(0)、支付成功(1)、处理完成(2)、处理失败(-1)',
`pay_order_id` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '支付订单ID',
`del_flag` char(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT '0' COMMENT '删除标志',
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`tenant_id` bigint(20) DEFAULT NULL COMMENT '租户ID',
PRIMARY KEY (`goods_order_id`) USING BTREE,
UNIQUE KEY `IDX_PayOrderId` (`pay_order_id`) USING BTREE
@@ -70,7 +70,7 @@ CREATE TABLE `pay_notify_record` (
`order_no` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '订单号',
`http_status` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT 'http状态',
`del_flag` char(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT '0' COMMENT '删除标志',
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`tenant_id` bigint(20) DEFAULT NULL COMMENT '租户ID',
PRIMARY KEY (`id`) USING BTREE
@@ -114,8 +114,8 @@ CREATE TABLE `pay_refund_order` (
`expire_time` datetime DEFAULT NULL COMMENT '订单失效时间',
`refund_succ_time` datetime DEFAULT NULL COMMENT '订单退款成功时间',
`del_flag` char(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT '0' COMMENT '删除标志',
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`tenant_id` bigint(20) DEFAULT NULL COMMENT '租户ID',
PRIMARY KEY (`refund_order_id`) USING BTREE,
UNIQUE KEY `IDX_MchId_MchOrderNo` (`mch_id`,`mch_refund_no`) USING BTREE
@@ -153,8 +153,8 @@ CREATE TABLE `pay_trade_order` (
`last_notify_time` bigint(20) DEFAULT NULL COMMENT '最后一次通知时间',
`expire_time` bigint(20) DEFAULT NULL COMMENT '订单失效时间',
`pay_succ_time` datetime DEFAULT NULL COMMENT '订单支付成功时间',
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`del_flag` char(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT '0' COMMENT '删除标志',
`tenant_id` bigint(20) DEFAULT NULL COMMENT '租户ID',
PRIMARY KEY (`order_id`) USING BTREE
+159 -108
View File
@@ -10,7 +10,7 @@ DROP TABLE IF EXISTS `gen_datasource_conf`;
CREATE TABLE `gen_datasource_conf` (
`id` bigint NOT NULL COMMENT '主键',
`name` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '别名',
`url` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT 'jdbcurl',
`url` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT 'jdbcurl',
`username` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '用户名',
`password` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '密码',
`create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
@@ -41,6 +41,8 @@ CREATE TABLE `gen_field_type` (
`column_type` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '字段类型',
`attr_type` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '属性类型',
`package_name` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '属性包名',
`default_form_type` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '默认表单类型',
`default_query_form_type` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '默认查询表单类型',
`create_time` datetime DEFAULT NULL COMMENT '创建时间',
`create_by` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '创建人',
`update_time` datetime DEFAULT NULL COMMENT '修改时间',
@@ -54,61 +56,55 @@ CREATE TABLE `gen_field_type` (
-- Records of gen_field_type
-- ----------------------------
BEGIN;
INSERT INTO `gen_field_type` VALUES (1, 'datetime', 'LocalDateTime', 'java.time.LocalDateTime', '2023-02-06 08:45:10', NULL, NULL, NULL, '0');
INSERT INTO `gen_field_type` VALUES (2, 'date', 'LocalDate', 'java.time.LocalDate', '2023-02-06 08:45:10', NULL, NULL, NULL, '0');
INSERT INTO `gen_field_type` VALUES (3, 'tinyint', 'Integer', NULL, '2023-02-06 08:45:11', NULL, NULL, NULL, '0');
INSERT INTO `gen_field_type` VALUES (4, 'smallint', 'Integer', NULL, '2023-02-06 08:45:11', NULL, NULL, NULL, '0');
INSERT INTO `gen_field_type` VALUES (5, 'mediumint', 'Integer', NULL, '2023-02-06 08:45:11', NULL, NULL, NULL, '0');
INSERT INTO `gen_field_type` VALUES (6, 'int', 'Integer', NULL, '2023-02-06 08:45:11', NULL, NULL, NULL, '0');
INSERT INTO `gen_field_type` VALUES (7, 'integer', 'Integer', NULL, '2023-02-06 08:45:11', NULL, NULL, NULL, '0');
INSERT INTO `gen_field_type` VALUES (8, 'bigint', 'Long', NULL, '2023-02-06 08:45:11', NULL, NULL, NULL, '0');
INSERT INTO `gen_field_type` VALUES (9, 'float', 'Float', NULL, '2023-02-06 08:45:11', NULL, NULL, NULL, '0');
INSERT INTO `gen_field_type` VALUES (10, 'double', 'Double', NULL, '2023-02-06 08:45:11', NULL, NULL, NULL, '0');
INSERT INTO `gen_field_type` VALUES (11, 'decimal', 'BigDecimal', 'java.math.BigDecimal', '2023-02-06 08:45:11', NULL, NULL, NULL, '0');
INSERT INTO `gen_field_type` VALUES (12, 'bit', 'Boolean', NULL, '2023-02-06 08:45:11', NULL, NULL, NULL, '0');
INSERT INTO `gen_field_type` VALUES (13, 'char', 'String', NULL, '2023-02-06 08:45:11', NULL, NULL, NULL, '0');
INSERT INTO `gen_field_type` VALUES (14, 'varchar', 'String', NULL, '2023-02-06 08:45:11', NULL, NULL, NULL, '0');
INSERT INTO `gen_field_type` VALUES (15, 'tinytext', 'String', NULL, '2023-02-06 08:45:11', NULL, NULL, NULL, '0');
INSERT INTO `gen_field_type` VALUES (16, 'text', 'String', NULL, '2023-02-06 08:45:11', NULL, NULL, NULL, '0');
INSERT INTO `gen_field_type` VALUES (17, 'mediumtext', 'String', NULL, '2023-02-06 08:45:11', NULL, NULL, NULL, '0');
INSERT INTO `gen_field_type` VALUES (18, 'longtext', 'String', NULL, '2023-02-06 08:45:11', NULL, NULL, NULL, '0');
INSERT INTO `gen_field_type` VALUES (19, 'timestamp', 'LocalDateTime', 'java.time.LocalDateTime', '2023-02-06 08:45:11', NULL, NULL, NULL, '0');
INSERT INTO `gen_field_type` VALUES (20, 'NUMBER', 'Integer', NULL, '2023-02-06 08:45:11', NULL, NULL, NULL, '0');
INSERT INTO `gen_field_type` VALUES (21, 'BINARY_INTEGER', 'Integer', NULL, '2023-02-06 08:45:12', NULL, NULL, NULL, '0');
INSERT INTO `gen_field_type` VALUES (22, 'BINARY_FLOAT', 'Float', NULL, '2023-02-06 08:45:12', NULL, NULL, NULL, '0');
INSERT INTO `gen_field_type` VALUES (23, 'BINARY_DOUBLE', 'Double', NULL, '2023-02-06 08:45:12', NULL, NULL, NULL, '0');
INSERT INTO `gen_field_type` VALUES (24, 'VARCHAR2', 'String', NULL, '2023-02-06 08:45:12', NULL, NULL, NULL, '0');
INSERT INTO `gen_field_type` VALUES (25, 'NVARCHAR', 'String', NULL, '2023-02-06 08:45:12', NULL, NULL, NULL, '0');
INSERT INTO `gen_field_type` VALUES (26, 'NVARCHAR2', 'String', NULL, '2023-02-06 08:45:12', NULL, NULL, NULL, '0');
INSERT INTO `gen_field_type` VALUES (27, 'CLOB', 'String', NULL, '2023-02-06 08:45:12', NULL, NULL, NULL, '0');
INSERT INTO `gen_field_type` VALUES (28, 'int8', 'Long', NULL, '2023-02-06 08:45:12', NULL, NULL, NULL, '0');
INSERT INTO `gen_field_type` VALUES (29, 'int4', 'Integer', NULL, '2023-02-06 08:45:12', NULL, NULL, NULL, '0');
INSERT INTO `gen_field_type` VALUES (30, 'int2', 'Integer', NULL, '2023-02-06 08:45:12', NULL, NULL, NULL, '0');
INSERT INTO `gen_field_type` VALUES (31, 'numeric', 'BigDecimal', 'java.math.BigDecimal', '2023-02-06 08:45:12', NULL, NULL, NULL, '0');
INSERT INTO `gen_field_type` VALUES (32, 'json', 'String', NULL, '2023-02-06 08:45:12', NULL, NULL, NULL, '0');
COMMIT;
-- ----------------------------
-- Table structure for gen_form_conf
-- ----------------------------
DROP TABLE IF EXISTS `gen_form_conf`;
CREATE TABLE `gen_form_conf` (
`id` bigint NOT NULL COMMENT 'ID',
`ds_name` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '数据库名称',
`table_name` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '表名称',
`form_info` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '表单信息',
`create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间',
`del_flag` char(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT '0',
`tenant_id` bigint DEFAULT NULL COMMENT '所属租户',
PRIMARY KEY (`id`) USING BTREE,
KEY `table_name` (`table_name`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='表单配置';
-- ----------------------------
-- Records of gen_form_conf
-- ----------------------------
BEGIN;
INSERT INTO `gen_field_type` (`id`, `column_type`, `attr_type`, `package_name`, `default_form_type`, `default_query_form_type`, `create_time`, `create_by`, `update_time`, `update_by`, `del_flag`) VALUES (1,'datetime','LocalDateTime','java.time.LocalDateTime','datetime','datetimerange','2023-02-06 08:45:10',NULL,NULL,NULL,'0');
INSERT INTO `gen_field_type` (`id`, `column_type`, `attr_type`, `package_name`, `default_form_type`, `default_query_form_type`, `create_time`, `create_by`, `update_time`, `update_by`, `del_flag`) VALUES (2,'date','LocalDate','java.time.LocalDate','date','daterange','2023-02-06 08:45:10',NULL,NULL,NULL,'0');
INSERT INTO `gen_field_type` (`id`, `column_type`, `attr_type`, `package_name`, `default_form_type`, `default_query_form_type`, `create_time`, `create_by`, `update_time`, `update_by`, `del_flag`) VALUES (3,'tinyint','Integer',NULL,'number','number','2023-02-06 08:45:11',NULL,NULL,NULL,'0');
INSERT INTO `gen_field_type` (`id`, `column_type`, `attr_type`, `package_name`, `default_form_type`, `default_query_form_type`, `create_time`, `create_by`, `update_time`, `update_by`, `del_flag`) VALUES (4,'smallint','Integer',NULL,'number','number','2023-02-06 08:45:11',NULL,NULL,NULL,'0');
INSERT INTO `gen_field_type` (`id`, `column_type`, `attr_type`, `package_name`, `default_form_type`, `default_query_form_type`, `create_time`, `create_by`, `update_time`, `update_by`, `del_flag`) VALUES (5,'mediumint','Integer',NULL,'number','number','2023-02-06 08:45:11',NULL,NULL,NULL,'0');
INSERT INTO `gen_field_type` (`id`, `column_type`, `attr_type`, `package_name`, `default_form_type`, `default_query_form_type`, `create_time`, `create_by`, `update_time`, `update_by`, `del_flag`) VALUES (6,'int','Integer',NULL,'number','number','2023-02-06 08:45:11',NULL,NULL,NULL,'0');
INSERT INTO `gen_field_type` (`id`, `column_type`, `attr_type`, `package_name`, `default_form_type`, `default_query_form_type`, `create_time`, `create_by`, `update_time`, `update_by`, `del_flag`) VALUES (7,'integer','Integer',NULL,'number','number','2023-02-06 08:45:11',NULL,NULL,NULL,'0');
INSERT INTO `gen_field_type` (`id`, `column_type`, `attr_type`, `package_name`, `default_form_type`, `default_query_form_type`, `create_time`, `create_by`, `update_time`, `update_by`, `del_flag`) VALUES (8,'bigint','Long',NULL,'number','number','2023-02-06 08:45:11',NULL,NULL,NULL,'0');
INSERT INTO `gen_field_type` (`id`, `column_type`, `attr_type`, `package_name`, `default_form_type`, `default_query_form_type`, `create_time`, `create_by`, `update_time`, `update_by`, `del_flag`) VALUES (9,'float','Float',NULL,'number','number','2023-02-06 08:45:11',NULL,NULL,NULL,'0');
INSERT INTO `gen_field_type` (`id`, `column_type`, `attr_type`, `package_name`, `default_form_type`, `default_query_form_type`, `create_time`, `create_by`, `update_time`, `update_by`, `del_flag`) VALUES (10,'double','Double',NULL,'number','number','2023-02-06 08:45:11',NULL,NULL,NULL,'0');
INSERT INTO `gen_field_type` (`id`, `column_type`, `attr_type`, `package_name`, `default_form_type`, `default_query_form_type`, `create_time`, `create_by`, `update_time`, `update_by`, `del_flag`) VALUES (11,'decimal','BigDecimal','java.math.BigDecimal','number','number','2023-02-06 08:45:11',NULL,NULL,NULL,'0');
INSERT INTO `gen_field_type` (`id`, `column_type`, `attr_type`, `package_name`, `default_form_type`, `default_query_form_type`, `create_time`, `create_by`, `update_time`, `update_by`, `del_flag`) VALUES (12,'bit','Boolean',NULL,'radio','radio','2023-02-06 08:45:11',NULL,NULL,NULL,'0');
INSERT INTO `gen_field_type` (`id`, `column_type`, `attr_type`, `package_name`, `default_form_type`, `default_query_form_type`, `create_time`, `create_by`, `update_time`, `update_by`, `del_flag`) VALUES (13,'char','String',NULL,'radio','radio','2023-02-06 08:45:11',NULL,NULL,NULL,'0');
INSERT INTO `gen_field_type` (`id`, `column_type`, `attr_type`, `package_name`, `default_form_type`, `default_query_form_type`, `create_time`, `create_by`, `update_time`, `update_by`, `del_flag`) VALUES (14,'varchar','String',NULL,'text','text','2023-02-06 08:45:11',NULL,NULL,NULL,'0');
INSERT INTO `gen_field_type` (`id`, `column_type`, `attr_type`, `package_name`, `default_form_type`, `default_query_form_type`, `create_time`, `create_by`, `update_time`, `update_by`, `del_flag`) VALUES (15,'tinytext','String',NULL,'textarea','text','2023-02-06 08:45:11',NULL,NULL,NULL,'0');
INSERT INTO `gen_field_type` (`id`, `column_type`, `attr_type`, `package_name`, `default_form_type`, `default_query_form_type`, `create_time`, `create_by`, `update_time`, `update_by`, `del_flag`) VALUES (16,'text','String',NULL,'textarea','text','2023-02-06 08:45:11',NULL,NULL,NULL,'0');
INSERT INTO `gen_field_type` (`id`, `column_type`, `attr_type`, `package_name`, `default_form_type`, `default_query_form_type`, `create_time`, `create_by`, `update_time`, `update_by`, `del_flag`) VALUES (17,'mediumtext','String',NULL,'textarea','text','2023-02-06 08:45:11',NULL,NULL,NULL,'0');
INSERT INTO `gen_field_type` (`id`, `column_type`, `attr_type`, `package_name`, `default_form_type`, `default_query_form_type`, `create_time`, `create_by`, `update_time`, `update_by`, `del_flag`) VALUES (18,'longtext','String',NULL,'textarea','text','2023-02-06 08:45:11',NULL,NULL,NULL,'0');
INSERT INTO `gen_field_type` (`id`, `column_type`, `attr_type`, `package_name`, `default_form_type`, `default_query_form_type`, `create_time`, `create_by`, `update_time`, `update_by`, `del_flag`) VALUES (19,'timestamp','LocalDateTime','java.time.LocalDateTime','datetime','datetimerange','2023-02-06 08:45:11',NULL,NULL,NULL,'0');
INSERT INTO `gen_field_type` (`id`, `column_type`, `attr_type`, `package_name`, `default_form_type`, `default_query_form_type`, `create_time`, `create_by`, `update_time`, `update_by`, `del_flag`) VALUES (20,'NUMBER','Integer',NULL,'number','number','2023-02-06 08:45:11',NULL,NULL,NULL,'0');
INSERT INTO `gen_field_type` (`id`, `column_type`, `attr_type`, `package_name`, `default_form_type`, `default_query_form_type`, `create_time`, `create_by`, `update_time`, `update_by`, `del_flag`) VALUES (21,'BINARY_INTEGER','Integer',NULL,'number','number','2023-02-06 08:45:12',NULL,NULL,NULL,'0');
INSERT INTO `gen_field_type` (`id`, `column_type`, `attr_type`, `package_name`, `default_form_type`, `default_query_form_type`, `create_time`, `create_by`, `update_time`, `update_by`, `del_flag`) VALUES (22,'BINARY_FLOAT','Float',NULL,'number','number','2023-02-06 08:45:12',NULL,NULL,NULL,'0');
INSERT INTO `gen_field_type` (`id`, `column_type`, `attr_type`, `package_name`, `default_form_type`, `default_query_form_type`, `create_time`, `create_by`, `update_time`, `update_by`, `del_flag`) VALUES (23,'BINARY_DOUBLE','Double',NULL,'number','number','2023-02-06 08:45:12',NULL,NULL,NULL,'0');
INSERT INTO `gen_field_type` (`id`, `column_type`, `attr_type`, `package_name`, `default_form_type`, `default_query_form_type`, `create_time`, `create_by`, `update_time`, `update_by`, `del_flag`) VALUES (24,'VARCHAR2','String',NULL,'text','text','2023-02-06 08:45:12',NULL,NULL,NULL,'0');
INSERT INTO `gen_field_type` (`id`, `column_type`, `attr_type`, `package_name`, `default_form_type`, `default_query_form_type`, `create_time`, `create_by`, `update_time`, `update_by`, `del_flag`) VALUES (25,'NVARCHAR','String',NULL,'text','text','2023-02-06 08:45:12',NULL,NULL,NULL,'0');
INSERT INTO `gen_field_type` (`id`, `column_type`, `attr_type`, `package_name`, `default_form_type`, `default_query_form_type`, `create_time`, `create_by`, `update_time`, `update_by`, `del_flag`) VALUES (26,'NVARCHAR2','String',NULL,'text','text','2023-02-06 08:45:12',NULL,NULL,NULL,'0');
INSERT INTO `gen_field_type` (`id`, `column_type`, `attr_type`, `package_name`, `default_form_type`, `default_query_form_type`, `create_time`, `create_by`, `update_time`, `update_by`, `del_flag`) VALUES (27,'CLOB','String',NULL,'textarea','text','2023-02-06 08:45:12',NULL,NULL,NULL,'0');
INSERT INTO `gen_field_type` (`id`, `column_type`, `attr_type`, `package_name`, `default_form_type`, `default_query_form_type`, `create_time`, `create_by`, `update_time`, `update_by`, `del_flag`) VALUES (28,'int8','Long',NULL,'number','number','2023-02-06 08:45:12',NULL,NULL,NULL,'0');
INSERT INTO `gen_field_type` (`id`, `column_type`, `attr_type`, `package_name`, `default_form_type`, `default_query_form_type`, `create_time`, `create_by`, `update_time`, `update_by`, `del_flag`) VALUES (29,'int4','Integer',NULL,'number','number','2023-02-06 08:45:12',NULL,NULL,NULL,'0');
INSERT INTO `gen_field_type` (`id`, `column_type`, `attr_type`, `package_name`, `default_form_type`, `default_query_form_type`, `create_time`, `create_by`, `update_time`, `update_by`, `del_flag`) VALUES (30,'int2','Integer',NULL,'number','number','2023-02-06 08:45:12',NULL,NULL,NULL,'0');
INSERT INTO `gen_field_type` (`id`, `column_type`, `attr_type`, `package_name`, `default_form_type`, `default_query_form_type`, `create_time`, `create_by`, `update_time`, `update_by`, `del_flag`) VALUES (31,'numeric','BigDecimal','java.math.BigDecimal','number','number','2023-02-06 08:45:12',NULL,NULL,NULL,'0');
INSERT INTO `gen_field_type` (`id`, `column_type`, `attr_type`, `package_name`, `default_form_type`, `default_query_form_type`, `create_time`, `create_by`, `update_time`, `update_by`, `del_flag`) VALUES (32,'json','String',NULL,'textarea','text','2023-02-06 08:45:12',NULL,NULL,NULL,'0');
INSERT INTO `gen_field_type` (`id`, `column_type`, `attr_type`, `package_name`, `default_form_type`, `default_query_form_type`, `create_time`, `create_by`, `update_time`, `update_by`, `del_flag`) VALUES (33,'BPCHAR','String',NULL,'text','text','2026-04-07 20:27:29',NULL,NULL,NULL,'0');
INSERT INTO `gen_field_type` (`id`, `column_type`, `attr_type`, `package_name`, `default_form_type`, `default_query_form_type`, `create_time`, `create_by`, `update_time`, `update_by`, `del_flag`) VALUES (34,'time','LocalTime','java.time.LocalTime','text','text','2026-04-07 20:47:09',NULL,'2026-04-07 20:47:09',NULL,'0');
INSERT INTO `gen_field_type` (`id`, `column_type`, `attr_type`, `package_name`, `default_form_type`, `default_query_form_type`, `create_time`, `create_by`, `update_time`, `update_by`, `del_flag`) VALUES (35,'year','Integer',NULL,'number','number','2026-04-07 20:47:09',NULL,'2026-04-07 20:47:09',NULL,'0');
INSERT INTO `gen_field_type` (`id`, `column_type`, `attr_type`, `package_name`, `default_form_type`, `default_query_form_type`, `create_time`, `create_by`, `update_time`, `update_by`, `del_flag`) VALUES (36,'enum','String',NULL,'text','text','2026-04-07 20:47:09',NULL,'2026-04-07 20:47:09',NULL,'0');
INSERT INTO `gen_field_type` (`id`, `column_type`, `attr_type`, `package_name`, `default_form_type`, `default_query_form_type`, `create_time`, `create_by`, `update_time`, `update_by`, `del_flag`) VALUES (37,'set','String',NULL,'text','text','2026-04-07 20:47:09',NULL,'2026-04-07 20:47:09',NULL,'0');
INSERT INTO `gen_field_type` (`id`, `column_type`, `attr_type`, `package_name`, `default_form_type`, `default_query_form_type`, `create_time`, `create_by`, `update_time`, `update_by`, `del_flag`) VALUES (38,'bool','Boolean',NULL,'radio','radio','2026-04-07 20:47:09',NULL,'2026-04-07 20:47:09',NULL,'0');
INSERT INTO `gen_field_type` (`id`, `column_type`, `attr_type`, `package_name`, `default_form_type`, `default_query_form_type`, `create_time`, `create_by`, `update_time`, `update_by`, `del_flag`) VALUES (39,'boolean','Boolean',NULL,'radio','radio','2026-04-07 20:47:09',NULL,'2026-04-07 20:47:09',NULL,'0');
INSERT INTO `gen_field_type` (`id`, `column_type`, `attr_type`, `package_name`, `default_form_type`, `default_query_form_type`, `create_time`, `create_by`, `update_time`, `update_by`, `del_flag`) VALUES (40,'float4','Float',NULL,'number','number','2026-04-07 20:47:09',NULL,'2026-04-07 20:47:09',NULL,'0');
INSERT INTO `gen_field_type` (`id`, `column_type`, `attr_type`, `package_name`, `default_form_type`, `default_query_form_type`, `create_time`, `create_by`, `update_time`, `update_by`, `del_flag`) VALUES (41,'float8','Double',NULL,'number','number','2026-04-07 20:47:09',NULL,'2026-04-07 20:47:09',NULL,'0');
INSERT INTO `gen_field_type` (`id`, `column_type`, `attr_type`, `package_name`, `default_form_type`, `default_query_form_type`, `create_time`, `create_by`, `update_time`, `update_by`, `del_flag`) VALUES (42,'jsonb','String',NULL,'textarea','text','2026-04-07 20:47:09',NULL,'2026-04-07 20:47:09',NULL,'0');
INSERT INTO `gen_field_type` (`id`, `column_type`, `attr_type`, `package_name`, `default_form_type`, `default_query_form_type`, `create_time`, `create_by`, `update_time`, `update_by`, `del_flag`) VALUES (43,'uuid','String',NULL,'text','text','2026-04-07 20:47:09',NULL,'2026-04-07 20:47:09',NULL,'0');
INSERT INTO `gen_field_type` (`id`, `column_type`, `attr_type`, `package_name`, `default_form_type`, `default_query_form_type`, `create_time`, `create_by`, `update_time`, `update_by`, `del_flag`) VALUES (44,'serial','Integer',NULL,'number','number','2026-04-07 20:47:09',NULL,'2026-04-07 20:47:09',NULL,'0');
INSERT INTO `gen_field_type` (`id`, `column_type`, `attr_type`, `package_name`, `default_form_type`, `default_query_form_type`, `create_time`, `create_by`, `update_time`, `update_by`, `del_flag`) VALUES (45,'bigserial','Long',NULL,'number','number','2026-04-07 20:47:09',NULL,'2026-04-07 20:47:09',NULL,'0');
INSERT INTO `gen_field_type` (`id`, `column_type`, `attr_type`, `package_name`, `default_form_type`, `default_query_form_type`, `create_time`, `create_by`, `update_time`, `update_by`, `del_flag`) VALUES (46,'smallserial','Integer',NULL,'number','number','2026-04-07 20:47:09',NULL,'2026-04-07 20:47:09',NULL,'0');
INSERT INTO `gen_field_type` (`id`, `column_type`, `attr_type`, `package_name`, `default_form_type`, `default_query_form_type`, `create_time`, `create_by`, `update_time`, `update_by`, `del_flag`) VALUES (47,'timestamptz','LocalDateTime','java.time.LocalDateTime','datetime','datetimerange','2026-04-07 20:47:09',NULL,'2026-04-07 20:47:09',NULL,'0');
INSERT INTO `gen_field_type` (`id`, `column_type`, `attr_type`, `package_name`, `default_form_type`, `default_query_form_type`, `create_time`, `create_by`, `update_time`, `update_by`, `del_flag`) VALUES (48,'timetz','String',NULL,'text','text','2026-04-07 20:47:09',NULL,'2026-04-07 20:47:09',NULL,'0');
INSERT INTO `gen_field_type` (`id`, `column_type`, `attr_type`, `package_name`, `default_form_type`, `default_query_form_type`, `create_time`, `create_by`, `update_time`, `update_by`, `del_flag`) VALUES (49,'bytea','String',NULL,'textarea','text','2026-04-07 20:47:09',NULL,'2026-04-07 20:47:09',NULL,'0');
COMMIT;
-- ----------------------------
@@ -120,8 +116,8 @@ CREATE TABLE `gen_group` (
`group_name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '分组名称',
`group_desc` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '分组描述',
`tenant_id` bigint NOT NULL COMMENT '租户ID',
`create_by` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT ' ' COMMENT '创建人',
`update_by` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT ' ' COMMENT '修改人',
`create_by` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT ' ' COMMENT '创建人',
`update_by` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT ' ' COMMENT '修改人',
`create_time` datetime DEFAULT NULL COMMENT '创建人',
`update_time` datetime DEFAULT NULL COMMENT '修改人',
`del_flag` char(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT '0' COMMENT '删除标记',
@@ -132,8 +128,10 @@ CREATE TABLE `gen_group` (
-- Records of gen_group
-- ----------------------------
BEGIN;
INSERT INTO `gen_group` VALUES (1, '单表增删改查', '单表增删改查', 1, ' ', ' ', NULL, NULL, '0');
INSERT INTO `gen_group` VALUES (2, '主子表表增删改查', '主子表表增删改查', 1, ' ', ' ', NULL, NULL, '0');
INSERT INTO `gen_group` (`id`, `group_name`, `group_desc`, `tenant_id`, `create_by`, `update_by`, `create_time`, `update_time`, `del_flag`) VALUES (1,'单表增删改查V202611',NULL,1,'admin','admin','2026-04-08 17:38:24','2026-04-08 17:38:24','0');
INSERT INTO `gen_group` (`id`, `group_name`, `group_desc`, `tenant_id`, `create_by`, `update_by`, `create_time`, `update_time`, `del_flag`) VALUES (2,'主子表增删改查V202611',NULL,1,'admin','admin','2026-04-08 17:38:24','2026-04-08 17:38:24','0');
INSERT INTO `gen_group` (`id`, `group_name`, `group_desc`, `tenant_id`, `create_by`, `update_by`, `create_time`, `update_time`, `del_flag`) VALUES (3,'树形表格增删改查V202611',NULL,1,'admin','admin','2026-04-08 17:38:24','2026-04-08 17:38:24','0');
INSERT INTO `gen_group` (`id`, `group_name`, `group_desc`, `tenant_id`, `create_by`, `update_by`, `create_time`, `update_time`, `del_flag`) VALUES (4,'左树右表增删改查V202611',NULL,1,'admin','admin','2026-04-08 17:38:24','2026-04-08 17:38:24','0');
COMMIT;
-- ----------------------------
@@ -151,10 +149,14 @@ CREATE TABLE `gen_table` (
`package_name` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '项目包名',
`version` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '项目版本号',
`i18n` char(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT '0' COMMENT '是否生成带有i18n 0 不带有 1带有',
`style` bigint DEFAULT '1' COMMENT '代码风格',
`style` bigint DEFAULT NULL COMMENT '代码风格',
`sync_menu_id` bigint DEFAULT NULL COMMENT '所属菜单ID',
`sync_route` char(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT '0' COMMENT '是否自动同步路由',
`child_table_name` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '子表名称',
`main_field` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '主表关联键',
`child_field` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '子表关联键',
`parent_field` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '父表关联键',
`name_field` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '名称字段',
`generator_type` char(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT '0' COMMENT '生成方式 0:zip压缩包 1:自定义目录',
`backend_path` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '后端生成路径',
`frontend_path` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '前端生成路径',
@@ -165,7 +167,7 @@ CREATE TABLE `gen_table` (
`baseclass_id` bigint DEFAULT NULL COMMENT '基类ID',
`create_time` datetime DEFAULT NULL COMMENT '创建时间',
PRIMARY KEY (`id`),
UNIQUE KEY `table_name` (`table_name`,`ds_name`) USING BTREE
UNIQUE KEY `table_name_idx` (`table_name`,`ds_name`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='代码生成表';
-- ----------------------------
@@ -225,8 +227,8 @@ CREATE TABLE `gen_template` (
`update_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新',
`del_flag` char(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '0' COMMENT '删除标记',
`tenant_id` bigint NOT NULL COMMENT '租户ID',
`create_by` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT ' ' COMMENT '创建人',
`update_by` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT ' ' COMMENT '修改人',
`create_by` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT ' ' COMMENT '创建人',
`update_by` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT ' ' COMMENT '修改人',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='模板';
@@ -234,25 +236,51 @@ CREATE TABLE `gen_template` (
-- Records of gen_template
-- ----------------------------
BEGIN;
INSERT INTO `gen_template` (`id`, `template_name`, `generator_path`, `template_desc`, `template_code`, `create_time`, `update_time`, `del_flag`, `tenant_id`, `create_by`, `update_by`) VALUES (1, 'vform.json', '/', '表单设计器初始化json模板', '#set($key=${dateTool.getSystemTime()})\n{\n \"widgetList\": [\n {\n \"key\": $key,\n \"type\": \"grid\",\n \"category\": \"container\",\n \"icon\": \"grid\",\n \"cols\": [\n#foreach($field in $formList)\n#if($field.attrName != ${pk.attrName})\n {\n \"type\": \"grid-col\",\n \"category\": \"container\",\n \"icon\": \"grid-col\",\n \"internal\": true,\n \"widgetList\": [\n {\n \"key\": ${math.add($key,${foreach.index})},\n #if($field.formType == \'text\')\n \"type\": \"input\",\n \"icon\": \"text-field\",\n #elseif($field.formType == \'number\')\n \"type\": \"number\",\n \"icon\": \"number-field\",\n #elseif($field.formType == \'textarea\')\n \"type\": \"textarea\",\n \"icon\": \"textarea-field\",\n #elseif($field.formType == \'select\' && ${field.fieldDict})\n \"type\": \"select\",\n \"icon\": \"select-field\",\n #elseif($field.formType == \'radio\' && ${field.fieldDict})\n \"type\": \"radio\",\n \"icon\": \"radio-field\",\n #elseif($field.formType == \'checkbox\' && ${field.fieldDict} )\n \"type\": \"checkbox\",\n \"icon\": \"checkbox-field\",\n #elseif($field.formType == \'date\')\n \"type\": \"date\",\n \"icon\": \"date-field\",\n #elseif($field.formType == \'datetime\')\n \"type\": \"time\",\n \"icon\": \"time-field\",\n #elseif($field.formType == \'upload-file\')\n \"type\": \"file-upload\",\n \"icon\": \"file-upload-field\",\n #elseif($field.formType == \'upload-img\')\n \"type\": \"picture-upload\",\n \"icon\": \"picture-upload-field\",\n #elseif($field.formType == \'editor\')\n \"type\": \"rich-editor\",\n \"icon\": \"rich-editor-field\",\n #else\n \"type\": \"input\",\n \"icon\": \"text-field\",\n #end\n \"formItemFlag\": true,\n \"options\": {\n \"name\": \"${field.attrName}\",\n \"label\": \"#if(${field.fieldComment})${field.fieldComment}#else ${field.attrName}#end\",\n #if(($field.formType == \'select\' || $field.formType == \'radio\' || $field.formType == \'checkbox\') && ${field.fieldDict})\n \"optionItemsDictType\": \"${field.fieldDict}\",\n #end\n \"placeholder\": \"请输入#if(${field.fieldComment})${field.fieldComment}#else ${field.attrName}#end\"\n },\n #if($field.formRequired)\n \"required\": true,\n #end\n \"id\": \"input${math.add($key,${foreach.index})}\"\n }\n ],\n \"options\": {\n \"name\": \"gridCol${math.add($key,${foreach.index})}\",\n \"hidden\": false,\n \"offset\": 0,\n \"push\": 0,\n \"pull\": 0,\n #if($formLayout == 1)\n \"span\": 24,\n #elseif($formLayout == 2)\n \"span\": 12,\n #end\n \"responsive\": false\n },\n \"id\": \"grid-col-${math.add($key,${foreach.index})}\"\n }#if($foreach.hasNext),#end\n#end\n#end\n ],\n \"options\": {\n \"name\": \"grid${functionName}\",\n \"hidden\": false,\n \"gutter\": 12\n },\n \"id\": \"grid${functionName}\"\n }\n ],\n \"formConfig\": {\n \"modelName\": \"form\",\n \"refName\": \"form\",\n \"rulesName\": \"rules\",\n \"labelWidth\": 80,\n \"labelPosition\": \"left\",\n \"labelAlign\": \"label-left-align\",\n \"layoutType\": \"PC\",\n \"jsonVersion\": 3\n }\n}', '2023-02-23 04:33:16', '2023-06-04 10:35:51', '0', 1, ' ', ' ');
INSERT INTO `gen_template` (`id`, `template_name`, `generator_path`, `template_desc`, `template_code`, `create_time`, `update_time`, `del_flag`, `tenant_id`, `create_by`, `update_by`) VALUES (2, 'vform.vue', '/', '表单设计器生成sfc模板', '<template>\n <el-dialog :title=\"form.${pk.attrName} ? \'编辑\' : \'新增\'\" v-model=\"visible\" :close-on-click-modal=\"false\" draggable>\n <el-form ref=\"dataFormRef\" :model=\"form\" :rules=\"dataRules\" formDialogRef label-width=\"90px\">\n#foreach($key in $resultMap.keySet())\n#set($itemList = $resultMap.get($key))\n<el-row :gutter=\"24\">\n#foreach($field in $itemList)\n <el-col :span=\"$field.span\">\n#if($field.type == \'input\')\n <el-form-item label=\"${field.options.label}\" prop=\"${field.options.name}\">\n <el-input v-model=\"form.${field.options.name}\" placeholder=\"${field.options.placeholder}\"/>\n </el-form-item>\n#elseif($field.type == \'number\')\n <el-form-item label=\"${field.options.label}\" prop=\"${field.options.name}\">\n <el-input-number :min=\"${field.options.min}\" :max=\"${field.options.max}\" v-model=\"form.${field.options.name}\" placeholder=\"${field.options.placeholder}\"></el-input-number>\n </el-form-item>\n#elseif($field.type == \'textarea\')\n <el-form-item label=\"${field.options.label}\" prop=\"${field.options.name}\">\n <el-input type=\"textarea\" :rows=\"${field.options.rows}\" v-model=\"form.${field.options.name}\" placeholder=\"${field.options.placeholder}\"/>\n </el-form-item>\n#elseif($field.type == \'select\')\n <el-form-item label=\"${field.options.label}\" prop=\"${field.options.name}\">\n <el-select v-model=\"form.${field.options.name}\" placeholder=\"${field.options.placeholder}\">\n #if($field.options.optionItemsDictType)\n <el-option :value=\"item.value\" :label=\"item.label\" v-for=\"(item, index) in ${field.options.optionItemsDictType}\" :key=\"index\"></el-option>\n #else\n <el-option label=\"请选择\">0</el-option>\n #end\n </el-select>\n </el-form-item>\n#elseif($field.type == \'radio\')\n <el-form-item label=\"${field.options.label}\" prop=\"${field.options.name}\">\n <el-radio-group v-model=\"form.${field.options.name}\">\n #if($field.options.optionItemsDictType)\n <el-radio :label=\"item.value\" v-for=\"(item, index) in ${field.options.optionItemsDictType}\" border :key=\"index\">{{ item.label }}\n </el-radio>\n #end\n </el-radio-group>\n </el-form-item>\n#elseif($field.type == \'checkbox\')\n <el-form-item label=\"${field.options.label}\" prop=\"${field.options.name}\">\n <el-checkbox-group v-model=\"form.${field.options.name}\">\n #if($field.options.optionItemsDictType)\n <el-checkbox :label=\"item.value\" :name=\"item.label\" v-for=\"(item, index) in ${field.options.optionItemsDictType}\" :key=\"index\"></el-checkbox>\n #else\n <el-checkbox label=\"启用\" name=\"type\"></el-checkbox>\n <el-checkbox label=\"禁用\" name=\"type\"></el-checkbox>\n #end\n </<el-checkbox-group>\n </el-form-item>\n#elseif($field.type == \'date\')\n <el-form-item label=\"${field.options.label}\" prop=\"${field.options.name}\">\n <el-date-picker type=\"date\" placeholder=\"${field.options.placeholder}\" v-model=\"form.${field.options.name}\" :value-format=\"dateStr\"></el-date-picker>\n </el-form-item>\n#elseif($field.type == \'time\')\n <el-form-item label=\"${field.options.label}\" prop=\"${field.options.name}\">\n <el-time-picker placeholder=\"${field.options.placeholder}\" v-model=\"form.${field.options.name}\" :value-format=\"dateTimeStr\"></el-date-picker>\n </el-form-item>\n#elseif($field.type == \'file-upload\')\n <el-form-item label=\"${field.options.label}\" prop=\"${field.options.name}\">\n <upload-file v-model=\"form.${field.attrName}\" limit=\"${field.options.limit}\" fileMaxSize=\"${field.options.fileMaxSize}\"></upload-file>\n </el-form-item>\n#elseif($field.type == \'picture-upload\')\n <el-form-item label=\"${field.options.label}\" prop=\"${field.options.name}\">\n <upload-img v-model:imageUrl=\"form.${field.options.name}\" limit=\"${field.options.limit}\" fileMaxSize=\"${field.options.fileMaxSize}\"></upload-img>\n </el-form-item>\n#elseif($field.type == \'rich-editor\')\n <el-form-item label=\"${field.options.label}\" prop=\"${field.options.name}\">\n <editor v-model:get-html=\"form.${field.options.name}\" placeholder=\"${field.options.placeholder}\"></editor>\n </el-form-item>\n#elseif($field.type == \'switch\')\n <el-form-item label=\"${field.options.label}\" prop=\"${field.options.name}\">\n <el-switch v-model=\"form.${fLine truncated
INSERT INTO `gen_template` (`id`, `template_name`, `generator_path`, `template_desc`, `template_code`, `create_time`, `update_time`, `del_flag`, `tenant_id`, `create_by`, `update_by`) VALUES (3, 'Controller', '${backendPath}/src/main/java/${packagePath}/${moduleName}/controller/${ClassName}Controller.java', '后台Controller', 'package ${package}.${moduleName}.controller;\n\n#if($queryList)\nimport cn.hutool.core.util.StrUtil;\n#end\nimport cn.hutool.core.util.ArrayUtil;\nimport cn.hutool.core.collection.CollUtil;\nimport com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;\nimport com.baomidou.mybatisplus.core.toolkit.Wrappers;\nimport com.baomidou.mybatisplus.extension.plugins.pagination.Page;\nimport com.pig4cloud.pigx.common.core.util.R;\nimport com.pig4cloud.pigx.common.log.annotation.SysLog;\nimport ${package}.${moduleName}.entity.${ClassName}Entity;\nimport ${package}.${moduleName}.service.${ClassName}Service;\nimport org.springframework.security.access.prepost.PreAuthorize;\nimport com.pig4cloud.pigx.common.excel.annotation.ResponseExcel;\nimport io.swagger.v3.oas.annotations.security.SecurityRequirement;\n#if($isSpringBoot3)\nimport org.springdoc.core.annotations.ParameterObject;\n#else\nimport org.springdoc.api.annotations.ParameterObject;\n#end\nimport org.springframework.http.HttpHeaders;\nimport io.swagger.v3.oas.annotations.tags.Tag;\nimport io.swagger.v3.oas.annotations.Operation;\nimport lombok.RequiredArgsConstructor;\nimport org.springframework.web.bind.annotation.*;\n\nimport java.util.List;\nimport java.util.Objects;\n\n/**\n * ${tableComment}\n *\n * @author ${author}\n * @date ${datetime}\n */\n@RestController\n@RequiredArgsConstructor\n@RequestMapping(\"/${functionName}\" )\n@Tag(description = \"${functionName}\" , name = \"${tableComment}管理\" )\n@SecurityRequirement(name = HttpHeaders.AUTHORIZATION)\npublic class ${ClassName}Controller {\n\n private final ${ClassName}Service ${className}Service;\n\n /**\n * 分页查询\n * @param page 分页对象\n * @param ${className} ${tableComment}\n * @return\n */\n @Operation(summary = \"分页查询\" , description = \"分页查询\" )\n @GetMapping(\"/page\" )\n @PreAuthorize(\"@pms.hasPermission(\'${moduleName}_${functionName}_view\')\" )\n public R get${ClassName}Page(@ParameterObject Page page, @ParameterObject ${ClassName}Entity ${className}) {\n LambdaQueryWrapper<${ClassName}Entity> wrapper = Wrappers.lambdaQuery();\n#foreach ($field in $queryList)\n#set($getAttrName=$str.getProperty($field.attrName))\n#set($var=\"${className}.$getAttrName()\")\n#if($field.attrType == \'String\')\n#set($expression=\"StrUtil.isNotBlank\")\n#else\n#set($expression=\"Objects.nonNull\")\n#end\n#if($field.queryType == \'=\')\n wrapper.eq($expression($var),${ClassName}Entity::$getAttrName,$var);\n#elseif( $field.queryType == \'like\' )\n wrapper.like($expression($var),${ClassName}Entity::$getAttrName,$var);\n#elseif( $field.queryType == \'!-\' )\n wrapper.ne($expression($var),${ClassName}Entity::$getAttrName,$var);\n#elseif( $field.queryType == \'>\' )\n wrapper.gt($expression($var),${ClassName}Entity::$getAttrName,$var);\n#elseif( $field.queryType == \'<\' )\n wrapper.lt($expression($var),${ClassName}Entity::$getAttrName,$var);\n#elseif( $field.queryType == \'>=\' )\n wrapper.ge($expression($var),${ClassName}Entity::$getAttrName,$var);\n#elseif( $field.queryType == \'<=\' )\n wrapper.le($expression($var),${ClassName}Entity::$getAttrName,$var);\n#elseif( $field.queryType == \'left like\' )\n wrapper.likeLeft($expression($var),${ClassName}Entity::$getAttrName,$var);\n#elseif( $field.queryType == \'right like\' )\n wrapper.likeRight($expression($var),${ClassName}Entity::$getAttrName,$var);\n#end\n#end\n return R.ok(${className}Service.page(page, wrapper));\n }\n\n\n /**\n * 通过id查询${tableComment}\n * @param ${pk.attrName} id\n * @return R\n */\n @Operation(summary = \"通过id查询\" , description = \"通过id查询\" )\n @GetMapping(\"/{${pk.attrName}}\" )\n @PreAuthorize(\"@pms.hasPermission(\'${moduleName}_${functionName}_view\')\" )\n public R getById(@PathVariable(\"${pk.attrName}\" ) ${pk.attrType} ${pk.attrName}) {\n return R.ok(${className}Service.getById(${pk.attrName}));\n }\n\n /**\n * 新增${tableComment}\n * @param ${className} ${tableComment}\n * @return R\n */\n @Operation(summary = \"新增${tableComment}\" , description = \"新增${tableComment}\" )\n @SysLog(\"新增${tableComment}\" )\n @PostMapping\n @PreAuthorize(\"@pms.hasPermission(\'${moduleName}_${functionName}_add\')\" )\n public R save(@RequestBody ${ClassName}Entity ${className}) {\n return R.ok(${className}Service.save(${className}));\n }\n\n /**\n * 修改${tableComment}\n * @param ${className} ${tableComment}\n * @return R\n */\n @Operation(summary = \"修改${tableComment}\" , descLine truncated
INSERT INTO `gen_template` (`id`, `template_name`, `generator_path`, `template_desc`, `template_code`, `create_time`, `update_time`, `del_flag`, `tenant_id`, `create_by`, `update_by`) VALUES (4, 'Service', '${backendPath}/src/main/java/${packagePath}/${moduleName}/service/${ClassName}Service.java', 'Service', 'package ${package}.${moduleName}.service;\n\n#if($ChildClassName)\nimport com.github.yulichang.extension.mapping.base.MPJDeepService;\nimport ${package}.${moduleName}.entity.${ChildClassName}Entity;\n#else\nimport com.baomidou.mybatisplus.extension.service.IService;\n#end\nimport ${package}.${moduleName}.entity.${ClassName}Entity;\n\n#if($ChildClassName)\npublic interface ${ClassName}Service extends MPJDeepService<${ClassName}Entity> {\n Boolean saveDeep(${ClassName}Entity ${className});\n\n Boolean updateDeep(${ClassName}Entity ${className});\n\n Boolean removeDeep(Long[] ids);\n\n Boolean removeChild(Long[] ids);\n#else\npublic interface ${ClassName}Service extends IService<${ClassName}Entity> {\n#end\n\n}', '2023-02-23 01:16:53', '2023-06-04 10:35:25', '0', 1, ' ', ' ');
INSERT INTO `gen_template` (`id`, `template_name`, `generator_path`, `template_desc`, `template_code`, `create_time`, `update_time`, `del_flag`, `tenant_id`, `create_by`, `update_by`) VALUES (5, 'ServiceImpl', '${backendPath}/src/main/java/${packagePath}/${moduleName}/service/impl/${ClassName}ServiceImpl.java', 'ServiceImpl', 'package ${package}.${moduleName}.service.impl;\n\nimport com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;\nimport ${package}.${moduleName}.entity.${ClassName}Entity;\nimport ${package}.${moduleName}.mapper.${ClassName}Mapper;\nimport ${package}.${moduleName}.service.${ClassName}Service;\nimport org.springframework.stereotype.Service;\n#if($ChildClassName)\nimport cn.hutool.core.collection.CollUtil;\nimport com.baomidou.mybatisplus.core.toolkit.Wrappers;\nimport ${package}.${moduleName}.entity.${ChildClassName}Entity;\nimport ${package}.${moduleName}.mapper.${ChildClassName}Mapper;\nimport org.springframework.transaction.annotation.Transactional;\nimport lombok.RequiredArgsConstructor;\nimport java.util.Objects;\n#end\n/**\n * ${tableComment}\n *\n * @author ${author}\n * @date ${datetime}\n */\n@Service\n#if($ChildClassName)\n@RequiredArgsConstructor\n#end\npublic class ${ClassName}ServiceImpl extends ServiceImpl<${ClassName}Mapper, ${ClassName}Entity> implements ${ClassName}Service {\n#if($ChildClassName)\n private final ${ChildClassName}Mapper ${childClassName}Mapper;\n\n @Override\n @Transactional(rollbackFor = Exception.class)\n public Boolean saveDeep(${ClassName}Entity ${className}) {\n baseMapper.insert(${className});\n for (${ChildClassName}Entity ${childClassName} : ${className}.get${ChildClassName}List()) {\n ${childClassName}.$str.setProperty($childField)(${className}.$str.getProperty($mainField)());\n ${childClassName}Mapper.insert( ${childClassName});\n }\n\n return Boolean.TRUE;\n }\n\n @Override\n @Transactional(rollbackFor = Exception.class)\n public Boolean updateDeep(${ClassName}Entity ${className}) {\n baseMapper.updateById(${className});\n for (${ChildClassName}Entity ${childClassName} : ${className}.get${ChildClassName}List()) {\n#set($getChildPkName=$str.getProperty(${pk.attrName}))\n if (Objects.isNull(${childClassName}.$getChildPkName())) {\n ${childClassName}.$str.setProperty($childField)(${className}.$str.getProperty($mainField)());\n ${childClassName}Mapper.insert(${childClassName});\n } else {\n ${childClassName}Mapper.updateById(${childClassName});\n }\n }\n return Boolean.TRUE;\n }\n\n @Override\n @Transactional(rollbackFor = Exception.class)\n public Boolean removeDeep(Long[] ids) {\n baseMapper.deleteBatchIds(CollUtil.toList(ids));\n ${childClassName}Mapper.delete(Wrappers.<${ChildClassName}Entity>lambdaQuery().in(${ChildClassName}Entity::$str.getProperty($childField), ids));\n return Boolean.TRUE;\n }\n\n @Override\n @Transactional(rollbackFor = Exception.class)\n public Boolean removeChild(Long[] ids) {\n ${childClassName}Mapper.deleteBatchIds(CollUtil.toList(ids));\n return Boolean.TRUE;\n }\n#end\n}', '2023-02-23 01:17:36', '2023-08-27 23:29:58', '0', 1, ' ', ' ');
INSERT INTO `gen_template` (`id`, `template_name`, `generator_path`, `template_desc`, `template_code`, `create_time`, `update_time`, `del_flag`, `tenant_id`, `create_by`, `update_by`) VALUES (6, '实体', '${backendPath}/src/main/java/${packagePath}/${moduleName}/entity/${ClassName}Entity.java', 'Entity', 'package ${package}.${moduleName}.entity;\n\nimport com.baomidou.mybatisplus.annotation.*;\nimport com.baomidou.mybatisplus.extension.activerecord.Model;\nimport io.swagger.v3.oas.annotations.media.Schema;\nimport lombok.Data;\nimport lombok.EqualsAndHashCode;\n#if($isTenant)\nimport com.pig4cloud.pigx.common.core.util.TenantTable;\n#end\n#foreach($import in $importList)\nimport $import;\n#end\n#if($ChildClassName)\nimport com.alibaba.excel.annotation.ExcelIgnore;\nimport com.github.yulichang.annotation.EntityMapping;\nimport java.util.List;\n#end\n\n/**\n * ${tableComment}\n *\n * @author ${author}\n * @date ${datetime}\n */\n@Data\n#if($isTenant)\n@TenantTable\n#end\n@TableName(\"${tableName}\")\n@EqualsAndHashCode(callSuper = true)\n@Schema(description = \"${tableComment}\")\npublic class ${ClassName}Entity extends Model<${ClassName}Entity> {\n\n#foreach ($field in $fieldList)\n#if(${field.fieldComment})#set($comment=${field.fieldComment})#else #set($comment=${field.attrName})#end\n\n /**\n * $comment\n */\n#if($field.primaryPk == \'1\')\n @TableId(type = IdType.ASSIGN_ID)\n#end\n#if($field.autoFill == \'INSERT\')\n @TableField(fill = FieldFill.INSERT)\n#elseif($field.autoFill == \'INSERT_UPDATE\')\n @TableField(fill = FieldFill.INSERT_UPDATE)\n#elseif($field.autoFill == \'UPDATE\')\n @TableField(fill = FieldFill.UPDATE)\n#end\n#if($field.fieldName == \'del_flag\')\n @TableLogic\n @TableField(fill = FieldFill.INSERT)\n#end\n @Schema(description=\"$comment\"#if($field.hidden),hidden=$field.hidden#end)\n#if($field.formType == \'checkbox\')\n private ${field.attrType}[] $field.attrName;\n#else\n private $field.attrType $field.attrName;\n#end \n#end\n#if($ChildClassName)\n @ExcelIgnore\n @TableField(exist = false)\n @EntityMapping(thisField = \"$mainField\", joinField = \"$childField\")\n private List<${ChildClassName}Entity> ${childClassName}List;\n#end\n}', '2023-02-23 01:17:53', '2024-05-12 15:15:47', '0', 1, '', 'admin');
INSERT INTO `gen_template` (`id`, `template_name`, `generator_path`, `template_desc`, `template_code`, `create_time`, `update_time`, `del_flag`, `tenant_id`, `create_by`, `update_by`) VALUES (7, 'Mapper', '${backendPath}/src/main/java/${packagePath}/${moduleName}/mapper/${ClassName}Mapper.java', 'Mapper', 'package ${package}.${moduleName}.mapper;\n\nimport com.pig4cloud.pigx.common.data.datascope.PigxBaseMapper;\nimport ${package}.${moduleName}.entity.${ClassName}Entity;\nimport org.apache.ibatis.annotations.Mapper;\n\n@Mapper\npublic interface ${ClassName}Mapper extends PigxBaseMapper<${ClassName}Entity> {\n\n\n}', '2023-02-23 01:18:18', '2023-08-13 13:52:50', '0', 1, ' ', ' ');
INSERT INTO `gen_template` (`id`, `template_name`, `generator_path`, `template_desc`, `template_code`, `create_time`, `update_time`, `del_flag`, `tenant_id`, `create_by`, `update_by`) VALUES (8, 'Mapper.xml', '${backendPath}/src/main/resources/mapper/${ClassName}Mapper.xml', 'Mapper.xml', '<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE mapper PUBLIC \"-//mybatis.org//DTD Mapper 3.0//EN\" \"http://mybatis.org/dtd/mybatis-3-mapper.dtd\">\n\n<mapper namespace=\"${package}.${moduleName}.mapper.${ClassName}Mapper\">\n\n <resultMap id=\"${className}Map\" type=\"${package}.${moduleName}.entity.${ClassName}Entity\">\n#foreach ($field in $fieldList)\n #if($field.primaryPk == \'1\')\n <id property=\"$field.attrName\" column=\"$field.fieldName\"/>\n #else\n <result property=\"$field.attrName\" column=\"$field.fieldName\"/>\n #end\n#end\n </resultMap>\n</mapper>', '2023-02-23 01:18:35', '2023-09-23 21:36:09', '0', 1, ' ', ' ');
INSERT INTO `gen_template` (`id`, `template_name`, `generator_path`, `template_desc`, `template_code`, `create_time`, `update_time`, `del_flag`, `tenant_id`, `create_by`, `update_by`) VALUES (9, '权限菜单', '${backendPath}/menu/${functionName}_menu.sql', 'menu.sql', '-- 该脚本不要直接执行, 注意维护菜单的父节点ID 默认 父节点-1 , 默认租户 1\n#set($menuId=${dateTool.getSystemTime()})\n\n-- 菜单SQL\ninsert into sys_menu ( menu_id,parent_id, path, permission, menu_type, icon, del_flag, create_time, sort_order, update_time, name, tenant_id)\nvalues (${menuId}, \'-1\', \'/${moduleName}/${functionName}/index\', \'\', \'0\', \'icon-bangzhushouji\', \'0\', null , \'8\', null , \'${tableComment}管理\', 1);\n\n-- 菜单对应按钮SQL\ninsert into sys_menu ( menu_id,parent_id, permission, menu_type, path, icon, del_flag, create_time, sort_order, update_time, name, tenant_id)\nvalues (${math.add($menuId,1)},${menuId}, \'${moduleName}_${functionName}_view\', \'1\', null, \'1\', \'0\', null, \'0\', null, \'${tableComment}查看\', 1);\n\ninsert into sys_menu ( menu_id,parent_id, permission, menu_type, path, icon, del_flag, create_time, sort_order, update_time, name, tenant_id)\nvalues (${math.add($menuId,2)},${menuId}, \'${moduleName}_${functionName}_add\', \'1\', null, \'1\', \'0\', null, \'1\', null, \'${tableComment}新增\', 1);\n\ninsert into sys_menu (menu_id, parent_id, permission, menu_type, path, icon, del_flag, create_time, sort_order, update_time, name, tenant_id)\nvalues (${math.add($menuId,3)},${menuId}, \'${moduleName}_${functionName}_edit\', \'1\', null, \'1\', \'0\', null, \'2\', null, \'${tableComment}修改\', 1);\n\ninsert into sys_menu (menu_id, parent_id, permission, menu_type, path, icon, del_flag, create_time, sort_order, update_time, name, tenant_id)\nvalues (${math.add($menuId,4)},${menuId}, \'${moduleName}_${functionName}_del\', \'1\', null, \'1\', \'0\', null, \'3\', null, \'${tableComment}删除\', 1);\n\ninsert into sys_menu ( menu_id,parent_id, permission, menu_type, path, icon, del_flag, create_time, sort_order, update_time, name, tenant_id)\nvalues (${math.add($menuId,5)},${menuId}, \'${moduleName}_${functionName}_export\', \'1\', null, \'1\', \'0\', null, \'3\', null, \'导入导出\', 1);', '2023-02-23 01:19:08', '2023-08-27 23:16:31', '0', 1, ' ', ' ');
INSERT INTO `gen_template` (`id`, `template_name`, `generator_path`, `template_desc`, `template_code`, `create_time`, `update_time`, `del_flag`, `tenant_id`, `create_by`, `update_by`) VALUES (10, 'api.ts', '${frontendPath}/src/api/${moduleName}/${functionName}.ts', 'api.ts', 'import request from \"/@/utils/request\"\n\nexport function fetchList(query?: Object) {\n return request({\n url: \'/${moduleName}/${functionName}/page\',\n method: \'get\',\n params: query\n })\n}\n\nexport function addObj(obj?: Object) {\n return request({\n url: \'/${moduleName}/${functionName}\',\n method: \'post\',\n data: obj\n })\n}\n\nexport function getObj(id?: string) {\n return request({\n url: \'/${moduleName}/${functionName}/\' + id,\n method: \'get\'\n })\n}\n\nexport function delObjs(ids?: Object) {\n return request({\n url: \'/${moduleName}/${functionName}\',\n method: \'delete\',\n data: ids\n })\n}\n\nexport function putObj(obj?: Object) {\n return request({\n url: \'/${moduleName}/${functionName}\',\n method: \'put\',\n data: obj\n })\n}\n\n#if($ChildClassName)\nexport function delChildObj(ids?: Object) {\n return request({\n url: \'/${moduleName}/${functionName}/child\',\n method: \'delete\',\n data: ids\n })\n}\n#end', '2023-02-23 01:19:23', '2023-06-04 10:34:17', '0', 1, ' ', ' ');
INSERT INTO `gen_template` (`id`, `template_name`, `generator_path`, `template_desc`, `template_code`, `create_time`, `update_time`, `del_flag`, `tenant_id`, `create_by`, `update_by`) VALUES (11, '表格', '${frontendPath}/src/views/${moduleName}/${functionName}/index.vue', '表格不含i18n', '<template>\n <div class=\"layout-padding\">\n <div class=\"layout-padding-auto layout-padding-view\">\n#if($queryList)\n <el-row v-show=\"showSearch\">\n <el-form :model=\"state.queryForm\" ref=\"queryRef\" :inline=\"true\" @keyup.enter=\"getDataList\">\n#foreach($field in $queryList)\n#if($field.queryFormType == \'select\')\n <el-form-item label=\"#if(${field.fieldComment})${field.fieldComment}#else ${field.attrName}#end\" prop=\"${field.attrName}\">\n <el-select v-model=\"state.queryForm.${field.attrName}\" placeholder=\"请选择#if(${field.fieldComment})${field.fieldComment}#else ${field.attrName}#end\">\n #if($field.fieldDict)\n <el-option :label=\"item.label\" :value=\"item.value\" v-for=\"(item, index) in ${field.fieldDict}\" :key=\"index\"></el-option>\n #else\n <el-option label=\"请选择\">0</el-option>\n #end\n </el-select>\n </el-form-item>\n#elseif($field.queryFormType == \'date\')\n <el-form-item label=\"#if(${field.fieldComment})${field.fieldComment}#else ${field.attrName}#end\" prop=\"${field.attrName}\">\n <el-date-picker type=\"date\" placeholder=\"请输入#if(${field.fieldComment})${field.fieldComment}#else ${field.attrName}#end\" v-model=\"state.queryForm.${field.attrName}\"></el-date-picker>\n </el-form-item>\n#elseif($field.queryFormType == \'datetime\')\n <el-form-item label=\"#if(${field.fieldComment})${field.fieldComment}#else ${field.attrName}#end\" prop=\"${field.attrName}\" >\n <el-date-picker type=\"datetime\" placeholder=\"请输入#if(${field.fieldComment})${field.fieldComment}#else ${field.attrName}#end\" v-model=\"state.queryForm.${field.attrName}\"></el-date-picker>\n </el-form-item>\n </el-col>\n#else\n <el-form-item label=\"#if(${field.fieldComment})${field.fieldComment}#else ${field.attrName}#end\" prop=\"${field.attrName}\" >\n <el-input placeholder=\"请输入#if(${field.fieldComment})${field.fieldComment}#else ${field.attrName}#end\" v-model=\"state.queryForm.${field.attrName}\" />\n </el-form-item>\n#end\n#end\n <el-form-item>\n <el-button icon=\"search\" type=\"primary\" @click=\"getDataList\">\n 查询\n </el-button>\n <el-button icon=\"Refresh\" @click=\"resetQuery\">重置</el-button>\n </el-form-item>\n </el-form>\n </el-row>\n#end\n <el-row>\n <div class=\"mb8\" style=\"width: 100%\">\n <el-button icon=\"folder-add\" type=\"primary\" class=\"ml10\" @click=\"formDialogRef.openDialog()\"\n v-auth=\"\'${moduleName}_${functionName}_add\'\">\n 新 增\n </el-button>\n <el-button plain :disabled=\"multiple\" icon=\"Delete\" type=\"primary\"\n v-auth=\"\'${moduleName}_${functionName}_del\'\" @click=\"handleDelete(selectObjs)\">\n 删除\n </el-button>\n <right-toolbar v-model:showSearch=\"showSearch\" :export=\"\'${moduleName}_${functionName}_export\'\"\n @exportExcel=\"exportExcel\" class=\"ml10 mr20\" style=\"float: right;\"\n @queryTable=\"getDataList\"></right-toolbar>\n </div>\n </el-row>\n <el-table :data=\"state.dataList\" v-loading=\"state.loading\" border \n :cell-style=\"tableStyle.cellStyle\" :header-cell-style=\"tableStyle.headerCellStyle\"\n @selection-change=\"selectionChangHandle\"\n @sort-change=\"sortChangeHandle\">\n <el-table-column type=\"selection\" width=\"40\" align=\"center\" />\n <el-table-column type=\"index\" label=\"#\" width=\"40\" />\n #foreach($field in $gridList)\n #if($field.fieldDict)\n <el-table-column prop=\"${field.attrName}\" label=\"#if(${field.fieldComment})${field.fieldComment}#else ${field.attrName}#end\" show-overflow-tooltip>\n <template #default=\"scope\">\n <dict-tag :options=\"$field.fieldDict\" :value=\"scope.row.${field.attrName}\"></dict-tag>\n </template>\n </el-table-column>\n #else\n <el-table-column prop=\"${field.attrName}\" label=\"#if(${field.fieldComment})${field.fieldComment}#else ${field.attrName}#end\" #if(${field.gridSort} == \'1\')sortable=\"custom\"#end show-overflow-tooltip/>\n #end\n #end\n <el-table-column label=\"操作\" width=\"150\">\n <template #default=\"scope\">\n <el-button icon=\"edit-pen\" text type=\"primary\" v-auth=\"\'${moduleName}_${functionName}_edit\'\"\n @click=\"formDialogRef.openDialog(scope.row.${pk.attrName})\">编辑</el-button>\n <el-button icon=\"deleLine truncated
INSERT INTO `gen_template` (`id`, `template_name`, `generator_path`, `template_desc`, `template_code`, `create_time`, `update_time`, `del_flag`, `tenant_id`, `create_by`, `update_by`) VALUES (12, '表单', '${frontendPath}/src/views/${moduleName}/${functionName}/form.vue', '表单不含i18n', '<template>\n <el-dialog :title=\"form.${pk.attrName} ? \'编辑\' : \'新增\'\" v-model=\"visible\"\n :close-on-click-modal=\"false\" draggable>\n <el-form ref=\"dataFormRef\" :model=\"form\" :rules=\"dataRules\" formDialogRef label-width=\"90px\" v-loading=\"loading\">\n <el-row :gutter=\"24\">\n#foreach($field in $formList)\n#if($field.attrName != ${pk.attrName})\n#if($formLayout == 1)\n <el-col :span=\"24\" class=\"mb20\">\n#elseif($formLayout == 2)\n <el-col :span=\"12\" class=\"mb20\">\n#end\n#if($field.formType == \'text\')\n <el-form-item label=\"#if(${field.fieldComment})${field.fieldComment}#else ${field.attrName}#end\" prop=\"${field.attrName}\">\n <el-input v-model=\"form.${field.attrName}\" placeholder=\"请输入#if(${field.fieldComment})${field.fieldComment}#else ${field.attrName}#end\"/>\n </el-form-item>\n </el-col>\n#elseif($field.formType == \'textarea\')\n <el-form-item label=\"#if(${field.fieldComment})${field.fieldComment}#else ${field.attrName}#end\" prop=\"${field.attrName}\">\n <el-input type=\"textarea\" v-model=\"form.${field.attrName}\" placeholder=\"请输入#if(${field.fieldComment})${field.fieldComment}#else ${field.attrName}#end\"/>\n </el-form-item>\n </el-col>\n#elseif($field.formType == \'select\')\n <el-form-item label=\"#if(${field.fieldComment})${field.fieldComment}#else ${field.attrName}#end\" prop=\"${field.attrName}\">\n <el-select v-model=\"form.${field.attrName}\" placeholder=\"请选择#if(${field.fieldComment})${field.fieldComment}#else ${field.attrName}#end\">\n #if($field.fieldDict)\n <el-option :value=\"item.value\" :label=\"item.label\" v-for=\"(item, index) in ${field.fieldDict}\" :key=\"index\"></el-option>\n #end\n #if(!$field.fieldDict)\n <el-option label=\"请选择\">0</el-option>\n #end\n </el-select>\n </el-form-item>\n </el-col>\n#elseif($field.formType == \'radio\')\n <el-form-item label=\"#if(${field.fieldComment})${field.fieldComment}#else ${field.attrName}#end\" prop=\"${field.attrName}\">\n <el-radio-group v-model=\"form.${field.attrName}\">\n #if($field.fieldDict)\n <el-radio :label=\"item.value\" v-for=\"(item, index) in ${field.fieldDict}\" border :key=\"index\">{{ item.label }}\n </el-radio>\n #else\n <el-radio label=\"${field.fieldComment}\" border>${field.fieldComment}</el-radio>\n #end\n </el-radio-group>\n </el-form-item>\n </el-col>\n#elseif($field.formType == \'checkbox\')\n <el-form-item label=\"#if(${field.fieldComment})${field.fieldComment}#else ${field.attrName}#end\" prop=\"${field.attrName}\">\n <el-checkbox-group v-model=\"form.${field.attrName}\">\n #if($field.fieldDict)\n <el-checkbox :label=\"item.value\" v-for=\"(item, index) in ${field.fieldDict}\" :key=\"index\">{{ item.label }}</el-checkbox>\n #end\n #if(!$field.fieldDict)\n <el-checkbox label=\"启用\" name=\"type\"></el-checkbox>\n <el-checkbox label=\"禁用\" name=\"type\"></el-checkbox>\n #end\n </el-checkbox-group>\n </el-form-item>\n </el-col>\n#elseif($field.formType == \'date\')\n <el-form-item label=\"#if(${field.fieldComment})${field.fieldComment}#else ${field.attrName}#end\" prop=\"${field.attrName}\">\n <el-date-picker type=\"date\" placeholder=\"请选择#if(${field.fieldComment})${field.fieldComment}#else ${field.attrName}#end\" v-model=\"form.${field.attrName}\" :value-format=\"dateStr\"></el-date-picker>\n </el-form-item>\n </el-col>\n#elseif($field.formType == \'datetime\')\n <el-form-item label=\"#if(${field.fieldComment})${field.fieldComment}#else ${field.attrName}#end\" prop=\"${field.attrName}\">\n <el-date-picker type=\"datetime\" placeholder=\"请选择#if(${field.fieldComment})${field.fieldComment}#else ${field.attrName}#end\" v-model=\"form.${field.attrName}\" :value-format=\"dateTimeStr\"></el-date-picker>\n </el-form-item>\n </el-col>\n\n#elseif($field.formType == \'number\')\n <el-form-item label=\"#if(${field.fieldComment})${field.fieldComment}#else ${field.attrName}#end\" prop=\"${field.attrName}\">\n <el-input-number :min=\"1\" :max=\"1000\" v-model=\"form.${field.attrName}\" placeholder=\"请输入#if(${field.fieldComment})${field.fieldComment}#else ${field.attrName}#end\"></el-input-number>\n </el-form-item>\n </el-col>\n#elseif($field.formType == \'upload-file\')\n <el-form-item label=\"#if(${field.fieldComment})${field.fieldComment}#else ${field.attrName}#enLine truncated
INSERT INTO `gen_template` (`id`, `template_name`, `generator_path`, `template_desc`, `template_code`, `create_time`, `update_time`, `del_flag`, `tenant_id`, `create_by`, `update_by`) VALUES (13, 'i18n英文模板', '${frontendPath}/src/views/${moduleName}/${functionName}/i18n/en.ts', 'i18n英文模板', 'export default {\n ${functionName}: {\n index: \'#\',\n import${className}Tip: \'import ${ClassName}\',\n#foreach($field in $fieldList)\n ${field.attrName}: \'${field.attrName}\',\n#end\n#foreach($field in $fieldList)\n input$str.pascalCase(${field.attrName})Tip: \'input ${field.attrName}\',\n#end\n }\n}', '2023-02-23 01:20:25', '2023-06-04 10:49:25', '0', 1, '', 'admin');
INSERT INTO `gen_template` (`id`, `template_name`, `generator_path`, `template_desc`, `template_code`, `create_time`, `update_time`, `del_flag`, `tenant_id`, `create_by`, `update_by`) VALUES (14, 'i18n中文模板', '${frontendPath}/src/views/${moduleName}/${functionName}/i18n/zh-cn.ts', 'i18n中文模板', 'export default {\n ${functionName}: {\n index: \'#\',\n import${className}Tip: \'导入${tableComment}\',\n#foreach($field in $fieldList)\n ${field.attrName}: \'#if(${field.fieldComment})${field.fieldComment}#else ${field.attrName}#end\',\n#end\n#foreach($field in $fieldList)\n input$str.pascalCase(${field.attrName})Tip: \'请输入#if(${field.fieldComment})${field.fieldComment}#else ${field.attrName}#end\',\n#end\n }\n}', '2023-02-23 01:20:40', '2023-06-04 10:49:28', '0', 1, '', 'admin');
INSERT INTO `gen_template` (`id`, `template_name`, `generator_path`, `template_desc`, `template_code`, `create_time`, `update_time`, `del_flag`, `tenant_id`, `create_by`, `update_by`) VALUES (15, '子实体', '${backendPath}/src/main/java/${packagePath}/${moduleName}/entity/${ChildClassName}Entity.java', '子表实体对象', 'package ${package}.${moduleName}.entity;\n\nimport com.baomidou.mybatisplus.annotation.*;\nimport com.baomidou.mybatisplus.extension.activerecord.Model;\nimport io.swagger.v3.oas.annotations.media.Schema;\n#if($isChildTenant)\nimport com.pig4cloud.pigx.common.core.util.TenantTable;\n#end\nimport lombok.Data;\nimport lombok.EqualsAndHashCode;\n#foreach($import in $importList)\nimport $import;\n#end\n\n/**\n * ${tableComment}\n *\n * @author ${author}\n * @date ${datetime}\n */\n@Data\n#if($isChildTenant)\n@TenantTable\n#end\n@TableName(\"${childTableName}\")\n@EqualsAndHashCode(callSuper = true)\n@Schema(description = \"${childTableName}\")\npublic class ${ChildClassName}Entity extends Model<${ChildClassName}Entity> {\n\n#foreach ($field in $childFieldList)\n#if(${field.fieldComment})#set($comment=${field.fieldComment})#else #set($comment=${field.attrName})#end\n /**\n * $comment\n */\n#if($field.primaryPk == \'1\')\n @TableId(type = IdType.ASSIGN_ID)\n#end\n#if($field.autoFill == \'INSERT\')\n @TableField(fill = FieldFill.INSERT)\n#elseif($field.autoFill == \'INSERT_UPDATE\')\n @TableField(fill = FieldFill.INSERT_UPDATE)\n#elseif($field.autoFill == \'UPDATE\')\n @TableField(fill = FieldFill.UPDATE)\n#end\n#if($field.fieldName == \'del_flag\')\n @TableLogic\n @TableField(fill = FieldFill.INSERT)\n#end\n @Schema(description=\"$comment\"#if($field.hidden),hidden=$field.hidden#end)\n#if($field.formType == \'checkbox\')\n private ${field.attrType}[] $field.attrName;\n#else\n private $field.attrType $field.attrName;\n#end \n#end\n}', '2023-06-01 11:07:14', '2024-05-12 15:07:04', '0', 1, '', 'admin');
INSERT INTO `gen_template` (`id`, `template_name`, `generator_path`, `template_desc`, `template_code`, `create_time`, `update_time`, `del_flag`, `tenant_id`, `create_by`, `update_by`) VALUES (16, '主子Contoller', '${backendPath}/src/main/java/${packagePath}/${moduleName}/controller/${ClassName}Controller.java', '子表Controller对象', 'package ${package}.${moduleName}.controller;\n\n#if($queryList)\nimport cn.hutool.core.util.StrUtil;\n#end\nimport cn.hutool.core.util.ArrayUtil;\nimport com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;\nimport com.baomidou.mybatisplus.core.toolkit.Wrappers;\nimport com.baomidou.mybatisplus.extension.plugins.pagination.Page;\nimport com.pig4cloud.pigx.common.core.util.R;\nimport com.pig4cloud.pigx.common.log.annotation.SysLog;\nimport ${package}.${moduleName}.entity.${ClassName}Entity;\nimport ${package}.${moduleName}.entity.${ChildClassName}Entity;\nimport ${package}.${moduleName}.service.${ClassName}Service;\nimport org.springframework.security.access.prepost.PreAuthorize;\nimport com.pig4cloud.pigx.common.excel.annotation.ResponseExcel;\nimport io.swagger.v3.oas.annotations.security.SecurityRequirement;\n#if($isSpringBoot3)\nimport org.springdoc.core.annotations.ParameterObject;\n#else\nimport org.springdoc.api.annotations.ParameterObject;\n#end\nimport org.springframework.http.HttpHeaders;\nimport io.swagger.v3.oas.annotations.tags.Tag;\nimport io.swagger.v3.oas.annotations.Operation;\nimport lombok.RequiredArgsConstructor;\nimport org.springframework.web.bind.annotation.*;\n\nimport java.util.List;\nimport java.util.Objects;\n\n/**\n * ${tableComment}\n *\n * @author ${author}\n * @date ${datetime}\n */\n@RestController\n@RequiredArgsConstructor\n@RequestMapping(\"/${functionName}\" )\n@Tag(description = \"${functionName}\" , name = \"${tableComment}管理\" )\n@SecurityRequirement(name = HttpHeaders.AUTHORIZATION)\npublic class ${ClassName}Controller {\n\n private final ${ClassName}Service ${className}Service;\n\n /**\n * 分页查询\n * @param page 分页对象\n * @param ${className} ${tableComment}\n * @return\n */\n @Operation(summary = \"分页查询\" , description = \"分页查询\" )\n @GetMapping(\"/page\" )\n @PreAuthorize(\"@pms.hasPermission(\'${moduleName}_${functionName}_view\')\" )\n public R get${ClassName}Page(@ParameterObject Page page, @ParameterObject ${ClassName}Entity ${className}) {\n LambdaQueryWrapper<${ClassName}Entity> wrapper = Wrappers.lambdaQuery();\n#foreach ($field in $queryList)\n#set($getAttrName=$str.getProperty($field.attrName))\n#set($var=\"${className}.$getAttrName()\")\n#if($field.attrType == \'String\')\n#set($expression=\"StrUtil.isNotBlank\")\n#else\n#set($expression=\"Objects.nonNull\")\n#end\n#if($field.queryType == \'=\')\n wrapper.eq($expression($var),${ClassName}Entity::$getAttrName,$var);\n#elseif( $field.queryType == \'like\' )\n wrapper.like($expression($var),${ClassName}Entity::$getAttrName,$var);\n#elseif( $field.queryType == \'!-\' )\n wrapper.ne($expression($var),${ClassName}Entity::$getAttrName,$var);\n#elseif( $field.queryType == \'>\' )\n wrapper.gt($expression($var),${ClassName}Entity::$getAttrName,$var);\n#elseif( $field.queryType == \'<\' )\n wrapper.lt($expression($var),${ClassName}Entity::$getAttrName,$var);\n#elseif( $field.queryType == \'>=\' )\n wrapper.ge($expression($var),${ClassName}Entity::$getAttrName,$var);\n#elseif( $field.queryType == \'<=\' )\n wrapper.le($expression($var),${ClassName}Entity::$getAttrName,$var);\n#elseif( $field.queryType == \'left like\' )\n wrapper.likeLeft($expression($var),${ClassName}Entity::$getAttrName,$var);\n#elseif( $field.queryType == \'right like\' )\n wrapper.likeRight($expression($var),${ClassName}Entity::$getAttrName,$var);\n#end\n#end\n return R.ok(${className}Service.page(page, wrapper));\n }\n\n /**\n * 通过id查询${tableComment}\n * @param ${pk.attrName} id\n * @return R\n */\n @Operation(summary = \"通过id查询\" , description = \"通过id查询\" )\n @GetMapping(\"/{${pk.attrName}}\" )\n @PreAuthorize(\"@pms.hasPermission(\'${moduleName}_${functionName}_view\')\" )\n public R getById(@PathVariable(\"${pk.attrName}\" ) ${pk.attrType} ${pk.attrName}) {\n return R.ok(${className}Service.getByIdDeep(${pk.attrName}));\n }\n\n /**\n * 新增${tableComment}\n * @param ${className} ${tableComment}\n * @return R\n */\n @Operation(summary = \"新增${tableComment}\" , description = \"新增${tableComment}\" )\n @SysLog(\"新增${tableComment}\" )\n @PostMapping\n @PreAuthorize(\"@pms.hasPermission(\'${moduleName}_${functionName}_add\')\" )\n public R save(@RequestBody ${ClassName}Entity ${className}) {\n return R.ok(${className}Service.saveDeep(${className}));\n }\n\n /**\n * 修改${tableComment}\n * @param ${className} ${tableComment}\n * @return R\n */\n @Operation(sumLine truncated
INSERT INTO `gen_template` (`id`, `template_name`, `generator_path`, `template_desc`, `template_code`, `create_time`, `update_time`, `del_flag`, `tenant_id`, `create_by`, `update_by`) VALUES (17, '主子表单', '${frontendPath}/src/views/${moduleName}/${functionName}/form.vue', '子表表单', '<template>\n <el-drawer :title=\"form.${pk.attrName} ? (detail ? \'详情\' : \'编辑\') : \'添加\'\" v-model=\"visible\" size=\"50%\">\n <el-form ref=\"dataFormRef\" :model=\"form\" :rules=\"dataRules\" label-width=\"90px\" :disabled=\"detail\" v-loading=\"loading\">\n <el-row :gutter=\"24\">\n#foreach($field in $formList)\n#if($field.attrName != ${pk.attrName})\n#if($formLayout == 1)\n <el-col :span=\"24\" class=\"mb20\">\n#elseif($formLayout == 2)\n <el-col :span=\"12\" class=\"mb20\">\n#end\n#if($field.formType == \'text\')\n <el-form-item label=\"#if(${field.fieldComment})${field.fieldComment}#else ${field.attrName}#end\" prop=\"${field.attrName}\">\n <el-input v-model=\"form.${field.attrName}\" placeholder=\"请输入#if(${field.fieldComment})${field.fieldComment}#else ${field.attrName}#end\"/>\n </el-form-item>\n </el-col>\n#elseif($field.formType == \'textarea\')\n <el-form-item label=\"#if(${field.fieldComment})${field.fieldComment}#else ${field.attrName}#end\" prop=\"${field.attrName}\">\n <el-input type=\"textarea\" v-model=\"form.${field.attrName}\" placeholder=\"请输入#if(${field.fieldComment})${field.fieldComment}#else ${field.attrName}#end\"/>\n </el-form-item>\n </el-col>\n#elseif($field.formType == \'select\')\n <el-form-item label=\"#if(${field.fieldComment})${field.fieldComment}#else ${field.attrName}#end\" prop=\"${field.attrName}\">\n <el-select v-model=\"form.${field.attrName}\" placeholder=\"请选择#if(${field.fieldComment})${field.fieldComment}#else ${field.attrName}#end\">\n #if($field.fieldDict)\n <el-option :value=\"item.value\" :label=\"item.label\" v-for=\"(item, index) in ${field.fieldDict}\" :key=\"index\"></el-option>\n #end\n #if(!$field.fieldDict)\n <el-option label=\"请选择\">0</el-option>\n #end\n </el-select>\n </el-form-item>\n </el-col>\n#elseif($field.formType == \'radio\')\n <el-form-item label=\"#if(${field.fieldComment})${field.fieldComment}#else ${field.attrName}#end\" prop=\"${field.attrName}\">\n <el-radio-group v-model=\"form.${field.attrName}\">\n #if($field.fieldDict)\n <el-radio :label=\"item.value\" v-for=\"(item, index) in ${field.fieldDict}\" border :key=\"index\">{{ item.label }}\n </el-radio>\n #else\n <el-radio label=\"${field.fieldComment}\" border>${field.fieldComment}</el-radio>\n #end\n </el-radio-group>\n </el-form-item>\n </el-col>\n#elseif($field.formType == \'checkbox\')\n <el-form-item label=\"#if(${field.fieldComment})${field.fieldComment}#else ${field.attrName}#end\" prop=\"${field.attrName}\">\n <el-checkbox-group v-model=\"form.${field.attrName}\">\n #if($field.fieldDict)\n <el-checkbox :label=\"item.value\" v-for=\"(item, index) in ${field.fieldDict}\" :key=\"index\">{{ item.label }}</el-checkbox>\n #end\n #if(!$field.fieldDict)\n <el-checkbox label=\"启用\" name=\"type\"></el-checkbox>\n <el-checkbox label=\"禁用\" name=\"type\"></el-checkbox>\n #end\n </el-checkbox-group>\n </el-form-item>\n </el-col>\n#elseif($field.formType == \'date\')\n <el-form-item label=\"#if(${field.fieldComment})${field.fieldComment}#else ${field.attrName}#end\" prop=\"${field.attrName}\">\n <el-date-picker type=\"date\" placeholder=\"请选择#if(${field.fieldComment})${field.fieldComment}#else ${field.attrName}#end\" v-model=\"form.${field.attrName}\" :value-format=\"dateStr\"></el-date-picker>\n </el-form-item>\n </el-col>\n#elseif($field.formType == \'datetime\')\n <el-form-item label=\"#if(${field.fieldComment})${field.fieldComment}#else ${field.attrName}#end\" prop=\"${field.attrName}\">\n <el-date-picker type=\"datetime\" placeholder=\"请选择#if(${field.fieldComment})${field.fieldComment}#else ${field.attrName}#end\" v-model=\"form.${field.attrName}\" :value-format=\"dateTimeStr\"></el-date-picker>\n </el-form-item>\n </el-col>\n#elseif($field.formType == \'number\')\n <el-form-item label=\"#if(${field.fieldComment})${field.fieldComment}#else ${field.attrName}#end\" prop=\"${field.attrName}\">\n <el-input-number :min=\"1\" :max=\"1000\" v-model=\"form.${field.attrName}\" placeholder=\"请输入#if(${field.fieldComment})${field.fieldComment}#else ${field.attrName}#end\"></el-input-number>\n </el-form-item>\n </el-col>\n#elseif($field.formType == \'upload-file\')\n <el-form-item label=\"#if(${field.fieldComment})${field.fieldComment}#else ${field.attrNameLine truncated
INSERT INTO `gen_template` (`id`, `template_name`, `generator_path`, `template_desc`, `template_code`, `create_time`, `update_time`, `del_flag`, `tenant_id`, `create_by`, `update_by`) VALUES (18, '主子表格', '${frontendPath}/src/views/${moduleName}/${functionName}/index.vue', '子表单表格', '<template>\n <div class=\"layout-padding\">\n <div class=\"layout-padding-auto layout-padding-view\">\n#if($queryList)\n <el-row v-show=\"showSearch\">\n <el-form :model=\"state.queryForm\" ref=\"queryRef\" :inline=\"true\" @keyup.enter=\"getDataList\">\n#foreach($field in $queryList)\n#if($field.queryFormType == \'select\')\n <el-form-item label=\"#if(${field.fieldComment})${field.fieldComment}#else ${field.attrName}#end\" prop=\"${field.attrName}\">\n <el-select v-model=\"state.queryForm.${field.attrName}\" placeholder=\"请选择#if(${field.fieldComment})${field.fieldComment}#else ${field.attrName}#end\">\n #if($field.fieldDict)\n <el-option :label=\"item.label\" :value=\"item.value\" v-for=\"(item, index) in ${field.fieldDict}\" :key=\"index\"></el-option>\n #else\n <el-option label=\"请选择\">0</el-option>\n #end\n </el-select>\n </el-form-item>\n#elseif($field.queryFormType == \'date\')\n <el-form-item label=\"#if(${field.fieldComment})${field.fieldComment}#else ${field.attrName}#end\" prop=\"${field.attrName}\">\n <el-date-picker type=\"date\" placeholder=\"请输入#if(${field.fieldComment})${field.fieldComment}#else ${field.attrName}#end\" v-model=\"state.queryForm.${field.attrName}\"></el-date-picker>\n </el-form-item>\n#elseif($field.queryFormType == \'datetime\')\n <el-form-item label=\"#if(${field.fieldComment})${field.fieldComment}#else ${field.attrName}#end\" prop=\"${field.attrName}\" >\n <el-date-picker type=\"datetime\" placeholder=\"请输入#if(${field.fieldComment})${field.fieldComment}#else ${field.attrName}#end\" v-model=\"state.queryForm.${field.attrName}\"></el-date-picker>\n </el-form-item>\n </el-col>\n#else\n <el-form-item label=\"#if(${field.fieldComment})${field.fieldComment}#else ${field.attrName}#end\" prop=\"${field.attrName}\" >\n <el-input placeholder=\"请输入#if(${field.fieldComment})${field.fieldComment}#else ${field.attrName}#end\" v-model=\"state.queryForm.${field.attrName}\"\n style=\"max-width: 180px\" />\n </el-form-item>\n#end\n#end\n <el-form-item>\n <el-button icon=\"search\" type=\"primary\" @click=\"getDataList\">\n 查询\n </el-button>\n <el-button icon=\"Refresh\" @click=\"resetQuery\">重置</el-button>\n </el-form-item>\n </el-form>\n </el-row>\n#end\n <el-row>\n <div class=\"mb8\" style=\"width: 100%\">\n <el-button icon=\"folder-add\" type=\"primary\" class=\"ml10\" @click=\"formDialogRef.openDialog()\"\n v-auth=\"\'${moduleName}_${functionName}_add\'\">\n 新 增\n </el-button>\n <el-button plain :disabled=\"multiple\" icon=\"Delete\" type=\"primary\"\n v-auth=\"\'${moduleName}_${functionName}_del\'\" @click=\"handleDelete(selectObjs)\">\n 删除\n </el-button>\n <right-toolbar v-model:showSearch=\"showSearch\" :export=\"\'${moduleName}_${functionName}_export\'\"\n @exportExcel=\"exportExcel\" class=\"ml10 mr20\" style=\"float: right;\"\n @queryTable=\"getDataList\"></right-toolbar>\n </div>\n </el-row>\n <el-table :data=\"state.dataList\" v-loading=\"state.loading\" border \n :cell-style=\"tableStyle.cellStyle\" :header-cell-style=\"tableStyle.headerCellStyle\"\n @selection-change=\"selectionChangeHandle\" @sort-change=\"sortChangeHandle\">\n <el-table-column type=\"selection\" width=\"40\" align=\"center\" />\n <el-table-column type=\"index\" label=\"#\" width=\"40\" />\n #foreach($field in $gridList)\n #if($field.fieldDict)\n <el-table-column prop=\"${field.attrName}\" label=\"#if(${field.fieldComment})${field.fieldComment}#else ${field.attrName}#end\" show-overflow-tooltip>\n <template #default=\"scope\">\n <dict-tag :options=\"$field.fieldDict\" :value=\"scope.row.${field.attrName}\"></dict-tag>\n </template>\n </el-table-column>\n #else\n <el-table-column prop=\"${field.attrName}\" label=\"#if(${field.fieldComment})${field.fieldComment}#else ${field.attrName}#end\" #if(${field.gridSort} == \'1\')sortable=\"custom\"#end show-overflow-tooltip/>\n #end\n #end\n <el-table-column label=\"操作\" width=\"200\">\n <template #default=\"scope\">\n #if($ChildClassName)\n <el-button text type=\"primary\" icon=\"view\" v-auth=\"\'sys_role_edit\'\" @click=\"formDialogRef.openDialog(scope.row.${pk.attrName}, true)\">\n Line truncated
INSERT INTO `gen_template` (`id`, `template_name`, `generator_path`, `template_desc`, `template_code`, `create_time`, `update_time`, `del_flag`, `tenant_id`, `create_by`, `update_by`) VALUES (19, '子Mapper', '${backendPath}/src/main/java/${packagePath}/${moduleName}/mapper/${ChildClassName}Mapper.java', '子Mapper', 'package ${package}.${moduleName}.mapper;\n\nimport com.pig4cloud.pigx.common.data.datascope.PigxBaseMapper;\n#if($ChildClassName)\nimport ${package}.${moduleName}.entity.${ChildClassName}Entity;\n#else\nimport ${package}.${moduleName}.entity.${ClassName}Entity;\n#end\nimport org.apache.ibatis.annotations.Mapper;\n\n@Mapper\n#if($ChildClassName)\npublic interface ${ChildClassName}Mapper extends PigxBaseMapper<${ChildClassName}Entity> {\n#else\npublic interface ${ClassName}Mapper extends PigxBaseMapper<${ClassName}Entity> {\n#end\n\n}', '2023-02-23 01:18:18', '2023-08-07 09:54:36', '0', 1, ' ', ' ');
INSERT INTO `gen_template` (`id`, `template_name`, `generator_path`, `template_desc`, `template_code`, `create_time`, `update_time`, `del_flag`, `tenant_id`, `create_by`, `update_by`) VALUES (1,'ControllerV202611','${backendPath}/src/main/java/${packagePath}/${moduleName}/controller/${ClassName}Controller.java','ControllerV202611','## 查询条件按需导入:字符串字段和组织关键字用 StrUtil,其余类型用 Objects;复选框与日期范围两者都不用\n#set($needStrUtil = false)\n#set($needObjects = false)\n#foreach($field in $queryList)\n#if($field.formType == \'checkbox\' || $field.queryFormType == \'daterange\' || $field.queryFormType == \'datetimerange\')\n#elseif($field.formType.startsWith(\'org-\') || $field.attrType == \'String\')\n#set($needStrUtil = true)\n#else\n#set($needObjects = true)\n#end\n#end\n#set($hasOrgQuery = false)\n#foreach($field in $queryList)\n#if($field.formType.startsWith(\'org-\'))\n#set($hasOrgQuery = true)\n#end\n#end\n## 组织字段以 [{id,name}] JSON 存储,按 ${attrName}Keyword 对整列模糊查询,分页和导出共用\n#macro(orgKeywordParams)#foreach($field in $queryList)#if($field.formType.startsWith(\'org-\')), @RequestParam(required = false) String ${field.attrName}Keyword#end#end#end\n#macro(orgKeywordDecl)#foreach($field in $queryList)#if($field.formType.startsWith(\'org-\')), String ${field.attrName}Keyword#end#end#end\n#macro(orgKeywordArgs)#foreach($field in $queryList)#if($field.formType.startsWith(\'org-\')), ${field.attrName}Keyword#end#end#end\n#macro(orgKeywordFilters)\n#if($hasOrgQuery)\n // 组织字段对整列 JSON 做 LIKE:关键字为数字或 id/name 时会误命中,需精确匹配时改用数据库 JSON 函数\n#end\n#foreach($field in $queryList)\n#if($field.formType.startsWith(\'org-\'))\n wrapper.like(StrUtil.isNotBlank(${field.attrName}Keyword), ${ClassName}Entity::$str.getProperty($field.attrName), ${field.attrName}Keyword);\n#end\n#end\n#end\n#set($permissionPrefix = \"${moduleName}_${functionName}\")\n#set($permissionPrefix = $permissionPrefix.toLowerCase())\npackage ${package}.${moduleName}.controller;\n\n#if($needStrUtil)\nimport cn.hutool.core.util.StrUtil;\n#end\nimport cn.hutool.core.util.ArrayUtil;\nimport cn.hutool.core.collection.CollUtil;\nimport com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;\nimport com.baomidou.mybatisplus.core.toolkit.Wrappers;\nimport com.baomidou.mybatisplus.extension.plugins.pagination.Page;\nimport ${package}.common.core.util.R;\nimport ${package}.common.log.annotation.SysLog;\n#if($opensource)\nimport com.pig4cloud.plugin.excel.annotation.ResponseExcel;\nimport com.pig4cloud.plugin.excel.annotation.RequestExcel;\n#else\nimport ${package}.common.excel.annotation.ResponseExcel;\nimport ${package}.common.excel.annotation.RequestExcel;\n#end\nimport ${entityClassName};\nimport ${package}.${moduleName}.service.${ClassName}Service;\n\nimport io.swagger.v3.oas.annotations.security.SecurityRequirement;\n#if($isSpringBoot3)\nimport ${package}.common.security.annotation.HasPermission;\nimport org.springdoc.core.annotations.ParameterObject;\n#else\nimport org.springframework.security.access.prepost.PreAuthorize;\nimport org.springdoc.api.annotations.ParameterObject;\n#end\nimport org.springframework.http.HttpHeaders;\nimport io.swagger.v3.oas.annotations.tags.Tag;\nimport io.swagger.v3.oas.annotations.Operation;\nimport lombok.RequiredArgsConstructor;\nimport org.springframework.validation.BindingResult;\nimport org.springframework.web.bind.annotation.*;\n\nimport java.util.List;\n#if($needObjects)\nimport java.util.Objects;\n#end\n\n/**\n * ${tableComment}\n *\n * @author ${author}\n * @date ${datetime}\n */\n@RestController\n@RequiredArgsConstructor\n@RequestMapping(\"/${functionName}\" )\n@Tag(description = \"${functionName}\" , name = \"${tableComment}管理\" )\n@SecurityRequirement(name = HttpHeaders.AUTHORIZATION)\npublic class ${ClassName}Controller {\n\n private final ${ClassName}Service ${className}Service;\n\n /**\n * 分页查询\n * @param page 分页对象\n * @param ${className} ${tableComment}\n * @return\n */\n @Operation(summary = \"分页查询\" , description = \"分页查询\" )\n @GetMapping(\"/page\" )\n #if($isSpringBoot3)\n @HasPermission(\"${permissionPrefix}_view\")\n #else\n @PreAuthorize(\"@pms.hasPermission(\'${permissionPrefix}_view\')\" )\n #end\n public R get${ClassName}Page(@ParameterObject Page page, @ParameterObject ${ClassName}Entity ${className}#orgKeywordParams()) {\n return R.ok(${className}Service.page(page, buildQueryWrapper(${className}#orgKeywordArgs())));\n }\n\n /**\n * 列表与导出共用的查询条件,保证导出结果与列表一致\n */\n private LambdaQueryWrapper<${ClassName}Entity> buildQueryWrapper(${ClassName}Entity ${className}#orgKeywordDecl()) {\n LambdaQueryWrapper<${ClassName}Entity> wrapper = Wrappers.lambdaLine truncated
INSERT INTO `gen_template` (`id`, `template_name`, `generator_path`, `template_desc`, `template_code`, `create_time`, `update_time`, `del_flag`, `tenant_id`, `create_by`, `update_by`) VALUES (2,'ServiceV202611','${backendPath}/src/main/java/${packagePath}/${moduleName}/service/${ClassName}Service.java','ServiceV202611','package ${package}.${moduleName}.service;\n\nimport com.baomidou.mybatisplus.spring.service.IService;\nimport ${entityClassName};\n\npublic interface ${ClassName}Service extends IService<${ClassName}Entity> {\n\n}\n','2026-04-08 17:38:24','2026-04-08 17:38:24','0',1,'admin','admin');
INSERT INTO `gen_template` (`id`, `template_name`, `generator_path`, `template_desc`, `template_code`, `create_time`, `update_time`, `del_flag`, `tenant_id`, `create_by`, `update_by`) VALUES (3,'ServiceImplV202611','${backendPath}/src/main/java/${packagePath}/${moduleName}/service/impl/${ClassName}ServiceImpl.java','ServiceImplV202611','package ${package}.${moduleName}.service.impl;\n\nimport com.baomidou.mybatisplus.spring.service.impl.ServiceImpl;\nimport ${entityClassName};\nimport ${package}.${moduleName}.mapper.${ClassName}Mapper;\nimport ${package}.${moduleName}.service.${ClassName}Service;\nimport org.springframework.stereotype.Service;\n\n/**\n * ${tableComment}\n *\n * @author ${author}\n * @date ${datetime}\n */\n@Service\npublic class ${ClassName}ServiceImpl extends ServiceImpl<${ClassName}Mapper, ${ClassName}Entity> implements ${ClassName}Service {\n\n}\n','2026-04-08 17:38:24','2026-04-08 17:38:24','0',1,'admin','admin');
INSERT INTO `gen_template` (`id`, `template_name`, `generator_path`, `template_desc`, `template_code`, `create_time`, `update_time`, `del_flag`, `tenant_id`, `create_by`, `update_by`) VALUES (4,'实体V202611','${entityPath}/src/main/java/${entityPackagePath}/${ClassName}Entity.java','实体V202611','#set($hasOrg = false)\n#foreach($field in $fieldList)\n#if($field.formType.startsWith(\'org-\'))\n#set($hasOrg = true)\n#end\n#end\npackage ${entityPackage};\n\nimport com.baomidou.mybatisplus.annotation.*;\nimport com.baomidou.mybatisplus.spring.activerecord.Model;\nimport io.swagger.v3.oas.annotations.media.Schema;\nimport lombok.Data;\nimport lombok.EqualsAndHashCode;\n#if($hasOrg)\nimport com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler;\nimport ${package}.common.core.util.OrgRef;\nimport org.apache.fesod.sheet.annotation.ExcelIgnore;\nimport java.util.List;\n#end\n#if($isTenant)\nimport ${package}.common.core.util.TenantTable;\n#end\n#foreach($import in $importList)\n#if(!$import.startsWith(\'java.lang.\'))\nimport $import;\n#end\n#end\n\n/**\n * ${tableComment}\n *\n * @author ${author}\n * @date ${datetime}\n */\n@Data\n#if($isTenant)\n@TenantTable\n#end\n@TableName(value = \"${tableName}\"#if($hasOrg), autoResultMap = true#end)\n@EqualsAndHashCode(callSuper = true)\n@Schema(description = \"${tableComment}\")\npublic class ${ClassName}Entity extends Model<${ClassName}Entity> {\n\n#foreach ($field in $fieldList)\n#if(${field.fieldComment})#set($comment=${field.fieldComment})#else #set($comment=${field.attrName})#end\n\n /**\n * $comment\n */\n#if($field.primaryPk == \'1\')\n @TableId(type = IdType.ASSIGN_ID)\n#end\n#if($field.formType.startsWith(\'org-\'))\n @TableField(typeHandler = JacksonTypeHandler.class#if($field.autoFill == \'INSERT\' || $field.autoFill == \'INSERT_UPDATE\' || $field.autoFill == \'UPDATE\'), fill = FieldFill.${field.autoFill}#end)\n @ExcelIgnore\n#elseif($field.autoFill == \'INSERT\')\n @TableField(fill = FieldFill.INSERT)\n#elseif($field.autoFill == \'INSERT_UPDATE\')\n @TableField(fill = FieldFill.INSERT_UPDATE)\n#elseif($field.autoFill == \'UPDATE\')\n @TableField(fill = FieldFill.UPDATE)\n#end\n#if($field.fieldName == \'del_flag\')\n @TableLogic\n @TableField(fill = FieldFill.INSERT)\n#end\n @Schema(description=\"$comment\"#if($field.hidden),hidden=$field.hidden#end)\n#if($field.formType.startsWith(\'org-\'))\n private List<OrgRef> $field.attrName;\n#elseif($field.formType == \'checkbox\')\n private ${field.attrType}[] $field.attrName;\n#elseif($field.formType == \'daterange\' || $field.formType == \'datetimerange\')\n private String[] $field.attrName;\n#else\n private $field.attrType $field.attrName;\n#end\n#end\n#foreach ($field in $queryList)\n#if($field.queryFormType == \'daterange\' || $field.queryFormType == \'datetimerange\')\n#if(${field.fieldComment})#set($comment=${field.fieldComment})#else #set($comment=${field.attrName})#end\n\n /**\n * $comment 查询范围\n */\n @TableField(exist = false)\n @Schema(description=\"$comment 查询范围\",hidden=true)\n private String[] ${field.attrName}Range;\n#end\n#end\n}\n','2026-04-08 17:38:24','2026-04-08 17:38:24','0',1,'admin','admin');
INSERT INTO `gen_template` (`id`, `template_name`, `generator_path`, `template_desc`, `template_code`, `create_time`, `update_time`, `del_flag`, `tenant_id`, `create_by`, `update_by`) VALUES (5,'MapperV202611','${backendPath}/src/main/java/${packagePath}/${moduleName}/mapper/${ClassName}Mapper.java','MapperV202611','package ${package}.${moduleName}.mapper;\n\n\nimport com.baomidou.mybatisplus.core.mapper.BaseMapper;\nimport ${entityClassName};\nimport org.apache.ibatis.annotations.Mapper;\n\n@Mapper\npublic interface ${ClassName}Mapper extends BaseMapper<${ClassName}Entity> {\n\n}\n','2026-04-08 17:38:24','2026-04-08 17:38:24','0',1,'admin','admin');
INSERT INTO `gen_template` (`id`, `template_name`, `generator_path`, `template_desc`, `template_code`, `create_time`, `update_time`, `del_flag`, `tenant_id`, `create_by`, `update_by`) VALUES (6,'Mapper.xmlV202611','${backendPath}/src/main/resources/mapper/${ClassName}Mapper.xml','Mapper.xmlV202611','<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE mapper PUBLIC \"-//mybatis.org//DTD Mapper 3.0//EN\" \"http://mybatis.org/dtd/mybatis-3-mapper.dtd\">\n\n<mapper namespace=\"${package}.${moduleName}.mapper.${ClassName}Mapper\">\n\n <resultMap id=\"${className}Map\" type=\"${entityClassName}\">\n#foreach ($field in $fieldList)\n #if($field.primaryPk == \'1\')\n <id property=\"$field.attrName\" column=\"$field.fieldName\"/>\n #else\n <result property=\"$field.attrName\" column=\"$field.fieldName\"#if($field.formType.startsWith(\'org-\')) typeHandler=\"com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler\"#end/>\n #end\n#end\n </resultMap>\n</mapper>\n','2026-04-08 17:38:24','2026-04-08 17:38:24','0',1,'admin','admin');
INSERT INTO `gen_template` (`id`, `template_name`, `generator_path`, `template_desc`, `template_code`, `create_time`, `update_time`, `del_flag`, `tenant_id`, `create_by`, `update_by`) VALUES (7,'权限菜单V202611','${backendPath}/menu/${functionName}_menu.sql','权限菜单V202611','#set($permissionPrefix = \"${moduleName}_${functionName}\")\n#set($permissionPrefix = $permissionPrefix.toLowerCase())\n-- 该脚本不要直接执行, 注意维护菜单的父节点ID 默认 父节点-1 , #if(!$opensource)默认租户 1#end\n#set($menuId=${dateTool.getSystemTime()})\n\n-- 菜单SQL\ninsert into sys_menu ( menu_id,parent_id, path, permission, menu_type, icon, del_flag, create_time, sort_order, update_time, name#if(!$opensource), tenant_id#end)\nvalues (${menuId}, \'-1\', \'/${moduleName}/${functionName}/index\', \'\', \'0\', \'icon-bangzhushouji\', \'0\', null , \'8\', null , \'${tableComment}管理\'#if(!$opensource), 1#end);\n\n-- 菜单对应按钮SQL\ninsert into sys_menu ( menu_id,parent_id, permission, menu_type, path, icon, del_flag, create_time, sort_order, update_time, name#if(!$opensource), tenant_id#end)\nvalues (${math.add($menuId,1)},${menuId}, \'${permissionPrefix}_view\', \'1\', null, \'1\', \'0\', null, \'0\', null, \'${tableComment}查看\'#if(!$opensource), 1#end);\n\ninsert into sys_menu ( menu_id,parent_id, permission, menu_type, path, icon, del_flag, create_time, sort_order, update_time, name#if(!$opensource), tenant_id#end)\nvalues (${math.add($menuId,2)},${menuId}, \'${permissionPrefix}_add\', \'1\', null, \'1\', \'0\', null, \'1\', null, \'${tableComment}新增\'#if(!$opensource), 1#end);\n\ninsert into sys_menu (menu_id, parent_id, permission, menu_type, path, icon, del_flag, create_time, sort_order, update_time, name#if(!$opensource), tenant_id#end)\nvalues (${math.add($menuId,3)},${menuId}, \'${permissionPrefix}_edit\', \'1\', null, \'1\', \'0\', null, \'2\', null, \'${tableComment}修改\'#if(!$opensource), 1#end);\n\ninsert into sys_menu (menu_id, parent_id, permission, menu_type, path, icon, del_flag, create_time, sort_order, update_time, name#if(!$opensource), tenant_id#end)\nvalues (${math.add($menuId,4)},${menuId}, \'${permissionPrefix}_del\', \'1\', null, \'1\', \'0\', null, \'3\', null, \'${tableComment}删除\'#if(!$opensource), 1#end);\n\ninsert into sys_menu ( menu_id,parent_id, permission, menu_type, path, icon, del_flag, create_time, sort_order, update_time, name#if(!$opensource), tenant_id#end)\nvalues (${math.add($menuId,5)},${menuId}, \'${permissionPrefix}_export\', \'1\', null, \'1\', \'0\', null, \'3\', null, \'导入导出\'#if(!$opensource), 1#end);\n','2026-04-08 17:38:24','2026-04-08 17:38:24','0',1,'admin','admin');
INSERT INTO `gen_template` (`id`, `template_name`, `generator_path`, `template_desc`, `template_code`, `create_time`, `update_time`, `del_flag`, `tenant_id`, `create_by`, `update_by`) VALUES (8,'api.tsV202611','${frontendPath}/src/api/${moduleName}/${functionName}.ts','api.tsV202611','import request from \"/@/utils/request\"\n\n// ========== 基础CRUD接口 ==========\n\n/**\n * 分页查询列表数据\n * @param query - 查询参数对象\n * @returns Promise<分页数据>\n */\nexport function fetchList(query?: Object) {\n return request({\n url: \'/${moduleName}/${functionName}/page\',\n method: \'get\',\n params: query\n })\n}\n\n/**\n * 新增数据\n * @param obj - 要新增的数据对象\n * @returns Promise<boolean> - 操作结果\n */\nexport function addObj(obj?: Object) {\n return request({\n url: \'/${moduleName}/${functionName}\',\n method: \'post\',\n data: obj\n })\n}\n\n/**\n * 获取详情数据\n * @param obj - 查询参数对象(包含ID等)\n * @returns Promise<数据详情>\n */\nexport function getObj(obj?: Object) {\n return request({\n url: \'/${moduleName}/${functionName}/details\',\n method: \'get\',\n params: obj\n })\n}\n\n/**\n * 批量删除数据\n * @param ids - 要删除的ID数组\n * @returns Promise<操作结果>\n */\nexport function delObjs(ids?: Object) {\n return request({\n url: \'/${moduleName}/${functionName}\',\n method: \'delete\',\n data: ids\n })\n}\n\n/**\n * 更新数据\n * @param obj - 要更新的数据对象\n * @returns Promise<操作结果>\n */\nexport function putObj(obj?: Object) {\n return request({\n url: \'/${moduleName}/${functionName}\',\n method: \'put\',\n data: obj\n })\n}\n\n// ========== 工具函数 ==========\n\n/**\n * 验证字段值唯一性\n * @param rule - 验证规则对象\n * @param value - 要验证的值\n * @param callback - 验证回调函数\n * @param isEdit - 是否为编辑模式\n * \n * @example\n * // 在表单验证规则中使用\n * fieldName: [\n * {\n * validator: (rule, value, callback) => {\n * validateExist(rule, value, callback, form.${pk.attrName} !== \'\');\n * },\n * trigger: \'blur\',\n * },\n * ]\n */\nexport function validateExist(rule: any, value: any, callback: any, isEdit: boolean) {\n // 编辑模式下跳过验证\n if (isEdit) {\n return callback();\n }\n\n // 查询是否存在相同值\n getObj({ [rule.field]: value }).then((response) => {\n const result = response.data;\n if (result !== null && result.length > 0) {\n callback(new Error(\'数据已经存在\'));\n } else {\n callback();\n }\n });\n}\n\n#if($ChildClassName)\n// ========== 子表相关接口 ==========\n\n/**\n * 删除子表数据\n * @param ids - 要删除的子表数据ID数组\n * @returns Promise<操作结果>\n */\nexport function delChildObj(ids?: Object) {\n return request({\n url: \'/${moduleName}/${functionName}/child\',\n method: \'delete\',\n data: ids\n })\n}\n#end\n','2026-04-08 17:38:24','2026-04-08 17:38:24','0',1,'admin','admin');
INSERT INTO `gen_template` (`id`, `template_name`, `generator_path`, `template_desc`, `template_code`, `create_time`, `update_time`, `del_flag`, `tenant_id`, `create_by`, `update_by`) VALUES (9,'表格V202611','${frontendPath}/src/views/${moduleName}/${functionName}/index.vue','表格V202611','## 有字典字段时才导入 useDict\n#set($hasDictField = false)\n#foreach($field in $queryList)\n#if($field.fieldDict)\n#set($hasDictField = true)\n#end\n#end\n#foreach($field in $gridList)\n#if($field.fieldDict)\n#set($hasDictField = true)\n#end\n#end\n## 开关:按属性类型决定开/关的值,Boolean 用 true/false,整型用 1/0,其余用 \'1\'/\'0\'\n#macro(switchValues $f)\n#if($f.attrType == \'Boolean\')\n#set($switchOn = \'true\')\n#set($switchOff = \'false\')\n#elseif($f.attrType == \'Integer\' || $f.attrType == \'Long\' || $f.attrType == \'Short\')\n#set($switchOn = \'1\')\n#set($switchOff = \'0\')\n#else\n#set($switchOn = "\'1\'")\n#set($switchOff = "\'0\'")\n#end\n#end\n#set($permissionPrefix = "${moduleName}_${functionName}")\n#set($permissionPrefix = $permissionPrefix.toLowerCase())\n<template>\n <div class="layout-padding">\n <div class="layout-padding-auto layout-padding-view">\n#if($queryList)\n <!-- 查询表单区域 -->\n <el-row v-show="showSearch">\n <el-form :model="state.queryForm" ref="queryRef" :inline="true" @keyup.enter="getDataList">\n#foreach($field in $queryList)\n#if($field.formType.startsWith(\'org-\'))#set($queryKey = "${field.attrName}Keyword")#else#set($queryKey = $field.attrName)#end\n#if($field.queryFormType == \'select\')\n <el-form-item label="#if(${field.fieldComment})${field.fieldComment}#else${field.attrName}#end" prop="${field.attrName}">\n <el-select v-model="state.queryForm.${field.attrName}" placeholder="请选择#if(${field.fieldComment})${field.fieldComment}#else${field.attrName}#end">\n#if($field.fieldDict)\n <el-option \n :label="item.label" \n :value="item.value" \n v-for="(item, index) in ${field.fieldDict}" \n :key="index"\n />\n#else\n <el-option label="请选择" value="0" />\n#end\n </el-select>\n </el-form-item>\n#elseif($field.queryFormType == \'date\')\n <el-form-item label="#if(${field.fieldComment})${field.fieldComment}#else${field.attrName}#end" prop="${field.attrName}">\n <el-date-picker\n type="date"\n placeholder="请输入#if(${field.fieldComment})${field.fieldComment}#else${field.attrName}#end"\n v-model="state.queryForm.${field.attrName}"\n :value-format="dateStr"\n />\n </el-form-item>\n#elseif($field.queryFormType == \'daterange\')\n <el-form-item label="#if(${field.fieldComment})${field.fieldComment}#else${field.attrName}#end" prop="${field.attrName}Range">\n <el-date-picker\n type="daterange"\n range-separator="至"\n start-placeholder="开始日期"\n end-placeholder="结束日期"\n v-model="state.queryForm.${field.attrName}Range"\n :value-format="dateStr"\n />\n </el-form-item>\n#elseif($field.queryFormType == \'datetime\')\n <el-form-item label="#if(${field.fieldComment})${field.fieldComment}#else${field.attrName}#end" prop="${field.attrName}">\n <el-date-picker\n type="datetime"\n placeholder="请输入#if(${field.fieldComment})${field.fieldComment}#else${field.attrName}#end"\n v-model="state.queryForm.${field.attrName}"\n :value-format="dateTimeStr"\n />\n </el-form-item>\n#elseif($field.queryFormType == \'datetimerange\')\n <el-form-item label="#if(${field.fieldComment})${field.fieldComment}#else${field.attrName}#end" prop="${field.attrName}Range">\n <el-date-picker\n type="datetimerange"\n range-separator="至"\n start-placeholder="开始时间"\n end-placeholder="结束时间"\n v-model="state.queryForm.${field.attrName}Range"\n :value-format="dateTimeStr"\n />\n </el-form-item>\n#elseif($field.formType == \'radio\')\n <el-form-item label="#if(${field.fieldComment})${field.fieldComment}#else${field.attrName}#end" prop="${field.attrName}">\n <el-radio-group v-model="state.queryForm.${field.attrName}">\n#if($field.fieldDict)\n <el-radio \n :label="item.value" \n v-for="(item, index) in ${field.fieldDict}" \n border \n :key="index"\n >\n {{ item.label }}\n </el-radio>\n#else\n <el-radio label="${field.fieldComment}" border>\n ${field.fieldComment}\n </el-radio>\n#end\n </el-rLine truncated
INSERT INTO `gen_template` (`id`, `template_name`, `generator_path`, `template_desc`, `template_code`, `create_time`, `update_time`, `del_flag`, `tenant_id`, `create_by`, `update_by`) VALUES (10,'表单V202611','${frontendPath}/src/views/${moduleName}/${functionName}/form.vue','表单V202611','## 有字典字段时才导入 useDict\n#set($hasDictField = false)\n#foreach($field in $formList)\n#if($field.fieldDict)\n#set($hasDictField = true)\n#end\n#end\n#set($hasDuplicate = false)\n#foreach($field in $formList)\n#if($field.formValidator == \'duplicate\')\n#set($hasDuplicate = true)\n#end\n#end\n## 开关:按属性类型决定开/关的值,Boolean 用 true/false,整型用 1/0,其余用 \'1\'/\'0\'\n#macro(switchValues $f)\n#if($f.attrType == \'Boolean\')\n#set($switchOn = \'true\')\n#set($switchOff = \'false\')\n#elseif($f.attrType == \'Integer\' || $f.attrType == \'Long\' || $f.attrType == \'Short\')\n#set($switchOn = \'1\')\n#set($switchOff = \'0\')\n#else\n#set($switchOn = "\'1\'")\n#set($switchOff = "\'0\'")\n#end\n#end\n#set($hasOrg = false)\n#foreach($field in $formList)\n#if($field.formType.startsWith(\'org-\'))\n#set($hasOrg = true)\n#end\n#end\n<template>\n <el-dialog :title="form.${pk.attrName} ? \'编辑\' : \'新增\'" v-model="visible"\n :close-on-click-modal="false" draggable>\n <el-form ref="dataFormRef" :model="form" :rules="dataRules" label-width="90px" v-loading="loading">\n <el-row :gutter="24">\n#foreach($field in $formList)\n#if($field.attrName != ${pk.attrName})\n#if($formLayout == 1)\n <el-col :span="24" class="mb20">\n#elseif($formLayout == 2)\n <el-col :span="12" class="mb20">\n#end\n#if($field.formType.startsWith(\'org-\'))\n#set($orgType = $field.formType.replace(\'org-\', \'\').replace(\'-multiple\', \'\'))\n <el-form-item label="${field.fieldComment}" prop="${field.attrName}">\n <OrgSelect v-model="form.${field.attrName}" value-type="item" type="${orgType}" :multiple="#if($field.formType.endsWith(\'-multiple\'))true#else false#end" label="${field.fieldComment}" :disabled="loading" />\n </el-form-item>\n </el-col>\n#elseif($field.formType == \'switch\')\n#switchValues($field)\n <el-form-item label="#if(${field.fieldComment})${field.fieldComment}#else${field.attrName}#end" prop="${field.attrName}">\n <el-switch :model-value="String(form.${field.attrName}) === String($switchOn)" @change="(checked) => (form.${field.attrName} = checked ? $switchOn : $switchOff)" />\n </el-form-item>\n </el-col>\n#elseif($field.formType == \'text\')\n <el-form-item label="#if(${field.fieldComment})${field.fieldComment}#else${field.attrName}#end" prop="${field.attrName}">\n <el-input v-model="form.${field.attrName}" placeholder="请输入#if(${field.fieldComment})${field.fieldComment}#else${field.attrName}#end"/>\n </el-form-item>\n </el-col>\n#elseif($field.formType == \'textarea\')\n <el-form-item label="#if(${field.fieldComment})${field.fieldComment}#else${field.attrName}#end" prop="${field.attrName}">\n <el-input type="textarea" v-model="form.${field.attrName}" placeholder="请输入#if(${field.fieldComment})${field.fieldComment}#else${field.attrName}#end"/>\n </el-form-item>\n </el-col>\n#elseif($field.formType == \'select\')\n <el-form-item label="#if(${field.fieldComment})${field.fieldComment}#else${field.attrName}#end" prop="${field.attrName}">\n <el-select v-model="form.${field.attrName}" placeholder="请选择#if(${field.fieldComment})${field.fieldComment}#else${field.attrName}#end">\n#if($field.fieldDict)\n <el-option :value="item.value" :label="item.label" v-for="(item, index) in ${field.fieldDict}" :key="index"></el-option>\n#else\n <el-option label="请选择" value="0"></el-option>\n#end\n </el-select>\n </el-form-item>\n </el-col>\n#elseif($field.formType == \'radio\')\n <el-form-item label="#if(${field.fieldComment})${field.fieldComment}#else${field.attrName}#end" prop="${field.attrName}">\n <el-radio-group v-model="form.${field.attrName}">\n#if($field.fieldDict)\n <el-radio :label="item.value" v-for="(item, index) in ${field.fieldDict}" border :key="index">{{ item.label }}</el-radio>\n#else\n <el-radio label="${field.fieldComment}" border>${field.fieldComment}</el-radio>\n#end\n </el-radio-group>\n </el-form-item>\n </el-col>\n#elseif($field.formType == \'checkbox\')\n <el-form-item label="#if(${field.fieldComment})${field.fieldComment}#else${field.attrName}#end" prop="${field.attrName}">\n <el-checkbox-group v-model="form.${field.attrName}">\n#if($field.fieldDict)\n <el-checkbox :label="item.value" v-for="(item, index) in ${field.fieldDict}" :key="index">{{ item.label }}</el-checkbox>\n#else\n <el-checkbox label="启用"Line truncated
INSERT INTO `gen_template` (`id`, `template_name`, `generator_path`, `template_desc`, `template_code`, `create_time`, `update_time`, `del_flag`, `tenant_id`, `create_by`, `update_by`) VALUES (11,'主子ServiceV202611','${backendPath}/src/main/java/${packagePath}/${moduleName}/service/${ClassName}Service.java','主子ServiceV202611','#foreach($field in $childFieldList)\n#if($field.primaryPk == \'1\')\n#set($childPk = $field)\n#end\n#end\npackage ${package}.${moduleName}.service;\n\nimport com.github.yulichang.extension.mapping.base.MPJDeepService;\nimport ${entityClassName};\n\npublic interface ${ClassName}Service extends MPJDeepService<${ClassName}Entity> {\n Boolean saveDeep(${ClassName}Entity ${className});\n\n Boolean updateDeep(${ClassName}Entity ${className});\n\n Boolean removeDeep(${pk.attrType}[] ids);\n\n Boolean removeChild(${childPk.attrType}[] ids);\n}\n','2026-04-08 17:38:24','2026-04-08 17:38:24','0',1,'admin','admin');
INSERT INTO `gen_template` (`id`, `template_name`, `generator_path`, `template_desc`, `template_code`, `create_time`, `update_time`, `del_flag`, `tenant_id`, `create_by`, `update_by`) VALUES (12,'主子ServiceImplV202611','${backendPath}/src/main/java/${packagePath}/${moduleName}/service/impl/${ClassName}ServiceImpl.java','主子ServiceImplV202611','#foreach($field in $childFieldList)\n#if($field.primaryPk == \'1\')\n#set($childPk = $field)\n#end\n#end\npackage ${package}.${moduleName}.service.impl;\n\nimport com.baomidou.mybatisplus.spring.service.impl.ServiceImpl;\nimport ${entityClassName};\nimport ${package}.${moduleName}.mapper.${ClassName}Mapper;\nimport ${package}.${moduleName}.service.${ClassName}Service;\nimport org.springframework.stereotype.Service;\nimport cn.hutool.core.collection.CollUtil;\nimport com.baomidou.mybatisplus.core.toolkit.Wrappers;\nimport ${entityPackage}.${ChildClassName}Entity;\nimport ${package}.${moduleName}.mapper.${ChildClassName}Mapper;\nimport org.springframework.transaction.annotation.Transactional;\nimport lombok.RequiredArgsConstructor;\nimport java.util.Objects;\nimport java.util.List;\nimport java.util.stream.Collectors;\n\n/**\n * ${tableComment}\n *\n * @author ${author}\n * @date ${datetime}\n */\n@Service\n@RequiredArgsConstructor\npublic class ${ClassName}ServiceImpl extends ServiceImpl<${ClassName}Mapper, ${ClassName}Entity> implements ${ClassName}Service {\n\n private final ${ChildClassName}Mapper ${childClassName}Mapper;\n\n @Override\n @Transactional(rollbackFor = Exception.class)\n public Boolean saveDeep(${ClassName}Entity ${className}) {\n baseMapper.insert(${className});\n for (${ChildClassName}Entity ${childClassName} : ${className}.get${ChildClassName}List()) {\n ${childClassName}.$str.setProperty($childField)(${className}.$str.getProperty($mainField)());\n ${childClassName}Mapper.insert( ${childClassName});\n }\n\n return Boolean.TRUE;\n }\n\n @Override\n @Transactional(rollbackFor = Exception.class)\n public Boolean updateDeep(${ClassName}Entity ${className}) {\n baseMapper.updateById(${className});\n for (${ChildClassName}Entity ${childClassName} : ${className}.get${ChildClassName}List()) {\n#set($getChildPkName=$str.getProperty(${childPk.attrName}))\n if (Objects.isNull(${childClassName}.$getChildPkName())) {\n ${childClassName}.$str.setProperty($childField)(${className}.$str.getProperty($mainField)());\n ${childClassName}Mapper.insert(${childClassName});\n } else {\n ${childClassName}Mapper.updateById(${childClassName});\n }\n }\n return Boolean.TRUE;\n }\n\n @Override\n @Transactional(rollbackFor = Exception.class)\n public Boolean removeDeep(${pk.attrType}[] ids) {\n List<${ClassName}Entity> records = baseMapper.selectBatchIds(CollUtil.toList(ids));\n if (CollUtil.isEmpty(records)) {\n return Boolean.TRUE;\n }\n ${childClassName}Mapper.delete(Wrappers.<${ChildClassName}Entity>lambdaQuery()\n .in(${ChildClassName}Entity::$str.getProperty($childField), records.stream()\n .map(${ClassName}Entity::$str.getProperty($mainField)).collect(Collectors.toList())));\n baseMapper.deleteBatchIds(CollUtil.toList(ids));\n return Boolean.TRUE;\n }\n\n @Override\n @Transactional(rollbackFor = Exception.class)\n public Boolean removeChild(${childPk.attrType}[] ids) {\n ${childClassName}Mapper.deleteBatchIds(CollUtil.toList(ids));\n return Boolean.TRUE;\n }\n}\n','2026-04-08 17:38:24','2026-04-08 17:38:24','0',1,'admin','admin');
INSERT INTO `gen_template` (`id`, `template_name`, `generator_path`, `template_desc`, `template_code`, `create_time`, `update_time`, `del_flag`, `tenant_id`, `create_by`, `update_by`) VALUES (13,'主实体V202611','${entityPath}/src/main/java/${entityPackagePath}/${ClassName}Entity.java','主实体V202611','#set($hasOrg = false)\n#foreach($field in $fieldList)\n#if($field.formType.startsWith(\'org-\'))\n#set($hasOrg = true)\n#end\n#end\npackage ${entityPackage};\n\nimport com.baomidou.mybatisplus.annotation.*;\nimport com.baomidou.mybatisplus.spring.activerecord.Model;\nimport io.swagger.v3.oas.annotations.media.Schema;\nimport lombok.Data;\nimport lombok.EqualsAndHashCode;\n#if($hasOrg)\nimport com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler;\nimport ${package}.common.core.util.OrgRef;\n#end\n#if($isTenant)\nimport ${package}.common.core.util.TenantTable;\n#end\n#foreach($import in $importList)\n#if(!$import.startsWith(\'java.lang.\'))\nimport $import;\n#end\n#end\nimport org.apache.fesod.sheet.annotation.ExcelIgnore;\nimport com.github.yulichang.annotation.EntityMapping;\nimport java.util.List;\n\n/**\n * ${tableComment}\n *\n * @author ${author}\n * @date ${datetime}\n */\n@Data\n#if($isTenant)\n@TenantTable\n#end\n@TableName(value = \"${tableName}\"#if($hasOrg), autoResultMap = true#end)\n@EqualsAndHashCode(callSuper = true)\n@Schema(description = \"${tableComment}\")\npublic class ${ClassName}Entity extends Model<${ClassName}Entity> {\n\n#foreach ($field in $fieldList)\n#if(${field.fieldComment})#set($comment=${field.fieldComment})#else #set($comment=${field.attrName})#end\n\n /**\n * $comment\n */\n#if($field.primaryPk == \'1\')\n @TableId(type = IdType.ASSIGN_ID)\n#end\n#if($field.formType.startsWith(\'org-\'))\n @TableField(typeHandler = JacksonTypeHandler.class#if($field.autoFill == \'INSERT\' || $field.autoFill == \'INSERT_UPDATE\' || $field.autoFill == \'UPDATE\'), fill = FieldFill.${field.autoFill}#end)\n @ExcelIgnore\n#elseif($field.autoFill == \'INSERT\')\n @TableField(fill = FieldFill.INSERT)\n#elseif($field.autoFill == \'INSERT_UPDATE\')\n @TableField(fill = FieldFill.INSERT_UPDATE)\n#elseif($field.autoFill == \'UPDATE\')\n @TableField(fill = FieldFill.UPDATE)\n#end\n#if($field.fieldName == \'del_flag\')\n @TableLogic\n @TableField(fill = FieldFill.INSERT)\n#end\n @Schema(description=\"$comment\"#if($field.hidden),hidden=$field.hidden#end)\n#if($field.formType.startsWith(\'org-\'))\n private List<OrgRef> $field.attrName;\n#elseif($field.formType == \'checkbox\')\n private ${field.attrType}[] $field.attrName;\n#elseif($field.formType == \'daterange\' || $field.formType == \'datetimerange\')\n @TableField(typeHandler = JacksonTypeHandler.class)\n private String[] $field.attrName;\n#else\n private $field.attrType $field.attrName;\n#end\n#end\n#foreach ($field in $queryList)\n#if($field.queryFormType == \'daterange\' || $field.queryFormType == \'datetimerange\')\n#if(${field.fieldComment})#set($comment=${field.fieldComment})#else #set($comment=${field.attrName})#end\n\n /**\n * $comment 查询范围\n */\n @TableField(exist = false)\n @Schema(description=\"$comment 查询范围\",hidden=true)\n private String[] ${field.attrName}Range;\n#end\n#end\n @ExcelIgnore\n @TableField(exist = false)\n @EntityMapping(thisField = \"$mainField\", joinField = \"$childField\")\n private List<${ChildClassName}Entity> ${childClassName}List;\n}\n','2026-04-08 17:38:24','2026-04-08 17:38:24','0',1,'admin','admin');
INSERT INTO `gen_template` (`id`, `template_name`, `generator_path`, `template_desc`, `template_code`, `create_time`, `update_time`, `del_flag`, `tenant_id`, `create_by`, `update_by`) VALUES (14,'MapperV202611','${backendPath}/src/main/java/${packagePath}/${moduleName}/mapper/${ClassName}Mapper.java','MapperV202611','package ${package}.${moduleName}.mapper;\n\n\nimport com.baomidou.mybatisplus.core.mapper.BaseMapper;\nimport ${entityClassName};\nimport org.apache.ibatis.annotations.Mapper;\n\n@Mapper\npublic interface ${ClassName}Mapper extends BaseMapper<${ClassName}Entity> {\n\n}\n','2026-04-08 17:38:24','2026-04-08 17:38:24','0',1,'admin','admin');
INSERT INTO `gen_template` (`id`, `template_name`, `generator_path`, `template_desc`, `template_code`, `create_time`, `update_time`, `del_flag`, `tenant_id`, `create_by`, `update_by`) VALUES (15,'Mapper.xmlV202611','${backendPath}/src/main/resources/mapper/${ClassName}Mapper.xml','Mapper.xmlV202611','<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE mapper PUBLIC \"-//mybatis.org//DTD Mapper 3.0//EN\" \"http://mybatis.org/dtd/mybatis-3-mapper.dtd\">\n\n<mapper namespace=\"${package}.${moduleName}.mapper.${ClassName}Mapper\">\n\n <resultMap id=\"${className}Map\" type=\"${entityClassName}\">\n#foreach ($field in $fieldList)\n #if($field.primaryPk == \'1\')\n <id property=\"$field.attrName\" column=\"$field.fieldName\"/>\n #else\n <result property=\"$field.attrName\" column=\"$field.fieldName\"#if($field.formType.startsWith(\'org-\')) typeHandler=\"com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler\"#end/>\n #end\n#end\n </resultMap>\n</mapper>\n','2026-04-08 17:38:24','2026-04-08 17:38:24','0',1,'admin','admin');
INSERT INTO `gen_template` (`id`, `template_name`, `generator_path`, `template_desc`, `template_code`, `create_time`, `update_time`, `del_flag`, `tenant_id`, `create_by`, `update_by`) VALUES (16,'权限菜单V202611','${backendPath}/menu/${functionName}_menu.sql','权限菜单V202611','#set($permissionPrefix = \"${moduleName}_${functionName}\")\n#set($permissionPrefix = $permissionPrefix.toLowerCase())\n-- 该脚本不要直接执行, 注意维护菜单的父节点ID 默认 父节点-1 , #if(!$opensource)默认租户 1#end\n#set($menuId=${dateTool.getSystemTime()})\n\n-- 菜单SQL\ninsert into sys_menu ( menu_id,parent_id, path, permission, menu_type, icon, del_flag, create_time, sort_order, update_time, name#if(!$opensource), tenant_id#end)\nvalues (${menuId}, \'-1\', \'/${moduleName}/${functionName}/index\', \'\', \'0\', \'icon-bangzhushouji\', \'0\', null , \'8\', null , \'${tableComment}管理\'#if(!$opensource), 1#end);\n\n-- 菜单对应按钮SQL\ninsert into sys_menu ( menu_id,parent_id, permission, menu_type, path, icon, del_flag, create_time, sort_order, update_time, name#if(!$opensource), tenant_id#end)\nvalues (${math.add($menuId,1)},${menuId}, \'${permissionPrefix}_view\', \'1\', null, \'1\', \'0\', null, \'0\', null, \'${tableComment}查看\'#if(!$opensource), 1#end);\n\ninsert into sys_menu ( menu_id,parent_id, permission, menu_type, path, icon, del_flag, create_time, sort_order, update_time, name#if(!$opensource), tenant_id#end)\nvalues (${math.add($menuId,2)},${menuId}, \'${permissionPrefix}_add\', \'1\', null, \'1\', \'0\', null, \'1\', null, \'${tableComment}新增\'#if(!$opensource), 1#end);\n\ninsert into sys_menu (menu_id, parent_id, permission, menu_type, path, icon, del_flag, create_time, sort_order, update_time, name#if(!$opensource), tenant_id#end)\nvalues (${math.add($menuId,3)},${menuId}, \'${permissionPrefix}_edit\', \'1\', null, \'1\', \'0\', null, \'2\', null, \'${tableComment}修改\'#if(!$opensource), 1#end);\n\ninsert into sys_menu (menu_id, parent_id, permission, menu_type, path, icon, del_flag, create_time, sort_order, update_time, name#if(!$opensource), tenant_id#end)\nvalues (${math.add($menuId,4)},${menuId}, \'${permissionPrefix}_del\', \'1\', null, \'1\', \'0\', null, \'3\', null, \'${tableComment}删除\'#if(!$opensource), 1#end);\n\ninsert into sys_menu ( menu_id,parent_id, permission, menu_type, path, icon, del_flag, create_time, sort_order, update_time, name#if(!$opensource), tenant_id#end)\nvalues (${math.add($menuId,5)},${menuId}, \'${permissionPrefix}_export\', \'1\', null, \'1\', \'0\', null, \'3\', null, \'导入导出\'#if(!$opensource), 1#end);\n','2026-04-08 17:38:24','2026-04-08 17:38:24','0',1,'admin','admin');
INSERT INTO `gen_template` (`id`, `template_name`, `generator_path`, `template_desc`, `template_code`, `create_time`, `update_time`, `del_flag`, `tenant_id`, `create_by`, `update_by`) VALUES (17,'api.tsV202611','${frontendPath}/src/api/${moduleName}/${functionName}.ts','api.tsV202611','import request from \"/@/utils/request\"\n\n// ========== 基础CRUD接口 ==========\n\n/**\n * 分页查询列表数据\n * @param query - 查询参数对象\n * @returns Promise<分页数据>\n */\nexport function fetchList(query?: Object) {\n return request({\n url: \'/${moduleName}/${functionName}/page\',\n method: \'get\',\n params: query\n })\n}\n\n/**\n * 新增数据\n * @param obj - 要新增的数据对象\n * @returns Promise<boolean> - 操作结果\n */\nexport function addObj(obj?: Object) {\n return request({\n url: \'/${moduleName}/${functionName}\',\n method: \'post\',\n data: obj\n })\n}\n\n/**\n * 获取详情数据\n * @param obj - 查询参数对象(包含ID等)\n * @returns Promise<数据详情>\n */\nexport function getObj(obj?: Object) {\n return request({\n url: \'/${moduleName}/${functionName}/details\',\n method: \'get\',\n params: obj\n })\n}\n\n/**\n * 批量删除数据\n * @param ids - 要删除的ID数组\n * @returns Promise<操作结果>\n */\nexport function delObjs(ids?: Object) {\n return request({\n url: \'/${moduleName}/${functionName}\',\n method: \'delete\',\n data: ids\n })\n}\n\n/**\n * 更新数据\n * @param obj - 要更新的数据对象\n * @returns Promise<操作结果>\n */\nexport function putObj(obj?: Object) {\n return request({\n url: \'/${moduleName}/${functionName}\',\n method: \'put\',\n data: obj\n })\n}\n\n// ========== 工具函数 ==========\n\n/**\n * 验证字段值唯一性\n * @param rule - 验证规则对象\n * @param value - 要验证的值\n * @param callback - 验证回调函数\n * @param isEdit - 是否为编辑模式\n * \n * @example\n * // 在表单验证规则中使用\n * fieldName: [\n * {\n * validator: (rule, value, callback) => {\n * validateExist(rule, value, callback, form.${pk.attrName} !== \'\');\n * },\n * trigger: \'blur\',\n * },\n * ]\n */\nexport function validateExist(rule: any, value: any, callback: any, isEdit: boolean) {\n // 编辑模式下跳过验证\n if (isEdit) {\n return callback();\n }\n\n // 查询是否存在相同值\n getObj({ [rule.field]: value }).then((response) => {\n const result = response.data;\n if (result !== null && result.length > 0) {\n callback(new Error(\'数据已经存在\'));\n } else {\n callback();\n }\n });\n}\n\n#if($ChildClassName)\n// ========== 子表相关接口 ==========\n\n/**\n * 删除子表数据\n * @param ids - 要删除的子表数据ID数组\n * @returns Promise<操作结果>\n */\nexport function delChildObj(ids?: Object) {\n return request({\n url: \'/${moduleName}/${functionName}/child\',\n method: \'delete\',\n data: ids\n })\n}\n#end\n','2026-04-08 17:38:24','2026-04-08 17:38:24','0',1,'admin','admin');
INSERT INTO `gen_template` (`id`, `template_name`, `generator_path`, `template_desc`, `template_code`, `create_time`, `update_time`, `del_flag`, `tenant_id`, `create_by`, `update_by`) VALUES (18,'子实体V202611','${entityPath}/src/main/java/${entityPackagePath}/${ChildClassName}Entity.java','子实体V202611','#set($hasOrg = false)\n#foreach($field in $childFieldList)\n#if($field.formType.startsWith(\'org-\'))\n#set($hasOrg = true)\n#end\n#end\npackage ${entityPackage};\n\nimport com.baomidou.mybatisplus.annotation.*;\nimport com.baomidou.mybatisplus.spring.activerecord.Model;\nimport io.swagger.v3.oas.annotations.media.Schema;\n#if($isChildTenant)\nimport ${package}.common.core.util.TenantTable;\n#end\nimport lombok.Data;\nimport lombok.EqualsAndHashCode;\n#if($hasOrg)\nimport com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler;\nimport ${package}.common.core.util.OrgRef;\nimport java.util.List;\n#end\n#set($childImports = [])\n#foreach($field in $childFieldList)\n#if($field.packageName && !$field.packageName.startsWith(\'java.lang.\') && !$childImports.contains($field.packageName))\n#set($void = $childImports.add($field.packageName))\n#end\n#end\n#foreach($import in $childImports)\nimport $import;\n#end\n\n/**\n * ${tableComment}\n *\n * @author ${author}\n * @date ${datetime}\n */\n@Data\n#if($isChildTenant)\n@TenantTable\n#end\n@TableName(value = \"${childTableName}\"#if($hasOrg), autoResultMap = true#end)\n@EqualsAndHashCode(callSuper = true)\n@Schema(description = \"${childTableName}\")\npublic class ${ChildClassName}Entity extends Model<${ChildClassName}Entity> {\n\n#foreach ($field in $childFieldList)\n#if(${field.fieldComment})#set($comment=${field.fieldComment})#else #set($comment=${field.attrName})#end\n /**\n * $comment\n */\n#if($field.primaryPk == \'1\')\n @TableId(type = IdType.ASSIGN_ID)\n#end\n#if($field.formType.startsWith(\'org-\'))\n @TableField(typeHandler = JacksonTypeHandler.class#if($field.autoFill == \'INSERT\' || $field.autoFill == \'INSERT_UPDATE\' || $field.autoFill == \'UPDATE\'), fill = FieldFill.${field.autoFill}#end)\n#elseif($field.autoFill == \'INSERT\')\n @TableField(fill = FieldFill.INSERT)\n#elseif($field.autoFill == \'INSERT_UPDATE\')\n @TableField(fill = FieldFill.INSERT_UPDATE)\n#elseif($field.autoFill == \'UPDATE\')\n @TableField(fill = FieldFill.UPDATE)\n#end\n#if($field.fieldName == \'del_flag\')\n @TableLogic\n @TableField(fill = FieldFill.INSERT)\n#end\n @Schema(description=\"$comment\"#if($field.hidden),hidden=$field.hidden#end)\n#if($field.formType.startsWith(\'org-\'))\n private List<OrgRef> $field.attrName;\n#elseif($field.formType == \'checkbox\')\n private ${field.attrType}[] $field.attrName;\n#else\n private $field.attrType $field.attrName;\n#end \n#end\n}\n','2026-04-08 17:38:24','2026-04-08 17:38:24','0',1,'admin','admin');
INSERT INTO `gen_template` (`id`, `template_name`, `generator_path`, `template_desc`, `template_code`, `create_time`, `update_time`, `del_flag`, `tenant_id`, `create_by`, `update_by`) VALUES (19,'主子ControllerV202611','${backendPath}/src/main/java/${packagePath}/${moduleName}/controller/${ClassName}Controller.java','主子ControllerV202611','## 查询条件按需导入:字符串字段和组织关键字用 StrUtil,其余类型用 Objects;复选框与日期范围两者都不用\n#set($needStrUtil = false)\n#set($needObjects = false)\n#foreach($field in $queryList)\n#if($field.formType == \'checkbox\' || $field.queryFormType == \'daterange\' || $field.queryFormType == \'datetimerange\')\n#elseif($field.formType.startsWith(\'org-\') || $field.attrType == \'String\')\n#set($needStrUtil = true)\n#else\n#set($needObjects = true)\n#end\n#end\n#set($hasOrgQuery = false)\n#foreach($field in $queryList)\n#if($field.formType.startsWith(\'org-\'))\n#set($hasOrgQuery = true)\n#end\n#end\n## 组织字段以 [{id,name}] JSON 存储,按 ${attrName}Keyword 对整列模糊查询,分页和导出共用\n#macro(orgKeywordParams)#foreach($field in $queryList)#if($field.formType.startsWith(\'org-\')), @RequestParam(required = false) String ${field.attrName}Keyword#end#end#end\n#macro(orgKeywordDecl)#foreach($field in $queryList)#if($field.formType.startsWith(\'org-\')), String ${field.attrName}Keyword#end#end#end\n#macro(orgKeywordArgs)#foreach($field in $queryList)#if($field.formType.startsWith(\'org-\')), ${field.attrName}Keyword#end#end#end\n#macro(orgKeywordFilters)\n#if($hasOrgQuery)\n // 组织字段对整列 JSON 做 LIKE:关键字为数字或 id/name 时会误命中,需精确匹配时改用数据库 JSON 函数\n#end\n#foreach($field in $queryList)\n#if($field.formType.startsWith(\'org-\'))\n wrapper.like(StrUtil.isNotBlank(${field.attrName}Keyword), ${ClassName}Entity::$str.getProperty($field.attrName), ${field.attrName}Keyword);\n#end\n#end\n#end\n#set($permissionPrefix = \"${moduleName}_${functionName}\")\n#set($permissionPrefix = $permissionPrefix.toLowerCase())\n#foreach($field in $childFieldList)\n#if($field.primaryPk == \'1\')\n#set($childPk = $field)\n#end\n#end\npackage ${package}.${moduleName}.controller;\n\n#if($needStrUtil)\nimport cn.hutool.core.util.StrUtil;\n#end\nimport cn.hutool.core.util.ArrayUtil;\nimport com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;\nimport com.baomidou.mybatisplus.core.toolkit.Wrappers;\nimport com.baomidou.mybatisplus.extension.plugins.pagination.Page;\nimport ${package}.common.core.util.R;\nimport ${package}.common.log.annotation.SysLog;\n#if($opensource)\nimport com.pig4cloud.plugin.excel.annotation.ResponseExcel;\nimport com.pig4cloud.plugin.excel.annotation.RequestExcel;\n#else\nimport ${package}.common.excel.annotation.ResponseExcel;\nimport ${package}.common.excel.annotation.RequestExcel;\n#end\nimport ${entityClassName};\nimport ${package}.${moduleName}.service.${ClassName}Service;\nimport io.swagger.v3.oas.annotations.security.SecurityRequirement;\n#if($isSpringBoot3)\nimport ${package}.common.security.annotation.HasPermission;\nimport org.springdoc.core.annotations.ParameterObject;\n#else\nimport org.springframework.security.access.prepost.PreAuthorize;\nimport org.springdoc.api.annotations.ParameterObject;\n#end\nimport org.springframework.http.HttpHeaders;\nimport io.swagger.v3.oas.annotations.tags.Tag;\nimport io.swagger.v3.oas.annotations.Operation;\nimport lombok.RequiredArgsConstructor;\nimport org.springframework.validation.BindingResult;\nimport org.springframework.web.bind.annotation.*;\n\nimport java.util.List;\n#if($needObjects)\nimport java.util.Objects;\n#end\n\n/**\n * ${tableComment}\n *\n * @author ${author}\n * @date ${datetime}\n */\n@RestController\n@RequiredArgsConstructor\n@RequestMapping(\"/${functionName}\" )\n@Tag(description = \"${functionName}\" , name = \"${tableComment}管理\" )\n@SecurityRequirement(name = HttpHeaders.AUTHORIZATION)\npublic class ${ClassName}Controller {\n\n private final ${ClassName}Service ${className}Service;\n\n /**\n * 分页查询\n * @param page 分页对象\n * @param ${className} ${tableComment}\n * @return\n */\n @Operation(summary = \"分页查询\" , description = \"分页查询\" )\n @GetMapping(\"/page\" )\n #if($isSpringBoot3)\n @HasPermission(\"${permissionPrefix}_view\")\n #else\n @PreAuthorize(\"@pms.hasPermission(\'${permissionPrefix}_view\')\" )\n #end\n public R get${ClassName}Page(@ParameterObject Page page, @ParameterObject ${ClassName}Entity ${className}#orgKeywordParams()) {\n return R.ok(${className}Service.page(page, buildQueryWrapper(${className}#orgKeywordArgs())));\n }\n\n /**\n * 列表与导出共用的查询条件,保证导出结果与列表一致\n */\n private LambdaQueryWrapper<${ClassName}Entity> buildQueryWrapper(${ClassName}Entity ${className}#orgKeywordDecl()) {\Line truncated
INSERT INTO `gen_template` (`id`, `template_name`, `generator_path`, `template_desc`, `template_code`, `create_time`, `update_time`, `del_flag`, `tenant_id`, `create_by`, `update_by`) VALUES (20,'主子表单V202611','${frontendPath}/src/views/${moduleName}/${functionName}/form.vue','主子表单V202611','## 有字典字段时才导入 useDict\n#set($hasDictField = false)\n#foreach($field in $formList)\n#if($field.fieldDict)\n#set($hasDictField = true)\n#end\n#end\n#set($hasDuplicate = false)\n#foreach($field in $formList)\n#if($field.formValidator == \'duplicate\')\n#set($hasDuplicate = true)\n#end\n#end\n## 开关:按属性类型决定开/关的值,Boolean 用 true/false,整型用 1/0,其余用 \'1\'/\'0\'\n#macro(switchValues $f)\n#if($f.attrType == \'Boolean\')\n#set($switchOn = \'true\')\n#set($switchOff = \'false\')\n#elseif($f.attrType == \'Integer\' || $f.attrType == \'Long\' || $f.attrType == \'Short\')\n#set($switchOn = \'1\')\n#set($switchOff = \'0\')\n#else\n#set($switchOn = "\'1\'")\n#set($switchOff = "\'0\'")\n#end\n#end\n#set($hasOrg = false)\n#foreach($field in $formList)\n#if($field.formType.startsWith(\'org-\'))\n#set($hasOrg = true)\n#end\n#end\n#foreach($field in $childFieldList)\n#if($field.formType.startsWith(\'org-\'))\n#set($hasOrg = true)\n#end\n#end\n<template>\n <el-drawer :title="form.${pk.attrName} ? (detail ? \'详情\' : \'编辑\') : \'添加\'" v-model="visible" size="50%">\n <el-form ref="dataFormRef" :model="form" :rules="dataRules" :disabled="detail" v-loading="loading">\n <el-row :gutter="24">\n#foreach($field in $formList)\n#if($field.attrName != ${pk.attrName})\n#if($formLayout == 1)\n <el-col :span="24" class="mb20">\n#elseif($formLayout == 2)\n <el-col :span="12" class="mb20">\n#end\n#if($field.formType.startsWith(\'org-\'))\n#set($orgType = $field.formType.replace(\'org-\', \'\').replace(\'-multiple\', \'\'))\n <el-form-item label="${field.fieldComment}" prop="${field.attrName}">\n <OrgSelect v-model="form.${field.attrName}" value-type="item" type="${orgType}" :multiple="#if($field.formType.endsWith(\'-multiple\'))true#else false#end" label="${field.fieldComment}" :disabled="loading || detail" />\n </el-form-item>\n </el-col>\n#elseif($field.formType == \'switch\')\n#switchValues($field)\n <el-form-item label="#if(${field.fieldComment})${field.fieldComment}#else${field.attrName}#end" prop="${field.attrName}">\n <el-switch :model-value="String(form.${field.attrName}) === String($switchOn)" @change="(checked) => (form.${field.attrName} = checked ? $switchOn : $switchOff)" />\n </el-form-item>\n </el-col>\n#elseif($field.formType == \'text\')\n <el-form-item label="#if(${field.fieldComment})${field.fieldComment}#else${field.fieldName}#end" prop="${field.attrName}">\n <el-input v-model="form.${field.attrName}" placeholder="请输入#if(${field.fieldComment})${field.fieldComment}#else${field.fieldName}#end"/>\n </el-form-item>\n </el-col>\n#elseif($field.formType == \'textarea\')\n <el-form-item label="#if(${field.fieldComment})${field.fieldComment}#else${field.fieldName}#end" prop="${field.attrName}">\n <el-input type="textarea" v-model="form.${field.attrName}" placeholder="请输入#if(${field.fieldComment})${field.fieldComment}#else${field.fieldName}#end"/>\n </el-form-item>\n </el-col>\n#elseif($field.formType == \'select\')\n <el-form-item label="#if(${field.fieldComment})${field.fieldComment}#else${field.fieldName}#end" prop="${field.attrName}">\n <el-select v-model="form.${field.attrName}" placeholder="请选择#if(${field.fieldComment})${field.fieldComment}#else${field.fieldName}#end">\n#if($field.fieldDict)\n <el-option :value="item.value" :label="item.label" v-for="(item, index) in ${field.fieldDict}" :key="index"></el-option>\n#else\n <el-option label="请选择" value="0"></el-option>\n#end\n </el-select>\n </el-form-item>\n </el-col>\n#elseif($field.formType == \'radio\')\n <el-form-item label="#if(${field.fieldComment})${field.fieldComment}#else${field.fieldName}#end" prop="${field.attrName}">\n <el-radio-group v-model="form.${field.attrName}">\n#if($field.fieldDict)\n <el-radio :label="item.value" v-for="(item, index) in ${field.fieldDict}" border :key="index">{{ item.label }}</el-radio>\n#else\n <el-radio label="${field.fieldComment}" border>${field.fieldComment}</el-radio>\n#end\n </el-radio-group>\n </el-form-item>\n </el-col>\n#elseif($field.formType == \'checkbox\')\n <el-form-item label="#if(${field.fieldComment})${field.fieldComment}#else${field.fieldName}#end" prop="${field.attrName}">\n <el-checkbox-group v-model="form.${field.attrName}">\n#if($field.fieldDict)\n <el-checkbox :label="item.value" v-fLine truncated
INSERT INTO `gen_template` (`id`, `template_name`, `generator_path`, `template_desc`, `template_code`, `create_time`, `update_time`, `del_flag`, `tenant_id`, `create_by`, `update_by`) VALUES (21,'主子表格V202611','${frontendPath}/src/views/${moduleName}/${functionName}/index.vue','主子表格V202611','## 有字典字段时才导入 useDict\n#set($hasDictField = false)\n#foreach($field in $queryList)\n#if($field.fieldDict)\n#set($hasDictField = true)\n#end\n#end\n#foreach($field in $gridList)\n#if($field.fieldDict)\n#set($hasDictField = true)\n#end\n#end\n## 开关:按属性类型决定开/关的值,Boolean 用 true/false,整型用 1/0,其余用 \'1\'/\'0\'\n#macro(switchValues $f)\n#if($f.attrType == \'Boolean\')\n#set($switchOn = \'true\')\n#set($switchOff = \'false\')\n#elseif($f.attrType == \'Integer\' || $f.attrType == \'Long\' || $f.attrType == \'Short\')\n#set($switchOn = \'1\')\n#set($switchOff = \'0\')\n#else\n#set($switchOn = "\'1\'")\n#set($switchOff = "\'0\'")\n#end\n#end\n#set($permissionPrefix = "${moduleName}_${functionName}")\n#set($permissionPrefix = $permissionPrefix.toLowerCase())\n<template>\n <div class="layout-padding">\n <div class="layout-padding-auto layout-padding-view">\n#if($queryList)\n <el-row v-show="showSearch">\n <el-form :model="state.queryForm" ref="queryRef" :inline="true" @keyup.enter="getDataList">\n#foreach($field in $queryList)\n#if($field.formType.startsWith(\'org-\'))#set($queryKey = "${field.attrName}Keyword")#else#set($queryKey = $field.attrName)#end\n#if($field.queryFormType == \'select\')\n <el-form-item label="#if(${field.fieldComment})${field.fieldComment}#else${field.attrName}#end" prop="${field.attrName}">\n <el-select v-model="state.queryForm.${field.attrName}" placeholder="请选择#if(${field.fieldComment})${field.fieldComment}#else${field.attrName}#end">\n#if($field.fieldDict)\n <el-option \n :label="item.label" \n :value="item.value" \n v-for="(item, index) in ${field.fieldDict}" \n :key="index">\n </el-option>\n#else\n <el-option label="请选择">0</el-option>\n#end\n </el-select>\n </el-form-item>\n#elseif($field.queryFormType == \'date\')\n <el-form-item label="#if(${field.fieldComment})${field.fieldComment}#else${field.attrName}#end" prop="${field.attrName}">\n <el-date-picker\n type="date"\n placeholder="请输入#if(${field.fieldComment})${field.fieldComment}#else${field.attrName}#end"\n :value-format="dateStr"\n v-model="state.queryForm.${field.attrName}"\n />\n </el-form-item>\n#elseif($field.queryFormType == \'daterange\')\n <el-form-item label="#if(${field.fieldComment})${field.fieldComment}#else${field.attrName}#end" prop="${field.attrName}Range">\n <el-date-picker\n type="daterange"\n range-separator="至"\n start-placeholder="开始日期"\n end-placeholder="结束日期"\n v-model="state.queryForm.${field.attrName}Range"\n :value-format="dateStr"\n />\n </el-form-item>\n#elseif($field.queryFormType == \'datetime\')\n <el-form-item label="#if(${field.fieldComment})${field.fieldComment}#else${field.attrName}#end" prop="${field.attrName}">\n <el-date-picker\n type="datetime"\n placeholder="请输入#if(${field.fieldComment})${field.fieldComment}#else${field.attrName}#end"\n :value-format="dateTimeStr"\n v-model="state.queryForm.${field.attrName}"\n />\n </el-form-item>\n#elseif($field.queryFormType == \'datetimerange\')\n <el-form-item label="#if(${field.fieldComment})${field.fieldComment}#else${field.attrName}#end" prop="${field.attrName}Range">\n <el-date-picker\n type="datetimerange"\n range-separator="至"\n start-placeholder="开始时间"\n end-placeholder="结束时间"\n v-model="state.queryForm.${field.attrName}Range"\n :value-format="dateTimeStr"\n />\n </el-form-item>\n#elseif($field.formType == \'radio\')\n <el-form-item label="#if(${field.fieldComment})${field.fieldComment}#else${field.attrName}#end" prop="${field.attrName}">\n <el-radio-group v-model="state.queryForm.${field.attrName}">\n#if($field.fieldDict)\n <el-radio \n :label="item.value" \n v-for="(item, index) in ${field.fieldDict}" \n border \n :key="index">\n {{ item.label }}\n </el-radio>\n#else\n <el-radio label="${field.fieldComment}" border>${field.fieldComment}</el-radio>\n#end\n </el-radio-group>\n </el-form-item>\n#else\n <elLine truncated
INSERT INTO `gen_template` (`id`, `template_name`, `generator_path`, `template_desc`, `template_code`, `create_time`, `update_time`, `del_flag`, `tenant_id`, `create_by`, `update_by`) VALUES (22,'子MapperV202611','${backendPath}/src/main/java/${packagePath}/${moduleName}/mapper/${ChildClassName}Mapper.java','子MapperV202611','package ${package}.${moduleName}.mapper;\n\nimport ${package}.common.data.datascope.PigxBaseMapper;\nimport ${entityPackage}.${ChildClassName}Entity;\nimport org.apache.ibatis.annotations.Mapper;\n\n@Mapper\npublic interface ${ChildClassName}Mapper extends PigxBaseMapper<${ChildClassName}Entity> {\n\n}\n','2026-04-08 17:38:24','2026-04-08 17:38:24','0',1,'admin','admin');
INSERT INTO `gen_template` (`id`, `template_name`, `generator_path`, `template_desc`, `template_code`, `create_time`, `update_time`, `del_flag`, `tenant_id`, `create_by`, `update_by`) VALUES (23,'树形ControllerV202611','${backendPath}/src/main/java/${packagePath}/${moduleName}/controller/${ClassName}Controller.java','树形ControllerV202611','## 查询条件按需导入:字符串字段用 StrUtil,其余类型用 Objects;复选框与日期范围两者都不用\n#set($needStrUtil = false)\n#set($needObjects = false)\n#foreach($field in $queryList)\n#if($field.formType == \'checkbox\' || $field.queryFormType == \'daterange\' || $field.queryFormType == \'datetimerange\')\n#elseif($field.formType.startsWith(\'org-\') || $field.attrType == \'String\')\n#set($needStrUtil = true)\n#else\n#set($needObjects = true)\n#end\n#end\n#set($hasOrgQuery = false)\n#foreach($field in $queryList)\n#if($field.formType.startsWith(\'org-\'))\n#set($hasOrgQuery = true)\n#end\n#end\n## 组织字段以 [{id,name}] JSON 存储,按 ${attrName}Keyword 对整列模糊查询,分页和导出共用\n#macro(orgKeywordParams)#foreach($field in $queryList)#if($field.formType.startsWith(\'org-\')), @RequestParam(required = false) String ${field.attrName}Keyword#end#end#end\n#macro(orgKeywordDecl)#foreach($field in $queryList)#if($field.formType.startsWith(\'org-\')), String ${field.attrName}Keyword#end#end#end\n#macro(orgKeywordArgs)#foreach($field in $queryList)#if($field.formType.startsWith(\'org-\')), ${field.attrName}Keyword#end#end#end\n#macro(orgKeywordFilters)\n#if($hasOrgQuery)\n // 组织字段对整列 JSON 做 LIKE:关键字为数字或 id/name 时会误命中,需精确匹配时改用数据库 JSON 函数\n#end\n#foreach($field in $queryList)\n#if($field.formType.startsWith(\'org-\'))\n wrapper.like(StrUtil.isNotBlank(${field.attrName}Keyword), ${ClassName}Entity::$str.getProperty($field.attrName), ${field.attrName}Keyword);\n#end\n#end\n#end\npackage ${package}.${moduleName}.controller;\n\n#if($queryList)\n#if($needStrUtil)\nimport cn.hutool.core.util.StrUtil;\n#end\n#end\nimport cn.hutool.core.util.ArrayUtil;\nimport cn.hutool.core.collection.CollUtil;\nimport com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;\nimport com.baomidou.mybatisplus.core.toolkit.Wrappers;\nimport ${package}.common.core.util.R;\nimport ${package}.common.log.annotation.SysLog;\n#if($opensource)\nimport com.pig4cloud.plugin.excel.annotation.ResponseExcel;\nimport com.pig4cloud.plugin.excel.annotation.RequestExcel;\n#else\nimport ${package}.common.excel.annotation.ResponseExcel;\nimport ${package}.common.excel.annotation.RequestExcel;\n#end\nimport ${entityClassName};\nimport ${package}.${moduleName}.service.${ClassName}Service;\n\nimport io.swagger.v3.oas.annotations.security.SecurityRequirement;\n#if($isSpringBoot3)\nimport ${package}.common.security.annotation.HasPermission;\nimport org.springdoc.core.annotations.ParameterObject;\n#else\nimport org.springframework.security.access.prepost.PreAuthorize;\nimport org.springdoc.api.annotations.ParameterObject;\n#end\nimport org.springframework.http.HttpHeaders;\nimport io.swagger.v3.oas.annotations.tags.Tag;\nimport io.swagger.v3.oas.annotations.Operation;\nimport lombok.RequiredArgsConstructor;\nimport org.springframework.validation.BindingResult;\nimport org.springframework.web.bind.annotation.*;\n\nimport java.util.List;\n#if($needObjects)\nimport java.util.Objects;\n#end\n\n/**\n * ${tableComment}\n *\n * @author ${author}\n * @date ${datetime}\n */\n@RestController\n@RequiredArgsConstructor\n@RequestMapping("/${functionName}" )\n@Tag(description = "${functionName}" , name = "${tableComment}管理" )\n@SecurityRequirement(name = HttpHeaders.AUTHORIZATION)\npublic class ${ClassName}Controller {\n\n private final ${ClassName}Service ${className}Service;\n\n /**\n * 获取树形列表\n * @param ${className} ${tableComment}\n * @return\n */\n @Operation(summary = "获取树形列表" , description = "获取树形列表" )\n @GetMapping("/tree" )\n #if($isSpringBoot3)\n @HasPermission("$str.lowerCase($moduleName)_$str.lowerCase($functionName)_view")\n #else\n @PreAuthorize("@pms.hasPermission(\'$str.lowerCase($moduleName)_$str.lowerCase($functionName)_view\')" )\n #end\n public R get${ClassName}Tree(@ParameterObject ${ClassName}Entity ${className}#orgKeywordParams()) {\n return R.ok(${className}Service.buildTree(buildQueryWrapper(${className}#orgKeywordArgs())));\n }\n\n /**\n * 列表与导出共用的查询条件,保证导出结果与列表一致\n */\n private LambdaQueryWrapper<${ClassName}Entity> buildQueryWrapper(${ClassName}Entity ${className}#orgKeywordDecl()) {\n LambdaQueryWrapper<${ClassName}Entity> wrapper = Wrappers.lambdaQuery();\n#orgKeywordFilters()\n#foreach ($field in $queryList)\n#if(!$field.formType.startsWith(\'org-\'))\n#set($getAttrName=$str.getProperty($field.attLine truncated
INSERT INTO `gen_template` (`id`, `template_name`, `generator_path`, `template_desc`, `template_code`, `create_time`, `update_time`, `del_flag`, `tenant_id`, `create_by`, `update_by`) VALUES (24,'树形ServiceV202611','${backendPath}/src/main/java/${packagePath}/${moduleName}/service/${ClassName}Service.java','树形ServiceV202611','package ${package}.${moduleName}.service;\n\nimport cn.hutool.core.lang.tree.Tree;\nimport com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;\nimport com.baomidou.mybatisplus.spring.service.IService;\nimport ${entityClassName};\n\nimport java.util.List;\n\n/**\n * ${tableComment} Service接口\n *\n * @author ${author}\n * @date ${datetime}\n */\npublic interface ${ClassName}Service extends IService<${ClassName}Entity> {\n\n /**\n * 构建树形结构数据\n * @param wrapper 查询条件\n * @return 树形结构数据\n */\n List<Tree<${pk.attrType}>> buildTree(LambdaQueryWrapper<${ClassName}Entity> wrapper);\n\n /**\n * 递归删除节点及其子节点\n * @param ids 要删除的节点ID列表\n * @return 删除结果\n */\n boolean removeBatchByIds(List<${pk.attrType}> ids);\n} ','2026-04-08 17:38:24','2026-04-08 17:38:24','0',1,'admin','admin');
INSERT INTO `gen_template` (`id`, `template_name`, `generator_path`, `template_desc`, `template_code`, `create_time`, `update_time`, `del_flag`, `tenant_id`, `create_by`, `update_by`) VALUES (25,'树形ServiceImplV202611','${backendPath}/src/main/java/${packagePath}/${moduleName}/service/impl/${ClassName}ServiceImpl.java','树形ServiceImplV202611','## 根节点 ID 按主键类型生成,与 Tree<${pk.attrType}> 类型一致\n#if($pk.attrType == \'Long\')\n#set($treeRootId = \'0L\')\n#elseif($pk.attrType == \'String\')\n#set($treeRootId = \'"0"\')\n#else\n#set($treeRootId = \'0\')\n#end\npackage ${package}.${moduleName}.service.impl;\n\nimport cn.hutool.core.collection.CollUtil;\nimport cn.hutool.core.lang.tree.Tree;\nimport cn.hutool.core.lang.tree.TreeNode;\nimport cn.hutool.core.lang.tree.TreeUtil;\nimport com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;\nimport com.baomidou.mybatisplus.core.toolkit.Wrappers;\nimport com.baomidou.mybatisplus.spring.service.impl.ServiceImpl;\nimport ${entityClassName};\nimport ${package}.${moduleName}.mapper.${ClassName}Mapper;\nimport ${package}.${moduleName}.service.${ClassName}Service;\nimport jakarta.validation.constraints.NotNull;\nimport lombok.RequiredArgsConstructor;\nimport org.springframework.stereotype.Service;\nimport org.springframework.transaction.annotation.Transactional;\n\nimport java.util.ArrayList;\nimport java.util.HashMap;\nimport java.util.LinkedHashMap;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Objects;\nimport java.util.function.Function;\nimport java.util.stream.Collectors;\n\n/**\n * ${tableComment} Service实现类\n *\n * @author ${author}\n * @date ${datetime}\n */\n@Service\n@RequiredArgsConstructor\npublic class ${ClassName}ServiceImpl extends ServiceImpl<${ClassName}Mapper, ${ClassName}Entity> implements ${ClassName}Service {\n\n /**\n * 构建树形结构数据\n * @param wrapper 查询条件\n * @return 树形结构数据\n */\n @Override\n public List<Tree<${pk.attrType}>> buildTree(LambdaQueryWrapper<${ClassName}Entity> wrapper) {\n // 查询命中节点,再按层补齐祖先,保留完整树路径\n List<${ClassName}Entity> allList = list(wrapper);\n \n if (CollUtil.isEmpty(allList)) {\n return new ArrayList<>();\n }\n\n Map<${pk.attrType}, ${ClassName}Entity> nodes = new LinkedHashMap<>();\n allList.forEach(entity -> nodes.put(entity.$str.getProperty($pk.attrName)(), entity));\n List<${ClassName}Entity> level = allList;\n while (!level.isEmpty()) {\n List<${pk.attrType}> parentIds = level.stream()\n .map(${ClassName}Entity::$str.getProperty($parentField))\n .filter(id -> id != null && !Objects.equals(id, ${treeRootId}) && !nodes.containsKey(id))\n .distinct()\n .toList();\n if (parentIds.isEmpty()) {\n break;\n }\n level = listByIds(parentIds);\n level.forEach(entity -> nodes.put(entity.$str.getProperty($pk.attrName)(), entity));\n }\n\n // 转换为TreeNode,仅包含命中节点及其祖先\n List<TreeNode<${pk.attrType}>> collect = nodes.values().stream().map(getNodeFunction()).toList();\n\n // 使用TreeUtil构建树形结构,根节点ID为0\n return TreeUtil.build(collect, ${treeRootId});\n }\n\n /**\n * 获取TreeNode转换函数\n * @return TreeNode转换函数\n */\n @NotNull\n private Function<${ClassName}Entity, TreeNode<${pk.attrType}>> getNodeFunction() {\n return entity -> {\n TreeNode<${pk.attrType}> node = new TreeNode<>();\n node.setId(entity.$str.getProperty($pk.attrName)());\n node.setName(entity.$str.getProperty($nameField)());\n node.setParentId(entity.$str.getProperty($parentField)() != null ? entity.$str.getProperty($parentField)() : ${treeRootId});\n\n // 扩展属性\n Map<String, Object> extra = new HashMap<>();\n#foreach($field in $fieldList)\n extra.put(${ClassName}Entity.Fields.${field.attrName}, entity.$str.getProperty($field.attrName)());\n#end\n node.setExtra(extra);\n return node;\n };\n }\n\n /**\n * 递归删除节点及其子节点\n * @param ids 要删除的节点ID列表\n * @return 删除结果\n */\n @Override\n @Transactional(rollbackFor = Exception.class)\n public boolean removeBatchByIds(List<${pk.attrType}> ids) {\n if (CollUtil.isEmpty(ids)) {\n return true;\n }\n\n // 获取所有要删除的ID(包括子节点)\n List<${pk.attrType}> allDeleteIds = new ArrayList<>(ids);\n \n for (${pk.attrType} id : ids) {\n List<${pk.attrType}> childIds = getChildIdsRecursive(id);\n allDeleteIds.addAll(childIds);\n }\n\n // 去重\n allLine truncated
INSERT INTO `gen_template` (`id`, `template_name`, `generator_path`, `template_desc`, `template_code`, `create_time`, `update_time`, `del_flag`, `tenant_id`, `create_by`, `update_by`) VALUES (26,'树形实体V202611','${entityPath}/src/main/java/${entityPackagePath}/${ClassName}Entity.java','树形实体V202611','#set($hasOrg = false)\n#foreach($field in $fieldList)\n#if($field.formType.startsWith(\'org-\'))\n#set($hasOrg = true)\n#end\n#end\npackage ${entityPackage};\n\nimport com.baomidou.mybatisplus.annotation.*;\nimport com.baomidou.mybatisplus.spring.activerecord.Model;\nimport io.swagger.v3.oas.annotations.media.Schema;\nimport lombok.Data;\nimport lombok.EqualsAndHashCode;\nimport lombok.experimental.FieldNameConstants;\n#if($hasOrg)\nimport com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler;\nimport ${package}.common.core.util.OrgRef;\nimport org.apache.fesod.sheet.annotation.ExcelIgnore;\nimport java.util.List;\n#end\n#if($isTenant)\nimport ${package}.common.core.util.TenantTable;\n#end\n#foreach($import in $importList)\n#if(!$import.startsWith(\'java.lang.\'))\nimport $import;\n#end\n#end\n\n/**\n * ${tableComment}\n *\n * @author ${author}\n * @date ${datetime}\n */\n@Data\n@FieldNameConstants\n#if($isTenant)\n@TenantTable\n#end\n@TableName(value = "${tableName}"#if($hasOrg), autoResultMap = true#end)\n@EqualsAndHashCode(callSuper = true)\n@Schema(description = "${tableComment}")\npublic class ${ClassName}Entity extends Model<${ClassName}Entity> {\n\n#foreach ($field in $fieldList)\n#if(${field.fieldComment})#set($comment=${field.fieldComment})#else #set($comment=${field.attrName})#end\n\n /**\n * $comment\n */\n#if($field.primaryPk == \'1\')\n @TableId(type = IdType.ASSIGN_ID)\n#end\n#if($field.formType.startsWith(\'org-\'))\n @TableField(typeHandler = JacksonTypeHandler.class#if($field.autoFill == \'INSERT\' || $field.autoFill == \'INSERT_UPDATE\' || $field.autoFill == \'UPDATE\'), fill = FieldFill.${field.autoFill}#end)\n @ExcelIgnore\n#elseif($field.autoFill == \'INSERT\')\n @TableField(fill = FieldFill.INSERT)\n#elseif($field.autoFill == \'INSERT_UPDATE\')\n @TableField(fill = FieldFill.INSERT_UPDATE)\n#elseif($field.autoFill == \'UPDATE\')\n @TableField(fill = FieldFill.UPDATE)\n#end\n#if($field.fieldName == \'del_flag\')\n @TableLogic\n @TableField(fill = FieldFill.INSERT)\n#end\n @Schema(description="$comment"#if($field.hidden),hidden=$field.hidden#end)\n#if($field.formType.startsWith(\'org-\'))\n private List<OrgRef> $field.attrName;\n#elseif($field.formType == \'checkbox\')\n private ${field.attrType}[] $field.attrName;\n#elseif($field.formType == \'daterange\' || $field.formType == \'datetimerange\')\n private String[] $field.attrName;\n#else\n private $field.attrType $field.attrName;\n#end\n#end\n#foreach ($field in $queryList)\n#if($field.queryFormType == \'daterange\' || $field.queryFormType == \'datetimerange\')\n#if(${field.fieldComment})#set($comment=${field.fieldComment})#else #set($comment=${field.attrName})#end\n\n /**\n * $comment 查询范围\n */\n @TableField(exist = false)\n @Schema(description="$comment 查询范围",hidden=true)\n private String[] ${field.attrName}Range;\n#end\n#end\n}\n','2026-04-08 17:38:24','2026-04-08 17:38:24','0',1,'admin','admin');
INSERT INTO `gen_template` (`id`, `template_name`, `generator_path`, `template_desc`, `template_code`, `create_time`, `update_time`, `del_flag`, `tenant_id`, `create_by`, `update_by`) VALUES (27,'MapperV202611','${backendPath}/src/main/java/${packagePath}/${moduleName}/mapper/${ClassName}Mapper.java','MapperV202611','package ${package}.${moduleName}.mapper;\n\n\nimport com.baomidou.mybatisplus.core.mapper.BaseMapper;\nimport ${entityClassName};\nimport org.apache.ibatis.annotations.Mapper;\n\n@Mapper\npublic interface ${ClassName}Mapper extends BaseMapper<${ClassName}Entity> {\n\n}\n','2026-04-08 17:38:24','2026-04-08 17:38:24','0',1,'admin','admin');
INSERT INTO `gen_template` (`id`, `template_name`, `generator_path`, `template_desc`, `template_code`, `create_time`, `update_time`, `del_flag`, `tenant_id`, `create_by`, `update_by`) VALUES (28,'Mapper.xmlV202611','${backendPath}/src/main/resources/mapper/${ClassName}Mapper.xml','Mapper.xmlV202611','<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE mapper PUBLIC \"-//mybatis.org//DTD Mapper 3.0//EN\" \"http://mybatis.org/dtd/mybatis-3-mapper.dtd\">\n\n<mapper namespace=\"${package}.${moduleName}.mapper.${ClassName}Mapper\">\n\n <resultMap id=\"${className}Map\" type=\"${entityClassName}\">\n#foreach ($field in $fieldList)\n #if($field.primaryPk == \'1\')\n <id property=\"$field.attrName\" column=\"$field.fieldName\"/>\n #else\n <result property=\"$field.attrName\" column=\"$field.fieldName\"#if($field.formType.startsWith(\'org-\')) typeHandler=\"com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler\"#end/>\n #end\n#end\n </resultMap>\n</mapper>\n','2026-04-08 17:38:24','2026-04-08 17:38:24','0',1,'admin','admin');
INSERT INTO `gen_template` (`id`, `template_name`, `generator_path`, `template_desc`, `template_code`, `create_time`, `update_time`, `del_flag`, `tenant_id`, `create_by`, `update_by`) VALUES (29,'权限菜单V202611','${backendPath}/menu/${functionName}_menu.sql','权限菜单V202611','#set($permissionPrefix = \"${moduleName}_${functionName}\")\n#set($permissionPrefix = $permissionPrefix.toLowerCase())\n-- 该脚本不要直接执行, 注意维护菜单的父节点ID 默认 父节点-1 , #if(!$opensource)默认租户 1#end\n#set($menuId=${dateTool.getSystemTime()})\n\n-- 菜单SQL\ninsert into sys_menu ( menu_id,parent_id, path, permission, menu_type, icon, del_flag, create_time, sort_order, update_time, name#if(!$opensource), tenant_id#end)\nvalues (${menuId}, \'-1\', \'/${moduleName}/${functionName}/index\', \'\', \'0\', \'icon-bangzhushouji\', \'0\', null , \'8\', null , \'${tableComment}管理\'#if(!$opensource), 1#end);\n\n-- 菜单对应按钮SQL\ninsert into sys_menu ( menu_id,parent_id, permission, menu_type, path, icon, del_flag, create_time, sort_order, update_time, name#if(!$opensource), tenant_id#end)\nvalues (${math.add($menuId,1)},${menuId}, \'${permissionPrefix}_view\', \'1\', null, \'1\', \'0\', null, \'0\', null, \'${tableComment}查看\'#if(!$opensource), 1#end);\n\ninsert into sys_menu ( menu_id,parent_id, permission, menu_type, path, icon, del_flag, create_time, sort_order, update_time, name#if(!$opensource), tenant_id#end)\nvalues (${math.add($menuId,2)},${menuId}, \'${permissionPrefix}_add\', \'1\', null, \'1\', \'0\', null, \'1\', null, \'${tableComment}新增\'#if(!$opensource), 1#end);\n\ninsert into sys_menu (menu_id, parent_id, permission, menu_type, path, icon, del_flag, create_time, sort_order, update_time, name#if(!$opensource), tenant_id#end)\nvalues (${math.add($menuId,3)},${menuId}, \'${permissionPrefix}_edit\', \'1\', null, \'1\', \'0\', null, \'2\', null, \'${tableComment}修改\'#if(!$opensource), 1#end);\n\ninsert into sys_menu (menu_id, parent_id, permission, menu_type, path, icon, del_flag, create_time, sort_order, update_time, name#if(!$opensource), tenant_id#end)\nvalues (${math.add($menuId,4)},${menuId}, \'${permissionPrefix}_del\', \'1\', null, \'1\', \'0\', null, \'3\', null, \'${tableComment}删除\'#if(!$opensource), 1#end);\n\ninsert into sys_menu ( menu_id,parent_id, permission, menu_type, path, icon, del_flag, create_time, sort_order, update_time, name#if(!$opensource), tenant_id#end)\nvalues (${math.add($menuId,5)},${menuId}, \'${permissionPrefix}_export\', \'1\', null, \'1\', \'0\', null, \'3\', null, \'导入导出\'#if(!$opensource), 1#end);\n','2026-04-08 17:38:24','2026-04-08 17:38:24','0',1,'admin','admin');
INSERT INTO `gen_template` (`id`, `template_name`, `generator_path`, `template_desc`, `template_code`, `create_time`, `update_time`, `del_flag`, `tenant_id`, `create_by`, `update_by`) VALUES (30,'树形api.tsV202611','${frontendPath}/src/api/${moduleName}/${functionName}.ts','树形api.tsV202611','import request from \"/@/utils/request\"\n\n// ========== 树形表格CRUD接口 ==========\n\n/**\n * 获取树形列表数据\n * @param query - 查询参数对象\n * @returns Promise<树形数据>\n */\nexport function fetchTreeList(query?: Object) {\n return request({\n url: \'/${moduleName}/${functionName}/tree\',\n method: \'get\',\n params: query\n })\n}\n\n/**\n * 新增数据\n * @param obj - 要新增的数据对象\n * @returns Promise<boolean> - 操作结果\n */\nexport function addObj(obj?: Object) {\n return request({\n url: \'/${moduleName}/${functionName}\',\n method: \'post\',\n data: obj\n })\n}\n\n/**\n * 获取详情数据\n * @param obj - 查询参数对象(包含ID等)\n * @returns Promise<数据详情>\n */\nexport function getObj(obj?: Object) {\n return request({\n url: \'/${moduleName}/${functionName}/details\',\n method: \'get\',\n params: obj\n })\n}\n\n/**\n * 批量删除数据(递归删除子节点)\n * @param ids - 要删除的ID数组\n * @returns Promise<操作结果>\n */\nexport function delObjs(ids?: Object) {\n return request({\n url: \'/${moduleName}/${functionName}\',\n method: \'delete\',\n data: ids\n })\n}\n\n/**\n * 更新数据\n * @param obj - 要更新的数据对象\n * @returns Promise<操作结果>\n */\nexport function putObj(obj?: Object) {\n return request({\n url: \'/${moduleName}/${functionName}\',\n method: \'put\',\n data: obj\n })\n}\n\n\n// ========== 工具函数 ==========\n\n/**\n * 验证字段值唯一性\n * @param rule - 验证规则对象\n * @param value - 要验证的值\n * @param callback - 验证回调函数\n * @param isEdit - 是否为编辑模式\n * \n * @example\n * // 在表单验证规则中使用\n * fieldName: [\n * {\n * validator: (rule, value, callback) => {\n * validateExist(rule, value, callback, form.${pk.attrName} !== \'\');\n * },\n * trigger: \'blur\',\n * },\n * ]\n */\nexport function validateExist(rule: any, value: any, callback: any, isEdit: boolean) {\n // 编辑模式下跳过验证\n if (isEdit) {\n return callback();\n }\n\n // 查询是否存在相同值\n getObj({ [rule.field]: value }).then((response) => {\n const result = response.data;\n if (result !== null && result.length > 0) {\n callback(new Error(\'数据已经存在\'));\n } else {\n callback();\n }\n });\n}','2026-04-08 17:38:24','2026-04-08 17:38:24','0',1,'admin','admin');
INSERT INTO `gen_template` (`id`, `template_name`, `generator_path`, `template_desc`, `template_code`, `create_time`, `update_time`, `del_flag`, `tenant_id`, `create_by`, `update_by`) VALUES (31,'树形表格V202611','${frontendPath}/src/views/${moduleName}/${functionName}/index.vue','树形表格V202611','## 有字典字段时才导入 useDict\n#set($hasDictField = false)\n#foreach($field in $queryList)\n#if($field.fieldDict)\n#set($hasDictField = true)\n#end\n#end\n#foreach($field in $gridList)\n#if($field.fieldDict)\n#set($hasDictField = true)\n#end\n#end\n## 开关:按属性类型决定开/关的值,Boolean 用 true/false,整型用 1/0,其余用 \'1\'/\'0\'\n#macro(switchValues $f)\n#if($f.attrType == \'Boolean\')\n#set($switchOn = \'true\')\n#set($switchOff = \'false\')\n#elseif($f.attrType == \'Integer\' || $f.attrType == \'Long\' || $f.attrType == \'Short\')\n#set($switchOn = \'1\')\n#set($switchOff = \'0\')\n#else\n#set($switchOn = "\'1\'")\n#set($switchOff = "\'0\'")\n#end\n#end\n<template>\n <div class="layout-padding">\n <div class="layout-padding-auto layout-padding-view">\n#if($queryList)\n <!-- 查询表单区域 -->\n <el-row v-show="showSearch">\n <el-form :model="state.queryForm" ref="queryRef" :inline="true" @keyup.enter="getDataList">\n#foreach($field in $queryList)\n#if($field.formType.startsWith(\'org-\'))#set($queryKey = "${field.attrName}Keyword")#else#set($queryKey = $field.attrName)#end\n#if($field.queryFormType == \'select\')\n <el-form-item label="#if(${field.fieldComment})${field.fieldComment}#else${field.attrName}#end" prop="${queryKey}">\n <el-select v-model="state.queryForm.${queryKey}" placeholder="请选择#if(${field.fieldComment})${field.fieldComment}#else${field.attrName}#end">\n#if($field.fieldDict)\n <el-option \n :label="item.label" \n :value="item.value" \n v-for="(item, index) in ${field.fieldDict}" \n :key="index"\n />\n#else\n <el-option label="请选择" value="0" />\n#end\n </el-select>\n </el-form-item>\n#elseif($field.queryFormType == \'date\')\n <el-form-item label="#if(${field.fieldComment})${field.fieldComment}#else${field.attrName}#end" prop="${queryKey}">\n <el-date-picker \n type="date" \n placeholder="请输入#if(${field.fieldComment})${field.fieldComment}#else${field.attrName}#end" \n v-model="state.queryForm.${queryKey}"\n :value-format="dateStr"\n />\n </el-form-item>\n#elseif($field.queryFormType == \'datetime\')\n <el-form-item label="#if(${field.fieldComment})${field.fieldComment}#else${field.attrName}#end" prop="${queryKey}">\n <el-date-picker\n type="datetime"\n placeholder="请输入#if(${field.fieldComment})${field.fieldComment}#else${field.attrName}#end"\n v-model="state.queryForm.${queryKey}"\n :value-format="dateTimeStr"\n />\n </el-form-item>\n#elseif($field.queryFormType == \'daterange\')\n <el-form-item label="#if(${field.fieldComment})${field.fieldComment}#else${field.attrName}#end" prop="${field.attrName}Range">\n <el-date-picker\n type="daterange"\n range-separator="至"\n start-placeholder="开始日期"\n end-placeholder="结束日期"\n v-model="state.queryForm.${field.attrName}Range"\n :value-format="dateStr"\n />\n </el-form-item>\n#elseif($field.queryFormType == \'datetimerange\')\n <el-form-item label="#if(${field.fieldComment})${field.fieldComment}#else${field.attrName}#end" prop="${field.attrName}Range">\n <el-date-picker\n type="datetimerange"\n range-separator="至"\n start-placeholder="开始时间"\n end-placeholder="结束时间"\n v-model="state.queryForm.${field.attrName}Range"\n :value-format="dateTimeStr"\n />\n </el-form-item>\n#elseif($field.formType == \'radio\')\n <el-form-item label="#if(${field.fieldComment})${field.fieldComment}#else${field.attrName}#end" prop="${queryKey}">\n <el-radio-group v-model="state.queryForm.${queryKey}">\n#if($field.fieldDict)\n <el-radio \n :label="item.value" \n v-for="(item, index) in ${field.fieldDict}" \n border \n :key="index"\n >\n {{ item.label }}\n </el-radio>\n#else\n <el-radio label="${field.fieldComment}" border>\n ${field.fieldComment}\n </el-radio>\n#end\n </el-radio-group>\n </el-form-item>\n#else\n <el-form-item label="#if(${field.fieldComment})${field.fieldComment}#else${field.attrName}#enLine truncated
INSERT INTO `gen_template` (`id`, `template_name`, `generator_path`, `template_desc`, `template_code`, `create_time`, `update_time`, `del_flag`, `tenant_id`, `create_by`, `update_by`) VALUES (32,'树形表单V202611','${frontendPath}/src/views/${moduleName}/${functionName}/form.vue','树形表单V202611','#set($hasDuplicate = false)\n#foreach($field in $formList)\n#if($field.formValidator == \'duplicate\')\n#set($hasDuplicate = true)\n#end\n#end\n## 开关:按属性类型决定开/关的值,Boolean 用 true/false,整型用 1/0,其余用 \'1\'/\'0\'\n#macro(switchValues $f)\n#if($f.attrType == \'Boolean\')\n#set($switchOn = \'true\')\n#set($switchOff = \'false\')\n#elseif($f.attrType == \'Integer\' || $f.attrType == \'Long\' || $f.attrType == \'Short\')\n#set($switchOn = \'1\')\n#set($switchOff = \'0\')\n#else\n#set($switchOn = "\'1\'")\n#set($switchOff = "\'0\'")\n#end\n#end\n#set($hasOrg = false)\n#foreach($field in $formList)\n#if($field.formType.startsWith(\'org-\'))\n#set($hasOrg = true)\n#end\n#end\n<template>\n <el-dialog :title="form.${pk.attrName} ? \'编辑\' : \'新增\'" v-model="visible"\n :close-on-click-modal="false" draggable>\n <el-form ref="dataFormRef" :model="form" :rules="dataRules" formDialogRef label-width="90px" v-loading="loading">\n <el-row :gutter="24">\n <!-- 父级节点选择 -->\n#if($formLayout == 1)\n <el-col :span="24" class="mb20">\n#elseif($formLayout == 2)\n <el-col :span="12" class="mb20">\n#end\n <el-form-item label="父级节点" prop="${parentField}">\n <el-tree-select\n v-model="form.${parentField}"\n :data="parentNodes"\n :props="treeSelectProps"\n check-strictly\n :render-after-expand="false"\n placeholder="请选择父级节点"\n style="width: 100%"\n clearable\n filterable\n />\n </el-form-item>\n </el-col>\n#foreach($field in $formList)\n#if($field.attrName != ${pk.attrName} && $field.attrName != ${parentField})\n#if($formLayout == 1)\n <el-col :span="24" class="mb20">\n#elseif($formLayout == 2)\n <el-col :span="12" class="mb20">\n#end\n#if($field.formType.startsWith(\'org-\'))\n#set($orgType = $field.formType.replace(\'org-\', \'\').replace(\'-multiple\', \'\'))\n <el-form-item label="${field.fieldComment}" prop="${field.attrName}">\n <OrgSelect v-model="form.${field.attrName}" value-type="item" type="${orgType}" :multiple="#if($field.formType.endsWith(\'-multiple\'))true#else false#end" label="${field.fieldComment}" :disabled="loading" />\n </el-form-item>\n </el-col>\n#elseif($field.formType == \'switch\')\n#switchValues($field)\n <el-form-item label="#if(${field.fieldComment})${field.fieldComment}#else${field.attrName}#end" prop="${field.attrName}">\n <el-switch :model-value="String(form.${field.attrName}) === String($switchOn)" @change="(checked) => (form.${field.attrName} = checked ? $switchOn : $switchOff)" />\n </el-form-item>\n </el-col>\n#elseif($field.formType == \'text\')\n <el-form-item label="#if(${field.fieldComment})${field.fieldComment}#else${field.attrName}#end" prop="${field.attrName}">\n <el-input v-model="form.${field.attrName}" placeholder="请输入#if(${field.fieldComment})${field.fieldComment}#else${field.attrName}#end"/>\n </el-form-item>\n </el-col>\n#elseif($field.formType == \'textarea\')\n <el-form-item label="#if(${field.fieldComment})${field.fieldComment}#else${field.attrName}#end" prop="${field.attrName}">\n <el-input type="textarea" v-model="form.${field.attrName}" placeholder="请输入#if(${field.fieldComment})${field.fieldComment}#else${field.attrName}#end"/>\n </el-form-item>\n </el-col>\n#elseif($field.formType == \'select\')\n <el-form-item label="#if(${field.fieldComment})${field.fieldComment}#else${field.attrName}#end" prop="${field.attrName}">\n <el-select v-model="form.${field.attrName}" placeholder="请选择#if(${field.fieldComment})${field.fieldComment}#else${field.attrName}#end">\n#if($field.fieldDict)\n <el-option :value="item.value" :label="item.label" v-for="(item, index) in ${field.fieldDict}" :key="index"></el-option>\n#else\n <el-option label="请选择" value="0"></el-option>\n#end\n </el-select>\n </el-form-item>\n </el-col>\n#elseif($field.formType == \'radio\')\n <el-form-item label="#if(${field.fieldComment})${field.fieldComment}#else${field.attrName}#end" prop="${field.attrName}">\n <el-radio-group v-model="form.${field.attrName}">\n#if($field.fieldDict)\n <el-radio :label="item.value" v-for="(item, index) in ${field.fieldDict}" border :key="index">{{ item.label }}</el-radio>\n#else\n <el-radio label="${field.fieldComment}" bordLine truncated
INSERT INTO `gen_template` (`id`, `template_name`, `generator_path`, `template_desc`, `template_code`, `create_time`, `update_time`, `del_flag`, `tenant_id`, `create_by`, `update_by`) VALUES (33,'左树右表ControllerV202611','${backendPath}/src/main/java/${packagePath}/${moduleName}/controller/${ClassName}Controller.java','左树右表ControllerV202611','## 查询条件按需导入 StrUtil(字符串字段);Objects 用于树节点筛选,始终导入\n#set($needStrUtil = false)\n#foreach($field in $queryList)\n#if($field.formType.startsWith(\'org-\') || ($field.formType != \'checkbox\' && $field.queryFormType != \'daterange\' && $field.queryFormType != \'datetimerange\' && $field.attrType == \'String\'))\n#set($needStrUtil = true)\n#end\n#end\n#set($hasOrgQuery = false)\n#foreach($field in $queryList)\n#if($field.formType.startsWith(\'org-\'))\n#set($hasOrgQuery = true)\n#end\n#end\n## 组织字段以 [{id,name}] JSON 存储,按 ${attrName}Keyword 对整列模糊查询,分页和导出共用\n#macro(orgKeywordParams)#foreach($field in $queryList)#if($field.formType.startsWith(\'org-\')), @RequestParam(required = false) String ${field.attrName}Keyword#end#end#end\n#macro(orgKeywordDecl)#foreach($field in $queryList)#if($field.formType.startsWith(\'org-\')), String ${field.attrName}Keyword#end#end#end\n#macro(orgKeywordArgs)#foreach($field in $queryList)#if($field.formType.startsWith(\'org-\')), ${field.attrName}Keyword#end#end#end\n#macro(orgKeywordFilters)\n#if($hasOrgQuery)\n // 组织字段对整列 JSON 做 LIKE:关键字为数字或 id/name 时会误命中,需精确匹配时改用数据库 JSON 函数\n#end\n#foreach($field in $queryList)\n#if($field.formType.startsWith(\'org-\'))\n wrapper.like(StrUtil.isNotBlank(${field.attrName}Keyword), ${ClassName}Entity::$str.getProperty($field.attrName), ${field.attrName}Keyword);\n#end\n#end\n#end\npackage ${package}.${moduleName}.controller;\n\n#if($needStrUtil)\nimport cn.hutool.core.util.StrUtil;\n#end\nimport cn.hutool.core.util.ArrayUtil;\nimport cn.hutool.core.collection.CollUtil;\nimport com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;\nimport com.baomidou.mybatisplus.core.toolkit.Wrappers;\nimport com.baomidou.mybatisplus.extension.plugins.pagination.Page;\nimport ${package}.common.core.util.R;\nimport ${package}.common.log.annotation.SysLog;\n#if($opensource)\nimport com.pig4cloud.plugin.excel.annotation.ResponseExcel;\nimport com.pig4cloud.plugin.excel.annotation.RequestExcel;\n#else\nimport ${package}.common.excel.annotation.ResponseExcel;\nimport ${package}.common.excel.annotation.RequestExcel;\n#end\nimport ${entityPackage}.${ChildClassName}Entity;\nimport ${entityClassName};\nimport ${package}.${moduleName}.service.${ClassName}Service;\n\nimport io.swagger.v3.oas.annotations.security.SecurityRequirement;\n#if($isSpringBoot3)\nimport ${package}.common.security.annotation.HasPermission;\nimport org.springdoc.core.annotations.ParameterObject;\n#else\nimport org.springframework.security.access.prepost.PreAuthorize;\nimport org.springdoc.api.annotations.ParameterObject;\n#end\nimport org.springframework.http.HttpHeaders;\nimport io.swagger.v3.oas.annotations.tags.Tag;\nimport io.swagger.v3.oas.annotations.Operation;\nimport lombok.RequiredArgsConstructor;\nimport org.springframework.validation.BindingResult;\nimport org.springframework.web.bind.annotation.*;\n\nimport java.util.List;\nimport java.util.Objects;\n\n/**\n * ${tableComment}\n *\n * @author ${author}\n * @date ${datetime}\n */\n#foreach($field in $childFieldList)\n#if($field.primaryPk == \'1\')\n#set($childPkField = $field)\n#break\n#end\n#end\n#set($childFieldGetter = $str.getProperty($childField))\n@RestController\n@RequiredArgsConstructor\n@RequestMapping("/${functionName}" )\n@Tag(description = "${functionName}" , name = "${tableComment}管理" )\n@SecurityRequirement(name = HttpHeaders.AUTHORIZATION)\npublic class ${ClassName}Controller {\n\n private final ${ClassName}Service ${className}Service;\n\n /**\n * 分页查询\n * @param page 分页对象\n * @param ${className} ${tableComment}\n * @return\n */\n @Operation(summary = "分页查询" , description = "分页查询" )\n @GetMapping("/page" )\n #if($isSpringBoot3)\n @HasPermission("$str.lowerCase($moduleName)_$str.lowerCase($functionName)_view")\n #else\n @PreAuthorize("@pms.hasPermission(\'$str.lowerCase($moduleName)_$str.lowerCase($functionName)_view\')" )\n #end\n public R get${ClassName}Page(@ParameterObject Page page, @ParameterObject ${ClassName}Entity ${className}#orgKeywordParams()) {\n return R.ok(${className}Service.page(page, buildQueryWrapper(${className}#orgKeywordArgs())));\n }\n\n /**\n * 列表与导出共用的查询条件,保证导出结果与列表一致\n */\n private LambdaQueryWrapper<${ClassName}Entity> buildQueryWrapper(${ClassName}Entity ${className}#orgKeywordDecl()) {\n LambLine truncated
INSERT INTO `gen_template` (`id`, `template_name`, `generator_path`, `template_desc`, `template_code`, `create_time`, `update_time`, `del_flag`, `tenant_id`, `create_by`, `update_by`) VALUES (34,'左树右表ServiceV202611','${backendPath}/src/main/java/${packagePath}/${moduleName}/service/${ClassName}Service.java','左树右表ServiceV202611','package ${package}.${moduleName}.service;\n\nimport cn.hutool.core.lang.tree.Tree;\nimport com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;\nimport com.baomidou.mybatisplus.spring.service.IService;\nimport ${entityPackage}.${ChildClassName}Entity;\nimport ${entityClassName};\n\nimport java.util.List;\n\n/**\n * ${tableComment} Service接口\n *\n * @author ${author}\n * @date ${datetime}\n */\n#foreach($field in $childFieldList)\n#if($field.primaryPk == \'1\')\n#set($childPkField = $field)\n#break\n#end\n#end\npublic interface ${ClassName}Service extends IService<${ClassName}Entity> {\n\n /**\n * 构建树形结构数据\n * @param wrapper 查询条件\n * @return 树形结构数据\n */\n List<Tree<${childPkField.attrType}>> buildTree(LambdaQueryWrapper<${ChildClassName}Entity> wrapper);\n\n /**\n * 获取树节点详情\n * @param ${childClassName} 树节点查询对象\n * @return 树节点详情列表\n */\n List<${ChildClassName}Entity> getTreeDetails(${ChildClassName}Entity ${childClassName});\n\n /**\n * 保存树节点\n * @param ${childClassName} 树节点对象\n * @return 保存结果\n */\n Boolean saveTree(${ChildClassName}Entity ${childClassName});\n\n /**\n * 更新树节点\n * @param ${childClassName} 树节点对象\n * @return 更新结果\n */\n Boolean updateTree(${ChildClassName}Entity ${childClassName});\n\n /**\n * 批量删除树节点\n * @param ids 树节点ID列表\n * @return 删除结果\n */\n Boolean removeTreeByIds(${childPkField.attrType}[] ids);\n}\n','2026-04-08 17:38:24','2026-04-08 17:38:24','0',1,'admin','admin');
INSERT INTO `gen_template` (`id`, `template_name`, `generator_path`, `template_desc`, `template_code`, `create_time`, `update_time`, `del_flag`, `tenant_id`, `create_by`, `update_by`) VALUES (35,'左树右表ServiceImplV202611','${backendPath}/src/main/java/${packagePath}/${moduleName}/service/impl/${ClassName}ServiceImpl.java','左树右表ServiceImplV202611','package ${package}.${moduleName}.service.impl;\n\nimport cn.hutool.core.collection.CollUtil;\nimport cn.hutool.core.util.ArrayUtil;\nimport cn.hutool.core.lang.tree.Tree;\nimport cn.hutool.core.lang.tree.TreeNode;\nimport cn.hutool.core.lang.tree.TreeUtil;\nimport com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;\nimport com.baomidou.mybatisplus.core.toolkit.Wrappers;\nimport com.baomidou.mybatisplus.spring.service.impl.ServiceImpl;\nimport ${entityPackage}.${ChildClassName}Entity;\nimport ${entityClassName};\nimport ${package}.${moduleName}.mapper.${ChildClassName}Mapper;\nimport ${package}.${moduleName}.mapper.${ClassName}Mapper;\nimport ${package}.${moduleName}.service.${ClassName}Service;\nimport lombok.RequiredArgsConstructor;\nimport org.springframework.stereotype.Service;\nimport org.springframework.transaction.annotation.Transactional;\n\nimport java.util.ArrayList;\nimport java.util.HashMap;\nimport java.util.HashSet;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Objects;\nimport java.util.Set;\nimport java.util.function.Function;\n\n/**\n * ${tableComment} Service实现类\n *\n * @author ${author}\n * @date ${datetime}\n */\n#foreach($field in $childFieldList)\n#if($field.primaryPk == \'1\')\n#set($childPkField = $field)\n#set($childPkGetter = $str.getProperty($childPkField.attrName))\n#break\n#end\n#end\n#set($parentGetter = $str.getProperty($parentField))\n#set($childFieldGetter = $str.getProperty($childField))\n#if($childPkField.attrType == \'Long\')\n#set($treeRootId = \'0L\')\n#elseif($childPkField.attrType == \'String\')\n#set($treeRootId = \'\"0\"\')\n#else\n#set($treeRootId = \'0\')\n#end\n@Service\n@RequiredArgsConstructor\npublic class ${ClassName}ServiceImpl extends ServiceImpl<${ClassName}Mapper, ${ClassName}Entity> implements ${ClassName}Service {\n\n private final ${ChildClassName}Mapper ${childClassName}Mapper;\n\n /**\n * 构建树形结构数据\n * @param wrapper 查询条件\n * @return 树形结构数据\n */\n @Override\n public List<Tree<${childPkField.attrType}>> buildTree(LambdaQueryWrapper<${ChildClassName}Entity> wrapper) {\n List<${ChildClassName}Entity> allList = ${childClassName}Mapper.selectList(wrapper);\n\n if (CollUtil.isEmpty(allList)) {\n return new ArrayList<>();\n }\n\n List<TreeNode<${childPkField.attrType}>> collect = allList.stream().map(getNodeFunction()).toList();\n return TreeUtil.build(collect, ${treeRootId});\n }\n\n /**\n * 获取树节点详情\n * @param ${childClassName} 树节点查询对象\n * @return 树节点详情列表\n */\n @Override\n public List<${ChildClassName}Entity> getTreeDetails(${ChildClassName}Entity ${childClassName}) {\n return ${childClassName}Mapper.selectList(Wrappers.query(${childClassName}));\n }\n\n /**\n * 保存树节点\n * @param ${childClassName} 树节点对象\n * @return 保存结果\n */\n @Override\n @Transactional(rollbackFor = Exception.class)\n public Boolean saveTree(${ChildClassName}Entity ${childClassName}) {\n ${childClassName}.$str.setProperty($parentField)(validateParentRelation(null, ${childClassName}.$str.getProperty($parentField)()));\n return ${childClassName}Mapper.insert(${childClassName}) > 0;\n }\n\n /**\n * 更新树节点\n * @param ${childClassName} 树节点对象\n * @return 更新结果\n */\n @Override\n @Transactional(rollbackFor = Exception.class)\n public Boolean updateTree(${ChildClassName}Entity ${childClassName}) {\n ${childClassName}.$str.setProperty($parentField)(validateParentRelation(${childClassName}.$str.getProperty($childPkField.attrName)(), ${childClassName}.$str.getProperty($parentField)()));\n return ${childClassName}Mapper.updateById(${childClassName}) > 0;\n }\n\n /**\n * 批量删除树节点\n * @param ids 树节点ID列表\n * @return 删除结果\n */\n @Override\n @Transactional(rollbackFor = Exception.class)\n public Boolean removeTreeByIds(${childPkField.attrType}[] ids) {\n if (ArrayUtil.isEmpty(ids)) {\n return Boolean.TRUE;\n }\n\n for (${childPkField.attrType} id : ids) {\n if (hasChildNodes(id)) {\n throw new RuntimeException(\"当前节点存在子节点,不能删除\");\n }\n if (hasMainRecords(id)) {\n throw new RuntimeException(\"当前节点已关联主表数据,不能删除\");\n }\n }\n\n return ${childClassNameLine truncated
INSERT INTO `gen_template` (`id`, `template_name`, `generator_path`, `template_desc`, `template_code`, `create_time`, `update_time`, `del_flag`, `tenant_id`, `create_by`, `update_by`) VALUES (36,'实体V202611','${entityPath}/src/main/java/${entityPackagePath}/${ClassName}Entity.java','实体V202611','#set($hasOrg = false)\n#foreach($field in $fieldList)\n#if($field.formType.startsWith(\'org-\'))\n#set($hasOrg = true)\n#end\n#end\npackage ${entityPackage};\n\nimport com.baomidou.mybatisplus.annotation.*;\nimport com.baomidou.mybatisplus.spring.activerecord.Model;\nimport io.swagger.v3.oas.annotations.media.Schema;\nimport lombok.Data;\nimport lombok.EqualsAndHashCode;\n#if($hasOrg)\nimport com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler;\nimport ${package}.common.core.util.OrgRef;\nimport org.apache.fesod.sheet.annotation.ExcelIgnore;\nimport java.util.List;\n#end\n#if($isTenant)\nimport ${package}.common.core.util.TenantTable;\n#end\n#foreach($import in $importList)\n#if(!$import.startsWith(\'java.lang.\'))\nimport $import;\n#end\n#end\n\n/**\n * ${tableComment}\n *\n * @author ${author}\n * @date ${datetime}\n */\n@Data\n#if($isTenant)\n@TenantTable\n#end\n@TableName(value = \"${tableName}\"#if($hasOrg), autoResultMap = true#end)\n@EqualsAndHashCode(callSuper = true)\n@Schema(description = \"${tableComment}\")\npublic class ${ClassName}Entity extends Model<${ClassName}Entity> {\n\n#foreach ($field in $fieldList)\n#if(${field.fieldComment})#set($comment=${field.fieldComment})#else #set($comment=${field.attrName})#end\n\n /**\n * $comment\n */\n#if($field.primaryPk == \'1\')\n @TableId(type = IdType.ASSIGN_ID)\n#end\n#if($field.formType.startsWith(\'org-\'))\n @TableField(typeHandler = JacksonTypeHandler.class#if($field.autoFill == \'INSERT\' || $field.autoFill == \'INSERT_UPDATE\' || $field.autoFill == \'UPDATE\'), fill = FieldFill.${field.autoFill}#end)\n @ExcelIgnore\n#elseif($field.autoFill == \'INSERT\')\n @TableField(fill = FieldFill.INSERT)\n#elseif($field.autoFill == \'INSERT_UPDATE\')\n @TableField(fill = FieldFill.INSERT_UPDATE)\n#elseif($field.autoFill == \'UPDATE\')\n @TableField(fill = FieldFill.UPDATE)\n#end\n#if($field.fieldName == \'del_flag\')\n @TableLogic\n @TableField(fill = FieldFill.INSERT)\n#end\n @Schema(description=\"$comment\"#if($field.hidden),hidden=$field.hidden#end)\n#if($field.formType.startsWith(\'org-\'))\n private List<OrgRef> $field.attrName;\n#elseif($field.formType == \'checkbox\')\n private ${field.attrType}[] $field.attrName;\n#elseif($field.formType == \'daterange\' || $field.formType == \'datetimerange\')\n private String[] $field.attrName;\n#else\n private $field.attrType $field.attrName;\n#end\n#end\n#foreach ($field in $queryList)\n#if($field.queryFormType == \'daterange\' || $field.queryFormType == \'datetimerange\')\n#if(${field.fieldComment})#set($comment=${field.fieldComment})#else #set($comment=${field.attrName})#end\n\n /**\n * $comment 查询范围\n */\n @TableField(exist = false)\n @Schema(description=\"$comment 查询范围\",hidden=true)\n private String[] ${field.attrName}Range;\n#end\n#end\n}\n','2026-04-08 17:38:24','2026-04-08 17:38:24','0',1,'admin','admin');
INSERT INTO `gen_template` (`id`, `template_name`, `generator_path`, `template_desc`, `template_code`, `create_time`, `update_time`, `del_flag`, `tenant_id`, `create_by`, `update_by`) VALUES (37,'MapperV202611','${backendPath}/src/main/java/${packagePath}/${moduleName}/mapper/${ClassName}Mapper.java','MapperV202611','package ${package}.${moduleName}.mapper;\n\n\nimport com.baomidou.mybatisplus.core.mapper.BaseMapper;\nimport ${entityClassName};\nimport org.apache.ibatis.annotations.Mapper;\n\n@Mapper\npublic interface ${ClassName}Mapper extends BaseMapper<${ClassName}Entity> {\n\n}\n','2026-04-08 17:38:24','2026-04-08 17:38:24','0',1,'admin','admin');
INSERT INTO `gen_template` (`id`, `template_name`, `generator_path`, `template_desc`, `template_code`, `create_time`, `update_time`, `del_flag`, `tenant_id`, `create_by`, `update_by`) VALUES (38,'Mapper.xmlV202611','${backendPath}/src/main/resources/mapper/${ClassName}Mapper.xml','Mapper.xmlV202611','<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE mapper PUBLIC \"-//mybatis.org//DTD Mapper 3.0//EN\" \"http://mybatis.org/dtd/mybatis-3-mapper.dtd\">\n\n<mapper namespace=\"${package}.${moduleName}.mapper.${ClassName}Mapper\">\n\n <resultMap id=\"${className}Map\" type=\"${entityClassName}\">\n#foreach ($field in $fieldList)\n #if($field.primaryPk == \'1\')\n <id property=\"$field.attrName\" column=\"$field.fieldName\"/>\n #else\n <result property=\"$field.attrName\" column=\"$field.fieldName\"#if($field.formType.startsWith(\'org-\')) typeHandler=\"com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler\"#end/>\n #end\n#end\n </resultMap>\n</mapper>\n','2026-04-08 17:38:24','2026-04-08 17:38:24','0',1,'admin','admin');
INSERT INTO `gen_template` (`id`, `template_name`, `generator_path`, `template_desc`, `template_code`, `create_time`, `update_time`, `del_flag`, `tenant_id`, `create_by`, `update_by`) VALUES (39,'子实体V202611','${entityPath}/src/main/java/${entityPackagePath}/${ChildClassName}Entity.java','子实体V202611','#set($hasOrg = false)\n#foreach($field in $childFieldList)\n#if($field.formType.startsWith(\'org-\'))\n#set($hasOrg = true)\n#end\n#end\npackage ${entityPackage};\n\nimport com.baomidou.mybatisplus.annotation.*;\nimport com.baomidou.mybatisplus.spring.activerecord.Model;\nimport io.swagger.v3.oas.annotations.media.Schema;\n#if($isChildTenant)\nimport ${package}.common.core.util.TenantTable;\n#end\nimport lombok.Data;\nimport lombok.EqualsAndHashCode;\n#if($hasOrg)\nimport com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler;\nimport ${package}.common.core.util.OrgRef;\nimport java.util.List;\n#end\n#set($childImports = [])\n#foreach($field in $childFieldList)\n#if($field.packageName && !$field.packageName.startsWith(\'java.lang.\') && !$childImports.contains($field.packageName))\n#set($void = $childImports.add($field.packageName))\n#end\n#end\n#foreach($import in $childImports)\nimport $import;\n#end\n\n/**\n * ${tableComment}\n *\n * @author ${author}\n * @date ${datetime}\n */\n@Data\n#if($isChildTenant)\n@TenantTable\n#end\n@TableName(value = \"${childTableName}\"#if($hasOrg), autoResultMap = true#end)\n@EqualsAndHashCode(callSuper = true)\n@Schema(description = \"${childTableName}\")\npublic class ${ChildClassName}Entity extends Model<${ChildClassName}Entity> {\n\n#foreach ($field in $childFieldList)\n#if(${field.fieldComment})#set($comment=${field.fieldComment})#else #set($comment=${field.attrName})#end\n /**\n * $comment\n */\n#if($field.primaryPk == \'1\')\n @TableId(type = IdType.ASSIGN_ID)\n#end\n#if($field.formType.startsWith(\'org-\'))\n @TableField(typeHandler = JacksonTypeHandler.class#if($field.autoFill == \'INSERT\' || $field.autoFill == \'INSERT_UPDATE\' || $field.autoFill == \'UPDATE\'), fill = FieldFill.${field.autoFill}#end)\n#elseif($field.autoFill == \'INSERT\')\n @TableField(fill = FieldFill.INSERT)\n#elseif($field.autoFill == \'INSERT_UPDATE\')\n @TableField(fill = FieldFill.INSERT_UPDATE)\n#elseif($field.autoFill == \'UPDATE\')\n @TableField(fill = FieldFill.UPDATE)\n#end\n#if($field.fieldName == \'del_flag\')\n @TableLogic\n @TableField(fill = FieldFill.INSERT)\n#end\n @Schema(description=\"$comment\"#if($field.hidden),hidden=$field.hidden#end)\n#if($field.formType.startsWith(\'org-\'))\n private List<OrgRef> $field.attrName;\n#elseif($field.formType == \'checkbox\')\n private ${field.attrType}[] $field.attrName;\n#else\n private $field.attrType $field.attrName;\n#end \n#end\n}\n','2026-04-08 17:38:24','2026-04-08 17:38:24','0',1,'admin','admin');
INSERT INTO `gen_template` (`id`, `template_name`, `generator_path`, `template_desc`, `template_code`, `create_time`, `update_time`, `del_flag`, `tenant_id`, `create_by`, `update_by`) VALUES (40,'子MapperV202611','${backendPath}/src/main/java/${packagePath}/${moduleName}/mapper/${ChildClassName}Mapper.java','子MapperV202611','package ${package}.${moduleName}.mapper;\n\nimport ${package}.common.data.datascope.PigxBaseMapper;\nimport ${entityPackage}.${ChildClassName}Entity;\nimport org.apache.ibatis.annotations.Mapper;\n\n@Mapper\npublic interface ${ChildClassName}Mapper extends PigxBaseMapper<${ChildClassName}Entity> {\n\n}\n','2026-04-08 17:38:24','2026-04-08 17:38:24','0',1,'admin','admin');
INSERT INTO `gen_template` (`id`, `template_name`, `generator_path`, `template_desc`, `template_code`, `create_time`, `update_time`, `del_flag`, `tenant_id`, `create_by`, `update_by`) VALUES (41,'权限菜单V202611','${backendPath}/menu/${functionName}_menu.sql','权限菜单V202611','#set($permissionPrefix = \"${moduleName}_${functionName}\")\n#set($permissionPrefix = $permissionPrefix.toLowerCase())\n-- 该脚本不要直接执行, 注意维护菜单的父节点ID 默认 父节点-1 , #if(!$opensource)默认租户 1#end\n#set($menuId=${dateTool.getSystemTime()})\n\n-- 菜单SQL\ninsert into sys_menu ( menu_id,parent_id, path, permission, menu_type, icon, del_flag, create_time, sort_order, update_time, name#if(!$opensource), tenant_id#end)\nvalues (${menuId}, \'-1\', \'/${moduleName}/${functionName}/index\', \'\', \'0\', \'icon-bangzhushouji\', \'0\', null , \'8\', null , \'${tableComment}管理\'#if(!$opensource), 1#end);\n\n-- 菜单对应按钮SQL\ninsert into sys_menu ( menu_id,parent_id, permission, menu_type, path, icon, del_flag, create_time, sort_order, update_time, name#if(!$opensource), tenant_id#end)\nvalues (${math.add($menuId,1)},${menuId}, \'${permissionPrefix}_view\', \'1\', null, \'1\', \'0\', null, \'0\', null, \'${tableComment}查看\'#if(!$opensource), 1#end);\n\ninsert into sys_menu ( menu_id,parent_id, permission, menu_type, path, icon, del_flag, create_time, sort_order, update_time, name#if(!$opensource), tenant_id#end)\nvalues (${math.add($menuId,2)},${menuId}, \'${permissionPrefix}_add\', \'1\', null, \'1\', \'0\', null, \'1\', null, \'${tableComment}新增\'#if(!$opensource), 1#end);\n\ninsert into sys_menu (menu_id, parent_id, permission, menu_type, path, icon, del_flag, create_time, sort_order, update_time, name#if(!$opensource), tenant_id#end)\nvalues (${math.add($menuId,3)},${menuId}, \'${permissionPrefix}_edit\', \'1\', null, \'1\', \'0\', null, \'2\', null, \'${tableComment}修改\'#if(!$opensource), 1#end);\n\ninsert into sys_menu (menu_id, parent_id, permission, menu_type, path, icon, del_flag, create_time, sort_order, update_time, name#if(!$opensource), tenant_id#end)\nvalues (${math.add($menuId,4)},${menuId}, \'${permissionPrefix}_del\', \'1\', null, \'1\', \'0\', null, \'3\', null, \'${tableComment}删除\'#if(!$opensource), 1#end);\n\ninsert into sys_menu ( menu_id,parent_id, permission, menu_type, path, icon, del_flag, create_time, sort_order, update_time, name#if(!$opensource), tenant_id#end)\nvalues (${math.add($menuId,5)},${menuId}, \'${permissionPrefix}_export\', \'1\', null, \'1\', \'0\', null, \'3\', null, \'导入导出\'#if(!$opensource), 1#end);\n','2026-04-08 17:38:24','2026-04-08 17:38:24','0',1,'admin','admin');
INSERT INTO `gen_template` (`id`, `template_name`, `generator_path`, `template_desc`, `template_code`, `create_time`, `update_time`, `del_flag`, `tenant_id`, `create_by`, `update_by`) VALUES (42,'左树右表api.tsV202611','${frontendPath}/src/api/${moduleName}/${functionName}.ts','左树右表api.tsV202611','import request from \"/@/utils/request\"\n\n// ========== 基础CRUD接口 ==========\n\n/**\n * 分页查询列表数据\n * @param query - 查询参数对象\n * @returns Promise<分页数据>\n */\nexport function fetchList(query?: Object) {\n return request({\n url: \'/${moduleName}/${functionName}/page\',\n method: \'get\',\n params: query\n })\n}\n\n/**\n * 新增数据\n * @param obj - 要新增的数据对象\n * @returns Promise<boolean> - 操作结果\n */\nexport function addObj(obj?: Object) {\n return request({\n url: \'/${moduleName}/${functionName}\',\n method: \'post\',\n data: obj\n })\n}\n\n/**\n * 获取详情数据\n * @param obj - 查询参数对象(包含ID等)\n * @returns Promise<数据详情>\n */\nexport function getObj(obj?: Object) {\n return request({\n url: \'/${moduleName}/${functionName}/details\',\n method: \'get\',\n params: obj\n })\n}\n\n/**\n * 批量删除数据\n * @param ids - 要删除的ID数组\n * @returns Promise<操作结果>\n */\nexport function delObjs(ids?: Object) {\n return request({\n url: \'/${moduleName}/${functionName}\',\n method: \'delete\',\n data: ids\n })\n}\n\n/**\n * 更新数据\n * @param obj - 要更新的数据对象\n * @returns Promise<操作结果>\n */\nexport function putObj(obj?: Object) {\n return request({\n url: \'/${moduleName}/${functionName}\',\n method: \'put\',\n data: obj\n })\n}\n\n// ========== 树形CRUD接口 ==========\n\n/**\n * 获取树形列表数据\n * @param query - 查询参数对象\n * @returns Promise<树形数据>\n */\nexport function fetchTreeList(query?: Object) {\n return request({\n url: \'/${moduleName}/${functionName}/tree\',\n method: \'get\',\n params: query\n })\n}\n\n/**\n * 获取树节点详情\n * @param obj - 查询参数对象(包含ID等)\n * @returns Promise<树节点详情>\n */\nexport function getTreeObj(obj?: Object) {\n return request({\n url: \'/${moduleName}/${functionName}/tree/details\',\n method: \'get\',\n params: obj\n })\n}\n\n/**\n * 新增树节点\n * @param obj - 要新增的树节点对象\n * @returns Promise<操作结果>\n */\nexport function addTreeObj(obj?: Object) {\n return request({\n url: \'/${moduleName}/${functionName}/tree\',\n method: \'post\',\n data: obj\n })\n}\n\n/**\n * 更新树节点\n * @param obj - 要更新的树节点对象\n * @returns Promise<操作结果>\n */\nexport function putTreeObj(obj?: Object) {\n return request({\n url: \'/${moduleName}/${functionName}/tree\',\n method: \'put\',\n data: obj\n })\n}\n\n/**\n * 删除树节点\n * @param ids - 要删除的树节点ID数组\n * @returns Promise<操作结果>\n */\nexport function delTreeObjs(ids?: Object) {\n return request({\n url: \'/${moduleName}/${functionName}/tree\',\n method: \'delete\',\n data: ids\n })\n}\n\n// ========== 工具函数 ==========\n\n/**\n * 验证字段值唯一性\n * @param rule - 验证规则对象\n * @param value - 要验证的值\n * @param callback - 验证回调函数\n * @param isEdit - 是否为编辑模式\n *\n * @example\n * // 在表单验证规则中使用\n * fieldName: [\n * {\n * validator: (rule, value, callback) => {\n * validateExist(rule, value, callback, form.${pk.attrName} !== \'\');\n * },\n * trigger: \'blur\',\n * },\n * ]\n */\nexport function validateExist(rule: any, value: any, callback: any, isEdit: boolean) {\n // 编辑模式下跳过验证\n if (isEdit) {\n return callback();\n }\n\n // 查询是否存在相同值\n getObj({ [rule.field]: value }).then((response) => {\n const result = response.data;\n if (result !== null && result.length > 0) {\n callback(new Error(\'数据已经存在\'));\n } else {\n callback();\n }\n });\n}\n','2026-04-08 17:38:24','2026-04-08 17:38:24','0',1,'admin','admin');
INSERT INTO `gen_template` (`id`, `template_name`, `generator_path`, `template_desc`, `template_code`, `create_time`, `update_time`, `del_flag`, `tenant_id`, `create_by`, `update_by`) VALUES (43,'左树右表表格V202611','${frontendPath}/src/views/${moduleName}/${functionName}/index.vue','左树右表表格V202611','## 有字典字段时才导入 useDict\n#set($hasDictField = false)\n#foreach($field in $queryList)\n#if($field.fieldDict)\n#set($hasDictField = true)\n#end\n#end\n#foreach($field in $gridList)\n#if($field.fieldDict)\n#set($hasDictField = true)\n#end\n#end\n#foreach($field in $childFieldList)\n#if($field.primaryPk == \'1\')\n#set($childPkField = $field)\n#break\n#end\n#end\n## 开关:按属性类型决定开/关的值,Boolean 用 true/false,整型用 1/0,其余用 \'1\'/\'0\'\n#macro(switchValues $f)\n#if($f.attrType == \'Boolean\')\n#set($switchOn = \'true\')\n#set($switchOff = \'false\')\n#elseif($f.attrType == \'Integer\' || $f.attrType == \'Long\' || $f.attrType == \'Short\')\n#set($switchOn = \'1\')\n#set($switchOff = \'0\')\n#else\n#set($switchOn = "\'1\'")\n#set($switchOff = "\'0\'")\n#end\n#end\n<template>\n <div class="layout-padding">\n <splitpanes>\n <pane size="15">\n <div class="layout-padding-auto layout-padding-view">\n <el-scrollbar>\n <div class="mb8" style="display: flex; align-items: center; justify-content: space-between;">\n <span style="font-weight: 500;">左侧节点</span>\n <div>\n <el-tooltip :content="currentTreeId ? \'新增子节点\' : \'新增根节点\'" placement="top">\n <el-button link type="primary" icon="FolderAdd" @click="handleAddTree" />\n </el-tooltip>\n </div>\n </div>\n <el-tree\n ref="treeRef"\n :data="treeData"\n :props="treeProps"\n node-key="${childPkField.attrName}"\n highlight-current\n default-expand-all\n :expand-on-click-node="false"\n @node-click="handleTreeNodeClick"\n >\n <template #default="{ node, data }">\n <span style="flex: 1; display: flex; align-items: center; justify-content: space-between;">\n <span>{{ node.label }}</span>\n <span v-if="currentTreeId === data.${childPkField.attrName}" style="margin-left: 8px;">\n <el-tooltip content="编辑" placement="top">\n <el-button link type="primary" icon="Edit" size="small" @click.stop="handleEditTree" />\n </el-tooltip>\n <el-tooltip content="删除" placement="top">\n <el-button link type="danger" icon="Delete" size="small" @click.stop="handleDeleteTree" />\n </el-tooltip>\n </span>\n </span>\n </template>\n </el-tree>\n </el-scrollbar>\n </div>\n </pane>\n <pane class="ml8">\n <div class="layout-padding-auto layout-padding-view">\n#if($queryList)\n <el-row v-show="showSearch">\n <el-form :model="state.queryForm" ref="queryRef" :inline="true" @keyup.enter="getDataList">\n#foreach($field in $queryList)\n#if($field.formType.startsWith(\'org-\'))#set($queryKey = "${field.attrName}Keyword")#else#set($queryKey = $field.attrName)#end\n#if($field.attrName != ${childField})\n#if($field.queryFormType == \'select\')\n <el-form-item label="#if(${field.fieldComment})${field.fieldComment}#else${field.attrName}#end" prop="${queryKey}">\n <el-select v-model="state.queryForm.${queryKey}" placeholder="请选择#if(${field.fieldComment})${field.fieldComment}#else${field.attrName}#end">\n#if($field.fieldDict)\n <el-option \n :label="item.label" \n :value="item.value" \n v-for="(item, index) in ${field.fieldDict}" \n :key="index"\n />\n#else\n <el-option label="请选择" value="0" />\n#end\n </el-select>\n </el-form-item>\n#elseif($field.queryFormType == \'date\')\n <el-form-item label="#if(${field.fieldComment})${field.fieldComment}#else${field.attrName}#end" prop="${queryKey}">\n <el-date-picker\n type="date"\n placeholder="请输入#if(${field.fieldComment})${field.fieldComment}#else${field.attrName}#end"\n v-model="state.queryForm.${queryKey}"\n :value-format="dateStr"\n />\n </el-form-item>\n#elseif($field.queryFormType == \'daterange\')\n <el-form-item label="#if(${field.fieldComment})${field.fieldComment}#else${field.attrName}#end" prop="${field.attrName}Range">\n <el-date-pickerLine truncated
INSERT INTO `gen_template` (`id`, `template_name`, `generator_path`, `template_desc`, `template_code`, `create_time`, `update_time`, `del_flag`, `tenant_id`, `create_by`, `update_by`) VALUES (44,'左树右表树表单V202611','${frontendPath}/src/views/${moduleName}/${functionName}/tree-form.vue','左树右表树表单V202611','#foreach($field in $childFieldList)\n#if($field.primaryPk == \'1\')\n#set($childPkField = $field)\n#break\n#end\n#end\n#set($fieldDict=[])\n#foreach($field in $childFieldList)\n#if($field.fieldDict)\n#set($void=$fieldDict.add($field.fieldDict))\n#end\n#end\n## 开关:按属性类型决定开/关的值,Boolean 用 true/false,整型用 1/0,其余用 \'1\'/\'0\'\n#macro(switchValues $f)\n#if($f.attrType == \'Boolean\')\n#set($switchOn = \'true\')\n#set($switchOff = \'false\')\n#elseif($f.attrType == \'Integer\' || $f.attrType == \'Long\' || $f.attrType == \'Short\')\n#set($switchOn = \'1\')\n#set($switchOff = \'0\')\n#else\n#set($switchOn = "\'1\'")\n#set($switchOff = "\'0\'")\n#end\n#end\n#set($hasOrg = false)\n#foreach($field in $childFieldList)\n#if($field.formType.startsWith(\'org-\'))\n#set($hasOrg = true)\n#end\n#end\n<template>\n <el-dialog :title="form.${childPkField.attrName} ? \'编辑\' : \'新增\'" v-model="visible"\n :close-on-click-modal="false" draggable>\n <el-form ref="dataFormRef" :model="form" :rules="dataRules" label-width="90px" v-loading="loading">\n <el-row :gutter="24">\n#if($formLayout == 1)\n <el-col :span="24" class="mb20">\n#elseif($formLayout == 2)\n <el-col :span="12" class="mb20">\n#end\n <el-form-item label="父级节点" prop="${parentField}">\n <el-tree-select\n v-model="form.${parentField}"\n :data="parentNodes"\n :props="treeSelectProps"\n check-strictly\n :render-after-expand="false"\n placeholder="请选择父级节点"\n style="width: 100%"\n clearable\n filterable\n />\n </el-form-item>\n </el-col>\n#foreach($field in $childFieldList)\n#if($field.attrName != ${childPkField.attrName} && $field.attrName != ${parentField})\n#if($formLayout == 1)\n <el-col :span="24" class="mb20">\n#elseif($formLayout == 2)\n <el-col :span="12" class="mb20">\n#end\n#if($field.formType.startsWith(\'org-\'))\n#set($orgType = $field.formType.replace(\'org-\', \'\').replace(\'-multiple\', \'\'))\n <el-form-item label="${field.fieldComment}" prop="${field.attrName}">\n <OrgSelect v-model="form.${field.attrName}" value-type="item" type="${orgType}" :multiple="#if($field.formType.endsWith(\'-multiple\'))true#else false#end" label="${field.fieldComment}" :disabled="loading" />\n </el-form-item>\n </el-col>\n#elseif($field.formType == \'switch\')\n#switchValues($field)\n <el-form-item label="#if(${field.fieldComment})${field.fieldComment}#else${field.attrName}#end" prop="${field.attrName}">\n <el-switch :model-value="String(form.${field.attrName}) === String($switchOn)" @change="(checked) => (form.${field.attrName} = checked ? $switchOn : $switchOff)" />\n </el-form-item>\n </el-col>\n#elseif($field.formType == \'text\')\n <el-form-item label="#if(${field.fieldComment})${field.fieldComment}#else${field.attrName}#end" prop="${field.attrName}">\n <el-input v-model="form.${field.attrName}" placeholder="请输入#if(${field.fieldComment})${field.fieldComment}#else${field.attrName}#end"/>\n </el-form-item>\n </el-col>\n#elseif($field.formType == \'textarea\')\n <el-form-item label="#if(${field.fieldComment})${field.fieldComment}#else${field.attrName}#end" prop="${field.attrName}">\n <el-input type="textarea" v-model="form.${field.attrName}" placeholder="请输入#if(${field.fieldComment})${field.fieldComment}#else${field.attrName}#end"/>\n </el-form-item>\n </el-col>\n#elseif($field.formType == \'select\')\n <el-form-item label="#if(${field.fieldComment})${field.fieldComment}#else${field.attrName}#end" prop="${field.attrName}">\n <el-select v-model="form.${field.attrName}" placeholder="请选择#if(${field.fieldComment})${field.fieldComment}#else${field.attrName}#end">\n#if($field.fieldDict)\n <el-option :value="item.value" :label="item.label" v-for="(item, index) in ${field.fieldDict}" :key="index"></el-option>\n#else\n <el-option label="请选择" value="0"></el-option>\n#end\n </el-select>\n </el-form-item>\n </el-col>\n#elseif($field.formType == \'radio\')\n <el-form-item label="#if(${field.fieldComment})${field.fieldComment}#else${field.attrName}#end" prop="${field.attrName}">\n <el-radio-group v-model="form.${field.attrName}">\n#if($field.fieldDict)\n <el-radio :label="item.value" v-for="(item, index) in ${field.fieldDicLine truncated
INSERT INTO `gen_template` (`id`, `template_name`, `generator_path`, `template_desc`, `template_code`, `create_time`, `update_time`, `del_flag`, `tenant_id`, `create_by`, `update_by`) VALUES (45,'左树右表主表单V202611','${frontendPath}/src/views/${moduleName}/${functionName}/form.vue','左树右表主表单V202611','#set($hasDuplicate = false)\n#foreach($field in $formList)\n#if($field.attrName != ${childField} && $field.formValidator == \'duplicate\')\n#set($hasDuplicate = true)\n#end\n#end\n#foreach($field in $childFieldList)\n#if($field.primaryPk == \'1\')\n#set($childPkField = $field)\n#break\n#end\n#end\n#set($relationFieldLabel = $childField)\n#foreach($field in $fieldList)\n#if($field.attrName == $childField)\n#if($field.fieldComment)\n#set($relationFieldLabel = $field.fieldComment)\n#else\n#set($relationFieldLabel = $field.attrName)\n#end\n#break\n#end\n#end\n#set($fieldDict=[])\n#foreach($field in $formList)\n#if($field.fieldDict)\n#set($void=$fieldDict.add($field.fieldDict))\n#end\n#end\n## 开关:按属性类型决定开/关的值,Boolean 用 true/false,整型用 1/0,其余用 \'1\'/\'0\'\n#macro(switchValues $f)\n#if($f.attrType == \'Boolean\')\n#set($switchOn = \'true\')\n#set($switchOff = \'false\')\n#elseif($f.attrType == \'Integer\' || $f.attrType == \'Long\' || $f.attrType == \'Short\')\n#set($switchOn = \'1\')\n#set($switchOff = \'0\')\n#else\n#set($switchOn = "\'1\'")\n#set($switchOff = "\'0\'")\n#end\n#end\n#set($hasOrg = false)\n#foreach($field in $formList)\n#if($field.formType.startsWith(\'org-\'))\n#set($hasOrg = true)\n#end\n#end\n<template>\n <el-dialog :title="form.${pk.attrName} ? \'编辑\' : \'新增\'" v-model="visible"\n :close-on-click-modal="false" draggable>\n <el-form ref="dataFormRef" :model="form" :rules="dataRules" label-width="90px" v-loading="loading">\n <el-row :gutter="24">\n#if($formLayout == 1)\n <el-col :span="24" class="mb20">\n#elseif($formLayout == 2)\n <el-col :span="12" class="mb20">\n#end\n <el-form-item label="${relationFieldLabel}" prop="${childField}">\n <el-tree-select\n v-model="form.${childField}"\n :data="treeNodes"\n :props="treeSelectProps"\n check-strictly\n :render-after-expand="false"\n placeholder="请选择${relationFieldLabel}"\n style="width: 100%"\n clearable\n filterable\n />\n </el-form-item>\n </el-col>\n#foreach($field in $formList)\n#if($field.attrName != ${pk.attrName} && $field.attrName != ${childField})\n#if($formLayout == 1)\n <el-col :span="24" class="mb20">\n#elseif($formLayout == 2)\n <el-col :span="12" class="mb20">\n#end\n#if($field.formType.startsWith(\'org-\'))\n#set($orgType = $field.formType.replace(\'org-\', \'\').replace(\'-multiple\', \'\'))\n <el-form-item label="${field.fieldComment}" prop="${field.attrName}">\n <OrgSelect v-model="form.${field.attrName}" value-type="item" type="${orgType}" :multiple="#if($field.formType.endsWith(\'-multiple\'))true#else false#end" label="${field.fieldComment}" :disabled="loading" />\n </el-form-item>\n </el-col>\n#elseif($field.formType == \'switch\')\n#switchValues($field)\n <el-form-item label="#if(${field.fieldComment})${field.fieldComment}#else${field.attrName}#end" prop="${field.attrName}">\n <el-switch :model-value="String(form.${field.attrName}) === String($switchOn)" @change="(checked) => (form.${field.attrName} = checked ? $switchOn : $switchOff)" />\n </el-form-item>\n </el-col>\n#elseif($field.formType == \'text\')\n <el-form-item label="#if(${field.fieldComment})${field.fieldComment}#else${field.attrName}#end" prop="${field.attrName}">\n <el-input v-model="form.${field.attrName}" placeholder="请输入#if(${field.fieldComment})${field.fieldComment}#else${field.attrName}#end"/>\n </el-form-item>\n </el-col>\n#elseif($field.formType == \'textarea\')\n <el-form-item label="#if(${field.fieldComment})${field.fieldComment}#else${field.attrName}#end" prop="${field.attrName}">\n <el-input type="textarea" v-model="form.${field.attrName}" placeholder="请输入#if(${field.fieldComment})${field.fieldComment}#else${field.attrName}#end"/>\n </el-form-item>\n </el-col>\n#elseif($field.formType == \'select\')\n <el-form-item label="#if(${field.fieldComment})${field.fieldComment}#else${field.attrName}#end" prop="${field.attrName}">\n <el-select v-model="form.${field.attrName}" placeholder="请选择#if(${field.fieldComment})${field.fieldComment}#else${field.attrName}#end">\n#if($field.fieldDict)\n <el-option :value="item.value" :label="item.label" v-for="(item, index) in ${field.fieldDict}" :key="index"></el-option>\n#else\n <el-option label="请选择" value="0"></el-option>\n#end\n Line truncated
COMMIT;
-- ----------------------------
@@ -269,28 +297,51 @@ CREATE TABLE `gen_template_group` (
-- Records of gen_template_group
-- ----------------------------
BEGIN;
INSERT INTO `gen_template_group` VALUES (1, 3);
INSERT INTO `gen_template_group` VALUES (1, 4);
INSERT INTO `gen_template_group` VALUES (1, 5);
INSERT INTO `gen_template_group` VALUES (1, 6);
INSERT INTO `gen_template_group` VALUES (1, 7);
INSERT INTO `gen_template_group` VALUES (1, 8);
INSERT INTO `gen_template_group` VALUES (1, 9);
INSERT INTO `gen_template_group` VALUES (1, 10);
INSERT INTO `gen_template_group` VALUES (1, 11);
INSERT INTO `gen_template_group` VALUES (1, 12);
INSERT INTO `gen_template_group` VALUES (2, 4);
INSERT INTO `gen_template_group` VALUES (2, 5);
INSERT INTO `gen_template_group` VALUES (2, 6);
INSERT INTO `gen_template_group` VALUES (2, 7);
INSERT INTO `gen_template_group` VALUES (2, 8);
INSERT INTO `gen_template_group` VALUES (2, 9);
INSERT INTO `gen_template_group` VALUES (2, 10);
INSERT INTO `gen_template_group` VALUES (2, 15);
INSERT INTO `gen_template_group` VALUES (2, 16);
INSERT INTO `gen_template_group` VALUES (2, 17);
INSERT INTO `gen_template_group` VALUES (2, 18);
INSERT INTO `gen_template_group` VALUES (2, 19);
INSERT INTO `gen_template_group` (`group_id`, `template_id`) VALUES (1,1);
INSERT INTO `gen_template_group` (`group_id`, `template_id`) VALUES (1,2);
INSERT INTO `gen_template_group` (`group_id`, `template_id`) VALUES (1,3);
INSERT INTO `gen_template_group` (`group_id`, `template_id`) VALUES (1,4);
INSERT INTO `gen_template_group` (`group_id`, `template_id`) VALUES (1,5);
INSERT INTO `gen_template_group` (`group_id`, `template_id`) VALUES (1,6);
INSERT INTO `gen_template_group` (`group_id`, `template_id`) VALUES (1,7);
INSERT INTO `gen_template_group` (`group_id`, `template_id`) VALUES (1,8);
INSERT INTO `gen_template_group` (`group_id`, `template_id`) VALUES (1,9);
INSERT INTO `gen_template_group` (`group_id`, `template_id`) VALUES (1,10);
INSERT INTO `gen_template_group` (`group_id`, `template_id`) VALUES (2,11);
INSERT INTO `gen_template_group` (`group_id`, `template_id`) VALUES (2,12);
INSERT INTO `gen_template_group` (`group_id`, `template_id`) VALUES (2,13);
INSERT INTO `gen_template_group` (`group_id`, `template_id`) VALUES (2,14);
INSERT INTO `gen_template_group` (`group_id`, `template_id`) VALUES (2,15);
INSERT INTO `gen_template_group` (`group_id`, `template_id`) VALUES (2,16);
INSERT INTO `gen_template_group` (`group_id`, `template_id`) VALUES (2,17);
INSERT INTO `gen_template_group` (`group_id`, `template_id`) VALUES (2,18);
INSERT INTO `gen_template_group` (`group_id`, `template_id`) VALUES (2,19);
INSERT INTO `gen_template_group` (`group_id`, `template_id`) VALUES (2,20);
INSERT INTO `gen_template_group` (`group_id`, `template_id`) VALUES (2,21);
INSERT INTO `gen_template_group` (`group_id`, `template_id`) VALUES (2,22);
INSERT INTO `gen_template_group` (`group_id`, `template_id`) VALUES (3,23);
INSERT INTO `gen_template_group` (`group_id`, `template_id`) VALUES (3,24);
INSERT INTO `gen_template_group` (`group_id`, `template_id`) VALUES (3,25);
INSERT INTO `gen_template_group` (`group_id`, `template_id`) VALUES (3,26);
INSERT INTO `gen_template_group` (`group_id`, `template_id`) VALUES (3,27);
INSERT INTO `gen_template_group` (`group_id`, `template_id`) VALUES (3,28);
INSERT INTO `gen_template_group` (`group_id`, `template_id`) VALUES (3,29);
INSERT INTO `gen_template_group` (`group_id`, `template_id`) VALUES (3,30);
INSERT INTO `gen_template_group` (`group_id`, `template_id`) VALUES (3,31);
INSERT INTO `gen_template_group` (`group_id`, `template_id`) VALUES (3,32);
INSERT INTO `gen_template_group` (`group_id`, `template_id`) VALUES (4,33);
INSERT INTO `gen_template_group` (`group_id`, `template_id`) VALUES (4,34);
INSERT INTO `gen_template_group` (`group_id`, `template_id`) VALUES (4,35);
INSERT INTO `gen_template_group` (`group_id`, `template_id`) VALUES (4,36);
INSERT INTO `gen_template_group` (`group_id`, `template_id`) VALUES (4,37);
INSERT INTO `gen_template_group` (`group_id`, `template_id`) VALUES (4,38);
INSERT INTO `gen_template_group` (`group_id`, `template_id`) VALUES (4,39);
INSERT INTO `gen_template_group` (`group_id`, `template_id`) VALUES (4,40);
INSERT INTO `gen_template_group` (`group_id`, `template_id`) VALUES (4,41);
INSERT INTO `gen_template_group` (`group_id`, `template_id`) VALUES (4,42);
INSERT INTO `gen_template_group` (`group_id`, `template_id`) VALUES (4,43);
INSERT INTO `gen_template_group` (`group_id`, `template_id`) VALUES (4,44);
INSERT INTO `gen_template_group` (`group_id`, `template_id`) VALUES (4,45);
COMMIT;
-- ----------------------------
@@ -299,14 +350,14 @@ COMMIT;
DROP TABLE IF EXISTS `gen_create_table`;
CREATE TABLE `gen_create_table` (
`id` bigint NOT NULL COMMENT '主键ID',
`table_name` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '表名称',
`table_name` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL COMMENT '表名称',
`ds_name` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL COMMENT '数据源',
`comments` varchar(512) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '表注释',
`comments` varchar(512) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL COMMENT '表注释',
`create_by` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL COMMENT '创建人',
`update_by` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL,
`create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_time` datetime DEFAULT NULL,
`column_info` text CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '字段信息',
`column_info` text CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL COMMENT '字段信息',
`del_flag` char(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL COMMENT '删除标记',
`tenant_id` bigint DEFAULT NULL COMMENT '租户ID',
PRIMARY KEY (`id`) USING BTREE
+54 -111
View File
@@ -19,10 +19,10 @@ CREATE TABLE `app_article` (
`sort` int unsigned NOT NULL DEFAULT '50' COMMENT '排序',
`create_time` datetime DEFAULT NULL COMMENT '创建时间',
`update_time` datetime DEFAULT NULL COMMENT '更新时间',
`create_by` varchar(32) COLLATE utf8mb4_general_ci NOT NULL COMMENT '创建人',
`create_by` varchar(32) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '创建人',
`update_by` varchar(32) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '更新人',
`del_flag` char(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '删除时间',
`tenant_id` bigint(20) DEFAULT NULL,
`tenant_id` bigint(20) DEFAULT NULL,
PRIMARY KEY (`id`) USING BTREE,
KEY `cid_idx` (`cid`) USING BTREE COMMENT '分类索引'
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC COMMENT='文章资讯表';
@@ -47,7 +47,7 @@ CREATE TABLE `app_article_category` (
`update_time` datetime DEFAULT NULL COMMENT '更新时间',
`create_by` varchar(32) COLLATE utf8mb4_general_ci DEFAULT '0' COMMENT '创建人',
`update_by` varchar(32) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '更新人',
`tenant_id` bigint(20) DEFAULT NULL,
`tenant_id` bigint(20) DEFAULT NULL,
PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC COMMENT='文章分类表';
@@ -65,12 +65,12 @@ CREATE TABLE `app_article_collect` (
`id` bigint unsigned NOT NULL COMMENT '主键',
`user_id` bigint unsigned NOT NULL DEFAULT '0' COMMENT '用户ID',
`article_id` bigint unsigned NOT NULL DEFAULT '0' COMMENT '文章ID',
`create_time` datetime NOT NULL COMMENT '创建时间',
`update_time` datetime NOT NULL COMMENT '更新时间',
`create_time` datetime COMMENT '创建时间',
`update_time` datetime COMMENT '更新时间',
`del_flag` char(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '0' COMMENT '是否删除',
`create_by` varchar(32) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '创建人',
`update_by` varchar(32) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '更新人',
`tenant_id` bigint(20) DEFAULT NULL,
`tenant_id` bigint(20) DEFAULT NULL,
PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC COMMENT='文章收藏表';
@@ -80,6 +80,30 @@ CREATE TABLE `app_article_collect` (
BEGIN;
COMMIT;
-- ----------------------------
-- Table structure for app_contacts
-- ----------------------------
DROP TABLE IF EXISTS `app_contacts`;
CREATE TABLE `app_contacts` (
`id` bigint NOT NULL COMMENT '主键',
`contact_name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '联系人',
`contact_phone` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '手机号',
`remark` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '备注',
`create_by` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '创建人',
`create_time` datetime DEFAULT NULL COMMENT '创建时间',
`update_by` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '修改人',
`update_time` datetime DEFAULT NULL COMMENT '修改时间',
`del_flag` char(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT '0' COMMENT '删除标记',
`tenant_id` bigint DEFAULT NULL COMMENT '租户ID',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='通讯录表';
-- ----------------------------
-- Records of app_contacts
-- ----------------------------
BEGIN;
COMMIT;
-- ----------------------------
-- Table structure for app_page
-- ----------------------------
@@ -94,7 +118,7 @@ CREATE TABLE `app_page` (
`create_time` datetime DEFAULT NULL COMMENT '创建时间',
`update_time` datetime DEFAULT NULL COMMENT '修改时间',
`del_flag` char(1) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '删除标记',
`tenant_id` bigint(20) DEFAULT NULL,
`tenant_id` bigint(20) DEFAULT NULL,
PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC COMMENT='页面装修表';
@@ -102,9 +126,10 @@ CREATE TABLE `app_page` (
-- Records of app_page
-- ----------------------------
BEGIN;
INSERT INTO `app_page` VALUES (1, 1, '商城首页', '[{\"title\":\"搜索\",\"name\":\"search\",\"disabled\":1,\"content\":{},\"styles\":{}},{\"title\":\"首页轮播图\",\"name\":\"banner\",\"content\":{\"enabled\":1,\"data\":[{\"image\":\"/api/static/banner01.png\",\"name\":\"\",\"link\":{\"path\":\"/pages/index/index\",\"name\":\"商城首页\",\"type\":\"shop\"}}]},\"styles\":{}},{\"title\":\"导航菜单\",\"name\":\"nav\",\"content\":{\"enabled\":1,\"data\":[{\"image\":\"https://minio.pigx.top/oss/app/nav01.png\",\"name\":\"资讯中心\",\"link\":{\"path\":\"/pages/news/news\",\"name\":\"文章资讯\",\"type\":\"shop\"}},{\"image\":\"https://minio.pigx.top/oss/app/nav02.png\",\"name\":\"我的收藏\",\"link\":{\"path\":\"/pages/collection/collection\",\"name\":\"我的收藏\",\"type\":\"shop\"}},{\"image\":\"https://minio.pigx.top/oss/app/nav03.png\",\"name\":\"个人设置\",\"link\":{\"path\":\"/pages/user_set/user_set\",\"name\":\"个人设置\",\"type\":\"shop\"}},{\"image\":\"https://minio.pigx.top/oss/app/nav04.png\",\"name\":\"联系客服\",\"link\":{\"path\":\"/pages/customer_service/customer_service\",\"name\":\"联系客服\",\"type\":\"shop\"}},{\"image\":\"https://minio.pigx.top/oss/app/nav05.png\",\"name\":\"关于我们\",\"link\":{\"path\":\"/pages/as_us/as_us\",\"name\":\"关于我们\",\"type\":\"shop\"}}]},\"styles\":{}},{\"id\":\"l84almsk2uhyf\",\"title\":\"资讯\",\"name\":\"news\",\"disabled\":1,\"content\":{},\"styles\":{}}]', NULL, 'admin', NULL, '2023-06-15 09:18:02', '0',1);
INSERT INTO `app_page` VALUES (2, 2, '个人中心', '[{\"title\":\"用户信息\",\"name\":\"user-info\",\"disabled\":1,\"content\":{},\"styles\":{}},{\"title\":\"我的服务\",\"name\":\"my-service\",\"content\":{\"style\":2,\"title\":\"服务中心\",\"data\":[{\"image\":\"https://minio.pigx.top/oss/app/user_collect.png\",\"name\":\"我的收藏\",\"link\":{\"path\":\"/pages/collection/collection\",\"name\":\"我的收藏\",\"type\":\"shop\"}},{\"image\":\"https://minio.pigx.top/oss/app/user_setting.png\",\"name\":\"个人设置\",\"link\":{\"path\":\"/pages/user_set/user_set\",\"name\":\"个人设置\",\"type\":\"shop\"}},{\"image\":\"https://minio.pigx.top/oss/app/user_kefu.png\",\"name\":\"联系客服\",\"link\":{\"path\":\"/pages/customer_service/customer_service\",\"name\":\"联系客服\",\"type\":\"shop\"}}]},\"styles\":{}},{\"title\":\"个人中心广告图\",\"name\":\"user-banner\",\"content\":{\"enabled\":1,\"data\":[{\"image\":\"\",\"name\":\"sdds\",\"link\":{\"path\":\"/pages/user/user\",\"name\":\"个人中心\",\"type\":\"shop\"}}]},\"styles\":{}}]', NULL, 'admin', NULL, '2023-06-18 17:00:05', '0',1);
INSERT INTO `app_page` VALUES (3, 3, '客服设置', '[{\"title\":\"客服设置\",\"name\":\"customer-service\",\"content\":{\"title\":\"添加客服二维码\",\"time\":\"早上 9:00 - 22:00\",\"mobile\":\"13800138000\",\"qrcode\":\"/admin/sys-file/local/adc5061f99e9440abcd9b22572909c88.jpg\"},\"styles\":{}}]', NULL, 'admin', NULL, '2023-06-14 13:12:19', '0',1);
INSERT INTO `app_page` VALUES (1, 1, '首页装修', '[{\"name\":\"search\",\"title\":\"搜索\",\"styles\":{},\"content\":{},\"disabled\":1},{\"name\":\"banner\",\"title\":\"首页轮播图\",\"styles\":{},\"content\":{\"data\":[{\"link\":{\"name\":\"个人中心\",\"path\":\"/pages/user/index\",\"type\":\"shop\"},\"name\":\"商品大抽拼\",\"image\":\"https://minio.pigx.vip/oss/202605/home.jpg\"}],\"enabled\":1}},{\"name\":\"nav\",\"title\":\"导航菜单\",\"styles\":{},\"content\":{\"data\":[{\"icon\":\"star\",\"link\":{\"name\":\"我的收藏\",\"path\":\"/pages/user/collection/index\",\"type\":\"shop\"},\"name\":\"我的收藏\",\"image\":\"https://minio.pigx.top/oss/app/nav02.png\"},{\"icon\":\"calendar-line\",\"name\":\"日历\",\"link\":{\"path\":\"/pages/workbench/calendar/index\",\"name\":\"日程\",\"type\":\"shop\"}},{\"icon\":\"message\",\"name\":\"消息中心\",\"link\":{\"path\":\"/pages/user/messages/index\",\"name\":\"消息中心\",\"type\":\"shop\"}},{\"icon\":\"user-group\",\"name\":\"通讯录\",\"link\":{\"path\":\"/pages/workbench/contacts/index\",\"name\":\"通讯录\",\"type\":\"shop\"}}],\"enabled\":1}}]', NULL, 'admin', NULL, '2026-05-13 23:37:53', '0', 1);
INSERT INTO `app_page` VALUES (2, 2, '个人中心', '[{\"name\":\"user-info\",\"title\":\"用户信息\",\"styles\":{},\"content\":{},\"disabled\":1},{\"name\":\"my-service\",\"title\":\"我的服务\",\"styles\":{},\"content\":{\"data\":[{\"icon\":\"settings\",\"link\":{\"name\":\"个人设置\",\"path\":\"/pages/user/settings/index\",\"type\":\"shop\"},\"name\":\"个人设置\",\"image\":\"https://minio.pigx.top/oss/app/user_setting.png\"},{\"icon\":\"star\",\"link\":{\"name\":\"我的收藏\",\"path\":\"/pages/user/collection/index\",\"type\":\"shop\"},\"name\":\"我的收藏\",\"image\":\"https://minio.pigx.top/oss/app/user_collect.png\"},{\"icon\":\"headset\",\"link\":{\"name\":\"联系客服\",\"path\":\"/pages/user/customer-service/index\",\"type\":\"shop\"},\"name\":\"联系客服\",\"image\":\"https://minio.pigx.top/oss/app/user_kefu.png\"},{\"icon\":\"info-circle\",\"name\":\"关于我们\",\"link\":{\"path\":\"/pages/user/about/index\",\"name\":\"关于我们\",\"type\":\"shop\"}}],\"style\":2,\"title\":\"服务中心\"}},{\"name\":\"user-banner\",\"title\":\"个人中心广告图\",\"styles\":{},\"content\":{\"data\":[{\"link\":{\"name\":\"个人中心\",\"path\":\"/pages/user/index\",\"type\":\"shop\"},\"name\":\"sdds\",\"image\":\"https://minio.pigx.vip/oss/202605/ad.jpg\"}],\"enabled\":1}}]', NULL, 'admin', NULL, '2026-05-13 23:37:53', '0', 1);
INSERT INTO `app_page` VALUES (3, 3, '客服设置', '[{\"title\":\"客服设置\",\"name\":\"customer-service\",\"content\":{\"title\":\"添加客服二维码\",\"time\":\"早上 9:00 - 22:00\",\"mobile\":\"13800138000\",\"qrcode\":\"/admin/sys-file/oss/file?fileName=86f81144ab2a4984bbf63fe851d49faf.png\"},\"styles\":{}}]', NULL, 'admin', NULL, '2026-05-13 23:37:53', '0', 1);
INSERT INTO `app_page` VALUES (4, 4, '工作台', '[{\"id\":\"mp47dnlr51ltq\",\"title\":\"常用功能\",\"name\":\"workbench-shortcuts\",\"content\":{\"enabled\":1,\"data\":[{\"icon\":\"send\",\"name\":\"我的\",\"link\":{\"path\":\"/pages/workbench/flow/tasks/index?type=started\",\"name\":\"我的\",\"type\":\"flow-tasks\"},\"color\":\"#2563eb\"},{\"icon\":\"clock-circle\",\"name\":\"待办\",\"link\":{\"path\":\"/pages/workbench/flow/tasks/index?type=pending\",\"name\":\"待办\",\"type\":\"flow-tasks\"},\"color\":\"#d97706\"},{\"icon\":\"email\",\"name\":\"抄送\",\"link\":{\"path\":\"/pages/workbench/flow/tasks/index?type=cc\",\"name\":\"抄送\",\"type\":\"flow-tasks\"},\"color\":\"#4f46e5\"},{\"icon\":\"check-circle\",\"name\":\"已办\",\"link\":{\"path\":\"/pages/workbench/flow/tasks/index?type=completed\",\"name\":\"已办\",\"type\":\"flow-tasks\"},\"color\":\"#15803d\"}]},\"styles\":{}}]', NULL, 'admin', NULL, '2026-05-13 23:44:57', '0', 1);
COMMIT;
-- ----------------------------
@@ -114,9 +139,11 @@ DROP TABLE IF EXISTS `app_tabbar`;
CREATE TABLE `app_tabbar` (
`id` bigint unsigned NOT NULL COMMENT '主键',
`name` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '导航名称',
`selected` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '未选图标',
`unselected` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '已选图标',
`selected` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '选中图标',
`unselected` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '未选中图标',
`link` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '链接地址',
`sort_order` int(11) NOT NULL DEFAULT '0' COMMENT '排序',
`login_flag` char(1) COLLATE utf8mb4_general_ci NOT NULL DEFAULT '1' COMMENT '是否需要登录(0-不需要,1-需要)',
`create_time` datetime DEFAULT NULL COMMENT '创建时间',
`update_time` datetime DEFAULT NULL COMMENT '更新时间',
`create_by` varchar(32) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '创建人',
@@ -130,113 +157,29 @@ CREATE TABLE `app_tabbar` (
-- Records of app_tabbar
-- ----------------------------
BEGIN;
INSERT INTO `app_tabbar` VALUES (1, '首页', 'https://minio.pigx.top/oss/app/tabbar0.png', 'https://minio.pigx.top/oss/app/tabbar0_0.png', '{\"path\":\"/pages/index/index\",\"name\":\"商城首页\",\"type\":\"shop\"}', NULL, '2023-06-15 09:16:25', NULL, 'admin', '0',1);
INSERT INTO `app_tabbar` VALUES (2, '资讯', 'https://minio.pigx.top/oss/app/tabbar1.png', 'https://minio.pigx.top/oss/app/tabbar1_1.png', '{\"path\":\"/pages/news/news\",\"name\":\"文章资讯\",\"type\":\"shop\"}', NULL, '2023-06-15 09:16:25', NULL, 'admin', '0',1);
INSERT INTO `app_tabbar` VALUES (3, '我的', 'https://minio.pigx.top/oss/app/tabbar3.png', 'https://minio.pigx.top/oss/app/tabbar3_3.png', '{\"path\":\"/pages/user/user\",\"name\":\"个人中心\",\"type\":\"shop\"}', NULL, '2023-06-15 09:16:25', NULL, 'admin', '0',1);
INSERT INTO `app_tabbar` VALUES (1, '首页', 'home-fill', 'home', '{\"path\":\"/pages/index/index\",\"name\":\"首页\",\"type\":\"shop\"}', 0, '0', NULL, '2026-05-13 23:37:53', NULL, 'admin', '0', 1);
INSERT INTO `app_tabbar` VALUES (2, '工作台', 'apps', 'apps', '{\"path\":\"/pages/workbench/index\",\"name\":\"工作台\",\"type\":\"shop\"}', 1, '1', NULL, '2026-05-13 23:42:00', NULL, 'admin', '0', 1);
INSERT INTO `app_tabbar` VALUES (3, '我的', 'user', 'user', '{\"path\":\"/pages/user/index\",\"name\":\"个人中心\",\"type\":\"shop\"}', 2, '0', NULL, '2026-05-13 23:37:53', NULL, 'admin', '0', 1);
COMMIT;
-- ----------------------------
-- Table structure for app_role
-- Table structure for app_role_tabbar
-- ----------------------------
DROP TABLE IF EXISTS `app_role`;
CREATE TABLE `app_role` (
`role_id` bigint(20) NOT NULL,
`role_name` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
`role_code` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
`role_desc` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
`create_by` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT ' ' COMMENT '创建人',
`update_by` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT ' ' COMMENT '修改人',
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
`update_time` datetime DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,
`del_flag` char(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT '0',
`tenant_id` bigint(20) DEFAULT NULL,
PRIMARY KEY (`role_id`) USING BTREE,
KEY `role_idx1_role_code` (`role_code`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC COMMENT='app角色表';
DROP TABLE IF EXISTS `app_role_tabbar`;
CREATE TABLE `app_role_tabbar` (
`role_id` bigint(20) NOT NULL COMMENT '系统角色ID',
`tabbar_id` bigint(20) NOT NULL COMMENT '底部导航ID',
`tenant_id` bigint(20) NOT NULL DEFAULT '0' COMMENT '所属租户',
PRIMARY KEY (`role_id`,`tabbar_id`,`tenant_id`) USING BTREE,
KEY `app_role_tabbar_role_index` (`role_id`,`tenant_id`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC COMMENT='App角色底部导航表';
-- ----------------------------
-- Records of app_role
-- Records of app_role_tabbar
-- ----------------------------
BEGIN;
INSERT INTO `app_role` VALUES (1, 'app用户', 'APP_USER', 'app用户角色', '', '', '2022-12-07 06:34:18', '2023-03-09 06:34:42', '0', 1);
COMMIT;
-- ----------------------------
-- Table structure for app_social_details
-- ----------------------------
DROP TABLE IF EXISTS `app_social_details`;
CREATE TABLE `app_social_details` (
`id` bigint(20) NOT NULL COMMENT '主键', -- 主键
`type` varchar(16) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '社交类型', -- 社交类型
`remark` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '备注', -- 备注
`app_id` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '应用ID', -- 应用ID
`app_secret` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '应用密钥', -- 应用密钥
`redirect_url` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '重定向URL', -- 重定向URL
`ext` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '拓展字段', -- 拓展字段
`create_by` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT ' ' COMMENT '创建人', -- 创建人
`update_by` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT ' ' COMMENT '修改人', -- 修改人
`create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', -- 创建时间
`update_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', -- 更新时间
`del_flag` char(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT '0' COMMENT '删除标志', -- 删除标志
PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC
COMMENT='系统社交登录账号表'; -- 系统社交登录账号表
-- ----------------------------
-- Records of app_social_details
-- ----------------------------
BEGIN;
INSERT INTO `app_social_details` VALUES (1, 'MINI', '小程序登录', 'app_id', 'app_secret', 'http://www.baidu.com123', NULL, '', 'admin', '2022-12-09 01:44:42', '2023-04-03 06:12:30', '0');
COMMIT;
-- ----------------------------
-- Table structure for app_user
-- ----------------------------
DROP TABLE IF EXISTS `app_user`;
CREATE TABLE `app_user` (
`user_id` bigint(20) NOT NULL COMMENT '用户id',
`username` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '用户名',
`password` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '密码',
`salt` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '盐值',
`phone` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '手机号码',
`avatar` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '头像图片链接',
`nickname` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '拓展字段:昵称',
`name` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '拓展字段:姓名',
`email` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '拓展字段:邮箱',
`create_by` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '创建人',
`update_by` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT ' ' COMMENT '修改人',
`create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_time` datetime DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间',
`del_flag` char(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT '0' COMMENT '删除标志',
`tenant_id` bigint(20) NOT NULL DEFAULT '0' COMMENT '所属租户id',
`last_modified_time` datetime DEFAULT NULL COMMENT '最后一次密码修改时间',
`lock_flag` char(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT '0' COMMENT '锁定状态',
`wx_openid` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '微信登录openId',
PRIMARY KEY (`user_id`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC COMMENT='app用户表';
-- ----------------------------
-- Records of app_user
-- ----------------------------
BEGIN;
INSERT INTO `app_user` VALUES (1, 'appuser', '$2a$10$XQu3TmORLqDWayFspQN.U.LigJ5TWPTdXPIn/6SxGHKED3PVpuMH6', NULL, '13054729089', NULL, 'aeizzz', '刘洪磊', 'aeizzz@foxmail.com', '', 'appuser', '2022-12-07 02:59:38', '2023-03-09 15:14:44', '0', 1, NULL, '0', 'oBxPy5EnbDiN-gGEaovCpp_IkrkQ');
COMMIT;
-- ----------------------------
-- Table structure for app_user_role
-- ----------------------------
DROP TABLE IF EXISTS `app_user_role`;
CREATE TABLE `app_user_role` (
`user_id` bigint(20) NOT NULL COMMENT '用户ID',
`role_id` bigint(20) NOT NULL COMMENT '角色ID',
PRIMARY KEY (`user_id`,`role_id`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC COMMENT='用户角色表';
-- ----------------------------
-- Records of app_user_role
-- ----------------------------
BEGIN;
INSERT INTO `app_user_role` VALUES (1, 1);
INSERT INTO `app_role_tabbar` VALUES (1, 2, 1);
INSERT INTO `app_role_tabbar` VALUES (1, 3, 1);
COMMIT;
SET FOREIGN_KEY_CHECKS = 1;
+3624 -978
View File
File diff suppressed because it is too large. Load diff
+4 -1
View File
@@ -1,4 +1,4 @@
FROM mysql/mysql-server:8.0.32
FROM registry.cn-hangzhou.aliyuncs.com/dockerhub_mirror/mysql-server:8.0.32
MAINTAINER lengleng(wangiegie@gmail.com)
@@ -26,3 +26,6 @@ COPY ./8pigxx_codegen.sql /docker-entrypoint-initdb.d
COPY ./99pigxx_bi.sql /docker-entrypoint-initdb.d
COPY ./999pigxx_app.sql /docker-entrypoint-initdb.d
# 微服务版本可以注释掉下面这行
COPY ./0pigxx_boot.sql /docker-entrypoint-initdb.d
+41
View File
@@ -0,0 +1,41 @@
# 使用说明 V6.0 - 单体架构版本
# 1. 先构建单体 JAR: mvn clean install -Pboot -DskipTests
# 2. 启动服务: docker compose -f docker-compose-boot.yml up -d
# 3. 静静等待服务启动
services:
pigx-mysql:
build:
context: ./db
environment:
MYSQL_ROOT_HOST: "%"
MYSQL_ROOT_PASSWORD: root
restart: always
container_name: pigx-mysql
image: pigx-mysql
command: --lower_case_table_names=1
networks:
- spring_cloud_default
pigx-redis:
container_name: pigx-redis
image: registry.cn-hangzhou.aliyuncs.com/dockerhub_mirror/redis
restart: always
networks:
- spring_cloud_default
# 单体的时候注意,服务名称命名为 pigx-gateway 对应前端nginx 配置
pigx-gateway:
build:
context: ./pigx-boot
restart: always
container_name: pigx-boot
image: pigx-boot
ports:
- 9999:9999
networks:
- spring_cloud_default
networks:
spring_cloud_default:
name: spring_cloud_default
driver: bridge
+20 -18
View File
@@ -1,9 +1,7 @@
# 使用说明 V5.2
# 使用说明 V6.0 - 微服务架构版本
# 1. 使用docker-compose 宿主机不需要配置host来发现
# 2. 无需修改源码,根目录 docker-compose up 即可
# 3. 静静等待服务启动
version: '3'
services:
pigx-mysql:
build:
@@ -20,7 +18,7 @@ services:
pigx-redis:
container_name: pigx-redis
image: redis:6.2.6
image: registry.cn-hangzhou.aliyuncs.com/dockerhub_mirror/redis
restart: always
networks:
- spring_cloud_default
@@ -33,6 +31,8 @@ services:
image: pigx-register
ports:
- 8848:8848
- 9848:9848
- 18080:18080
networks:
- spring_cloud_default
@@ -65,21 +65,12 @@ services:
networks:
- spring_cloud_default
pigx-flow-task:
pigx-flow-biz:
build:
context: ./pigx-flow/pigx-flow-task/pigx-flow-task-biz
context: ./pigx-flow/pigx-flow-biz
restart: always
container_name: pigx-flow-task
image: pigx-flow-task
networks:
- spring_cloud_default
pigx-flow-engine:
build:
context: ./pigx-flow/pigx-flow-engine/pigx-flow-engine-biz
restart: always
container_name: pigx-flow-engine
image: pigx-flow-engine
container_name: pigx-flow-biz
image: pigx-flow-biz
networks:
- spring_cloud_default
@@ -121,6 +112,17 @@ services:
networks:
- spring_cloud_default
pigx-xxl-job-admin:
build:
context: ./pigx-visual/pigx-xxl-job-admin
restart: always
image: pigx-xxl-job-admin
container_name: pigx-xxl-job-admin
ports:
- 9080:9080
networks:
- spring_cloud_default
pigx-codegen:
build:
context: ./pigx-visual/pigx-codegen
@@ -172,5 +174,5 @@ services:
networks:
spring_cloud_default:
name: spring_cloud_default
name: spring_cloud_default
driver: bridge
+5
View File
@@ -0,0 +1,5 @@
# 此文件不得删除,构造器注入的时候自动复制字段上边的注解
lombok.copyableAnnotations += org.springframework.beans.factory.annotation.Value
lombok.copyableAnnotations += org.springframework.beans.factory.annotation.Qualifier
lombok.copyableAnnotations += org.springframework.context.annotation.Lazy
+36 -31
View File
@@ -1,37 +1,42 @@
<?xml version="1.0"?>
<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
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>
<parent>
<groupId>com.pig4cloud</groupId>
<artifactId>pigx-app-server</artifactId>
<version>5.5.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.pig4cloud</groupId>
<artifactId>pigx-app-server</artifactId>
<version>6.2.0</version>
</parent>
<artifactId>pigx-app-server-api</artifactId>
<artifactId>pigx-app-server-api</artifactId>
<dependencies>
<!--core 工具类-->
<dependency>
<groupId>com.pig4cloud</groupId>
<artifactId>pigx-common-core</artifactId>
</dependency>
<!--mybatis plus extension,包含了mybatis plus core-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-extension</artifactId>
</dependency>
<!--feign 工具类-->
<dependency>
<groupId>com.pig4cloud</groupId>
<artifactId>pigx-common-feign</artifactId>
</dependency>
<!-- excel 导入导出 -->
<dependency>
<groupId>com.pig4cloud</groupId>
<artifactId>pigx-common-excel</artifactId>
</dependency>
</dependencies>
<dependencies>
<!--core 工具类-->
<dependency>
<groupId>com.pig4cloud</groupId>
<artifactId>pigx-common-core</artifactId>
</dependency>
<!--mybatis plus extension,包含了mybatis plus core-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-spring</artifactId>
</dependency>
<!--feign 工具类-->
<dependency>
<groupId>com.pig4cloud</groupId>
<artifactId>pigx-common-feign</artifactId>
</dependency>
<!-- excel 导入导出 -->
<dependency>
<groupId>com.pig4cloud</groupId>
<artifactId>pigx-common-excel</artifactId>
</dependency>
<!-- 脱敏工具类-->
<dependency>
<groupId>com.pig4cloud</groupId>
<artifactId>pigx-common-sensitive</artifactId>
</dependency>
</dependencies>
</project>
@@ -0,0 +1,38 @@
package com.pig4cloud.pigx.app.api.dto;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
/**
* App 角色底部导航配置请求体。
* <p>
* 后台保存某个系统角色可见的 App Tabbar 列表。公开 Tabbar 由 {@code app_tabbar.login_flag=0}
* 控制,不依赖这里的角色授权。
*
* @author lengleng
* @date 2026-05-09
*/
@Data
@Schema(description = "App角色底部导航配置")
public class AppRoleTabbarDTO implements Serializable {
private static final long serialVersionUID = 1L;
@NotNull(message = "角色ID不能为空")
@Schema(description = "系统角色ID")
private Long roleId;
/**
* 该角色可见的登录态 Tabbar ID 列表。
* <p>
* 保存时采用覆盖语义,空列表表示清空该角色的 Tabbar 授权。
*/
@Schema(description = "底部导航ID列表")
private List<Long> tabbarIds = new ArrayList<>();
}
@@ -1,30 +0,0 @@
package com.pig4cloud.pigx.app.api.dto;
import com.pig4cloud.pigx.app.api.entity.AppUser;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.util.List;
@Data
@Schema(description = "APP用户传输对象")
@EqualsAndHashCode(callSuper = true)
public class AppUserDTO extends AppUser {
/**
* 角色ID
*/
@Schema(description = "角色id集合")
private List<Long> role;
/**
* 新密码
*/
@Schema(description = "新密码")
private String newpassword1;
@Schema(description = "验证码")
private String mobileCode;
}
@@ -1,7 +1,7 @@
package com.pig4cloud.pigx.app.api.entity;
import com.baomidou.mybatisplus.annotation.*;
import com.baomidou.mybatisplus.extension.activerecord.Model;
import com.baomidou.mybatisplus.spring.activerecord.Model;
import com.pig4cloud.pigx.common.core.util.TenantTable;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@@ -1,7 +1,7 @@
package com.pig4cloud.pigx.app.api.entity;
import com.baomidou.mybatisplus.annotation.*;
import com.baomidou.mybatisplus.extension.activerecord.Model;
import com.baomidou.mybatisplus.spring.activerecord.Model;
import com.pig4cloud.pigx.common.core.util.TenantTable;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@@ -22,65 +22,77 @@ import java.time.LocalDateTime;
@Schema(description = "文章收藏表")
public class AppArticleCollectEntity extends Model<AppArticleCollectEntity> {
/**
* 主键
*/
@TableId(type = IdType.ASSIGN_ID)
@Schema(description = "主键")
private Long id;
/**
* 主键
*/
@TableId(type = IdType.ASSIGN_ID)
@Schema(description = "主键")
private Long id;
/**
* 用户ID
*/
@Schema(description = "用户ID")
private Long userId;
/**
* 用户ID
*/
@Schema(description = "用户ID")
private Long userId;
/**
* 文章ID
*/
@Schema(description = "文章ID")
private Long articleId;
/**
* 文章ID
*/
@Schema(description = "文章ID")
private Long articleId;
/**
* 文章标题
*/
@TableField(exist = false)
private String title;
/**
* 文章标题
*/
@TableField(exist = false)
private String title;
/**
* 创建人
*/
@TableField(fill = FieldFill.INSERT)
@Schema(description = "创建人")
private String createBy;
/**
* 创建人
*/
@TableField(fill = FieldFill.INSERT)
@Schema(description = "创建人")
private String createBy;
/**
* 创建时间
*/
@TableField(fill = FieldFill.INSERT)
@Schema(description = "创建时间")
private LocalDateTime createTime;
/**
* 创建时间
*/
@TableField(fill = FieldFill.INSERT)
@Schema(description = "创建时间")
private LocalDateTime createTime;
/**
* 更新人
*/
@TableField(fill = FieldFill.INSERT_UPDATE)
@Schema(description = "更新人")
private String updateBy;
/**
* 更新人
*/
@TableField(fill = FieldFill.INSERT_UPDATE)
@Schema(description = "更新人")
private String updateBy;
/**
* 更新时间
*/
@TableField(fill = FieldFill.INSERT_UPDATE)
@Schema(description = "更新时间")
private LocalDateTime updateTime;
/**
* 更新时间
*/
@TableField(fill = FieldFill.INSERT_UPDATE)
@Schema(description = "更新时间")
private LocalDateTime updateTime;
/**
* 是否删除
*/
@TableLogic
@TableField(fill = FieldFill.INSERT)
@Schema(description = "是否删除")
private String delFlag;
/**
* 是否删除
*/
@TableLogic
@TableField(fill = FieldFill.INSERT)
@Schema(description = "是否删除")
private String delFlag;
/**
* 图片
*/
@TableField(exist = false)
private String image;
/**
* 访问次数
*/
@TableField(exist = false)
private Long visit;
}
@@ -1,7 +1,7 @@
package com.pig4cloud.pigx.app.api.entity;
import com.baomidou.mybatisplus.annotation.*;
import com.baomidou.mybatisplus.extension.activerecord.Model;
import com.baomidou.mybatisplus.spring.activerecord.Model;
import com.pig4cloud.pigx.common.core.util.TenantTable;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@@ -0,0 +1,92 @@
package com.pig4cloud.pigx.app.api.entity;
import com.baomidou.mybatisplus.annotation.*;
import com.baomidou.mybatisplus.spring.activerecord.Model;
import com.pig4cloud.pigx.common.core.util.TenantTable;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.time.LocalDateTime;
/**
* 通讯录表
*
* @author pigx
* @date 2025-05-29 17:30:30
*/
@Data
@TenantTable
@TableName("app_contacts")
@EqualsAndHashCode(callSuper = true)
@Schema(description = "通讯录表")
public class AppContactsEntity extends Model<AppContactsEntity> {
/**
* 主键
*/
@TableId(type = IdType.ASSIGN_ID)
@Schema(description = "主键")
private Long id;
/**
* 联系人
*/
@Schema(description = "联系人")
private String contactName;
/**
* 手机号
*/
@Schema(description = "手机号")
private String contactPhone;
/**
* 备注
*/
@Schema(description = "备注")
private String remark;
/**
* 创建人
*/
@TableField(fill = FieldFill.INSERT)
@Schema(description = "创建人")
private String createBy;
/**
* 创建时间
*/
@TableField(fill = FieldFill.INSERT)
@Schema(description = "创建时间")
private LocalDateTime createTime;
/**
* 修改人
*/
@TableField(fill = FieldFill.INSERT_UPDATE)
@Schema(description = "修改人")
private String updateBy;
/**
* 修改时间
*/
@TableField(fill = FieldFill.INSERT_UPDATE)
@Schema(description = "修改时间")
private LocalDateTime updateTime;
/**
* 删除标记
*/
@TableLogic
@TableField(fill = FieldFill.INSERT)
@Schema(description = "删除标记")
private String delFlag;
/**
* 租户ID
*/
@Schema(description = "租户ID")
private Long tenantId;
}
@@ -1,15 +1,20 @@
package com.pig4cloud.pigx.app.api.entity;
import com.baomidou.mybatisplus.annotation.*;
import com.baomidou.mybatisplus.extension.activerecord.Model;
import com.baomidou.mybatisplus.spring.activerecord.Model;
import com.pig4cloud.pigx.common.core.util.TenantTable;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.FieldNameConstants;
import java.time.LocalDateTime;
/**
* 页面
* App 装修页面实体。
* <p>
* 仅对应 {@code app_page} 表,保存页面类型、页面名称和页面组件 JSON。
* 底部 Tabbar 已拆分到 {@code app_tabbar},不要再塞进 {@link #pageData}。
*
* @author lengleng
* @date 2023-06-08 11:19:23
@@ -17,6 +22,7 @@ import java.time.LocalDateTime;
@Data
@TenantTable
@TableName("app_page")
@FieldNameConstants
@EqualsAndHashCode(callSuper = true)
@Schema(description = "页面")
public class AppPageEntity extends Model<AppPageEntity> {
@@ -29,7 +35,7 @@ public class AppPageEntity extends Model<AppPageEntity> {
private Long id;
/**
* 页面类型
* 页面类型,对应 {@link com.pig4cloud.pigx.app.api.enums.PageTypeEnums}
*/
@Schema(description = "页面类型")
private Integer pageType;
@@ -41,7 +47,10 @@ public class AppPageEntity extends Model<AppPageEntity> {
private String pageName;
/**
* 页面数据
* 页面装修组件 JSON。
* <p>
* 只保存页面内部组件,例如搜索、轮播、导航块、服务块等;
* 运行时需要 Tabbar 时由服务层聚合 {@code app_tabbar} 返回。
*/
@Schema(description = "页面数据")
private String pageData;
@@ -1,107 +0,0 @@
/*
* Copyright (c) 2018-2025, lengleng All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* Neither the name of the pig4cloud.com developer nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
* Author: lengleng (wangiegie@gmail.com)
*/
package com.pig4cloud.pigx.app.api.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.extension.activerecord.Model;
import com.pig4cloud.pigx.common.core.util.TenantTable;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.time.LocalDateTime;
/**
* app角色表
*
* @author aeizzz
* @date 2022-12-07 09:52:03
*/
@Data
@TenantTable
@TableName("app_role")
@EqualsAndHashCode(callSuper = true)
@Schema(description = "app角色表")
public class AppRole extends Model<AppRole> {
private static final long serialVersionUID = 1L;
/**
* roleId
*/
@TableId(type = IdType.ASSIGN_ID)
@Schema(description = "roleId")
private Long roleId;
/**
* roleName
*/
@Schema(description = "roleName")
private String roleName;
/**
* roleCode
*/
@Schema(description = "roleCode")
private String roleCode;
/**
* roleDesc
*/
@Schema(description = "roleDesc")
private String roleDesc;
/**
* 创建人
*/
@Schema(description = "创建人")
private String createBy;
/**
* 修改人
*/
@Schema(description = "修改人")
private String updateBy;
/**
* createTime
*/
@Schema(description = "createTime")
private LocalDateTime createTime;
/**
* updateTime
*/
@Schema(description = "updateTime")
private LocalDateTime updateTime;
/**
* delFlag
*/
@Schema(description = "delFlag")
private String delFlag;
/**
* tenantId
*/
@Schema(description = "tenantId", hidden = true)
private Long tenantId;
}
@@ -0,0 +1,37 @@
package com.pig4cloud.pigx.app.api.entity;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.spring.activerecord.Model;
import com.pig4cloud.pigx.common.core.util.TenantTable;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
* App 角色底部导航关联实体,以 (role_id, tabbar_id, tenant_id) 为复合主键。
* <p>
* 这里的 roleId 是系统角色 {@code sys_role.role_id}。运行时不会跨库查询 {@code sys_user_role},
* 而是从登录 token 的角色权限中解析 roleId,再回到本表查询可见 Tabbar。
*
* @author lengleng
* @date 2026-05-09
*/
@Data
@TenantTable
@TableName("app_role_tabbar")
@EqualsAndHashCode(callSuper = true)
@Schema(description = "App角色底部导航")
public class AppRoleTabbar extends Model<AppRoleTabbar> {
private static final long serialVersionUID = 1L;
@Schema(description = "系统角色ID")
private Long roleId;
@Schema(description = "底部导航ID")
private Long tabbarId;
@Schema(description = "租户ID", hidden = true)
private Long tenantId;
}
@@ -1,125 +0,0 @@
/*
* Copyright (c) 2018-2025, lengleng All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* Neither the name of the pig4cloud.com developer nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
* Author: lengleng (wangiegie@gmail.com)
*/
package com.pig4cloud.pigx.app.api.entity;
import com.baomidou.mybatisplus.annotation.*;
import com.baomidou.mybatisplus.extension.activerecord.Model;
import com.pig4cloud.pigx.common.core.sensitive.Sensitive;
import com.pig4cloud.pigx.common.core.util.ValidGroup;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import jakarta.validation.constraints.NotBlank;
import java.time.LocalDateTime;
/**
* app 社交账号登录
*/
@Data
@Schema(description = "第三方账号信息")
@EqualsAndHashCode(callSuper = true)
public class AppSocialDetails extends Model<AppSocialDetails> {
private static final long serialVersionUID = 1L;
/**
* 主鍵
*/
@TableId(type = IdType.ASSIGN_ID)
@Schema(description = "主键")
private Long id;
/**
* 类型
*/
@NotBlank(message = "类型不能为空")
@Schema(description = "账号类型")
private String type;
/**
* 描述
*/
@Schema(description = "描述")
private String remark;
/**
* appid
*/
@Sensitive(prefixNoMaskLen = 4, suffixNoMaskLen = 4)
@NotBlank(message = "账号不能为空")
@Schema(description = "appId")
private String appId;
/**
* app_secret
*/
@Sensitive(prefixNoMaskLen = 4, suffixNoMaskLen = 4)
@NotBlank(message = "密钥不能为空", groups = { ValidGroup.Insert.class })
@Schema(description = "app secret")
private String appSecret;
/**
* 回调地址
*/
@Schema(description = "回调地址")
private String redirectUrl;
/**
* 拓展字段
*/
@Schema(description = "拓展字段")
private String ext;
/**
* 创建人
*/
@TableField(fill = FieldFill.INSERT)
@Schema(description = "创建人")
private String createBy;
/**
* 修改人
*/
@TableField(fill = FieldFill.UPDATE)
@Schema(description = "修改人")
private String updateBy;
/**
* 创建时间
*/
@Schema(description = "创建时间")
@TableField(fill = FieldFill.INSERT)
private LocalDateTime createTime;
/**
* 更新时间
*/
@Schema(description = "更新时间")
@TableField(fill = FieldFill.UPDATE)
private LocalDateTime updateTime;
/**
* 删除标记
*/
@TableLogic
@TableField(fill = FieldFill.INSERT)
@Schema(description = "删除标记,1:已删除,0:正常")
private String delFlag;
}
@@ -1,7 +1,7 @@
package com.pig4cloud.pigx.app.api.entity;
import com.baomidou.mybatisplus.annotation.*;
import com.baomidou.mybatisplus.extension.activerecord.Model;
import com.baomidou.mybatisplus.spring.activerecord.Model;
import com.fasterxml.jackson.annotation.JsonRawValue;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.pig4cloud.pigx.common.core.util.TenantTable;
@@ -12,7 +12,10 @@ import lombok.EqualsAndHashCode;
import java.time.LocalDateTime;
/**
* 导航栏
* App 底部导航实体。
* <p>
* 该表是移动端底部 Tabbar 的唯一数据源。图标字段保存 Wot UI 图标名,
* 运行时可见性由 {@link #loginFlag} 和 {@code app_role_tabbar} 共同决定。
*
* @author lengleng
* @date 2023-06-08 11:18:46
@@ -38,25 +41,43 @@ public class AppTabbarEntity extends Model<AppTabbarEntity> {
private String name;
/**
* 未选图标
* 选中态图标名。
* <p>
* 保存 Wot UI 内置图标名称,例如 {@code home-fill}。
*/
@Schema(description = "未选图标")
@Schema(description = "选中态图标名")
private String selected;
/**
* 已选图标
* 未选中态图标名。
* <p>
* 保存 Wot UI 内置图标名称,例如 {@code home}。
*/
@Schema(description = "已选图标")
@Schema(description = "未选中态图标名")
private String unselected;
/**
* 链接地址
* 跳转链接 JSON。
* <p>
* 前端按装修链接结构解析,例如 {@code {"path":"/pages/index/index","type":"shop"}}。
*/
@Schema(description = "链接地址")
@JsonRawValue
@JsonDeserialize()
private String link;
/**
* 排序顺序
*/
@Schema(description = "排序值")
private Integer sortOrder;
/**
* 是否需要登录,0=不需要登录也可见,1=登录后按角色授权可见。
*/
@Schema(description = "是否需要登录,0=不需要登录也可见,1=登录后按角色授权可见")
private String loginFlag;
/**
* 创建人
*/
@@ -1,161 +0,0 @@
/*
* Copyright (c) 2018-2025, lengleng All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* Neither the name of the pig4cloud.com developer nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
* Author: lengleng (wangiegie@gmail.com)
*/
package com.pig4cloud.pigx.app.api.entity;
import com.baomidou.mybatisplus.annotation.*;
import com.baomidou.mybatisplus.extension.activerecord.Model;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.pig4cloud.pigx.common.core.util.TenantTable;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.time.LocalDateTime;
/**
* app用户表
*
* @author aeizzz
* @date 2022-12-07 09:52:03
*/
@Data
@TenantTable
@TableName("app_user")
@EqualsAndHashCode(callSuper = true)
@Schema(description = "app用户表")
public class AppUser extends Model<AppUser> {
private static final long serialVersionUID = 1L;
/**
* userId
*/
@TableId(type = IdType.ASSIGN_ID)
@Schema(description = "userId")
private Long userId;
/**
* 用户名
*/
@Schema(description = "用户名")
private String username;
/**
* 密码
*/
@Schema(description = "密码")
private String password;
/**
* 随机盐
*/
@JsonIgnore
@Schema(description = "随机盐")
private String salt;
/**
* 手机号
*/
@Schema(description = "手机号")
private String phone;
/**
* 头像
*/
@Schema(description = "头像")
private String avatar;
/**
* 昵称
*/
@Schema(description = "拓展字段:昵称")
private String nickname;
/**
* 姓名
*/
@Schema(description = "拓展字段:姓名")
private String name;
/**
* 邮箱
*/
@Schema(description = "拓展字段:邮箱")
private String email;
/**
* 创建人
*/
@Schema(description = "创建人")
@TableField(fill = FieldFill.INSERT)
private String createBy;
/**
* 修改人
*/
@Schema(description = "修改人")
@TableField(fill = FieldFill.UPDATE)
private String updateBy;
/**
* 创建时间
*/
@Schema(description = "创建时间")
@TableField(fill = FieldFill.INSERT)
private LocalDateTime createTime;
/**
* 修改时间
*/
@Schema(description = "修改时间")
@TableField(fill = FieldFill.UPDATE)
private LocalDateTime updateTime;
/**
* 删除标记
*/
@Schema(description = "删除标记,1:已删除,0:正常")
@TableField(fill = FieldFill.INSERT)
@TableLogic
private String delFlag;
/**
* 所属租户
*/
@Schema(description = "所属租户", hidden = true)
private Long tenantId;
/**
* 最后一次密码修改时间
*/
@Schema(description = "最后一次密码修改时间")
private LocalDateTime lastModifiedTime;
/**
* 锁定标记
*/
@Schema(description = "锁定标记")
private String lockFlag;
/**
* 微信小程序登录openId
*/
@Schema(description = "微信小程序登录openId")
private String wxOpenid;
}
@@ -0,0 +1,28 @@
package com.pig4cloud.pigx.app.api.enums;
/**
* App Server 模块错误编码
*
* @author lengleng
* @date 2022/3/30
*/
public interface AppErrorCodes {
// === App 用户相关 ===
String APP_USER_USERINFO_EMPTY = "app.user.userInfo.empty";
String APP_USER_USERNAME_EXISTING = "app.user.username.existing";
String APP_USER_IMPORT_SUCCEED = "app.user.import.succeed";
String APP_USER_QUERY_ERROR = "app.user.query.error";
// === App 角色相关 ===
String APP_ROLE_ROLENAME_INEXISTENCE = "app.role.roleName.inexistence";
String APP_ROLE_NAMEORCODE_EXISTING = "app.role.nameOrCode.existing";
// === App 短信相关 ===
String APP_SMS_OFTEN = "app.sms.often";
}
@@ -0,0 +1,60 @@
package com.pig4cloud.pigx.app.api.enums;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
/**
* App 装修页面类型枚举。
* <p>
* 页面类型会写入 {@code app_page.page_type},后台保存装修页时根据该枚举回填页面名称。
*
* @author lengleng
* @date 2024/12/22
*/
@Getter
@RequiredArgsConstructor
public enum PageTypeEnums {
/**
* 首页
*/
HOME(1, "首页装修"),
/**
* 个人中心
*/
USER(2, "个人中心"),
/**
* 客服设置
*/
SERVICE(3, "客服设置"),
/**
* 工作台属性
*/
WORKBENCH(4, "工作台");
/**
* 页面类型编码,和 app_page.page_type 对应。
*/
private final Integer pageType;
/**
* 页面类型展示名称。
*/
private final String name;
/**
* 按类型获取名称
*
* @param pageType 页面类型
* @return {@link String }
*/
public static String getNameByType(Integer pageType) {
for (PageTypeEnums value : PageTypeEnums.values()) {
if (value.pageType.equals(pageType)) {
return value.name;
}
}
return null;
}
}
@@ -0,0 +1,102 @@
package com.pig4cloud.pigx.app.api.vo;
import com.pig4cloud.pigx.app.api.entity.AppPageEntity;
import com.pig4cloud.pigx.app.api.entity.AppTabbarEntity;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import org.springframework.beans.BeanUtils;
import java.time.LocalDateTime;
import java.util.List;
/**
* APP 装修页聚合数据。
* <p>
* 对外保持页面字段在顶层,额外追加 {@link #tabbar},避免把底部导航配置重新写回
* {@code app_page.page_data}。
*
* @author lengleng
*/
@Data
@Schema(description = "APP 装修页聚合数据")
public class AppDecorateVO {
/**
* 主键
*/
@Schema(description = "主键")
private Long id;
/**
* 页面类型
*/
@Schema(description = "页面类型")
private Integer pageType;
/**
* 页面名称
*/
@Schema(description = "页面名称")
private String pageName;
/**
* 页面装修组件 JSON,不包含底部 Tabbar。
*/
@Schema(description = "页面数据")
private String pageData;
/**
* 创建人
*/
@Schema(description = "创建人")
private String createBy;
/**
* 创建时间
*/
@Schema(description = "创建时间")
private LocalDateTime createTime;
/**
* 修改人
*/
@Schema(description = "修改人")
private String updateBy;
/**
* 修改时间
*/
@Schema(description = "修改时间")
private LocalDateTime updateTime;
/**
* 删除标记
*/
@Schema(description = "删除标记")
private String delFlag;
/**
* 当前查询场景下可用的底部导航栏。
* <p>
* 后台装修查询返回完整 Tabbar;App 运行时查询返回公开 Tabbar + 当前角色授权 Tabbar。
*/
@Schema(description = "底部导航栏")
private List<AppTabbarEntity> tabbar;
/**
* 根据页面实体和 Tabbar 列表构建装修聚合 VO。
*
* @param page 页面实体,可能为空
* @param tabbar Tabbar 列表
* @return 装修聚合数据
*/
public static AppDecorateVO of(AppPageEntity page, List<AppTabbarEntity> tabbar) {
AppDecorateVO vo = new AppDecorateVO();
if (page != null) {
BeanUtils.copyProperties(page, vo);
}
vo.setTabbar(tabbar);
return vo;
}
}
@@ -1,83 +0,0 @@
package com.pig4cloud.pigx.app.api.vo;
import com.alibaba.excel.annotation.ExcelIgnore;
import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.excel.annotation.write.style.ColumnWidth;
import com.pig4cloud.pigx.common.excel.annotation.ExcelLine;
import lombok.Data;
import jakarta.validation.constraints.NotBlank;
import java.time.LocalDateTime;
@Data
@ColumnWidth(30)
public class AppUserExcelVO {
/**
* 导入时候回显行号
*/
@ExcelLine
@ExcelIgnore
private Long lineNum;
/**
* 主键ID
*/
@ExcelProperty("用户编号")
private Long userId;
/**
* 用户名
*/
@NotBlank(message = "用户名不能为空")
@ExcelProperty("用户名")
private String username;
/**
* 手机号
*/
@NotBlank(message = "手机号不能为空")
@ExcelProperty("手机号")
private String phone;
/**
* 手机号
*/
@NotBlank(message = "昵称不能为空")
@ExcelProperty("昵称")
private String nickname;
/**
* 手机号
*/
@NotBlank(message = "姓名不能为空")
@ExcelProperty("姓名")
private String name;
/**
* 手机号
*/
@NotBlank(message = "邮箱不能为空")
@ExcelProperty("邮箱")
private String email;
/**
* 角色列表
*/
@NotBlank(message = "角色不能为空")
@ExcelProperty("角色")
private String roleNameList;
/**
* 锁定标记
*/
@ExcelProperty("锁定标记,0:正常,9:已锁定")
private String lockFlag;
/**
* 创建时间
*/
@ExcelProperty(value = "创建时间")
private LocalDateTime createTime;
}
@@ -1,101 +0,0 @@
package com.pig4cloud.pigx.app.api.vo;
import com.pig4cloud.pigx.app.api.entity.AppRole;
import com.pig4cloud.pigx.common.core.sensitive.Sensitive;
import com.pig4cloud.pigx.common.core.sensitive.SensitiveTypeEnum;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.io.Serializable;
import java.time.LocalDateTime;
import java.util.List;
@Data
public class AppUserVO implements Serializable {
/**
* 主键
*/
@Schema(description = "主键")
private Long userId;
/**
* 用户名
*/
@Schema(description = "用户名")
private String username;
/**
* 密码
*/
@Schema(description = "密码")
private String password;
/**
* 手机号
*/
@Schema(description = "手机号")
@Sensitive(type = SensitiveTypeEnum.MOBILE_PHONE)
private String phone;
/**
* 头像
*/
@Schema(description = "头像")
private String avatar;
/**
* 昵称
*/
@Schema(description = "拓展字段:昵称")
private String nickname;
/**
* 姓名
*/
@Schema(description = "拓展字段:姓名")
private String name;
/**
* 邮箱
*/
@Schema(description = "拓展字段:邮箱")
private String email;
/**
* 创建时间
*/
@Schema(description = "创建时间")
private LocalDateTime createTime;
/**
* 删除标记
*/
@Schema(description = "删除标记,1:已删除,0:正常")
private String delFlag;
/**
* 所属租户
*/
@Schema(description = "所属租户")
private Long tenantId;
/**
* 最后一次密码修改时间
*/
@Schema(description = "最后一次密码修改时间")
private LocalDateTime lastModifiedTime;
/**
* 锁定标记
*/
@Schema(description = "锁定标记")
private String lockFlag;
/**
* 角色列表
*/
@Schema(description = "拥有的角色列表")
private List<AppRole> roleList;
}
@@ -1 +0,0 @@
com.pig4cloud.pigx.app.api.feign.RemoteAppUserService
@@ -0,0 +1,14 @@
# App Server Module i18n Messages - English
# App user related
app.user.userInfo.empty=App user information is empty for {0}
app.user.username.existing=Username {0} already exists
app.user.import.succeed=User import succeeded; default password is the phone number
app.user.query.error=Failed to fetch current user information
# App role related
app.role.roleName.inexistence=Role name {0} does not exist
app.role.nameOrCode.existing=Role name or code already exists ({0} {1})
# App SMS related
app.sms.often=Verification code sent too frequently
@@ -0,0 +1,14 @@
# App Server 模块国际化消息 - 中文
# App 用户相关
app.user.userInfo.empty={0} \u7528\u6237\u4FE1\u606F\u4E3A\u7A7A
app.user.username.existing={0} \u7528\u6237\u540D\u5DF2\u5B58\u5728
app.user.import.succeed=\u7528\u6237\u5BFC\u5165\u6210\u529F\uFF0C\u9ED8\u8BA4\u5BC6\u7801\u4E3A\u624B\u673A\u53F7
app.user.query.error=\u83B7\u53D6\u5F53\u524D\u7528\u6237\u4FE1\u606F\u5931\u8D25
# App 角色相关
app.role.roleName.inexistence={0} \u89D2\u8272\u540D\u79F0\u4E0D\u5B58\u5728
app.role.nameOrCode.existing={0} {1} \u89D2\u8272\u540D\u6216\u89D2\u8272\u7F16\u7801\u5DF2\u7ECF\u5B58\u5728
# App 短信相关
app.sms.often=\u9A8C\u8BC1\u7801\u53D1\u9001\u8FC7\u9891\u7E41
@@ -1,4 +1,4 @@
FROM alibabadragonwell/dragonwell:17-anolis
FROM registry.cn-hangzhou.aliyuncs.com/dockerhub_mirror/java:21-anolis
MAINTAINER wangiegie@gmail.com
+17 -13
View File
@@ -7,21 +7,16 @@
<parent>
<groupId>com.pig4cloud</groupId>
<artifactId>pigx-app-server</artifactId>
<version>5.5.0</version>
<version>6.2.0</version>
</parent>
<artifactId>pigx-app-server-biz</artifactId>
<dependencies>
<!--必备: undertow容器-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-undertow</artifactId>
</dependency>
<!--必备: spring boot web-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<artifactId>spring-boot-starter-webmvc</artifactId>
</dependency>
<!--必备: 注册中心客户端-->
<dependency>
@@ -62,22 +57,31 @@
<dependency>
<groupId>com.pig4cloud</groupId>
<artifactId>pigx-app-server-api</artifactId>
<version>5.5.0</version>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.pig4cloud</groupId>
<artifactId>pigx-upms-api</artifactId>
</dependency>
<!--必备: log 依赖-->
<dependency>
<groupId>com.pig4cloud</groupId>
<artifactId>pigx-common-log</artifactId>
</dependency>
<!--必备: API加解密 -->
<dependency>
<groupId>com.pig4cloud</groupId>
<artifactId>pigx-common-encrypt-api</artifactId>
</dependency>
<!--选配: mybatis 依赖 -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-spring-boot3-starter</artifactId>
<artifactId>mybatis-plus-spring-boot4-starter</artifactId>
</dependency>
<!--选配: druid 连接池 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-3-starter</artifactId>
<artifactId>druid-spring-boot-4-starter</artifactId>
</dependency>
<!--选配: mysql 数据库驱动 -->
<dependency>
@@ -94,6 +98,9 @@
<profiles>
<profile>
<id>cloud</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<build>
<plugins>
<plugin>
@@ -104,9 +111,6 @@
<goals>
<goal>repackage</goal>
</goals>
<configuration>
<loaderImplementation>CLASSIC</loaderImplementation>
</configuration>
</execution>
</executions>
</plugin>
@@ -10,6 +10,7 @@ import com.pig4cloud.pigx.app.service.AppArticleCategoryService;
import com.pig4cloud.pigx.common.core.util.R;
import com.pig4cloud.pigx.common.excel.annotation.ResponseExcel;
import com.pig4cloud.pigx.common.log.annotation.SysLog;
import com.pig4cloud.pigx.common.security.annotation.HasPermission;
import com.pig4cloud.pigx.common.security.annotation.Inner;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
@@ -17,7 +18,6 @@ import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import org.springdoc.core.annotations.ParameterObject;
import org.springframework.http.HttpHeaders;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@@ -45,12 +45,13 @@ public class AppArticleCategoryController {
*/
@Operation(summary = "分页查询", description = "分页查询")
@GetMapping("/page")
@PreAuthorize("@pms.hasPermission('app_appArticleCategory_view')")
@HasPermission("app_appArticleCategory_view")
public R getAppArticleCategoryPage(@ParameterObject Page page,
@ParameterObject AppArticleCategoryEntity appArticleCategory) {
LambdaQueryWrapper<AppArticleCategoryEntity> wrapper = Wrappers.lambdaQuery();
wrapper.like(StrUtil.isNotBlank(appArticleCategory.getName()), AppArticleCategoryEntity::getName,
appArticleCategory.getName());
wrapper.orderByAsc(AppArticleCategoryEntity::getSort, AppArticleCategoryEntity::getId);
return R.ok(appArticleCategoryService.page(page, wrapper));
}
@@ -61,7 +62,7 @@ public class AppArticleCategoryController {
*/
@Operation(summary = "通过id查询", description = "通过id查询")
@GetMapping("/{id}")
@PreAuthorize("@pms.hasPermission('app_appArticleCategory_view')")
@HasPermission("app_appArticleCategory_view")
public R getById(@PathVariable("id") Long id) {
return R.ok(appArticleCategoryService.getById(id));
}
@@ -74,7 +75,8 @@ public class AppArticleCategoryController {
@Inner(value = false)
@GetMapping("/list")
public R list() {
return R.ok(appArticleCategoryService.list());
return R.ok(appArticleCategoryService.list(Wrappers.<AppArticleCategoryEntity>lambdaQuery()
.orderByAsc(AppArticleCategoryEntity::getSort, AppArticleCategoryEntity::getId)));
}
/**
@@ -85,7 +87,7 @@ public class AppArticleCategoryController {
@Operation(summary = "新增文章分类表", description = "新增文章分类表")
@SysLog("新增文章分类表")
@PostMapping
@PreAuthorize("@pms.hasPermission('app_appArticleCategory_add')")
@HasPermission("app_appArticleCategory_add")
public R save(@RequestBody AppArticleCategoryEntity appArticleCategory) {
return R.ok(appArticleCategoryService.save(appArticleCategory));
}
@@ -98,11 +100,29 @@ public class AppArticleCategoryController {
@Operation(summary = "修改文章分类表", description = "修改文章分类表")
@SysLog("修改文章分类表")
@PutMapping
@PreAuthorize("@pms.hasPermission('app_appArticleCategory_edit')")
@HasPermission("app_appArticleCategory_edit")
public R updateById(@RequestBody AppArticleCategoryEntity appArticleCategory) {
return R.ok(appArticleCategoryService.updateById(appArticleCategory));
}
/**
* 按传入 ID 顺序调整文章分类,保留未选中记录在排序序列中的位置。
* <p>
* 以当前租户内未删除记录的排序值、主键升序为基准,仅重排选中记录占据的位置, 再将全部记录的排序值从 1 起连续重编号。
* @param ids 按目标顺序排列的文章分类 ID;不可为 null 或空,不可包含 null、重复或不可用的 ID
* @return 排序保存成功的响应;校验或更新失败时抛出异常,由统一异常处理器转换响应
* @throws IllegalArgumentException ID 列表为空、包含 null 或重复值,或指定记录已删除、不属于当前租户 或不存在
* @throws IllegalStateException 批量更新返回失败
*/
@Operation(summary = "拖拽排序", description = "按当前列表顺序保存排序")
@SysLog("文章分类排序")
@PutMapping("/sort")
@HasPermission("app_appArticleCategory_edit")
public R sort(@RequestBody List<Long> ids) {
appArticleCategoryService.sort(ids);
return R.ok();
}
/**
* 通过id删除文章分类表
* @param ids id列表
@@ -111,7 +131,7 @@ public class AppArticleCategoryController {
@Operation(summary = "通过id删除文章分类表", description = "通过id删除文章分类表")
@SysLog("通过id删除文章分类表")
@DeleteMapping
@PreAuthorize("@pms.hasPermission('app_appArticleCategory_del')")
@HasPermission("app_appArticleCategory_del")
public R removeById(@RequestBody Long[] ids) {
return R.ok(appArticleCategoryService.removeBatchByIds(CollUtil.toList(ids)));
}
@@ -123,7 +143,7 @@ public class AppArticleCategoryController {
*/
@ResponseExcel
@GetMapping("/export")
@PreAuthorize("@pms.hasPermission('app_appArticleCategory_export')")
@HasPermission("app_appArticleCategory_export")
public List<AppArticleCategoryEntity> export(AppArticleCategoryEntity appArticleCategory) {
return appArticleCategoryService.list(Wrappers.query(appArticleCategory));
}
@@ -10,6 +10,7 @@ import com.pig4cloud.pigx.app.service.AppArticleCollectService;
import com.pig4cloud.pigx.common.core.util.R;
import com.pig4cloud.pigx.common.excel.annotation.ResponseExcel;
import com.pig4cloud.pigx.common.log.annotation.SysLog;
import com.pig4cloud.pigx.common.security.annotation.HasPermission;
import com.pig4cloud.pigx.common.security.util.SecurityUtils;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
@@ -17,7 +18,6 @@ import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import org.springdoc.core.annotations.ParameterObject;
import org.springframework.http.HttpHeaders;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@@ -35,92 +35,97 @@ import java.util.List;
@SecurityRequirement(name = HttpHeaders.AUTHORIZATION)
public class AppArticleCollectController {
private final AppArticleCollectService appArticleCollectService;
private final AppArticleCollectService appArticleCollectService;
/**
* 分页查询
* @param page 分页对象
* @param appArticleCollect 文章收藏表
* @return
*/
@Operation(summary = "分页查询", description = "分页查询")
@GetMapping("/page")
public R getAppArticleCollectPage(@ParameterObject Page page) {
MPJLambdaWrapper<AppArticleCollectEntity> wrapper = new MPJLambdaWrapper<AppArticleCollectEntity>()
.selectAll(AppArticleCollectEntity.class)
.select(AppArticleEntity::getTitle)
.leftJoin(AppArticleEntity.class, AppArticleEntity::getId, AppArticleCollectEntity::getArticleId)
.eq(AppArticleCollectEntity::getUserId, SecurityUtils.getUser().getId());
return R.ok(appArticleCollectService.selectJoinListPage(page, AppArticleCollectEntity.class, wrapper));
}
/**
* 分页查询文章收藏信息。
*
* @param page 分页查询参数对象
* @return 返回分页结果对象,包含文章收藏信息列表
*/
@Operation(summary = "分页查询", description = "分页查询")
@GetMapping("/page")
public R getAppArticleCollectPage(@ParameterObject Page page) {
MPJLambdaWrapper<AppArticleCollectEntity> wrapper = new MPJLambdaWrapper<AppArticleCollectEntity>()
.selectAll(AppArticleCollectEntity.class)
.select(AppArticleEntity::getTitle, AppArticleEntity::getImage, AppArticleEntity::getVisit)
.leftJoin(AppArticleEntity.class, AppArticleEntity::getId, AppArticleCollectEntity::getArticleId)
.eq(AppArticleCollectEntity::getUserId, SecurityUtils.getUser().getId());
return R.ok(appArticleCollectService.selectJoinListPage(page, AppArticleCollectEntity.class, wrapper));
}
/**
* 通过id查询文章收藏表
* @param id id
* @return R
*/
@Operation(summary = "通过id查询", description = "通过id查询")
@GetMapping("/{id}")
public R getById(@PathVariable("id") Long id) {
return R.ok(appArticleCollectService.getById(id));
}
/**
* 通过id查询文章收藏表
*
* @param id id
* @return R
*/
@Operation(summary = "通过id查询", description = "通过id查询")
@GetMapping("/{id}")
public R getById(@PathVariable("id") Long id) {
return R.ok(appArticleCollectService.getById(id));
}
/**
* 新增文章收藏表
* @param appArticleCollect 文章收藏表
* @return R
*/
@Operation(summary = "新增文章收藏表", description = "新增文章收藏表")
@SysLog("新增文章收藏表")
@PostMapping
public R save(@RequestBody AppArticleCollectEntity appArticleCollect) {
return R.ok(appArticleCollectService.saveArticleCollect(appArticleCollect));
}
/**
* 新增文章收藏表
*
* @param appArticleCollect 文章收藏表
* @return R
*/
@Operation(summary = "新增文章收藏表", description = "新增文章收藏表")
@SysLog("新增文章收藏表")
@PostMapping
public R save(@RequestBody AppArticleCollectEntity appArticleCollect) {
return R.ok(appArticleCollectService.saveArticleCollect(appArticleCollect));
}
/**
* 修改文章收藏表
* @param appArticleCollect 文章收藏表
* @return R
*/
@Operation(summary = "修改文章收藏表", description = "修改文章收藏表")
@SysLog("修改文章收藏表")
@PutMapping
public R updateById(@RequestBody AppArticleCollectEntity appArticleCollect) {
return R.ok(appArticleCollectService.updateById(appArticleCollect));
}
/**
* 修改文章收藏表
*
* @param appArticleCollect 文章收藏表
* @return R
*/
@Operation(summary = "修改文章收藏表", description = "修改文章收藏表")
@SysLog("修改文章收藏表")
@PutMapping
public R updateById(@RequestBody AppArticleCollectEntity appArticleCollect) {
return R.ok(appArticleCollectService.updateById(appArticleCollect));
}
/**
* 通过id删除文章收藏表
* @param ids id列表
* @return R
*/
@Operation(summary = "通过id删除文章收藏表", description = "通过id删除文章收藏表")
@SysLog("通过id删除文章收藏表")
@DeleteMapping
public R removeById(@RequestBody Long[] ids) {
return R.ok(appArticleCollectService.removeBatchByIds(CollUtil.toList(ids)));
}
/**
* 通过id删除文章收藏表
*
* @param ids id列表
* @return R
*/
@Operation(summary = "通过id删除文章收藏表", description = "通过id删除文章收藏表")
@SysLog("通过id删除文章收藏表")
@DeleteMapping
public R removeById(@RequestBody Long[] ids) {
return R.ok(appArticleCollectService.removeBatchByIds(CollUtil.toList(ids)));
}
@Operation(summary = "通过文章id删除文章收藏表", description = "通过文章id删除文章收藏表")
@SysLog("通过文章id删除文章收藏表")
@DeleteMapping("/{articleId}")
public R removeByArticleId(@PathVariable String articleId) {
Long id = SecurityUtils.getUser().getId();
return R.ok(appArticleCollectService.remove(Wrappers.<AppArticleCollectEntity>lambdaQuery()
.eq(AppArticleCollectEntity::getUserId, id)
.eq(AppArticleCollectEntity::getArticleId, articleId)));
}
@Operation(summary = "通过文章id删除文章收藏表", description = "通过文章id删除文章收藏表")
@SysLog("通过文章id删除文章收藏表")
@DeleteMapping("/{articleId}")
public R removeByArticleId(@PathVariable String articleId) {
Long id = SecurityUtils.getUser().getId();
return R.ok(appArticleCollectService.remove(Wrappers.<AppArticleCollectEntity>lambdaQuery()
.eq(AppArticleCollectEntity::getUserId, id)
.eq(AppArticleCollectEntity::getArticleId, articleId)));
}
/**
* 导出excel 表格
* @param appArticleCollect 查询条件
* @return excel 文件流
*/
@ResponseExcel
@GetMapping("/export")
@PreAuthorize("@pms.hasPermission('app_collect_export')")
public List<AppArticleCollectEntity> export(AppArticleCollectEntity appArticleCollect) {
return appArticleCollectService.list(Wrappers.query(appArticleCollect));
}
/**
* 导出excel 表格
*
* @param appArticleCollect 查询条件
* @return excel 文件流
*/
@ResponseExcel
@GetMapping("/export")
@HasPermission("app_collect_export")
public List<AppArticleCollectEntity> export(AppArticleCollectEntity appArticleCollect) {
return appArticleCollectService.list(Wrappers.query(appArticleCollect));
}
}
@@ -8,6 +8,7 @@ import com.pig4cloud.pigx.app.service.AppArticleService;
import com.pig4cloud.pigx.common.core.util.R;
import com.pig4cloud.pigx.common.excel.annotation.ResponseExcel;
import com.pig4cloud.pigx.common.log.annotation.SysLog;
import com.pig4cloud.pigx.common.security.annotation.HasPermission;
import com.pig4cloud.pigx.common.security.annotation.Inner;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
@@ -15,7 +16,6 @@ import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import org.springdoc.core.annotations.ParameterObject;
import org.springframework.http.HttpHeaders;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@@ -36,10 +36,12 @@ public class AppArticleController {
private final AppArticleService appArticleService;
/**
* 分页查询
* 分页查询文章资讯。
* <p>
* 返回文章列表时会关联分类名称,供 App 资讯列表和后台管理复用。
* @param page 分页对象
* @param appArticle 文章资讯
* @return
* @return 文章分页结果
*/
@Operation(summary = "分页查询", description = "分页查询")
@Inner(value = false)
@@ -49,9 +51,12 @@ public class AppArticleController {
}
/**
* 通过id查询文章资讯
* @param id id
* @return R
* 查询文章详情。
* <p>
* 会递增访问次数;如果传入 userId,则额外返回该用户是否收藏当前文章。
* @param id 文章 ID
* @param userId 用户 ID,可为空
* @return 文章详情
*/
@Inner(value = false)
@Operation(summary = "通过id查询", description = "通过id查询")
@@ -68,7 +73,7 @@ public class AppArticleController {
@Operation(summary = "新增文章资讯", description = "新增文章资讯")
@SysLog("新增文章资讯")
@PostMapping
@PreAuthorize("@pms.hasPermission('app_appArticle_add')")
@HasPermission("app_appArticle_add")
public R save(@RequestBody AppArticleEntity appArticle) {
return R.ok(appArticleService.save(appArticle));
}
@@ -81,11 +86,29 @@ public class AppArticleController {
@Operation(summary = "修改文章资讯", description = "修改文章资讯")
@SysLog("修改文章资讯")
@PutMapping
@PreAuthorize("@pms.hasPermission('app_appArticle_edit')")
@HasPermission("app_appArticle_edit")
public R updateById(@RequestBody AppArticleEntity appArticle) {
return R.ok(appArticleService.updateById(appArticle));
}
/**
* 按传入 ID 顺序调整文章,保留未选中记录在排序序列中的位置。
* <p>
* 以当前租户内未删除记录的排序值、主键升序为基准,仅重排选中记录占据的位置, 再将全部记录的排序值从 1 起连续重编号。
* @param ids 按目标顺序排列的文章 ID;不可为 null 或空,不可包含 null、重复或不可用的 ID
* @return 排序保存成功的响应;校验或更新失败时抛出异常,由统一异常处理器转换响应
* @throws IllegalArgumentException ID 列表为空、包含 null 或重复值,或指定记录已删除、不属于当前租户 或不存在
* @throws IllegalStateException 批量更新返回失败
*/
@Operation(summary = "拖拽排序", description = "按当前列表顺序保存排序")
@SysLog("文章资讯排序")
@PutMapping("/sort")
@HasPermission("app_appArticle_edit")
public R sort(@RequestBody List<Long> ids) {
appArticleService.sort(ids);
return R.ok();
}
/**
* 通过id删除文章资讯
* @param ids id列表
@@ -94,7 +117,7 @@ public class AppArticleController {
@Operation(summary = "通过id删除文章资讯", description = "通过id删除文章资讯")
@SysLog("通过id删除文章资讯")
@DeleteMapping
@PreAuthorize("@pms.hasPermission('app_appArticle_del')")
@HasPermission("app_appArticle_del")
public R removeById(@RequestBody Long[] ids) {
return R.ok(appArticleService.removeBatchByIds(CollUtil.toList(ids)));
}
@@ -106,7 +129,7 @@ public class AppArticleController {
*/
@ResponseExcel
@GetMapping("/export")
@PreAuthorize("@pms.hasPermission('app_appArticle_export')")
@HasPermission("app_appArticle_export")
public List<AppArticleEntity> export(AppArticleEntity appArticle) {
return appArticleService.list(Wrappers.query(appArticle));
}
@@ -0,0 +1,122 @@
package com.pig4cloud.pigx.app.controller;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ArrayUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.pig4cloud.pigx.app.api.entity.AppContactsEntity;
import com.pig4cloud.pigx.app.service.AppContactsService;
import com.pig4cloud.pigx.common.core.util.R;
import com.pig4cloud.pigx.common.excel.annotation.ResponseExcel;
import com.pig4cloud.pigx.common.log.annotation.SysLog;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import org.springdoc.core.annotations.ParameterObject;
import org.springframework.http.HttpHeaders;
import com.pig4cloud.pigx.common.security.annotation.HasPermission;
import org.springframework.web.bind.annotation.*;
import java.util.List;
/**
* 通讯录表管理控制器
*
* @author lengleng
* @date 2025/05/29
*/
@RestController
@RequiredArgsConstructor
@RequestMapping("/appContacts")
@Tag(description = "appContacts", name = "通讯录表管理")
@SecurityRequirement(name = HttpHeaders.AUTHORIZATION)
public class AppContactsController {
private final AppContactsService appContactsService;
/**
* 分页查询
*
* @param page 分页对象
* @param appContacts 通讯录表
* @return
*/
@Operation(summary = "分页查询", description = "分页查询")
@GetMapping("/page")
@HasPermission("app_appContacts_view")
public R getAppContactsPage(@ParameterObject Page page, @ParameterObject AppContactsEntity appContacts) {
return R.ok(appContactsService.pageScope(page, appContacts));
}
/**
* 通过id查询通讯录表
*
* @param id id
* @return R
*/
@Operation(summary = "通过id查询", description = "通过id查询")
@GetMapping("/{id}")
@HasPermission("app_appContacts_view")
public R getById(@PathVariable("id") Long id) {
return R.ok(appContactsService.getById(id));
}
/**
* 新增通讯录表
*
* @param appContacts 通讯录表
* @return R
*/
@Operation(summary = "新增通讯录表", description = "新增通讯录表")
@SysLog("新增通讯录表")
@PostMapping
@HasPermission("app_appContacts_add")
public R save(@RequestBody AppContactsEntity appContacts) {
return R.ok(appContactsService.save(appContacts));
}
/**
* 修改通讯录表
*
* @param appContacts 通讯录表
* @return R
*/
@Operation(summary = "修改通讯录表", description = "修改通讯录表")
@SysLog("修改通讯录表")
@PutMapping
@HasPermission("app_appContacts_edit")
public R updateById(@RequestBody AppContactsEntity appContacts) {
return R.ok(appContactsService.updateById(appContacts));
}
/**
* 通过id删除通讯录表
*
* @param ids id列表
* @return R
*/
@Operation(summary = "通过id删除通讯录表", description = "通过id删除通讯录表")
@SysLog("通过id删除通讯录表")
@DeleteMapping
@HasPermission("app_appContacts_del")
public R removeById(@RequestBody Long[] ids) {
return R.ok(appContactsService.removeBatchByIds(CollUtil.toList(ids)));
}
/**
* 导出excel 表格
*
* @param appContacts 查询条件
* @param ids 导出指定ID
* @return excel 文件流
*/
@ResponseExcel
@GetMapping("/export")
@HasPermission("app_appContacts_export")
public List<AppContactsEntity> export(AppContactsEntity appContacts, Long[] ids) {
return appContactsService.list(Wrappers.lambdaQuery(appContacts).in(ArrayUtil.isNotEmpty(ids), AppContactsEntity::getId, ids));
}
}
@@ -1,6 +1,5 @@
package com.pig4cloud.pigx.app.controller;
import com.pig4cloud.pigx.app.api.entity.AppPageEntity;
import com.pig4cloud.pigx.app.service.AppIndexService;
import com.pig4cloud.pigx.common.core.util.R;
import com.pig4cloud.pigx.common.security.annotation.Inner;
@@ -14,10 +13,11 @@ import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.util.Map;
/**
* app 首页控制
* App 运行时页面接口。
* <p>
* 这里的接口主要给移动端调用,返回首页、装修页、底部 Tabbar 等运行时数据。
* 部分接口允许匿名访问,具体可见方法上的 {@link Inner} 配置。
*
* @author lengleng
* @date 2023/6/8
@@ -29,31 +29,58 @@ import java.util.Map;
@SecurityRequirement(name = HttpHeaders.AUTHORIZATION)
public class AppIndexController {
private final AppIndexService indexService;
private final AppIndexService indexService;
/**
* 首页
* @return Object
*/
@Inner(value = false)
@GetMapping("/index")
public R index() {
Map<String, Object> detail = indexService.index();
return R.ok(detail);
}
/**
* 获取首页基础数据。
* <p>
* 当前返回首页装修页记录和资讯列表,适合旧版首页一次性拉取基础内容。
*
* @return 首页页面数据和资讯列表
*/
@Inner(value = false)
@GetMapping("/index")
public R index() {
return R.ok(indexService.index());
}
@Inner(value = false)
@GetMapping("/config")
public R config() {
Map<String, Object> map = indexService.config();
return R.ok(map);
}
/**
* 获取移动端底部导航配置。
* <p>
* 未登录时只返回公开 Tabbar;登录后返回公开 Tabbar + 当前用户角色授权的 Tabbar。
*
* @return 当前访问身份可见的 Tabbar 列表
*/
@Inner(value = false)
@GetMapping("/config")
public R config() {
return R.ok(indexService.config());
}
@Inner(value = false)
@GetMapping("/decorate")
public R decorate(@Validated @RequestParam("id") Integer id) {
AppPageEntity detail = indexService.decorate(id);
return R.ok(detail);
}
/**
* 获取指定页面类型的装修数据。
* <p>
* 返回页面装修 JSON,同时聚合当前访问身份可见的 Tabbar,方便移动端一次请求完成页面渲染。
*
* @param pageType 页面类型
* @return 装修页聚合数据
*/
@Inner(value = false)
@GetMapping("/decorate")
public R decorate(@Validated @RequestParam("id") Integer pageType) {
return R.ok(indexService.decorate(pageType));
}
/**
* 获取工作台页面装修数据。
* <p>
* 工作台内部按钮权限复用 B 端权限体系,这里不再按 App 专属菜单做二次过滤。
*
* @return 工作台页面数据
*/
@GetMapping("/workbench")
public R workbench() {
return R.ok(indexService.workbench());
}
}
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2018-2025, lengleng All rights reserved.
* Copyright (c) 2018-2026, lengleng All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@@ -30,6 +30,8 @@ import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* App 手机验证码接口。
*
* @author lengleng
* @date 2018/11/14
* <p>
@@ -44,6 +46,12 @@ public class AppMobileController {
private final AppMobileService appMobileService;
/**
* 发送 App 手机验证码。
*
* @param mobile 手机号
* @return 发送结果
*/
@Inner(value = false)
@GetMapping("/{mobile}")
public R sendSmsCode(@PathVariable String mobile) {
@@ -1,17 +1,29 @@
package com.pig4cloud.pigx.app.controller;
import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.pig4cloud.pigx.app.api.entity.AppPageEntity;
import com.pig4cloud.pigx.app.api.entity.AppTabbarEntity;
import com.pig4cloud.pigx.app.api.enums.PageTypeEnums;
import com.pig4cloud.pigx.app.api.vo.AppDecorateVO;
import com.pig4cloud.pigx.app.service.AppPageService;
import com.pig4cloud.pigx.app.service.AppTabbarService;
import com.pig4cloud.pigx.common.core.util.R;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import org.springframework.http.HttpHeaders;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;
import java.util.List;
/**
* 页面管理
* App 装修页面后台管理接口。
* <p>
* 页面表只保存页面装修组件 JSON,底部 Tabbar 由 {@code app_tabbar} 独立维护;
* 查询装修页时会聚合 Tabbar,便于后台预览。
*
* @author pig
* @date 2023-06-07 16:32:35
@@ -23,23 +35,58 @@ import org.springframework.web.bind.annotation.*;
@SecurityRequirement(name = HttpHeaders.AUTHORIZATION)
public class AppPageController {
private final AppPageService pageService;
private final AppPageService pageService;
/**
* 通过id查询文章资讯
* @param id id
* @return R
*/
@Operation(summary = "通过id查询", description = "通过id查询")
@GetMapping("/{id}")
public R getById(@PathVariable("id") Long id) {
return R.ok(pageService.getById(id));
}
private final AppTabbarService tabbarService;
@Operation(summary = "更新页面", description = "更新页面")
@PutMapping
public R update(@RequestBody AppPageEntity page) {
return R.ok(pageService.updateById(page));
}
/**
* 按页面类型查询后台装修页配置。
* <p>
* 返回结构保持页面字段在顶层,并额外携带完整 Tabbar 列表,用于后台装修预览和 Tabbar 设置区初始化。
*
* @param pageType 页面类型,见 {@link PageTypeEnums}
* @return 页面装修数据和完整 Tabbar 列表
*/
@Operation(summary = "通过页面类型查询", description = "通过页面类型查询")
@GetMapping("/{pageType}")
public R getByPageType(@PathVariable("pageType") Integer pageType) {
AppPageEntity appPage = pageService.getOne(Wrappers.<AppPageEntity>lambdaQuery()
.eq(AppPageEntity::getPageType, pageType)
.orderByDesc(AppPageEntity::getCreateTime), false);
List<AppTabbarEntity> tabbarList = tabbarService
.list(Wrappers.<AppTabbarEntity>lambdaQuery().orderByAsc(AppTabbarEntity::getSortOrder).orderByAsc(AppTabbarEntity::getId));
AppDecorateVO decorateVO = AppDecorateVO.of(appPage, tabbarList);
if (appPage == null) {
decorateVO.setPageType(pageType);
decorateVO.setPageName(PageTypeEnums.getNameByType(pageType));
decorateVO.setPageData("[]");
}
return R.ok(decorateVO);
}
/**
* 保存页面装修数据。
* <p>
* 同一页面类型只保留一份最新配置;保存时先删除旧记录,再写入新记录。
* Tabbar 不随页面一起保存,需通过 {@link AppTabbarController} 单独维护。
*
* @param page 页面
* @return 保存结果
*/
@Operation(summary = "更新页面", description = "更新页面")
@PutMapping
@Transactional(rollbackFor = Exception.class)
public R update(@RequestBody AppPageEntity page) {
List<AppPageEntity> pageEntityList = pageService
.list(Wrappers.<AppPageEntity>lambdaQuery().eq(AppPageEntity::getPageType, page.getPageType()));
if (CollUtil.isNotEmpty(pageEntityList)) {
// app_page 按页面类型覆盖保存,避免同一页面类型存在多份装修数据。
pageService.removeByIds(pageEntityList.stream().map(AppPageEntity::getId).toList());
}
page.setPageName(PageTypeEnums.getNameByType(page.getPageType()));
return R.ok(pageService.save(page));
}
}
@@ -1,175 +0,0 @@
/*
* Copyright (c) 2018-2025, lengleng All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* Neither the name of the pig4cloud.com developer nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
* Author: lengleng (wangiegie@gmail.com)
*/
package com.pig4cloud.pigx.app.controller;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.pig4cloud.pigx.app.api.entity.AppRole;
import com.pig4cloud.pigx.app.api.vo.AppRoleExcelVO;
import com.pig4cloud.pigx.app.service.AppRoleService;
import com.pig4cloud.pigx.common.core.util.R;
import com.pig4cloud.pigx.common.excel.annotation.RequestExcel;
import com.pig4cloud.pigx.common.excel.annotation.ResponseExcel;
import com.pig4cloud.pigx.common.log.annotation.SysLog;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import org.springframework.http.HttpHeaders;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.*;
import java.util.List;
/**
* app角色表
*
* @author aeizzz
* @date 2022-12-07 09:52:03
*/
@RestController
@RequiredArgsConstructor
@RequestMapping("/approle")
@Tag(description = "approle", name = "app角色表管理")
@SecurityRequirement(name = HttpHeaders.AUTHORIZATION)
public class AppRoleController {
private final AppRoleService appRoleService;
/**
* 分页查询
* @param page 分页对象
* @param appRole app角色表
* @return
*/
@Operation(summary = "分页查询", description = "分页查询")
@GetMapping("/page")
public R getAppRolePage(Page page, AppRole appRole) {
return R.ok(appRoleService.page(page, Wrappers.<AppRole>lambdaQuery()
.like(StrUtil.isNotBlank(appRole.getRoleName()), AppRole::getRoleName, appRole.getRoleName())));
}
/**
* 查询全部角色
* @return
*/
@Operation(summary = "查询全部", description = "查询全部")
@GetMapping("/list")
public R list() {
return R.ok(appRoleService.list(Wrappers.emptyWrapper()));
}
/**
* 通过id查询app角色表
* @param roleId id
* @return R
*/
@Operation(summary = "通过id查询", description = "通过id查询")
@GetMapping("/{roleId}")
public R getById(@PathVariable("roleId") Long roleId) {
return R.ok(appRoleService.getById(roleId));
}
/**
* 通过roleName查询app角色表
* @param roleName roleName
* @return R
*/
@Operation(summary = "通过id查询", description = "通过id查询")
@GetMapping("/details/{roleName}")
public R getByUserName(@PathVariable("roleName") String roleName) {
return R.ok(appRoleService.getOne(Wrappers.<AppRole>lambdaQuery().eq(AppRole::getRoleName, roleName)));
}
/**
* 通过roleCode查询app角色表
* @param roleCode roleCode
* @return R
*/
@Operation(summary = "通过roleCode查询", description = "通过roleCode查询")
@GetMapping("/detailsByCode/{roleCode}")
public R getByPhone(@PathVariable("roleCode") String roleCode) {
return R.ok(appRoleService.getOne(Wrappers.<AppRole>lambdaQuery().eq(AppRole::getRoleCode, roleCode)));
}
/**
* 新增app角色表
* @param appRole app角色表
* @return R
*/
@Operation(summary = "新增app角色表", description = "新增app角色表")
@SysLog("新增app角色表")
@PostMapping
@PreAuthorize("@pms.hasPermission('app_approle_add')")
public R save(@RequestBody AppRole appRole) {
return R.ok(appRoleService.save(appRole));
}
/**
* 修改app角色表
* @param appRole app角色表
* @return R
*/
@Operation(summary = "修改app角色表", description = "修改app角色表")
@SysLog("修改app角色表")
@PutMapping
@PreAuthorize("@pms.hasPermission('app_approle_edit')")
public R updateById(@RequestBody AppRole appRole) {
return R.ok(appRoleService.updateById(appRole));
}
/**
* 通过ids批量删除app角色表
* @param ids roleIds
* @return R
*/
@Operation(summary = "通过ids批量删除app角色表", description = "通过ids批量删除app角色表")
@SysLog("通过ids批量删除app角色表")
@DeleteMapping
@PreAuthorize("@pms.hasPermission('app_approle_del')")
public R removeById(@RequestBody Long[] ids) {
return R.ok(appRoleService.deleteRoleByIds(ids));
}
/**
* 导出excel 表格
* @param appRole 查询条件
* @return excel 文件流
*/
@ResponseExcel
@GetMapping("/export")
@PreAuthorize("@pms.hasPermission('app_approle_export')")
public List<AppRole> export(AppRole appRole) {
return appRoleService.list(Wrappers.query(appRole));
}
/**
* 导入角色
* @param excelVOList 角色列表
* @param bindingResult 错误信息列表
* @return ok fail
*/
@PostMapping("/import")
@PreAuthorize("@pms.hasPermission('app_approle_export')")
public R importRole(@RequestExcel List<AppRoleExcelVO> excelVOList, BindingResult bindingResult) {
return appRoleService.importRole(excelVOList, bindingResult);
}
}
@@ -0,0 +1,105 @@
package com.pig4cloud.pigx.app.controller;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.pig4cloud.pigx.admin.api.entity.SysRole;
import com.pig4cloud.pigx.admin.api.feign.RemoteRoleService;
import com.pig4cloud.pigx.app.api.dto.AppRoleTabbarDTO;
import com.pig4cloud.pigx.app.api.entity.AppTabbarEntity;
import com.pig4cloud.pigx.app.service.AppRoleTabbarService;
import com.pig4cloud.pigx.app.service.AppTabbarService;
import com.pig4cloud.pigx.common.core.util.R;
import com.pig4cloud.pigx.common.security.annotation.HasPermission;
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import org.springframework.http.HttpHeaders;
import org.springframework.web.bind.annotation.*;
import java.util.List;
/**
* App 角色底部导航授权管理接口。
* <p>
* 该接口只维护「系统角色 -> App Tabbar」的授权关系。角色本身仍来自 upms 的 {@code sys_role},
* App 端运行时根据登录 token 中的角色 ID 读取 {@code app_role_tabbar},不跨库 join {@code sys_user_role}。
*
* @author lengleng
* @date 2026-05-09
*/
@RestController
@RequiredArgsConstructor
@RequestMapping("/role-tabbar")
@Tag(description = "role-tabbar", name = "App角色底部导航授权")
@SecurityRequirement(name = HttpHeaders.AUTHORIZATION)
public class AppRoleTabbarController {
private final RemoteRoleService remoteRoleService;
private final AppTabbarService appTabbarService;
private final AppRoleTabbarService appRoleTabbarService;
/**
* 查询可授权的系统角色列表。
* <p>
* 角色来源于 upms 远程接口,前端可按角色名称做轻量过滤,用于角色 Tabbar 授权页面。
*
* @param roleName 角色名称关键字,可为空
* @return 系统角色列表
*/
@GetMapping("/roles")
@HasPermission("app_role_tabbar_view")
public R<List<SysRole>> roles(@RequestParam(required = false) String roleName) {
R<List<SysRole>> roles = remoteRoleService.getAllRole();
if (!roles.isOk() || roles.getData() == null || StrUtil.isBlank(roleName)) {
return roles;
}
return R.ok(roles.getData()
.stream()
.filter(role -> StrUtil.containsIgnoreCase(role.getRoleName(), roleName))
.toList());
}
/**
* 查询可授权的 App 底部导航列表。
* <p>
* 返回完整 Tabbar 列表,公开 Tabbar 前端可固定勾选,登录可见 Tabbar 由角色授权控制。
*
* @return App Tabbar 列表
*/
@GetMapping("/tabbar")
@HasPermission("app_role_tabbar_view")
public R<List<AppTabbarEntity>> tabbars() {
return R.ok(appTabbarService.list(Wrappers.<AppTabbarEntity>lambdaQuery()
.orderByAsc(AppTabbarEntity::getSortOrder)));
}
/**
* 查询指定角色已授权的 Tabbar ID。
*
* @param roleId 系统角色 ID
* @return 已授权的 Tabbar ID 列表
*/
@GetMapping("/{roleId}")
@HasPermission("app_role_tabbar_view")
public R<List<Long>> roleTabbars(@PathVariable Long roleId) {
return R.ok(appRoleTabbarService.listTabbarIdsByRoleId(roleId));
}
/**
* 保存角色 Tabbar 授权。
* <p>
* 保存采用覆盖语义:先清空该角色原有授权,再写入本次提交的 Tabbar ID 列表。
*
* @param dto 角色 Tabbar 授权请求
* @return 保存结果
*/
@PutMapping
@HasPermission("app_role_tabbar_edit")
public R<Boolean> saveRoleTabbars(@Valid @RequestBody AppRoleTabbarDTO dto) {
return R.ok(appRoleTabbarService.saveRoleTabbars(dto));
}
}
@@ -1,139 +0,0 @@
/*
* Copyright (c) 2018-2025, lengleng All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* Neither the name of the pig4cloud.com developer nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
* Author: lengleng (wangiegie@gmail.com)
*/
package com.pig4cloud.pigx.app.controller;
import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.pig4cloud.pigx.app.api.entity.AppSocialDetails;
import com.pig4cloud.pigx.app.service.AppSocialDetailsService;
import com.pig4cloud.pigx.common.core.util.R;
import com.pig4cloud.pigx.common.core.util.ValidGroup;
import com.pig4cloud.pigx.common.excel.annotation.ResponseExcel;
import com.pig4cloud.pigx.common.log.annotation.SysLog;
import com.pig4cloud.pigx.common.security.annotation.Inner;
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.AllArgsConstructor;
import org.springframework.http.HttpHeaders;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import jakarta.validation.Valid;
import java.util.List;
@RestController
@RequestMapping("/appsocial")
@AllArgsConstructor
@Tag(description = "social", name = "三方账号管理模块")
@SecurityRequirement(name = HttpHeaders.AUTHORIZATION)
public class AppSocialDetailsController {
private final AppSocialDetailsService appSocialDetailsService;
/**
* 社交登录账户简单分页查询
* @param page 分页对象
* @param appSocialDetails 社交登录
* @return
*/
@GetMapping("/page")
public R getSocialDetailsPage(Page page, AppSocialDetails appSocialDetails) {
return R.ok(appSocialDetailsService.page(page, Wrappers.query(appSocialDetails)));
}
/**
* 信息
* @param id id
* @return R
*/
@GetMapping("/{id}")
public R getinfo(@PathVariable("id") Long id) {
return R.ok(appSocialDetailsService.getById(id));
}
/**
* 保存
* @param appSocialDetails
* @return R
*/
@SysLog("保存三方信息")
@PostMapping
@PreAuthorize("@pms.hasPermission('app_social_details_add')")
public R save(@Valid @RequestBody AppSocialDetails appSocialDetails) {
return R.ok(appSocialDetailsService.save(appSocialDetails));
}
/**
* 修改
* @param appSocialDetails
* @return R
*/
@SysLog("修改三方信息")
@PutMapping
@PreAuthorize("@pms.hasPermission('app_social_details_edit')")
public R updateById(@Validated({ ValidGroup.Update.class }) @RequestBody AppSocialDetails appSocialDetails) {
appSocialDetailsService.updateById(appSocialDetails);
return R.ok(Boolean.TRUE);
}
/**
* 删除
* @param ids
* @return R
*/
@SysLog("删除三方信息")
@DeleteMapping
@PreAuthorize("@pms.hasPermission('app_social_details_del')")
public R removeById(@RequestBody Long[] ids) {
return R.ok(appSocialDetailsService.removeBatchByIds(CollUtil.toList(ids)));
}
/**
* 通过社交账号、手机号查询用户、角色信息
* @param inStr appid@code
* @return
*/
@Inner
@GetMapping("/info/{inStr}")
public R getUserInfo(@PathVariable String inStr) {
return R.ok(appSocialDetailsService.getUserInfo(inStr));
}
/**
* 绑定社交账号
* @param state 类型
* @param code code
* @return
*/
@PostMapping("/bind")
public R bindSocial(String state, String code) {
return R.ok(appSocialDetailsService.bindSocial(state, code));
}
/**
* 导出
*/
@GetMapping("/export")
@ResponseExcel
public List<AppSocialDetails> export(AppSocialDetails appSocialDetails) {
return appSocialDetailsService.list(Wrappers.query(appSocialDetails));
}
}
@@ -1,7 +1,10 @@
package com.pig4cloud.pigx.app.controller;
import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.pig4cloud.pigx.app.api.entity.AppRoleTabbar;
import com.pig4cloud.pigx.app.api.entity.AppTabbarEntity;
import com.pig4cloud.pigx.app.service.AppRoleTabbarService;
import com.pig4cloud.pigx.app.service.AppTabbarService;
import com.pig4cloud.pigx.common.core.util.R;
import io.swagger.v3.oas.annotations.Operation;
@@ -12,10 +15,12 @@ import org.springframework.http.HttpHeaders;
import org.springframework.web.bind.annotation.*;
import java.util.List;
import java.util.stream.Collectors;
/**
* 底部导航
* App 底部导航后台管理接口。
* <p>
* Tabbar 是移动端底部入口的数据源,图标字段保存 Wot UI 图标名;
* 是否登录可见由 {@code loginFlag} 控制,登录后再叠加角色授权。
*
* @author pig
* @date 2023-06-07 16:32:35
@@ -27,26 +32,56 @@ import java.util.stream.Collectors;
@SecurityRequirement(name = HttpHeaders.AUTHORIZATION)
public class AppTabbarController {
private final AppTabbarService tabbarService;
private final AppTabbarService tabbarService;
/**
* 查询导航列表
* @return R
*/
@Operation(summary = "查询导航列表", description = "查询导航列表")
@GetMapping("/list")
public R list() {
return R.ok(tabbarService.list());
}
private final AppRoleTabbarService roleTabbarService;
@Operation(summary = "更新导航", description = "更新导航")
@PutMapping
public R update(@RequestBody List<AppTabbarEntity> tabbarEntityList) {
// 删除不在新增范围的导航菜单
List<Long> idList = tabbarService.list().stream().map(AppTabbarEntity::getId).collect(Collectors.toList());
List<Long> newIdList = tabbarEntityList.stream().map(AppTabbarEntity::getId).collect(Collectors.toList());
tabbarService.removeBatchByIds(CollUtil.subtractToList(idList, newIdList));
return R.ok(tabbarService.saveOrUpdateBatch(tabbarEntityList));
/**
* 查询全部底部导航。
* <p>
* 后台维护页面使用完整列表;移动端运行时请走 {@code /app/index/config},
* 由运行时接口按公开/角色授权规则过滤。
*
* @return 完整 Tabbar 列表
*/
@Operation(summary = "查询导航列表", description = "查询导航列表")
@GetMapping("/list")
public R list() {
return R.ok(tabbarService.list(
Wrappers.<AppTabbarEntity>lambdaQuery().orderByAsc(AppTabbarEntity::getSortOrder).orderByAsc(AppTabbarEntity::getId)));
}
/**
* 批量保存底部导航。
* <p>
* 前端提交的是当前完整 Tabbar 列表。这里会删除数据库中已不存在的 Tabbar,
* 并同步清理角色授权关系,避免 {@code app_role_tabbar} 残留无效 tabbar_id。
*
* @param tabbarEntityList 当前完整 Tabbar 配置
* @return 保存结果
*/
@Operation(summary = "更新导航", description = "更新导航")
@PutMapping
public R update(@RequestBody List<AppTabbarEntity> tabbarEntityList) {
tabbarEntityList.forEach(tabbar -> {
if (tabbar.getLoginFlag() == null) {
tabbar.setLoginFlag("1");
}
});
// 删除不在新增范围的导航菜单
List<Long> idList = tabbarService.list().stream().map(AppTabbarEntity::getId).toList();
List<Long> newIdList = tabbarEntityList.stream().map(AppTabbarEntity::getId).toList();
// 计算需要删除的 ID 列表
List<Long> idsToRemove = CollUtil.subtractToList(idList, newIdList);
// 如果有需要删除的菜单,则批量删除
if (CollUtil.isNotEmpty(idsToRemove)) {
tabbarService.removeBatchByIds(idsToRemove);
roleTabbarService.remove(Wrappers.<AppRoleTabbar>lambdaQuery().in(AppRoleTabbar::getTabbarId, idsToRemove));
}
return R.ok(tabbarService.saveOrUpdateBatch(tabbarEntityList));
}
}
@@ -1,207 +0,0 @@
/*
* Copyright (c) 2018-2025, lengleng All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* Neither the name of the pig4cloud.com developer nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
* Author: lengleng (wangiegie@gmail.com)
*/
package com.pig4cloud.pigx.app.controller;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.pig4cloud.pigx.app.api.dto.AppUserDTO;
import com.pig4cloud.pigx.app.api.entity.AppUser;
import com.pig4cloud.pigx.app.api.vo.AppUserExcelVO;
import com.pig4cloud.pigx.app.service.AppUserService;
import com.pig4cloud.pigx.common.core.constant.CommonConstants;
import com.pig4cloud.pigx.common.core.constant.enums.UserTypeEnum;
import com.pig4cloud.pigx.common.core.exception.ErrorCodes;
import com.pig4cloud.pigx.common.core.util.MsgUtils;
import com.pig4cloud.pigx.common.core.util.R;
import com.pig4cloud.pigx.common.excel.annotation.RequestExcel;
import com.pig4cloud.pigx.common.excel.annotation.ResponseExcel;
import com.pig4cloud.pigx.common.log.annotation.SysLog;
import com.pig4cloud.pigx.common.security.annotation.Inner;
import com.pig4cloud.pigx.common.security.util.SecurityUtils;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import org.springframework.http.HttpHeaders;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.*;
import jakarta.validation.Valid;
import java.util.List;
/**
* app用户表
*
* @author aeizzz
* @date 2022-12-07 09:52:03
*/
@RestController
@RequiredArgsConstructor
@RequestMapping("/appuser")
@Tag(description = "appuser", name = "app用户表管理")
@SecurityRequirement(name = HttpHeaders.AUTHORIZATION)
public class AppUserController {
private final AppUserService appUserService;
@Inner
@GetMapping("/info/{username}")
public R info(@PathVariable String username) {
AppUser user = appUserService.getOne(Wrappers.<AppUser>query()
.lambda()
.eq(AppUser::getUsername, username)
.or()
.eq(AppUser::getPhone, username));
if (user == null) {
return R.failed(MsgUtils.getMessage(ErrorCodes.APP_USER_USERINFO_EMPTY, username));
}
return R.ok(appUserService.findUserInfo(user));
}
/**
* 获取当前用户全部信息
* @return 用户信息
*/
@GetMapping(value = { "/info" })
public R info() {
String username = SecurityUtils.getUser().getUsername();
AppUser user = appUserService.getOne(Wrappers.<AppUser>query().lambda().eq(AppUser::getUsername, username));
if (user == null) {
return R.failed(MsgUtils.getMessage(ErrorCodes.SYS_USER_QUERY_ERROR));
}
return R.ok(appUserService.findUserInfo(user));
}
/**
* 分页查询
* @param page 分页对象
* @param appUserDTO app用户表
* @return
*/
@Operation(summary = "分页查询", description = "分页查询")
@GetMapping("/page")
public R getAppUserPage(Page page, AppUserDTO appUserDTO) {
return R.ok(appUserService.getUsersWithRolePage(page, appUserDTO));
}
/**
* 通过id查询app用户表
* @param userId id
* @return R
*/
@Operation(summary = "通过id查询", description = "通过id查询")
@GetMapping("/details/{userId}")
public R getById(@PathVariable("userId") Long userId) {
return R.ok(appUserService.selectUserVoById(userId));
}
/**
* @return R
*/
@Operation(summary = "通过userName查询", description = "通过userName查询")
@GetMapping("/details")
public R getByUserName(AppUser user) {
AppUser one = appUserService.getOne(Wrappers.query(user), false);
return R.ok(one == null ? null : CommonConstants.SUCCESS);
}
/**
* 新增app用户表
* @param appUser app用户表
* @return R
*/
@Operation(summary = "新增app用户表", description = "新增app用户表")
@SysLog("新增app用户表")
@PostMapping
@PreAuthorize("@pms.hasPermission('app_appuser_add')")
public R save(@RequestBody AppUserDTO appUser) {
appUserService.saveUser(appUser);
return R.ok();
}
/**
* 修改app用户表
* @param appUser app用户表
* @return R
*/
@Operation(summary = "修改app用户表", description = "修改app用户表")
@SysLog("修改app用户表")
@PutMapping
@PreAuthorize("@pms.hasPermission('app_appuser_edit')")
public R updateById(@RequestBody AppUserDTO appUser) {
return R.ok(appUserService.updateUser(appUser));
}
/**
* 通过id删除app用户表
* @param ids userIds
* @return R
*/
@Operation(summary = "通过ids删除app用户表", description = "通过ids删除app用户表")
@SysLog("通过id删除app用户表")
@DeleteMapping
@PreAuthorize("@pms.hasPermission('app_appuser_del')")
public R removeById(@RequestBody Long[] ids) {
return R.ok(appUserService.deleteAppUserByIds(ids));
}
/**
* 导出excel 表格
* @param appUser 查询条件
* @return excel 文件流
*/
@ResponseExcel
@GetMapping("/export")
@PreAuthorize("@pms.hasPermission('app_appuser_export')")
public List<AppUserExcelVO> export(AppUserDTO appUser) {
return appUserService.listUser(appUser);
}
@SysLog("修改个人信息")
@PutMapping("/edit")
public R updateUserInfo(@Valid @RequestBody AppUserDTO userDto) {
if (UserTypeEnum.TOC.getStatus().equals(SecurityUtils.getUser().getUserType())) {
userDto.setUserId(SecurityUtils.getUser().getId());
// TOC 以手机号为key
userDto.setUsername(SecurityUtils.getUser().getUsername());
}
return appUserService.updateUserInfo(userDto);
}
/**
* 导入用户
* @param excelVOList 用户列表
* @param bindingResult 错误信息列表
* @return R
*/
@PostMapping("/import")
@PreAuthorize("@pms.hasPermission('app_appuser_export')")
public R importUser(@RequestExcel List<AppUserExcelVO> excelVOList, BindingResult bindingResult) {
return appUserService.importUser(excelVOList, bindingResult);
}
@Operation(summary = "注册app用户表", description = "注册app用户表")
@SysLog("注册app用户表")
@Inner(value = false)
@PostMapping("/register")
public R register(@RequestBody AppUserDTO appUser) {
return appUserService.registerAppUser(appUser);
}
}
@@ -1,128 +0,0 @@
/*
* Copyright (c) 2018-2025, lengleng All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* Neither the name of the pig4cloud.com developer nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
* Author: lengleng (wangiegie@gmail.com)
*/
package com.pig4cloud.pigx.app.controller;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.pig4cloud.pigx.app.api.entity.AppUserRole;
import com.pig4cloud.pigx.app.service.AppUserRoleService;
import com.pig4cloud.pigx.common.core.util.R;
import com.pig4cloud.pigx.common.excel.annotation.ResponseExcel;
import com.pig4cloud.pigx.common.log.annotation.SysLog;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import org.springframework.http.HttpHeaders;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import java.util.List;
/**
* 用户角色表
*
* @author aeizzz
* @date 2022-12-07 09:52:03
*/
@RestController
@RequiredArgsConstructor
@RequestMapping("/appuserrole")
@Tag(description = "appuserrole", name = "用户角色表管理")
@SecurityRequirement(name = HttpHeaders.AUTHORIZATION)
public class AppUserRoleController {
private final AppUserRoleService appUserRoleService;
/**
* 分页查询
* @param page 分页对象
* @param appUserRole 用户角色表
* @return
*/
@Operation(summary = "分页查询", description = "分页查询")
@GetMapping("/page")
@PreAuthorize("@pms.hasPermission('app_appuserrole_view')")
public R getAppUserRolePage(Page page, AppUserRole appUserRole) {
return R.ok(appUserRoleService.page(page, Wrappers.query(appUserRole)));
}
/**
* 通过id查询用户角色表
* @param userId id
* @return R
*/
@Operation(summary = "通过id查询", description = "通过id查询")
@GetMapping("/{userId}")
@PreAuthorize("@pms.hasPermission('app_appuserrole_view')")
public R getById(@PathVariable("userId") Long userId) {
return R.ok(appUserRoleService.getById(userId));
}
/**
* 新增用户角色表
* @param appUserRole 用户角色表
* @return R
*/
@Operation(summary = "新增用户角色表", description = "新增用户角色表")
@SysLog("新增用户角色表")
@PostMapping
@PreAuthorize("@pms.hasPermission('app_appuserrole_add')")
public R save(@RequestBody AppUserRole appUserRole) {
return R.ok(appUserRoleService.save(appUserRole));
}
/**
* 修改用户角色表
* @param appUserRole 用户角色表
* @return R
*/
@Operation(summary = "修改用户角色表", description = "修改用户角色表")
@SysLog("修改用户角色表")
@PutMapping
@PreAuthorize("@pms.hasPermission('app_appuserrole_edit')")
public R updateById(@RequestBody AppUserRole appUserRole) {
return R.ok(appUserRoleService.updateById(appUserRole));
}
/**
* 通过id删除用户角色表
* @param userId id
* @return R
*/
@Operation(summary = "通过id删除用户角色表", description = "通过id删除用户角色表")
@SysLog("通过id删除用户角色表")
@DeleteMapping("/{userId}")
@PreAuthorize("@pms.hasPermission('app_appuserrole_del')")
public R removeById(@PathVariable Long userId) {
return R.ok(appUserRoleService.removeById(userId));
}
/**
* 导出excel 表格
* @param appUserRole 查询条件
* @return excel 文件流
*/
@ResponseExcel
@GetMapping("/export")
@PreAuthorize("@pms.hasPermission('app_appuserrole_export')")
public List<AppUserRole> export(AppUserRole appUserRole) {
return appUserRoleService.list(Wrappers.query(appUserRole));
}
}
@@ -1,69 +0,0 @@
/*
* Copyright (c) 2018-2025, lengleng All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* Neither the name of the pig4cloud.com developer nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
* Author: lengleng (wangiegie@gmail.com)
*/
package com.pig4cloud.pigx.app.handler;
import com.pig4cloud.pigx.app.api.dto.AppUserInfo;
import com.pig4cloud.pigx.app.api.entity.AppUser;
/**
* @author lengleng
* @date 2018/11/18
* <p>
* 登录处理器
*/
public interface LoginHandler {
/***
* 数据合法性校验
* @param loginStr 通过用户传入获取唯一标识
* @return
*/
Boolean check(String loginStr);
/**
* 通过用户传入获取唯一标识
* @param loginStr
* @return
*/
String identify(String loginStr);
/**
* 通过openId 获取用户信息
* @param identify
* @return
*/
AppUserInfo info(String identify);
/**
* 处理方法
* @param loginStr 登录参数
* @return
*/
AppUserInfo handle(String loginStr);
/**
* 绑定逻辑
* @param user 用户实体
* @param identify 渠道返回唯一标识
* @return
*/
default Boolean bind(AppUser user, String identify) {
return false;
}
}
@@ -1,122 +0,0 @@
/*
* Copyright (c) 2018-2025, lengleng All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* Neither the name of the pig4cloud.com developer nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
* Author: lengleng (wangiegie@gmail.com)
*/
package com.pig4cloud.pigx.app.handler;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.pig4cloud.pigx.app.api.dto.AppUserInfo;
import com.pig4cloud.pigx.app.api.entity.AppSocialDetails;
import com.pig4cloud.pigx.app.api.entity.AppUser;
import com.pig4cloud.pigx.app.mapper.AppSocialDetailsMapper;
import com.pig4cloud.pigx.app.service.AppUserService;
import com.pig4cloud.pigx.common.core.constant.SecurityConstants;
import com.pig4cloud.pigx.common.core.constant.enums.LoginTypeEnum;
import com.pig4cloud.pigx.common.core.exception.CheckedException;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
/**
* @author lengleng
* @date 2019年11月02日
* <p>
* 微信小程序
*/
@Slf4j
@Component("APP-MINI")
@AllArgsConstructor
public class MiniAppLoginHandler extends AbstractLoginHandler {
private final AppUserService appUserService;
private final AppSocialDetailsMapper appSocialDetailsMapper;
/**
* 小程序登录传入code
* <p>
* 通过code 调用qq 获取唯一标识
*
* @param code
* @return
*/
@Override
public String identify(String code) {
AppSocialDetails condition = new AppSocialDetails();
condition.setType(LoginTypeEnum.MINI_APP.getType());
AppSocialDetails socialDetails = appSocialDetailsMapper.selectOne(new QueryWrapper<>(condition));
String url = String.format(SecurityConstants.MINI_APP_AUTHORIZATION_CODE_URL, socialDetails.getAppId(),
socialDetails.getAppSecret(), code);
String result = HttpUtil.get(url);
log.debug("微信小程序响应报文:{}", result);
if (JSONUtil.parseObj(result).containsKey("openid")) {
return JSONUtil.parseObj(result).get("openid").toString();
} else {
log.error("微信小程序登录失败:{}", result);
throw new CheckedException("微信小程序登录失败");
}
}
/**
* openId 获取用户信息
*
* @param openId
* @return
*/
@Override
public AppUserInfo info(String openId) {
AppUser user = appUserService.getOne(Wrappers.<AppUser>query().lambda().eq(AppUser::getWxOpenid, openId));
if (user == null) {
log.info("微信小程序未绑定:{},创建新的用户", openId);
return createAndSaveAppUserInfo(openId);
}
return appUserService.findUserInfo(user);
}
/**
* 绑定逻辑
*
* @param user 用户实体
* @param identify 渠道返回唯一标识
* @return
*/
@Override
public Boolean bind(AppUser user, String identify) {
user.setWxOpenid(identify);
appUserService.updateById(user);
return true;
}
private AppUserInfo createAndSaveAppUserInfo(String openId) {
AppUser appUser = new AppUser();
appUser.setWxOpenid(openId);
appUser.setUsername(openId);
appUser.setCreateBy(openId);
appUser.setUpdateBy(openId);
appUserService.saveOrUpdate(appUser, Wrappers.<AppUser>lambdaQuery().eq(AppUser::getUsername, openId));
AppUserInfo appUserDTO = new AppUserInfo();
appUserDTO.setAppUser(appUser);
return appUserDTO;
}
}
@@ -1,96 +0,0 @@
/*
* Copyright (c) 2018-2025, lengleng All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* Neither the name of the pig4cloud.com developer nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
* Author: lengleng (wangiegie@gmail.com)
*/
package com.pig4cloud.pigx.app.handler;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.pig4cloud.pigx.app.api.dto.AppUserInfo;
import com.pig4cloud.pigx.app.api.entity.AppUser;
import com.pig4cloud.pigx.app.service.AppUserService;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
/**
* @author lengleng
* @date 2018/11/18
*/
@Slf4j
@Component("APP-SMS")
@AllArgsConstructor
public class SmsLoginHandler extends AbstractLoginHandler {
private final AppUserService appUserService;
/**
* 验证码登录传入为手机号 不用不处理
* @param mobile
* @return
*/
@Override
public String identify(String mobile) {
return mobile;
}
/**
* 通过mobile 获取用户信息
* @param identify
* @return
*/
@Override
public AppUserInfo info(String identify) {
AppUser user = appUserService.getOne(Wrappers.<AppUser>query().lambda().eq(AppUser::getPhone, identify));
if (user == null) {
log.info("手机号未注册:{}", identify);
return createAndSaveAppUserInfo(identify);
}
return appUserService.findUserInfo(user);
}
/**
* 创建并插入用户
* @param identify
* @return
*/
private AppUserInfo createAndSaveAppUserInfo(String phone) {
AppUser appUser = new AppUser();
appUser.setUsername(phone);
appUser.setPhone(phone);
appUser.setCreateBy(phone);
appUser.setUpdateBy(phone);
appUserService.saveOrUpdate(appUser, Wrappers.<AppUser>lambdaQuery().eq(AppUser::getPhone, phone));
AppUserInfo appUserDTO = new AppUserInfo();
appUserDTO.setAppUser(appUser);
return appUserDTO;
}
/**
* 绑定逻辑
* @param user 用户实体
* @param identify 渠道返回唯一标识
* @return
*/
@Override
public Boolean bind(AppUser user, String identify) {
user.setPhone(identify);
appUserService.updateById(user);
return true;
}
}
@@ -4,6 +4,9 @@ import com.pig4cloud.pigx.app.api.entity.AppArticleCategoryEntity;
import com.pig4cloud.pigx.common.data.datascope.PigxBaseMapper;
import org.apache.ibatis.annotations.Mapper;
/**
* 文章分类 Mapper。
*/
@Mapper
public interface AppArticleCategoryMapper extends PigxBaseMapper<AppArticleCategoryEntity> {
@@ -4,6 +4,9 @@ import com.pig4cloud.pigx.app.api.entity.AppArticleCollectEntity;
import com.pig4cloud.pigx.common.data.datascope.PigxBaseMapper;
import org.apache.ibatis.annotations.Mapper;
/**
* 文章收藏 Mapper。
*/
@Mapper
public interface AppArticleCollectMapper extends PigxBaseMapper<AppArticleCollectEntity> {
@@ -4,6 +4,9 @@ import com.pig4cloud.pigx.app.api.entity.AppArticleEntity;
import com.pig4cloud.pigx.common.data.datascope.PigxBaseMapper;
import org.apache.ibatis.annotations.Mapper;
/**
* 文章资讯 Mapper。
*/
@Mapper
public interface AppArticleMapper extends PigxBaseMapper<AppArticleEntity> {
@@ -0,0 +1,16 @@
package com.pig4cloud.pigx.app.mapper;
import com.pig4cloud.pigx.app.api.entity.AppContactsEntity;
import com.pig4cloud.pigx.common.data.datascope.PigxBaseMapper;
import org.apache.ibatis.annotations.Mapper;
/**
* 通讯录 Mapper。
* <p>
* 继承 {@link PigxBaseMapper} 后可配合数据权限插件执行范围查询。
*/
@Mapper
public interface AppContactsMapper extends PigxBaseMapper<AppContactsEntity> {
}
@@ -4,6 +4,9 @@ import com.pig4cloud.pigx.app.api.entity.AppPageEntity;
import com.pig4cloud.pigx.common.data.datascope.PigxBaseMapper;
import org.apache.ibatis.annotations.Mapper;
/**
* App 装修页面 Mapper。
*/
@Mapper
public interface AppPageMapper extends PigxBaseMapper<AppPageEntity> {
@@ -0,0 +1,16 @@
package com.pig4cloud.pigx.app.mapper;
import com.pig4cloud.pigx.app.api.entity.AppRoleTabbar;
import com.pig4cloud.pigx.common.data.datascope.PigxBaseMapper;
import org.apache.ibatis.annotations.Mapper;
/**
* App 角色底部导航 Mapper。
*
* @author lengleng
* @date 2026-05-09
*/
@Mapper
public interface AppRoleTabbarMapper extends PigxBaseMapper<AppRoleTabbar> {
}
@@ -1,33 +0,0 @@
/*
* Copyright (c) 2018-2025, lengleng All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* Neither the name of the pig4cloud.com developer nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
* Author: lengleng (wangiegie@gmail.com)
*/
package com.pig4cloud.pigx.app.mapper;
import com.pig4cloud.pigx.app.api.entity.AppSocialDetails;
import com.pig4cloud.pigx.common.data.datascope.PigxBaseMapper;
import org.apache.ibatis.annotations.Mapper;
/**
* 系统社交登录账号表
*
* @author lengleng
* @date 2018-08-16 21:30:41
*/
@Mapper
public interface AppSocialDetailsMapper extends PigxBaseMapper<AppSocialDetails> {
}
@@ -4,6 +4,9 @@ import com.pig4cloud.pigx.app.api.entity.AppTabbarEntity;
import com.pig4cloud.pigx.common.data.datascope.PigxBaseMapper;
import org.apache.ibatis.annotations.Mapper;
/**
* App 底部导航 Mapper。
*/
@Mapper
public interface AppTabbarMapper extends PigxBaseMapper<AppTabbarEntity> {
@@ -1,42 +0,0 @@
/*
* Copyright (c) 2018-2025, lengleng All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* Neither the name of the pig4cloud.com developer nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
* Author: lengleng (wangiegie@gmail.com)
*/
package com.pig4cloud.pigx.app.mapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.pig4cloud.pigx.app.api.dto.AppUserDTO;
import com.pig4cloud.pigx.app.api.entity.AppUser;
import com.pig4cloud.pigx.app.api.vo.AppUserVO;
import com.pig4cloud.pigx.common.data.datascope.PigxBaseMapper;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
/**
* app用户表
*
* @author aeizzz
* @date 2022-12-07 09:52:03
*/
@Mapper
public interface AppUserMapper extends PigxBaseMapper<AppUser> {
IPage<AppUserVO> getUserVosPage(Page page, @Param("query") AppUserDTO appUserDTO);
AppUserVO getUserVoById(Long userId);
}
@@ -1,33 +0,0 @@
/*
* Copyright (c) 2018-2025, lengleng All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* Neither the name of the pig4cloud.com developer nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
* Author: lengleng (wangiegie@gmail.com)
*/
package com.pig4cloud.pigx.app.mapper;
import com.pig4cloud.pigx.app.api.entity.AppUserRole;
import com.pig4cloud.pigx.common.data.datascope.PigxBaseMapper;
import org.apache.ibatis.annotations.Mapper;
/**
* 用户角色表
*
* @author aeizzz
* @date 2022-12-07 09:52:03
*/
@Mapper
public interface AppUserRoleMapper extends PigxBaseMapper<AppUserRole> {
}
@@ -1,8 +1,23 @@
package com.pig4cloud.pigx.app.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.baomidou.mybatisplus.spring.service.IService;
import com.pig4cloud.pigx.app.api.entity.AppArticleCategoryEntity;
import java.util.List;
/**
* 文章分类基础服务。
*/
public interface AppArticleCategoryService extends IService<AppArticleCategoryEntity> {
/**
* 按传入 ID 顺序调整文章分类,保留未选中记录在排序序列中的位置。
* <p>
* 以当前租户内未删除记录的排序值、主键升序为基准,仅重排选中记录占据的位置, 再将全部记录的排序值从 1 起连续重编号。
* @param ids 按目标顺序排列的文章分类 ID;不可为 null 或空,不可包含 null、重复或不可用的 ID
* @throws IllegalArgumentException ID 列表为空、包含 null 或重复值,或指定记录已删除、不属于当前租户 或不存在
* @throws IllegalStateException 批量更新返回失败
*/
void sort(List<Long> ids);
}
@@ -3,8 +3,19 @@ package com.pig4cloud.pigx.app.service;
import com.github.yulichang.base.MPJBaseService;
import com.pig4cloud.pigx.app.api.entity.AppArticleCollectEntity;
/**
* 文章收藏服务。
* <p>
* 收藏记录以当前登录用户为维度保存,同一用户对同一文章只允许收藏一次。
*/
public interface AppArticleCollectService extends MPJBaseService<AppArticleCollectEntity> {
/**
* 保存当前用户的文章收藏。
*
* @param appArticleCollect 收藏请求,需包含文章 ID
* @return true=保存成功,false=已收藏或未保存
*/
Boolean saveArticleCollect(AppArticleCollectEntity appArticleCollect);
}
@@ -1,11 +1,26 @@
package com.pig4cloud.pigx.app.service;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.IService;
import com.baomidou.mybatisplus.spring.service.IService;
import com.pig4cloud.pigx.app.api.entity.AppArticleEntity;
import java.util.List;
/**
* 文章查询与排序服务,供管理端和 App 文章接口调用。
*/
public interface AppArticleService extends IService<AppArticleEntity> {
/**
* 按传入 ID 顺序调整文章,保留未选中记录在排序序列中的位置。
* <p>
* 以当前租户内未删除记录的排序值、主键升序为基准,仅重排选中记录占据的位置, 再将全部记录的排序值从 1 起连续重编号。
* @param ids 按目标顺序排列的文章 ID;不可为 null 或空,不可包含 null、重复或不可用的 ID
* @throws IllegalArgumentException ID 列表为空、包含 null 或重复值,或指定记录已删除、不属于当前租户 或不存在
* @throws IllegalStateException 批量更新返回失败
*/
void sort(List<Long> ids);
/**
* 获取文章并使阅读数+1
* @param id id
@@ -0,0 +1,23 @@
package com.pig4cloud.pigx.app.service;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.spring.service.IService;
import com.pig4cloud.pigx.app.api.entity.AppContactsEntity;
/**
* 应用联系人服务接口
*
* @author lengleng
* @date 2025/05/29
*/
public interface AppContactsService extends IService<AppContactsEntity> {
/**
* 根据应用联系人实体获取分页范围
*
* @param page 分页对象
* @param contactsEntity 应用联系人实体
* @return 分页范围对象
*/
Page pageScope(Page page, AppContactsEntity contactsEntity);
}
@@ -1,11 +1,15 @@
package com.pig4cloud.pigx.app.service;
import com.pig4cloud.pigx.app.api.entity.AppPageEntity;
import com.pig4cloud.pigx.app.api.vo.AppDecorateVO;
import java.util.Map;
/**
* app 页面控制
* App 运行时页面服务。
* <p>
* 负责给移动端聚合首页、装修页、工作台和 Tabbar 配置;
* 后台装修管理接口不直接走这里。
*
* @author lengleng
* @date 2023/6/8
@@ -13,21 +17,33 @@ import java.util.Map;
public interface AppIndexService {
/**
* 首页
* 获取首页基础数据。
*
* @return 首页页面记录和资讯列表
*/
Map<String, Object> index();
/**
* 配置
* @return Map<String, Object>
* 获取运行时配置。
*
* @return 当前访问身份可见的 Tabbar 等配置
*/
Map<String, Object> config();
/**
* 装修
* @param id 装修ID
* @return Map<String, Object>
* 获取指定页面类型的装修页聚合数据。
*
* @param id 页面类型
* @return 装修页聚合数据
*/
AppPageEntity decorate(Integer id);
AppDecorateVO decorate(Integer id);
/**
* 返回工作台页面实体对象。
* <p>
* 工作台按钮权限由 B 端 permission 控制,这里只返回页面装修数据。
*
* @return 工作台页面实体对象
*/
AppPageEntity workbench();
}
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2018-2025, lengleng All rights reserved.
* Copyright (c) 2018-2026, lengleng All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@@ -1,8 +1,14 @@
package com.pig4cloud.pigx.app.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.baomidou.mybatisplus.spring.service.IService;
import com.pig4cloud.pigx.app.api.entity.AppPageEntity;
/**
* App 装修页面基础服务。
* <p>
* 页面组件 JSON 保存在 {@link AppPageEntity#getPageData()},
* 底部 Tabbar 不保存在页面 JSON 中。
*/
public interface AppPageService extends IService<AppPageEntity> {
}
@@ -0,0 +1,40 @@
package com.pig4cloud.pigx.app.service;
import com.baomidou.mybatisplus.spring.service.IService;
import com.pig4cloud.pigx.app.api.dto.AppRoleTabbarDTO;
import com.pig4cloud.pigx.app.api.entity.AppRoleTabbar;
import java.util.List;
/**
* App 角色底部导航服务,管理系统角色与 App 底部导航的授权关系。
*
* @author lengleng
*/
public interface AppRoleTabbarService extends IService<AppRoleTabbar> {
/**
* 查询指定角色已授权的底部导航 ID 列表。
*
* @param roleId 系统角色 ID
* @return 底部导航 ID 列表
*/
List<Long> listTabbarIdsByRoleId(Long roleId);
/**
* 查询指定角色列表已授权的底部导航 ID 列表。
*
* @param roleIds 系统角色 ID 列表
* @return 底部导航 ID 列表
*/
List<Long> listTabbarIdsByRoleIds(List<Long> roleIds);
/**
* 保存角色底部导航授权。
*
* @param dto 角色底部导航配置
* @return 操作结果
*/
Boolean saveRoleTabbars(AppRoleTabbarDTO dto);
}
@@ -1,47 +0,0 @@
/*
* Copyright (c) 2018-2025, lengleng All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* Neither the name of the pig4cloud.com developer nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
* Author: lengleng (wangiegie@gmail.com)
*/
package com.pig4cloud.pigx.app.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.pig4cloud.pigx.app.api.dto.AppUserInfo;
import com.pig4cloud.pigx.app.api.entity.AppSocialDetails;
/**
* 系统社交登录账号表
*
* @author lengleng
* @date 2018-08-16 21:30:41
*/
public interface AppSocialDetailsService extends IService<AppSocialDetails> {
/**
* 绑定社交账号
* @param state 类型
* @param code code
* @return
*/
Boolean bindSocial(String state, String code);
/**
* 根据入参查询用户信息
* @param inStr
* @return
*/
AppUserInfo getUserInfo(String inStr);
}
@@ -1,8 +1,11 @@
package com.pig4cloud.pigx.app.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.baomidou.mybatisplus.spring.service.IService;
import com.pig4cloud.pigx.app.api.entity.AppTabbarEntity;
/**
* App 底部导航基础服务。
*/
public interface AppTabbarService extends IService<AppTabbarEntity> {
}
@@ -1,31 +0,0 @@
/*
* Copyright (c) 2018-2025, lengleng All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* Neither the name of the pig4cloud.com developer nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
* Author: lengleng (wangiegie@gmail.com)
*/
package com.pig4cloud.pigx.app.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.pig4cloud.pigx.app.api.entity.AppUserRole;
/**
* 用户角色表
*
* @author aeizzz
* @date 2022-12-07 09:52:03
*/
public interface AppUserRoleService extends IService<AppUserRole> {
}
@@ -1,61 +0,0 @@
/*
* Copyright (c) 2018-2025, lengleng All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* Neither the name of the pig4cloud.com developer nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
* Author: lengleng (wangiegie@gmail.com)
*/
package com.pig4cloud.pigx.app.service;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.IService;
import com.pig4cloud.pigx.app.api.dto.AppUserDTO;
import com.pig4cloud.pigx.app.api.dto.AppUserInfo;
import com.pig4cloud.pigx.app.api.entity.AppUser;
import com.pig4cloud.pigx.app.api.vo.AppUserExcelVO;
import com.pig4cloud.pigx.app.api.vo.AppUserVO;
import com.pig4cloud.pigx.common.core.util.R;
import org.springframework.validation.BindingResult;
import java.util.List;
/**
* app用户表
*
* @author aeizzz
* @date 2022-12-07 09:52:03
*/
public interface AppUserService extends IService<AppUser> {
Boolean updateUser(AppUserDTO appUser);
Boolean saveUser(AppUserDTO appUser);
List<AppUserExcelVO> listUser(AppUserDTO appUser);
IPage getUsersWithRolePage(Page page, AppUserDTO appUserDTO);
AppUserInfo findUserInfo(AppUser user);
R updateUserInfo(AppUserDTO userDto);
AppUserVO selectUserVoById(Long userId);
Boolean deleteAppUserByIds(Long[] ids);
R importUser(List<AppUserExcelVO> excelVOList, BindingResult bindingResult);
R registerAppUser(AppUserDTO appUser);
}
@@ -1,10 +1,18 @@
package com.pig4cloud.pigx.app.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.spring.service.impl.ServiceImpl;
import com.pig4cloud.pigx.app.api.entity.AppArticleCategoryEntity;
import com.pig4cloud.pigx.app.mapper.AppArticleCategoryMapper;
import com.pig4cloud.pigx.app.service.AppArticleCategoryService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
/**
* 文章分类表
@@ -16,4 +24,37 @@ import org.springframework.stereotype.Service;
public class AppArticleCategoryServiceImpl extends ServiceImpl<AppArticleCategoryMapper, AppArticleCategoryEntity>
implements AppArticleCategoryService {
/**
* 按传入 ID 顺序调整文章分类,保留未选中记录在排序序列中的位置。
* <p>
* 以当前租户内未删除记录的排序值、主键升序为基准,仅重排选中记录占据的位置, 再将全部记录的排序值从 1 起连续重编号。
* @param ids 按目标顺序排列的文章分类 ID;不可为 null 或空,不可包含 null、重复或不可用的 ID
* @throws IllegalArgumentException ID 列表为空、包含 null 或重复值,或指定记录已删除、不属于当前租户 或不存在
* @throws IllegalStateException 批量更新返回失败
*/
@Override
@Transactional(rollbackFor = Exception.class)
public void sort(List<Long> ids) {
Assert.notEmpty(ids, "排序记录不能为空");
Set<Long> selected = new HashSet<>(ids);
Assert.isTrue(!selected.contains(null) && selected.size() == ids.size(), "排序记录无效");
// 锁定统一顺序,避免重复排序值和分页边界导致拖动后顺序丢失。
List<AppArticleCategoryEntity> records = list(Wrappers.<AppArticleCategoryEntity>lambdaQuery()
.orderByAsc(AppArticleCategoryEntity::getSort, AppArticleCategoryEntity::getId)
.last("FOR UPDATE"));
long matched = records.stream().filter(row -> selected.contains(row.getId())).count();
Assert.isTrue(matched == ids.size(), "记录已变更,请刷新后重试");
List<AppArticleCategoryEntity> updates = new ArrayList<>();
int next = 0;
for (int i = 0; i < records.size(); i++) {
AppArticleCategoryEntity current = records.get(i);
Long id = selected.contains(current.getId()) ? ids.get(next++) : current.getId();
AppArticleCategoryEntity update = new AppArticleCategoryEntity();
update.setId(id);
update.setSort(i + 1);
updates.add(update);
}
Assert.state(updateBatchById(updates), "排序保存失败");
}
}
@@ -1,7 +1,7 @@
package com.pig4cloud.pigx.app.service.impl;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.baomidou.mybatisplus.spring.service.impl.ServiceImpl;
import com.pig4cloud.pigx.app.api.entity.AppArticleCollectEntity;
import com.pig4cloud.pigx.app.mapper.AppArticleCollectMapper;
import com.pig4cloud.pigx.app.service.AppArticleCollectService;
@@ -9,26 +9,36 @@ import com.pig4cloud.pigx.common.security.util.SecurityUtils;
import org.springframework.stereotype.Service;
/**
* 文章收藏表
* 文章收藏服务实现。
* <p>
* 收藏归属当前登录用户,保存前会校验同一用户是否已经收藏过同一文章。
*
* @author pig
* @date 2023-06-16 14:33:41
*/
@Service
public class AppArticleCollectServiceImpl extends ServiceImpl<AppArticleCollectMapper, AppArticleCollectEntity>
implements AppArticleCollectService {
implements AppArticleCollectService {
@Override
public Boolean saveArticleCollect(AppArticleCollectEntity appArticleCollect) {
Long id = SecurityUtils.getUser().getId();
appArticleCollect.setUserId(id);
/**
* 保存当前登录用户的文章收藏。
*
* @param appArticleCollect 收藏请求,业务上只需要文章 ID,用户 ID 由登录态写入
* @return true=收藏成功,false=已经收藏
*/
@Override
public Boolean saveArticleCollect(AppArticleCollectEntity appArticleCollect) {
Long id = SecurityUtils.getUser().getId();
appArticleCollect.setUserId(id);
this.saveOrUpdate(appArticleCollect,
Wrappers.<AppArticleCollectEntity>lambdaQuery()
.eq(AppArticleCollectEntity::getUserId, id)
.eq(AppArticleCollectEntity::getArticleId, appArticleCollect.getArticleId()));
if (baseMapper.exists(Wrappers.<AppArticleCollectEntity>lambdaQuery()
.eq(AppArticleCollectEntity::getUserId, id)
.eq(AppArticleCollectEntity::getArticleId, appArticleCollect.getArticleId()))) {
return Boolean.FALSE;
}
return Boolean.TRUE;
}
return this.save(appArticleCollect);
}
}
@@ -3,7 +3,7 @@ package com.pig4cloud.pigx.app.service.impl;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.baomidou.mybatisplus.spring.service.impl.ServiceImpl;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import com.pig4cloud.pigx.app.api.entity.AppArticleCategoryEntity;
import com.pig4cloud.pigx.app.api.entity.AppArticleCollectEntity;
@@ -13,11 +13,20 @@ import com.pig4cloud.pigx.app.mapper.AppArticleMapper;
import com.pig4cloud.pigx.app.service.AppArticleService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.Objects;
/**
* 文章资讯
* 文章资讯服务实现。
* <p>
* 负责文章列表关联分类名称、文章详情访问次数递增,以及当前用户收藏状态补充。
*
* @author pig
* @date 2023-06-07 16:32:35
@@ -30,14 +39,17 @@ public class AppArticleServiceImpl extends ServiceImpl<AppArticleMapper, AppArti
private final AppArticleCollectMapper collectMapper;
/**
* 获取文章并使阅读数+1
* @param id id
* @return
* 获取文章详情,并尝试将阅读数加 1。
* <p>
* 如果传入用户 ID,会额外查询该用户是否已收藏当前文章。 阅读数更新使用当前 visit 值作为条件,降低并发覆盖风险。
* @param id 文章 ID
* @param userId 当前用户 ID,可为空
* @return 文章详情
*/
@Override
public AppArticleEntity getArticleAndIncrById(Long id, Long userId) {
AppArticleEntity appArticleEntity = baseMapper.selectById(id);
// 查询是否收藏了
// 登录用户访问详情时,补充当前用户是否已收藏该文章。
if (Objects.nonNull(userId)) {
boolean exists = collectMapper.exists(Wrappers.<AppArticleCollectEntity>lambdaQuery()//
.eq(AppArticleCollectEntity::getArticleId, appArticleEntity.getId())//
@@ -45,10 +57,9 @@ public class AppArticleServiceImpl extends ServiceImpl<AppArticleMapper, AppArti
appArticleEntity.setCollect(exists);
}
// TODO 更新条件需要根据其他指数限制
Integer nowVisit = appArticleEntity.getVisit();
appArticleEntity.setVisit(nowVisit + 1);
// 乐观锁
// 使用旧 visit 值作为更新条件,避免并发访问时直接覆盖最新阅读数。
baseMapper.update(appArticleEntity,
Wrappers.<AppArticleEntity>lambdaQuery()
.eq(AppArticleEntity::getId, id)
@@ -57,10 +68,10 @@ public class AppArticleServiceImpl extends ServiceImpl<AppArticleMapper, AppArti
}
/**
* 分页查询文章列表 包含分类名称
* 分页查询文章列表,并关联分类名称。
* @param page 分页参数
* @param appArticle 文章查询条件
* @return
* @return 文章分页结果,包含分类名称 cname
*/
@Override
public Page pageAndCname(Page page, AppArticleEntity appArticle) {
@@ -70,8 +81,42 @@ public class AppArticleServiceImpl extends ServiceImpl<AppArticleMapper, AppArti
.leftJoin(AppArticleCategoryEntity.class, AppArticleCategoryEntity::getId, AppArticleEntity::getCid)
.like(StrUtil.isNotBlank(appArticle.getAuthor()), AppArticleEntity::getAuthor, appArticle.getAuthor())
.like(StrUtil.isNotBlank(appArticle.getTitle()), AppArticleEntity::getTitle, appArticle.getTitle())
.eq(Objects.nonNull(appArticle.getCid()), AppArticleEntity::getCid, appArticle.getCid());
.eq(Objects.nonNull(appArticle.getCid()), AppArticleEntity::getCid, appArticle.getCid())
.orderByAsc(AppArticleEntity::getSort, AppArticleEntity::getId);
return this.page(page, wrapper);
}
/**
* 按传入 ID 顺序调整文章,保留未选中记录在排序序列中的位置。
* <p>
* 以当前租户内未删除记录的排序值、主键升序为基准,仅重排选中记录占据的位置, 再将全部记录的排序值从 1 起连续重编号。
* @param ids 按目标顺序排列的文章 ID;不可为 null 或空,不可包含 null、重复或不可用的 ID
* @throws IllegalArgumentException ID 列表为空、包含 null 或重复值,或指定记录已删除、不属于当前租户 或不存在
* @throws IllegalStateException 批量更新返回失败
*/
@Override
@Transactional(rollbackFor = Exception.class)
public void sort(List<Long> ids) {
Assert.notEmpty(ids, "排序记录不能为空");
Set<Long> selected = new HashSet<>(ids);
Assert.isTrue(!selected.contains(null) && selected.size() == ids.size(), "排序记录无效");
// 锁定统一顺序,避免重复排序值和分页边界导致拖动后顺序丢失。
List<AppArticleEntity> records = list(Wrappers.<AppArticleEntity>lambdaQuery()
.orderByAsc(AppArticleEntity::getSort, AppArticleEntity::getId)
.last("FOR UPDATE"));
long matched = records.stream().filter(row -> selected.contains(row.getId())).count();
Assert.isTrue(matched == ids.size(), "记录已变更,请刷新后重试");
List<AppArticleEntity> updates = new ArrayList<>();
int next = 0;
for (int i = 0; i < records.size(); i++) {
AppArticleEntity current = records.get(i);
Long id = selected.contains(current.getId()) ? ids.get(next++) : current.getId();
AppArticleEntity update = new AppArticleEntity();
update.setId(id);
update.setSort(i + 1);
updates.add(update);
}
Assert.state(updateBatchById(updates), "排序保存失败");
}
}
@@ -0,0 +1,42 @@
package com.pig4cloud.pigx.app.service.impl;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.spring.service.impl.ServiceImpl;
import com.pig4cloud.pigx.app.api.entity.AppContactsEntity;
import com.pig4cloud.pigx.app.mapper.AppContactsMapper;
import com.pig4cloud.pigx.app.service.AppContactsService;
import com.pig4cloud.pigx.common.data.datascope.DataScope;
import com.pig4cloud.pigx.common.security.util.SecurityUtils;
import org.springframework.stereotype.Service;
/**
* 通讯录服务实现类
* <p>
* 通讯录列表会结合系统数据权限,只返回当前登录用户可见范围内的数据。
*
* @author lengleng
* @date 2025/05/29
*/
@Service
public class AppContactsServiceImpl extends ServiceImpl<AppContactsMapper, AppContactsEntity> implements AppContactsService {
/**
* 根据查询条件分页查询通讯录,并应用数据权限范围。
*
* @param page 分页对象
* @param appContacts 应用联系人实体
* @return 分页范围对象
*/
@Override
public Page pageScope(Page page, AppContactsEntity appContacts) {
LambdaQueryWrapper<AppContactsEntity> wrapper = Wrappers.lambdaQuery();
wrapper.like(StrUtil.isNotBlank(appContacts.getContactName()), AppContactsEntity::getContactName, appContacts.getContactName());
wrapper.like(StrUtil.isNotBlank(appContacts.getContactPhone()), AppContactsEntity::getContactPhone, appContacts.getContactPhone());
DataScope dataScope = new DataScope();
dataScope.setUsername(SecurityUtils.getUser().getUsername());
return baseMapper.selectPageByScope(page, wrapper, dataScope);
}
}
@@ -4,10 +4,15 @@ import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.pig4cloud.pigx.app.api.entity.AppArticleEntity;
import com.pig4cloud.pigx.app.api.entity.AppPageEntity;
import com.pig4cloud.pigx.app.api.entity.AppTabbarEntity;
import com.pig4cloud.pigx.app.api.enums.PageTypeEnums;
import com.pig4cloud.pigx.app.api.vo.AppDecorateVO;
import com.pig4cloud.pigx.app.mapper.AppArticleMapper;
import com.pig4cloud.pigx.app.mapper.AppPageMapper;
import com.pig4cloud.pigx.app.mapper.AppTabbarMapper;
import com.pig4cloud.pigx.app.service.AppIndexService;
import com.pig4cloud.pigx.app.service.AppRoleTabbarService;
import com.pig4cloud.pigx.common.core.constant.CommonConstants;
import com.pig4cloud.pigx.common.security.util.SecurityUtils;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
@@ -16,58 +21,119 @@ import java.util.List;
import java.util.Map;
/**
* app 页面控制
* App首页服务实现类
* 实现AppIndexService接口,提供首页数据、导航栏配置以及页面配置等功能。
* <p>
* 该实现面向移动端运行时:Tabbar 会按公开/登录角色授权规则过滤,
* 页面装修数据则保持原始组件 JSON,不在这里做页面组件级权限裁剪。
*
* @author lengleng
* @date 2023/6/8
*/
@Service
@RequiredArgsConstructor
public class AppIndexServiceImpl implements AppIndexService {
private final AppArticleMapper appArticleMapper;
private final AppTabbarMapper appTabbarMapper;
private final AppTabbarMapper appTabbarMapper;
private final AppPageMapper appPageMapper;
private final AppPageMapper appPageMapper;
private final AppArticleMapper appArticleMapper;
/**
* 商城首页 首页数据
*/
@Override
public Map<String, Object> index() {
Map<String, Object> response = new LinkedHashMap<>();
AppPageEntity appPageEntity = appPageMapper.selectById(1);
List<AppArticleEntity> articleList = appArticleMapper
.selectList(Wrappers.<AppArticleEntity>lambdaQuery().orderByDesc(AppArticleEntity::getSort));
response.put("pages", appPageEntity);
response.put("article", articleList);
return response;
private final AppRoleTabbarService appRoleTabbarService;
/**
* 获取商城首页基础数据。
* <p>
* 旧版首页接口返回首页装修页记录和资讯列表;新版装修页推荐使用 {@link #decorate(Integer)}。
*
* @return 首页页面数据和资讯列表
*/
@Override
public Map<String, Object> index() {
Map<String, Object> response = new LinkedHashMap<>();
AppPageEntity appPageEntity = appPageMapper.selectOne(Wrappers.<AppPageEntity>lambdaQuery()
.eq(AppPageEntity::getPageType, PageTypeEnums.HOME.getPageType())
.orderByDesc(AppPageEntity::getCreateTime),
false
);
List<AppArticleEntity> articleList = appArticleMapper
.selectList(Wrappers.<AppArticleEntity>lambdaQuery().orderByDesc(AppArticleEntity::getSort));
response.put("pages", appPageEntity);
response.put("article", articleList);
return response;
}
/**
* 获取运行时配置。
* <p>
* 当前只包含 Tabbar,并按 {@link #listAuthorizedTabbar()} 的规则过滤。
*
* @return 运行时配置集合
*/
@Override
public Map<String, Object> config() {
Map<String, Object> response = new LinkedHashMap<>();
response.put("tabbar", listAuthorizedTabbar());
return response;
}
/**
* 根据页面类型获取最新装修页,并附加当前访问身份可见的 Tabbar。
*
* @param pageType 页面类型
* @return 装修页聚合数据
*/
@Override
public AppDecorateVO decorate(Integer pageType) {
AppPageEntity appPageEntity = appPageMapper.selectOne(
Wrappers.<AppPageEntity>lambdaQuery()
.eq(AppPageEntity::getPageType, pageType)
.orderByDesc(AppPageEntity::getCreateTime),
false
);
return AppDecorateVO.of(appPageEntity, listAuthorizedTabbar());
}
/**
* 获取工作台页面数据。
* <p>
* 工作台内部按钮权限复用系统菜单 permission,这里不再读取 App 专属菜单授权。
*
* @return 工作台页面实体
*/
@Override
public AppPageEntity workbench() {
return appPageMapper.selectOne(
Wrappers.<AppPageEntity>lambdaQuery()
.eq(AppPageEntity::getPageType, PageTypeEnums.WORKBENCH.getPageType())
.orderByDesc(AppPageEntity::getCreateTime),
false
);
}
/**
* 查询当前访问身份可见的 Tabbar。
* <p>
* 匿名访问只返回 {@code loginFlag=0} 的公开 Tabbar;登录访问从 token authorities
* 解析角色 ID,再读取 {@code app_role_tabbar} 中授权的 Tabbar,避免跨库 join upms 的
* {@code sys_user_role}。
*
* @return 当前可见的 Tabbar 列表
*/
private List<AppTabbarEntity> listAuthorizedTabbar() {
List<Long> roleIds = SecurityUtils.getUser() == null ? List.of() : SecurityUtils.getRoleIds();
List<Long> tabbarIds = appRoleTabbarService.listTabbarIdsByRoleIds(roleIds);
return appTabbarMapper.selectList(Wrappers.<AppTabbarEntity>lambdaQuery()
.and(wrapper -> {
wrapper.eq(AppTabbarEntity::getLoginFlag, CommonConstants.STATUS_NORMAL);
if (!tabbarIds.isEmpty()) {
wrapper.or().in(AppTabbarEntity::getId, tabbarIds);
}
})
.orderByAsc(AppTabbarEntity::getSortOrder)
.orderByAsc(AppTabbarEntity::getId));
}
/**
* 配置
* @return Map<String, Object>
*/
@Override
public Map<String, Object> config() {
Map<String, Object> response = new LinkedHashMap<>();
List<AppTabbarEntity> tabbarEntityList = appTabbarMapper.selectList(Wrappers.emptyWrapper());
response.put("tabbar", tabbarEntityList);
return response;
}
/**
* 装修
*
* @author fzr
* @param id 主键
* @return Map<String, Object>
*/
@Override
public AppPageEntity decorate(Integer id) {
return appPageMapper.selectById(id);
}
}
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2018-2025, lengleng All rights reserved.
* Copyright (c) 2018-2026, lengleng All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@@ -20,21 +20,24 @@ package com.pig4cloud.pigx.app.service.impl;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.toolkit.StringPool;
import com.pig4cloud.pigx.app.api.enums.AppErrorCodes;
import com.pig4cloud.pigx.app.service.AppMobileService;
import com.pig4cloud.pigx.common.core.constant.CacheConstants;
import com.pig4cloud.pigx.common.core.constant.SecurityConstants;
import com.pig4cloud.pigx.common.core.constant.enums.LoginTypeEnum;
import com.pig4cloud.pigx.common.core.exception.ErrorCodes;
import com.pig4cloud.pigx.common.core.util.MsgUtils;
import com.pig4cloud.pigx.common.core.util.R;
import com.pig4cloud.pigx.common.data.cache.RedisUtils;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import java.util.concurrent.TimeUnit;
/**
* App 手机验证码服务实现。
* <p>
* 验证码按 {@code 验证码缓存前缀 + 登录类型 + 手机号} 写入 Redis,
* 过期时间使用统一安全常量配置。
*
* @author lengleng
* @date 2018/11/14
* <p>
@@ -45,29 +48,28 @@ import java.util.concurrent.TimeUnit;
@AllArgsConstructor
public class AppMobileServiceImpl implements AppMobileService {
private final StringRedisTemplate redisTemplate;
/**
* 发送手机验证码。
* <p>
* 如果验证码仍在有效期内,则拒绝重复发送。当前实现只生成并缓存验证码,
* 后续接入短信网关时应在生成验证码后调用真实发送能力。
*
* @param mobile 手机号
* @return true=生成成功,false=验证码未过期
*/
@Override
public R<Boolean> sendSmsCode(String mobile) {
String codeObj = RedisUtils.get(CacheConstants.SMS_CODE_KEY + LoginTypeEnum.APPSMS.getType() + StringPool.AT + mobile);
/**
* 发送手机验证码 TODO: 调用短信网关发送验证码,测试返回前端
* @param mobile mobile
* @return code
*/
@Override
public R<Boolean> sendSmsCode(String mobile) {
String codeObj = redisTemplate.opsForValue()
.get(CacheConstants.DEFAULT_CODE_KEY + LoginTypeEnum.APPSMS.getType() + StringPool.AT + mobile);
if (StrUtil.isNotBlank(codeObj)) {
log.info("手机号验证码未过期:{},{}", mobile, codeObj);
return R.ok(Boolean.FALSE, MsgUtils.getMessage(AppErrorCodes.APP_SMS_OFTEN));
}
if (StrUtil.isNotBlank(codeObj)) {
log.info("手机号验证码未过期:{},{}", mobile, codeObj);
return R.ok(Boolean.FALSE, MsgUtils.getMessage(ErrorCodes.SYS_APP_SMS_OFTEN));
}
String code = RandomUtil.randomNumbers(Integer.parseInt(SecurityConstants.CODE_SIZE));
log.debug("手机号生成验证码成功:{},{}", mobile, code);
redisTemplate.opsForValue()
.set(CacheConstants.DEFAULT_CODE_KEY + LoginTypeEnum.APPSMS.getType() + StringPool.AT + mobile, code,
SecurityConstants.CODE_TIME, TimeUnit.SECONDS);
return R.ok(Boolean.TRUE, code);
}
String code = RandomUtil.randomNumbers(Integer.parseInt(SecurityConstants.CODE_SIZE));
log.debug("手机号生成验证码成功:{},{}", mobile, code);
RedisUtils.set(CacheConstants.SMS_CODE_KEY + LoginTypeEnum.APPSMS.getType() + StringPool.AT + mobile, code, SecurityConstants.CODE_TIME);
return R.ok(Boolean.TRUE);
}
}
@@ -1,6 +1,6 @@
package com.pig4cloud.pigx.app.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.baomidou.mybatisplus.spring.service.impl.ServiceImpl;
import com.pig4cloud.pigx.app.api.entity.AppPageEntity;
import com.pig4cloud.pigx.app.mapper.AppPageMapper;
import com.pig4cloud.pigx.app.service.AppPageService;
@@ -1,113 +0,0 @@
/*
* Copyright (c) 2018-2025, lengleng All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* Neither the name of the pig4cloud.com developer nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
* Author: lengleng (wangiegie@gmail.com)
*/
package com.pig4cloud.pigx.app.service.impl;
import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.pig4cloud.pigx.app.api.entity.AppRole;
import com.pig4cloud.pigx.app.api.vo.AppRoleExcelVO;
import com.pig4cloud.pigx.app.mapper.AppRoleMapper;
import com.pig4cloud.pigx.app.service.AppRoleService;
import com.pig4cloud.pigx.common.core.exception.ErrorCodes;
import com.pig4cloud.pigx.common.core.util.MsgUtils;
import com.pig4cloud.pigx.common.core.util.R;
import com.pig4cloud.pigx.common.excel.vo.ErrorMessage;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.validation.BindingResult;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
/**
* app角色表
*
* @author aeizzz
* @date 2022-12-07 09:52:03
*/
@Service
@AllArgsConstructor
public class AppRoleServiceImpl extends ServiceImpl<AppRoleMapper, AppRole> implements AppRoleService {
@Override
public List<AppRole> findRolesByUserId(Long userId) {
return baseMapper.listRolesByUserId(userId);
}
/**
* 删除用户的同时,把role_menu关系删除
* @param ids roleIds
*/
@Override
public Boolean deleteRoleByIds(Long[] ids) {
this.removeBatchByIds(CollUtil.toList(ids));
return Boolean.TRUE;
}
/**
* 导入角色
* @param excelVOList
* @param bindingResult
* @return
*/
@Override
public R importRole(List<AppRoleExcelVO> excelVOList, BindingResult bindingResult) {
// 通用校验获取失败的数据
List<ErrorMessage> errorMessageList = (List<ErrorMessage>) bindingResult.getTarget();
// 个性化校验逻辑
List<AppRole> roleList = this.list();
// 执行数据插入操作 组装 RoleDto
for (AppRoleExcelVO excel : excelVOList) {
Set<String> errorMsg = new HashSet<>();
// 检验角色名称或者角色编码是否存在
boolean existRole = roleList.stream()
.anyMatch(appRole -> excel.getRoleName().equals(appRole.getRoleName())
|| excel.getRoleCode().equals(appRole.getRoleCode()));
if (existRole) {
errorMsg.add(MsgUtils.getMessage(ErrorCodes.SYS_ROLE_NAMEORCODE_EXISTING, excel.getRoleName(),
excel.getRoleCode()));
}
// 数据合法情况
if (CollUtil.isEmpty(errorMsg)) {
insertExcelRole(excel);
}
else {
// 数据不合法情况
errorMessageList.add(new ErrorMessage(excel.getLineNum(), errorMsg));
}
}
if (CollUtil.isNotEmpty(errorMessageList)) {
return R.failed(errorMessageList);
}
return R.ok();
}
private void insertExcelRole(AppRoleExcelVO excel) {
AppRole appRole = new AppRole();
appRole.setRoleName(excel.getRoleName());
appRole.setRoleDesc(excel.getRoleDesc());
appRole.setRoleCode(excel.getRoleCode());
this.save(appRole);
}
}
@@ -0,0 +1,83 @@
package com.pig4cloud.pigx.app.service.impl;
import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.spring.service.impl.ServiceImpl;
import com.pig4cloud.pigx.app.api.dto.AppRoleTabbarDTO;
import com.pig4cloud.pigx.app.api.entity.AppRoleTabbar;
import com.pig4cloud.pigx.app.mapper.AppRoleTabbarMapper;
import com.pig4cloud.pigx.app.service.AppRoleTabbarService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
import java.util.Objects;
/**
* App 角色底部导航服务实现。
* <p>
* 只访问 app-server 本库的 {@code app_role_tabbar}。运行时角色来源由 Spring Security
* token authorities 提供,避免 app-server 跨库 join upms 的用户角色表。
*
* @author lengleng
* @date 2026-05-09
*/
@Service
@RequiredArgsConstructor
public class AppRoleTabbarServiceImpl extends ServiceImpl<AppRoleTabbarMapper, AppRoleTabbar>
implements AppRoleTabbarService {
@Override
public List<Long> listTabbarIdsByRoleId(Long roleId) {
return roleId == null ? List.of() : listTabbarIdsByRoleIds(List.of(roleId));
}
/**
* 根据多个角色查询可见 Tabbar。
* <p>
* 一个用户可能同时拥有多个角色,因此这里会先对角色 ID 去重,再对查询出的 Tabbar ID 去重。
*
* @param roleIds 系统角色 ID 列表
* @return 去重后的 Tabbar ID 列表
*/
@Override
public List<Long> listTabbarIdsByRoleIds(List<Long> roleIds) {
if (CollUtil.isEmpty(roleIds)) {
return List.of();
}
List<Long> distinctRoleIds = roleIds.stream().filter(Objects::nonNull).distinct().toList();
if (CollUtil.isEmpty(distinctRoleIds)) {
return List.of();
}
return this.list(Wrappers.<AppRoleTabbar>lambdaQuery().in(AppRoleTabbar::getRoleId, distinctRoleIds))
.stream()
.map(AppRoleTabbar::getTabbarId)
.filter(Objects::nonNull)
.distinct()
.toList();
}
@Override
@Transactional(rollbackFor = Exception.class)
public Boolean saveRoleTabbars(AppRoleTabbarDTO dto) {
// 覆盖保存:后台每次提交的是该角色完整授权结果,先删旧关系再写新关系。
this.remove(Wrappers.<AppRoleTabbar>lambdaQuery().eq(AppRoleTabbar::getRoleId, dto.getRoleId()));
if (CollUtil.isEmpty(dto.getTabbarIds())) {
return Boolean.TRUE;
}
List<AppRoleTabbar> records = dto.getTabbarIds()
.stream()
.filter(Objects::nonNull)
.distinct()
.map(tabbarId -> {
AppRoleTabbar roleTabbar = new AppRoleTabbar();
roleTabbar.setRoleId(dto.getRoleId());
roleTabbar.setTabbarId(tabbarId);
return roleTabbar;
})
.toList();
return this.saveBatch(records);
}
}
@@ -1,86 +0,0 @@
/*
* Copyright (c) 2018-2025, lengleng All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* Neither the name of the pig4cloud.com developer nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
* Author: lengleng (wangiegie@gmail.com)
*/
package com.pig4cloud.pigx.app.service.impl;
import com.baomidou.mybatisplus.core.toolkit.StringPool;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.pig4cloud.pigx.app.api.dto.AppUserInfo;
import com.pig4cloud.pigx.app.api.entity.AppSocialDetails;
import com.pig4cloud.pigx.app.api.entity.AppUser;
import com.pig4cloud.pigx.app.handler.LoginHandler;
import com.pig4cloud.pigx.app.mapper.AppSocialDetailsMapper;
import com.pig4cloud.pigx.app.mapper.AppUserMapper;
import com.pig4cloud.pigx.app.service.AppSocialDetailsService;
import com.pig4cloud.pigx.common.core.constant.CacheConstants;
import com.pig4cloud.pigx.common.security.util.SecurityUtils;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cache.CacheManager;
import org.springframework.stereotype.Service;
import java.util.Map;
/**
* @author lengleng
* @date 2018年08月16日
*/
@Slf4j
@AllArgsConstructor
@Service("appSocialDetailsService")
public class AppSocialDetailsServiceImpl extends ServiceImpl<AppSocialDetailsMapper, AppSocialDetails>
implements AppSocialDetailsService {
private final Map<String, LoginHandler> loginHandlerMap;
private final CacheManager cacheManager;
private final AppUserMapper appUserMapper;
/**
* 绑定社交账号
* @param type type
* @param code code
* @return
*/
@Override
public Boolean bindSocial(String type, String code) {
LoginHandler loginHandler = loginHandlerMap.get(type);
// 绑定逻辑
String identify = loginHandler.identify(code);
AppUser user = appUserMapper.selectById(SecurityUtils.getUser().getId());
loginHandler.bind(user, identify);
// 更新緩存
cacheManager.getCache(CacheConstants.USER_DETAILS_MINI).evict(user.getUsername());
return Boolean.TRUE;
}
/**
* 根据入参查询用户信息
* @param inStr TYPE@code
* @return
*/
@Override
public AppUserInfo getUserInfo(String inStr) {
String[] inStrs = inStr.split(StringPool.AT);
String type = inStrs[0];
String loginStr = inStr.substring(type.length() + 1);
return loginHandlerMap.get(type).handle(loginStr);
}
}
@@ -1,6 +1,6 @@
package com.pig4cloud.pigx.app.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.baomidou.mybatisplus.spring.service.impl.ServiceImpl;
import com.pig4cloud.pigx.app.api.entity.AppTabbarEntity;
import com.pig4cloud.pigx.app.mapper.AppTabbarMapper;
import com.pig4cloud.pigx.app.service.AppTabbarService;
@@ -1,34 +0,0 @@
/*
* Copyright (c) 2018-2025, lengleng All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* Neither the name of the pig4cloud.com developer nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
* Author: lengleng (wangiegie@gmail.com)
*/
package com.pig4cloud.pigx.app.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.pig4cloud.pigx.app.api.entity.AppUserRole;
import com.pig4cloud.pigx.app.mapper.AppUserRoleMapper;
import com.pig4cloud.pigx.app.service.AppUserRoleService;
import org.springframework.stereotype.Service;
/**
* 用户角色表
*
* @author aeizzz
* @date 2022-12-07 09:52:03
*/
@Service
public class AppUserRoleServiceImpl extends ServiceImpl<AppUserRoleMapper, AppUserRole> implements AppUserRoleService {
}
@@ -1,318 +0,0 @@
/*
* Copyright (c) 2018-2025, lengleng All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* Neither the name of the pig4cloud.com developer nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
* Author: lengleng (wangiegie@gmail.com)
*/
package com.pig4cloud.pigx.app.service.impl;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.StringPool;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.pig4cloud.pigx.app.api.dto.AppUserDTO;
import com.pig4cloud.pigx.app.api.dto.AppUserInfo;
import com.pig4cloud.pigx.app.api.entity.AppRole;
import com.pig4cloud.pigx.app.api.entity.AppUser;
import com.pig4cloud.pigx.app.api.entity.AppUserRole;
import com.pig4cloud.pigx.app.api.vo.AppUserExcelVO;
import com.pig4cloud.pigx.app.api.vo.AppUserVO;
import com.pig4cloud.pigx.app.mapper.AppUserMapper;
import com.pig4cloud.pigx.app.service.AppRoleService;
import com.pig4cloud.pigx.app.service.AppUserRoleService;
import com.pig4cloud.pigx.app.service.AppUserService;
import com.pig4cloud.pigx.common.core.constant.CacheConstants;
import com.pig4cloud.pigx.common.core.constant.CommonConstants;
import com.pig4cloud.pigx.common.core.constant.enums.LoginTypeEnum;
import com.pig4cloud.pigx.common.core.constant.enums.UserTypeEnum;
import com.pig4cloud.pigx.common.core.exception.ErrorCodes;
import com.pig4cloud.pigx.common.core.util.MsgUtils;
import com.pig4cloud.pigx.common.core.util.R;
import com.pig4cloud.pigx.common.excel.vo.ErrorMessage;
import com.pig4cloud.pigx.common.security.service.PigxUser;
import com.pig4cloud.pigx.common.security.util.SecurityUtils;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.cache.Cache;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.validation.BindingResult;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
/**
* app用户表
*
* @author aeizzz
* @date 2022-12-07 09:52:03
*/
@Service
@AllArgsConstructor
@Slf4j
public class AppUserServiceImpl extends ServiceImpl<AppUserMapper, AppUser> implements AppUserService {
private static final PasswordEncoder ENCODER = new BCryptPasswordEncoder();
private final AppUserRoleService appUserRoleService;
private final StringRedisTemplate redisTemplate;
private final AppRoleService appRoleService;
private final CacheManager cacheManager;
/**
* 更新用户
* @param userDTO
* @return
*/
@Override
@CacheEvict(value = CacheConstants.USER_DETAILS_MINI, key = "#userDTO.username")
public Boolean updateUser(AppUserDTO userDTO) {
AppUser appUser = new AppUser();
BeanUtils.copyProperties(userDTO, appUser);
if (StrUtil.isNotBlank(userDTO.getPassword())) {
appUser.setPassword(ENCODER.encode(userDTO.getPassword()));
}
this.updateById(appUser);
appUserRoleService.remove(Wrappers.<AppUserRole>lambdaQuery().eq(AppUserRole::getUserId, appUser.getUserId()));
userDTO.getRole().forEach(roleId -> {
AppUserRole appUserRole = new AppUserRole();
appUserRole.setRoleId(roleId);
appUserRole.setUserId(userDTO.getUserId());
appUserRole.insert();
});
return Boolean.TRUE;
}
/**
* 新增用户
* @param userDTO
* @return
*/
@Override
public Boolean saveUser(AppUserDTO userDTO) {
AppUser appUser = new AppUser();
BeanUtils.copyProperties(userDTO, appUser);
appUser.setDelFlag(CommonConstants.STATUS_NORMAL);
appUser.setPassword(ENCODER.encode(userDTO.getPassword()));
baseMapper.insert(appUser);
// 如果角色为空,赋默认角色
if (CollUtil.isNotEmpty(userDTO.getRole())) {
List<AppUserRole> userRoleList = userDTO.getRole().stream().map(roleId -> {
AppUserRole userRole = new AppUserRole();
userRole.setUserId(appUser.getUserId());
userRole.setRoleId(roleId);
return userRole;
}).collect(Collectors.toList());
appUserRoleService.saveBatch(userRoleList);
}
return Boolean.TRUE;
}
/**
* 查询全部的用户
* @param appUser
* @return
*/
@Override
public List<AppUserExcelVO> listUser(AppUserDTO appUser) {
List<AppUser> appUsers = baseMapper.selectList(null);
List<AppUserExcelVO> appUserExcelVOS = appUsers.stream().map(item -> {
AppUserExcelVO appUserExcelVO = new AppUserExcelVO();
BeanUtils.copyProperties(item, appUserExcelVO);
return appUserExcelVO;
}).collect(Collectors.toList());
return appUserExcelVOS;
}
@Override
public IPage getUsersWithRolePage(Page page, AppUserDTO appUserDTO) {
return baseMapper.getUserVosPage(page, appUserDTO);
}
@Override
public AppUserInfo findUserInfo(AppUser user) {
AppUserInfo info = new AppUserInfo();
info.setAppUser(user);
// 设置角色列表 (ID)
List<Long> roleIds = appRoleService.findRolesByUserId(user.getUserId())
.stream()
.map(AppRole::getRoleId)
.collect(Collectors.toList());
info.setRoles(ArrayUtil.toArray(roleIds, Long.class));
// 设置权限列表(menu.permission)
Set<String> permissions = new HashSet<>();
info.setPermissions(ArrayUtil.toArray(permissions, String.class));
return info;
}
@Override
@CacheEvict(value = CacheConstants.USER_DETAILS_MINI, key = "#userDto.username")
public R updateUserInfo(AppUserDTO userDto) {
// C端客户修改手机号需要判断验证码是否正确
PigxUser user = SecurityUtils.getUser();
if (UserTypeEnum.TOC.getStatus().equals(user.getUserType()) && StrUtil.isNotBlank(userDto.getPhone())) {
String key = CacheConstants.DEFAULT_CODE_KEY + LoginTypeEnum.APPSMS.getType() + StringPool.AT
+ userDto.getPhone();
String codeObj = redisTemplate.opsForValue().get(key);
if (!userDto.getMobileCode().equals(codeObj)) {
return R.failed("验证码错误");
}
}
// 更新密码
if (StrUtil.isNotBlank(userDto.getPassword())) {
userDto.setPassword(ENCODER.encode(userDto.getPassword()));
}
AppUser appUser = baseMapper.selectById(userDto.getUserId());
BeanUtils.copyProperties(userDto, appUser);
return R.ok(this.updateById(appUser));
}
@Override
public AppUserVO selectUserVoById(Long userId) {
return baseMapper.getUserVoById(userId);
}
/**
* 删除user用户同时删除user-role关系表
* @param ids userIds
*/
@Override
public Boolean deleteAppUserByIds(Long[] ids) {
Cache cache = cacheManager.getCache(CacheConstants.USER_DETAILS_MINI);
for (AppUser appUser : baseMapper.selectBatchIds(CollUtil.toList(ids))) {
cache.evict(appUser.getUsername());
}
// 删除用户关联表
this.appUserRoleService
.remove(Wrappers.<AppUserRole>lambdaQuery().in(AppUserRole::getUserId, CollUtil.toList(ids)));
this.removeBatchByIds(CollUtil.toList(ids));
return Boolean.TRUE;
}
@Override
public R registerAppUser(AppUserDTO appUser) {
List<AppUser> appUserList = baseMapper
.selectList(Wrappers.<AppUser>lambdaQuery().eq(AppUser::getPhone, appUser.getPhone()));
if (CollUtil.isNotEmpty(appUserList)) {
return R.failed("手机号已注册,请使用验证码直接登录");
}
String key = CacheConstants.DEFAULT_CODE_KEY + LoginTypeEnum.APPSMS.getType() + StringPool.AT
+ appUser.getPhone();
String codeObj = redisTemplate.opsForValue().get(key);
if (!appUser.getMobileCode().equals(codeObj)) {
return R.failed("验证码错误");
}
AppUser app = new AppUser();
BeanUtils.copyProperties(appUser, app);
appUser.setUsername(app.getPhone());
appUser.setDelFlag(CommonConstants.STATUS_NORMAL);
appUser.setPassword(ENCODER.encode(appUser.getPassword()));
baseMapper.insert(appUser);
return null;
}
/**
* @param excelVOList
* @param bindingResult
* @return
*/
@Override
public R importUser(List<AppUserExcelVO> excelVOList, BindingResult bindingResult) {
// 通用校验获取失败的数据
List<ErrorMessage> errorMessageList = (List<ErrorMessage>) bindingResult.getTarget();
// 执行数据插入操作 组装 UserDto
for (AppUserExcelVO excel : excelVOList) {
// 个性化校验逻辑
List<AppUser> userList = this.list();
List<AppRole> roleList = appRoleService.list();
Set<String> errorMsg = new HashSet<>();
// 校验用户名是否存在
boolean exsitUserName = userList.stream()
.anyMatch(sysUser -> excel.getUsername().equals(sysUser.getUsername()));
if (exsitUserName) {
errorMsg.add(MsgUtils.getMessage(ErrorCodes.SYS_USER_USERNAME_EXISTING, excel.getUsername()));
}
// 判断输入的角色名称列表是否合法
List<String> roleNameList = StrUtil.split(excel.getRoleNameList(), StrUtil.COMMA);
List<AppRole> roleCollList = roleList.stream()
.filter(role -> roleNameList.stream().anyMatch(name -> role.getRoleName().equals(name)))
.collect(Collectors.toList());
if (roleCollList.size() != roleNameList.size()) {
errorMsg.add(MsgUtils.getMessage(ErrorCodes.SYS_ROLE_ROLENAME_INEXISTENCE, excel.getRoleNameList()));
}
// 数据合法情况
if (CollUtil.isEmpty(errorMsg)) {
insertExcelUser(excel, roleCollList);
}
else {
// 数据不合法情况
errorMessageList.add(new ErrorMessage(excel.getLineNum(), errorMsg));
}
}
if (CollUtil.isNotEmpty(errorMessageList)) {
return R.failed(errorMessageList);
}
return R.ok(null, MsgUtils.getMessage(ErrorCodes.SYS_USER_IMPORT_SUCCEED));
}
private void insertExcelUser(AppUserExcelVO excel, List<AppRole> roleCollList) {
AppUserDTO userDTO = new AppUserDTO();
userDTO.setUsername(excel.getUsername());
userDTO.setPhone(excel.getPhone());
userDTO.setNickname(excel.getNickname());
userDTO.setName(excel.getName());
userDTO.setEmail(excel.getEmail());
// 批量导入初始密码为手机号
userDTO.setPassword(userDTO.getPhone());
// 根据角色名称查询角色ID
List<Long> roleIdList = roleCollList.stream().map(AppRole::getRoleId).collect(Collectors.toList());
userDTO.setRole(roleIdList);
// 插入用户
this.saveUser(userDTO);
}
}
@@ -13,11 +13,11 @@
<property name="CONSOLE_LOG_PATTERN"
value="${CONSOLE_LOG_PATTERN:-%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){faint} %clr(${LOG_LEVEL_PATTERN:-%5p}) %clr(${PID:- }){magenta} %clr(---){faint} %clr([%15.15t]){faint} %clr(%-40.40logger{39}){cyan} %clr(:){faint} %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}}"/>
<!-- 彩色日志依赖的渲染类 -->
<conversionRule conversionWord="clr" converterClass="org.springframework.boot.logging.logback.ColorConverter"/>
<conversionRule conversionWord="clr" class="org.springframework.boot.logging.logback.ColorConverter"/>
<conversionRule conversionWord="wex"
converterClass="org.springframework.boot.logging.logback.WhitespaceThrowableProxyConverter"/>
class="org.springframework.boot.logging.logback.WhitespaceThrowableProxyConverter"/>
<conversionRule conversionWord="wEx"
converterClass="org.springframework.boot.logging.logback.ExtendedWhitespaceThrowableProxyConverter"/>
class="org.springframework.boot.logging.logback.ExtendedWhitespaceThrowableProxyConverter"/>
<!-- Console log output -->
<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.pig4cloud.pigx.app.mapper.AppContactsMapper">
<resultMap id="appContactsMap" type="com.pig4cloud.pigx.app.api.entity.AppContactsEntity">
<id property="id" column="id"/>
<result property="contactName" column="contact_name"/>
<result property="contactPhone" column="contact_phone"/>
<result property="remark" column="remark"/>
<result property="createBy" column="create_by"/>
<result property="createTime" column="create_time"/>
<result property="updateBy" column="update_by"/>
<result property="updateTime" column="update_time"/>
<result property="delFlag" column="del_flag"/>
<result property="tenantId" column="tenant_id"/>
</resultMap>
</mapper>
@@ -1,52 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~
~ Copyright (c) 2018-2025, lengleng All rights reserved.
~
~ Redistribution and use in source and binary forms, with or without
~ modification, are permitted provided that the following conditions are met:
~
~ Redistributions of source code must retain the above copyright notice,
~ this list of conditions and the following disclaimer.
~ Redistributions in binary form must reproduce the above copyright
~ notice, this list of conditions and the following disclaimer in the
~ documentation and/or other materials provided with the distribution.
~ Neither the name of the pig4cloud.com developer nor the names of its
~ contributors may be used to endorse or promote products derived from
~ this software without specific prior written permission.
~ Author: lengleng (wangiegie@gmail.com)
~
-->
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.pig4cloud.pigx.app.mapper.AppRoleMapper">
<resultMap id="appRoleMap" type="com.pig4cloud.pigx.app.api.entity.AppRole">
<id property="roleId" column="role_id"/>
<result property="roleName" column="role_name"/>
<result property="roleCode" column="role_code"/>
<result property="roleDesc" column="role_desc"/>
<result property="createBy" column="create_by"/>
<result property="updateBy" column="update_by"/>
<result property="createTime" column="create_time"/>
<result property="updateTime" column="update_time"/>
<result property="delFlag" column="del_flag"/>
<result property="tenantId" column="tenant_id"/>
</resultMap>
<select id="listRolesByUserId" resultType="com.pig4cloud.pigx.app.api.entity.AppRole">
SELECT app_role.role_id,
app_role.role_name,
app_role.role_code,
app_role.role_desc,
app_role.create_time,
app_role.update_time,
app_role.del_flag
FROM app_role,
app_user_role
WHERE app_role.role_id = app_user_role.role_id
AND app_role.del_flag = '0'
and app_user_role.user_id = #{userId}
</select>
</mapper>
@@ -9,6 +9,8 @@
<result property="selected" column="selected"/>
<result property="unselected" column="unselected"/>
<result property="link" column="link"/>
<result property="sortOrder" column="sort_order"/>
<result property="loginFlag" column="login_flag"/>
<result property="createBy" column="create_by"/>
<result property="createTime" column="create_time"/>
<result property="updateBy" column="update_by"/>
@@ -1,97 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~
~ Copyright (c) 2018-2025, lengleng All rights reserved.
~
~ Redistribution and use in source and binary forms, with or without
~ modification, are permitted provided that the following conditions are met:
~
~ Redistributions of source code must retain the above copyright notice,
~ this list of conditions and the following disclaimer.
~ Redistributions in binary form must reproduce the above copyright
~ notice, this list of conditions and the following disclaimer in the
~ documentation and/or other materials provided with the distribution.
~ Neither the name of the pig4cloud.com developer nor the names of its
~ contributors may be used to endorse or promote products derived from
~ this software without specific prior written permission.
~ Author: lengleng (wangiegie@gmail.com)
~
-->
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.pig4cloud.pigx.app.mapper.AppUserMapper">
<resultMap id="appUserMap" type="com.pig4cloud.pigx.app.api.vo.AppUserVO">
<id property="userId" column="user_id"/>
<result property="username" column="username"/>
<result property="password" column="password"/>
<result property="phone" column="phone"/>
<result property="avatar" column="avatar"/>
<result property="nickname" column="nickname"/>
<result property="name" column="name"/>
<result property="email" column="email"/>
<result property="createTime" column="create_time"/>
<result property="delFlag" column="del_flag"/>
<result property="tenantId" column="tenant_id"/>
<result property="lastModifiedTime" column="last_modified_time"/>
<collection property="roleList" ofType="com.pig4cloud.pigx.app.api.entity.AppRole"
select="com.pig4cloud.pigx.app.mapper.AppRoleMapper.listRolesByUserId" column="user_id">
</collection>
</resultMap>
<select id="getUserVosPage" resultMap="appUserMap">
select
u.user_id,
u.username,
u.password,
u.phone,
u.avatar,
u.create_time,
u.del_flag,
u.lock_flag,
u.tenant_id,
u.nickname,
u.name,
u.email
from app_user u
<where>
u.del_flag = '0'
<if test="query.username != null and query.username != ''">
<bind name="usernameLike" value="'%'+query.username+'%'"/>
AND u.username LIKE #{usernameLike}
</if>
</where>
</select>
<sql id="userRoleDeptSql">
u.user_id,
u.username,
u.password,
u.salt,
u.phone,
u.avatar,
u.wx_openid,
u.del_flag,
u.lock_flag,
u.tenant_id,
u.nickname,
u.name,
u.email,
u.create_by,
u.create_time ucreate_time,
u.update_time uupdate_time,
r.role_id
</sql>
<select id="getUserVoById" resultMap="appUserMap">
SELECT
<include refid="userRoleDeptSql"/>
FROM
app_user u
LEFT JOIN app_user_role urole ON urole.user_id = u.user_id
LEFT JOIN app_role r ON r.role_id = urole.role_id
WHERE
u.user_id = #{id}
</select>
</mapper>
Loaded 100 of 1720 files, more files were not shown because too many files have changed in this diff. Show more