110 Commits

Author SHA1 Message Date
geht
5cb24c582d MES审批复用钉钉审批设置 2026-06-10 16:57:07 +08:00
geht
617d47a3db MES本地审批共用钉钉审批等配置 2026-06-10 16:33:44 +08:00
geht
c4447b91dd Merge branch '20260519-3.9.2版本-葛昊天分支' 2026-06-10 15:43:15 +08:00
geht
39a9bd83f1 钉钉审批功能完善、混炼示方新增是否附加料 2026-06-10 15:41:02 +08:00
geht
de48bd2324 集群问题处理 2026-06-09 18:26:31 +08:00
geht
5b8bd2797a 钉钉回调事件处理 2026-06-09 17:52:33 +08:00
geht
fd5205e33e 钉钉审批配置优化 2026-06-08 19:05:29 +08:00
geht
1d0b4c9fbb 增强审批流管理能力,新增审批环节的 stageKey 区分关键环节与过路审批节点,完善钉钉回调日志记录,停用部分 HTTP 回调接口,改由集成方案驱动审批流,优化审批注册中心的查询逻辑。 2026-06-05 19:05:48 +08:00
geht
b9be88ae3f Merge branch '20260519-3.9.2版本-葛昊天分支' 2026-06-05 10:45:42 +08:00
geht
fc4e3211ad 新增钉钉 Stream SDK 依赖,支持无 HTTP 上下文的后台线程显式传入 token 进行审批回调。同时,完善了 MES 审批台账功能,新增审批记录同步、批量发起审批时的门禁与台账写入逻辑,增强了系统的审批流管理能力。 2026-06-05 10:44:30 +08:00
geht
4785c55e52 新增钉钉审批模板配置功能,包括相关实体、控制器、服务及接口的实现,支持审批模板的增删改查及从钉钉同步模板,增强了系统的审批流管理能力。 2026-06-04 11:38:08 +08:00
457089e271 设备对应部位功能新增 2026-06-03 16:28:57 +08:00
geht
1c5cede957 Merge branch '20260519-3.9.2版本-葛昊天分支' 2026-06-02 18:54:07 +08:00
geht
2d142dbc9c 新增多个控制器以支持密炼相关功能,包括报警记录、自动卸料日志、物料对应、称量校验日志、密炼机动作状态等,提供分页查询、通过ID查询及导出Excel功能,增强系统的可用性与数据管理能力。 2026-06-02 18:53:40 +08:00
a65ae7be60 Merge branch 'main' of http://27.223.88.102:33000/chenx/qhmes 2026-06-02 16:55:53 +08:00
38f22ef8bd Merge branch 'main' into 生产及设备基础资料 2026-06-02 16:40:56 +08:00
69a60ca07b Merge branch 'main' of http://27.223.88.102:33000/chenx/qhmes 2026-06-02 16:38:48 +08:00
a08ca8985a 胶料小料锁定原因、锁定日志添加 2026-06-02 16:37:48 +08:00
29efd6694f 胶料维护规则 2026-06-02 16:32:10 +08:00
geht
e92cab555f 新增密炼物料皮重策略功能,包括相关实体、控制器、服务及接口的实现,支持桌面端免密CRUD操作,优化了打印记录的字段填充逻辑,提升了用户体验。 2026-06-02 16:30:46 +08:00
geht
fef7d25e3c 新增密炼物料皮重策略功能,包括相关实体、服务、控制器及接口,支持桌面端免密CRUD操作,优化打印记录与原料入场记录的衍生字段填充逻辑,提升用户体验。 2026-06-02 16:28:51 +08:00
b8b06a881a 胶料小料锁定原因新增 2026-06-02 15:29:16 +08:00
3f2c486f04 停机记录新增,设备管理查询条件完善 2026-06-02 14:11:35 +08:00
geht
37239e1b0a 更新混炼示方功能,优化胶料信息同步逻辑,新增胶料字段复制机制,提升胶料生成与更新的准确性与一致性。 2026-06-02 10:33:36 +08:00
geht
3586f86ea6 Merge branch '20260519-3.9.2版本-葛昊天分支' 2026-06-01 11:30:44 +08:00
geht
bfb00804e6 更新混炼示方功能,优化胶料信息同步与删除逻辑,新增胶料类别名称匹配支持,调整选料弹窗以支持胶料查询,提升用户体验。 2026-06-01 11:30:07 +08:00
geht
767214b7db Merge branch '20260519-3.9.2版本-葛昊天分支' 2026-05-29 18:57:49 +08:00
geht
0ff4a201b0 完善MES审批流设计功能,新增审批可选回调动作、发起人撤销及催办接口,支持审批状态恢复与联动回退,提升审批流程的灵活性与用户体验。 2026-05-29 18:57:09 +08:00
71f9dab1be Merge remote-tracking branch 'origin/20260519-3.9.2版本-葛昊天分支' 2026-05-29 15:51:29 +08:00
geht
aefa44b8a9 新增MES审批流设计功能,包括审批流定义、审批实例管理及审批办理接口,支持可视化设计与业务单据联动,提升审批流程的灵活性与用户体验。 2026-05-29 15:49:10 +08:00
4aa9952b26 Merge branch 'main' of http://27.223.88.102:33000/chenx/qhmes 2026-05-29 15:49:02 +08:00
c8ce7a6fa3 母胶计划、终胶计划 2026-05-29 15:48:58 +08:00
geht
94132ea8da Merge branch '20260519-3.9.2版本-葛昊天分支' 2026-05-29 10:50:42 +08:00
geht
e281f7fd92 新增IM聊天群管理接口,包括群聊详情、添加成员、移除成员、修改群名称、转让群主、退出群聊及解散群聊功能,提升群聊管理体验。 2026-05-29 10:49:11 +08:00
geht
22814cb1a7 增强IM聊天功能,支持群聊会话的打开与处理,优化消息过滤逻辑,提升用户体验。 2026-05-29 10:28:58 +08:00
geht
44a5868349 实现IM聊天群聊功能,包括群聊列表和创建群聊接口,优化消息处理和未读消息统计,增强用户体验。 2026-05-28 18:46:27 +08:00
71f6cfed3d Merge remote-tracking branch 'origin/生产及设备基础资料' 2026-05-28 17:16:45 +08:00
84821955c9 胶料快检记录新增 2026-05-28 17:15:20 +08:00
geht
a63cd6ad1a IM聊天功能优化 2026-05-28 17:08:34 +08:00
geht
3539eab924 新增IM聊天 2026-05-28 14:37:05 +08:00
geht
99e574f600 新增架子车数设定 2026-05-28 10:38:57 +08:00
geht
f3e0ffca4c 优化混炼示方日志记录逻辑,直接从入参构建快照以减少数据库查询,提高性能与效率。 2026-05-27 17:38:55 +08:00
geht
d2c1d4443b 优化配方日志查询功能,新增默认排序和参数处理逻辑,提升数据获取效率与用户体验。 2026-05-26 17:53:24 +08:00
geht
9e36435a72 新增配方日志查询功能,记录配方和混炼示方的创建、更新与删除操作,增强数据追溯能力。 2026-05-26 17:50:55 +08:00
geht
c70f7b2b90 新增混炼示方密炼PS审批联动同步审批人功能,优化混炼示方的编辑与删除权限控制,增强用户交互体验。 2026-05-26 11:15:00 +08:00
geht
7786369a63 Merge branch '20260519-3.9.2版本-葛昊天分支' 2026-05-26 11:09:41 +08:00
geht
e6241c16c7 优化混炼示方中换算系数和配方参数的数值展示与输入解析,调整相关字段的小数精度,增强用户交互体验。 2026-05-26 10:26:53 +08:00
geht
51cac2c17a 新增混炼示方选择弹窗及相关功能,支持规格选择与参照新增,优化用户交互体验。 2026-05-26 10:21:56 +08:00
geht
a579f0e15c 新增参照历史混合步骤功能,包含混合步骤复制、状态解析及历史步骤选择弹窗,优化用户交互体验。 2026-05-26 10:10:28 +08:00
geht
41f8cef462 优化混炼示方 2026-05-26 09:52:42 +08:00
geht
72aeee0f10 优化种类生成逻辑 2026-05-25 20:42:13 +08:00
geht
441c19e87a 实现密炼物料种类配置关联解析功能,新增种类查找表加载与解析接口,优化选料弹窗层级与刷新功能,增强用户体验与系统稳定性。 2026-05-25 20:29:07 +08:00
geht
dc3f305303 优化混炼示方,新增种类配置 2026-05-25 19:44:14 +08:00
589961397c 快检实验标准新增 2026-05-25 16:01:14 +08:00
837a85f7ba Merge branch '生产及设备基础资料' 2026-05-25 11:02:18 +08:00
a6579f019a 快检实验方法新增 2026-05-25 11:01:26 +08:00
af8bf14b5e 胶料快检实验类型、胶料快检数据点、胶料快检实验方法新增 2026-05-25 11:01:00 +08:00
geht
c85657d199 新增混炼示方生成预览与批量创建功能,优化相关字段及用户交互,修复界面显示问题,增强系统稳定性和用户体验。 2026-05-22 19:43:41 +08:00
geht
f3e3a99ebc Merge remote-tracking branch 'origin/main' into 20260519-3.9.2版本-葛昊天分支 2026-05-22 16:35:11 +08:00
geht
d7fd9c6037 新增MES混炼示方模块,包括主表及子表结构、控制器、服务和映射器的实现,支持增删改查功能,优化数据验证和用户体验,增强系统稳定性。 2026-05-22 16:34:33 +08:00
geht
680eb6c54c 更新配合示方模块,新增密炼PS审批联动功能,支持状态与审批人同步,优化相关服务实现,调整数据库状态字典,增强系统数据一致性和用户体验。 2026-05-22 12:15:05 +08:00
b56bf74bb8 Merge branch 'main' of http://27.223.88.102:33000/chenx/qhmes 2026-05-22 12:04:56 +08:00
467c49f432 密炼机动作维护、日罐物料对应信息、密炼机条件维护、生产订单、金蝶对接配置 2026-05-22 12:04:46 +08:00
fa1c5c9b42 Merge remote-tracking branch 'origin/生产及设备基础资料' 2026-05-22 09:58:43 +08:00
geht
442b31ad37 Merge branch '20260519-3.9.2版本-葛昊天分支' 2026-05-21 18:50:05 +08:00
geht
89407d1f1d 新增配合示方模块,包括主子表结构、控制器、服务及映射器的实现,支持增删改查功能,优化胶料代号生成逻辑及相关字段,增强数据验证和用户体验。 2026-05-21 18:49:20 +08:00
2496d05349 设备点检记录新增 2026-05-21 17:54:57 +08:00
874e513c90 Merge branch 'main' of http://27.223.88.102:33000/chenx/qhmes 2026-05-21 10:04:24 +08:00
e678276aba 密炼机动作维护、日罐物料对应关系 2026-05-21 10:04:06 +08:00
geht
a10aae420a 更新胶料信息处理逻辑,优化字段描述及数据验证,增强系统稳定性和用户体验。 2026-05-20 19:06:58 +08:00
geht
9f37292eea 更新胶料编码为胶料别名,调整相关字段和描述,新增数据库字段以支持胶料信息补全 2026-05-20 16:12:38 +08:00
geht
1a4027086c Merge branch 'main' into 20260519-3.9.2版本-葛昊天分支 2026-05-20 15:59:44 +08:00
geht
031725de7e 新增MES密炼物料替代对应关系及开炼机参数维护模块,包括相关实体、控制器、服务和映射器的实现,支持增删改查及数据验证功能。 2026-05-20 15:56:27 +08:00
09c58f80eb 胶料信息更换分类字典 2026-05-20 15:55:54 +08:00
geht
cd3194d1a6 Merge remote-tracking branch 'origin/main' into 20260519-3.9.2版本-葛昊天分支 2026-05-20 15:49:36 +08:00
c09ca584c3 解决终端汉字乱码问题 2026-05-20 15:37:39 +08:00
0e6eba8cf4 Merge branch 'main' of http://27.223.88.102:33000/chenx/qhmes 2026-05-20 15:30:46 +08:00
34b6ed4478 胶料信息 2026-05-20 15:30:42 +08:00
1b45d6124d 设备点检配置新增 2026-05-20 15:30:37 +08:00
geht
27c2ed898c 添加兼容旧库的桌面端登录设置配置项,确保在缺失时自动补全相关 sys_config 项 2026-05-20 12:29:10 +08:00
geht
e5e8341b3e 修正日志输出中的访问URL提示信息,去掉多余的冒号以提高可读性。 2026-05-20 11:59:21 +08:00
geht
39c990b2ae 修正日志输出中的访问URL提示信息,调整标点符号以提高可读性。 2026-05-20 11:58:43 +08:00
b86c94add9 Merge remote-tracking branch 'origin/main' into 生产及设备基础资料 2026-05-20 11:35:54 +08:00
84286a6769 配置地址 2026-05-20 11:29:52 +08:00
9fe1da209d 点检及保养项目新增 2026-05-19 15:20:51 +08:00
geht
ddc10cf7ea 桌面端打包,降低版本。 2026-05-19 14:13:32 +08:00
d57cb6cb8c eclipse文件隐藏 2026-05-19 12:01:13 +08:00
geht
be169ed131 Update VSCode configuration, enhance Java project settings, and modify application properties for improved logging and encoding support 2026-05-19 11:22:53 +08:00
geht
500de8961d Merge branch '升级分支' 2026-05-19 10:23:33 +08:00
e0833d3cbd Merge branch '生产及设备基础资料' 2026-05-19 10:17:03 +08:00
5fd499e095 升级配置修改 2026-05-19 10:11:20 +08:00
geht
3eed489df6 修正日志输出中的访问URL提示信息,去掉多余的冒号以提高可读性。 2026-05-18 20:15:44 +08:00
geht
feb857f7a0 修正日志输出中的访问URL提示信息,调整标点符号以提高可读性。 2026-05-18 20:15:16 +08:00
geht
ba80c96294 更新到3.9.2 2026-05-18 20:05:46 +08:00
geht
140f4a816e 新增 CLAUDE.md 文件以提供项目指导,添加 .claudeignore 文件以排除不必要的文件,更新 pom.xml 版本至 3.9.2,修复多个路径遍历和 SQL 注入漏洞,优化字典翻译切面逻辑,增强文件上传和下载的安全性,新增音频文件类型支持,改进动态数据源的安全校验。 2026-05-18 20:05:03 +08:00
geht
67ca5287e2 修改后端运行端口,改为8888,前端调用后端接口也同步改成8888 2026-05-18 18:20:10 +08:00
geht
50b74f484f 实现原料入场条码与批次号生成逻辑,离线时支持本地兜底;并在后续处理前补充入场记录必要标识校验。 2026-05-18 17:57:47 +08:00
geht
a102ed46f2 Merge branch 'SCADA系统测试' 2026-05-18 17:32:22 +08:00
geht
2ed796c1a1 桌面端打包优化 2026-05-18 17:31:18 +08:00
4a4bcb3fab Merge branch 'main' of http://27.223.88.102:33000/chenx/qhmes 2026-05-18 16:59:45 +08:00
a1181e49fc 原材料送检记录 2026-05-18 16:59:34 +08:00
34009b8900 设备管理基础资料准备 2026-05-18 16:36:04 +08:00
geht
c11f3104cb 优化桌面端无用菜单和地磅数据可手动功能。 2026-05-18 15:55:11 +08:00
5800b6b61c 原材料汇总页面修复 2026-05-18 14:26:02 +08:00
geht
878961649d Merge branch 'main' of http://27.223.88.102:33000/chenx/qhmes 2026-05-18 14:19:41 +08:00
geht
9461ba39e0 Update login mini assets: replace logo and ad text images, and enhance home.less styles for better layout and responsiveness. 2026-05-18 14:19:36 +08:00
36015f26d9 Merge remote-tracking branch 'origin/生产及设备基础资料' 2026-05-18 14:17:47 +08:00
6733f5f641 Merge branch 'cxversion' 2026-05-18 14:15:15 +08:00
23a6b717d7 Merge branch 'main' of http://27.223.88.102:33000/chenx/qhmes 2026-05-18 14:14:39 +08:00
a22a573c0d feat(xslmes): 停机分类与设备/工序基础资料菜单及权限完善
新增停机大类、停机类型 CRUD(含 Flyway 与独立 db 脚本);调整工序/设备分类/设备类型菜单归属与权限;同步厂家信息菜单脚本。

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-18 14:02:37 +08:00
1695 changed files with 182626 additions and 5135 deletions

10
.gitignore vendored
View File

@@ -1,10 +1,20 @@
## ide
**/.idea
**/.project
**/.classpath
**/.factorypath
**/.settings/
*.iml
rebel.xml
.project
.classpath
.settings/
.factorypath
**/.settings/
## backend
**/target
**/bin/
**/logs
## front

41
.vscode/launch.json vendored
View File

@@ -1,11 +1,32 @@
{
"configurations": [
{
"type": "java",
"name": "JeecgSystemApplication",
"request": "launch",
"mainClass": "org.jeecg.JeecgSystemApplication",
"projectName": "jeecg-system-start"
}
]
}
"version": "0.2.0",
"configurations": [
{
"type": "chrome",
"request": "launch",
"name": "jeecgboot-vue3: 调试前端 (Chrome)",
"url": "http://localhost:3100",
"webRoot": "${workspaceFolder}/jeecgboot-vue3",
"preLaunchTask": "jeecgboot-vue3: dev"
},
{
"type": "node",
"request": "launch",
"name": "jeecgboot-vue3: dev",
"runtimeExecutable": "pnpm",
"runtimeArgs": ["run", "dev"],
"cwd": "${workspaceFolder}/jeecgboot-vue3",
"console": "integratedTerminal",
"skipFiles": ["<node_internals>/**", "**/node_modules/**"]
},
{
"type": "java",
"name": "JeecgSystemApplication (单体)",
"request": "launch",
"mainClass": "org.jeecg.JeecgSystemApplication",
"projectName": "jeecg-system-start",
"cwd": "${workspaceFolder}/jeecg-boot/jeecg-module-system/jeecg-system-start",
"vmArgs": "-Dfile.encoding=UTF-8 -Dspring.main.banner-mode=log -Dspring.banner.charset=UTF-8 -Dlogging.charset.console=GBK"
}
]
}

34
.vscode/settings.json vendored
View File

@@ -2,7 +2,10 @@
"java.compile.nullAnalysis.mode": "automatic",
"java.jdt.ls.vmargs": "-XX:+UseParallelGC -XX:GCTimeRatio=4 -XX:AdaptiveSizePolicyWeight=90 -Dsun.zip.disableMemoryMapping=true -Xmx4G -Xms100m -Xlog:disable",
"java.import.maven.enabled": true,
"java.configuration.updateBuildConfiguration": "interactive",
"java.configuration.updateBuildConfiguration": "automatic",
"java.autobuild.enabled": true,
"java.import.maven.offline.enabled": false,
"java.configuration.maven.notCoveredPluginExecutionSeverity": "ignore",
"java.jdt.ls.java.home": "C:\\Program Files\\Java\\jdk-17",
"java.configuration.runtimes": [
{
@@ -10,5 +13,32 @@
"path": "C:\\Program Files\\Java\\jdk-17",
"default": true
}
]
],
"java.maven.downloadSources": true,
"java.eclipse.downloadSources": true,
"java.project.importOnFirstTimeStartup": "automatic",
"java.configuration.checkProjectSettingsExclusions": false,
"java.import.exclusions": [
"**/jeecg-server-cloud/**",
"**/jeecg-boot-platform/**",
"**/node_modules/**",
"**/.metadata/**",
"**/archetype-resources/**",
"**/META-INF/maven/**"
],
"java.project.resourceFilters": [
"node_modules",
".git",
"jeecg-server-cloud",
"jeecg-boot-platform"
],
"java.debug.settings.console": "integratedTerminal",
"java.debug.settings.vmArgs": "-Dfile.encoding=UTF-8 -Dspring.main.banner-mode=log -Dspring.banner.charset=UTF-8 -Dlogging.charset.console=GBK",
"terminal.integrated.defaultProfile.windows": "PowerShell",
"terminal.integrated.profiles.windows": {
"PowerShell": {
"source": "PowerShell",
"args": ["-NoExit", "-Command", "chcp 936 | Out-Null"]
}
}
}

39
.vscode/tasks.json vendored
View File

@@ -1,6 +1,27 @@
{
"version": "2.0.0",
"tasks": [
{
"label": "JeecgBoot: compile",
"type": "shell",
"command": "mvn",
"args": [
"compile",
"-pl",
"jeecg-module-system/jeecg-system-start",
"-am",
"-DskipTests",
"-q"
],
"options": {
"cwd": "${workspaceFolder}/jeecg-boot",
"env": {
"JAVA_HOME": "C:\\Program Files\\Java\\jdk-17"
}
},
"problemMatcher": "$javac",
"group": "build"
},
{
"label": "YY.Admin: restore",
"type": "process",
@@ -33,6 +54,24 @@
"dependsOn": "YY.Admin: build",
"problemMatcher": []
},
{
"label": "jeecgboot-vue3: dev",
"type": "shell",
"command": "pnpm run dev",
"options": {
"cwd": "${workspaceFolder}/jeecgboot-vue3"
},
"isBackground": true,
"problemMatcher": {
"owner": "vite",
"pattern": { "regexp": "^$" },
"background": {
"activeOnStart": true,
"beginsPattern": ".",
"endsPattern": "(Local:|ready in|http://localhost)"
}
}
},
{
"label": "YY.Admin: run (script)",
"type": "process",

View File

@@ -324,17 +324,26 @@ func waitForWindowsPrintCompletion(printerName string, existingIDs map[int]bool,
queued := false
jobID := 0
sumatraDone := false
for {
select {
case err := <-cmdDone:
sumatraDone = true
if err != nil && !queued {
return fmt.Errorf("sumatra print failed: %v", err)
}
// Sumatra 已正常退出且 spooler 未出现新任务:部分驱动/打印机直接出纸,不经过队列
if err == nil && !queued {
return nil
}
default:
}
now := time.Now()
if !queued && sumatraDone {
return nil
}
if !queued && now.After(appearDeadline) {
return fmt.Errorf("print job not queued within %s", printQueueAppearTimeout)
}

57
jeecg-boot/.claudeignore Normal file
View File

@@ -0,0 +1,57 @@
# Git
.git/
.gitignore
.gitmodules
# SVN
.svn/
# IntelliJ IDEA
.idea/
*.iml
*.iws
*.ipr
out/
# Eclipse
.classpath
.project
.settings/
# VS Code
.vscode/
# Maven / Gradle build output
target/
build/
!.mvn/wrapper/maven-wrapper.jar
# OS files
.DS_Store
Thumbs.db
desktop.ini
# Logs
*.log
logs/
# Node (frontend artifacts if any)
node_modules/
dist/
# Docker volumes / data
docker/data/
# Compiled classes
*.class
# Custom
*.qqy
代码修改.log
代码修改日志
*.zip
backup/
.history/
.cursor/
doc/
docs/

View File

@@ -2,10 +2,18 @@
**/.idea
*.iml
rebel.xml
# VS Code/Cursor Java 扩展Eclipse JDT导入 Maven 时自动生成,勿提交
.project
.classpath
.settings/
.factorypath
**/.settings/
## backend
**/target
**/logs
# 开发者本机钉钉 Stream 接收配置(从 application-dev-local.yml.example 复制)
**/application-dev-local.yml
## front
**/*.lock

14
jeecg-boot/.vscode/launch.json vendored Normal file
View File

@@ -0,0 +1,14 @@
{
"version": "0.2.0",
"configurations": [
{
"type": "java",
"name": "JeecgSystemApplication (单体)",
"request": "launch",
"mainClass": "org.jeecg.JeecgSystemApplication",
"projectName": "jeecg-system-start",
"cwd": "${workspaceFolder}/jeecg-module-system/jeecg-system-start",
"vmArgs": "-Dspring.main.banner-mode=log -Dspring.banner.charset=UTF-8 -Dlogging.charset.console=GBK"
}
]
}

37
jeecg-boot/.vscode/settings.json vendored Normal file
View File

@@ -0,0 +1,37 @@
{
"java.compile.nullAnalysis.mode": "automatic",
"java.jdt.ls.vmargs": "-XX:+UseParallelGC -XX:GCTimeRatio=4 -XX:AdaptiveSizePolicyWeight=90 -Dsun.zip.disableMemoryMapping=true -Xmx4G -Xms100m -Xlog:disable",
"java.import.maven.enabled": true,
"java.configuration.updateBuildConfiguration": "automatic",
"java.autobuild.enabled": true,
"java.import.maven.offline.enabled": false,
"java.configuration.maven.notCoveredPluginExecutionSeverity": "ignore",
"java.jdt.ls.java.home": "C:\\Program Files\\Java\\jdk-17",
"java.configuration.runtimes": [
{
"name": "JavaSE-17",
"path": "C:\\Program Files\\Java\\jdk-17",
"default": true
}
],
"java.maven.downloadSources": true,
"java.eclipse.downloadSources": true,
"java.project.importOnFirstTimeStartup": "automatic",
"java.configuration.checkProjectSettingsExclusions": false,
"java.import.exclusions": [
"**/jeecg-server-cloud/**",
"**/jeecg-boot-platform/**",
"**/node_modules/**",
"**/.metadata/**",
"**/archetype-resources/**",
"**/META-INF/maven/**"
],
"java.project.resourceFilters": [
"node_modules",
".git",
"jeecg-server-cloud",
"jeecg-boot-platform"
],
"java.debug.settings.console": "integratedTerminal",
"java.debug.settings.vmArgs": "-Dspring.main.banner-mode=log -Dspring.banner.charset=UTF-8 -Dlogging.charset.console=GBK"
}

18
jeecg-boot/.vscode/tasks.json vendored Normal file
View File

@@ -0,0 +1,18 @@
{
"version": "2.0.0",
"tasks": [
{
"label": "Maven: 修复 Java Classpath",
"type": "shell",
"command": "mvn clean install -DskipTests -pl jeecg-boot-base-core,jeecg-boot-module/jeecg-module-print,jeecg-boot-module/jeecg-module-xslmes -am",
"options": {
"cwd": "${workspaceFolder}"
},
"group": {
"kind": "build",
"isDefault": false
},
"problemMatcher": []
}
]
}

142
jeecg-boot/CLAUDE.md Normal file
View File

@@ -0,0 +1,142 @@
# CLAUDE.md
> You should always answer questions in Simplified Chinese first, unless the user explicitly requests another language.
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
## Project Overview
JeecgBoot 3.9.2 — a Java low-code development platform built on **Spring Boot 3.5.5**, **Java 17** (also supports 21, 24). It runs as a monolithic app by default, with an optional Spring Cloud microservices mode. Uses `jakarta` namespace (not `javax`) throughout.
## Build & Run Commands
```bash
# Full build (tests are skipped by default via surefire config)
mvn clean package
# Build with tests
mvn clean package -DskipTests=false
# Run the standalone application (port 8080, context-path: /jeecg-boot)
cd jeecg-module-system/jeecg-system-start
mvn spring-boot:run
# Build a specific module (with dependencies)
mvn clean package -pl jeecg-boot-base-core -am
# Run a single test class
mvn test -DskipTests=false -pl <module> -Dtest=<TestClassName>
# Build with microservices modules included
mvn clean package -P SpringCloud
# Docker startup
./start-docker-compose.sh # or start-docker-compose.bat on Windows
```
## Module Architecture
```
jeecg-boot-parent (root pom)
├── jeecg-boot-base-core # Core framework: Shiro/JWT auth, MyBatis-Plus config,
│ # common utilities, AOP aspects, base controllers
├── jeecg-module-system # System management (users, roles, permissions, dicts, menus)
│ ├── jeecg-system-api # API interfaces (local-api vs cloud-api for mono/micro switch)
│ │ ├── jeecg-system-local-api # Direct method calls (monolithic)
│ │ └── jeecg-system-cloud-api # Feign clients (microservices)
│ ├── jeecg-system-biz # Business logic, entities, mappers, services
│ └── jeecg-system-start # Main entry point (JeecgSystemApplication), all configs
├── jeecg-boot-module # Business feature modules
│ ├── jeecg-module-demo # Demo/example code
│ ├── jeecg-boot-module-airag # AI/RAG integration
│ ├── jeecg-boot-module-easyoa # Simple OA module
│ ├── jeecg-boot-module-joa-flowable # OA + Flowable workflow
│ ├── jeecg-boot-module-pay # Payment module
│ └── jeecg-boot-module-wps # WPS document integration
└── jeecg-boot-platform # Low-code platform modules
├── jeecg-boot-module-bpm-flowable # BPM workflow engine
├── jeecg-boot-module-airag-flow # AI RAG flow
├── jeecg-boot-module-bigscreen # Big screen/dashboard designer
├── jeecg-boot-module-desform # Form designer
├── jeecg-boot-module-drag # Drag-and-drop report designer
├── jeecg-boot-module-lowapp # Low-code application engine
├── jeecg-boot-module-mindesflow-flowable # Simple flow designer
└── jeecg-boot-module-online # Online code generator & forms
```
Optional microservices modules (activated via `-P SpringCloud`):
- `jeecg-server-cloud/` — Gateway (port 9999), Nacos (8848), cloud service starters, monitoring (9111), XXL-Job (9080), Sentinel (9000)
## Key Technology Stack
| Layer | Technology |
|-------|-----------|
| ORM | MyBatis-Plus 3.5.12 (`BaseMapper<T>`, `ServiceImpl<M,T>`) |
| Auth | Apache Shiro 2.0.5 + JWT 4.5.0, Redis-backed sessions |
| DB Pool | Druid 1.2.24 with dynamic datasource support |
| DB Migration | Flyway (scripts in `jeecg-system-start/src/main/resources/flyway/sql/mysql/`) |
| JSON | FastJSON 2 |
| Excel | AutoPoi (`autopoi-spring-boot-3-starter`) |
| API Docs | Knife4j 4.5.0 (OpenAPI v3, `@Schema` annotations) |
| Scheduled Jobs | Quartz (JDBC store, clustered) |
| File Storage | MinIO / Aliyun OSS / Qiniu (controlled by `jeecg.uploadType` config) |
| Microservices | Spring Cloud 2025.0.0 + Alibaba (Nacos, Gateway, Sentinel) |
## Code Conventions & Patterns
**Package structure:** `org.jeecg.modules.<module-name>.{controller,entity,mapper,mapper.xml,service,service.impl,vo}`
**Naming conventions:**
- Entities: `Sys` prefix for system entities (e.g., `SysUser`, `SysRole`). Use `@TableName`, `@TableId(type = IdType.ASSIGN_ID)`
- Controllers: `<Entity>Controller extends JeecgController<Entity, IService>` — base class provides standard CRUD + Excel import/export
- Services: Interface `I<Entity>Service extends IService<Entity>`, impl `<Entity>ServiceImpl extends ServiceImpl<Mapper, Entity>`
- Mappers: `<Entity>Mapper extends BaseMapper<Entity>`, with XML in `mapper/xml/`
**Common annotations on entities:** `@Data`, `@EqualsAndHashCode(callSuper = false)`, `@Accessors(chain = true)`, `@TableName`
**API response wrapper:** `Result<T>` (from `org.jeecg.common.api.vo.Result`) — use `Result.OK(data)`, `Result.OK(msg, data)`, `Result.error(msg)`. The `result` field holds data, `success`/`code`/`message` hold status.
**Auto query building:** `QueryGenerator.initQueryWrapper(entity, request.getParameterMap())` auto-builds `QueryWrapper` from HTTP request params, supporting fuzzy match, range queries, etc.
**Monolithic ↔ Microservices switch:** The `jeecg-system-api` module has two implementations (`local-api` for direct calls, `cloud-api` for Feign). Switching is done by changing the dependency in the startup module, not by modifying business code.
**代码修改痕迹日志:** 所有新增或修改的代码块必须用 `update-begin` / `update-end` 注释包裹,格式如下:
```java
//update-begin---author:作者 ---date:YYYY-MM-DD for【bug号/需求号】修改说明-----------
// 新增或修改的代码
//update-end---author:作者 ---date:YYYY-MM-DD for【bug号/需求号】修改说明-----------
```
规则:
- `author` 填实际修改人,`date` 填修改日期(格式 `YYYY-MM-DD``for` 填 bug 号或需求号 + 简要说明
- 新增方法:`update-begin` 放在方法声明前,`update-end` 放在方法结束 `}`
- 修改已有方法中的代码:`update-begin` / `update-end` 只包裹被修改的代码段,不包裹整个方法
- 用户未提供 bug 号时,需要主动询问
## Database
**Supported:** MySQL 8.0+ (default), PostgreSQL, Oracle 11g+, SQL Server 2017+, MariaDB, DM8 (达梦), KingBase ES. Database-specific configs are in `application-{dbtype}.yml` profiles.
**Initial setup:** Import `db/jeecgboot-mysql-5.7.sql` for the base schema. Flyway handles incremental migrations (scripts organized by date folders like `202512/`).
**Flyway note:** In dev mode, `spring.main.lazy-initialization=true` is enabled for startup speed, which can interfere with Flyway auto-config. Flyway auto-config is explicitly excluded and managed separately.
## Configuration
Main config files are in `jeecg-module-system/jeecg-system-start/src/main/resources/`:
- `application.yml` — profile selector (active profile set by Maven: dev/test/prod/docker)
- `application-dev.yml` — development config (port 8080, lazy-init enabled)
- Dev environment requires: MySQL, Redis. Optional: MongoDB, RabbitMQ
Key config namespace: `jeecg.*` in YAML controls platform features (upload type, firewall settings, AI config, MinIO, shiro excludes, etc.).
## Docker Services (docker-compose.yml)
MySQL (port 13306), Redis, PostgreSQL+pgvector, MongoDB, and the application container (port 8080).
## Online 低代码模块 (jeecg-boot-module-online)
Online 模块采用**元数据驱动**架构,通过数据库配置表(`onl_cgform_*`)实现运行时 CRUD无需生成代码。配置存在数据库中而非文件系统Claude Code 无法直接读取具体表单配置,需用户提供 JSON 导出或截图。
**完整的配置 Schema、控件类型、默认值语法、增强机制等详见: [online-form-schema.md](online-form-schema.md)**

View File

@@ -0,0 +1,64 @@
-- 修复胶料分类字典XSLMES_RUBBER数据库有数据但页面不展示
-- 场景开启多租户后sys_category tenant_id 与当前登录租户不一致/为空
SET NAMES utf8mb4;
-- 1) 目标租户默认取 admin 用户租户若为空则回退到 0
SET @target_tenant_id = (
SELECT COALESCE(tenant_id, 0)
FROM sys_user
WHERE username = 'admin'
ORDER BY create_time ASC
LIMIT 1
);
SET @target_tenant_id = IFNULL(@target_tenant_id, 0);
-- 2) 定位根分类编码
SET @rubber_code = 'XSLMES_RUBBER';
-- 若根节点不存在则补一个最小根节点避免前端 pcode 查询直接失败
INSERT INTO sys_category (id, pid, name, code, has_child, tenant_id, create_by, create_time, update_by, update_time)
SELECT '1994000000000000001', '0', 'MES胶料分类', @rubber_code, '1', @target_tenant_id, 'admin', NOW(), 'admin', NOW()
FROM dual
WHERE NOT EXISTS (
SELECT 1 FROM sys_category WHERE code = @rubber_code
);
SET @rubber_root_id = (
SELECT id
FROM sys_category
WHERE code = @rubber_code
ORDER BY create_time ASC
LIMIT 1
);
-- 3) 若根节点存在统一修复租户与父子标记
UPDATE sys_category
SET tenant_id = @target_tenant_id
WHERE id = @rubber_root_id;
UPDATE sys_category
SET tenant_id = @target_tenant_id
WHERE pid = @rubber_root_id;
-- 根节点是否有子节点按真实数据回写
UPDATE sys_category
SET has_child = CASE
WHEN EXISTS (SELECT 1 FROM (SELECT id FROM sys_category WHERE pid = @rubber_root_id LIMIT 1) t) THEN '1'
ELSE '0'
END
WHERE id = @rubber_root_id;
-- 子节点统一标记为无子当前这批分类通常为叶子
UPDATE sys_category
SET has_child = '0'
WHERE pid = @rubber_root_id;
-- 4) 结果检查执行后看返回
SELECT 'ROOT' AS level_tag, id, pid, code, name, tenant_id, has_child
FROM sys_category
WHERE id = @rubber_root_id
UNION ALL
SELECT 'CHILD' AS level_tag, id, pid, code, name, tenant_id, has_child
FROM sys_category
WHERE pid = @rubber_root_id
ORDER BY level_tag, code;

View File

@@ -11,9 +11,9 @@ menu_type=VALUES(menu_type), perms=VALUES(perms), perms_type=VALUES(perms_type),
is_route=VALUES(is_route), is_leaf=VALUES(is_leaf), hidden=VALUES(hidden), status=VALUES(status), del_flag=VALUES(del_flag),
always_show=VALUES(always_show), keep_alive=VALUES(keep_alive), internal_or_external=VALUES(internal_or_external);
-- 二级菜单料信息
-- 二级菜单料信息
INSERT INTO sys_permission(id, parent_id, name, url, component, component_name, menu_type, perms, perms_type, sort_no, is_route, is_leaf, hidden, status, del_flag, keep_alive, internal_or_external, create_by, create_time)
VALUES ('1860000000000000011', '1860000000000000001', '料信息', '/mes/materialinfo', 'mes/materialinfo/index', 'MesMaterialList', 1, NULL, '1', 1, 1, 1, 0, '1', 0, 1, 0, 'admin', NOW())
VALUES ('1860000000000000011', '1860000000000000001', '料信息', '/mes/materialinfo', 'mes/materialinfo/index', 'MesMaterialList', 1, NULL, '1', 1, 1, 1, 0, '1', 0, 1, 0, 'admin', NOW())
ON DUPLICATE KEY UPDATE
parent_id=VALUES(parent_id), name=VALUES(name), url=VALUES(url), component=VALUES(component), component_name=VALUES(component_name),
menu_type=VALUES(menu_type), perms=VALUES(perms), perms_type=VALUES(perms_type), sort_no=VALUES(sort_no),

View File

@@ -32,19 +32,19 @@ VALUES ('1860000000000000060', @mes_base_pid, '工序管理', '/xslmes/mesXslPro
ON DUPLICATE KEY UPDATE
`parent_id` = VALUES(`parent_id`), `name` = VALUES(`name`), `url` = VALUES(`url`), `component` = VALUES(`component`), `component_name` = VALUES(`component_name`),
`menu_type` = VALUES(`menu_type`), `perms` = VALUES(`perms`), `perms_type` = VALUES(`perms_type`), `sort_no` = VALUES(`sort_no`),
`is_route` = VALUES(`is_route`), `is_leaf` = VALUES(`is_leaf`), `hidden` = VALUES(`hidden`), `status` = VALUES(`status`), `del_flag` = VALUES(`del_flag`),
`is_route` = VALUES(`is_route`), `is_leaf` = 0, `hidden` = 0, `status` = '1', `del_flag` = 0,
`keep_alive` = VALUES(`keep_alive`), `internal_or_external` = VALUES(`internal_or_external`);
INSERT INTO `sys_permission`(`id`, `parent_id`, `name`, `menu_type`, `perms`, `perms_type`, `status`, `del_flag`, `create_by`, `create_time`) VALUES
('1860000000000000061', '1860000000000000060', '新增', 2, 'mes:mes_process_operation:add', '1', '1', 0, 'admin', NOW()),
('1860000000000000062', '1860000000000000060', '编辑', 2, 'mes:mes_process_operation:edit', '1', '1', 0, 'admin', NOW()),
('1860000000000000063', '1860000000000000060', '删除', 2, 'mes:mes_process_operation:delete', '1', '1', 0, 'admin', NOW()),
('1860000000000000064', '1860000000000000060', '批量删除', 2, 'mes:mes_process_operation:deleteBatch', '1', '1', 0, 'admin', NOW()),
('1860000000000000065', '1860000000000000060', '导出', 2, 'mes:mes_process_operation:exportXls', '1', '1', 0, 'admin', NOW()),
('1860000000000000066', '1860000000000000060', '导入', 2, 'mes:mes_process_operation:importExcel', '1', '1', 0, 'admin', NOW())
INSERT INTO `sys_permission`(`id`, `parent_id`, `name`, `menu_type`, `perms`, `perms_type`, `is_leaf`, `status`, `del_flag`, `create_by`, `create_time`) VALUES
('1860000000000000061', '1860000000000000060', '新增', 2, 'mes:mes_process_operation:add', '1', 1, '1', 0, 'admin', NOW()),
('1860000000000000062', '1860000000000000060', '编辑', 2, 'mes:mes_process_operation:edit', '1', 1, '1', 0, 'admin', NOW()),
('1860000000000000063', '1860000000000000060', '删除', 2, 'mes:mes_process_operation:delete', '1', 1, '1', 0, 'admin', NOW()),
('1860000000000000064', '1860000000000000060', '批量删除', 2, 'mes:mes_process_operation:deleteBatch', '1', 1, '1', 0, 'admin', NOW()),
('1860000000000000065', '1860000000000000060', '导出', 2, 'mes:mes_process_operation:exportXls', '1', 1, '1', 0, 'admin', NOW()),
('1860000000000000066', '1860000000000000060', '导入', 2, 'mes:mes_process_operation:importExcel', '1', 1, '1', 0, 'admin', NOW())
ON DUPLICATE KEY UPDATE
`parent_id` = VALUES(`parent_id`), `name` = VALUES(`name`), `menu_type` = VALUES(`menu_type`), `perms` = VALUES(`perms`), `perms_type` = VALUES(`perms_type`),
`status` = VALUES(`status`), `del_flag` = VALUES(`del_flag`);
`is_leaf` = 1, `status` = '1', `del_flag` = 0;
INSERT INTO `sys_role_permission`(`id`, `role_id`, `permission_id`, `operate_date`, `operate_ip`)
SELECT REPLACE(UUID(), '-', ''), r.`id`, p.`id`, NOW(), '127.0.0.1'

View File

@@ -0,0 +1,92 @@
-- 日罐物料对应信息菜单与权限挂到MES密炼工程目录
SET NAMES utf8mb4;
SET @mixer_parent_id = (
SELECT id
FROM sys_permission
WHERE name = 'MES密炼工程' AND menu_type = 0 AND del_flag = 0
ORDER BY create_time ASC
LIMIT 1
);
SET @mixer_parent_id = IFNULL(@mixer_parent_id, (
SELECT id
FROM sys_permission
WHERE url = '/mes' AND menu_type = 0 AND del_flag = 0
ORDER BY create_time ASC
LIMIT 1
));
SET @mixer_parent_id = IFNULL(@mixer_parent_id, '1860000000000000001');
INSERT INTO sys_permission(
id, parent_id, name, url, component, component_name, menu_type, perms, perms_type, sort_no,
is_route, is_leaf, hidden, status, del_flag, keep_alive, internal_or_external, create_by, create_time
)
VALUES (
'1860000000000099311', @mixer_parent_id, '日罐物料对应信息',
'/mes/daytankmaterialmapinfo',
'mes/daytankmaterialmapinfo/index',
'MesXslDayTankMaterialMapList', 1, NULL, '1', 31,
1, 1, 0, '1', 0, 1, 0, 'admin', NOW()
)
ON DUPLICATE KEY UPDATE
parent_id = VALUES(parent_id),
name = VALUES(name),
url = VALUES(url),
component = VALUES(component),
component_name = VALUES(component_name),
menu_type = VALUES(menu_type),
perms = VALUES(perms),
perms_type = VALUES(perms_type),
sort_no = VALUES(sort_no),
is_route = VALUES(is_route),
is_leaf = VALUES(is_leaf),
hidden = VALUES(hidden),
status = VALUES(status),
del_flag = VALUES(del_flag),
keep_alive = VALUES(keep_alive),
internal_or_external = VALUES(internal_or_external);
INSERT INTO sys_permission(id, parent_id, name, menu_type, perms, perms_type, status, del_flag, create_by, create_time) VALUES
('1860000000000099312', '1860000000000099311', '新增', 2, 'xslmes:mes_xsl_day_tank_material_map:add', '1', '1', 0, 'admin', NOW()),
('1860000000000099313', '1860000000000099311', '编辑', 2, 'xslmes:mes_xsl_day_tank_material_map:edit', '1', '1', 0, 'admin', NOW()),
('1860000000000099314', '1860000000000099311', '删除', 2, 'xslmes:mes_xsl_day_tank_material_map:delete', '1', '1', 0, 'admin', NOW()),
('1860000000000099315', '1860000000000099311', '批量删除', 2, 'xslmes:mes_xsl_day_tank_material_map:deleteBatch', '1', '1', 0, 'admin', NOW()),
('1860000000000099316', '1860000000000099311', '导出', 2, 'xslmes:mes_xsl_day_tank_material_map:exportXls', '1', '1', 0, 'admin', NOW())
ON DUPLICATE KEY UPDATE
parent_id = VALUES(parent_id),
name = VALUES(name),
menu_type = VALUES(menu_type),
perms = VALUES(perms),
perms_type = VALUES(perms_type),
status = VALUES(status),
del_flag = VALUES(del_flag);
-- admin 角色授权
INSERT INTO sys_role_permission(id, role_id, permission_id, operate_date, operate_ip)
SELECT REPLACE(UUID(), '-', ''), 'f6817f48af4fb3af11b9e8bf182f618b', p.id, NOW(), '127.0.0.1'
FROM sys_permission p
WHERE p.id IN (
'1860000000000099311',
'1860000000000099312', '1860000000000099313', '1860000000000099314', '1860000000000099315', '1860000000000099316'
)
AND NOT EXISTS (
SELECT 1
FROM sys_role_permission rp
WHERE rp.role_id = 'f6817f48af4fb3af11b9e8bf182f618b'
AND rp.permission_id = p.id
);
-- 强制修复确保菜单路由与组件路径正确避免历史错误路径导致查看组件引用是否正确
UPDATE sys_permission
SET
parent_id = @mixer_parent_id,
url = '/mes/daytankmaterialmapinfo',
component = 'mes/daytankmaterialmapinfo/index',
component_name = 'MesXslDayTankMaterialMapList',
menu_type = 1,
is_route = 1,
is_leaf = 1,
hidden = 0,
status = '1',
del_flag = 0
WHERE id = '1860000000000099311';

View File

@@ -0,0 +1,82 @@
-- MES 停机主类型字典 + 建表 + 菜单 + 按钮 + 租户 admin 授权可整文件一次执行
-- 权限前缀与 Controller前端 v-auth 一致mes:mes_xsl_downtime_main_type:*
-- 父菜单MES基础资料 / MES资料修改租户改 SET @mes_tenant_id
-- 新环境也可依赖 FlywayV3.9.2_64__mes_xsl_downtime_main_type.sql
SET NAMES utf8mb4;
INSERT INTO `sys_dict` (`id`, `dict_name`, `dict_code`, `description`, `del_flag`, `create_by`, `create_time`, `type`, `tenant_id`)
SELECT REPLACE(UUID(), '-', ''), 'MES停机主类型是否启用', 'xslmes_downtime_main_type_status', '0启用1停用', 0, 'admin', NOW(), 0, 0
WHERE NOT EXISTS (SELECT 1 FROM `sys_dict` WHERE `dict_code` = 'xslmes_downtime_main_type_status' AND `del_flag` = 0);
INSERT INTO `sys_dict_item` (`id`, `dict_id`, `item_text`, `item_value`, `sort_order`, `status`, `create_by`, `create_time`)
SELECT REPLACE(UUID(), '-', ''), d.id, '启用', '0', 1, 1, 'admin', NOW() FROM `sys_dict` d
WHERE d.`dict_code` = 'xslmes_downtime_main_type_status' AND NOT EXISTS (SELECT 1 FROM `sys_dict_item` i WHERE i.`dict_id` = d.id AND i.`item_value` = '0');
INSERT INTO `sys_dict_item` (`id`, `dict_id`, `item_text`, `item_value`, `sort_order`, `status`, `create_by`, `create_time`)
SELECT REPLACE(UUID(), '-', ''), d.id, '停用', '1', 2, 1, 'admin', NOW() FROM `sys_dict` d
WHERE d.`dict_code` = 'xslmes_downtime_main_type_status' AND NOT EXISTS (SELECT 1 FROM `sys_dict_item` i WHERE i.`dict_id` = d.id AND i.`item_value` = '1');
CREATE TABLE IF NOT EXISTS `mes_xsl_downtime_main_type` (
`id` varchar(32) NOT NULL COMMENT '主键',
`process_operation_id` varchar(32) NOT NULL COMMENT '所属工序 mes_xsl_process_operation.id',
`process_operation_name` varchar(500) DEFAULT NULL COMMENT '工序名称冗余',
`downtime_type` varchar(500) NOT NULL COMMENT '停机类型同租户未删除数据中唯一',
`display_order` int NOT NULL DEFAULT '0' COMMENT '显示顺序升序',
`distinguish_color` varchar(500) DEFAULT NULL COMMENT '区分颜色十六进制色值#1890ff',
`status` varchar(1) NOT NULL DEFAULT '0' COMMENT '是否启用字典xslmes_downtime_main_type_status0启用1停用',
`tenant_id` int DEFAULT NULL COMMENT '租户',
`sys_org_code` varchar(500) DEFAULT NULL COMMENT '部门',
`create_by` varchar(500) DEFAULT NULL COMMENT '创建人',
`create_time` datetime DEFAULT NULL COMMENT '创建时间',
`update_by` varchar(500) DEFAULT NULL COMMENT '更新人',
`update_time` datetime DEFAULT NULL COMMENT '更新时间',
`del_flag` int DEFAULT '0' COMMENT '删除标记0正常1删除',
PRIMARY KEY (`id`),
KEY `idx_mdmt_tenant_type` (`tenant_id`, `downtime_type`),
KEY `idx_mdmt_process` (`process_operation_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='MES停机主类型';
SET @mes_tenant_id = 1002;
SET @mes_equip_pid = (
SELECT `id` FROM `sys_permission`
WHERE `del_flag` = 0 AND `menu_type` = 0 AND `name` = '设备管理'
LIMIT 1
);
SET @mes_equip_pid = IFNULL(@mes_equip_pid, '1860000000000000133');
INSERT INTO `sys_permission`(`id`, `parent_id`, `name`, `url`, `component`, `component_name`, `menu_type`, `perms`, `perms_type`, `sort_no`, `is_route`, `is_leaf`, `hidden`, `status`, `del_flag`, `keep_alive`, `internal_or_external`, `create_by`, `create_time`)
VALUES ('1860000000000000119', @mes_equip_pid, '停机主类型', '/xslmes/mesXslDowntimeMainType', 'xslmes/mesXslDowntimeMainType/MesXslDowntimeMainTypeList', NULL, 1, NULL, '1', 9, 1, 0, 0, '1', 0, 1, 0, 'admin', NOW())
ON DUPLICATE KEY UPDATE
`parent_id` = VALUES(`parent_id`), `name` = VALUES(`name`), `url` = VALUES(`url`), `component` = VALUES(`component`), `component_name` = VALUES(`component_name`),
`menu_type` = VALUES(`menu_type`), `perms` = VALUES(`perms`), `perms_type` = VALUES(`perms_type`), `sort_no` = VALUES(`sort_no`),
`is_route` = VALUES(`is_route`), `is_leaf` = VALUES(`is_leaf`), `hidden` = VALUES(`hidden`), `status` = VALUES(`status`), `del_flag` = VALUES(`del_flag`),
`keep_alive` = VALUES(`keep_alive`), `internal_or_external` = VALUES(`internal_or_external`), `icon` = 'ant-design:partition-outlined';
UPDATE `sys_permission` SET `icon` = 'ant-design:partition-outlined' WHERE `id` = '1860000000000000119' AND `del_flag` = 0;
INSERT INTO `sys_permission`(`id`, `parent_id`, `name`, `menu_type`, `perms`, `perms_type`, `status`, `del_flag`, `create_by`, `create_time`) VALUES
('1860000000000000120', '1860000000000000119', '新增', 2, 'mes:mes_xsl_downtime_main_type:add', '1', '1', 0, 'admin', NOW()),
('1860000000000000121', '1860000000000000119', '编辑', 2, 'mes:mes_xsl_downtime_main_type:edit', '1', '1', 0, 'admin', NOW()),
('1860000000000000122', '1860000000000000119', '删除', 2, 'mes:mes_xsl_downtime_main_type:delete', '1', '1', 0, 'admin', NOW()),
('1860000000000000123', '1860000000000000119', '批量删除', 2, 'mes:mes_xsl_downtime_main_type:deleteBatch', '1', '1', 0, 'admin', NOW()),
('1860000000000000124', '1860000000000000119', '导出', 2, 'mes:mes_xsl_downtime_main_type:exportXls', '1', '1', 0, 'admin', NOW()),
('1860000000000000125', '1860000000000000119', '导入', 2, 'mes:mes_xsl_downtime_main_type:importExcel', '1', '1', 0, 'admin', NOW())
ON DUPLICATE KEY UPDATE
`parent_id` = VALUES(`parent_id`), `name` = VALUES(`name`), `menu_type` = VALUES(`menu_type`), `perms` = VALUES(`perms`), `perms_type` = VALUES(`perms_type`),
`status` = VALUES(`status`), `del_flag` = VALUES(`del_flag`);
INSERT INTO `sys_role_permission`(`id`, `role_id`, `permission_id`, `operate_date`, `operate_ip`)
SELECT REPLACE(UUID(), '-', ''), r.`id`, p.`id`, NOW(), '127.0.0.1'
FROM `sys_role` r
CROSS JOIN `sys_permission` p
WHERE r.`tenant_id` = @mes_tenant_id
AND r.`role_code` = 'admin'
AND p.`id` IN (
'1860000000000000119',
'1860000000000000120', '1860000000000000121', '1860000000000000122', '1860000000000000123',
'1860000000000000124', '1860000000000000125'
)
AND NOT EXISTS (
SELECT 1 FROM `sys_role_permission` rp
WHERE rp.`role_id` = r.`id` AND rp.`permission_id` = p.`id`
);

View File

@@ -0,0 +1,22 @@
-- 仅建表 mes_xsl_downtime_main_type完整初始化请执行 mes-xsl-downtime-main-type-menu-permission.sql
SET NAMES utf8mb4;
CREATE TABLE IF NOT EXISTS `mes_xsl_downtime_main_type` (
`id` varchar(32) NOT NULL COMMENT '主键',
`process_operation_id` varchar(32) NOT NULL COMMENT '所属工序 mes_xsl_process_operation.id',
`process_operation_name` varchar(500) DEFAULT NULL COMMENT '工序名称冗余',
`downtime_type` varchar(500) NOT NULL COMMENT '停机类型同租户未删除数据中唯一',
`display_order` int NOT NULL DEFAULT '0' COMMENT '显示顺序升序',
`distinguish_color` varchar(500) DEFAULT NULL COMMENT '区分颜色十六进制色值#1890ff',
`status` varchar(1) NOT NULL DEFAULT '0' COMMENT '是否启用字典xslmes_downtime_main_type_status0启用1停用',
`tenant_id` int DEFAULT NULL COMMENT '租户',
`sys_org_code` varchar(500) DEFAULT NULL COMMENT '部门',
`create_by` varchar(500) DEFAULT NULL COMMENT '创建人',
`create_time` datetime DEFAULT NULL COMMENT '创建时间',
`update_by` varchar(500) DEFAULT NULL COMMENT '更新人',
`update_time` datetime DEFAULT NULL COMMENT '更新时间',
`del_flag` int DEFAULT '0' COMMENT '删除标记0正常1删除',
PRIMARY KEY (`id`),
KEY `idx_mdmt_tenant_type` (`tenant_id`, `downtime_type`),
KEY `idx_mdmt_process` (`process_operation_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='MES停机主类型';

View File

@@ -0,0 +1,82 @@
-- MES 停机记录建表 + 菜单 + 按钮 + 租户 admin 授权可整文件一次执行
-- 权限前缀mes:mes_xsl_downtime_record:*
-- 依赖mes_xsl_equipment_ledgermes_xsl_downtime_type父菜单 设备管理
-- FlywayV3.9.2_117__mes_xsl_downtime_record.sql
SET NAMES utf8mb4;
CREATE TABLE IF NOT EXISTS `mes_xsl_downtime_record` (
`id` varchar(32) NOT NULL COMMENT '主键',
`equipment_ledger_id` varchar(32) NOT NULL COMMENT '设备台账主键 mes_xsl_equipment_ledger.id',
`equipment_code` varchar(500) DEFAULT NULL COMMENT '设备编号冗余',
`equipment_name` varchar(500) DEFAULT NULL COMMENT '设备名称冗余',
`downtime_type_id` varchar(32) NOT NULL COMMENT '停机类型主键 mes_xsl_downtime_type.id',
`downtime_type_name` varchar(500) DEFAULT NULL COMMENT '停机类型名称冗余',
`start_time` datetime NOT NULL COMMENT '开始时间',
`end_time` datetime DEFAULT NULL COMMENT '结束时间',
`equipment_part_id` varchar(32) DEFAULT NULL COMMENT '设备部位主键 mes_xsl_equipment_part.id',
`equipment_part_name` varchar(500) DEFAULT NULL COMMENT '设备部位名称冗余',
`inspect_maintain_item_id` varchar(32) DEFAULT NULL COMMENT '点检及保养项目主键 mes_xsl_inspect_maintain_item.id',
`inspect_maintain_item_name` varchar(500) DEFAULT NULL COMMENT '点检项目名称冗余',
`maintenance_result` varchar(500) DEFAULT NULL COMMENT '维修结果',
`maintainer_user_id` varchar(32) DEFAULT NULL COMMENT '维修人用户ID',
`maintainer_username` varchar(500) DEFAULT NULL COMMENT '维修人账号',
`maintainer_realname` varchar(500) DEFAULT NULL COMMENT '维修人姓名',
`maintenance_filled_flag` varchar(1) DEFAULT '0' COMMENT '是否已录入维修结果字典yn1是0否',
`tenant_id` int DEFAULT NULL COMMENT '租户',
`sys_org_code` varchar(500) DEFAULT NULL COMMENT '部门',
`create_by` varchar(500) DEFAULT NULL COMMENT '创建人',
`create_time` datetime DEFAULT NULL COMMENT '创建时间',
`update_by` varchar(500) DEFAULT NULL COMMENT '更新人',
`update_time` datetime DEFAULT NULL COMMENT '更新时间',
`del_flag` int DEFAULT '0' COMMENT '删除标记0正常1删除',
PRIMARY KEY (`id`),
KEY `idx_mdr_equipment` (`equipment_ledger_id`),
KEY `idx_mdr_downtime_type` (`downtime_type_id`),
KEY `idx_mdr_start_time` (`start_time`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='MES停机记录';
SET @mes_tenant_id = 1002;
SET @mes_equip_pid = (
SELECT `id` FROM `sys_permission`
WHERE `del_flag` = 0 AND `menu_type` = 0 AND `name` = '设备管理'
LIMIT 1
);
SET @mes_equip_pid = IFNULL(@mes_equip_pid, '1860000000000000133');
INSERT INTO `sys_permission`(`id`, `parent_id`, `name`, `url`, `component`, `component_name`, `menu_type`, `perms`, `perms_type`, `sort_no`, `is_route`, `is_leaf`, `hidden`, `status`, `del_flag`, `keep_alive`, `internal_or_external`, `create_by`, `create_time`)
VALUES ('1860000000000000201', @mes_equip_pid, '停机记录', '/xslmes/mesXslDowntimeRecord', 'xslmes/mesXslDowntimeRecord/MesXslDowntimeRecordList', 'MesXslDowntimeRecordList', 1, NULL, '1', 12, 1, 0, 0, '1', 0, 1, 0, 'admin', NOW())
ON DUPLICATE KEY UPDATE
`parent_id` = VALUES(`parent_id`), `name` = VALUES(`name`), `url` = VALUES(`url`), `component` = VALUES(`component`), `component_name` = VALUES(`component_name`),
`menu_type` = VALUES(`menu_type`), `perms` = VALUES(`perms`), `perms_type` = VALUES(`perms_type`), `sort_no` = VALUES(`sort_no`),
`is_route` = VALUES(`is_route`), `is_leaf` = VALUES(`is_leaf`), `hidden` = VALUES(`hidden`), `status` = VALUES(`status`), `del_flag` = VALUES(`del_flag`),
`keep_alive` = VALUES(`keep_alive`), `internal_or_external` = VALUES(`internal_or_external`), `icon` = 'ant-design:history-outlined';
UPDATE `sys_permission` SET `icon` = 'ant-design:history-outlined' WHERE `id` = '1860000000000000201' AND `del_flag` = 0;
INSERT INTO `sys_permission`(`id`, `parent_id`, `name`, `menu_type`, `perms`, `perms_type`, `status`, `del_flag`, `create_by`, `create_time`) VALUES
('1860000000000000202', '1860000000000000201', '新增', 2, 'mes:mes_xsl_downtime_record:add', '1', '1', 0, 'admin', NOW()),
('1860000000000000203', '1860000000000000201', '编辑', 2, 'mes:mes_xsl_downtime_record:edit', '1', '1', 0, 'admin', NOW()),
('1860000000000000204', '1860000000000000201', '删除', 2, 'mes:mes_xsl_downtime_record:delete', '1', '1', 0, 'admin', NOW()),
('1860000000000000205', '1860000000000000201', '批量删除', 2, 'mes:mes_xsl_downtime_record:deleteBatch', '1', '1', 0, 'admin', NOW()),
('1860000000000000206', '1860000000000000201', '导出', 2, 'mes:mes_xsl_downtime_record:exportXls', '1', '1', 0, 'admin', NOW()),
('1860000000000000207', '1860000000000000201', '导入', 2, 'mes:mes_xsl_downtime_record:importExcel', '1', '1', 0, 'admin', NOW())
ON DUPLICATE KEY UPDATE
`parent_id` = VALUES(`parent_id`), `name` = VALUES(`name`), `menu_type` = VALUES(`menu_type`), `perms` = VALUES(`perms`), `perms_type` = VALUES(`perms_type`),
`status` = VALUES(`status`), `del_flag` = VALUES(`del_flag`);
INSERT INTO `sys_role_permission`(`id`, `role_id`, `permission_id`, `operate_date`, `operate_ip`)
SELECT REPLACE(UUID(), '-', ''), r.`id`, p.`id`, NOW(), '127.0.0.1'
FROM `sys_role` r
CROSS JOIN `sys_permission` p
WHERE r.`tenant_id` = @mes_tenant_id
AND r.`role_code` = 'admin'
AND p.`id` IN (
'1860000000000000201',
'1860000000000000202', '1860000000000000203', '1860000000000000204', '1860000000000000205',
'1860000000000000206', '1860000000000000207'
)
AND NOT EXISTS (
SELECT 1 FROM `sys_role_permission` rp
WHERE rp.`role_id` = r.`id` AND rp.`permission_id` = p.`id`
);

View File

@@ -0,0 +1,90 @@
-- MES 停机类型字典 + 建表 + 菜单 + 按钮 + 租户 admin 授权可整文件一次执行
-- 权限前缀mes:mes_xsl_downtime_type:*
-- 依赖mes_xsl_process_operationmes_xsl_downtime_main_type父菜单 MES基础资料
-- FlywayV3.9.2_65__mes_xsl_downtime_type.sql
SET NAMES utf8mb4;
-- 责任区分故障等级为手填不初始化字典已上线库请执行 mes-xsl-downtime-type-remove-unused-dict.sql
INSERT INTO `sys_dict` (`id`, `dict_name`, `dict_code`, `description`, `del_flag`, `create_by`, `create_time`, `type`, `tenant_id`)
SELECT REPLACE(UUID(), '-', ''), 'MES停机类型是否启用', 'xslmes_downtime_type_status', '0启用1停用', 0, 'admin', NOW(), 0, 0
WHERE NOT EXISTS (SELECT 1 FROM `sys_dict` WHERE `dict_code` = 'xslmes_downtime_type_status' AND `del_flag` = 0);
INSERT INTO `sys_dict_item` (`id`, `dict_id`, `item_text`, `item_value`, `sort_order`, `status`, `create_by`, `create_time`)
SELECT REPLACE(UUID(), '-', ''), d.id, '启用', '0', 1, 1, 'admin', NOW() FROM `sys_dict` d
WHERE d.`dict_code` = 'xslmes_downtime_type_status' AND NOT EXISTS (SELECT 1 FROM `sys_dict_item` i WHERE i.`dict_id` = d.id AND i.`item_value` = '0');
INSERT INTO `sys_dict_item` (`id`, `dict_id`, `item_text`, `item_value`, `sort_order`, `status`, `create_by`, `create_time`)
SELECT REPLACE(UUID(), '-', ''), d.id, '停用', '1', 2, 1, 'admin', NOW() FROM `sys_dict` d
WHERE d.`dict_code` = 'xslmes_downtime_type_status' AND NOT EXISTS (SELECT 1 FROM `sys_dict_item` i WHERE i.`dict_id` = d.id AND i.`item_value` = '1');
CREATE TABLE IF NOT EXISTS `mes_xsl_downtime_type` (
`id` varchar(32) NOT NULL COMMENT '主键',
`process_operation_id` varchar(32) NOT NULL COMMENT '所属工序 mes_xsl_process_operation.id',
`process_operation_name` varchar(500) DEFAULT NULL COMMENT '工序名称冗余',
`downtime_main_type_id` varchar(32) NOT NULL COMMENT '所属主类型 mes_xsl_downtime_main_type.id',
`downtime_main_type_name` varchar(500) DEFAULT NULL COMMENT '主类型名称冗余停机主类型.downtime_type',
`downtime_type` varchar(500) NOT NULL COMMENT '停机类型同租户未删除数据中唯一',
`display_order` int NOT NULL DEFAULT '0' COMMENT '显示顺序升序必填',
`distinguish_color` varchar(500) DEFAULT NULL COMMENT '区分颜色十六进制色值',
`responsibility_distinct` varchar(500) DEFAULT NULL COMMENT '责任区分手填',
`fault_level` varchar(500) DEFAULT NULL COMMENT '故障等级手填',
`downtime_maintenance` varchar(1) DEFAULT '0' COMMENT '是否停机维修字典yn1是0否',
`status` varchar(1) NOT NULL DEFAULT '0' COMMENT '是否启用字典xslmes_downtime_type_status0启用1停用',
`tenant_id` int DEFAULT NULL COMMENT '租户',
`sys_org_code` varchar(500) DEFAULT NULL COMMENT '部门',
`create_by` varchar(500) DEFAULT NULL COMMENT '创建人',
`create_time` datetime DEFAULT NULL COMMENT '创建时间',
`update_by` varchar(500) DEFAULT NULL COMMENT '更新人',
`update_time` datetime DEFAULT NULL COMMENT '更新时间',
`del_flag` int DEFAULT '0' COMMENT '删除标记0正常1删除',
PRIMARY KEY (`id`),
KEY `idx_mdt_tenant_type` (`tenant_id`, `downtime_type`),
KEY `idx_mdt_process` (`process_operation_id`),
KEY `idx_mdt_main_type` (`downtime_main_type_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='MES停机类型';
SET @mes_tenant_id = 1002;
SET @mes_equip_pid = (
SELECT `id` FROM `sys_permission`
WHERE `del_flag` = 0 AND `menu_type` = 0 AND `name` = '设备管理'
LIMIT 1
);
SET @mes_equip_pid = IFNULL(@mes_equip_pid, '1860000000000000133');
INSERT INTO `sys_permission`(`id`, `parent_id`, `name`, `url`, `component`, `component_name`, `menu_type`, `perms`, `perms_type`, `sort_no`, `is_route`, `is_leaf`, `hidden`, `status`, `del_flag`, `keep_alive`, `internal_or_external`, `create_by`, `create_time`)
VALUES ('1860000000000000126', @mes_equip_pid, '停机类型', '/xslmes/mesXslDowntimeType', 'xslmes/mesXslDowntimeType/MesXslDowntimeTypeList', NULL, 1, NULL, '1', 10, 1, 0, 0, '1', 0, 1, 0, 'admin', NOW())
ON DUPLICATE KEY UPDATE
`parent_id` = VALUES(`parent_id`), `name` = VALUES(`name`), `url` = VALUES(`url`), `component` = VALUES(`component`), `component_name` = VALUES(`component_name`),
`menu_type` = VALUES(`menu_type`), `perms` = VALUES(`perms`), `perms_type` = VALUES(`perms_type`), `sort_no` = VALUES(`sort_no`),
`is_route` = VALUES(`is_route`), `is_leaf` = VALUES(`is_leaf`), `hidden` = VALUES(`hidden`), `status` = VALUES(`status`), `del_flag` = VALUES(`del_flag`),
`keep_alive` = VALUES(`keep_alive`), `internal_or_external` = VALUES(`internal_or_external`), `icon` = 'ant-design:pause-circle-outlined';
UPDATE `sys_permission` SET `icon` = 'ant-design:pause-circle-outlined' WHERE `id` = '1860000000000000126' AND `del_flag` = 0;
INSERT INTO `sys_permission`(`id`, `parent_id`, `name`, `menu_type`, `perms`, `perms_type`, `status`, `del_flag`, `create_by`, `create_time`) VALUES
('1860000000000000127', '1860000000000000126', '新增', 2, 'mes:mes_xsl_downtime_type:add', '1', '1', 0, 'admin', NOW()),
('1860000000000000128', '1860000000000000126', '编辑', 2, 'mes:mes_xsl_downtime_type:edit', '1', '1', 0, 'admin', NOW()),
('1860000000000000129', '1860000000000000126', '删除', 2, 'mes:mes_xsl_downtime_type:delete', '1', '1', 0, 'admin', NOW()),
('1860000000000000130', '1860000000000000126', '批量删除', 2, 'mes:mes_xsl_downtime_type:deleteBatch', '1', '1', 0, 'admin', NOW()),
('1860000000000000131', '1860000000000000126', '导出', 2, 'mes:mes_xsl_downtime_type:exportXls', '1', '1', 0, 'admin', NOW()),
('1860000000000000132', '1860000000000000126', '导入', 2, 'mes:mes_xsl_downtime_type:importExcel', '1', '1', 0, 'admin', NOW())
ON DUPLICATE KEY UPDATE
`parent_id` = VALUES(`parent_id`), `name` = VALUES(`name`), `menu_type` = VALUES(`menu_type`), `perms` = VALUES(`perms`), `perms_type` = VALUES(`perms_type`),
`status` = VALUES(`status`), `del_flag` = VALUES(`del_flag`);
INSERT INTO `sys_role_permission`(`id`, `role_id`, `permission_id`, `operate_date`, `operate_ip`)
SELECT REPLACE(UUID(), '-', ''), r.`id`, p.`id`, NOW(), '127.0.0.1'
FROM `sys_role` r
CROSS JOIN `sys_permission` p
WHERE r.`tenant_id` = @mes_tenant_id
AND r.`role_code` = 'admin'
AND p.`id` IN (
'1860000000000000126',
'1860000000000000127', '1860000000000000128', '1860000000000000129', '1860000000000000130',
'1860000000000000131', '1860000000000000132'
)
AND NOT EXISTS (
SELECT 1 FROM `sys_role_permission` rp
WHERE rp.`role_id` = r.`id` AND rp.`permission_id` = p.`id`
);

View File

@@ -0,0 +1,11 @@
-- 删除停机类型模块中已废弃的字典责任区分故障等级已改为手填不再使用下拉字典
-- 保留xslmes_downtime_type_status是否启用xslmes_downtime_main_type_status停机主类型是否启用
-- 执行后请在系统管理刷新字典缓存或重新登录
SET NAMES utf8mb4;
DELETE i FROM `sys_dict_item` i
INNER JOIN `sys_dict` d ON i.`dict_id` = d.`id`
WHERE d.`dict_code` IN ('xslmes_downtime_responsibility', 'xslmes_downtime_fault_level');
DELETE FROM `sys_dict`
WHERE `dict_code` IN ('xslmes_downtime_responsibility', 'xslmes_downtime_fault_level');

View File

@@ -0,0 +1,28 @@
-- 仅建表 mes_xsl_downtime_type完整初始化请执行 mes-xsl-downtime-type-menu-permission.sql
SET NAMES utf8mb4;
CREATE TABLE IF NOT EXISTS `mes_xsl_downtime_type` (
`id` varchar(32) NOT NULL COMMENT '主键',
`process_operation_id` varchar(32) NOT NULL COMMENT '所属工序 mes_xsl_process_operation.id',
`process_operation_name` varchar(500) DEFAULT NULL COMMENT '工序名称冗余',
`downtime_main_type_id` varchar(32) NOT NULL COMMENT '所属主类型 mes_xsl_downtime_main_type.id',
`downtime_main_type_name` varchar(500) DEFAULT NULL COMMENT '主类型名称冗余停机主类型.downtime_type',
`downtime_type` varchar(500) NOT NULL COMMENT '停机类型同租户未删除数据中唯一',
`display_order` int NOT NULL DEFAULT '0' COMMENT '显示顺序升序必填',
`distinguish_color` varchar(500) DEFAULT NULL COMMENT '区分颜色十六进制色值',
`responsibility_distinct` varchar(500) DEFAULT NULL COMMENT '责任区分手填',
`fault_level` varchar(500) DEFAULT NULL COMMENT '故障等级手填',
`downtime_maintenance` varchar(1) DEFAULT '0' COMMENT '是否停机维修字典yn1是0否',
`status` varchar(1) NOT NULL DEFAULT '0' COMMENT '是否启用字典xslmes_downtime_type_status0启用1停用',
`tenant_id` int DEFAULT NULL COMMENT '租户',
`sys_org_code` varchar(500) DEFAULT NULL COMMENT '部门',
`create_by` varchar(500) DEFAULT NULL COMMENT '创建人',
`create_time` datetime DEFAULT NULL COMMENT '创建时间',
`update_by` varchar(500) DEFAULT NULL COMMENT '更新人',
`update_time` datetime DEFAULT NULL COMMENT '更新时间',
`del_flag` int DEFAULT '0' COMMENT '删除标记0正常1删除',
PRIMARY KEY (`id`),
KEY `idx_mdt_tenant_type` (`tenant_id`, `downtime_type`),
KEY `idx_mdt_process` (`process_operation_id`),
KEY `idx_mdt_main_type` (`downtime_main_type_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='MES停机类型';

View File

@@ -0,0 +1,91 @@
-- MES 设备点检配置主子表建表 + 菜单 + 按钮 + 租户 admin 授权
-- 权限前缀mes:mes_xsl_equip_inspect_config:*
-- 父菜单设备管理类型字典复用 xslmes_im_item_category须先有点检及保养项目功能
-- FlywayV3.9.2_78__mes_xsl_equip_inspect_config.sql
SET NAMES utf8mb4;
CREATE TABLE IF NOT EXISTS `mes_xsl_equip_inspect_config` (
`id` varchar(32) NOT NULL COMMENT '主键',
`equipment_ledger_id` varchar(32) NOT NULL COMMENT '设备台账主键 mes_xsl_equipment_ledger.id',
`equipment_name` varchar(500) DEFAULT NULL COMMENT '设备名称冗余',
`equipment_code` varchar(500) DEFAULT NULL COMMENT '设备编号冗余',
`config_type` varchar(500) NOT NULL COMMENT '配置类型字典xslmes_im_item_categoryinspect点检/maintain保养同设备同类型唯一',
`tenant_id` int DEFAULT NULL COMMENT '租户',
`sys_org_code` varchar(500) DEFAULT NULL COMMENT '部门',
`create_by` varchar(500) DEFAULT NULL COMMENT '创建人',
`create_time` datetime DEFAULT NULL COMMENT '创建时间',
`update_by` varchar(500) DEFAULT NULL COMMENT '更新人',
`update_time` datetime DEFAULT NULL COMMENT '更新时间',
`del_flag` int DEFAULT '0' COMMENT '删除标记0正常1删除',
PRIMARY KEY (`id`),
KEY `idx_meic_tenant_equip_type` (`tenant_id`, `equipment_ledger_id`, `config_type`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='MES设备点检配置';
CREATE TABLE IF NOT EXISTS `mes_xsl_equip_inspect_config_line` (
`id` varchar(32) NOT NULL COMMENT '主键',
`config_id` varchar(32) NOT NULL COMMENT '主表主键 mes_xsl_equip_inspect_config.id',
`inspect_maintain_item_id` varchar(32) NOT NULL COMMENT '点检及保养项目主键 mes_xsl_inspect_maintain_item.id',
`item_code` varchar(500) DEFAULT NULL COMMENT '点检项目编号冗余',
`item_name` varchar(500) DEFAULT NULL COMMENT '项目名称冗余',
`item_category` varchar(500) DEFAULT NULL COMMENT '项目类别冗余',
`item_type` varchar(500) DEFAULT NULL COMMENT '项目类型冗余',
`equipment_part_name` varchar(500) DEFAULT NULL COMMENT '设备部位名称冗余',
`equipment_sub_part_name` varchar(500) DEFAULT NULL COMMENT '设备小部位名称冗余',
`inspect_method` varchar(500) DEFAULT NULL COMMENT '点检方式冗余',
`judgment_criteria` varchar(500) DEFAULT NULL COMMENT '判断基准冗余',
`sort_no` int DEFAULT '0' COMMENT '排序号',
`create_by` varchar(500) DEFAULT NULL COMMENT '创建人',
`create_time` datetime DEFAULT NULL COMMENT '创建时间',
`update_by` varchar(500) DEFAULT NULL COMMENT '更新人',
`update_time` datetime DEFAULT NULL COMMENT '更新时间',
PRIMARY KEY (`id`),
KEY `idx_meicl_config` (`config_id`),
KEY `idx_meicl_item` (`inspect_maintain_item_id`),
UNIQUE KEY `uk_meicl_config_item` (`config_id`, `inspect_maintain_item_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='MES设备点检配置明细';
SET @mes_tenant_id = 1002;
SET @mes_equip_pid = (
SELECT `id` FROM `sys_permission`
WHERE `del_flag` = 0 AND `menu_type` = 0 AND `name` = '设备管理'
LIMIT 1
);
SET @mes_equip_pid = IFNULL(@mes_equip_pid, '1860000000000000133');
INSERT INTO `sys_permission`(`id`, `parent_id`, `name`, `url`, `component`, `component_name`, `menu_type`, `perms`, `perms_type`, `sort_no`, `is_route`, `is_leaf`, `hidden`, `status`, `del_flag`, `keep_alive`, `internal_or_external`, `create_by`, `create_time`)
VALUES ('1860000000000000148', @mes_equip_pid, '设备点检配置', '/xslmes/mesXslEquipInspectConfig', 'xslmes/mesXslEquipInspectConfig/MesXslEquipInspectConfigList', NULL, 1, NULL, '1', 12, 1, 0, 0, '1', 0, 1, 0, 'admin', NOW())
ON DUPLICATE KEY UPDATE
`parent_id` = VALUES(`parent_id`), `name` = VALUES(`name`), `url` = VALUES(`url`), `component` = VALUES(`component`), `component_name` = VALUES(`component_name`),
`menu_type` = VALUES(`menu_type`), `perms` = VALUES(`perms`), `perms_type` = VALUES(`perms_type`), `sort_no` = VALUES(`sort_no`),
`is_route` = VALUES(`is_route`), `is_leaf` = VALUES(`is_leaf`), `hidden` = VALUES(`hidden`), `status` = VALUES(`status`), `del_flag` = VALUES(`del_flag`),
`keep_alive` = VALUES(`keep_alive`), `internal_or_external` = VALUES(`internal_or_external`), `icon` = 'ant-design:control-outlined';
UPDATE `sys_permission` SET `icon` = 'ant-design:control-outlined' WHERE `id` = '1860000000000000148' AND `del_flag` = 0;
INSERT INTO `sys_permission`(`id`, `parent_id`, `name`, `menu_type`, `perms`, `perms_type`, `status`, `del_flag`, `create_by`, `create_time`) VALUES
('1860000000000000149', '1860000000000000148', '新增', 2, 'mes:mes_xsl_equip_inspect_config:add', '1', '1', 0, 'admin', NOW()),
('1860000000000000150', '1860000000000000148', '编辑', 2, 'mes:mes_xsl_equip_inspect_config:edit', '1', '1', 0, 'admin', NOW()),
('1860000000000000151', '1860000000000000148', '删除', 2, 'mes:mes_xsl_equip_inspect_config:delete', '1', '1', 0, 'admin', NOW()),
('1860000000000000152', '1860000000000000148', '批量删除', 2, 'mes:mes_xsl_equip_inspect_config:deleteBatch', '1', '1', 0, 'admin', NOW()),
('1860000000000000153', '1860000000000000148', '导出', 2, 'mes:mes_xsl_equip_inspect_config:exportXls', '1', '1', 0, 'admin', NOW()),
('1860000000000000154', '1860000000000000148', '导入', 2, 'mes:mes_xsl_equip_inspect_config:importExcel', '1', '1', 0, 'admin', NOW())
ON DUPLICATE KEY UPDATE
`parent_id` = VALUES(`parent_id`), `name` = VALUES(`name`), `menu_type` = VALUES(`menu_type`), `perms` = VALUES(`perms`), `perms_type` = VALUES(`perms_type`),
`status` = VALUES(`status`), `del_flag` = VALUES(`del_flag`);
INSERT INTO `sys_role_permission`(`id`, `role_id`, `permission_id`, `operate_date`, `operate_ip`)
SELECT REPLACE(UUID(), '-', ''), r.`id`, p.`id`, NOW(), '127.0.0.1'
FROM `sys_role` r
CROSS JOIN `sys_permission` p
WHERE r.`tenant_id` = @mes_tenant_id
AND r.`role_code` = 'admin'
AND p.`id` IN (
'1860000000000000148',
'1860000000000000149', '1860000000000000150', '1860000000000000151', '1860000000000000152',
'1860000000000000153', '1860000000000000154'
)
AND NOT EXISTS (
SELECT 1 FROM `sys_role_permission` rp
WHERE rp.`role_id` = r.`id` AND rp.`permission_id` = p.`id`
);

View File

@@ -0,0 +1,138 @@
-- MES 点检/保养记录主子表建表 + 字典 + 菜单 + 按钮 + 租户 admin 授权
-- 权限前缀mes:mes_xsl_equip_inspect_record:*
-- 父菜单设备管理依赖设备点检配置设备台账
-- FlywayV3.9.2_79__mes_xsl_equip_inspect_record.sql
SET NAMES utf8mb4;
INSERT INTO `sys_dict`(`id`, `dict_name`, `dict_code`, `description`, `del_flag`, `create_by`, `create_time`, `type`, `tenant_id`)
SELECT REPLACE(UUID(), '-', ''), 'MES点检记录结果', 'xslmes_im_inspect_result', '合格/不合格', 0, 'admin', NOW(), 0, 0
WHERE NOT EXISTS (SELECT 1 FROM `sys_dict` WHERE `dict_code` = 'xslmes_im_inspect_result' AND `del_flag` = 0);
INSERT INTO `sys_dict_item`(`id`, `dict_id`, `item_text`, `item_value`, `description`, `sort_order`, `status`, `create_by`, `create_time`)
SELECT REPLACE(UUID(), '-', ''), d.`id`, '合格', 'pass', '', 1, 1, 'admin', NOW()
FROM `sys_dict` d
WHERE d.`dict_code` = 'xslmes_im_inspect_result' AND NOT EXISTS (SELECT 1 FROM `sys_dict_item` i WHERE i.`dict_id` = d.`id` AND i.`item_value` = 'pass');
INSERT INTO `sys_dict_item`(`id`, `dict_id`, `item_text`, `item_value`, `description`, `sort_order`, `status`, `create_by`, `create_time`)
SELECT REPLACE(UUID(), '-', ''), d.`id`, '不合格', 'fail', '', 2, 1, 'admin', NOW()
FROM `sys_dict` d
WHERE d.`dict_code` = 'xslmes_im_inspect_result' AND NOT EXISTS (SELECT 1 FROM `sys_dict_item` i WHERE i.`dict_id` = d.`id` AND i.`item_value` = 'fail');
INSERT INTO `sys_dict`(`id`, `dict_name`, `dict_code`, `description`, `del_flag`, `create_by`, `create_time`, `type`, `tenant_id`)
SELECT REPLACE(UUID(), '-', ''), 'MES点检记录状态', 'xslmes_im_record_status', '待点检/已点检', 0, 'admin', NOW(), 0, 0
WHERE NOT EXISTS (SELECT 1 FROM `sys_dict` WHERE `dict_code` = 'xslmes_im_record_status' AND `del_flag` = 0);
INSERT INTO `sys_dict_item`(`id`, `dict_id`, `item_text`, `item_value`, `description`, `sort_order`, `status`, `create_by`, `create_time`)
SELECT REPLACE(UUID(), '-', ''), d.`id`, '待点检', 'pending', '', 1, 1, 'admin', NOW()
FROM `sys_dict` d
WHERE d.`dict_code` = 'xslmes_im_record_status' AND NOT EXISTS (SELECT 1 FROM `sys_dict_item` i WHERE i.`dict_id` = d.`id` AND i.`item_value` = 'pending');
INSERT INTO `sys_dict_item`(`id`, `dict_id`, `item_text`, `item_value`, `description`, `sort_order`, `status`, `create_by`, `create_time`)
SELECT REPLACE(UUID(), '-', ''), d.`id`, '已点检', 'done', '', 2, 1, 'admin', NOW()
FROM `sys_dict` d
WHERE d.`dict_code` = 'xslmes_im_record_status' AND NOT EXISTS (SELECT 1 FROM `sys_dict_item` i WHERE i.`dict_id` = d.`id` AND i.`item_value` = 'done');
CREATE TABLE IF NOT EXISTS `mes_xsl_equip_inspect_record` (
`id` varchar(32) NOT NULL COMMENT '主键',
`record_no` varchar(32) NOT NULL COMMENT '记录编号EC+yyyyMMdd+4位流水租户内按日递增',
`plan_no` varchar(500) DEFAULT NULL COMMENT '计划单号',
`plan_id` varchar(32) DEFAULT NULL COMMENT '计划主键隐藏',
`equipment_ledger_id` varchar(32) NOT NULL COMMENT '设备台账主键 mes_xsl_equipment_ledger.id',
`equipment_code` varchar(500) DEFAULT NULL COMMENT '设备编码冗余',
`equipment_name` varchar(500) DEFAULT NULL COMMENT '设备名称冗余',
`equip_inspect_config_id` varchar(32) DEFAULT NULL COMMENT '设备点检配置主键 mes_xsl_equip_inspect_config.id',
`record_type` varchar(500) NOT NULL COMMENT '类型字典xslmes_im_item_categoryinspect点检/maintain保养',
`inspect_date` date DEFAULT NULL COMMENT '点检日期',
`inspector_user_id` varchar(32) DEFAULT NULL COMMENT '点检人用户ID',
`inspector_username` varchar(500) DEFAULT NULL COMMENT '点检人账号',
`inspector_realname` varchar(500) DEFAULT NULL COMMENT '点检人姓名',
`inspect_result` varchar(500) NOT NULL COMMENT '点检结果字典xslmes_im_inspect_resultpass合格/fail不合格',
`record_status` varchar(500) NOT NULL COMMENT '状态字典xslmes_im_record_statuspending待点检/done已点检',
`handled_flag` varchar(1) DEFAULT NULL COMMENT '是否已处理字典yn1是0否仅不合格记录使用',
`handler_user_id` varchar(32) DEFAULT NULL COMMENT '处理人用户ID',
`handler_username` varchar(500) DEFAULT NULL COMMENT '处理人账号',
`handler_realname` varchar(500) DEFAULT NULL COMMENT '处理人姓名',
`handle_time` datetime DEFAULT NULL COMMENT '处理时间',
`tenant_id` int DEFAULT NULL COMMENT '租户',
`sys_org_code` varchar(500) DEFAULT NULL COMMENT '部门',
`create_by` varchar(500) DEFAULT NULL COMMENT '创建人',
`create_time` datetime DEFAULT NULL COMMENT '创建时间',
`update_by` varchar(500) DEFAULT NULL COMMENT '更新人',
`update_time` datetime DEFAULT NULL COMMENT '更新时间',
`del_flag` int DEFAULT '0' COMMENT '删除标记0正常1删除',
PRIMARY KEY (`id`),
UNIQUE KEY `uk_meir_tenant_record_no` (`tenant_id`, `record_no`),
KEY `idx_meir_equip_type` (`equipment_ledger_id`, `record_type`),
KEY `idx_meir_inspect_date` (`inspect_date`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='MES点检保养记录';
CREATE TABLE IF NOT EXISTS `mes_xsl_equip_inspect_record_line` (
`id` varchar(32) NOT NULL COMMENT '主键',
`record_id` varchar(32) NOT NULL COMMENT '主表主键 mes_xsl_equip_inspect_record.id',
`equip_inspect_config_line_id` varchar(32) NOT NULL COMMENT '设备点检配置明细主键 mes_xsl_equip_inspect_config_line.id',
`inspect_maintain_item_id` varchar(32) DEFAULT NULL COMMENT '点检及保养项目主键冗余',
`item_code` varchar(500) DEFAULT NULL COMMENT '点检项目编号冗余',
`item_name` varchar(500) DEFAULT NULL COMMENT '项目名称冗余',
`item_category` varchar(500) DEFAULT NULL COMMENT '项目类别冗余',
`item_type` varchar(500) DEFAULT NULL COMMENT '项目类型冗余',
`equipment_part_name` varchar(500) DEFAULT NULL COMMENT '设备部位冗余',
`equipment_sub_part_name` varchar(500) DEFAULT NULL COMMENT '设备小部位冗余',
`inspect_method` varchar(500) DEFAULT NULL COMMENT '点检方式冗余',
`judgment_criteria` varchar(500) DEFAULT NULL COMMENT '判断基准冗余',
`line_inspect_result` varchar(500) DEFAULT NULL COMMENT '明细点检结果文本',
`picture_files` varchar(2000) DEFAULT NULL COMMENT '图片上传路径逗号分隔',
`sort_no` int DEFAULT '0' COMMENT '排序号',
`create_by` varchar(500) DEFAULT NULL COMMENT '创建人',
`create_time` datetime DEFAULT NULL COMMENT '创建时间',
`update_by` varchar(500) DEFAULT NULL COMMENT '更新人',
`update_time` datetime DEFAULT NULL COMMENT '更新时间',
PRIMARY KEY (`id`),
KEY `idx_meirl_record` (`record_id`),
KEY `idx_meirl_config_line` (`equip_inspect_config_line_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='MES点检保养记录明细';
SET @mes_tenant_id = 1002;
SET @mes_equip_pid = (
SELECT `id` FROM `sys_permission`
WHERE `del_flag` = 0 AND `menu_type` = 0 AND `name` = '设备管理'
LIMIT 1
);
SET @mes_equip_pid = IFNULL(@mes_equip_pid, '1860000000000000133');
INSERT INTO `sys_permission`(`id`, `parent_id`, `name`, `url`, `component`, `component_name`, `menu_type`, `perms`, `perms_type`, `sort_no`, `is_route`, `is_leaf`, `hidden`, `status`, `del_flag`, `keep_alive`, `internal_or_external`, `create_by`, `create_time`)
VALUES ('1860000000000000155', @mes_equip_pid, '点检保养记录', '/xslmes/mesXslEquipInspectRecord', 'xslmes/mesXslEquipInspectRecord/MesXslEquipInspectRecordList', 'MesXslEquipInspectRecordList', 1, NULL, '1', 13, 1, 0, 0, '1', 0, 1, 0, 'admin', NOW())
ON DUPLICATE KEY UPDATE
`parent_id` = VALUES(`parent_id`), `name` = VALUES(`name`), `url` = VALUES(`url`), `component` = VALUES(`component`), `component_name` = VALUES(`component_name`),
`menu_type` = VALUES(`menu_type`), `perms` = VALUES(`perms`), `perms_type` = VALUES(`perms_type`), `sort_no` = VALUES(`sort_no`),
`is_route` = VALUES(`is_route`), `is_leaf` = VALUES(`is_leaf`), `hidden` = VALUES(`hidden`), `status` = VALUES(`status`), `del_flag` = VALUES(`del_flag`),
`keep_alive` = VALUES(`keep_alive`), `internal_or_external` = VALUES(`internal_or_external`), `icon` = 'ant-design:file-done-outlined';
UPDATE `sys_permission` SET `icon` = 'ant-design:file-done-outlined' WHERE `id` = '1860000000000000155' AND `del_flag` = 0;
INSERT INTO `sys_permission`(`id`, `parent_id`, `name`, `menu_type`, `perms`, `perms_type`, `status`, `del_flag`, `create_by`, `create_time`) VALUES
('1860000000000000156', '1860000000000000155', '新增', 2, 'mes:mes_xsl_equip_inspect_record:add', '1', '1', 0, 'admin', NOW()),
('1860000000000000157', '1860000000000000155', '编辑', 2, 'mes:mes_xsl_equip_inspect_record:edit', '1', '1', 0, 'admin', NOW()),
('1860000000000000158', '1860000000000000155', '删除', 2, 'mes:mes_xsl_equip_inspect_record:delete', '1', '1', 0, 'admin', NOW()),
('1860000000000000159', '1860000000000000155', '批量删除', 2, 'mes:mes_xsl_equip_inspect_record:deleteBatch', '1', '1', 0, 'admin', NOW()),
('1860000000000000160', '1860000000000000155', '导出', 2, 'mes:mes_xsl_equip_inspect_record:exportXls', '1', '1', 0, 'admin', NOW()),
('1860000000000000161', '1860000000000000155', '导入', 2, 'mes:mes_xsl_equip_inspect_record:importExcel', '1', '1', 0, 'admin', NOW())
ON DUPLICATE KEY UPDATE
`parent_id` = VALUES(`parent_id`), `name` = VALUES(`name`), `menu_type` = VALUES(`menu_type`), `perms` = VALUES(`perms`), `perms_type` = VALUES(`perms_type`),
`status` = VALUES(`status`), `del_flag` = VALUES(`del_flag`);
INSERT INTO `sys_role_permission`(`id`, `role_id`, `permission_id`, `operate_date`, `operate_ip`)
SELECT REPLACE(UUID(), '-', ''), r.`id`, p.`id`, NOW(), '127.0.0.1'
FROM `sys_role` r
CROSS JOIN `sys_permission` p
WHERE r.`tenant_id` = @mes_tenant_id
AND r.`role_code` = 'admin'
AND p.`id` IN (
'1860000000000000155',
'1860000000000000156', '1860000000000000157', '1860000000000000158', '1860000000000000159',
'1860000000000000160', '1860000000000000161'
)
AND NOT EXISTS (
SELECT 1 FROM `sys_role_permission` rp
WHERE rp.`role_id` = r.`id` AND rp.`permission_id` = p.`id`
);

View File

@@ -0,0 +1,65 @@
-- MES 设备对应部位建表 + 菜单 + 按钮 + 租户 admin 授权可整文件一次执行
-- 权限前缀mes:mes_xsl_equip_part_mapping:*
-- 数据由设备点检配置保存后自动生成列表无手工新增
-- FlywayV3.9.2_123__mes_xsl_equip_part_mapping.sql
SET NAMES utf8mb4;
CREATE TABLE IF NOT EXISTS `mes_xsl_equip_part_mapping` (
`id` varchar(32) NOT NULL COMMENT '主键',
`equipment_ledger_id` varchar(32) NOT NULL COMMENT '设备台账主键 mes_xsl_equipment_ledger.id',
`equipment_name` varchar(500) NOT NULL COMMENT '设备名称',
`machine_code` varchar(500) DEFAULT NULL COMMENT '机台代号设备编号冗余',
`equipment_part_id` varchar(32) NOT NULL COMMENT '设备大部位主键 mes_xsl_equipment_part.id',
`equipment_part_name` varchar(500) DEFAULT NULL COMMENT '设备大部位名称',
`part_code` varchar(500) DEFAULT NULL COMMENT '大部位代码',
`equipment_sub_part_id` varchar(32) NOT NULL COMMENT '设备小部位主键 mes_xsl_equipment_sub_part.id',
`equipment_sub_part_name` varchar(500) DEFAULT NULL COMMENT '设备小部位名称',
`sub_part_code` varchar(500) DEFAULT NULL COMMENT '小部位代码',
`tenant_id` int DEFAULT NULL COMMENT '租户',
`sys_org_code` varchar(64) DEFAULT NULL COMMENT '部门',
`create_by` varchar(32) DEFAULT NULL COMMENT '创建人',
`create_time` datetime DEFAULT NULL COMMENT '创建时间',
`update_by` varchar(32) DEFAULT NULL COMMENT '更新人',
`update_time` datetime DEFAULT NULL COMMENT '更新时间',
`del_flag` int DEFAULT '0' COMMENT '删除标记0正常1删除',
PRIMARY KEY (`id`),
UNIQUE KEY `uk_mepm_ledger_part_sub` (`equipment_ledger_id`, `equipment_part_id`, `equipment_sub_part_id`),
KEY `idx_mepm_tenant_equip_name` (`tenant_id`, `equipment_name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='MES设备对应部位';
SET @mes_tenant_id = 1002;
SET @mes_equip_pid = (
SELECT `id` FROM `sys_permission`
WHERE `del_flag` = 0 AND `menu_type` = 0 AND `name` = '设备管理'
LIMIT 1
);
SET @mes_equip_pid = IFNULL(@mes_equip_pid, '1860000000000000133');
INSERT INTO `sys_permission`(`id`, `parent_id`, `name`, `url`, `component`, `component_name`, `menu_type`, `perms`, `perms_type`, `sort_no`, `is_route`, `is_leaf`, `hidden`, `status`, `del_flag`, `keep_alive`, `internal_or_external`, `create_by`, `create_time`)
VALUES ('1860000000000000215', @mes_equip_pid, '设备对应部位', '/xslmes/mesXslEquipPartMapping', 'xslmes/mesXslEquipPartMapping/MesXslEquipPartMappingList', 'MesXslEquipPartMappingList', 1, NULL, '1', 14, 1, 0, 0, '1', 0, 1, 0, 'admin', NOW())
ON DUPLICATE KEY UPDATE
`parent_id` = VALUES(`parent_id`), `name` = VALUES(`name`), `url` = VALUES(`url`), `component` = VALUES(`component`), `component_name` = VALUES(`component_name`),
`menu_type` = VALUES(`menu_type`), `perms` = VALUES(`perms`), `perms_type` = VALUES(`perms_type`), `sort_no` = VALUES(`sort_no`),
`is_route` = VALUES(`is_route`), `is_leaf` = VALUES(`is_leaf`), `hidden` = VALUES(`hidden`), `status` = VALUES(`status`), `del_flag` = VALUES(`del_flag`),
`keep_alive` = VALUES(`keep_alive`), `internal_or_external` = VALUES(`internal_or_external`), `icon` = 'ant-design:apartment-outlined';
UPDATE `sys_permission` SET `icon` = 'ant-design:apartment-outlined' WHERE `id` = '1860000000000000215' AND `del_flag` = 0;
INSERT INTO `sys_permission`(`id`, `parent_id`, `name`, `menu_type`, `perms`, `perms_type`, `status`, `del_flag`, `create_by`, `create_time`) VALUES
('1860000000000000216', '1860000000000000215', '导出', 2, 'mes:mes_xsl_equip_part_mapping:exportXls', '1', '1', 0, 'admin', NOW())
ON DUPLICATE KEY UPDATE
`parent_id` = VALUES(`parent_id`), `name` = VALUES(`name`), `menu_type` = VALUES(`menu_type`), `perms` = VALUES(`perms`), `perms_type` = VALUES(`perms_type`),
`status` = VALUES(`status`), `del_flag` = VALUES(`del_flag`);
INSERT INTO `sys_role_permission`(`id`, `role_id`, `permission_id`, `operate_date`, `operate_ip`)
SELECT REPLACE(UUID(), '-', ''), r.`id`, p.`id`, NOW(), '127.0.0.1'
FROM `sys_role` r
CROSS JOIN `sys_permission` p
WHERE r.`tenant_id` = @mes_tenant_id
AND r.`role_code` = 'admin'
AND p.`id` IN ('1860000000000000215', '1860000000000000216')
AND NOT EXISTS (
SELECT 1 FROM `sys_role_permission` rp
WHERE rp.`role_id` = r.`id` AND rp.`permission_id` = p.`id`
);

View File

@@ -56,30 +56,31 @@ WHERE d.`dict_code` = 'xslmes_equipment_maintain_distinct'
SET @mes_tenant_id = 1002;
SET @mes_base_pid = (
SELECT MIN(`id`) FROM `sys_permission`
WHERE `del_flag` = 0 AND `menu_type` = 0 AND `name` IN ('MES基础资料', 'MES资料')
SET @mes_equip_pid = (
SELECT `id` FROM `sys_permission`
WHERE `del_flag` = 0 AND `menu_type` = 0 AND `name` = '设备管理'
LIMIT 1
);
SET @mes_base_pid = IFNULL(@mes_base_pid, '1860000000000000001');
SET @mes_equip_pid = IFNULL(@mes_equip_pid, '1860000000000000133');
INSERT INTO `sys_permission`(`id`, `parent_id`, `name`, `url`, `component`, `component_name`, `menu_type`, `perms`, `perms_type`, `sort_no`, `is_route`, `is_leaf`, `hidden`, `status`, `del_flag`, `keep_alive`, `internal_or_external`, `create_by`, `create_time`)
VALUES ('1860000000000000070', @mes_base_pid, '设备类别', '/xslmes/mesXslEquipmentCategory', 'xslmes/mesXslEquipmentCategory/MesXslEquipmentCategoryList', NULL, 1, NULL, '1', 10, 1, 0, 0, '1', 0, 1, 0, 'admin', NOW())
VALUES ('1860000000000000070', @mes_equip_pid, '设备类别', '/xslmes/mesXslEquipmentCategory', 'xslmes/mesXslEquipmentCategory/MesXslEquipmentCategoryList', NULL, 1, NULL, '1', 2, 1, 0, 0, '1', 0, 1, 0, 'admin', NOW())
ON DUPLICATE KEY UPDATE
`parent_id` = VALUES(`parent_id`), `name` = VALUES(`name`), `url` = VALUES(`url`), `component` = VALUES(`component`), `component_name` = VALUES(`component_name`),
`menu_type` = VALUES(`menu_type`), `perms` = VALUES(`perms`), `perms_type` = VALUES(`perms_type`), `sort_no` = VALUES(`sort_no`),
`is_route` = VALUES(`is_route`), `is_leaf` = VALUES(`is_leaf`), `hidden` = VALUES(`hidden`), `status` = VALUES(`status`), `del_flag` = VALUES(`del_flag`),
`is_route` = VALUES(`is_route`), `is_leaf` = 0, `hidden` = 0, `status` = '1', `del_flag` = 0,
`keep_alive` = VALUES(`keep_alive`), `internal_or_external` = VALUES(`internal_or_external`);
INSERT INTO `sys_permission`(`id`, `parent_id`, `name`, `menu_type`, `perms`, `perms_type`, `status`, `del_flag`, `create_by`, `create_time`) VALUES
('1860000000000000071', '1860000000000000070', '新增', 2, 'mes:mes_xsl_equipment_category:add', '1', '1', 0, 'admin', NOW()),
('1860000000000000072', '1860000000000000070', '编辑', 2, 'mes:mes_xsl_equipment_category:edit', '1', '1', 0, 'admin', NOW()),
('1860000000000000073', '1860000000000000070', '删除', 2, 'mes:mes_xsl_equipment_category:delete', '1', '1', 0, 'admin', NOW()),
('1860000000000000074', '1860000000000000070', '批量删除', 2, 'mes:mes_xsl_equipment_category:deleteBatch', '1', '1', 0, 'admin', NOW()),
('1860000000000000075', '1860000000000000070', '导出', 2, 'mes:mes_xsl_equipment_category:exportXls', '1', '1', 0, 'admin', NOW()),
('1860000000000000076', '1860000000000000070', '导入', 2, 'mes:mes_xsl_equipment_category:importExcel', '1', '1', 0, 'admin', NOW())
INSERT INTO `sys_permission`(`id`, `parent_id`, `name`, `menu_type`, `perms`, `perms_type`, `is_leaf`, `status`, `del_flag`, `create_by`, `create_time`) VALUES
('1860000000000000071', '1860000000000000070', '新增', 2, 'mes:mes_xsl_equipment_category:add', '1', 1, '1', 0, 'admin', NOW()),
('1860000000000000072', '1860000000000000070', '编辑', 2, 'mes:mes_xsl_equipment_category:edit', '1', 1, '1', 0, 'admin', NOW()),
('1860000000000000073', '1860000000000000070', '删除', 2, 'mes:mes_xsl_equipment_category:delete', '1', 1, '1', 0, 'admin', NOW()),
('1860000000000000074', '1860000000000000070', '批量删除', 2, 'mes:mes_xsl_equipment_category:deleteBatch', '1', 1, '1', 0, 'admin', NOW()),
('1860000000000000075', '1860000000000000070', '导出', 2, 'mes:mes_xsl_equipment_category:exportXls', '1', 1, '1', 0, 'admin', NOW()),
('1860000000000000076', '1860000000000000070', '导入', 2, 'mes:mes_xsl_equipment_category:importExcel', '1', 1, '1', 0, 'admin', NOW())
ON DUPLICATE KEY UPDATE
`parent_id` = VALUES(`parent_id`), `name` = VALUES(`name`), `menu_type` = VALUES(`menu_type`), `perms` = VALUES(`perms`), `perms_type` = VALUES(`perms_type`),
`status` = VALUES(`status`), `del_flag` = VALUES(`del_flag`);
`is_leaf` = 1, `status` = '1', `del_flag` = 0;
INSERT INTO `sys_role_permission`(`id`, `role_id`, `permission_id`, `operate_date`, `operate_ip`)
SELECT REPLACE(UUID(), '-', ''), r.`id`, p.`id`, NOW(), '127.0.0.1'

View File

@@ -0,0 +1,31 @@
-- 设备管理目录 MES管理 下迁出 MES基础资料 同级已执行旧版 mes-xsl-equipment-ledger-menu-permission 时用
SET NAMES utf8mb4;
SET @mes_equip_root_parent = (
SELECT `parent_id` FROM `sys_permission`
WHERE `del_flag` = 0 AND `menu_type` = 0 AND `name` = 'MES基础资料'
LIMIT 1
);
SET @mes_equip_root_parent = IFNULL(@mes_equip_root_parent, (
SELECT `parent_id` FROM `sys_permission`
WHERE `del_flag` = 0 AND `menu_type` = 0 AND `name` = 'MES资料'
LIMIT 1
));
SET @mes_equip_root_sort = IFNULL((
SELECT `sort_no` + 1 FROM `sys_permission`
WHERE `del_flag` = 0 AND `menu_type` = 0 AND `name` IN ('MES基础资料', 'MES资料')
ORDER BY `sort_no` DESC
LIMIT 1
), 51);
UPDATE `sys_permission`
SET
`parent_id` = @mes_equip_root_parent,
`sort_no` = @mes_equip_root_sort,
`menu_type` = 0,
`is_leaf` = 0,
`hidden` = 0,
`status` = '1',
`del_flag` = 0
WHERE `id` = '1860000000000000133';

View File

@@ -0,0 +1,133 @@
-- MES 设备台账字典 + 建表 + 设备管理目录菜单 + 设备台账菜单 + 按钮 + 租户 admin 授权可整文件一次执行
-- 权限前缀mes:mes_xsl_equipment_ledger:*
-- 父菜单设备管理目录 MES基础资料 同级 MES管理 子级子菜单设备台账
-- 修改租户 SET @mes_tenant_id新环境也可依赖 Flyway V3.9.2_72__mes_xsl_equipment_ledger.sql
SET NAMES utf8mb4;
INSERT INTO `sys_dict` (`id`, `dict_name`, `dict_code`, `description`, `del_flag`, `create_by`, `create_time`, `type`, `tenant_id`)
SELECT REPLACE(UUID(), '-', ''), 'MES设备台账状态', 'xslmes_equipment_ledger_status', '在用/停用/报废', 0, 'admin', NOW(), 0, 0
WHERE NOT EXISTS (SELECT 1 FROM `sys_dict` WHERE `dict_code` = 'xslmes_equipment_ledger_status' AND `del_flag` = 0);
INSERT INTO `sys_dict_item` (`id`, `dict_id`, `item_text`, `item_value`, `sort_order`, `status`, `create_by`, `create_time`)
SELECT REPLACE(UUID(), '-', ''), d.id, '在用', '0', 1, 1, 'admin', NOW() FROM `sys_dict` d
WHERE d.`dict_code` = 'xslmes_equipment_ledger_status' AND NOT EXISTS (SELECT 1 FROM `sys_dict_item` i WHERE i.`dict_id` = d.id AND i.`item_value` = '0');
INSERT INTO `sys_dict_item` (`id`, `dict_id`, `item_text`, `item_value`, `sort_order`, `status`, `create_by`, `create_time`)
SELECT REPLACE(UUID(), '-', ''), d.id, '停用', '1', 2, 1, 'admin', NOW() FROM `sys_dict` d
WHERE d.`dict_code` = 'xslmes_equipment_ledger_status' AND NOT EXISTS (SELECT 1 FROM `sys_dict_item` i WHERE i.`dict_id` = d.id AND i.`item_value` = '1');
INSERT INTO `sys_dict_item` (`id`, `dict_id`, `item_text`, `item_value`, `sort_order`, `status`, `create_by`, `create_time`)
SELECT REPLACE(UUID(), '-', ''), d.id, '报废', '2', 3, 1, 'admin', NOW() FROM `sys_dict` d
WHERE d.`dict_code` = 'xslmes_equipment_ledger_status' AND NOT EXISTS (SELECT 1 FROM `sys_dict_item` i WHERE i.`dict_id` = d.id AND i.`item_value` = '2');
CREATE TABLE IF NOT EXISTS `mes_xsl_equipment_ledger` (
`id` varchar(32) NOT NULL COMMENT '主键',
`process_operation_id` varchar(32) NOT NULL COMMENT '所属工序 mes_xsl_process_operation.id',
`process_operation_name` varchar(500) DEFAULT NULL COMMENT '工序名称冗余',
`equipment_name` varchar(500) NOT NULL COMMENT '设备名称同租户未删除唯一',
`ledger_no` varchar(16) DEFAULT NULL COMMENT '编号租户内从001递增自动生成只读',
`equipment_code` varchar(128) NOT NULL COMMENT '设备编号同租户未删除唯一',
`manufacturer_id` varchar(32) DEFAULT NULL COMMENT '所属设备厂家 mes_xsl_manufacturer.id',
`manufacturer_name` varchar(500) DEFAULT NULL COMMENT '设备厂家名称冗余',
`equipment_category_id` varchar(32) DEFAULT NULL COMMENT '设备类别 mes_xsl_equipment_category.id',
`equipment_category_name` varchar(500) DEFAULT NULL COMMENT '设备类别名称冗余',
`equipment_type_id` varchar(32) DEFAULT NULL COMMENT '设备类型 mes_xsl_equipment_type.id',
`equipment_type_name` varchar(500) DEFAULT NULL COMMENT '设备类型名称冗余',
`factory_id` varchar(32) DEFAULT NULL COMMENT '所属工厂厂家信息',
`factory_name` varchar(500) DEFAULT NULL COMMENT '所属工厂名称冗余',
`equipment_model` varchar(500) DEFAULT NULL COMMENT '设备型号',
`equipment_status` varchar(1) NOT NULL DEFAULT '0' COMMENT '设备状态 字典xslmes_equipment_ledger_status0在用1停用2报废',
`serial_no` varchar(500) DEFAULT NULL COMMENT '序列号',
`nameplate` varchar(500) DEFAULT NULL COMMENT '铭牌',
`maintain_dept_id` varchar(32) DEFAULT NULL COMMENT '维修部门 sys_depart.id',
`maintain_person` varchar(500) DEFAULT NULL COMMENT '维修人员',
`manage_dept_id` varchar(32) DEFAULT NULL COMMENT '主管部门 sys_depart.id',
`doc_file_no` varchar(500) DEFAULT NULL COMMENT '资料文件编号',
`production_date` date DEFAULT NULL COMMENT '生产日期',
`purchase_date` date DEFAULT NULL COMMENT '购买日期',
`use_date` date DEFAULT NULL COMMENT '使用日期',
`vendor_contact` varchar(500) DEFAULT NULL COMMENT '厂商联系人',
`asset_value` varchar(128) DEFAULT NULL COMMENT '价值',
`controlled_pda` varchar(500) DEFAULT NULL COMMENT '受控PDA',
`overproduction_ratio` varchar(128) DEFAULT NULL COMMENT '超产比率',
`effective_volume` varchar(128) DEFAULT NULL COMMENT '有效体积',
`enabled_flag` varchar(1) NOT NULL DEFAULT '1' COMMENT '是否启用 字典yn1是0否',
`equipment_desc` varchar(1000) DEFAULT NULL COMMENT '设备描述',
`tenant_id` int DEFAULT NULL COMMENT '租户',
`sys_org_code` varchar(500) DEFAULT NULL COMMENT '部门',
`create_by` varchar(500) DEFAULT NULL COMMENT '创建人',
`create_time` datetime DEFAULT NULL COMMENT '创建时间',
`update_by` varchar(500) DEFAULT NULL COMMENT '更新人',
`update_time` datetime DEFAULT NULL COMMENT '更新时间',
`del_flag` int DEFAULT '0' COMMENT '删除标记0正常1删除',
PRIMARY KEY (`id`),
KEY `idx_mel_tenant_code` (`tenant_id`, `equipment_code`),
KEY `idx_mel_tenant_ledger_no` (`tenant_id`, `ledger_no`),
KEY `idx_mel_tenant_name` (`tenant_id`, `equipment_name`),
KEY `idx_mel_process` (`process_operation_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='MES设备台账';
SET @mes_tenant_id = 1002;
-- MES基础资料同级取其 parent_id通常为 NULL MES管理 并列
SET @mes_equip_root_parent = (
SELECT `parent_id` FROM `sys_permission`
WHERE `del_flag` = 0 AND `menu_type` = 0 AND `name` = 'MES基础资料'
LIMIT 1
);
SET @mes_equip_root_parent = IFNULL(@mes_equip_root_parent, (
SELECT `parent_id` FROM `sys_permission`
WHERE `del_flag` = 0 AND `menu_type` = 0 AND `name` = 'MES资料'
LIMIT 1
));
SET @mes_equip_root_sort = IFNULL((
SELECT `sort_no` + 1 FROM `sys_permission`
WHERE `del_flag` = 0 AND `menu_type` = 0 AND `name` IN ('MES基础资料', 'MES资料')
ORDER BY `sort_no` DESC
LIMIT 1
), 51);
UPDATE `sys_permission`
SET `is_leaf` = 0
WHERE `id` = '1860000000000000133' AND `del_flag` = 0;
INSERT INTO `sys_permission`(`id`, `parent_id`, `name`, `url`, `component`, `component_name`, `menu_type`, `perms`, `perms_type`, `sort_no`, `is_route`, `is_leaf`, `hidden`, `status`, `del_flag`, `keep_alive`, `internal_or_external`, `create_by`, `create_time`)
VALUES ('1860000000000000133', @mes_equip_root_parent, '设备管理', '/xslmes/equipment', 'layouts/RouteView', 'MesEquipmentLayout', 0, NULL, '1', @mes_equip_root_sort, 1, 0, 0, '1', 0, 0, 0, 'admin', NOW())
ON DUPLICATE KEY UPDATE
`parent_id` = VALUES(`parent_id`), `name` = VALUES(`name`), `url` = VALUES(`url`), `component` = VALUES(`component`),
`menu_type` = VALUES(`menu_type`), `icon` = 'ant-design:tool-outlined', `is_leaf` = 0, `hidden` = 0, `status` = '1', `del_flag` = 0;
UPDATE `sys_permission` SET `icon` = 'ant-design:tool-outlined' WHERE `id` = '1860000000000000133' AND `del_flag` = 0;
INSERT INTO `sys_permission`(`id`, `parent_id`, `name`, `url`, `component`, `component_name`, `menu_type`, `perms`, `perms_type`, `sort_no`, `is_route`, `is_leaf`, `hidden`, `status`, `del_flag`, `keep_alive`, `internal_or_external`, `create_by`, `create_time`)
VALUES ('1860000000000000134', '1860000000000000133', '设备台账', '/xslmes/mesXslEquipmentLedger', 'xslmes/mesXslEquipmentLedger/MesXslEquipmentLedgerList', 'MesXslEquipmentLedgerList', 1, NULL, '1', 1, 1, 0, 0, '1', 0, 1, 0, 'admin', NOW())
ON DUPLICATE KEY UPDATE
`parent_id` = VALUES(`parent_id`), `name` = VALUES(`name`), `url` = VALUES(`url`), `component` = VALUES(`component`), `component_name` = VALUES(`component_name`),
`is_leaf` = 0, `hidden` = 0, `status` = '1', `del_flag` = 0;
INSERT INTO `sys_permission`(`id`, `parent_id`, `name`, `menu_type`, `perms`, `perms_type`, `status`, `del_flag`, `create_by`, `create_time`) VALUES
('1860000000000000135', '1860000000000000134', '新增', 2, 'mes:mes_xsl_equipment_ledger:add', '1', '1', 0, 'admin', NOW()),
('1860000000000000136', '1860000000000000134', '编辑', 2, 'mes:mes_xsl_equipment_ledger:edit', '1', '1', 0, 'admin', NOW()),
('1860000000000000137', '1860000000000000134', '删除', 2, 'mes:mes_xsl_equipment_ledger:delete', '1', '1', 0, 'admin', NOW()),
('1860000000000000138', '1860000000000000134', '批量删除', 2, 'mes:mes_xsl_equipment_ledger:deleteBatch', '1', '1', 0, 'admin', NOW()),
('1860000000000000139', '1860000000000000134', '导出', 2, 'mes:mes_xsl_equipment_ledger:exportXls', '1', '1', 0, 'admin', NOW()),
('1860000000000000140', '1860000000000000134', '导入', 2, 'mes:mes_xsl_equipment_ledger:importExcel', '1', '1', 0, 'admin', NOW())
ON DUPLICATE KEY UPDATE
`parent_id` = VALUES(`parent_id`), `name` = VALUES(`name`), `menu_type` = VALUES(`menu_type`), `perms` = VALUES(`perms`),
`status` = VALUES(`status`), `del_flag` = VALUES(`del_flag`);
INSERT INTO `sys_role_permission`(`id`, `role_id`, `permission_id`, `operate_date`, `operate_ip`)
SELECT REPLACE(UUID(), '-', ''), r.`id`, p.`id`, NOW(), '127.0.0.1'
FROM `sys_role` r
CROSS JOIN `sys_permission` p
WHERE r.`tenant_id` = @mes_tenant_id
AND r.`role_code` = 'admin'
AND p.`id` IN (
'1860000000000000133',
'1860000000000000134',
'1860000000000000135', '1860000000000000136', '1860000000000000137', '1860000000000000138',
'1860000000000000139', '1860000000000000140'
)
AND NOT EXISTS (
SELECT 1 FROM `sys_role_permission` rp
WHERE rp.`role_id` = r.`id` AND rp.`permission_id` = p.`id`
);

View File

@@ -0,0 +1,48 @@
-- MES 设备台账仅建表完整初始化请执行 mes-xsl-equipment-ledger-menu-permission.sql
SET NAMES utf8mb4;
CREATE TABLE IF NOT EXISTS `mes_xsl_equipment_ledger` (
`id` varchar(32) NOT NULL COMMENT '主键',
`process_operation_id` varchar(32) NOT NULL COMMENT '所属工序',
`process_operation_name` varchar(500) DEFAULT NULL COMMENT '工序名称冗余',
`equipment_name` varchar(500) NOT NULL COMMENT '设备名称',
`ledger_no` varchar(16) DEFAULT NULL COMMENT '编号租户内从001递增自动生成只读',
`equipment_code` varchar(128) NOT NULL COMMENT '设备编号同租户不可重复',
`manufacturer_id` varchar(32) DEFAULT NULL COMMENT '所属设备厂家',
`manufacturer_name` varchar(500) DEFAULT NULL COMMENT '设备厂家名称冗余',
`equipment_category_id` varchar(32) DEFAULT NULL COMMENT '设备类别',
`equipment_category_name` varchar(500) DEFAULT NULL COMMENT '设备类别名称冗余',
`equipment_type_id` varchar(32) DEFAULT NULL COMMENT '设备类型',
`equipment_type_name` varchar(500) DEFAULT NULL COMMENT '设备类型名称冗余',
`factory_id` varchar(32) DEFAULT NULL COMMENT '所属工厂',
`factory_name` varchar(500) DEFAULT NULL COMMENT '所属工厂名称冗余',
`equipment_model` varchar(500) DEFAULT NULL COMMENT '设备型号',
`equipment_status` varchar(1) NOT NULL DEFAULT '0' COMMENT '设备状态',
`serial_no` varchar(500) DEFAULT NULL COMMENT '序列号',
`nameplate` varchar(500) DEFAULT NULL COMMENT '铭牌',
`maintain_dept_id` varchar(32) DEFAULT NULL COMMENT '维修部门',
`maintain_person` varchar(500) DEFAULT NULL COMMENT '维修人员',
`manage_dept_id` varchar(32) DEFAULT NULL COMMENT '主管部门',
`doc_file_no` varchar(500) DEFAULT NULL COMMENT '资料文件编号',
`production_date` date DEFAULT NULL COMMENT '生产日期',
`purchase_date` date DEFAULT NULL COMMENT '购买日期',
`use_date` date DEFAULT NULL COMMENT '使用日期',
`vendor_contact` varchar(500) DEFAULT NULL COMMENT '厂商联系人',
`asset_value` varchar(128) DEFAULT NULL COMMENT '价值',
`controlled_pda` varchar(500) DEFAULT NULL COMMENT '受控PDA',
`overproduction_ratio` varchar(128) DEFAULT NULL COMMENT '超产比率',
`effective_volume` varchar(128) DEFAULT NULL COMMENT '有效体积',
`enabled_flag` varchar(1) NOT NULL DEFAULT '1' COMMENT '是否启用',
`equipment_desc` varchar(1000) DEFAULT NULL COMMENT '设备描述',
`tenant_id` int DEFAULT NULL COMMENT '租户',
`sys_org_code` varchar(500) DEFAULT NULL COMMENT '部门',
`create_by` varchar(500) DEFAULT NULL COMMENT '创建人',
`create_time` datetime DEFAULT NULL COMMENT '创建时间',
`update_by` varchar(500) DEFAULT NULL COMMENT '更新人',
`update_time` datetime DEFAULT NULL COMMENT '更新时间',
`del_flag` int DEFAULT '0' COMMENT '删除标记',
PRIMARY KEY (`id`),
KEY `idx_mel_tenant_code` (`tenant_id`, `equipment_code`),
KEY `idx_mel_tenant_ledger_no` (`tenant_id`, `ledger_no`),
KEY `idx_mel_tenant_name` (`tenant_id`, `equipment_name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='MES设备台账';

View File

@@ -0,0 +1,10 @@
-- 设备管理目录及指定子菜单图标可重复执行
SET NAMES utf8mb4;
UPDATE `sys_permission` SET `icon` = 'ant-design:tool-outlined' WHERE `id` = '1860000000000000133' AND `del_flag` = 0;
UPDATE `sys_permission` SET `icon` = 'ant-design:apartment-outlined' WHERE `id` = '1860000000000000091' AND `del_flag` = 0;
UPDATE `sys_permission` SET `icon` = 'ant-design:tags-outlined' WHERE `id` = '1860000000000000098' AND `del_flag` = 0;
UPDATE `sys_permission` SET `icon` = 'ant-design:shopping-outlined' WHERE `id` = '1860000000000000105' AND `del_flag` = 0;
UPDATE `sys_permission` SET `icon` = 'ant-design:shop-outlined' WHERE `id` = '1860000000000000112' AND `del_flag` = 0;
UPDATE `sys_permission` SET `icon` = 'ant-design:partition-outlined' WHERE `id` = '1860000000000000119' AND `del_flag` = 0;
UPDATE `sys_permission` SET `icon` = 'ant-design:pause-circle-outlined' WHERE `id` = '1860000000000000126' AND `del_flag` = 0;

View File

@@ -24,14 +24,15 @@ CREATE TABLE IF NOT EXISTS `mes_xsl_equipment_part` (
SET @mes_tenant_id = 1002;
SET @mes_base_pid = (
SELECT MIN(`id`) FROM `sys_permission`
WHERE `del_flag` = 0 AND `menu_type` = 0 AND `name` IN ('MES基础资料', 'MES资料')
SET @mes_equip_pid = (
SELECT `id` FROM `sys_permission`
WHERE `del_flag` = 0 AND `menu_type` = 0 AND `name` = '设备管理'
LIMIT 1
);
SET @mes_base_pid = IFNULL(@mes_base_pid, '1860000000000000001');
SET @mes_equip_pid = IFNULL(@mes_equip_pid, '1860000000000000133');
INSERT INTO `sys_permission`(`id`, `parent_id`, `name`, `url`, `component`, `component_name`, `menu_type`, `perms`, `perms_type`, `sort_no`, `is_route`, `is_leaf`, `hidden`, `status`, `del_flag`, `keep_alive`, `internal_or_external`, `create_by`, `create_time`)
VALUES ('1860000000000000084', @mes_base_pid, '设备部位', '/xslmes/mesXslEquipmentPart', 'xslmes/mesXslEquipmentPart/MesXslEquipmentPartList', NULL, 1, NULL, '1', 12, 1, 0, 0, '1', 0, 1, 0, 'admin', NOW())
VALUES ('1860000000000000084', @mes_equip_pid, '设备部位', '/xslmes/mesXslEquipmentPart', 'xslmes/mesXslEquipmentPart/MesXslEquipmentPartList', NULL, 1, NULL, '1', 4, 1, 0, 0, '1', 0, 1, 0, 'admin', NOW())
ON DUPLICATE KEY UPDATE
`parent_id` = VALUES(`parent_id`), `name` = VALUES(`name`), `url` = VALUES(`url`), `component` = VALUES(`component`), `component_name` = VALUES(`component_name`),
`menu_type` = VALUES(`menu_type`), `perms` = VALUES(`perms`), `perms_type` = VALUES(`perms_type`), `sort_no` = VALUES(`sort_no`),

View File

@@ -27,19 +27,22 @@ CREATE TABLE IF NOT EXISTS `mes_xsl_equipment_sub_part` (
SET @mes_tenant_id = 1002;
SET @xslmes_root_pid = (
SELECT MIN(`id`) FROM `sys_permission`
WHERE `del_flag` = 0 AND `menu_type` = 0 AND `name` IN ('MES XSL', 'XSLMES管理', 'XSLMES')
SET @mes_equip_pid = (
SELECT `id` FROM `sys_permission`
WHERE `del_flag` = 0 AND `menu_type` = 0 AND `name` = '设备管理'
LIMIT 1
);
SET @xslmes_root_pid = IFNULL(@xslmes_root_pid, '1900000000000000300');
SET @mes_equip_pid = IFNULL(@mes_equip_pid, '1860000000000000133');
INSERT INTO `sys_permission`(`id`, `parent_id`, `name`, `url`, `component`, `component_name`, `menu_type`, `perms`, `perms_type`, `sort_no`, `is_route`, `is_leaf`, `hidden`, `status`, `del_flag`, `keep_alive`, `internal_or_external`, `create_by`, `create_time`)
VALUES ('1860000000000000091', @xslmes_root_pid, '设备小部位', '/xslmes/mesXslEquipmentSubPart', 'xslmes/mesXslEquipmentSubPart/MesXslEquipmentSubPartList', NULL, 1, NULL, '1', 14, 1, 0, 0, '1', 0, 1, 0, 'admin', NOW())
VALUES ('1860000000000000091', @mes_equip_pid, '设备小部位', '/xslmes/mesXslEquipmentSubPart', 'xslmes/mesXslEquipmentSubPart/MesXslEquipmentSubPartList', NULL, 1, NULL, '1', 5, 1, 0, 0, '1', 0, 1, 0, 'admin', NOW())
ON DUPLICATE KEY UPDATE
`parent_id` = VALUES(`parent_id`), `name` = VALUES(`name`), `url` = VALUES(`url`), `component` = VALUES(`component`), `component_name` = VALUES(`component_name`),
`menu_type` = VALUES(`menu_type`), `perms` = VALUES(`perms`), `perms_type` = VALUES(`perms_type`), `sort_no` = VALUES(`sort_no`),
`is_route` = VALUES(`is_route`), `is_leaf` = VALUES(`is_leaf`), `hidden` = VALUES(`hidden`), `status` = VALUES(`status`), `del_flag` = VALUES(`del_flag`),
`keep_alive` = VALUES(`keep_alive`), `internal_or_external` = VALUES(`internal_or_external`);
`keep_alive` = VALUES(`keep_alive`), `internal_or_external` = VALUES(`internal_or_external`), `icon` = 'ant-design:apartment-outlined';
UPDATE `sys_permission` SET `icon` = 'ant-design:apartment-outlined' WHERE `id` = '1860000000000000091' AND `del_flag` = 0;
INSERT INTO `sys_permission`(`id`, `parent_id`, `name`, `menu_type`, `perms`, `perms_type`, `status`, `del_flag`, `create_by`, `create_time`) VALUES
('1860000000000000092', '1860000000000000091', '新增', 2, 'mes:mes_xsl_equipment_sub_part:add', '1', '1', 0, 'admin', NOW()),

View File

@@ -0,0 +1,65 @@
-- 设备类型菜单/按钮补全并挂到设备管理解决仅 UPDATE id 077 不存在菜单与权限均不显示
-- 可重复执行修改租户改 SET @mes_tenant_id
SET NAMES utf8mb4;
SET @mes_tenant_id = 1002;
SET @mes_equip_pid = (
SELECT `id` FROM `sys_permission`
WHERE `del_flag` = 0 AND `menu_type` = 0 AND `name` = '设备管理'
LIMIT 1
);
SET @mes_equip_pid = IFNULL(@mes_equip_pid, '1860000000000000133');
UPDATE `sys_permission`
SET `is_leaf` = 0
WHERE `id` = @mes_equip_pid;
INSERT INTO `sys_permission`(`id`, `parent_id`, `name`, `url`, `component`, `component_name`, `menu_type`, `perms`, `perms_type`, `sort_no`, `is_route`, `is_leaf`, `hidden`, `status`, `del_flag`, `keep_alive`, `internal_or_external`, `create_by`, `create_time`)
VALUES ('1860000000000000077', @mes_equip_pid, '设备类型', '/xslmes/mesXslEquipmentType', 'xslmes/mesXslEquipmentType/MesXslEquipmentTypeList', NULL, 1, NULL, '1', 3, 1, 0, 0, '1', 0, 1, 0, 'admin', NOW())
ON DUPLICATE KEY UPDATE
`parent_id` = VALUES(`parent_id`), `name` = VALUES(`name`), `url` = VALUES(`url`), `component` = VALUES(`component`),
`menu_type` = VALUES(`menu_type`), `perms` = VALUES(`perms`), `perms_type` = VALUES(`perms_type`), `sort_no` = VALUES(`sort_no`),
`is_route` = VALUES(`is_route`), `is_leaf` = 0, `hidden` = 0, `status` = '1', `del_flag` = 0,
`keep_alive` = VALUES(`keep_alive`), `internal_or_external` = VALUES(`internal_or_external`);
INSERT INTO `sys_permission`(`id`, `parent_id`, `name`, `menu_type`, `perms`, `perms_type`, `is_leaf`, `status`, `del_flag`, `create_by`, `create_time`) VALUES
('1860000000000000078', '1860000000000000077', '新增', 2, 'mes:mes_xsl_equipment_type:add', '1', 1, '1', 0, 'admin', NOW()),
('1860000000000000079', '1860000000000000077', '编辑', 2, 'mes:mes_xsl_equipment_type:edit', '1', 1, '1', 0, 'admin', NOW()),
('1860000000000000080', '1860000000000000077', '删除', 2, 'mes:mes_xsl_equipment_type:delete', '1', 1, '1', 0, 'admin', NOW()),
('1860000000000000081', '1860000000000000077', '批量删除', 2, 'mes:mes_xsl_equipment_type:deleteBatch', '1', 1, '1', 0, 'admin', NOW()),
('1860000000000000082', '1860000000000000077', '导出', 2, 'mes:mes_xsl_equipment_type:exportXls', '1', 1, '1', 0, 'admin', NOW()),
('1860000000000000083', '1860000000000000077', '导入', 2, 'mes:mes_xsl_equipment_type:importExcel', '1', 1, '1', 0, 'admin', NOW())
ON DUPLICATE KEY UPDATE
`parent_id` = VALUES(`parent_id`), `name` = VALUES(`name`), `menu_type` = VALUES(`menu_type`), `perms` = VALUES(`perms`),
`perms_type` = VALUES(`perms_type`), `is_leaf` = 1, `status` = '1', `del_flag` = 0;
UPDATE `sys_permission` p
INNER JOIN (SELECT @mes_equip_pid AS `pid`) x ON 1 = 1
SET p.`parent_id` = x.`pid`,
p.`is_leaf` = 0,
p.`url` = '/xslmes/mesXslEquipmentType',
p.`component` = 'xslmes/mesXslEquipmentType/MesXslEquipmentTypeList',
p.`hidden` = 0,
p.`del_flag` = 0,
p.`status` = '1',
p.`update_time` = NOW()
WHERE p.`menu_type` = 1
AND p.`url` = '/xslmes/mesXslEquipmentType'
AND p.`id` <> '1860000000000000077';
INSERT INTO `sys_role_permission`(`id`, `role_id`, `permission_id`, `operate_date`, `operate_ip`)
SELECT REPLACE(UUID(), '-', ''), r.`id`, p.`id`, NOW(), '127.0.0.1'
FROM `sys_role` r
CROSS JOIN `sys_permission` p
WHERE r.`tenant_id` = @mes_tenant_id
AND r.`role_code` = 'admin'
AND p.`id` IN (
'1860000000000000077',
'1860000000000000078', '1860000000000000079', '1860000000000000080',
'1860000000000000081', '1860000000000000082', '1860000000000000083'
)
AND NOT EXISTS (
SELECT 1 FROM `sys_role_permission` rp
WHERE rp.`role_id` = r.`id` AND rp.`permission_id` = p.`id`
);

View File

@@ -23,14 +23,15 @@ CREATE TABLE IF NOT EXISTS `mes_xsl_equipment_type` (
SET @mes_tenant_id = 1002;
SET @mes_base_pid = (
SELECT MIN(`id`) FROM `sys_permission`
WHERE `del_flag` = 0 AND `menu_type` = 0 AND `name` IN ('MES基础资料', 'MES资料')
SET @mes_equip_pid = (
SELECT `id` FROM `sys_permission`
WHERE `del_flag` = 0 AND `menu_type` = 0 AND `name` = '设备管理'
LIMIT 1
);
SET @mes_base_pid = IFNULL(@mes_base_pid, '1860000000000000001');
SET @mes_equip_pid = IFNULL(@mes_equip_pid, '1860000000000000133');
INSERT INTO `sys_permission`(`id`, `parent_id`, `name`, `url`, `component`, `component_name`, `menu_type`, `perms`, `perms_type`, `sort_no`, `is_route`, `is_leaf`, `hidden`, `status`, `del_flag`, `keep_alive`, `internal_or_external`, `create_by`, `create_time`)
VALUES ('1860000000000000077', @mes_base_pid, '设备类型', '/xslmes/mesXslEquipmentType', 'xslmes/mesXslEquipmentType/MesXslEquipmentTypeList', NULL, 1, NULL, '1', 11, 1, 0, 0, '1', 0, 1, 0, 'admin', NOW())
VALUES ('1860000000000000077', @mes_equip_pid, '设备类型', '/xslmes/mesXslEquipmentType', 'xslmes/mesXslEquipmentType/MesXslEquipmentTypeList', NULL, 1, NULL, '1', 3, 1, 0, 0, '1', 0, 1, 0, 'admin', NOW())
ON DUPLICATE KEY UPDATE
`parent_id` = VALUES(`parent_id`), `name` = VALUES(`name`), `url` = VALUES(`url`), `component` = VALUES(`component`), `component_name` = VALUES(`component_name`),
`menu_type` = VALUES(`menu_type`), `perms` = VALUES(`perms`), `perms_type` = VALUES(`perms_type`), `sort_no` = VALUES(`sort_no`),

View File

@@ -0,0 +1,92 @@
-- 终胶计划菜单与权限挂到MES密炼工程目录
SET NAMES utf8mb4;
SET @mixer_parent_id = (
SELECT id
FROM sys_permission
WHERE name = 'MES密炼工程' AND menu_type = 0 AND del_flag = 0
ORDER BY create_time ASC
LIMIT 1
);
SET @mixer_parent_id = IFNULL(@mixer_parent_id, (
SELECT id
FROM sys_permission
WHERE url = '/mes' AND menu_type = 0 AND del_flag = 0
ORDER BY create_time ASC
LIMIT 1
));
SET @mixer_parent_id = IFNULL(@mixer_parent_id, '1860000000000000001');
INSERT INTO sys_permission(
id, parent_id, name, url, component, component_name, menu_type, perms, perms_type, sort_no,
is_route, is_leaf, hidden, status, del_flag, keep_alive, internal_or_external, create_by, create_time
)
VALUES (
'1860000000000099711', @mixer_parent_id, '终胶计划',
'/mes/finalbatchplaninfo',
'mes/finalbatchplaninfo/index',
'MesXslFinalBatchPlanList', 1, NULL, '1', 35,
1, 1, 0, '1', 0, 1, 0, 'admin', NOW()
)
ON DUPLICATE KEY UPDATE
parent_id = VALUES(parent_id),
name = VALUES(name),
url = VALUES(url),
component = VALUES(component),
component_name = VALUES(component_name),
menu_type = VALUES(menu_type),
perms = VALUES(perms),
perms_type = VALUES(perms_type),
sort_no = VALUES(sort_no),
is_route = VALUES(is_route),
is_leaf = VALUES(is_leaf),
hidden = VALUES(hidden),
status = VALUES(status),
del_flag = VALUES(del_flag),
keep_alive = VALUES(keep_alive),
internal_or_external = VALUES(internal_or_external);
INSERT INTO sys_permission(id, parent_id, name, menu_type, perms, perms_type, status, del_flag, create_by, create_time) VALUES
('1860000000000099712', '1860000000000099711', '新增', 2, 'xslmes:mes_xsl_final_batch_plan:add', '1', '1', 0, 'admin', NOW()),
('1860000000000099713', '1860000000000099711', '编辑', 2, 'xslmes:mes_xsl_final_batch_plan:edit', '1', '1', 0, 'admin', NOW()),
('1860000000000099714', '1860000000000099711', '删除', 2, 'xslmes:mes_xsl_final_batch_plan:delete', '1', '1', 0, 'admin', NOW()),
('1860000000000099715', '1860000000000099711', '批量删除', 2, 'xslmes:mes_xsl_final_batch_plan:deleteBatch', '1', '1', 0, 'admin', NOW()),
('1860000000000099716', '1860000000000099711', '导出', 2, 'xslmes:mes_xsl_final_batch_plan:exportXls', '1', '1', 0, 'admin', NOW())
ON DUPLICATE KEY UPDATE
parent_id = VALUES(parent_id),
name = VALUES(name),
menu_type = VALUES(menu_type),
perms = VALUES(perms),
perms_type = VALUES(perms_type),
status = VALUES(status),
del_flag = VALUES(del_flag);
-- admin 角色授权
INSERT INTO sys_role_permission(id, role_id, permission_id, operate_date, operate_ip)
SELECT REPLACE(UUID(), '-', ''), 'f6817f48af4fb3af11b9e8bf182f618b', p.id, NOW(), '127.0.0.1'
FROM sys_permission p
WHERE p.id IN (
'1860000000000099711',
'1860000000000099712', '1860000000000099713', '1860000000000099714', '1860000000000099715', '1860000000000099716'
)
AND NOT EXISTS (
SELECT 1
FROM sys_role_permission rp
WHERE rp.role_id = 'f6817f48af4fb3af11b9e8bf182f618b'
AND rp.permission_id = p.id
);
-- 强制修复确保菜单路由与组件路径正确
UPDATE sys_permission
SET
parent_id = @mixer_parent_id,
url = '/mes/finalbatchplaninfo',
component = 'mes/finalbatchplaninfo/index',
component_name = 'MesXslFinalBatchPlanList',
menu_type = 1,
is_route = 1,
is_leaf = 1,
hidden = 0,
status = '1',
del_flag = 0
WHERE id = '1860000000000099711';

View File

@@ -0,0 +1,30 @@
-- 终胶计划建表SQL
SET NAMES utf8mb4;
CREATE TABLE IF NOT EXISTS `mes_xsl_final_batch_plan` (
`id` varchar(32) NOT NULL COMMENT '主键',
`source_order_id` varchar(32) DEFAULT NULL COMMENT '来源生产订单ID',
`order_serial_no` varchar(500) DEFAULT NULL COMMENT '订单流水',
`order_no` varchar(500) DEFAULT NULL COMMENT '订单编号',
`production_segment_count` int DEFAULT NULL COMMENT '生产段数',
`order_date` date DEFAULT NULL COMMENT '订单日期',
`material_code` varchar(500) DEFAULT NULL COMMENT '物料编码',
`mes_material_name` varchar(500) DEFAULT NULL COMMENT 'MES胶料信息',
`plan_weight` decimal(18,4) DEFAULT NULL COMMENT '计划重量',
`per_car_weight` decimal(18,4) DEFAULT NULL COMMENT '每车重量',
`planned_car_count` int DEFAULT 0 COMMENT '计划车数',
`scheduled_car_count` int DEFAULT 0 COMMENT '已排产车数',
`finished_car_count` int DEFAULT 0 COMMENT '完成车数',
`status` int DEFAULT 0 COMMENT '状态0未开始 1进行中 2已完成',
`tenant_id` int DEFAULT NULL COMMENT '租户',
`sys_org_code` varchar(64) DEFAULT NULL COMMENT '部门编码',
`create_by` varchar(64) DEFAULT NULL COMMENT '创建人',
`create_time` datetime DEFAULT NULL COMMENT '创建时间',
`update_by` varchar(64) DEFAULT NULL COMMENT '更新人',
`update_time` datetime DEFAULT NULL COMMENT '更新时间',
`del_flag` int DEFAULT 0 COMMENT '删除标记0正常1删除',
PRIMARY KEY (`id`),
KEY `idx_mxfb_source_order` (`source_order_id`),
KEY `idx_mxfb_material_code` (`material_code`),
UNIQUE KEY `uk_mxfb_source_order_del` (`source_order_id`, `del_flag`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='MES终胶计划';

View File

@@ -0,0 +1,118 @@
-- MES 点检及保养项目字典 + 建表 + 菜单 + 按钮 + 租户 admin 授权可整文件一次执行
-- 权限前缀与 Controller前端 v-auth 一致mes:mes_xsl_inspect_maintain_item:*
-- 父菜单设备管理修改租户改 SET @mes_tenant_id
-- 新环境也可依赖 FlywayV3.9.2_77__mes_xsl_inspect_maintain_item.sql
SET NAMES utf8mb4;
INSERT INTO `sys_dict` (`id`, `dict_name`, `dict_code`, `description`, `del_flag`, `create_by`, `create_time`, `type`, `tenant_id`)
SELECT REPLACE(UUID(), '-', ''), 'MES点检保养项目类别', 'xslmes_im_item_category', 'inspect点检/maintain保养', 0, 'admin', NOW(), 0, 0
WHERE NOT EXISTS (SELECT 1 FROM `sys_dict` WHERE `dict_code` = 'xslmes_im_item_category' AND `del_flag` = 0);
INSERT INTO `sys_dict_item` (`id`, `dict_id`, `item_text`, `item_value`, `sort_order`, `status`, `create_by`, `create_time`)
SELECT REPLACE(UUID(), '-', ''), d.id, '点检', 'inspect', 1, 1, 'admin', NOW() FROM `sys_dict` d
WHERE d.`dict_code` = 'xslmes_im_item_category' AND NOT EXISTS (SELECT 1 FROM `sys_dict_item` i WHERE i.`dict_id` = d.id AND i.`item_value` = 'inspect');
INSERT INTO `sys_dict_item` (`id`, `dict_id`, `item_text`, `item_value`, `sort_order`, `status`, `create_by`, `create_time`)
SELECT REPLACE(UUID(), '-', ''), d.id, '保养', 'maintain', 2, 1, 'admin', NOW() FROM `sys_dict` d
WHERE d.`dict_code` = 'xslmes_im_item_category' AND NOT EXISTS (SELECT 1 FROM `sys_dict_item` i WHERE i.`dict_id` = d.id AND i.`item_value` = 'maintain');
INSERT INTO `sys_dict` (`id`, `dict_name`, `dict_code`, `description`, `del_flag`, `create_by`, `create_time`, `type`, `tenant_id`)
SELECT REPLACE(UUID(), '-', ''), 'MES点检保养项目类型', 'xslmes_im_item_type', 'mechanical机械类/electrical电气类', 0, 'admin', NOW(), 0, 0
WHERE NOT EXISTS (SELECT 1 FROM `sys_dict` WHERE `dict_code` = 'xslmes_im_item_type' AND `del_flag` = 0);
INSERT INTO `sys_dict_item` (`id`, `dict_id`, `item_text`, `item_value`, `sort_order`, `status`, `create_by`, `create_time`)
SELECT REPLACE(UUID(), '-', ''), d.id, '机械类', 'mechanical', 1, 1, 'admin', NOW() FROM `sys_dict` d
WHERE d.`dict_code` = 'xslmes_im_item_type' AND NOT EXISTS (SELECT 1 FROM `sys_dict_item` i WHERE i.`dict_id` = d.id AND i.`item_value` = 'mechanical');
INSERT INTO `sys_dict_item` (`id`, `dict_id`, `item_text`, `item_value`, `sort_order`, `status`, `create_by`, `create_time`)
SELECT REPLACE(UUID(), '-', ''), d.id, '电气类', 'electrical', 2, 1, 'admin', NOW() FROM `sys_dict` d
WHERE d.`dict_code` = 'xslmes_im_item_type' AND NOT EXISTS (SELECT 1 FROM `sys_dict_item` i WHERE i.`dict_id` = d.id AND i.`item_value` = 'electrical');
INSERT INTO `sys_dict` (`id`, `dict_name`, `dict_code`, `description`, `del_flag`, `create_by`, `create_time`, `type`, `tenant_id`)
SELECT REPLACE(UUID(), '-', ''), 'MES点检方式', 'xslmes_im_inspect_method', 'visual视觉/sight目测/hearing听觉', 0, 'admin', NOW(), 0, 0
WHERE NOT EXISTS (SELECT 1 FROM `sys_dict` WHERE `dict_code` = 'xslmes_im_inspect_method' AND `del_flag` = 0);
INSERT INTO `sys_dict_item` (`id`, `dict_id`, `item_text`, `item_value`, `sort_order`, `status`, `create_by`, `create_time`)
SELECT REPLACE(UUID(), '-', ''), d.id, '视觉', 'visual', 1, 1, 'admin', NOW() FROM `sys_dict` d
WHERE d.`dict_code` = 'xslmes_im_inspect_method' AND NOT EXISTS (SELECT 1 FROM `sys_dict_item` i WHERE i.`dict_id` = d.id AND i.`item_value` = 'visual');
INSERT INTO `sys_dict_item` (`id`, `dict_id`, `item_text`, `item_value`, `sort_order`, `status`, `create_by`, `create_time`)
SELECT REPLACE(UUID(), '-', ''), d.id, '目测', 'sight', 2, 1, 'admin', NOW() FROM `sys_dict` d
WHERE d.`dict_code` = 'xslmes_im_inspect_method' AND NOT EXISTS (SELECT 1 FROM `sys_dict_item` i WHERE i.`dict_id` = d.id AND i.`item_value` = 'sight');
INSERT INTO `sys_dict_item` (`id`, `dict_id`, `item_text`, `item_value`, `sort_order`, `status`, `create_by`, `create_time`)
SELECT REPLACE(UUID(), '-', ''), d.id, '听觉', 'hearing', 3, 1, 'admin', NOW() FROM `sys_dict` d
WHERE d.`dict_code` = 'xslmes_im_inspect_method' AND NOT EXISTS (SELECT 1 FROM `sys_dict_item` i WHERE i.`dict_id` = d.id AND i.`item_value` = 'hearing');
CREATE TABLE IF NOT EXISTS `mes_xsl_inspect_maintain_item` (
`id` varchar(32) NOT NULL COMMENT '主键',
`item_name` varchar(500) NOT NULL COMMENT '项目名称同租户未删除数据中唯一',
`item_code` varchar(500) NOT NULL COMMENT '项目编号同租户未删除数据中唯一',
`equipment_category_id` varchar(32) NOT NULL COMMENT '设备类别主键 mes_xsl_equipment_category.id',
`equipment_category_name` varchar(500) DEFAULT NULL COMMENT '设备类别名称冗余',
`equipment_type_id` varchar(32) NOT NULL COMMENT '设备类型主键 mes_xsl_equipment_type.id',
`equipment_type_name` varchar(500) DEFAULT NULL COMMENT '设备类型名称冗余',
`equipment_part_id` varchar(32) NOT NULL COMMENT '设备部位主键 mes_xsl_equipment_part.id',
`equipment_part_name` varchar(500) DEFAULT NULL COMMENT '设备部位名称冗余',
`equipment_sub_part_id` varchar(32) NOT NULL COMMENT '设备小部位主键 mes_xsl_equipment_sub_part.id',
`equipment_sub_part_name` varchar(500) DEFAULT NULL COMMENT '设备小部位名称冗余',
`item_category` varchar(500) NOT NULL COMMENT '项目类别字典xslmes_im_item_categoryinspect点检/maintain保养',
`item_type` varchar(500) NOT NULL COMMENT '项目类型字典xslmes_im_item_typemechanical机械类/electrical电气类',
`inspect_method` varchar(500) NOT NULL COMMENT '点检方式字典xslmes_im_inspect_methodvisual视觉/sight目测/hearing听觉',
`judgment_criteria` varchar(500) NOT NULL COMMENT '判断基准',
`maintain_cycle_days` int DEFAULT NULL COMMENT '保养周期',
`tenant_id` int DEFAULT NULL COMMENT '租户',
`sys_org_code` varchar(500) DEFAULT NULL COMMENT '部门',
`create_by` varchar(500) DEFAULT NULL COMMENT '创建人',
`create_time` datetime DEFAULT NULL COMMENT '创建时间',
`update_by` varchar(500) DEFAULT NULL COMMENT '更新人',
`update_time` datetime DEFAULT NULL COMMENT '更新时间',
`del_flag` int DEFAULT '0' COMMENT '删除标记0正常1删除',
PRIMARY KEY (`id`),
KEY `idx_mimi_tenant_name` (`tenant_id`, `item_name`),
KEY `idx_mimi_tenant_code` (`tenant_id`, `item_code`),
KEY `idx_mimi_category` (`equipment_category_id`),
KEY `idx_mimi_type` (`equipment_type_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='MES点检及保养项目';
SET @mes_tenant_id = 1002;
SET @mes_equip_pid = (
SELECT `id` FROM `sys_permission`
WHERE `del_flag` = 0 AND `menu_type` = 0 AND `name` = '设备管理'
LIMIT 1
);
SET @mes_equip_pid = IFNULL(@mes_equip_pid, '1860000000000000133');
INSERT INTO `sys_permission`(`id`, `parent_id`, `name`, `url`, `component`, `component_name`, `menu_type`, `perms`, `perms_type`, `sort_no`, `is_route`, `is_leaf`, `hidden`, `status`, `del_flag`, `keep_alive`, `internal_or_external`, `create_by`, `create_time`)
VALUES ('1860000000000000141', @mes_equip_pid, '点检及保养项目', '/xslmes/mesXslInspectMaintainItem', 'xslmes/mesXslInspectMaintainItem/MesXslInspectMaintainItemList', NULL, 1, NULL, '1', 11, 1, 0, 0, '1', 0, 1, 0, 'admin', NOW())
ON DUPLICATE KEY UPDATE
`parent_id` = VALUES(`parent_id`), `name` = VALUES(`name`), `url` = VALUES(`url`), `component` = VALUES(`component`), `component_name` = VALUES(`component_name`),
`menu_type` = VALUES(`menu_type`), `perms` = VALUES(`perms`), `perms_type` = VALUES(`perms_type`), `sort_no` = VALUES(`sort_no`),
`is_route` = VALUES(`is_route`), `is_leaf` = VALUES(`is_leaf`), `hidden` = VALUES(`hidden`), `status` = VALUES(`status`), `del_flag` = VALUES(`del_flag`),
`keep_alive` = VALUES(`keep_alive`), `internal_or_external` = VALUES(`internal_or_external`), `icon` = 'ant-design:audit-outlined';
UPDATE `sys_permission` SET `icon` = 'ant-design:audit-outlined' WHERE `id` = '1860000000000000141' AND `del_flag` = 0;
INSERT INTO `sys_permission`(`id`, `parent_id`, `name`, `menu_type`, `perms`, `perms_type`, `status`, `del_flag`, `create_by`, `create_time`) VALUES
('1860000000000000142', '1860000000000000141', '新增', 2, 'mes:mes_xsl_inspect_maintain_item:add', '1', '1', 0, 'admin', NOW()),
('1860000000000000143', '1860000000000000141', '编辑', 2, 'mes:mes_xsl_inspect_maintain_item:edit', '1', '1', 0, 'admin', NOW()),
('1860000000000000144', '1860000000000000141', '删除', 2, 'mes:mes_xsl_inspect_maintain_item:delete', '1', '1', 0, 'admin', NOW()),
('1860000000000000145', '1860000000000000141', '批量删除', 2, 'mes:mes_xsl_inspect_maintain_item:deleteBatch', '1', '1', 0, 'admin', NOW()),
('1860000000000000146', '1860000000000000141', '导出', 2, 'mes:mes_xsl_inspect_maintain_item:exportXls', '1', '1', 0, 'admin', NOW()),
('1860000000000000147', '1860000000000000141', '导入', 2, 'mes:mes_xsl_inspect_maintain_item:importExcel', '1', '1', 0, 'admin', NOW())
ON DUPLICATE KEY UPDATE
`parent_id` = VALUES(`parent_id`), `name` = VALUES(`name`), `menu_type` = VALUES(`menu_type`), `perms` = VALUES(`perms`), `perms_type` = VALUES(`perms_type`),
`status` = VALUES(`status`), `del_flag` = VALUES(`del_flag`);
INSERT INTO `sys_role_permission`(`id`, `role_id`, `permission_id`, `operate_date`, `operate_ip`)
SELECT REPLACE(UUID(), '-', ''), r.`id`, p.`id`, NOW(), '127.0.0.1'
FROM `sys_role` r
CROSS JOIN `sys_permission` p
WHERE r.`tenant_id` = @mes_tenant_id
AND r.`role_code` = 'admin'
AND p.`id` IN (
'1860000000000000141',
'1860000000000000142', '1860000000000000143', '1860000000000000144', '1860000000000000145',
'1860000000000000146', '1860000000000000147'
)
AND NOT EXISTS (
SELECT 1 FROM `sys_role_permission` rp
WHERE rp.`role_id` = r.`id` AND rp.`permission_id` = p.`id`
);

View File

@@ -1,6 +1,6 @@
-- MES 厂家信息字典 + 建表 + 菜单 + 按钮 + 租户 admin 授权可整文件一次执行
-- 权限前缀与 Controller前端 v-auth 一致mes:mes_xsl_manufacturer:*
-- 父菜单MES基础资料 / MES资料与备品件等脚本相同 @mes_base_pid修改租户改 SET @mes_tenant_id
-- 父菜单设备管理@mes_equip_pid修改租户改 SET @mes_tenant_id
-- 新环境也可依赖 FlywayV3.9.2_63__mes_xsl_manufacturer.sql与本文内容一致重复执行幂等
SET NAMES utf8mb4;
@@ -31,14 +31,14 @@ WHERE d.`dict_code` = 'xslmes_manufacturer_valid' AND NOT EXISTS (SELECT 1 FROM
CREATE TABLE IF NOT EXISTS `mes_xsl_manufacturer` (
`id` varchar(32) NOT NULL COMMENT '主键',
`manufacturer_category` varchar(32) NOT NULL COMMENT '厂家类别字典xslmes_manufacturer_categorymold模具 capsule胶囊 equipment设备',
`manufacturer_name` varchar(128) NOT NULL COMMENT '厂家名称同租户未删除数据中唯一',
`manufacturer_category` varchar(500) NOT NULL COMMENT '厂家类别字典xslmes_manufacturer_categorymold模具 capsule胶囊 equipment设备',
`manufacturer_name` varchar(500) NOT NULL COMMENT '厂家名称同租户未删除数据中唯一',
`valid_status` varchar(1) NOT NULL DEFAULT '0' COMMENT '是否有效字典xslmes_manufacturer_valid0有效1无效',
`tenant_id` int DEFAULT NULL COMMENT '租户',
`sys_org_code` varchar(64) DEFAULT NULL COMMENT '部门',
`create_by` varchar(32) DEFAULT NULL COMMENT '创建人',
`sys_org_code` varchar(500) DEFAULT NULL COMMENT '部门',
`create_by` varchar(500) DEFAULT NULL COMMENT '创建人',
`create_time` datetime DEFAULT NULL COMMENT '创建时间',
`update_by` varchar(32) DEFAULT NULL COMMENT '更新人',
`update_by` varchar(500) DEFAULT NULL COMMENT '更新人',
`update_time` datetime DEFAULT NULL COMMENT '更新时间',
`del_flag` int DEFAULT '0' COMMENT '删除标记0正常1删除',
PRIMARY KEY (`id`),
@@ -47,19 +47,22 @@ CREATE TABLE IF NOT EXISTS `mes_xsl_manufacturer` (
SET @mes_tenant_id = 1002;
SET @mes_base_pid = (
SELECT MIN(`id`) FROM `sys_permission`
WHERE `del_flag` = 0 AND `menu_type` = 0 AND `name` IN ('MES基础资料', 'MES资料')
SET @mes_equip_pid = (
SELECT `id` FROM `sys_permission`
WHERE `del_flag` = 0 AND `menu_type` = 0 AND `name` = '设备管理'
LIMIT 1
);
SET @mes_base_pid = IFNULL(@mes_base_pid, '1860000000000000001');
SET @mes_equip_pid = IFNULL(@mes_equip_pid, '1860000000000000133');
INSERT INTO `sys_permission`(`id`, `parent_id`, `name`, `url`, `component`, `component_name`, `menu_type`, `perms`, `perms_type`, `sort_no`, `is_route`, `is_leaf`, `hidden`, `status`, `del_flag`, `keep_alive`, `internal_or_external`, `create_by`, `create_time`)
VALUES ('1860000000000000112', @mes_base_pid, '厂家信息', '/xslmes/mesXslManufacturer', 'xslmes/mesXslManufacturer/MesXslManufacturerList', NULL, 1, NULL, '1', 17, 1, 0, 0, '1', 0, 1, 0, 'admin', NOW())
VALUES ('1860000000000000112', @mes_equip_pid, '厂家信息', '/xslmes/mesXslManufacturer', 'xslmes/mesXslManufacturer/MesXslManufacturerList', NULL, 1, NULL, '1', 8, 1, 0, 0, '1', 0, 1, 0, 'admin', NOW())
ON DUPLICATE KEY UPDATE
`parent_id` = VALUES(`parent_id`), `name` = VALUES(`name`), `url` = VALUES(`url`), `component` = VALUES(`component`), `component_name` = VALUES(`component_name`),
`menu_type` = VALUES(`menu_type`), `perms` = VALUES(`perms`), `perms_type` = VALUES(`perms_type`), `sort_no` = VALUES(`sort_no`),
`is_route` = VALUES(`is_route`), `is_leaf` = VALUES(`is_leaf`), `hidden` = VALUES(`hidden`), `status` = VALUES(`status`), `del_flag` = VALUES(`del_flag`),
`keep_alive` = VALUES(`keep_alive`), `internal_or_external` = VALUES(`internal_or_external`);
`keep_alive` = VALUES(`keep_alive`), `internal_or_external` = VALUES(`internal_or_external`), `icon` = 'ant-design:shop-outlined';
UPDATE `sys_permission` SET `icon` = 'ant-design:shop-outlined' WHERE `id` = '1860000000000000112' AND `del_flag` = 0;
INSERT INTO `sys_permission`(`id`, `parent_id`, `name`, `menu_type`, `perms`, `perms_type`, `status`, `del_flag`, `create_by`, `create_time`) VALUES
('1860000000000000113', '1860000000000000112', '新增', 2, 'mes:mes_xsl_manufacturer:add', '1', '1', 0, 'admin', NOW()),

View File

@@ -3,14 +3,14 @@ SET NAMES utf8mb4;
CREATE TABLE IF NOT EXISTS `mes_xsl_manufacturer` (
`id` varchar(32) NOT NULL COMMENT '主键',
`manufacturer_category` varchar(32) NOT NULL COMMENT '厂家类别字典xslmes_manufacturer_categorymold模具 capsule胶囊 equipment设备',
`manufacturer_name` varchar(128) NOT NULL COMMENT '厂家名称同租户未删除数据中唯一',
`manufacturer_category` varchar(500) NOT NULL COMMENT '厂家类别字典xslmes_manufacturer_categorymold模具 capsule胶囊 equipment设备',
`manufacturer_name` varchar(500) NOT NULL COMMENT '厂家名称同租户未删除数据中唯一',
`valid_status` varchar(1) NOT NULL DEFAULT '0' COMMENT '是否有效字典xslmes_manufacturer_valid0有效1无效',
`tenant_id` int DEFAULT NULL COMMENT '租户',
`sys_org_code` varchar(64) DEFAULT NULL COMMENT '部门',
`create_by` varchar(32) DEFAULT NULL COMMENT '创建人',
`sys_org_code` varchar(500) DEFAULT NULL COMMENT '部门',
`create_by` varchar(500) DEFAULT NULL COMMENT '创建人',
`create_time` datetime DEFAULT NULL COMMENT '创建时间',
`update_by` varchar(32) DEFAULT NULL COMMENT '更新人',
`update_by` varchar(500) DEFAULT NULL COMMENT '更新人',
`update_time` datetime DEFAULT NULL COMMENT '更新时间',
`del_flag` int DEFAULT '0' COMMENT '删除标记0正常1删除',
PRIMARY KEY (`id`),

View File

@@ -0,0 +1,92 @@
-- 母胶计划菜单与权限挂到MES密炼工程目录
SET NAMES utf8mb4;
SET @mixer_parent_id = (
SELECT id
FROM sys_permission
WHERE name = 'MES密炼工程' AND menu_type = 0 AND del_flag = 0
ORDER BY create_time ASC
LIMIT 1
);
SET @mixer_parent_id = IFNULL(@mixer_parent_id, (
SELECT id
FROM sys_permission
WHERE url = '/mes' AND menu_type = 0 AND del_flag = 0
ORDER BY create_time ASC
LIMIT 1
));
SET @mixer_parent_id = IFNULL(@mixer_parent_id, '1860000000000000001');
INSERT INTO sys_permission(
id, parent_id, name, url, component, component_name, menu_type, perms, perms_type, sort_no,
is_route, is_leaf, hidden, status, del_flag, keep_alive, internal_or_external, create_by, create_time
)
VALUES (
'1860000000000099611', @mixer_parent_id, '母胶计划',
'/mes/masterbatchplaninfo',
'mes/masterbatchplaninfo/index',
'MesXslMasterBatchPlanList', 1, NULL, '1', 34,
1, 1, 0, '1', 0, 1, 0, 'admin', NOW()
)
ON DUPLICATE KEY UPDATE
parent_id = VALUES(parent_id),
name = VALUES(name),
url = VALUES(url),
component = VALUES(component),
component_name = VALUES(component_name),
menu_type = VALUES(menu_type),
perms = VALUES(perms),
perms_type = VALUES(perms_type),
sort_no = VALUES(sort_no),
is_route = VALUES(is_route),
is_leaf = VALUES(is_leaf),
hidden = VALUES(hidden),
status = VALUES(status),
del_flag = VALUES(del_flag),
keep_alive = VALUES(keep_alive),
internal_or_external = VALUES(internal_or_external);
INSERT INTO sys_permission(id, parent_id, name, menu_type, perms, perms_type, status, del_flag, create_by, create_time) VALUES
('1860000000000099612', '1860000000000099611', '新增', 2, 'xslmes:mes_xsl_master_batch_plan:add', '1', '1', 0, 'admin', NOW()),
('1860000000000099613', '1860000000000099611', '编辑', 2, 'xslmes:mes_xsl_master_batch_plan:edit', '1', '1', 0, 'admin', NOW()),
('1860000000000099614', '1860000000000099611', '删除', 2, 'xslmes:mes_xsl_master_batch_plan:delete', '1', '1', 0, 'admin', NOW()),
('1860000000000099615', '1860000000000099611', '批量删除', 2, 'xslmes:mes_xsl_master_batch_plan:deleteBatch', '1', '1', 0, 'admin', NOW()),
('1860000000000099616', '1860000000000099611', '导出', 2, 'xslmes:mes_xsl_master_batch_plan:exportXls', '1', '1', 0, 'admin', NOW())
ON DUPLICATE KEY UPDATE
parent_id = VALUES(parent_id),
name = VALUES(name),
menu_type = VALUES(menu_type),
perms = VALUES(perms),
perms_type = VALUES(perms_type),
status = VALUES(status),
del_flag = VALUES(del_flag);
-- admin 角色授权
INSERT INTO sys_role_permission(id, role_id, permission_id, operate_date, operate_ip)
SELECT REPLACE(UUID(), '-', ''), 'f6817f48af4fb3af11b9e8bf182f618b', p.id, NOW(), '127.0.0.1'
FROM sys_permission p
WHERE p.id IN (
'1860000000000099611',
'1860000000000099612', '1860000000000099613', '1860000000000099614', '1860000000000099615', '1860000000000099616'
)
AND NOT EXISTS (
SELECT 1
FROM sys_role_permission rp
WHERE rp.role_id = 'f6817f48af4fb3af11b9e8bf182f618b'
AND rp.permission_id = p.id
);
-- 强制修复确保菜单路由与组件路径正确
UPDATE sys_permission
SET
parent_id = @mixer_parent_id,
url = '/mes/masterbatchplaninfo',
component = 'mes/masterbatchplaninfo/index',
component_name = 'MesXslMasterBatchPlanList',
menu_type = 1,
is_route = 1,
is_leaf = 1,
hidden = 0,
status = '1',
del_flag = 0
WHERE id = '1860000000000099611';

View File

@@ -0,0 +1,30 @@
-- 母胶计划建表SQL
SET NAMES utf8mb4;
CREATE TABLE IF NOT EXISTS `mes_xsl_master_batch_plan` (
`id` varchar(32) NOT NULL COMMENT '主键',
`source_order_id` varchar(32) DEFAULT NULL COMMENT '来源生产订单ID',
`order_serial_no` varchar(500) DEFAULT NULL COMMENT '订单流水号',
`order_no` varchar(500) DEFAULT NULL COMMENT '订单编号',
`production_segment_count` int DEFAULT NULL COMMENT '生产段数',
`order_date` date DEFAULT NULL COMMENT '订单日期',
`material_code` varchar(500) DEFAULT NULL COMMENT '物料编号',
`mes_material_name` varchar(500) DEFAULT NULL COMMENT 'MES胶料名称',
`plan_weight` decimal(18,4) DEFAULT NULL COMMENT '计划重量',
`per_car_weight` decimal(18,4) DEFAULT NULL COMMENT '每车重量',
`planned_car_count` int DEFAULT 0 COMMENT '计划车数',
`scheduled_car_count` int DEFAULT 0 COMMENT '已排产车数',
`finished_car_count` int DEFAULT 0 COMMENT '完成车数',
`status` int DEFAULT 0 COMMENT '状态0未开始 1进行中 2已完成',
`tenant_id` int DEFAULT NULL COMMENT '租户',
`sys_org_code` varchar(64) DEFAULT NULL COMMENT '部门编码',
`create_by` varchar(64) DEFAULT NULL COMMENT '创建人',
`create_time` datetime DEFAULT NULL COMMENT '创建时间',
`update_by` varchar(64) DEFAULT NULL COMMENT '更新人',
`update_time` datetime DEFAULT NULL COMMENT '更新时间',
`del_flag` int DEFAULT 0 COMMENT '删除标记0正常1删除',
PRIMARY KEY (`id`),
KEY `idx_mxmbp_source_order` (`source_order_id`),
KEY `idx_mxmbp_material_code` (`material_code`),
UNIQUE KEY `uk_mxmbp_source_order_del` (`source_order_id`, `del_flag`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='MES母胶计划';

View File

@@ -0,0 +1,92 @@
-- 密炼机动作维护菜单与权限挂到MES密炼工程目录
SET NAMES utf8mb4;
SET @mixer_parent_id = (
SELECT id
FROM sys_permission
WHERE name = 'MES密炼工程' AND menu_type = 0 AND del_flag = 0
ORDER BY create_time ASC
LIMIT 1
);
SET @mixer_parent_id = IFNULL(@mixer_parent_id, (
SELECT id
FROM sys_permission
WHERE url = '/mes' AND menu_type = 0 AND del_flag = 0
ORDER BY create_time ASC
LIMIT 1
));
SET @mixer_parent_id = IFNULL(@mixer_parent_id, '1860000000000000001');
INSERT INTO sys_permission(
id, parent_id, name, url, component, component_name, menu_type, perms, perms_type, sort_no,
is_route, is_leaf, hidden, status, del_flag, keep_alive, internal_or_external, create_by, create_time
)
VALUES (
'1860000000000099211', @mixer_parent_id, '密炼机动作维护',
'/mes/mixeractioninfo',
'mes/mixeractioninfo/index',
'MesXslMixerActionList', 1, NULL, '1', 30,
1, 1, 0, '1', 0, 1, 0, 'admin', NOW()
)
ON DUPLICATE KEY UPDATE
parent_id = VALUES(parent_id),
name = VALUES(name),
url = VALUES(url),
component = VALUES(component),
component_name = VALUES(component_name),
menu_type = VALUES(menu_type),
perms = VALUES(perms),
perms_type = VALUES(perms_type),
sort_no = VALUES(sort_no),
is_route = VALUES(is_route),
is_leaf = VALUES(is_leaf),
hidden = VALUES(hidden),
status = VALUES(status),
del_flag = VALUES(del_flag),
keep_alive = VALUES(keep_alive),
internal_or_external = VALUES(internal_or_external);
INSERT INTO sys_permission(id, parent_id, name, menu_type, perms, perms_type, status, del_flag, create_by, create_time) VALUES
('1860000000000099212', '1860000000000099211', '新增', 2, 'xslmes:mes_xsl_mixer_action:add', '1', '1', 0, 'admin', NOW()),
('1860000000000099213', '1860000000000099211', '编辑', 2, 'xslmes:mes_xsl_mixer_action:edit', '1', '1', 0, 'admin', NOW()),
('1860000000000099214', '1860000000000099211', '删除', 2, 'xslmes:mes_xsl_mixer_action:delete', '1', '1', 0, 'admin', NOW()),
('1860000000000099215', '1860000000000099211', '批量删除', 2, 'xslmes:mes_xsl_mixer_action:deleteBatch', '1', '1', 0, 'admin', NOW()),
('1860000000000099216', '1860000000000099211', '导出', 2, 'xslmes:mes_xsl_mixer_action:exportXls', '1', '1', 0, 'admin', NOW())
ON DUPLICATE KEY UPDATE
parent_id = VALUES(parent_id),
name = VALUES(name),
menu_type = VALUES(menu_type),
perms = VALUES(perms),
perms_type = VALUES(perms_type),
status = VALUES(status),
del_flag = VALUES(del_flag);
-- admin 角色授权
INSERT INTO sys_role_permission(id, role_id, permission_id, operate_date, operate_ip)
SELECT REPLACE(UUID(), '-', ''), 'f6817f48af4fb3af11b9e8bf182f618b', p.id, NOW(), '127.0.0.1'
FROM sys_permission p
WHERE p.id IN (
'1860000000000099211',
'1860000000000099212', '1860000000000099213', '1860000000000099214', '1860000000000099215', '1860000000000099216'
)
AND NOT EXISTS (
SELECT 1
FROM sys_role_permission rp
WHERE rp.role_id = 'f6817f48af4fb3af11b9e8bf182f618b'
AND rp.permission_id = p.id
);
-- 强制修复确保菜单路由与组件路径正确避免历史错误路径导致查看组件引用是否正确
UPDATE sys_permission
SET
parent_id = @mixer_parent_id,
url = '/mes/mixeractioninfo',
component = 'mes/mixeractioninfo/index',
component_name = 'MesXslMixerActionList',
menu_type = 1,
is_route = 1,
is_leaf = 1,
hidden = 0,
status = '1',
del_flag = 0
WHERE id = '1860000000000099211';

View File

@@ -0,0 +1,92 @@
-- 密炼机条件维护菜单与权限挂到MES密炼工程目录
SET NAMES utf8mb4;
SET @mixer_parent_id = (
SELECT id
FROM sys_permission
WHERE name = 'MES密炼工程' AND menu_type = 0 AND del_flag = 0
ORDER BY create_time ASC
LIMIT 1
);
SET @mixer_parent_id = IFNULL(@mixer_parent_id, (
SELECT id
FROM sys_permission
WHERE url = '/mes' AND menu_type = 0 AND del_flag = 0
ORDER BY create_time ASC
LIMIT 1
));
SET @mixer_parent_id = IFNULL(@mixer_parent_id, '1860000000000000001');
INSERT INTO sys_permission(
id, parent_id, name, url, component, component_name, menu_type, perms, perms_type, sort_no,
is_route, is_leaf, hidden, status, del_flag, keep_alive, internal_or_external, create_by, create_time
)
VALUES (
'1860000000000099411', @mixer_parent_id, '密炼机条件维护',
'/mes/mixerconditioninfo',
'mes/mixerconditioninfo/index',
'MesXslMixerConditionList', 1, NULL, '1', 32,
1, 1, 0, '1', 0, 1, 0, 'admin', NOW()
)
ON DUPLICATE KEY UPDATE
parent_id = VALUES(parent_id),
name = VALUES(name),
url = VALUES(url),
component = VALUES(component),
component_name = VALUES(component_name),
menu_type = VALUES(menu_type),
perms = VALUES(perms),
perms_type = VALUES(perms_type),
sort_no = VALUES(sort_no),
is_route = VALUES(is_route),
is_leaf = VALUES(is_leaf),
hidden = VALUES(hidden),
status = VALUES(status),
del_flag = VALUES(del_flag),
keep_alive = VALUES(keep_alive),
internal_or_external = VALUES(internal_or_external);
INSERT INTO sys_permission(id, parent_id, name, menu_type, perms, perms_type, status, del_flag, create_by, create_time) VALUES
('1860000000000099412', '1860000000000099411', '新增', 2, 'xslmes:mes_xsl_mixer_condition:add', '1', '1', 0, 'admin', NOW()),
('1860000000000099413', '1860000000000099411', '编辑', 2, 'xslmes:mes_xsl_mixer_condition:edit', '1', '1', 0, 'admin', NOW()),
('1860000000000099414', '1860000000000099411', '删除', 2, 'xslmes:mes_xsl_mixer_condition:delete', '1', '1', 0, 'admin', NOW()),
('1860000000000099415', '1860000000000099411', '批量删除', 2, 'xslmes:mes_xsl_mixer_condition:deleteBatch', '1', '1', 0, 'admin', NOW()),
('1860000000000099416', '1860000000000099411', '导出', 2, 'xslmes:mes_xsl_mixer_condition:exportXls', '1', '1', 0, 'admin', NOW())
ON DUPLICATE KEY UPDATE
parent_id = VALUES(parent_id),
name = VALUES(name),
menu_type = VALUES(menu_type),
perms = VALUES(perms),
perms_type = VALUES(perms_type),
status = VALUES(status),
del_flag = VALUES(del_flag);
-- admin 角色授权
INSERT INTO sys_role_permission(id, role_id, permission_id, operate_date, operate_ip)
SELECT REPLACE(UUID(), '-', ''), 'f6817f48af4fb3af11b9e8bf182f618b', p.id, NOW(), '127.0.0.1'
FROM sys_permission p
WHERE p.id IN (
'1860000000000099411',
'1860000000000099412', '1860000000000099413', '1860000000000099414', '1860000000000099415', '1860000000000099416'
)
AND NOT EXISTS (
SELECT 1
FROM sys_role_permission rp
WHERE rp.role_id = 'f6817f48af4fb3af11b9e8bf182f618b'
AND rp.permission_id = p.id
);
-- 强制修复确保菜单路由与组件路径正确
UPDATE sys_permission
SET
parent_id = @mixer_parent_id,
url = '/mes/mixerconditioninfo',
component = 'mes/mixerconditioninfo/index',
component_name = 'MesXslMixerConditionList',
menu_type = 1,
is_route = 1,
is_leaf = 1,
hidden = 0,
status = '1',
del_flag = 0
WHERE id = '1860000000000099411';

View File

@@ -0,0 +1,62 @@
-- 将设备类别/类型/部位/小部位备品件厂家停机类菜单挂到设备管理目录下工序管理仍留 MES基础资料
-- 前置已执行 mes-xsl-equipment-ledger-menu-permission.sql Flyway V3.9.2_72 创建设备管理目录 id=1860000000000000133
-- 修改租户 SET @mes_tenant_id
SET NAMES utf8mb4;
SET @mes_tenant_id = 1002;
SET @mes_equip_pid = (
SELECT `id` FROM `sys_permission`
WHERE `del_flag` = 0 AND `menu_type` = 0 AND `name` = '设备管理'
LIMIT 1
);
SET @mes_equip_pid = IFNULL(@mes_equip_pid, '1860000000000000133');
UPDATE `sys_permission`
SET `is_leaf` = 0, `hidden` = 0, `status` = '1', `del_flag` = 0
WHERE `id` = @mes_equip_pid;
UPDATE `sys_permission` SET `parent_id` = @mes_equip_pid, `sort_no` = 1, `is_leaf` = 0 WHERE `id` = '1860000000000000134';
UPDATE `sys_permission` SET `parent_id` = @mes_equip_pid, `sort_no` = 2, `is_leaf` = 0 WHERE `id` = '1860000000000000070';
UPDATE `sys_permission` SET `parent_id` = @mes_equip_pid, `sort_no` = 3, `is_leaf` = 0 WHERE `id` = '1860000000000000077';
UPDATE `sys_permission` SET `parent_id` = @mes_equip_pid, `sort_no` = 4, `is_leaf` = 0 WHERE `id` = '1860000000000000084';
UPDATE `sys_permission` SET `parent_id` = @mes_equip_pid, `sort_no` = 5, `is_leaf` = 0 WHERE `id` = '1860000000000000091';
UPDATE `sys_permission` SET `parent_id` = @mes_equip_pid, `sort_no` = 6, `is_leaf` = 0 WHERE `id` = '1860000000000000098';
UPDATE `sys_permission` SET `parent_id` = @mes_equip_pid, `sort_no` = 7, `is_leaf` = 0 WHERE `id` = '1860000000000000105';
UPDATE `sys_permission` SET `parent_id` = @mes_equip_pid, `sort_no` = 8, `is_leaf` = 0 WHERE `id` = '1860000000000000112';
UPDATE `sys_permission` SET `parent_id` = @mes_equip_pid, `sort_no` = 9, `is_leaf` = 0 WHERE `id` = '1860000000000000119';
UPDATE `sys_permission` SET `parent_id` = @mes_equip_pid, `sort_no` = 10, `is_leaf` = 0 WHERE `id` = '1860000000000000126';
INSERT INTO `sys_role_permission`(`id`, `role_id`, `permission_id`, `operate_date`, `operate_ip`)
SELECT REPLACE(UUID(), '-', ''), r.`id`, p.`id`, NOW(), '127.0.0.1'
FROM `sys_role` r
CROSS JOIN `sys_permission` p
WHERE r.`tenant_id` = @mes_tenant_id
AND r.`role_code` = 'admin'
AND p.`id` IN (
@mes_equip_pid,
'1860000000000000134',
'1860000000000000070',
'1860000000000000071', '1860000000000000072', '1860000000000000073', '1860000000000000074', '1860000000000000075', '1860000000000000076',
'1860000000000000077',
'1860000000000000078', '1860000000000000079', '1860000000000000080', '1860000000000000081', '1860000000000000082', '1860000000000000083',
'1860000000000000084',
'1860000000000000085', '1860000000000000086', '1860000000000000087', '1860000000000000088', '1860000000000000089', '1860000000000000090',
'1860000000000000091',
'1860000000000000092', '1860000000000000093', '1860000000000000094', '1860000000000000095', '1860000000000000096', '1860000000000000097',
'1860000000000000098',
'1860000000000000099', '1860000000000000100', '1860000000000000101', '1860000000000000102', '1860000000000000103', '1860000000000000104',
'1860000000000000105',
'1860000000000000106', '1860000000000000107', '1860000000000000108', '1860000000000000109', '1860000000000000110', '1860000000000000111',
'1860000000000000112',
'1860000000000000113', '1860000000000000114', '1860000000000000115', '1860000000000000116', '1860000000000000117', '1860000000000000118',
'1860000000000000119',
'1860000000000000120', '1860000000000000121', '1860000000000000122', '1860000000000000123', '1860000000000000124', '1860000000000000125',
'1860000000000000126',
'1860000000000000127', '1860000000000000128', '1860000000000000129', '1860000000000000130', '1860000000000000131', '1860000000000000132',
'1860000000000000135', '1860000000000000136', '1860000000000000137', '1860000000000000138', '1860000000000000139', '1860000000000000140'
)
AND NOT EXISTS (
SELECT 1 FROM `sys_role_permission` rp
WHERE rp.`role_id` = r.`id` AND rp.`permission_id` = p.`id`
);

View File

@@ -0,0 +1,104 @@
-- 工序管理挂MES基础资料设备类别设备类型挂设备管理修复权限树is_leaf与租户 admin 授权
-- 适用菜单曾在 MES XSL 根下或 is_leaf=1 导致角色授权页不显示按钮权限
-- 修改租户 SET @mes_tenant_id
SET NAMES utf8mb4;
SET @mes_tenant_id = 1002;
SET @mes_base_pid = (
SELECT `id` FROM `sys_permission`
WHERE `del_flag` = 0 AND `menu_type` = 0 AND `name` = 'MES基础资料'
LIMIT 1
);
SET @mes_base_pid = IFNULL(@mes_base_pid, (
SELECT MIN(`id`) FROM `sys_permission`
WHERE `del_flag` = 0 AND `menu_type` = 0 AND `name` = 'MES资料'
));
SET @mes_base_pid = IFNULL(@mes_base_pid, '1860000000000000001');
SET @mes_equip_pid = (
SELECT `id` FROM `sys_permission`
WHERE `del_flag` = 0 AND `menu_type` = 0 AND `name` = '设备管理'
LIMIT 1
);
SET @mes_equip_pid = IFNULL(@mes_equip_pid, '1860000000000000133');
UPDATE `sys_permission`
SET `is_leaf` = 0
WHERE `del_flag` = 0 AND `menu_type` = 0 AND `name` IN ('MES基础资料', 'MES资料');
UPDATE `sys_permission`
SET `is_leaf` = 0
WHERE `id` = @mes_equip_pid;
INSERT INTO `sys_permission`(`id`, `parent_id`, `name`, `url`, `component`, `component_name`, `menu_type`, `perms`, `perms_type`, `sort_no`, `is_route`, `is_leaf`, `hidden`, `status`, `del_flag`, `keep_alive`, `internal_or_external`, `create_by`, `create_time`)
VALUES ('1860000000000000060', @mes_base_pid, '工序管理', '/xslmes/mesXslProcessOperation', 'xslmes/mesXslProcessOperation/MesXslProcessOperationList', NULL, 1, NULL, '1', 9, 1, 0, 0, '1', 0, 1, 0, 'admin', NOW())
ON DUPLICATE KEY UPDATE
`parent_id` = VALUES(`parent_id`), `url` = VALUES(`url`), `component` = VALUES(`component`),
`is_leaf` = 0, `hidden` = 0, `status` = '1', `del_flag` = 0;
INSERT INTO `sys_permission`(`id`, `parent_id`, `name`, `menu_type`, `perms`, `perms_type`, `is_leaf`, `status`, `del_flag`, `create_by`, `create_time`) VALUES
('1860000000000000061', '1860000000000000060', '新增', 2, 'mes:mes_process_operation:add', '1', 1, '1', 0, 'admin', NOW()),
('1860000000000000062', '1860000000000000060', '编辑', 2, 'mes:mes_process_operation:edit', '1', 1, '1', 0, 'admin', NOW()),
('1860000000000000063', '1860000000000000060', '删除', 2, 'mes:mes_process_operation:delete', '1', 1, '1', 0, 'admin', NOW()),
('1860000000000000064', '1860000000000000060', '批量删除', 2, 'mes:mes_process_operation:deleteBatch', '1', 1, '1', 0, 'admin', NOW()),
('1860000000000000065', '1860000000000000060', '导出', 2, 'mes:mes_process_operation:exportXls', '1', 1, '1', 0, 'admin', NOW()),
('1860000000000000066', '1860000000000000060', '导入', 2, 'mes:mes_process_operation:importExcel', '1', 1, '1', 0, 'admin', NOW())
ON DUPLICATE KEY UPDATE
`parent_id` = VALUES(`parent_id`), `perms` = VALUES(`perms`), `is_leaf` = 1, `status` = '1', `del_flag` = 0;
INSERT INTO `sys_permission`(`id`, `parent_id`, `name`, `url`, `component`, `component_name`, `menu_type`, `perms`, `perms_type`, `sort_no`, `is_route`, `is_leaf`, `hidden`, `status`, `del_flag`, `keep_alive`, `internal_or_external`, `create_by`, `create_time`)
VALUES ('1860000000000000070', @mes_equip_pid, '设备类别', '/xslmes/mesXslEquipmentCategory', 'xslmes/mesXslEquipmentCategory/MesXslEquipmentCategoryList', NULL, 1, NULL, '1', 2, 1, 0, 0, '1', 0, 1, 0, 'admin', NOW())
ON DUPLICATE KEY UPDATE
`parent_id` = VALUES(`parent_id`), `url` = VALUES(`url`), `component` = VALUES(`component`),
`is_leaf` = 0, `hidden` = 0, `status` = '1', `del_flag` = 0;
INSERT INTO `sys_permission`(`id`, `parent_id`, `name`, `menu_type`, `perms`, `perms_type`, `is_leaf`, `status`, `del_flag`, `create_by`, `create_time`) VALUES
('1860000000000000071', '1860000000000000070', '新增', 2, 'mes:mes_xsl_equipment_category:add', '1', 1, '1', 0, 'admin', NOW()),
('1860000000000000072', '1860000000000000070', '编辑', 2, 'mes:mes_xsl_equipment_category:edit', '1', 1, '1', 0, 'admin', NOW()),
('1860000000000000073', '1860000000000000070', '删除', 2, 'mes:mes_xsl_equipment_category:delete', '1', 1, '1', 0, 'admin', NOW()),
('1860000000000000074', '1860000000000000070', '批量删除', 2, 'mes:mes_xsl_equipment_category:deleteBatch', '1', 1, '1', 0, 'admin', NOW()),
('1860000000000000075', '1860000000000000070', '导出', 2, 'mes:mes_xsl_equipment_category:exportXls', '1', 1, '1', 0, 'admin', NOW()),
('1860000000000000076', '1860000000000000070', '导入', 2, 'mes:mes_xsl_equipment_category:importExcel', '1', 1, '1', 0, 'admin', NOW())
ON DUPLICATE KEY UPDATE
`parent_id` = VALUES(`parent_id`), `perms` = VALUES(`perms`), `is_leaf` = 1, `status` = '1', `del_flag` = 0;
INSERT INTO `sys_permission`(`id`, `parent_id`, `name`, `url`, `component`, `component_name`, `menu_type`, `perms`, `perms_type`, `sort_no`, `is_route`, `is_leaf`, `hidden`, `status`, `del_flag`, `keep_alive`, `internal_or_external`, `create_by`, `create_time`)
VALUES ('1860000000000000077', @mes_equip_pid, '设备类型', '/xslmes/mesXslEquipmentType', 'xslmes/mesXslEquipmentType/MesXslEquipmentTypeList', NULL, 1, NULL, '1', 3, 1, 0, 0, '1', 0, 1, 0, 'admin', NOW())
ON DUPLICATE KEY UPDATE
`parent_id` = VALUES(`parent_id`), `name` = VALUES(`name`), `url` = VALUES(`url`), `component` = VALUES(`component`),
`is_leaf` = 0, `hidden` = 0, `status` = '1', `del_flag` = 0;
INSERT INTO `sys_permission`(`id`, `parent_id`, `name`, `menu_type`, `perms`, `perms_type`, `is_leaf`, `status`, `del_flag`, `create_by`, `create_time`) VALUES
('1860000000000000078', '1860000000000000077', '新增', 2, 'mes:mes_xsl_equipment_type:add', '1', 1, '1', 0, 'admin', NOW()),
('1860000000000000079', '1860000000000000077', '编辑', 2, 'mes:mes_xsl_equipment_type:edit', '1', 1, '1', 0, 'admin', NOW()),
('1860000000000000080', '1860000000000000077', '删除', 2, 'mes:mes_xsl_equipment_type:delete', '1', 1, '1', 0, 'admin', NOW()),
('1860000000000000081', '1860000000000000077', '批量删除', 2, 'mes:mes_xsl_equipment_type:deleteBatch', '1', 1, '1', 0, 'admin', NOW()),
('1860000000000000082', '1860000000000000077', '导出', 2, 'mes:mes_xsl_equipment_type:exportXls', '1', 1, '1', 0, 'admin', NOW()),
('1860000000000000083', '1860000000000000077', '导入', 2, 'mes:mes_xsl_equipment_type:importExcel', '1', 1, '1', 0, 'admin', NOW())
ON DUPLICATE KEY UPDATE
`parent_id` = VALUES(`parent_id`), `perms` = VALUES(`perms`), `is_leaf` = 1, `status` = '1', `del_flag` = 0;
UPDATE `sys_permission` SET `name` = '新增' WHERE `id` = '1860000000000000061' AND `name` = '添加';
INSERT INTO `sys_role_permission`(`id`, `role_id`, `permission_id`, `operate_date`, `operate_ip`)
SELECT REPLACE(UUID(), '-', ''), r.`id`, p.`id`, NOW(), '127.0.0.1'
FROM `sys_role` r
CROSS JOIN `sys_permission` p
WHERE r.`tenant_id` = @mes_tenant_id
AND r.`role_code` = 'admin'
AND p.`id` IN (
'1860000000000000060',
'1860000000000000061', '1860000000000000062', '1860000000000000063',
'1860000000000000064', '1860000000000000065', '1860000000000000066',
'1860000000000000070',
'1860000000000000071', '1860000000000000072', '1860000000000000073',
'1860000000000000074', '1860000000000000075', '1860000000000000076',
'1860000000000000077',
'1860000000000000078', '1860000000000000079', '1860000000000000080',
'1860000000000000081', '1860000000000000082', '1860000000000000083'
)
AND NOT EXISTS (
SELECT 1 FROM `sys_role_permission` rp
WHERE rp.`role_id` = r.`id` AND rp.`permission_id` = p.`id`
);

View File

@@ -0,0 +1,90 @@
-- 工序管理(060) MES基础资料设备类别(070)挂设备管理修复 is_leaf租户 admin 授权
-- 可重复执行修改租户改 SET @mes_tenant_id
SET NAMES utf8mb4;
SET @mes_tenant_id = 1002;
SET @mes_base_pid = (
SELECT `id` FROM `sys_permission`
WHERE `del_flag` = 0 AND `menu_type` = 0 AND `name` = 'MES基础资料'
LIMIT 1
);
SET @mes_base_pid = IFNULL(@mes_base_pid, (
SELECT MIN(`id`) FROM `sys_permission`
WHERE `del_flag` = 0 AND `menu_type` = 0 AND `name` = 'MES资料'
));
SET @mes_base_pid = IFNULL(@mes_base_pid, '1860000000000000001');
SET @mes_equip_pid = (
SELECT `id` FROM `sys_permission`
WHERE `del_flag` = 0 AND `menu_type` = 0 AND `name` = '设备管理'
LIMIT 1
);
SET @mes_equip_pid = IFNULL(@mes_equip_pid, '1860000000000000133');
UPDATE `sys_permission`
SET `is_leaf` = 0
WHERE `del_flag` = 0 AND `menu_type` = 0 AND `name` IN ('MES基础资料', 'MES资料');
UPDATE `sys_permission`
SET `is_leaf` = 0
WHERE `id` = @mes_equip_pid;
-- 工序管理
INSERT INTO `sys_permission`(`id`, `parent_id`, `name`, `url`, `component`, `component_name`, `menu_type`, `perms`, `perms_type`, `sort_no`, `is_route`, `is_leaf`, `hidden`, `status`, `del_flag`, `keep_alive`, `internal_or_external`, `create_by`, `create_time`)
VALUES ('1860000000000000060', @mes_base_pid, '工序管理', '/xslmes/mesXslProcessOperation', 'xslmes/mesXslProcessOperation/MesXslProcessOperationList', NULL, 1, NULL, '1', 9, 1, 0, 0, '1', 0, 1, 0, 'admin', NOW())
ON DUPLICATE KEY UPDATE
`parent_id` = VALUES(`parent_id`), `name` = VALUES(`name`), `url` = VALUES(`url`), `component` = VALUES(`component`),
`menu_type` = VALUES(`menu_type`), `perms_type` = VALUES(`perms_type`), `sort_no` = VALUES(`sort_no`),
`is_route` = VALUES(`is_route`), `is_leaf` = 0, `hidden` = 0, `status` = '1', `del_flag` = 0;
INSERT INTO `sys_permission`(`id`, `parent_id`, `name`, `menu_type`, `perms`, `perms_type`, `is_leaf`, `status`, `del_flag`, `create_by`, `create_time`) VALUES
('1860000000000000061', '1860000000000000060', '新增', 2, 'mes:mes_process_operation:add', '1', 1, '1', 0, 'admin', NOW()),
('1860000000000000062', '1860000000000000060', '编辑', 2, 'mes:mes_process_operation:edit', '1', 1, '1', 0, 'admin', NOW()),
('1860000000000000063', '1860000000000000060', '删除', 2, 'mes:mes_process_operation:delete', '1', 1, '1', 0, 'admin', NOW()),
('1860000000000000064', '1860000000000000060', '批量删除', 2, 'mes:mes_process_operation:deleteBatch', '1', 1, '1', 0, 'admin', NOW()),
('1860000000000000065', '1860000000000000060', '导出', 2, 'mes:mes_process_operation:exportXls', '1', 1, '1', 0, 'admin', NOW()),
('1860000000000000066', '1860000000000000060', '导入', 2, 'mes:mes_process_operation:importExcel', '1', 1, '1', 0, 'admin', NOW())
ON DUPLICATE KEY UPDATE
`parent_id` = VALUES(`parent_id`), `name` = VALUES(`name`), `menu_type` = VALUES(`menu_type`), `perms` = VALUES(`perms`),
`perms_type` = VALUES(`perms_type`), `is_leaf` = 1, `status` = '1', `del_flag` = 0;
UPDATE `sys_permission` SET `name` = '新增' WHERE `id` = '1860000000000000061' AND `name` = '添加';
-- 设备类别
INSERT INTO `sys_permission`(`id`, `parent_id`, `name`, `url`, `component`, `component_name`, `menu_type`, `perms`, `perms_type`, `sort_no`, `is_route`, `is_leaf`, `hidden`, `status`, `del_flag`, `keep_alive`, `internal_or_external`, `create_by`, `create_time`)
VALUES ('1860000000000000070', @mes_equip_pid, '设备类别', '/xslmes/mesXslEquipmentCategory', 'xslmes/mesXslEquipmentCategory/MesXslEquipmentCategoryList', NULL, 1, NULL, '1', 2, 1, 0, 0, '1', 0, 1, 0, 'admin', NOW())
ON DUPLICATE KEY UPDATE
`parent_id` = VALUES(`parent_id`), `name` = VALUES(`name`), `url` = VALUES(`url`), `component` = VALUES(`component`),
`menu_type` = VALUES(`menu_type`), `perms_type` = VALUES(`perms_type`), `sort_no` = VALUES(`sort_no`),
`is_route` = VALUES(`is_route`), `is_leaf` = 0, `hidden` = 0, `status` = '1', `del_flag` = 0;
INSERT INTO `sys_permission`(`id`, `parent_id`, `name`, `menu_type`, `perms`, `perms_type`, `is_leaf`, `status`, `del_flag`, `create_by`, `create_time`) VALUES
('1860000000000000071', '1860000000000000070', '新增', 2, 'mes:mes_xsl_equipment_category:add', '1', 1, '1', 0, 'admin', NOW()),
('1860000000000000072', '1860000000000000070', '编辑', 2, 'mes:mes_xsl_equipment_category:edit', '1', 1, '1', 0, 'admin', NOW()),
('1860000000000000073', '1860000000000000070', '删除', 2, 'mes:mes_xsl_equipment_category:delete', '1', 1, '1', 0, 'admin', NOW()),
('1860000000000000074', '1860000000000000070', '批量删除', 2, 'mes:mes_xsl_equipment_category:deleteBatch', '1', 1, '1', 0, 'admin', NOW()),
('1860000000000000075', '1860000000000000070', '导出', 2, 'mes:mes_xsl_equipment_category:exportXls', '1', 1, '1', 0, 'admin', NOW()),
('1860000000000000076', '1860000000000000070', '导入', 2, 'mes:mes_xsl_equipment_category:importExcel', '1', 1, '1', 0, 'admin', NOW())
ON DUPLICATE KEY UPDATE
`parent_id` = VALUES(`parent_id`), `name` = VALUES(`name`), `menu_type` = VALUES(`menu_type`), `perms` = VALUES(`perms`),
`perms_type` = VALUES(`perms_type`), `is_leaf` = 1, `status` = '1', `del_flag` = 0;
INSERT INTO `sys_role_permission`(`id`, `role_id`, `permission_id`, `operate_date`, `operate_ip`)
SELECT REPLACE(UUID(), '-', ''), r.`id`, p.`id`, NOW(), '127.0.0.1'
FROM `sys_role` r
CROSS JOIN `sys_permission` p
WHERE r.`tenant_id` = @mes_tenant_id
AND r.`role_code` = 'admin'
AND p.`id` IN (
'1860000000000000060',
'1860000000000000061', '1860000000000000062', '1860000000000000063',
'1860000000000000064', '1860000000000000065', '1860000000000000066',
'1860000000000000070',
'1860000000000000071', '1860000000000000072', '1860000000000000073',
'1860000000000000074', '1860000000000000075', '1860000000000000076'
)
AND NOT EXISTS (
SELECT 1 FROM `sys_role_permission` rp
WHERE rp.`role_id` = r.`id` AND rp.`permission_id` = p.`id`
);

View File

@@ -0,0 +1,93 @@
-- 生产订单菜单与权限挂到MES密炼工程目录
SET NAMES utf8mb4;
SET @mixer_parent_id = (
SELECT id
FROM sys_permission
WHERE name = 'MES密炼工程' AND menu_type = 0 AND del_flag = 0
ORDER BY create_time ASC
LIMIT 1
);
SET @mixer_parent_id = IFNULL(@mixer_parent_id, (
SELECT id
FROM sys_permission
WHERE url = '/mes' AND menu_type = 0 AND del_flag = 0
ORDER BY create_time ASC
LIMIT 1
));
SET @mixer_parent_id = IFNULL(@mixer_parent_id, '1860000000000000001');
INSERT INTO sys_permission(
id, parent_id, name, url, component, component_name, menu_type, perms, perms_type, sort_no,
is_route, is_leaf, hidden, status, del_flag, keep_alive, internal_or_external, create_by, create_time
)
VALUES (
'1860000000000099511', @mixer_parent_id, '生产订单',
'/mes/productionorderinfo',
'mes/productionorderinfo/index',
'MesXslProductionOrderList', 1, NULL, '1', 33,
1, 1, 0, '1', 0, 1, 0, 'admin', NOW()
)
ON DUPLICATE KEY UPDATE
parent_id = VALUES(parent_id),
name = VALUES(name),
url = VALUES(url),
component = VALUES(component),
component_name = VALUES(component_name),
menu_type = VALUES(menu_type),
perms = VALUES(perms),
perms_type = VALUES(perms_type),
sort_no = VALUES(sort_no),
is_route = VALUES(is_route),
is_leaf = VALUES(is_leaf),
hidden = VALUES(hidden),
status = VALUES(status),
del_flag = VALUES(del_flag),
keep_alive = VALUES(keep_alive),
internal_or_external = VALUES(internal_or_external);
INSERT INTO sys_permission(id, parent_id, name, menu_type, perms, perms_type, status, del_flag, create_by, create_time) VALUES
('1860000000000099512', '1860000000000099511', '新增', 2, 'xslmes:mes_xsl_production_order:add', '1', '1', 0, 'admin', NOW()),
('1860000000000099513', '1860000000000099511', '编辑', 2, 'xslmes:mes_xsl_production_order:edit', '1', '1', 0, 'admin', NOW()),
('1860000000000099514', '1860000000000099511', '删除', 2, 'xslmes:mes_xsl_production_order:delete', '1', '1', 0, 'admin', NOW()),
('1860000000000099515', '1860000000000099511', '批量删除', 2, 'xslmes:mes_xsl_production_order:deleteBatch', '1', '1', 0, 'admin', NOW()),
('1860000000000099516', '1860000000000099511', '导出', 2, 'xslmes:mes_xsl_production_order:exportXls', '1', '1', 0, 'admin', NOW()),
('1860000000000099517', '1860000000000099511', '拆分', 2, 'xslmes:mes_xsl_production_order:split', '1', '1', 0, 'admin', NOW())
ON DUPLICATE KEY UPDATE
parent_id = VALUES(parent_id),
name = VALUES(name),
menu_type = VALUES(menu_type),
perms = VALUES(perms),
perms_type = VALUES(perms_type),
status = VALUES(status),
del_flag = VALUES(del_flag);
-- admin 角色授权
INSERT INTO sys_role_permission(id, role_id, permission_id, operate_date, operate_ip)
SELECT REPLACE(UUID(), '-', ''), 'f6817f48af4fb3af11b9e8bf182f618b', p.id, NOW(), '127.0.0.1'
FROM sys_permission p
WHERE p.id IN (
'1860000000000099511',
'1860000000000099512', '1860000000000099513', '1860000000000099514', '1860000000000099515', '1860000000000099516', '1860000000000099517'
)
AND NOT EXISTS (
SELECT 1
FROM sys_role_permission rp
WHERE rp.role_id = 'f6817f48af4fb3af11b9e8bf182f618b'
AND rp.permission_id = p.id
);
-- 强制修复确保菜单路由与组件路径正确
UPDATE sys_permission
SET
parent_id = @mixer_parent_id,
url = '/mes/productionorderinfo',
component = 'mes/productionorderinfo/index',
component_name = 'MesXslProductionOrderList',
menu_type = 1,
is_route = 1,
is_leaf = 1,
hidden = 0,
status = '1',
del_flag = 0
WHERE id = '1860000000000099511';

View File

@@ -0,0 +1,64 @@
-- 生产订单拆分按钮权限补丁
SET NAMES utf8mb4;
-- 优先按组件路径定位生产订单菜单
SET @prod_menu_id = (
SELECT id
FROM sys_permission
WHERE component = 'mes/productionorderinfo/index'
AND menu_type = 1
AND del_flag = 0
ORDER BY create_time ASC
LIMIT 1
);
-- 兜底按URL定位
SET @prod_menu_id = IFNULL(@prod_menu_id, (
SELECT id
FROM sys_permission
WHERE url = '/mes/productionorderinfo'
AND menu_type = 1
AND del_flag = 0
ORDER BY create_time ASC
LIMIT 1
));
-- 再兜底按名称定位
SET @prod_menu_id = IFNULL(@prod_menu_id, (
SELECT id
FROM sys_permission
WHERE name = '生产订单'
AND menu_type = 1
AND del_flag = 0
ORDER BY create_time ASC
LIMIT 1
));
-- 若找不到页面菜单回退到约定ID你现有脚本中使用
SET @prod_menu_id = IFNULL(@prod_menu_id, '1860000000000099511');
-- 写入/修复拆分按钮权限
INSERT INTO sys_permission (
id, parent_id, name, menu_type, perms, perms_type, status, del_flag, create_by, create_time
) VALUES (
'1860000000000099517', @prod_menu_id, '拆分', 2, 'xslmes:mes_xsl_production_order:split', '1', '1', 0, 'admin', NOW()
)
ON DUPLICATE KEY UPDATE
parent_id = VALUES(parent_id),
name = VALUES(name),
menu_type = VALUES(menu_type),
perms = VALUES(perms),
perms_type = VALUES(perms_type),
status = VALUES(status),
del_flag = VALUES(del_flag);
-- 给admin角色授权
INSERT INTO sys_role_permission(id, role_id, permission_id, operate_date, operate_ip)
SELECT REPLACE(UUID(), '-', ''), 'f6817f48af4fb3af11b9e8bf182f618b', '1860000000000099517', NOW(), '127.0.0.1'
FROM dual
WHERE NOT EXISTS (
SELECT 1
FROM sys_role_permission
WHERE role_id = 'f6817f48af4fb3af11b9e8bf182f618b'
AND permission_id = '1860000000000099517'
);

View File

@@ -0,0 +1,66 @@
-- 原材料送检记录菜单与权限挂到 MES管理
SET NAMES utf8mb4;
SET @mes_parent_id = (
SELECT id
FROM sys_permission
WHERE url = '/mes' AND menu_type = 0
ORDER BY create_time ASC
LIMIT 1
);
SET @mes_parent_id = IFNULL(@mes_parent_id, '1860000000000000001');
-- 二级菜单原材料送检记录
INSERT INTO sys_permission(
id, parent_id, name, url, component, component_name, menu_type, perms, perms_type, sort_no,
is_route, is_leaf, hidden, status, del_flag, keep_alive, internal_or_external, create_by, create_time
)
VALUES (
'1860000000000099111', @mes_parent_id, '原材料送检记录',
'/xslmes/mesXslRawMaterialInspectRecordList',
'xslmes/mesXslRawMaterialInspectRecord/MesXslRawMaterialInspectRecordList',
'MesXslRawMaterialInspectRecordList', 1, NULL, '1', 22,
1, 1, 0, '1', 0, 1, 0, 'admin', NOW()
)
ON DUPLICATE KEY UPDATE
parent_id = VALUES(parent_id),
name = VALUES(name),
url = VALUES(url),
component = VALUES(component),
component_name = VALUES(component_name),
menu_type = VALUES(menu_type),
perms = VALUES(perms),
perms_type = VALUES(perms_type),
sort_no = VALUES(sort_no),
is_route = VALUES(is_route),
is_leaf = VALUES(is_leaf),
hidden = VALUES(hidden),
status = VALUES(status),
del_flag = VALUES(del_flag),
keep_alive = VALUES(keep_alive),
internal_or_external = VALUES(internal_or_external);
-- 按钮权限
INSERT INTO sys_permission(id, parent_id, name, menu_type, perms, perms_type, status, del_flag, create_by, create_time) VALUES
('1860000000000099112', '1860000000000099111', '编辑', 2, 'xslmes:mes_xsl_raw_material_inspect_record:edit', '1', '1', 0, 'admin', NOW()),
('1860000000000099113', '1860000000000099111', '导出', 2, 'xslmes:mes_xsl_raw_material_inspect_record:exportXls', '1', '1', 0, 'admin', NOW())
ON DUPLICATE KEY UPDATE
parent_id = VALUES(parent_id),
name = VALUES(name),
menu_type = VALUES(menu_type),
perms = VALUES(perms),
perms_type = VALUES(perms_type),
status = VALUES(status),
del_flag = VALUES(del_flag);
-- admin 角色授权
INSERT INTO sys_role_permission(id, role_id, permission_id, operate_date, operate_ip)
SELECT REPLACE(UUID(), '-', ''), 'f6817f48af4fb3af11b9e8bf182f618b', p.id, NOW(), '127.0.0.1'
FROM sys_permission p
WHERE p.id IN ('1860000000000099111', '1860000000000099112', '1860000000000099113')
AND NOT EXISTS (
SELECT 1
FROM sys_role_permission rp
WHERE rp.role_id = 'f6817f48af4fb3af11b9e8bf182f618b'
AND rp.permission_id = p.id
);

View File

@@ -0,0 +1,36 @@
-- 原材料送检记录测试数据重置脚本稳妥版
-- 作用
-- 1) 将存在送检记录关联的原材料卡片检测结果重置为未检(0)
-- 2) 清空原材料送检记录主表/子表数据
SET NAMES utf8mb4;
START TRANSACTION;
-- 执行前计数便于确认是否命中数据
SELECT COUNT(1) AS before_record_count FROM mes_xsl_raw_material_inspect_record;
SELECT COUNT(1) AS before_record_line_count FROM mes_xsl_raw_material_inspect_record_line;
-- 回写原材料卡片检测结果为未检0只重置存在送检记录关联的卡片
UPDATE mes_xsl_raw_material_card c
JOIN (
SELECT DISTINCT r.raw_material_card_id AS card_id
FROM mes_xsl_raw_material_inspect_record r
WHERE r.raw_material_card_id IS NOT NULL
AND r.raw_material_card_id <> ''
) t ON t.card_id = c.id
SET c.test_result = '0',
c.update_time = NOW();
-- 先删子表再删主表
DELETE FROM mes_xsl_raw_material_inspect_record_line
WHERE record_id IN (
SELECT id FROM mes_xsl_raw_material_inspect_record
);
DELETE FROM mes_xsl_raw_material_inspect_record;
COMMIT;
-- 执行后计数
SELECT COUNT(1) AS remaining_record_count FROM mes_xsl_raw_material_inspect_record;
SELECT COUNT(1) AS remaining_record_line_count FROM mes_xsl_raw_material_inspect_record_line;

View File

@@ -0,0 +1,80 @@
-- 原材料送检记录主表 + 子表
SET NAMES utf8mb4;
CREATE TABLE IF NOT EXISTS `mes_xsl_raw_material_inspect_record` (
`id` varchar(32) NOT NULL COMMENT '主键',
`raw_material_card_id` varchar(32) DEFAULT NULL COMMENT '原材料卡片ID',
`barcode` varchar(128) DEFAULT NULL COMMENT '条码',
`batch_no` varchar(128) DEFAULT NULL COMMENT '批次号',
`material_id` varchar(32) DEFAULT NULL COMMENT '物料ID',
`material_name` varchar(200) DEFAULT NULL COMMENT '物料名称',
`inspect_status` varchar(10) DEFAULT '0' COMMENT '检验状态字典 xslmes_inspect_status0待检 1合格 2不合格',
`inspect_time` datetime DEFAULT NULL COMMENT '送检时间',
`result_time` datetime DEFAULT NULL COMMENT '判定时间',
`remark` varchar(500) DEFAULT NULL COMMENT '备注',
`create_by` varchar(32) DEFAULT NULL COMMENT '创建人',
`create_time` datetime DEFAULT NULL COMMENT '创建时间',
`update_by` varchar(32) DEFAULT NULL COMMENT '更新人',
`update_time` datetime DEFAULT NULL COMMENT '更新时间',
`tenant_id` int DEFAULT NULL COMMENT '租户',
PRIMARY KEY (`id`),
KEY `idx_xsl_rm_ir_card` (`raw_material_card_id`),
KEY `idx_xsl_rm_ir_status` (`inspect_status`),
KEY `idx_xsl_rm_ir_time` (`inspect_time`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='原材料送检记录';
CREATE TABLE IF NOT EXISTS `mes_xsl_raw_material_inspect_record_line` (
`id` varchar(32) NOT NULL COMMENT '主键',
`record_id` varchar(32) NOT NULL COMMENT '送检记录主表ID',
`inspect_std_id` varchar(32) DEFAULT NULL COMMENT '检验标准ID',
`inspect_item_id` varchar(32) DEFAULT NULL COMMENT '检验项目ID',
`inspect_item_name` varchar(200) DEFAULT NULL COMMENT '检验项目名称',
`allow_min` decimal(24,6) DEFAULT NULL COMMENT '容许最小值',
`include_min_flag` int NOT NULL DEFAULT '0' COMMENT '包含最小值1是 0否',
`allow_max` decimal(24,6) DEFAULT NULL COMMENT '容许最大值',
`include_max_flag` int NOT NULL DEFAULT '0' COMMENT '包含最大值1是 0否',
`inspect_value` decimal(24,6) DEFAULT NULL COMMENT '检验值',
`pass_flag` varchar(10) DEFAULT '0' COMMENT '判定状态字典 xslmes_inspect_status0待检 1合格 2不合格',
`sort_no` int DEFAULT NULL COMMENT '排序',
`create_by` varchar(32) DEFAULT NULL COMMENT '创建人',
`create_time` datetime DEFAULT NULL COMMENT '创建时间',
`update_by` varchar(32) DEFAULT NULL COMMENT '更新人',
`update_time` datetime DEFAULT NULL COMMENT '更新时间',
PRIMARY KEY (`id`),
KEY `idx_xsl_rm_irl_record` (`record_id`),
KEY `idx_xsl_rm_irl_item` (`inspect_item_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='原材料送检记录-检验明细';
-- 字典送检状态
INSERT INTO `sys_dict` (`id`, `dict_name`, `dict_code`, `description`, `del_flag`, `create_by`, `create_time`, `type`)
SELECT REPLACE(UUID(), '-', ''), '送检状态', 'xslmes_inspect_status', '原材料送检状态待检/合格/不合格', 0, 'admin', NOW(), 0
WHERE NOT EXISTS (
SELECT 1 FROM `sys_dict` WHERE `dict_code` = 'xslmes_inspect_status' AND `del_flag` = 0
);
INSERT INTO `sys_dict_item` (`id`, `dict_id`, `item_text`, `item_value`, `description`, `sort_order`, `status`, `create_by`, `create_time`)
SELECT REPLACE(UUID(), '-', ''), d.id, '待检', '0', '待检', 1, 1, 'admin', NOW()
FROM `sys_dict` d
WHERE d.`dict_code` = 'xslmes_inspect_status'
AND d.`del_flag` = 0
AND NOT EXISTS (
SELECT 1 FROM `sys_dict_item` i WHERE i.dict_id = d.id AND i.item_value = '0'
);
INSERT INTO `sys_dict_item` (`id`, `dict_id`, `item_text`, `item_value`, `description`, `sort_order`, `status`, `create_by`, `create_time`)
SELECT REPLACE(UUID(), '-', ''), d.id, '合格', '1', '合格', 2, 1, 'admin', NOW()
FROM `sys_dict` d
WHERE d.`dict_code` = 'xslmes_inspect_status'
AND d.`del_flag` = 0
AND NOT EXISTS (
SELECT 1 FROM `sys_dict_item` i WHERE i.dict_id = d.id AND i.item_value = '1'
);
INSERT INTO `sys_dict_item` (`id`, `dict_id`, `item_text`, `item_value`, `description`, `sort_order`, `status`, `create_by`, `create_time`)
SELECT REPLACE(UUID(), '-', ''), d.id, '不合格', '2', '不合格', 3, 1, 'admin', NOW()
FROM `sys_dict` d
WHERE d.`dict_code` = 'xslmes_inspect_status'
AND d.`del_flag` = 0
AND NOT EXISTS (
SELECT 1 FROM `sys_dict_item` i WHERE i.dict_id = d.id AND i.item_value = '2'
);

View File

@@ -0,0 +1,66 @@
-- MES 胶料快检数据点建表 + 菜单质量管理下+ 按钮 + 租户 admin 授权可整文件一次执行
-- 权限前缀mes:mes_xsl_rubber_quick_test_data_point:*
-- 依赖mes_xsl_rubber_quick_test_type修改租户改 SET @mes_tenant_id
SET NAMES utf8mb4;
CREATE TABLE IF NOT EXISTS `mes_xsl_rubber_quick_test_data_point` (
`id` varchar(32) NOT NULL COMMENT '主键',
`point_name` varchar(128) NOT NULL COMMENT '数据点名称同租户未删除唯一',
`quick_test_type_id` varchar(32) NOT NULL COMMENT '实验类型 mes_xsl_rubber_quick_test_type.id',
`quick_test_type_name` varchar(128) DEFAULT NULL COMMENT '实验类型名称冗余',
`unit_type` varchar(64) DEFAULT NULL COMMENT '单位类型手填',
`point_desc` varchar(500) DEFAULT NULL COMMENT '描述',
`tenant_id` int DEFAULT NULL COMMENT '租户',
`sys_org_code` varchar(64) DEFAULT NULL COMMENT '部门',
`create_by` varchar(32) DEFAULT NULL COMMENT '创建人',
`create_time` datetime DEFAULT NULL COMMENT '创建时间',
`update_by` varchar(32) DEFAULT NULL COMMENT '更新人',
`update_time` datetime DEFAULT NULL COMMENT '更新时间',
`del_flag` int DEFAULT '0' COMMENT '删除标记0正常1删除',
PRIMARY KEY (`id`),
KEY `idx_mrqtdp_tenant_type` (`tenant_id`, `quick_test_type_id`),
UNIQUE KEY `uk_mrqtdp_tenant_name_del` (`tenant_id`, `point_name`, `del_flag`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='MES胶料快检数据点';
SET @mes_tenant_id = 1002;
SET @mes_quality_pid = IFNULL(
(SELECT `id` FROM `sys_permission` WHERE `del_flag` = 0 AND `menu_type` = 0 AND `name` = '质量管理' LIMIT 1),
'1860000000000000162'
);
INSERT INTO `sys_permission`(`id`, `parent_id`, `name`, `url`, `component`, `component_name`, `menu_type`, `perms`, `perms_type`, `sort_no`, `is_route`, `is_leaf`, `hidden`, `status`, `del_flag`, `keep_alive`, `internal_or_external`, `create_by`, `create_time`)
VALUES ('1860000000000000170', @mes_quality_pid, '胶料快检数据点', '/xslmes/mesXslRubberQuickTestDataPoint', 'xslmes/mesXslRubberQuickTestDataPoint/MesXslRubberQuickTestDataPointList', 'MesXslRubberQuickTestDataPointList', 1, NULL, '1', 2, 1, 0, 0, '1', 0, 1, 0, 'admin', NOW())
ON DUPLICATE KEY UPDATE
`parent_id` = VALUES(`parent_id`), `name` = VALUES(`name`), `url` = VALUES(`url`), `component` = VALUES(`component`), `component_name` = VALUES(`component_name`),
`menu_type` = VALUES(`menu_type`), `perms` = VALUES(`perms`), `perms_type` = VALUES(`perms_type`), `sort_no` = VALUES(`sort_no`),
`is_route` = VALUES(`is_route`), `is_leaf` = 0, `hidden` = 0, `status` = '1', `del_flag` = 0,
`keep_alive` = VALUES(`keep_alive`), `internal_or_external` = VALUES(`internal_or_external`);
UPDATE `sys_permission` SET `icon` = 'ant-design:dot-chart-outlined' WHERE `id` = '1860000000000000170' AND `del_flag` = 0;
INSERT INTO `sys_permission`(`id`, `parent_id`, `name`, `menu_type`, `perms`, `perms_type`, `is_leaf`, `status`, `del_flag`, `create_by`, `create_time`) VALUES
('1860000000000000171', '1860000000000000170', '新增', 2, 'mes:mes_xsl_rubber_quick_test_data_point:add', '1', 1, '1', 0, 'admin', NOW()),
('1860000000000000172', '1860000000000000170', '编辑', 2, 'mes:mes_xsl_rubber_quick_test_data_point:edit', '1', 1, '1', 0, 'admin', NOW()),
('1860000000000000173', '1860000000000000170', '删除', 2, 'mes:mes_xsl_rubber_quick_test_data_point:delete', '1', 1, '1', 0, 'admin', NOW()),
('1860000000000000174', '1860000000000000170', '批量删除', 2, 'mes:mes_xsl_rubber_quick_test_data_point:deleteBatch', '1', 1, '1', 0, 'admin', NOW()),
('1860000000000000175', '1860000000000000170', '导出', 2, 'mes:mes_xsl_rubber_quick_test_data_point:exportXls', '1', 1, '1', 0, 'admin', NOW()),
('1860000000000000176', '1860000000000000170', '导入', 2, 'mes:mes_xsl_rubber_quick_test_data_point:importExcel', '1', 1, '1', 0, 'admin', NOW())
ON DUPLICATE KEY UPDATE
`parent_id` = VALUES(`parent_id`), `name` = VALUES(`name`), `menu_type` = VALUES(`menu_type`), `perms` = VALUES(`perms`), `perms_type` = VALUES(`perms_type`),
`is_leaf` = 1, `status` = '1', `del_flag` = 0;
INSERT INTO `sys_role_permission`(`id`, `role_id`, `permission_id`, `operate_date`, `operate_ip`)
SELECT REPLACE(UUID(), '-', ''), r.`id`, p.`id`, NOW(), '127.0.0.1'
FROM `sys_role` r
CROSS JOIN `sys_permission` p
WHERE r.`tenant_id` = @mes_tenant_id
AND r.`role_code` = 'admin'
AND p.`id` IN (
'1860000000000000170',
'1860000000000000171', '1860000000000000172', '1860000000000000173', '1860000000000000174',
'1860000000000000175', '1860000000000000176'
)
AND NOT EXISTS (
SELECT 1 FROM `sys_role_permission` rp
WHERE rp.`role_id` = r.`id` AND rp.`permission_id` = p.`id`
);

View File

@@ -0,0 +1,27 @@
-- 撤销胶料快检实验方法删除菜单权限字典业务表可整文件一次执行
-- 说明若仅未执行过 V3.9.2_99 / mes-xsl-rubber-quick-test-method-menu-permission.sql执行本脚本即可
-- Flyway 执行过 V3.9.2_99 的环境请同时执行 flyway V3.9.2_100 或本脚本内容一致
SET NAMES utf8mb4;
DELETE FROM `sys_role_permission`
WHERE `permission_id` IN (
'1860000000000000170',
'1860000000000000171', '1860000000000000172', '1860000000000000173',
'1860000000000000174', '1860000000000000175', '1860000000000000176'
);
DELETE FROM `sys_permission`
WHERE `id` IN (
'1860000000000000170',
'1860000000000000171', '1860000000000000172', '1860000000000000173',
'1860000000000000174', '1860000000000000175', '1860000000000000176'
);
DELETE di FROM `sys_dict_item` di
INNER JOIN `sys_dict` d ON di.`dict_id` = d.`id`
WHERE d.`dict_code` = 'xslmes_rubber_quick_test_rotor_type' AND d.`del_flag` = 0;
DELETE FROM `sys_dict`
WHERE `dict_code` = 'xslmes_rubber_quick_test_rotor_type';
DROP TABLE IF EXISTS `mes_xsl_rubber_quick_test_method`;

View File

@@ -0,0 +1,294 @@
-- 胶料快检实验方法主子表字典 + 建表 + 菜单质量管理下+ 按钮 + 租户 admin 授权
-- 权限前缀mes:mes_xsl_rubber_quick_test_method:*
-- 菜单 ID 1860000000000000177与数据点 170 段区分
-- 可与 Flyway V3.9.2_102 重复执行ON DUPLICATE / IF NOT EXISTS
-- SET @mes_tenant_id多租户 admin 授权目标租户
SET NAMES utf8mb4;
INSERT INTO `sys_dict` (`id`, `dict_name`, `dict_code`, `description`, `del_flag`, `create_by`, `create_time`, `type`, `tenant_id`)
SELECT REPLACE(UUID(), '-', ''), 'MES胶料快检转子类型', 'xslmes_rubber_quick_test_rotor_type', '1大转子2小转子', 0, 'admin', NOW(), 0, 0
WHERE NOT EXISTS (SELECT 1 FROM `sys_dict` WHERE `dict_code` = 'xslmes_rubber_quick_test_rotor_type' AND `del_flag` = 0);
INSERT INTO `sys_dict_item` (`id`, `dict_id`, `item_text`, `item_value`, `sort_order`, `status`, `create_by`, `create_time`)
SELECT REPLACE(UUID(), '-', ''), d.id, '大转子', '1', 1, 1, 'admin', NOW() FROM `sys_dict` d
WHERE d.`dict_code` = 'xslmes_rubber_quick_test_rotor_type' AND NOT EXISTS (SELECT 1 FROM `sys_dict_item` i WHERE i.`dict_id` = d.id AND i.`item_value` = '1');
INSERT INTO `sys_dict_item` (`id`, `dict_id`, `item_text`, `item_value`, `sort_order`, `status`, `create_by`, `create_time`)
SELECT REPLACE(UUID(), '-', ''), d.id, '小转子', '2', 2, 1, 'admin', NOW() FROM `sys_dict` d
WHERE d.`dict_code` = 'xslmes_rubber_quick_test_rotor_type' AND NOT EXISTS (SELECT 1 FROM `sys_dict_item` i WHERE i.`dict_id` = d.id AND i.`item_value` = '2');
INSERT INTO `sys_dict` (`id`, `dict_name`, `dict_code`, `description`, `del_flag`, `create_by`, `create_time`, `type`, `tenant_id`)
SELECT REPLACE(UUID(), '-', ''), 'MES胶料快检扭矩单位', 'xslmes_rubber_quick_test_torque_unit', 'Ib.indNmkg.cmNmmdm', 0, 'admin', NOW(), 0, 0
WHERE NOT EXISTS (SELECT 1 FROM `sys_dict` WHERE `dict_code` = 'xslmes_rubber_quick_test_torque_unit' AND `del_flag` = 0);
INSERT INTO `sys_dict_item` (`id`, `dict_id`, `item_text`, `item_value`, `sort_order`, `status`, `create_by`, `create_time`)
SELECT REPLACE(UUID(), '-', ''), d.id, v.txt, v.val, v.ord, 1, 'admin', NOW()
FROM `sys_dict` d
CROSS JOIN (
SELECT 'Ib.in' AS txt, 'Ib.in' AS val, 1 AS ord UNION ALL
SELECT 'dNm', 'dNm', 2 UNION ALL
SELECT 'kg.cm', 'kg.cm', 3 UNION ALL
SELECT 'Nm', 'Nm', 4 UNION ALL
SELECT 'mdm', 'mdm', 5
) v
WHERE d.`dict_code` = 'xslmes_rubber_quick_test_torque_unit'
AND NOT EXISTS (SELECT 1 FROM `sys_dict_item` i WHERE i.`dict_id` = d.id AND i.`item_value` = v.val);
INSERT INTO `sys_dict` (`id`, `dict_name`, `dict_code`, `description`, `del_flag`, `create_by`, `create_time`, `type`, `tenant_id`)
SELECT REPLACE(UUID(), '-', ''), 'MES胶料快检时间单位', 'xslmes_rubber_quick_test_time_unit', 'secminm:s', 0, 'admin', NOW(), 0, 0
WHERE NOT EXISTS (SELECT 1 FROM `sys_dict` WHERE `dict_code` = 'xslmes_rubber_quick_test_time_unit' AND `del_flag` = 0);
INSERT INTO `sys_dict_item` (`id`, `dict_id`, `item_text`, `item_value`, `sort_order`, `status`, `create_by`, `create_time`)
SELECT REPLACE(UUID(), '-', ''), d.id, v.txt, v.val, v.ord, 1, 'admin', NOW()
FROM `sys_dict` d
CROSS JOIN (
SELECT 'sec' AS txt, 'sec' AS val, 1 AS ord UNION ALL
SELECT 'min', 'min', 2 UNION ALL
SELECT 'm:s', 'm:s', 3
) v
WHERE d.`dict_code` = 'xslmes_rubber_quick_test_time_unit'
AND NOT EXISTS (SELECT 1 FROM `sys_dict_item` i WHERE i.`dict_id` = d.id AND i.`item_value` = v.val);
INSERT INTO `sys_dict` (`id`, `dict_name`, `dict_code`, `description`, `del_flag`, `create_by`, `create_time`, `type`, `tenant_id`)
SELECT REPLACE(UUID(), '-', ''), 'MES胶料快检门尼单位', 'xslmes_rubber_quick_test_mooney_unit', 'MU', 0, 'admin', NOW(), 0, 0
WHERE NOT EXISTS (SELECT 1 FROM `sys_dict` WHERE `dict_code` = 'xslmes_rubber_quick_test_mooney_unit' AND `del_flag` = 0);
INSERT INTO `sys_dict_item` (`id`, `dict_id`, `item_text`, `item_value`, `sort_order`, `status`, `create_by`, `create_time`)
SELECT REPLACE(UUID(), '-', ''), d.id, 'MU', 'MU', 1, 1, 'admin', NOW() FROM `sys_dict` d
WHERE d.`dict_code` = 'xslmes_rubber_quick_test_mooney_unit'
AND NOT EXISTS (SELECT 1 FROM `sys_dict_item` i WHERE i.`dict_id` = d.id AND i.`item_value` = 'MU');
CREATE TABLE IF NOT EXISTS `mes_xsl_rubber_quick_test_method` (
`id` varchar(32) NOT NULL COMMENT '主键',
`method_code` varchar(16) NOT NULL COMMENT '方法编号租户内从001递增自动生成',
`method_name` varchar(128) NOT NULL COMMENT '实验方法名称同租户未删除唯一',
`quick_test_type_id` varchar(32) NOT NULL COMMENT '实验类型 mes_xsl_rubber_quick_test_type.id',
`quick_test_type_name` varchar(128) DEFAULT NULL COMMENT '实验类型名称冗余',
`test_temp_c` decimal(12,2) DEFAULT NULL COMMENT '实验温度°C',
`preheat_time_min` decimal(12,2) DEFAULT NULL COMMENT '预热时间min',
`test_time_min` decimal(12,2) DEFAULT NULL COMMENT '实验时间min',
`test_angle_deg` decimal(12,2) DEFAULT NULL COMMENT '实验角度Deg',
`test_freq_hz` decimal(12,2) DEFAULT NULL COMMENT '实验频率Hz',
`rotor_type` varchar(2) DEFAULT NULL COMMENT '转子类型字典xslmes_rubber_quick_test_rotor_type1大转子2小转子',
`rotor_speed_rpm` decimal(12,2) DEFAULT NULL COMMENT '转子速度rpm',
`method_desc` varchar(500) DEFAULT NULL COMMENT '方法描述',
`tenant_id` int DEFAULT NULL COMMENT '租户',
`sys_org_code` varchar(64) DEFAULT NULL COMMENT '部门',
`create_by` varchar(32) DEFAULT NULL COMMENT '创建人',
`create_time` datetime DEFAULT NULL COMMENT '创建时间',
`update_by` varchar(32) DEFAULT NULL COMMENT '更新人',
`update_time` datetime DEFAULT NULL COMMENT '更新时间',
`del_flag` int DEFAULT '0' COMMENT '删除标记0正常1删除',
PRIMARY KEY (`id`),
KEY `idx_mrqtm_tenant_code` (`tenant_id`, `method_code`),
KEY `idx_mrqtm_type` (`quick_test_type_id`),
UNIQUE KEY `uk_mrqtm_tenant_name_del` (`tenant_id`, `method_name`, `del_flag`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='MES胶料快检实验方法';
CREATE TABLE IF NOT EXISTS `mes_xsl_rubber_quick_test_method_line` (
`id` varchar(32) NOT NULL COMMENT '主键',
`method_id` varchar(32) NOT NULL COMMENT '主表 mes_xsl_rubber_quick_test_method.id',
`data_point_id` varchar(32) NOT NULL COMMENT '数据点 mes_xsl_rubber_quick_test_data_point.id',
`point_name` varchar(128) DEFAULT NULL COMMENT '数据点名称冗余只读带出',
`unit_type` varchar(64) DEFAULT NULL COMMENT '单位类型冗余只读带出',
`torque_unit_type` varchar(32) DEFAULT NULL COMMENT '扭矩单位类型字典xslmes_rubber_quick_test_torque_unit',
`time_unit_type` varchar(32) DEFAULT NULL COMMENT '时间单位类型字典xslmes_rubber_quick_test_time_unit',
`mooney_unit_type` varchar(32) DEFAULT NULL COMMENT '门尼单位类型字典xslmes_rubber_quick_test_mooney_unit',
`sort_no` int DEFAULT NULL COMMENT '排序号',
`create_by` varchar(32) DEFAULT NULL COMMENT '创建人',
`create_time` datetime DEFAULT NULL COMMENT '创建时间',
`update_by` varchar(32) DEFAULT NULL COMMENT '更新人',
`update_time` datetime DEFAULT NULL COMMENT '更新时间',
PRIMARY KEY (`id`),
KEY `idx_mrqtml_method` (`method_id`),
UNIQUE KEY `uk_mrqtml_method_point` (`method_id`, `data_point_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='MES胶料快检实验方法明细';
SET @mes_tenant_id = 1002;
SET @mes_quality_pid = IFNULL(
(SELECT `id` FROM `sys_permission` WHERE `del_flag` = 0 AND `menu_type` = 0 AND `name` = '质量管理' LIMIT 1),
'1860000000000000162'
);
INSERT INTO `sys_permission`(`id`, `parent_id`, `name`, `url`, `component`, `component_name`, `menu_type`, `perms`, `perms_type`, `sort_no`, `is_route`, `is_leaf`, `hidden`, `status`, `del_flag`, `keep_alive`, `internal_or_external`, `create_by`, `create_time`)
VALUES ('1860000000000000177', @mes_quality_pid, '胶料快检实验方法', '/xslmes/mesXslRubberQuickTestMethod', 'xslmes/mesXslRubberQuickTestMethod/MesXslRubberQuickTestMethodList', 'MesXslRubberQuickTestMethodList', 1, NULL, '1', 3, 1, 0, 0, '1', 0, 1, 0, 'admin', NOW())
ON DUPLICATE KEY UPDATE
`parent_id` = VALUES(`parent_id`), `name` = VALUES(`name`), `url` = VALUES(`url`), `component` = VALUES(`component`), `component_name` = VALUES(`component_name`),
`menu_type` = VALUES(`menu_type`), `perms` = VALUES(`perms`), `perms_type` = VALUES(`perms_type`), `sort_no` = VALUES(`sort_no`),
`is_route` = VALUES(`is_route`), `is_leaf` = 0, `hidden` = 0, `status` = '1', `del_flag` = 0,
`keep_alive` = VALUES(`keep_alive`), `internal_or_external` = VALUES(`internal_or_external`);
UPDATE `sys_permission` SET `icon` = 'ant-design:profile-outlined' WHERE `id` = '1860000000000000177' AND `del_flag` = 0;
INSERT INTO `sys_permission`(`id`, `parent_id`, `name`, `menu_type`, `perms`, `perms_type`, `is_leaf`, `status`, `del_flag`, `create_by`, `create_time`) VALUES
('1860000000000000178', '1860000000000000177', '新增', 2, 'mes:mes_xsl_rubber_quick_test_method:add', '1', 1, '1', 0, 'admin', NOW()),
('1860000000000000179', '1860000000000000177', '编辑', 2, 'mes:mes_xsl_rubber_quick_test_method:edit', '1', 1, '1', 0, 'admin', NOW()),
('1860000000000000180', '1860000000000000177', '删除', 2, 'mes:mes_xsl_rubber_quick_test_method:delete', '1', 1, '1', 0, 'admin', NOW()),
('1860000000000000181', '1860000000000000177', '批量删除', 2, 'mes:mes_xsl_rubber_quick_test_method:deleteBatch', '1', 1, '1', 0, 'admin', NOW()),
('1860000000000000182', '1860000000000000177', '导出', 2, 'mes:mes_xsl_rubber_quick_test_method:exportXls', '1', 1, '1', 0, 'admin', NOW()),
('1860000000000000183', '1860000000000000177', '导入', 2, 'mes:mes_xsl_rubber_quick_test_method:importExcel', '1', 1, '1', 0, 'admin', NOW())
ON DUPLICATE KEY UPDATE
`parent_id` = VALUES(`parent_id`), `name` = VALUES(`name`), `menu_type` = VALUES(`menu_type`), `perms` = VALUES(`perms`), `perms_type` = VALUES(`perms_type`),
`is_leaf` = 1, `status` = '1', `del_flag` = 0;
INSERT INTO `sys_role_permission`(`id`, `role_id`, `permission_id`, `operate_date`, `operate_ip`)
SELECT REPLACE(UUID(), '-', ''), r.`id`, p.`id`, NOW(), '127.0.0.1'
FROM `sys_role` r
CROSS JOIN `sys_permission` p
WHERE r.`tenant_id` = @mes_tenant_id
AND r.`role_code` = 'admin'
AND p.`id` IN (
'1860000000000000177',
'1860000000000000178', '1860000000000000179', '1860000000000000180', '1860000000000000181',
'1860000000000000182', '1860000000000000183'
)
AND NOT EXISTS (
SELECT 1 FROM `sys_role_permission` rp
WHERE rp.`role_id` = r.`id` AND rp.`permission_id` = p.`id`
);

View File

@@ -0,0 +1,151 @@
-- 胶料快检记录主子表字典 + 建表 + 菜单质量管理下+ 按钮 + 胶料信息检验按钮 + 租户 admin 授权
-- 权限前缀mes:mes_xsl_rubber_quick_test_record:*
-- 菜单 ID 1860000000000000192
-- SET @mes_tenant_id多租户 admin 授权目标租户
SET NAMES utf8mb4;
INSERT INTO `sys_dict` (`id`, `dict_name`, `dict_code`, `description`, `del_flag`, `create_by`, `create_time`, `type`, `tenant_id`)
SELECT REPLACE(UUID(), '-', ''), 'MES胶料快检记录检验结果', 'xslmes_rubber_quick_test_record_result', '1合格0不合格', 0, 'admin', NOW(), 0, 0
WHERE NOT EXISTS (SELECT 1 FROM `sys_dict` WHERE `dict_code` = 'xslmes_rubber_quick_test_record_result' AND `del_flag` = 0);
INSERT INTO `sys_dict_item` (`id`, `dict_id`, `item_text`, `item_value`, `sort_order`, `status`, `create_by`, `create_time`)
SELECT REPLACE(UUID(), '-', ''), d.id, '合格', '1', 1, 1, 'admin', NOW() FROM `sys_dict` d
WHERE d.`dict_code` = 'xslmes_rubber_quick_test_record_result' AND NOT EXISTS (SELECT 1 FROM `sys_dict_item` i WHERE i.`dict_id` = d.id AND i.`item_value` = '1');
INSERT INTO `sys_dict_item` (`id`, `dict_id`, `item_text`, `item_value`, `sort_order`, `status`, `create_by`, `create_time`)
SELECT REPLACE(UUID(), '-', ''), d.id, '不合格', '0', 2, 1, 'admin', NOW() FROM `sys_dict` d
WHERE d.`dict_code` = 'xslmes_rubber_quick_test_record_result' AND NOT EXISTS (SELECT 1 FROM `sys_dict_item` i WHERE i.`dict_id` = d.id AND i.`item_value` = '0');
INSERT INTO `sys_dict` (`id`, `dict_name`, `dict_code`, `description`, `del_flag`, `create_by`, `create_time`, `type`, `tenant_id`)
SELECT REPLACE(UUID(), '-', ''), 'MES胶料快检班次', 'xslmes_rubber_quick_test_work_shift', '班次', 0, 'admin', NOW(), 0, 0
WHERE NOT EXISTS (SELECT 1 FROM `sys_dict` WHERE `dict_code` = 'xslmes_rubber_quick_test_work_shift' AND `del_flag` = 0);
INSERT INTO `sys_dict_item` (`id`, `dict_id`, `item_text`, `item_value`, `sort_order`, `status`, `create_by`, `create_time`)
SELECT REPLACE(UUID(), '-', ''), d.id, v.txt, v.val, v.ord, 1, 'admin', NOW()
FROM `sys_dict` d
CROSS JOIN (
SELECT '早班' AS txt, '1' AS val, 1 AS ord UNION ALL
SELECT '中班', '2', 2 UNION ALL
SELECT '晚班', '3', 3
) v
WHERE d.`dict_code` = 'xslmes_rubber_quick_test_work_shift'
AND NOT EXISTS (SELECT 1 FROM `sys_dict_item` i WHERE i.`dict_id` = d.id AND i.`item_value` = v.val);
INSERT INTO `sys_dict` (`id`, `dict_name`, `dict_code`, `description`, `del_flag`, `create_by`, `create_time`, `type`, `tenant_id`)
SELECT REPLACE(UUID(), '-', ''), 'MES胶料快检班组', 'xslmes_rubber_quick_test_work_team', '班组', 0, 'admin', NOW(), 0, 0
WHERE NOT EXISTS (SELECT 1 FROM `sys_dict` WHERE `dict_code` = 'xslmes_rubber_quick_test_work_team' AND `del_flag` = 0);
INSERT INTO `sys_dict_item` (`id`, `dict_id`, `item_text`, `item_value`, `sort_order`, `status`, `create_by`, `create_time`)
SELECT REPLACE(UUID(), '-', ''), d.id, v.txt, v.val, v.ord, 1, 'admin', NOW()
FROM `sys_dict` d
CROSS JOIN (
SELECT '甲班' AS txt, '1' AS val, 1 AS ord UNION ALL
SELECT '乙班', '2', 2 UNION ALL
SELECT '丙班', '3', 3
) v
WHERE d.`dict_code` = 'xslmes_rubber_quick_test_work_team'
AND NOT EXISTS (SELECT 1 FROM `sys_dict_item` i WHERE i.`dict_id` = d.id AND i.`item_value` = v.val);
CREATE TABLE IF NOT EXISTS `mes_xsl_rubber_quick_test_record` (
`id` varchar(32) NOT NULL COMMENT '主键',
`record_no` varchar(32) DEFAULT NULL COMMENT '单号JL+日期+4位流水如JL202605280001',
`rubber_material_id` varchar(32) DEFAULT NULL COMMENT '胶料 mes_material.id',
`rubber_material_name` varchar(128) DEFAULT NULL COMMENT '胶料名称冗余',
`std_id` varchar(32) DEFAULT NULL COMMENT '引用的实验标准 mes_xsl_rubber_quick_test_std.id',
`prod_equipment_ledger_id` varchar(32) DEFAULT NULL COMMENT '生产机台 mes_xsl_equipment_ledger.id',
`prod_equipment_name` varchar(128) DEFAULT NULL COMMENT '生产机台名称冗余',
`production_date` date DEFAULT NULL COMMENT '生产日期',
`train_no` varchar(64) DEFAULT NULL COMMENT '车次编号',
`work_shift` varchar(8) DEFAULT NULL COMMENT '班次字典xslmes_rubber_quick_test_work_shift',
`work_team` varchar(8) DEFAULT NULL COMMENT '班组字典xslmes_rubber_quick_test_work_team',
`inspect_times` int DEFAULT NULL COMMENT '检验次数',
`inspect_time` datetime DEFAULT NULL COMMENT '检验时间',
`inspector_user_id` varchar(32) DEFAULT NULL COMMENT '检验人用户ID',
`inspector_username` varchar(64) DEFAULT NULL COMMENT '检验人账号冗余',
`inspector_realname` varchar(64) DEFAULT NULL COMMENT '检验人姓名冗余',
`quick_test_type_id` varchar(32) DEFAULT NULL COMMENT '检验类型 mes_xsl_rubber_quick_test_type.id',
`quick_test_type_name` varchar(128) DEFAULT NULL COMMENT '检验类型名称冗余',
`inspect_result` varchar(2) DEFAULT NULL COMMENT '检验结果字典xslmes_rubber_quick_test_record_result1合格0不合格',
`production_plan_no` varchar(100) DEFAULT NULL COMMENT '生产计划号',
`inspect_equipment_ledger_id` varchar(32) DEFAULT NULL COMMENT '检验机台 mes_xsl_equipment_ledger.id',
`inspect_equipment_name` varchar(128) DEFAULT NULL COMMENT '检验机台名称冗余',
`rubber_card_no` varchar(100) DEFAULT NULL COMMENT '胶料卡片号',
`rubber_batch_no` varchar(100) DEFAULT NULL COMMENT '胶料批次',
`tenant_id` int DEFAULT NULL COMMENT '租户',
`sys_org_code` varchar(64) DEFAULT NULL COMMENT '部门',
`create_by` varchar(32) DEFAULT NULL COMMENT '创建人',
`create_time` datetime DEFAULT NULL COMMENT '创建时间',
`update_by` varchar(32) DEFAULT NULL COMMENT '更新人',
`update_time` datetime DEFAULT NULL COMMENT '更新时间',
`del_flag` int DEFAULT '0' COMMENT '删除标记0正常1删除',
PRIMARY KEY (`id`),
UNIQUE KEY `uk_mrqtr_record_no` (`record_no`),
KEY `idx_mrqtr_material` (`rubber_material_id`),
KEY `idx_mrqtr_std` (`std_id`),
KEY `idx_mrqtr_tenant` (`tenant_id`),
KEY `idx_mrqtr_inspect_time` (`inspect_time`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='MES胶料快检记录';
CREATE TABLE IF NOT EXISTS `mes_xsl_rubber_quick_test_record_line` (
`id` varchar(32) NOT NULL COMMENT '主键',
`record_id` varchar(32) NOT NULL COMMENT '主表 mes_xsl_rubber_quick_test_record.id',
`data_point_id` varchar(32) DEFAULT NULL COMMENT '数据点 mes_xsl_rubber_quick_test_data_point.id',
`inspect_item` varchar(128) DEFAULT NULL COMMENT '检验项目数据点名称只读带出',
`lower_limit` decimal(18,6) DEFAULT NULL COMMENT '检验下限只读带出',
`inspect_value` decimal(18,6) DEFAULT NULL COMMENT '检验值',
`upper_limit` decimal(18,6) DEFAULT NULL COMMENT '检验上限只读带出',
`sort_no` int DEFAULT NULL COMMENT '排序号',
`create_by` varchar(32) DEFAULT NULL COMMENT '创建人',
`create_time` datetime DEFAULT NULL COMMENT '创建时间',
`update_by` varchar(32) DEFAULT NULL COMMENT '更新人',
`update_time` datetime DEFAULT NULL COMMENT '更新时间',
PRIMARY KEY (`id`),
KEY `idx_mrqtrl_record` (`record_id`),
UNIQUE KEY `uk_mrqtrl_record_point` (`record_id`, `data_point_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='MES胶料快检记录明细';
SET @mes_tenant_id = 1002;
SET @mes_quality_pid = IFNULL(
(SELECT `id` FROM `sys_permission` WHERE `del_flag` = 0 AND `menu_type` = 0 AND `name` = '质量管理' LIMIT 1),
'1860000000000000162'
);
INSERT INTO `sys_permission`(`id`, `parent_id`, `name`, `url`, `component`, `component_name`, `menu_type`, `perms`, `perms_type`, `sort_no`, `is_route`, `is_leaf`, `hidden`, `status`, `del_flag`, `keep_alive`, `internal_or_external`, `create_by`, `create_time`)
VALUES ('1860000000000000192', @mes_quality_pid, '胶料快检记录', '/xslmes/mesXslRubberQuickTestRecord', 'xslmes/mesXslRubberQuickTestRecord/MesXslRubberQuickTestRecordList', 'MesXslRubberQuickTestRecordList', 1, NULL, '1', 5, 1, 0, 0, '1', 0, 1, 0, 'admin', NOW())
ON DUPLICATE KEY UPDATE
`parent_id` = VALUES(`parent_id`), `name` = VALUES(`name`), `url` = VALUES(`url`), `component` = VALUES(`component`),
`component_name` = VALUES(`component_name`), `sort_no` = VALUES(`sort_no`), `is_leaf` = VALUES(`is_leaf`), `keep_alive` = VALUES(`keep_alive`);
UPDATE `sys_permission` SET `icon` = 'ant-design:file-search-outlined' WHERE `id` = '1860000000000000192' AND `del_flag` = 0;
INSERT INTO `sys_permission`(`id`, `parent_id`, `name`, `menu_type`, `perms`, `perms_type`, `status`, `del_flag`, `create_by`, `create_time`) VALUES
('1860000000000000193', '1860000000000000192', '新增', 2, 'mes:mes_xsl_rubber_quick_test_record:add', '1', '1', 0, 'admin', NOW()),
('1860000000000000194', '1860000000000000192', '编辑', 2, 'mes:mes_xsl_rubber_quick_test_record:edit', '1', '1', 0, 'admin', NOW()),
('1860000000000000195', '1860000000000000192', '删除', 2, 'mes:mes_xsl_rubber_quick_test_record:delete', '1', '1', 0, 'admin', NOW()),
('1860000000000000196', '1860000000000000192', '批量删除', 2, 'mes:mes_xsl_rubber_quick_test_record:deleteBatch', '1', '1', 0, 'admin', NOW()),
('1860000000000000197', '1860000000000000192', '导出', 2, 'mes:mes_xsl_rubber_quick_test_record:exportXls', '1', '1', 0, 'admin', NOW()),
('1860000000000000198', '1860000000000000192', '导入', 2, 'mes:mes_xsl_rubber_quick_test_record:importExcel', '1', '1', 0, 'admin', NOW()),
('1860000000000000199', '1860000000000000192', '从胶料生成', 2, 'mes:mes_xsl_rubber_quick_test_record:batchFromMaterial', '1', '1', 0, 'admin', NOW())
ON DUPLICATE KEY UPDATE `perms` = VALUES(`perms`), `name` = VALUES(`name`);
INSERT INTO `sys_permission`(`id`, `parent_id`, `name`, `menu_type`, `perms`, `perms_type`, `status`, `del_flag`, `create_by`, `create_time`) VALUES
('1860000000000000200', '1860000000000000011', '胶料快检', 2, 'mes:mes_material:rubberQuickTestInspect', '1', '1', 0, 'admin', NOW())
ON DUPLICATE KEY UPDATE `perms` = VALUES(`perms`), `name` = VALUES(`name`);
INSERT INTO `sys_role_permission`(`id`, `role_id`, `permission_id`, `operate_date`, `operate_ip`)
SELECT REPLACE(UUID(), '-', ''), r.id, p.id, NOW(), '127.0.0.1'
FROM sys_role r
CROSS JOIN sys_permission p
WHERE r.tenant_id = @mes_tenant_id
AND r.role_code = 'admin'
AND p.id IN (
'1860000000000000192',
'1860000000000000193', '1860000000000000194', '1860000000000000195', '1860000000000000196',
'1860000000000000197', '1860000000000000198', '1860000000000000199',
'1860000000000000200'
)
AND NOT EXISTS (
SELECT 1 FROM sys_role_permission rp
WHERE rp.role_id = r.id AND rp.permission_id = p.id
);

View File

@@ -0,0 +1,130 @@
-- 胶料快检实验标准主子表字典 + 建表 + 菜单质量管理下+ 按钮 + 租户 admin 授权
-- 权限前缀mes:mes_xsl_rubber_quick_test_std:*
-- 菜单 ID 1860000000000000184实验方法占用 177-183
-- 可与 Flyway V3.9.2_103 重复执行ON DUPLICATE / IF NOT EXISTS
-- SET @mes_tenant_id多租户 admin 授权目标租户
SET NAMES utf8mb4;
INSERT INTO `sys_dict` (`id`, `dict_name`, `dict_code`, `description`, `del_flag`, `create_by`, `create_time`, `type`, `tenant_id`)
SELECT REPLACE(UUID(), '-', ''), 'MES胶料快检密炼机类型', 'xslmes_rubber_quick_test_mixer_type', '1普通密炼机2串密炼机', 0, 'admin', NOW(), 0, 0
WHERE NOT EXISTS (SELECT 1 FROM `sys_dict` WHERE `dict_code` = 'xslmes_rubber_quick_test_mixer_type' AND `del_flag` = 0);
INSERT INTO `sys_dict_item` (`id`, `dict_id`, `item_text`, `item_value`, `sort_order`, `status`, `create_by`, `create_time`)
SELECT REPLACE(UUID(), '-', ''), d.id, '普通密炼机', '1', 1, 1, 'admin', NOW() FROM `sys_dict` d
WHERE d.`dict_code` = 'xslmes_rubber_quick_test_mixer_type' AND NOT EXISTS (SELECT 1 FROM `sys_dict_item` i WHERE i.`dict_id` = d.id AND i.`item_value` = '1');
INSERT INTO `sys_dict_item` (`id`, `dict_id`, `item_text`, `item_value`, `sort_order`, `status`, `create_by`, `create_time`)
SELECT REPLACE(UUID(), '-', ''), d.id, '串密炼机', '2', 2, 1, 'admin', NOW() FROM `sys_dict` d
WHERE d.`dict_code` = 'xslmes_rubber_quick_test_mixer_type' AND NOT EXISTS (SELECT 1 FROM `sys_dict_item` i WHERE i.`dict_id` = d.id AND i.`item_value` = '2');
INSERT INTO `sys_dict` (`id`, `dict_name`, `dict_code`, `description`, `del_flag`, `create_by`, `create_time`, `type`, `tenant_id`)
SELECT REPLACE(UUID(), '-', ''), 'MES胶料快检标准启用状态', 'xslmes_rubber_quick_test_std_enable_status', '1使用中0已停用', 0, 'admin', NOW(), 0, 0
WHERE NOT EXISTS (SELECT 1 FROM `sys_dict` WHERE `dict_code` = 'xslmes_rubber_quick_test_std_enable_status' AND `del_flag` = 0);
INSERT INTO `sys_dict_item` (`id`, `dict_id`, `item_text`, `item_value`, `sort_order`, `status`, `create_by`, `create_time`)
SELECT REPLACE(UUID(), '-', ''), d.id, '使用中', '1', 1, 1, 'admin', NOW() FROM `sys_dict` d
WHERE d.`dict_code` = 'xslmes_rubber_quick_test_std_enable_status' AND NOT EXISTS (SELECT 1 FROM `sys_dict_item` i WHERE i.`dict_id` = d.id AND i.`item_value` = '1');
INSERT INTO `sys_dict_item` (`id`, `dict_id`, `item_text`, `item_value`, `sort_order`, `status`, `create_by`, `create_time`)
SELECT REPLACE(UUID(), '-', ''), d.id, '已停用', '0', 2, 1, 'admin', NOW() FROM `sys_dict` d
WHERE d.`dict_code` = 'xslmes_rubber_quick_test_std_enable_status' AND NOT EXISTS (SELECT 1 FROM `sys_dict_item` i WHERE i.`dict_id` = d.id AND i.`item_value` = '0');
INSERT INTO `sys_dict` (`id`, `dict_name`, `dict_code`, `description`, `del_flag`, `create_by`, `create_time`, `type`, `tenant_id`)
SELECT REPLACE(UUID(), '-', ''), 'MES胶料快检标准审核状态', 'xslmes_rubber_quick_test_std_audit_status', '0草稿1已批准', 0, 'admin', NOW(), 0, 0
WHERE NOT EXISTS (SELECT 1 FROM `sys_dict` WHERE `dict_code` = 'xslmes_rubber_quick_test_std_audit_status' AND `del_flag` = 0);
INSERT INTO `sys_dict_item` (`id`, `dict_id`, `item_text`, `item_value`, `sort_order`, `status`, `create_by`, `create_time`)
SELECT REPLACE(UUID(), '-', ''), d.id, '草稿', '0', 1, 1, 'admin', NOW() FROM `sys_dict` d
WHERE d.`dict_code` = 'xslmes_rubber_quick_test_std_audit_status' AND NOT EXISTS (SELECT 1 FROM `sys_dict_item` i WHERE i.`dict_id` = d.id AND i.`item_value` = '0');
INSERT INTO `sys_dict_item` (`id`, `dict_id`, `item_text`, `item_value`, `sort_order`, `status`, `create_by`, `create_time`)
SELECT REPLACE(UUID(), '-', ''), d.id, '已批准', '1', 2, 1, 'admin', NOW() FROM `sys_dict` d
WHERE d.`dict_code` = 'xslmes_rubber_quick_test_std_audit_status' AND NOT EXISTS (SELECT 1 FROM `sys_dict_item` i WHERE i.`dict_id` = d.id AND i.`item_value` = '1');
CREATE TABLE IF NOT EXISTS `mes_xsl_rubber_quick_test_std` (
`id` varchar(32) NOT NULL COMMENT '主键',
`std_name` varchar(128) NOT NULL COMMENT '实验标准名称同租户未删除唯一',
`test_method_id` varchar(32) NOT NULL COMMENT '实验方法 mes_xsl_rubber_quick_test_method.id',
`test_method_name` varchar(128) DEFAULT NULL COMMENT '实验方法名称冗余',
`mixer_type` varchar(2) DEFAULT NULL COMMENT '密炼机类型字典xslmes_rubber_quick_test_mixer_type1普通密炼机2串密炼机',
`rubber_material_id` varchar(32) DEFAULT NULL COMMENT '胶料 mes_material.id',
`rubber_material_name` varchar(128) DEFAULT NULL COMMENT '胶料名称冗余',
`ps_compile_id` varchar(32) DEFAULT NULL COMMENT '密炼PS编制 mes_xsl_mixer_ps_compile.id',
`issue_number` varchar(100) DEFAULT NULL COMMENT '发行编号密炼PS编码冗余',
`issue_date` date DEFAULT NULL COMMENT '发行日期',
`issue_dept_id` varchar(32) DEFAULT NULL COMMENT '发行部门ID',
`issue_dept_name` varchar(200) DEFAULT NULL COMMENT '发行部门名称冗余',
`enable_status` varchar(2) DEFAULT '1' COMMENT '启用状态字典xslmes_rubber_quick_test_std_enable_status1使用中0已停用',
`audit_status` varchar(2) DEFAULT '0' COMMENT '审核状态字典xslmes_rubber_quick_test_std_audit_status0草稿1已批准',
`tenant_id` int DEFAULT NULL COMMENT '租户',
`sys_org_code` varchar(64) DEFAULT NULL COMMENT '部门',
`create_by` varchar(32) DEFAULT NULL COMMENT '创建人',
`create_time` datetime DEFAULT NULL COMMENT '创建时间',
`update_by` varchar(32) DEFAULT NULL COMMENT '更新人',
`update_time` datetime DEFAULT NULL COMMENT '更新时间',
`del_flag` int DEFAULT '0' COMMENT '删除标记0正常1删除',
PRIMARY KEY (`id`),
KEY `idx_mrqts_method` (`test_method_id`),
KEY `idx_mrqts_material` (`rubber_material_id`),
KEY `idx_mrqts_tenant` (`tenant_id`),
UNIQUE KEY `uk_mrqts_tenant_name_del` (`tenant_id`, `std_name`, `del_flag`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='MES胶料快检实验标准';
CREATE TABLE IF NOT EXISTS `mes_xsl_rubber_quick_test_std_line` (
`id` varchar(32) NOT NULL COMMENT '主键',
`std_id` varchar(32) NOT NULL COMMENT '主表 mes_xsl_rubber_quick_test_std.id',
`data_point_id` varchar(32) NOT NULL COMMENT '数据点 mes_xsl_rubber_quick_test_data_point.id',
`point_name` varchar(128) DEFAULT NULL COMMENT '数据点名称冗余只读带出',
`lower_limit` decimal(18,6) DEFAULT NULL COMMENT '下限值',
`lower_warn` decimal(18,6) DEFAULT NULL COMMENT '下警告值',
`target_value` decimal(18,6) DEFAULT NULL COMMENT '目标值',
`upper_warn` decimal(18,6) DEFAULT NULL COMMENT '上警告值',
`upper_limit` decimal(18,6) DEFAULT NULL COMMENT '上限值',
`sort_no` int DEFAULT NULL COMMENT '排序号',
`create_by` varchar(32) DEFAULT NULL COMMENT '创建人',
`create_time` datetime DEFAULT NULL COMMENT '创建时间',
`update_by` varchar(32) DEFAULT NULL COMMENT '更新人',
`update_time` datetime DEFAULT NULL COMMENT '更新时间',
PRIMARY KEY (`id`),
KEY `idx_mrqtsl_std` (`std_id`),
UNIQUE KEY `uk_mrqtsl_std_point` (`std_id`, `data_point_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='MES胶料快检实验标准明细';
SET @mes_tenant_id = 1002;
SET @mes_quality_pid = IFNULL(
(SELECT `id` FROM `sys_permission` WHERE `del_flag` = 0 AND `menu_type` = 0 AND `name` = '质量管理' LIMIT 1),
'1860000000000000162'
);
INSERT INTO `sys_permission`(`id`, `parent_id`, `name`, `url`, `component`, `component_name`, `menu_type`, `perms`, `perms_type`, `sort_no`, `is_route`, `is_leaf`, `hidden`, `status`, `del_flag`, `keep_alive`, `internal_or_external`, `create_by`, `create_time`)
VALUES ('1860000000000000184', @mes_quality_pid, '胶料快检实验标准', '/xslmes/mesXslRubberQuickTestStd', 'xslmes/mesXslRubberQuickTestStd/MesXslRubberQuickTestStdList', 'MesXslRubberQuickTestStdList', 1, NULL, '1', 4, 1, 0, 0, '1', 0, 1, 0, 'admin', NOW())
ON DUPLICATE KEY UPDATE
`parent_id` = VALUES(`parent_id`), `name` = VALUES(`name`), `url` = VALUES(`url`), `component` = VALUES(`component`),
`component_name` = VALUES(`component_name`), `sort_no` = VALUES(`sort_no`), `is_leaf` = VALUES(`is_leaf`), `keep_alive` = VALUES(`keep_alive`);
UPDATE `sys_permission` SET `icon` = 'ant-design:file-protect-outlined' WHERE `id` = '1860000000000000184' AND `del_flag` = 0;
INSERT INTO `sys_permission`(`id`, `parent_id`, `name`, `menu_type`, `perms`, `perms_type`, `status`, `del_flag`, `create_by`, `create_time`) VALUES
('1860000000000000185', '1860000000000000184', '新增', 2, 'mes:mes_xsl_rubber_quick_test_std:add', '1', '1', 0, 'admin', NOW()),
('1860000000000000186', '1860000000000000184', '编辑', 2, 'mes:mes_xsl_rubber_quick_test_std:edit', '1', '1', 0, 'admin', NOW()),
('1860000000000000187', '1860000000000000184', '删除', 2, 'mes:mes_xsl_rubber_quick_test_std:delete', '1', '1', 0, 'admin', NOW()),
('1860000000000000188', '1860000000000000184', '批量删除', 2, 'mes:mes_xsl_rubber_quick_test_std:deleteBatch', '1', '1', 0, 'admin', NOW()),
('1860000000000000189', '1860000000000000184', '导出', 2, 'mes:mes_xsl_rubber_quick_test_std:exportXls', '1', '1', 0, 'admin', NOW()),
('1860000000000000190', '1860000000000000184', '导入', 2, 'mes:mes_xsl_rubber_quick_test_std:importExcel', '1', '1', 0, 'admin', NOW()),
('1860000000000000191', '1860000000000000184', '启用停用', 2, 'mes:mes_xsl_rubber_quick_test_std:updateStatus', '1', '1', 0, 'admin', NOW())
ON DUPLICATE KEY UPDATE `perms` = VALUES(`perms`), `name` = VALUES(`name`);
INSERT INTO `sys_role_permission`(`id`, `role_id`, `permission_id`, `operate_date`, `operate_ip`)
SELECT REPLACE(UUID(), '-', ''), r.id, p.id, NOW(), '127.0.0.1'
FROM sys_role r
CROSS JOIN sys_permission p
WHERE r.tenant_id = @mes_tenant_id
AND r.role_code = 'admin'
AND p.id IN (
'1860000000000000184',
'1860000000000000185', '1860000000000000186', '1860000000000000187', '1860000000000000188',
'1860000000000000189', '1860000000000000190', '1860000000000000191'
)
AND NOT EXISTS (
SELECT 1 FROM sys_role_permission rp
WHERE rp.role_id = r.id AND rp.permission_id = p.id
);

View File

@@ -0,0 +1,87 @@
-- MES 胶料快检实验类型建表 + 质量管理目录 + 子菜单 + 按钮 + 租户 admin 授权可整文件一次执行
-- 权限前缀与 Controller前端 v-auth 一致mes:mes_xsl_rubber_quick_test_type:*
-- 修改租户 SET @mes_tenant_id
SET NAMES utf8mb4;
CREATE TABLE IF NOT EXISTS `mes_xsl_rubber_quick_test_type` (
`id` varchar(32) NOT NULL COMMENT '主键',
`type_code` varchar(16) NOT NULL COMMENT '实验类型编号租户内从001递增自动生成',
`type_name` varchar(128) NOT NULL COMMENT '实验类型名称',
`tenant_id` int DEFAULT NULL COMMENT '租户',
`sys_org_code` varchar(64) DEFAULT NULL COMMENT '部门',
`create_by` varchar(32) DEFAULT NULL COMMENT '创建人',
`create_time` datetime DEFAULT NULL COMMENT '创建时间',
`update_by` varchar(32) DEFAULT NULL COMMENT '更新人',
`update_time` datetime DEFAULT NULL COMMENT '更新时间',
`del_flag` int DEFAULT '0' COMMENT '删除标记0正常1删除',
PRIMARY KEY (`id`),
KEY `idx_mrqtt_tenant_code` (`tenant_id`, `type_code`),
KEY `idx_mrqtt_tenant_name` (`tenant_id`, `type_name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='MES胶料快检实验类型';
SET @mes_tenant_id = 1002;
SET @mes_root_parent = (
SELECT `parent_id` FROM `sys_permission`
WHERE `del_flag` = 0 AND `menu_type` = 0 AND `name` = 'MES基础资料'
LIMIT 1
);
SET @mes_root_parent = IFNULL(@mes_root_parent, (
SELECT `parent_id` FROM `sys_permission`
WHERE `del_flag` = 0 AND `menu_type` = 0 AND `name` = 'MES资料'
LIMIT 1
));
SET @mes_root_parent = IFNULL(@mes_root_parent, '1860000000000000001');
SET @mes_quality_sort = IFNULL((
SELECT `sort_no` + 1 FROM `sys_permission`
WHERE `del_flag` = 0 AND `menu_type` = 0 AND `name` IN ('MES基础资料', 'MES资料', '设备管理')
ORDER BY `sort_no` DESC
LIMIT 1
), 52);
INSERT INTO `sys_permission`(`id`, `parent_id`, `name`, `url`, `component`, `component_name`, `menu_type`, `perms`, `perms_type`, `sort_no`, `is_route`, `is_leaf`, `hidden`, `status`, `del_flag`, `keep_alive`, `internal_or_external`, `create_by`, `create_time`)
VALUES ('1860000000000000162', @mes_root_parent, '质量管理', '/xslmes/quality', 'layouts/RouteView', 'MesQualityLayout', 0, NULL, '1', @mes_quality_sort, 1, 0, 0, '1', 0, 0, 0, 'admin', NOW())
ON DUPLICATE KEY UPDATE
`parent_id` = VALUES(`parent_id`), `name` = VALUES(`name`), `url` = VALUES(`url`), `component` = VALUES(`component`),
`menu_type` = VALUES(`menu_type`), `is_leaf` = 0, `hidden` = 0, `status` = '1', `del_flag` = 0;
UPDATE `sys_permission` SET `icon` = 'ant-design:safety-certificate-outlined' WHERE `id` = '1860000000000000162' AND `del_flag` = 0;
INSERT INTO `sys_permission`(`id`, `parent_id`, `name`, `url`, `component`, `component_name`, `menu_type`, `perms`, `perms_type`, `sort_no`, `is_route`, `is_leaf`, `hidden`, `status`, `del_flag`, `keep_alive`, `internal_or_external`, `create_by`, `create_time`)
VALUES ('1860000000000000163', '1860000000000000162', '胶料快检实验类型', '/xslmes/mesXslRubberQuickTestType', 'xslmes/mesXslRubberQuickTestType/MesXslRubberQuickTestTypeList', 'MesXslRubberQuickTestTypeList', 1, NULL, '1', 1, 1, 0, 0, '1', 0, 1, 0, 'admin', NOW())
ON DUPLICATE KEY UPDATE
`parent_id` = VALUES(`parent_id`), `name` = VALUES(`name`), `url` = VALUES(`url`), `component` = VALUES(`component`), `component_name` = VALUES(`component_name`),
`menu_type` = VALUES(`menu_type`), `perms` = VALUES(`perms`), `perms_type` = VALUES(`perms_type`), `sort_no` = VALUES(`sort_no`),
`is_route` = VALUES(`is_route`), `is_leaf` = 0, `hidden` = 0, `status` = '1', `del_flag` = 0,
`keep_alive` = VALUES(`keep_alive`), `internal_or_external` = VALUES(`internal_or_external`);
UPDATE `sys_permission` SET `icon` = 'ant-design:experiment-outlined' WHERE `id` = '1860000000000000163' AND `del_flag` = 0;
INSERT INTO `sys_permission`(`id`, `parent_id`, `name`, `menu_type`, `perms`, `perms_type`, `is_leaf`, `status`, `del_flag`, `create_by`, `create_time`) VALUES
('1860000000000000164', '1860000000000000163', '新增', 2, 'mes:mes_xsl_rubber_quick_test_type:add', '1', 1, '1', 0, 'admin', NOW()),
('1860000000000000165', '1860000000000000163', '编辑', 2, 'mes:mes_xsl_rubber_quick_test_type:edit', '1', 1, '1', 0, 'admin', NOW()),
('1860000000000000166', '1860000000000000163', '删除', 2, 'mes:mes_xsl_rubber_quick_test_type:delete', '1', 1, '1', 0, 'admin', NOW()),
('1860000000000000167', '1860000000000000163', '批量删除', 2, 'mes:mes_xsl_rubber_quick_test_type:deleteBatch', '1', 1, '1', 0, 'admin', NOW()),
('1860000000000000168', '1860000000000000163', '导出', 2, 'mes:mes_xsl_rubber_quick_test_type:exportXls', '1', 1, '1', 0, 'admin', NOW()),
('1860000000000000169', '1860000000000000163', '导入', 2, 'mes:mes_xsl_rubber_quick_test_type:importExcel', '1', 1, '1', 0, 'admin', NOW())
ON DUPLICATE KEY UPDATE
`parent_id` = VALUES(`parent_id`), `name` = VALUES(`name`), `menu_type` = VALUES(`menu_type`), `perms` = VALUES(`perms`), `perms_type` = VALUES(`perms_type`),
`is_leaf` = 1, `status` = '1', `del_flag` = 0;
INSERT INTO `sys_role_permission`(`id`, `role_id`, `permission_id`, `operate_date`, `operate_ip`)
SELECT REPLACE(UUID(), '-', ''), r.`id`, p.`id`, NOW(), '127.0.0.1'
FROM `sys_role` r
CROSS JOIN `sys_permission` p
WHERE r.`tenant_id` = @mes_tenant_id
AND r.`role_code` = 'admin'
AND p.`id` IN (
'1860000000000000162',
'1860000000000000163',
'1860000000000000164', '1860000000000000165', '1860000000000000166', '1860000000000000167',
'1860000000000000168', '1860000000000000169'
)
AND NOT EXISTS (
SELECT 1 FROM `sys_role_permission` rp
WHERE rp.`role_id` = r.`id` AND rp.`permission_id` = p.`id`
);

View File

@@ -0,0 +1,85 @@
-- MES 胶料小料锁定日志 + 锁定原因字段 reason_desc可整文件一次执行
-- 若已执行 V3.9.2_119 Flyway 可只跑本脚本补菜单/字段幂等
-- 权限前缀mes:mes_xsl_rubber_small_lock_log:*
SET NAMES utf8mb4;
SET @reason_desc_exists := (
SELECT COUNT(1)
FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA = DATABASE()
AND TABLE_NAME = 'mes_xsl_rubber_small_lock_reason'
AND COLUMN_NAME = 'reason_desc'
);
SET @ddl_reason_desc := IF(
@reason_desc_exists = 0,
'ALTER TABLE `mes_xsl_rubber_small_lock_reason` ADD COLUMN `reason_desc` varchar(500) NOT NULL DEFAULT '''' COMMENT ''原因手动输入必填'' AFTER `barcode_type`',
'SELECT 1'
);
PREPARE stmt_reason_desc FROM @ddl_reason_desc;
EXECUTE stmt_reason_desc;
DEALLOCATE PREPARE stmt_reason_desc;
UPDATE `mes_xsl_rubber_small_lock_reason` SET `reason_desc` = CONCAT('原因', `reason_code`) WHERE `reason_desc` = '' OR `reason_desc` IS NULL;
CREATE TABLE IF NOT EXISTS `mes_xsl_rubber_small_lock_log` (
`id` varchar(32) NOT NULL COMMENT '主键',
`lock_reason_id` varchar(32) NOT NULL COMMENT '锁定原因ID',
`barcode_type` varchar(16) NOT NULL COMMENT '条码类型',
`barcode` varchar(128) NOT NULL COMMENT '条码',
`lock_type` varchar(16) NOT NULL COMMENT '状态',
`reason_desc` varchar(500) NOT NULL COMMENT '原因',
`log_date` date NOT NULL COMMENT '日期',
`tenant_id` int DEFAULT NULL COMMENT '租户',
`sys_org_code` varchar(64) DEFAULT NULL COMMENT '部门',
`create_by` varchar(32) DEFAULT NULL COMMENT '创建人',
`create_time` datetime DEFAULT NULL COMMENT '创建时间',
`update_by` varchar(32) DEFAULT NULL COMMENT '修改人',
`update_time` datetime DEFAULT NULL COMMENT '修改时间',
`del_flag` int DEFAULT '0' COMMENT '删除标记0正常1删除',
PRIMARY KEY (`id`),
KEY `idx_mrsl_log_tenant_date` (`tenant_id`, `log_date`),
KEY `idx_mrsl_log_barcode` (`tenant_id`, `barcode_type`, `barcode`),
KEY `idx_mrsl_log_reason` (`lock_reason_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='MES胶料小料锁定日志';
SET @mes_tenant_id = 1002;
SET @mes_quality_pid = IFNULL(
(SELECT `id` FROM `sys_permission` WHERE `del_flag` = 0 AND `menu_type` = 0 AND `name` = '质量管理' LIMIT 1),
'1860000000000000162'
);
INSERT INTO `sys_permission`(`id`, `parent_id`, `name`, `url`, `component`, `component_name`, `menu_type`, `perms`, `perms_type`, `sort_no`, `is_route`, `is_leaf`, `hidden`, `status`, `del_flag`, `keep_alive`, `internal_or_external`, `create_by`, `create_time`)
VALUES ('1860000000000000215', @mes_quality_pid, '胶料小料锁定日志', '/xslmes/mesXslRubberSmallLockLog', 'xslmes/mesXslRubberSmallLockLog/MesXslRubberSmallLockLogList', 'MesXslRubberSmallLockLogList', 1, NULL, '1', 7, 1, 0, 0, '1', 0, 1, 0, 'admin', NOW())
ON DUPLICATE KEY UPDATE
`parent_id` = VALUES(`parent_id`), `name` = VALUES(`name`), `url` = VALUES(`url`), `component` = VALUES(`component`), `component_name` = VALUES(`component_name`),
`sort_no` = VALUES(`sort_no`), `is_leaf` = 0, `status` = '1', `del_flag` = 0, `keep_alive` = VALUES(`keep_alive`);
UPDATE `sys_permission` SET `icon` = 'ant-design:file-text-outlined' WHERE `id` = '1860000000000000215' AND `del_flag` = 0;
INSERT INTO `sys_permission`(`id`, `parent_id`, `name`, `menu_type`, `perms`, `perms_type`, `is_leaf`, `status`, `del_flag`, `create_by`, `create_time`) VALUES
('1860000000000000216', '1860000000000000215', '新增', 2, 'mes:mes_xsl_rubber_small_lock_log:add', '1', 1, '1', 0, 'admin', NOW()),
('1860000000000000217', '1860000000000000215', '编辑', 2, 'mes:mes_xsl_rubber_small_lock_log:edit', '1', 1, '1', 0, 'admin', NOW()),
('1860000000000000218', '1860000000000000215', '删除', 2, 'mes:mes_xsl_rubber_small_lock_log:delete', '1', 1, '1', 0, 'admin', NOW()),
('1860000000000000219', '1860000000000000215', '批量删除', 2, 'mes:mes_xsl_rubber_small_lock_log:deleteBatch', '1', 1, '1', 0, 'admin', NOW()),
('1860000000000000220', '1860000000000000215', '导出', 2, 'mes:mes_xsl_rubber_small_lock_log:exportXls', '1', 1, '1', 0, 'admin', NOW()),
('1860000000000000221', '1860000000000000215', '导入', 2, 'mes:mes_xsl_rubber_small_lock_log:importExcel', '1', 1, '1', 0, 'admin', NOW())
ON DUPLICATE KEY UPDATE
`parent_id` = VALUES(`parent_id`), `name` = VALUES(`name`), `menu_type` = VALUES(`menu_type`), `perms` = VALUES(`perms`), `perms_type` = VALUES(`perms_type`),
`is_leaf` = 1, `status` = '1', `del_flag` = 0;
INSERT INTO `sys_role_permission`(`id`, `role_id`, `permission_id`, `operate_date`, `operate_ip`)
SELECT REPLACE(UUID(), '-', ''), r.`id`, p.`id`, NOW(), '127.0.0.1'
FROM `sys_role` r
CROSS JOIN `sys_permission` p
WHERE r.`tenant_id` = @mes_tenant_id
AND r.`role_code` = 'admin'
AND p.`id` IN (
'1860000000000000215',
'1860000000000000216', '1860000000000000217', '1860000000000000218', '1860000000000000219',
'1860000000000000220', '1860000000000000221'
)
AND NOT EXISTS (
SELECT 1 FROM `sys_role_permission` rp
WHERE rp.`role_id` = r.`id` AND rp.`permission_id` = p.`id`
);

View File

@@ -0,0 +1,87 @@
-- MES 胶料小料锁定原因字典 + 建表 + 菜单质量管理下+ 按钮 + 租户 admin 授权可整文件一次执行
-- 权限前缀mes:mes_xsl_rubber_small_lock_reason:*
-- 菜单 ID 1860000000000000208按钮 209-214
-- 修改租户 SET @mes_tenant_id
SET NAMES utf8mb4;
INSERT INTO `sys_dict` (`id`, `dict_name`, `dict_code`, `description`, `del_flag`, `create_by`, `create_time`, `type`, `tenant_id`)
SELECT REPLACE(UUID(), '-', ''), 'MES胶料小料锁定类型', 'xslmes_rubber_small_lock_type', '锁定/解锁', 0, 'admin', NOW(), 0, 0
WHERE NOT EXISTS (SELECT 1 FROM `sys_dict` WHERE `dict_code` = 'xslmes_rubber_small_lock_type' AND `del_flag` = 0);
INSERT INTO `sys_dict_item` (`id`, `dict_id`, `item_text`, `item_value`, `sort_order`, `status`, `create_by`, `create_time`)
SELECT REPLACE(UUID(), '-', ''), d.id, '锁定', 'lock', 1, 1, 'admin', NOW() FROM `sys_dict` d
WHERE d.`dict_code` = 'xslmes_rubber_small_lock_type' AND NOT EXISTS (SELECT 1 FROM `sys_dict_item` i WHERE i.`dict_id` = d.id AND i.`item_value` = 'lock');
INSERT INTO `sys_dict_item` (`id`, `dict_id`, `item_text`, `item_value`, `sort_order`, `status`, `create_by`, `create_time`)
SELECT REPLACE(UUID(), '-', ''), d.id, '解锁', 'unlock', 2, 1, 'admin', NOW() FROM `sys_dict` d
WHERE d.`dict_code` = 'xslmes_rubber_small_lock_type' AND NOT EXISTS (SELECT 1 FROM `sys_dict_item` i WHERE i.`dict_id` = d.id AND i.`item_value` = 'unlock');
INSERT INTO `sys_dict` (`id`, `dict_name`, `dict_code`, `description`, `del_flag`, `create_by`, `create_time`, `type`, `tenant_id`)
SELECT REPLACE(UUID(), '-', ''), 'MES胶料小料锁定条码类型', 'xslmes_rubber_small_lock_barcode_type', '小料/胶料', 0, 'admin', NOW(), 0, 0
WHERE NOT EXISTS (SELECT 1 FROM `sys_dict` WHERE `dict_code` = 'xslmes_rubber_small_lock_barcode_type' AND `del_flag` = 0);
INSERT INTO `sys_dict_item` (`id`, `dict_id`, `item_text`, `item_value`, `sort_order`, `status`, `create_by`, `create_time`)
SELECT REPLACE(UUID(), '-', ''), d.id, '小料', 'small', 1, 1, 'admin', NOW() FROM `sys_dict` d
WHERE d.`dict_code` = 'xslmes_rubber_small_lock_barcode_type' AND NOT EXISTS (SELECT 1 FROM `sys_dict_item` i WHERE i.`dict_id` = d.id AND i.`item_value` = 'small');
INSERT INTO `sys_dict_item` (`id`, `dict_id`, `item_text`, `item_value`, `sort_order`, `status`, `create_by`, `create_time`)
SELECT REPLACE(UUID(), '-', ''), d.id, '胶料', 'rubber', 2, 1, 'admin', NOW() FROM `sys_dict` d
WHERE d.`dict_code` = 'xslmes_rubber_small_lock_barcode_type' AND NOT EXISTS (SELECT 1 FROM `sys_dict_item` i WHERE i.`dict_id` = d.id AND i.`item_value` = 'rubber');
CREATE TABLE IF NOT EXISTS `mes_xsl_rubber_small_lock_reason` (
`id` varchar(32) NOT NULL COMMENT '主键',
`reason_code` varchar(16) NOT NULL COMMENT '编号租户内从001递增自动生成只读',
`lock_type` varchar(16) NOT NULL COMMENT '类型字典xslmes_rubber_small_lock_typelock锁定unlock解锁',
`barcode_type` varchar(16) NOT NULL COMMENT '条码类型字典xslmes_rubber_small_lock_barcode_typesmall小料rubber胶料',
`reason_desc` varchar(500) NOT NULL COMMENT '原因手动输入必填',
`tenant_id` int DEFAULT NULL COMMENT '租户',
`sys_org_code` varchar(64) DEFAULT NULL COMMENT '部门',
`create_by` varchar(32) DEFAULT NULL COMMENT '创建人',
`create_time` datetime DEFAULT NULL COMMENT '创建日期',
`update_by` varchar(32) DEFAULT NULL COMMENT '更新人',
`update_time` datetime DEFAULT NULL COMMENT '更新时间',
`del_flag` int DEFAULT '0' COMMENT '删除标记0正常1删除',
PRIMARY KEY (`id`),
KEY `idx_mrslr_tenant_code` (`tenant_id`, `reason_code`),
KEY `idx_mrslr_tenant_lock` (`tenant_id`, `lock_type`, `barcode_type`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='MES胶料小料锁定原因';
SET @mes_tenant_id = 1002;
SET @mes_quality_pid = IFNULL(
(SELECT `id` FROM `sys_permission` WHERE `del_flag` = 0 AND `menu_type` = 0 AND `name` = '质量管理' LIMIT 1),
'1860000000000000162'
);
INSERT INTO `sys_permission`(`id`, `parent_id`, `name`, `url`, `component`, `component_name`, `menu_type`, `perms`, `perms_type`, `sort_no`, `is_route`, `is_leaf`, `hidden`, `status`, `del_flag`, `keep_alive`, `internal_or_external`, `create_by`, `create_time`)
VALUES ('1860000000000000208', @mes_quality_pid, '胶料小料锁定原因', '/xslmes/mesXslRubberSmallLockReason', 'xslmes/mesXslRubberSmallLockReason/MesXslRubberSmallLockReasonList', 'MesXslRubberSmallLockReasonList', 1, NULL, '1', 6, 1, 0, 0, '1', 0, 1, 0, 'admin', NOW())
ON DUPLICATE KEY UPDATE
`parent_id` = VALUES(`parent_id`), `name` = VALUES(`name`), `url` = VALUES(`url`), `component` = VALUES(`component`), `component_name` = VALUES(`component_name`),
`menu_type` = VALUES(`menu_type`), `sort_no` = VALUES(`sort_no`), `is_route` = VALUES(`is_route`), `is_leaf` = 0, `hidden` = 0, `status` = '1', `del_flag` = 0, `keep_alive` = VALUES(`keep_alive`);
UPDATE `sys_permission` SET `icon` = 'ant-design:lock-outlined' WHERE `id` = '1860000000000000208' AND `del_flag` = 0;
INSERT INTO `sys_permission`(`id`, `parent_id`, `name`, `menu_type`, `perms`, `perms_type`, `is_leaf`, `status`, `del_flag`, `create_by`, `create_time`) VALUES
('1860000000000000209', '1860000000000000208', '新增', 2, 'mes:mes_xsl_rubber_small_lock_reason:add', '1', 1, '1', 0, 'admin', NOW()),
('1860000000000000210', '1860000000000000208', '编辑', 2, 'mes:mes_xsl_rubber_small_lock_reason:edit', '1', 1, '1', 0, 'admin', NOW()),
('1860000000000000211', '1860000000000000208', '删除', 2, 'mes:mes_xsl_rubber_small_lock_reason:delete', '1', 1, '1', 0, 'admin', NOW()),
('1860000000000000212', '1860000000000000208', '批量删除', 2, 'mes:mes_xsl_rubber_small_lock_reason:deleteBatch', '1', 1, '1', 0, 'admin', NOW()),
('1860000000000000213', '1860000000000000208', '导出', 2, 'mes:mes_xsl_rubber_small_lock_reason:exportXls', '1', 1, '1', 0, 'admin', NOW()),
('1860000000000000214', '1860000000000000208', '导入', 2, 'mes:mes_xsl_rubber_small_lock_reason:importExcel', '1', 1, '1', 0, 'admin', NOW())
ON DUPLICATE KEY UPDATE
`parent_id` = VALUES(`parent_id`), `name` = VALUES(`name`), `menu_type` = VALUES(`menu_type`), `perms` = VALUES(`perms`), `perms_type` = VALUES(`perms_type`),
`is_leaf` = 1, `status` = '1', `del_flag` = 0;
INSERT INTO `sys_role_permission`(`id`, `role_id`, `permission_id`, `operate_date`, `operate_ip`)
SELECT REPLACE(UUID(), '-', ''), r.`id`, p.`id`, NOW(), '127.0.0.1'
FROM `sys_role` r
CROSS JOIN `sys_permission` p
WHERE r.`tenant_id` = @mes_tenant_id
AND r.`role_code` = 'admin'
AND p.`id` IN (
'1860000000000000208',
'1860000000000000209', '1860000000000000210', '1860000000000000211', '1860000000000000212',
'1860000000000000213', '1860000000000000214'
)
AND NOT EXISTS (
SELECT 1 FROM `sys_role_permission` rp
WHERE rp.`role_id` = r.`id` AND rp.`permission_id` = p.`id`
);

View File

@@ -26,19 +26,22 @@ CREATE TABLE IF NOT EXISTS `mes_xsl_spare_part` (
SET @mes_tenant_id = 1002;
SET @mes_base_pid = (
SELECT MIN(`id`) FROM `sys_permission`
WHERE `del_flag` = 0 AND `menu_type` = 0 AND `name` IN ('MES基础资料', 'MES资料')
SET @mes_equip_pid = (
SELECT `id` FROM `sys_permission`
WHERE `del_flag` = 0 AND `menu_type` = 0 AND `name` = '设备管理'
LIMIT 1
);
SET @mes_base_pid = IFNULL(@mes_base_pid, '1860000000000000001');
SET @mes_equip_pid = IFNULL(@mes_equip_pid, '1860000000000000133');
INSERT INTO `sys_permission`(`id`, `parent_id`, `name`, `url`, `component`, `component_name`, `menu_type`, `perms`, `perms_type`, `sort_no`, `is_route`, `is_leaf`, `hidden`, `status`, `del_flag`, `keep_alive`, `internal_or_external`, `create_by`, `create_time`)
VALUES ('1860000000000000105', @mes_base_pid, '备品件信息', '/xslmes/mesXslSparePart', 'xslmes/mesXslSparePart/MesXslSparePartList', NULL, 1, NULL, '1', 16, 1, 0, 0, '1', 0, 1, 0, 'admin', NOW())
VALUES ('1860000000000000105', @mes_equip_pid, '备品件信息', '/xslmes/mesXslSparePart', 'xslmes/mesXslSparePart/MesXslSparePartList', NULL, 1, NULL, '1', 7, 1, 0, 0, '1', 0, 1, 0, 'admin', NOW())
ON DUPLICATE KEY UPDATE
`parent_id` = VALUES(`parent_id`), `name` = VALUES(`name`), `url` = VALUES(`url`), `component` = VALUES(`component`), `component_name` = VALUES(`component_name`),
`menu_type` = VALUES(`menu_type`), `perms` = VALUES(`perms`), `perms_type` = VALUES(`perms_type`), `sort_no` = VALUES(`sort_no`),
`is_route` = VALUES(`is_route`), `is_leaf` = VALUES(`is_leaf`), `hidden` = VALUES(`hidden`), `status` = VALUES(`status`), `del_flag` = VALUES(`del_flag`),
`keep_alive` = VALUES(`keep_alive`), `internal_or_external` = VALUES(`internal_or_external`);
`keep_alive` = VALUES(`keep_alive`), `internal_or_external` = VALUES(`internal_or_external`), `icon` = 'ant-design:shopping-outlined';
UPDATE `sys_permission` SET `icon` = 'ant-design:shopping-outlined' WHERE `id` = '1860000000000000105' AND `del_flag` = 0;
INSERT INTO `sys_permission`(`id`, `parent_id`, `name`, `menu_type`, `perms`, `perms_type`, `status`, `del_flag`, `create_by`, `create_time`) VALUES
('1860000000000000106', '1860000000000000105', '新增', 2, 'mes:mes_xsl_spare_part:add', '1', '1', 0, 'admin', NOW()),

View File

@@ -20,19 +20,22 @@ CREATE TABLE IF NOT EXISTS `mes_xsl_spare_parts_category` (
SET @mes_tenant_id = 1002;
SET @mes_base_pid = (
SELECT MIN(`id`) FROM `sys_permission`
WHERE `del_flag` = 0 AND `menu_type` = 0 AND `name` IN ('MES基础资料', 'MES资料')
SET @mes_equip_pid = (
SELECT `id` FROM `sys_permission`
WHERE `del_flag` = 0 AND `menu_type` = 0 AND `name` = '设备管理'
LIMIT 1
);
SET @mes_base_pid = IFNULL(@mes_base_pid, '1860000000000000001');
SET @mes_equip_pid = IFNULL(@mes_equip_pid, '1860000000000000133');
INSERT INTO `sys_permission`(`id`, `parent_id`, `name`, `url`, `component`, `component_name`, `menu_type`, `perms`, `perms_type`, `sort_no`, `is_route`, `is_leaf`, `hidden`, `status`, `del_flag`, `keep_alive`, `internal_or_external`, `create_by`, `create_time`)
VALUES ('1860000000000000098', @mes_base_pid, '备品件类别', '/xslmes/mesXslSparePartsCategory', 'xslmes/mesXslSparePartsCategory/MesXslSparePartsCategoryList', NULL, 1, NULL, '1', 15, 1, 0, 0, '1', 0, 1, 0, 'admin', NOW())
VALUES ('1860000000000000098', @mes_equip_pid, '备品件类别', '/xslmes/mesXslSparePartsCategory', 'xslmes/mesXslSparePartsCategory/MesXslSparePartsCategoryList', NULL, 1, NULL, '1', 6, 1, 0, 0, '1', 0, 1, 0, 'admin', NOW())
ON DUPLICATE KEY UPDATE
`parent_id` = VALUES(`parent_id`), `name` = VALUES(`name`), `url` = VALUES(`url`), `component` = VALUES(`component`), `component_name` = VALUES(`component_name`),
`menu_type` = VALUES(`menu_type`), `perms` = VALUES(`perms`), `perms_type` = VALUES(`perms_type`), `sort_no` = VALUES(`sort_no`),
`is_route` = VALUES(`is_route`), `is_leaf` = VALUES(`is_leaf`), `hidden` = VALUES(`hidden`), `status` = VALUES(`status`), `del_flag` = VALUES(`del_flag`),
`keep_alive` = VALUES(`keep_alive`), `internal_or_external` = VALUES(`internal_or_external`);
`keep_alive` = VALUES(`keep_alive`), `internal_or_external` = VALUES(`internal_or_external`), `icon` = 'ant-design:tags-outlined';
UPDATE `sys_permission` SET `icon` = 'ant-design:tags-outlined' WHERE `id` = '1860000000000000098' AND `del_flag` = 0;
INSERT INTO `sys_permission`(`id`, `parent_id`, `name`, `menu_type`, `perms`, `perms_type`, `status`, `del_flag`, `create_by`, `create_time`) VALUES
('1860000000000000099', '1860000000000000098', '新增', 2, 'mes:mes_xsl_spare_parts_category:add', '1', '1', 0, 'admin', NOW()),

View File

@@ -4,7 +4,7 @@
<parent>
<groupId>org.jeecgframework.boot3</groupId>
<artifactId>jeecg-boot-parent</artifactId>
<version>3.9.1</version>
<version>3.9.2</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jeecg-boot-base-core</artifactId>
@@ -377,7 +377,7 @@
<!-- chatgpt -->
<dependency>
<groupId>org.jeecgframework.boot3</groupId>
<artifactId>jeecg-boot-starter-chatgpt</artifactId>
<artifactId>jeecg-boot-starter-ai</artifactId>
</dependency>
<!-- 腾讯云 -->
<dependency>

View File

@@ -2,10 +2,8 @@ package org.jeecg.common.aspect;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.parser.Feature;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
@@ -23,7 +21,11 @@ import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
@@ -44,9 +46,6 @@ public class DictAspect {
@Autowired
public RedisTemplate redisTemplate;
@Autowired
private ObjectMapper objectMapper;
private static final String JAVA_UTIL_DATE = "java.util.Date";
/**
@@ -113,19 +112,25 @@ public class DictAspect {
log.debug(" __ 进入字典翻译切面 DictAspect —— " );
for (Object record : records) {
String json="{}";
try {
//解决@JsonFormat注解解析不了的问题详见SysAnnouncement类的@JsonFormat
json = objectMapper.writeValueAsString(record);
} catch (JsonProcessingException e) {
log.error("json解析失败"+e.getMessage(),e);
}
// 代码逻辑说明: 【issues/3303】restcontroller返回json数据后key顺序错乱 -----
JSONObject item = JSONObject.parseObject(json, Feature.OrderedField);
//for (Field field : record.getClass().getDeclaredFields()) {
// 遍历所有字段把字典Code取出来放到 map 里
//update-begin---author:scott ---date:2026-04-15 for【issues/9543】改用反射直接读取字段构建 JSONObject避免 ObjectMapper 对循环引用实体进行全量序列化导致 OOM合并字典字段收集逻辑为同一次循环避免对 getAllFields 遍历两遍;保留 【issues/#3629】@JsonFormat 的 Date 格式化兼容;保留 【issues/3303】字段顺序LinkedHashMap-----------
JSONObject item = new JSONObject(true);
for (Field field : oConvertUtils.getAllFields(record)) {
if (Modifier.isStatic(field.getModifiers())) {
continue;
}
//update-begin---author:scott ---date:2026-04-16 for【issues/9543】优先通过 getter 方法读取字段值(兼容实体重写 getter 的场景getter 不存在时 fallback 到直接读字段-----------
Object fieldValue = getFieldValue(record, field);
//update-end---author:scott ---date:2026-04-16 for【issues/9543】优先通过 getter 方法读取字段值(兼容实体重写 getter 的场景getter 不存在时 fallback 到直接读字段-----------
// 解决@JsonFormat注解解析不了的问题详见SysAnnouncement类的@JsonFormat
if (fieldValue instanceof Date) {
JsonFormat jsonFormat = field.getAnnotation(JsonFormat.class);
if (jsonFormat != null && oConvertUtils.isNotEmpty(jsonFormat.pattern())) {
fieldValue = new SimpleDateFormat(jsonFormat.pattern()).format((Date) fieldValue);
}
}
item.put(field.getName(), fieldValue);
// 遍历所有字段把字典Code取出来放到 map 里
String value = item.getString(field.getName());
if (oConvertUtils.isEmpty(value)) {
continue;
@@ -154,6 +159,7 @@ public class DictAspect {
// item.put(field.getName(), aDate.format(new Date((Long) item.get(field.getName()))));
//}
}
//update-end---author:scott ---date:2026-04-15 for【issues/9543】改用反射直接读取字段构建 JSONObject避免 ObjectMapper 对循环引用实体进行全量序列化导致 OOM合并字典字段收集逻辑为同一次循环避免对 getAllFields 遍历两遍;保留 【issues/#3629】@JsonFormat 的 Date 格式化兼容;保留 【issues/3303】字段顺序LinkedHashMap-----------
items.add(item);
}
@@ -417,6 +423,30 @@ public class DictAspect {
return textValue.toString();
}
//update-begin---author:scott ---date:2026-04-16 for【issues/9543】优先通过 getter 方法读取字段值(兼容实体重写 getter 的场景getter 不存在时 fallback 到直接读字段-----------
/**
* 优先通过 PropertyDescriptor 获取 getter 方法读取字段值,兼容实体重写 getter 的场景;
* getter 不存在或调用异常时 fallback 到直接反射读字段。
*/
private Object getFieldValue(Object record, Field field) {
try {
PropertyDescriptor pd = new PropertyDescriptor(field.getName(), record.getClass());
Method readMethod = pd.getReadMethod();
if (readMethod != null) {
return readMethod.invoke(record);
}
} catch (Exception ignored) {
}
try {
field.setAccessible(true);
return field.get(record);
} catch (IllegalAccessException e) {
log.error("反射读取字段失败: " + field.getName(), e);
return null;
}
}
//update-end---author:scott ---date:2026-04-16 for【issues/9543】优先通过 getter 方法读取字段值(兼容实体重写 getter 的场景getter 不存在时 fallback 到直接读字段-----------
/**
* 检测返回结果集中是否包含Dict注解
* @param records

View File

@@ -27,7 +27,8 @@ public enum FileTypeEnum {
mp4(".mp4","video","视频"),
zip(".zip","zip","压缩包"),
pdf(".pdf","pdf","pdf"),
mp3(".mp3","mp3","语音");
mp3(".mp3","mp3","语音"),
wav(".wav","wav","语音");
private String type;
private String value;

View File

@@ -23,7 +23,11 @@ public enum UniPushTypeEnum {
/**
* 系统消息
*/
SYS_MSG("system", "系统消息", "收到一条系统通告");
SYS_MSG("system", "系统消息", "收到一条系统通告"),
/**
* 协同工作
*/
COLLABORATION_MSG("collaboration", "系统消息", "收到一条协同工作消息");
/**
* 业务类型(chat:聊天 bpm_task:流程 bpm_cc:流程抄送)

View File

@@ -34,6 +34,7 @@ import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.multipart.MaxUploadSizeExceededException;
import org.springframework.web.multipart.MultipartException;
import org.springframework.web.servlet.NoHandlerFoundException;
import org.springframework.web.servlet.resource.NoResourceFoundException;
import java.util.Map;
import java.util.stream.Collectors;
@@ -105,6 +106,23 @@ public class JeecgBootExceptionHandler {
return Result.error(404, "路径不存在,请检查路径是否正确");
}
/**
* 处理静态资源不存在异常Spring Boot 3.2+
* WebSocket路径被当作静态资源请求时会触发此异常降级为debug日志避免刷屏
*/
@ExceptionHandler(NoResourceFoundException.class)
public Result<?> handleNoResourceFoundException(NoResourceFoundException e, HttpServletRequest request) {
String uri = request.getRequestURI();
// WebSocket路径的非upgrade请求降级为debug日志
if (uri.contains("Socket/") || uri.contains("websocket/") || uri.contains("Websocket/")) {
log.debug("WebSocket路径被当作静态资源请求: {}", uri);
} else {
log.error(e.getMessage(), e);
addSysLog(e);
}
return Result.error(404, "路径不存在,请检查路径是否正确");
}
@ExceptionHandler(DuplicateKeyException.class)
public Result<?> handleDuplicateKeyException(DuplicateKeyException e){
log.error(e.getMessage(), e);

View File

@@ -135,7 +135,11 @@ public class QueryGenerator {
//权限规则自定义SQL表达式
for (String c : ruleMap.keySet()) {
if(oConvertUtils.isNotEmpty(c) && c.startsWith(SQL_RULES_COLUMN)){
queryWrapper.and(i ->i.apply(getSqlRuleValue(ruleMap.get(c).getRuleValue())));
// update-begin---author:sunjianlei ---date:20260331 for【#9434】修复 QueryGenerator 自定义权限规则逻辑存在 SQL 注入漏洞
String sqlRule = getSqlRuleValue(ruleMap.get(c).getRuleValue());
SqlInjectionUtil.filterContent(sqlRule, null);
queryWrapper.and(i ->i.apply(sqlRule));
// update-end-----author:sunjianlei ---date:20260331 for【#9434】修复 QueryGenerator 自定义权限规则逻辑存在 SQL 注入漏洞
}
}
@@ -165,26 +169,23 @@ public class QueryGenerator {
//区间查询
doIntervalQuery(queryWrapper, parameterMap, type, name, column);
//判断单值 参数带不同标识字符串 走不同的查询
//TODO 这种前后带逗号的支持分割后模糊查询(多选字段查询生效) 示例:,1,3,
// update-begin--author:claude--date:20260330--for:【issues/9265】多选字段查询精确匹配避免值1匹配到值10
//多选字段查询生效 示例:,1,3, 使用精确边界匹配(兼容所有数据库)
if (null != value && value.toString().startsWith(COMMA) && value.toString().endsWith(COMMA)) {
String multiLikeval = value.toString().replace(",,", COMMA);
String[] vals = multiLikeval.substring(1, multiLikeval.length()).split(COMMA);
final String field = oConvertUtils.camelToUnderline(column);
if(vals.length>1) {
queryWrapper.and(j -> {
log.info("---查询过滤器Query规则---field:{}, rule:{}, value:{}", field, "like", vals[0]);
j = j.like(field,vals[0]);
for (int k=1;k<vals.length;k++) {
j = j.or().like(field,vals[k]);
log.info("---查询过滤器Query规则 .or()---field:{}, rule:{}, value:{}", field, "like", vals[k]);
}
//return j;
});
}else {
log.info("---查询过滤器Query规则---field:{}, rule:{}, value:{}", field, "like", vals[0]);
queryWrapper.and(j -> j.like(field,vals[0]));
}
}else {
queryWrapper.and(j -> {
log.info("---查询过滤器Query规则(多选精确匹配)---field:{}, rule:{}, value:{}", field, "multi_select", vals[0]);
j = j.eq(field, vals[0]).or().likeRight(field, vals[0] + ",").or().like(field, "," + vals[0] + ",").or().likeLeft(field, "," + vals[0]);
for (int k = 1; k < vals.length; k++) {
log.info("---查询过滤器Query规则(多选精确匹配) .or()---field:{}, rule:{}, value:{}", field, "multi_select", vals[k]);
j = j.or().eq(field, vals[k]).or().likeRight(field, vals[k] + ",").or().like(field, "," + vals[k] + ",").or().likeLeft(field, "," + vals[k]);
}
});
}
// update-end--author:claude--date:20260330--for:【issues/9265】多选字段查询精确匹配避免值1匹配到值10
else {
// 代码逻辑说明: [TV360X-378]增加自定义字段查询规则功能------------
QueryRuleEnum rule;
if(null != customRuleMap && customRuleMap.containsKey(name)) {
@@ -576,10 +577,16 @@ public class QueryGenerator {
value = val.substring(1, val.length() - 1);
//mysql 模糊查询之特殊字符下划线 _、\
value = specialStrConvert(value.toString());
} else if (rule == QueryRuleEnum.LEFT_LIKE || rule == QueryRuleEnum.NE) {
} else if (rule == QueryRuleEnum.LEFT_LIKE) {
value = val.substring(1);
//mysql 模糊查询之特殊字符下划线 _、\
value = specialStrConvert(value.toString());
//update-begin---author:scott ---date:20260416 for【PR#9322】修复NE规则与LEFT_LIKE共用substring(1)导致ID首位字符丢失-----------
} else if (rule == QueryRuleEnum.NE) {
if (val.startsWith(QueryRuleEnum.NE.getValue())) {
value = val.substring(1);
}
//update-end---author:scott ---date:20260416 for【PR#9322】修复NE规则与LEFT_LIKE共用substring(1)导致ID首位字符丢失-----------
} else if (rule == QueryRuleEnum.RIGHT_LIKE) {
value = val.substring(0, val.length() - 1);
//mysql 模糊查询之特殊字符下划线 _、\
@@ -754,6 +761,7 @@ public class QueryGenerator {
queryWrapper.notLikeRight(name, value);
break;
// 代码逻辑说明: [TV360X-378]下拉多框根据条件查询不出来:增加自定义字段查询规则功能------------
// update-begin--author:claude--date:20260330--for:【issues/9265】LIKE_WITH_OR多选查询精确匹配避免值1匹配到值10
case LIKE_WITH_OR:
final String nameFinal = name;
Object[] vals;
@@ -769,14 +777,15 @@ public class QueryGenerator {
vals = new Object[]{value};
}
queryWrapper.and(j -> {
log.info("---查询过滤器Query规则---field:{}, rule:{}, value:{}", nameFinal, "like", vals[0]);
j = j.like(nameFinal, vals[0]);
log.info("---查询过滤器Query规则(多选精确匹配)---field:{}, rule:{}, value:{}", nameFinal, "multi_select", vals[0]);
j = j.eq(nameFinal, vals[0]).or().likeRight(nameFinal, vals[0] + ",").or().like(nameFinal, "," + vals[0] + ",").or().likeLeft(nameFinal, "," + vals[0]);
for (int k = 1; k < vals.length; k++) {
j = j.or().like(nameFinal, vals[k]);
log.info("---查询过滤器Query规则 .or()---field:{}, rule:{}, value:{}", nameFinal, "like", vals[k]);
log.info("---查询过滤器Query规则(多选精确匹配) .or()---field:{}, rule:{}, value:{}", nameFinal, "multi_select", vals[k]);
j = j.or().eq(nameFinal, vals[k]).or().likeRight(nameFinal, vals[k] + ",").or().like(nameFinal, "," + vals[k] + ",").or().likeLeft(nameFinal, "," + vals[k]);
}
});
break;
// update-end--author:claude--date:20260330--for:【issues/9265】LIKE_WITH_OR多选查询精确匹配避免值1匹配到值10
default:
log.info("--查询规则未匹配到---");
break;
@@ -984,7 +993,11 @@ public class QueryGenerator {
PropertyDescriptor[] origDescriptors = PropertyUtils.getPropertyDescriptors(clazz);
for (String c : ruleMap.keySet()) {
if(oConvertUtils.isNotEmpty(c) && c.startsWith(SQL_RULES_COLUMN)){
queryWrapper.and(i ->i.apply(getSqlRuleValue(ruleMap.get(c).getRuleValue())));
// update-begin---author:sunjianlei ---date:20260331 for【#9434】修复 QueryGenerator 自定义权限规则逻辑存在 SQL 注入漏洞
String sqlRule = getSqlRuleValue(ruleMap.get(c).getRuleValue());
SqlInjectionUtil.filterContent(sqlRule, null);
queryWrapper.and(i ->i.apply(sqlRule));
// update-end-----author:sunjianlei ---date:20260331 for【#9434】修复 QueryGenerator 自定义权限规则逻辑存在 SQL 注入漏洞
}
}
String name, column;

View File

@@ -144,7 +144,9 @@ public class ResourceUtil {
*/
private static void processEnumClass(String classname) {
try {
Class<?> clazz = Class.forName(classname);
//update-begin---author:scott ---date:20260416 for【PR#9538】Class.forName使用上下文类加载器增强部署兼容性-----------
Class<?> clazz = Class.forName(classname, true, Thread.currentThread().getContextClassLoader());
//update-end---author:scott ---date:20260416 for【PR#9538】Class.forName使用上下文类加载器增强部署兼容性-----------
EnumDict enumDict = clazz.getAnnotation(EnumDict.class);
if (enumDict != null) {

View File

@@ -15,6 +15,8 @@ public class SysDepartModel {
private String departNameEn;
/**缩写*/
private String departNameAbbr;
/**机构/部门路径名称*/
private String departPathName;
/**排序*/
private Integer departOrder;
/**描述*/
@@ -74,6 +76,14 @@ public class SysDepartModel {
this.departNameAbbr = departNameAbbr;
}
public String getDepartPathName() {
return departPathName;
}
public void setDepartPathName(String departPathName) {
this.departPathName = departPathName;
}
public Integer getDepartOrder() {
return departOrder;
}

View File

@@ -26,6 +26,8 @@ import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.SQLException;
@@ -61,7 +63,18 @@ public class CommonUtils {
//update-end---author:wangshuai---date:2026-01-08---for:【QQYUN-14535】ai生成图片的后缀不一致的导致不展示---
try {
if(CommonConstant.UPLOAD_TYPE_LOCAL.equals(uploadType)){
File file = new File(basePath + File.separator + bizPath + File.separator );
//update-begin---author:wangshuai---date:2026-03-30---for:【issues/9435】uploadOnlineImage路径遍历漏洞修复---
// 1. 使用已有的路径遍历检查
SsrfFileTypeFilter.checkPathTraversal(bizPath);
// 2. 标准化路径并校验是否在basePath范围内
Path root = Paths.get(basePath).toAbsolutePath().normalize();
Path targetDir = root.resolve(bizPath).toAbsolutePath().normalize();
if (!targetDir.startsWith(root)) {
log.error("检测到路径遍历攻击!非法 bizPath: {}", bizPath);
throw new SecurityException("Illegal access to path outside of base directory.");
}
File file = targetDir.toFile();
//update-end---author:wangshuai---date:2026-03-30---for:【issues/9435】uploadOnlineImage路径遍历漏洞修复---
if (!file.exists()) {
file.mkdirs();// 创建文件根目录
}
@@ -159,7 +172,14 @@ public class CommonUtils {
SsrfFileTypeFilter.checkUploadFileType(mf, bizPath);
String fileName = null;
File file = new File(uploadpath + File.separator + bizPath + File.separator );
//update-begin---author:liusq ---date:2026-03-30 for【issues/9428】修复uploadLocal bizPath路径遍历漏洞(CWE-22)-----------
// 路径遍历校验规范化后确保目标目录在uploadpath内
File uploadDir = new File(uploadpath).getCanonicalFile();
File file = new File(uploadpath + File.separator + bizPath + File.separator).getCanonicalFile();
if (!file.toPath().startsWith(uploadDir.toPath())) {
throw new JeecgBootException("非法业务路径,禁止访问上传目录之外的路径: " + bizPath);
}
//update-end---author:liusq ---date:2026-03-30 for【issues/9428】修复uploadLocal bizPath路径遍历漏洞(CWE-22)-----------
if (!file.exists()) {
// 创建文件根目录
file.mkdirs();
@@ -198,8 +218,14 @@ public class CommonUtils {
}
/**
* 统一全局上传 带桶
* @Return: java.lang.String
* 统一全局上传(支持自定义桶)
* 根据 uploadType 自动选择 MinIO 或 阿里云OSS 进行文件上传
*
* @param file 待上传的文件
* @param bizPath 业务路径,作为文件存储的目录前缀(如 "upload/images"
* @param uploadType 上传方式:{@link CommonConstant#UPLOAD_TYPE_MINIO} 使用MinIO其他使用阿里云OSS
* @param customBucket 自定义桶名称,为空则使用各存储服务的默认桶
* @return 文件访问URL上传失败返回空字符串
*/
public static String upload(MultipartFile file, String bizPath, String uploadType, String customBucket) {
String url = "";
@@ -368,7 +394,7 @@ public class CommonUtils {
}else{
baseDomainPath = scheme + "://" + serverName + ":" + serverPort + contextPath ;
}
log.info("-----Common getBaseUrl----- : " + baseDomainPath);
log.debug("-----获取当前服务 BaseUrl----- : " + baseDomainPath);
return baseDomainPath;
}

View File

@@ -131,6 +131,22 @@ public class FileDownloadUtils {
* @date 2024/1/19 10:09
*/
public static String download2DiskFromNet(String fileUrl, String storePath) {
//update-begin---author:liusq ---date:2026-03-30 for【issues/9437】修复download2DiskFromNet storePath路径遍历漏洞(CWE-22)-----------
// 路径遍历校验:拦截 ../ 等遍历字符,并确保规范化路径与原始路径一致
SsrfFileTypeFilter.checkPathTraversal(storePath);
try {
String canonicalPath = new File(storePath).getCanonicalPath();
String absolutePath = new File(storePath).getAbsolutePath();
if (!canonicalPath.equals(absolutePath)) {
throw new JeecgBootException("非法存储路径,路径包含遍历字符: " + storePath);
}
} catch (IOException e) {
throw new JeecgBootException("存储路径校验失败: " + storePath, e);
}
//update-end---author:liusq ---date:2026-03-30 for【issues/9437】修复download2DiskFromNet storePath路径遍历漏洞(CWE-22)-----------
//update-begin---author:zhangdaihao ---date:2026-04-15 for【issues/9553】下载网络资源前增加SSRF校验-----------
SsrfFileTypeFilter.checkSsrfHttpUrl(fileUrl);
//update-end---author:zhangdaihao ---date:2026-04-15 for【issues/9553】下载网络资源前增加SSRF校验-----------
try {
URL url = new URL(fileUrl);
URLConnection conn = url.openConnection();
@@ -260,6 +276,9 @@ public class FileDownloadUtils {
try {
// 处理HTTP URL通过网络下载
if (oConvertUtils.isNotEmpty(fileUrl) && fileUrl.startsWith(CommonConstant.STR_HTTP)) {
//update-begin---author:zhangdaihao ---date:2026-04-15 for【issues/9553】修复二次SSRF漏洞对HTTP下载URL进行安全校验-----------
SsrfFileTypeFilter.checkSsrfHttpUrl(fileUrl);
//update-end---author:zhangdaihao ---date:2026-04-15 for【issues/9553】修复二次SSRF漏洞对HTTP下载URL进行安全校验-----------
URL url = new URL(fileUrl);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setConnectTimeout(5000); // 连接超时5秒

View File

@@ -73,8 +73,20 @@ public class FillRuleUtil {
if (formData == null) {
formData = new JSONObject();
}
// 通过反射执行配置的类里的方法
IFillRuleHandler ruleHandler = (IFillRuleHandler) Class.forName(ruleClass).newInstance();
// 包路径白名单校验,防止任意类加载漏洞
if (!ruleClass.startsWith("org.jeecg.")) {
log.error("检测到非法填值规则类加载尝试: {}", ruleClass);
throw new SecurityException("不允许加载非 org.jeecg 包路径下的填值规则类: " + ruleClass);
}
// 通过反射执行配置的类里的方法(先加载类并校验接口,再实例化)
//update-begin---author:scott ---date:20260416 for【PR#9538】Class.forName使用上下文类加载器增强部署兼容性-----------
Class<?> clazz = Class.forName(ruleClass, true, Thread.currentThread().getContextClassLoader());
//update-end---author:scott ---date:20260416 for【PR#9538】Class.forName使用上下文类加载器增强部署兼容性-----------
if (!IFillRuleHandler.class.isAssignableFrom(clazz)) {
throw new IllegalArgumentException("" + ruleClass + " 未实现 IFillRuleHandler 接口");
}
IFillRuleHandler ruleHandler = (IFillRuleHandler) clazz.getDeclaredConstructor().newInstance();
return ruleHandler.execute(params, formData);
} catch (Exception e) {
e.printStackTrace();

View File

@@ -152,11 +152,13 @@ public class MinioUtil {
}
/**
* 获取文件外链
* @param bucketName
* @param objectName
* @param expires
* @return
* 获取私有桶文件的预签名访问URL带过期时间
* 通过MinIO预签名机制生成临时GET链接无需公开桶即可让外部访问文件
*
* @param bucketName 桶名称
* @param objectName 文件对象路径(如 "eoafile/2026/04/test.pdf"
* @param expires 链接有效期,单位:秒(注意不是天)
* @return 预签名URL失败返回null
*/
public static String getObjectUrl(String bucketName, String objectName, Integer expires) {
initMinio(minioUrl, minioName,minioPass);
@@ -195,10 +197,13 @@ public class MinioUtil {
}
/**
* 上传文件到minio
* @param stream
* @param relativePath
* @return
* 通过输入流上传文件到MinIO默认桶
* 若桶不存在会自动创建,上传成功后关闭输入流
*
* @param stream 文件输入流
* @param relativePath 文件在桶中的相对路径(如 "upload/2026/04/test.pdf"
* @return 文件完整访问URL格式minioUrl + bucketName + "/" + relativePath
* @throws Exception 桶操作或上传过程中的异常
*/
public static String upload(InputStream stream,String relativePath) throws Exception {
initMinio(minioUrl, minioName,minioPass);

View File

@@ -9,7 +9,9 @@ public class MyClassLoader extends ClassLoader {
public static Class getClassByScn(String className) {
Class myclass = null;
try {
myclass = Class.forName(className);
//update-begin---author:scott ---date:20260416 for【PR#9538】Class.forName使用上下文类加载器增强部署兼容性-----------
myclass = Class.forName(className, true, Thread.currentThread().getContextClassLoader());
//update-end---author:scott ---date:20260416 for【PR#9538】Class.forName使用上下文类加载器增强部署兼容性-----------
} catch (ClassNotFoundException e) {
e.printStackTrace();
throw new RuntimeException(className+" not found!");

View File

@@ -8,6 +8,8 @@ import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.web.client.RestTemplate;
import java.net.URI;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.Iterator;
import java.util.Map;
@@ -235,7 +237,7 @@ public class RestUtil {
}
// 发送请求
HttpEntity<String> request = new HttpEntity<>(body, headers);
return RT.exchange(url, method, request, responseType);
return RT.exchange(URI.create(url), method, request, responseType);
}
/**
@@ -308,7 +310,7 @@ public class RestUtil {
// 发送请求
HttpEntity<String> request = new HttpEntity<>(body, headers);
return restTemplate.exchange(url, method, request, responseType);
return restTemplate.exchange(URI.create(url), method, request, responseType);
}
/**
@@ -341,7 +343,10 @@ public class RestUtil {
Object object = source.get(key);
if (object != null) {
if (!StringUtils.isEmpty(object.toString())) {
value = object.toString();
//update-begin---author:sjlei---date:20260414 for【jeecg-ai#17】修复工具节点参数值含{}时URI模板展开报错-----------
// URL 编码参数值,防止值中含 {}、空格等特殊字符导致 URI 解析异常
value = URLEncoder.encode(object.toString(), StandardCharsets.UTF_8);
//update-end-----author:sjlei---date:20260414 for【jeecg-ai#17】修复工具节点参数值含{}时URI模板展开报错-----------
}
}
urlVariables.append("&").append(key).append("=").append(value);

View File

@@ -33,8 +33,10 @@ public class SqlInjectionUtil {
private static String specialReportXssStr = "exec |peformance_schema|information_schema|extractvalue|updatexml|geohash|gtid_subset|gtid_subtract|insert |alter |delete |grant |update |drop |master |truncate |declare |--";
/**
* 字典专用—sql注入关键词
*
* @updateBy: sunjianlei 20260331 加上 substring 注入检测
*/
private static String specialDictSqlXssStr = "exec |peformance_schema|information_schema|extractvalue|updatexml|geohash|gtid_subset|gtid_subtract|insert |select |delete |update |drop |count |chr |mid |master |truncate |char |declare |;|+|--";
private static String specialDictSqlXssStr = "exec |peformance_schema|information_schema|extractvalue|updatexml|geohash|gtid_subset|gtid_subtract|insert |select |delete |update |drop |count |chr |mid |master |truncate |char |declare |;|+|--|substring |substring(";
/**
* 完整匹配的key不需要考虑前空格
*/
@@ -62,6 +64,27 @@ public class SqlInjectionUtil {
"show\\s+databases",
"sleep\\(\\d*\\)",
"sleep\\(.*\\)",
// update-begin---author:sjlei---date:20260413 for【#9523】修复 SQL 注入漏洞
// 时间盲注函数(#9523MySQL BENCHMARK、PostgreSQL pg_sleep、SQL Server WAITFOR DELAY
"benchmark\\s*\\(",
"pg_sleep\\s*\\(",
"waitfor\\s+delay",
// update-end-----author:sjlei---date:20260413 for【#9523】修复 SQL 注入漏洞
// update-begin---author:zhangdaihao---date:20260427 for【issue/9571】修复字典/Online报表 boolean-blind 信息泄露
// 通过 case-when + database()/version() 等函数 + LIKE 前缀枚举进行字符级数据提取(绕过 select/union 黑名单),
"database\\s*\\(",
"version\\s*\\(",
"current_user\\s*\\(",
"current_database\\s*\\(",
"current_schema\\s*\\(",
"session_user\\s*\\(",
"system_user\\s*\\(",
"ascii\\s*\\(",
"unhex\\s*\\(",
"load_file\\s*\\(",
"into\\s+outfile",
"into\\s+dumpfile",
// update-end-----author:zhangdaihao---date:20260427 for【issue/9571】修复字典/Online报表 boolean-blind 信息泄露
};
/**
* sql注释的正则
@@ -146,7 +169,20 @@ public class SqlInjectionUtil {
private static boolean isExistSqlInjectKeyword(String sql, String keyword) {
if (sql.startsWith(keyword.trim())) {
return true;
} else if (sql.contains(keyword)) {
}
// update-begin---author:zhangdaihao---date:20260427 for【issue/9572】修复 SQL 黑名单 keyword( 紧贴形式绕过
// 原来对带 trailing space 的关键字(如 "select ")只能匹配 "select " 形式,
// 导致 id=(select(id)from(sys_user)where(...)) 的 select( 形式绕过检测。
// 这里补充:对带 trailing space 的关键字,额外检测 trimmedKeyword + "(" 形式。
// FULL_MATCHING_KEYWRODS;、+、--)保持原匹配逻辑不变。
if (keyword.endsWith(" ") && !FULL_MATCHING_KEYWRODS.contains(keyword)) {
String trimmedKeyword = keyword.trim();
if (sql.contains(trimmedKeyword + "(")) {
return true;
}
}
// update-end-----author:zhangdaihao---date:20260427 for【issue/9572】修复 SQL 黑名单 keyword( 紧贴形式绕过
if (sql.contains(keyword)) {
// 需要匹配的sql注入关键词
String matchingText = " " + keyword;
if(FULL_MATCHING_KEYWRODS.contains(keyword)){
@@ -156,6 +192,18 @@ public class SqlInjectionUtil {
if (sql.contains(matchingText)) {
return true;
} else {
// update-begin---author:sjlei---date:20260413 for【#9524】修复 SQL 注入漏洞
// 检测关键词前紧跟非字母分隔符的情况,原来只检测前置空格,
// 导致 (updatexml(、(extractvalue( 等写法绕过检测(#9524
String[] sqlTokenPrefixes = {"(", ",", "=", "!", "<", ">"};
for (String prefix : sqlTokenPrefixes) {
if (sql.contains(prefix + keyword)) {
return true;
}
}
// update-end-----author:sjlei---date:20260413 for【#9524】修复 SQL 注入漏洞
// 检测编码空格绕过(%09 %0A %0D 等可替代空格的字符)
String regularStr = "\\s+\\S+" + keyword;
List<String> resultFindAll = ReUtil.findAll(regularStr, sql, 0, new ArrayList<String>());
for (String res : resultFindAll) {

View File

@@ -8,6 +8,7 @@ import org.jeecg.common.exception.JeecgBootException;
import org.jeecg.common.system.vo.DynamicDataSourceModel;
import org.jeecg.common.util.ReflectHelper;
import org.jeecg.common.util.oConvertUtils;
import org.jeecg.common.util.security.JdbcSecurityUtil;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
@@ -42,7 +43,10 @@ public class DynamicDBUtil {
if (oConvertUtils.isEmpty(url) || !url.toLowerCase().startsWith("jdbc:")) {
throw new JeecgBootException("数据源URL配置格式不正确");
}
// 纵深防御: 连接建立时二次校验 URL 和驱动安全性
JdbcSecurityUtil.validate(url);
JdbcSecurityUtil.validateDriver(driverClassName);
String dbUser = dbSource.getDbUsername();
String dbPassword = dbSource.getDbPassword();
dataSource.setDriverClassName(driverClassName);

View File

@@ -7,6 +7,10 @@ import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
import java.io.InputStream;
import java.net.InetAddress;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
@@ -305,6 +309,50 @@ public class SsrfFileTypeFilter {
}
}
//update-begin---author:zhangdaihao ---date:2026-04-15 for【issues/9553】修复二次SSRF漏洞对HTTP下载URL进行安全校验-----------
/**
* 校验HTTP(S) URL防止SSRF攻击最小化拦截只挡真正危险的目标
* 规则:
* 1. 仅允许 http / https 协议;
* 2. 解析主机IP拒绝 loopback127.x / ::1和 link-local169.254.x含云元数据 169.254.169.254 / fe80:
* 注意RFC1918 私网段10/172.16/192.168)允许通过,兼容企业内网 MinIO/OSS/文件服务等合法用途。
*
* @param fileUrl HTTP(S) URL
*/
public static void checkSsrfHttpUrl(String fileUrl) {
if (StringUtils.isBlank(fileUrl)) {
throw new JeecgBootException("非法URL地址为空");
}
URI uri;
try {
uri = new URI(fileUrl);
} catch (URISyntaxException e) {
throw new JeecgBootException("非法URL格式错误");
}
String scheme = uri.getScheme();
if (scheme == null || !(scheme.equalsIgnoreCase("http") || scheme.equalsIgnoreCase("https"))) {
throw new JeecgBootException("非法URL仅允许 http / https 协议");
}
String host = uri.getHost();
if (StringUtils.isBlank(host)) {
throw new JeecgBootException("非法URL主机名为空");
}
// 去掉 IPv6 的中括号
if (host.startsWith("[") && host.endsWith("]")) {
host = host.substring(1, host.length() - 1);
}
try {
for (InetAddress addr : InetAddress.getAllByName(host)) {
if (addr.isLoopbackAddress() || addr.isLinkLocalAddress()) {
throw new JeecgBootException("非法URL禁止访问本机或链路本地地址 " + addr.getHostAddress());
}
}
} catch (UnknownHostException e) {
throw new JeecgBootException("非法URL主机名无法解析");
}
}
//update-end---author:zhangdaihao ---date:2026-04-15 for【issues/9553】修复二次SSRF漏洞对HTTP下载URL进行安全校验-----------
/**
* 批量校验文件路径安全性(逗号分隔的多个文件路径)
* @param files 逗号分隔的文件路径

View File

@@ -22,6 +22,7 @@ import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.math.RoundingMode;
import java.net.*;
import java.sql.Date;
import java.util.*;
@@ -1046,7 +1047,7 @@ public class oConvertUtils {
BigDecimal bigDecimal = new BigDecimal(uploadCount);
//换算成MB
BigDecimal divide = bigDecimal.divide(new BigDecimal(1048576));
count = divide.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
count = divide.setScale(2, RoundingMode.HALF_UP).doubleValue();
return count;
}
return count;

View File

@@ -249,10 +249,12 @@ public class OssBootUtil {
}
/**
* 获取文件流
* @param objectName
* @param bucket
* @return
* 获取指定桶(私有桶)中的文件流
* 通过OSS SDK直接读取文件内容支持指定自定义桶名如 "eoafile"),为空则使用默认桶
*
* @param objectName 文件对象路径(如 "eoafile/2026/04/test.pdf",会自动替换前缀)
* @param bucket 自定义桶名称,为空则使用默认桶
* @return 文件输入流失败返回null
*/
public static InputStream getOssFile(String objectName,String bucket){
InputStream inputStream = null;
@@ -282,11 +284,13 @@ public class OssBootUtil {
//}
/**
* 获取文件外链
* @param bucketName
* @param objectName
* @param expires
* @return
* 获取私有桶文件的预签名访问URL带过期时间
* 通过OSS预签名机制生成临时访问链接无需公开桶即可让外部下载/预览文件
*
* @param bucketName 桶名称(如 "eoafile"
* @param objectName 文件对象路径(会自动替换前缀)
* @param expires 链接过期时间点Date类型如1天后过期
* @return 预签名URL字符串文件不存在或失败返回null
*/
public static String getObjectUrl(String bucketName, String objectName, Date expires) {
initOss(endPoint, accessKeyId, accessKeySecret);
@@ -322,10 +326,12 @@ public class OssBootUtil {
/**
* 上传文件到oss
* @param stream
* @param relativePath
* @return
* 通过输入流上传文件到阿里云OSS默认桶
* 上传后设置桶为公开读权限返回文件完整访问URL
*
* @param stream 文件输入流
* @param relativePath 文件在桶中的相对路径(如 "upload/2026/04/test.pdf"
* @return 文件完整访问URL优先使用staticDomain否则拼接 bucketName.endPoint
*/
public static String upload(InputStream stream, String relativePath) {
String filePath = null;

View File

@@ -4,43 +4,132 @@ import org.jeecg.common.exception.JeecgBootException;
import org.jeecg.common.util.oConvertUtils;
/**
* jdbc连接校验
* JDBC连接安全校验工具类
*
* 修复说明:
* 原实现仅检查 URL 中 '?' 之后的参数,且黑名单仅包含 5 个 PostgreSQL 参数。
* 存在以下安全隐患:
* 1. MySQL 危险参数 (allowLoadLocalInfile, autoDeserialize 等) 未覆盖
* 2. H2 使用 ';' 分隔参数,完全绕过 '?' 检查
* 3. MySQL multi-host 语法 '(host,param=val)' 和 address-block 语法不使用 '?'
*
* 修复方案: 对 URL 全文做 toLowerCase() + contains() 匹配,
* 覆盖所有参数分隔符格式 (?, ;, (), address=),并扩展黑名单覆盖全部主流驱动。
*
* @Author taoYan
* @Date 2022/8/10 18:15
**/
*/
public class JdbcSecurityUtil {
/**
* 连接驱动漏洞 最新版本修复后可删除相应的key
* postgreauthenticationPluginClassName, sslhostnameverifier, socketFactory, sslfactory, sslpasswordcallback
* https://github.com/pgjdbc/pgjdbc/security/advisories/GHSA-v7wg-cpwc-24m4
*
* 全驱动危险参数黑名单 (全小写,用于 contains 匹配)
*
* 使用 URL 全文 contains 匹配策略,覆盖所有参数分隔符:
* - 标准格式: ?key=value&key=value
* - H2 格式: ;KEY=value
* - MySQL multi-host: (host,key=value)
* - MySQL address-block: address=(key=value)
*/
public static final String[] notAllowedProps = new String[]{"authenticationPluginClassName", "sslhostnameverifier", "socketFactory", "sslfactory", "sslpasswordcallback"};
private static final String[] UNSAFE_PARAMS = {
// === MySQL / MariaDB ===
// 文件读取相关
"allowloadlocalinfile", // LOAD DATA LOCAL INFILE
"allowurlinlocalinfile", // 通过 URL 读取远程文件
"allowloadlocalinfileinpath", // 指定路径文件读取
// 反序列化相关
"autodeserialize", // 启用反序列化
"queryinterceptors", // 查询拦截器 (反序列化触发点)
"statementinterceptors", // 语句拦截器 (反序列化触发点)
"detectcustomcollations", // 自定义排序规则检测 (反序列化触发点)
// 配合攻击
"maxallowedpacket", // 突破数据包大小限制
// === PostgreSQL ===
// https://github.com/pgjdbc/pgjdbc/security/advisories/GHSA-v7wg-cpwc-24m4
"socketfactory", // 任意类实例化 RCE
"socketfactoryarg", // socketFactory 构造参数
"sslfactory", // SSL 工厂类加载
"sslhostnameverifier", // SSL 主机名验证器类加载
"sslpasswordcallback", // SSL 密码回调类加载
"authenticationpluginclassname", // 认证插件类加载
"jaasapplicationname", // JAAS 认证攻击
// === H2 ===
"init=", // 连接初始化 SQL (带 '=' 防止匹配到正常单词 'init')
"runscript", // 远程/本地 SQL 脚本加载
"trace_level_system_out", // 系统信息泄露
};
/**
* 校验sql是否有特定的key
* @param jdbcUrl
* @return
* 允许的 JDBC 驱动类名白名单
*/
public static void validate(String jdbcUrl){
if(oConvertUtils.isEmpty(jdbcUrl)){
private static final String[] ALLOWED_DRIVERS = {
// MySQL 数据库
"com.mysql.jdbc.Driver",
// MySQL5.7+ 数据库
"com.mysql.cj.jdbc.Driver",
// Oracle
"oracle.jdbc.OracleDriver",
"oracle.jdbc.driver.OracleDriver",
// SQLServer 数据库
"com.microsoft.sqlserver.jdbc.SQLServerDriver",
// marialDB 数据库
"org.mariadb.jdbc.Driver",
// postgresql 数据库
"org.postgresql.Driver",
// 达梦 数据库
"dm.jdbc.driver.DmDriver",
// 人大金仓 数据库
"com.kingbase8.Driver",
// 神通 数据库
"com.oscar.Driver",
// SQLite 数据库
"org.sqlite.JDBC",
// DB2 数据库
"com.ibm.db2.jcc.DB2Driver",
// Hsqldb 数据库
"org.hsqldb.jdbc.JDBCDriver",
// Derby 数据库
"org.apache.derby.jdbc.ClientDriver",
// H2 数据库
"org.h2.Driver",
};
/**
* 校验 JDBC URL 是否包含危险参数
*
* @param jdbcUrl JDBC 连接地址
* @throws JeecgBootException 包含危险参数时抛出
*/
public static void validate(String jdbcUrl) {
if (oConvertUtils.isEmpty(jdbcUrl)) {
return;
}
String urlConcatChar = "?";
if(jdbcUrl.indexOf(urlConcatChar)<0){
return;
}
String argString = jdbcUrl.substring(jdbcUrl.indexOf(urlConcatChar)+1);
String[] keyAndValues = argString.split("&");
for(String temp: keyAndValues){
String key = temp.split("=")[0];
for(String prop: notAllowedProps){
if(prop.equalsIgnoreCase(key)){
throw new JeecgBootException("连接地址有安全风险,【"+key+"");
}
String lowerUrl = jdbcUrl.toLowerCase();
for (String unsafeParam : UNSAFE_PARAMS) {
if (lowerUrl.contains(unsafeParam)) {
throw new JeecgBootException("连接地址有安全风险,包含不安全参数【" + unsafeParam + "");
}
}
}
}
/**
* 校验驱动类名是否在白名单中
*
* @param driverClassName JDBC 驱动类名
* @throws JeecgBootException 驱动不在白名单时抛出
*/
public static void validateDriver(String driverClassName) {
if (oConvertUtils.isEmpty(driverClassName)) {
throw new JeecgBootException("数据库驱动类名不能为空");
}
for (String allowed : ALLOWED_DRIVERS) {
if (allowed.equals(driverClassName)) {
return;
}
}
throw new JeecgBootException("不支持的数据库驱动【" + driverClassName + "】,如需支持请联系管理员");
}
}

View File

@@ -0,0 +1,100 @@
package org.jeecg.config;
import lombok.Data;
import org.jeecg.ai.factory.AiModelFactory;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
@Data
@Component("jeecgAiChatConfig")
@ConfigurationProperties(prefix = "jeecg.ai-chat")
public class AiChatConfig {
/**
* skills配置文件路径
*/
private String skillsDir;
/**
* shell命令行配置文件路径
*/
private String skillsShellDir;
/**
* AI绘图(文生图)
*/
private ModelConfig aiModelDraw = new ModelConfig();
/**
* AI图生(图绘画)
*/
private ModelConfig aiModelPicDraw = new ModelConfig();
/**
* AI语音
*/
private VoiceModelConfig aiModelVoice = new VoiceModelConfig();
/**
* AI视频
*/
private VideoModelConfig aiModelVideo = new VideoModelConfig();
/**
* AI默认向量模型
*/
private ModelConfig aiModelEmbed = new ModelConfig();
@Data
public static class ModelConfig {
/**
* 使用的模型
*/
private String model;
/**
* api秘钥
*/
private String apiKey;
/**
* api域名
*/
private String apiHost;
/**
* 超时时间
*/
private int timeout = 60;
/**
* 供应商
*/
private String provider = AiModelFactory.AIMODEL_TYPE_QWEN;
}
@Data
public static class VideoModelConfig extends ModelConfig {
/**
* ffmpeg 可执行文件路径,为空时自动查找
*/
private String ffmpegPath;
/**
* edge-tts 可执行文件路径,为空时自动查找
*/
private String edgeTtsPath;
}
@Data
public static class VoiceModelConfig extends ModelConfig {
/**
* 默认声色
*/
private String voice = "alloy";
/**
* 默认倍速范围0.25~4.0
*/
private double speed = 1.0;
/**
* 默认音量增益(dB)
*/
private double volume = 0.0;
}
}

View File

@@ -21,4 +21,29 @@ public class AiRagConfigBean {
* stdio mpc命令行功能开启sqlAI流程SQL节点开启
*/
private String allowSensitiveNodes = "";
//update-begin---author:wangshuai ---date:2026-04-15 forBrave Search配置迁移到AiRagConfigBean去掉enabled字段apiKey为空即不启用-----------
/**
* Brave Search 联网检索配置
*/
private BraveSearchConfig braveSearch = new BraveSearchConfig();
@Data
public static class BraveSearchConfig {
/** Brave Search API Key为空时联网检索不生效 */
private String apiKey;
/** API 端点,默认官方地址 */
private String endpoint = "https://api.search.brave.com/res/v1/web/search";
/** 默认返回结果条数,最大 20 */
private Integer count = 10;
/** 请求超时秒数 */
private Integer timeout = 15;
/**
* 搜索结果缓存时长(分钟)。
* 大于 0 时开启缓存,相同参数的查询直接返回缓存结果,不重复调用 API。
* 设为 0 或不配置则关闭缓存。
*/
private Integer cacheExpireMinutes = 60;
}
//update-end---author:wangshuai ---date:2026-04-15 forBrave Search配置迁移到AiRagConfigBean去掉enabled字段apiKey为空即不启用-----------
}

View File

@@ -211,6 +211,10 @@ public class ShiroConfig {
filterChainDefinitionMap.put("/xslmes/mesXslWarehouse/anon/**", "anon");
// MES库区管理免密接口供桌面端调用
filterChainDefinitionMap.put("/xslmes/mesXslWarehouseArea/anon/**", "anon");
// MES密炼物料皮重策略免密接口供桌面端调用
filterChainDefinitionMap.put("/xslmes/mesXslMixerMaterialTareStrategy/anon/**", "anon");
// MES单位只读免密接口供桌面端单位下拉调用
filterChainDefinitionMap.put("/xslmes/mesXslUnit/anon/**", "anon");
// MES密炼物料管理免密接口供桌面端调用
filterChainDefinitionMap.put("/mes/material/mixerMaterial/anon/**", "anon");
// 打印模板免密接口(供桌面端调用)

View File

@@ -6,7 +6,7 @@
<parent>
<groupId>org.jeecgframework.boot3</groupId>
<artifactId>jeecg-boot-module</artifactId>
<version>3.9.1</version>
<version>3.9.2</version>
</parent>
<artifactId>jeecg-boot-module-airag</artifactId>
@@ -41,14 +41,14 @@
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-bom</artifactId>
<version>1.9.1</version>
<version>1.12.2</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-community-bom</artifactId>
<version>1.9.1-beta17</version>
<version>1.12.1-beta21</version>
<type>pom</type>
<scope>import</scope>
</dependency>
@@ -75,7 +75,7 @@
<dependency>
<groupId>org.jeecgframework.boot3</groupId>
<artifactId>jeecg-aiflow</artifactId>
<version>3.9.1-beta1</version>
<version>3.9.2-beta</version>
<exclusions>
<exclusion>
<groupId>commons-io</groupId>
@@ -103,7 +103,7 @@
<groupId>com.yomahub</groupId>
<artifactId>liteflow-script-graaljs</artifactId>
<version>${liteflow.version}</version>
<scope>compile</scope>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.yomahub</groupId>
@@ -160,6 +160,10 @@
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-ollama</artifactId>
</dependency>
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-google-ai-gemini</artifactId>
</dependency>
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-community-zhipu-ai</artifactId>
@@ -233,12 +237,29 @@
<artifactId>tika-parser-text-module</artifactId>
<version>${apache-tika.version}</version>
</dependency>
<!--skills-->
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-skills</artifactId>
</dependency>
<!--命令模式-->
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-experimental-skills-shell</artifactId>
<version>1.12.2-beta22</version>
</dependency>
<!-- word模版引擎 -->
<dependency>
<groupId>com.deepoove</groupId>
<artifactId>poi-tl</artifactId>
<version>1.12.2</version>
</dependency>
<!-- jsoup HTML parser library @ https://jsoup.org/ -->
<dependency>
<groupId>org.jsoup</groupId>
<artifactId>jsoup</artifactId>
<version>1.22.1</version>
</dependency>
</dependencies>
</project>

View File

@@ -0,0 +1,107 @@
package org.jeecg.modules.airag.api;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import lombok.extern.slf4j.Slf4j;
import org.jeecg.common.airag.api.IAiragBaseApi;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.exception.JeecgBootBizTipException;
import org.jeecg.common.util.AssertUtils;
import org.jeecg.common.util.oConvertUtils;
import org.jeecg.modules.airag.app.entity.AiragApp;
import org.jeecg.modules.airag.app.service.IAiragAppService;
import org.jeecg.modules.airag.app.service.IAiragVariableService;
import org.jeecg.modules.airag.llm.consts.LLMConsts;
import org.jeecg.modules.airag.llm.entity.AiragKnowledgeDoc;
import org.jeecg.modules.airag.llm.service.IAiragKnowledgeDocService;
import org.jeecg.modules.airag.prompts.entity.AiragPrompts;
import org.jeecg.modules.airag.prompts.service.IAiragPromptsService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Service;
/**
* airag baseAPI 实现类
*/
@Slf4j
@Primary
@Service("airagBaseApiImpl")
public class AiragBaseApiImpl implements IAiragBaseApi {
@Autowired
private IAiragKnowledgeDocService airagKnowledgeDocService;
@Override
public String knowledgeWriteTextDocument(String knowledgeId, String title, String content, String segmentConfig) {
AssertUtils.assertNotEmpty("知识库ID不能为空", knowledgeId);
AssertUtils.assertNotEmpty("写入内容不能为空", content);
AiragKnowledgeDoc knowledgeDoc = new AiragKnowledgeDoc();
knowledgeDoc.setKnowledgeId(knowledgeId);
knowledgeDoc.setTitle(title);
knowledgeDoc.setType(LLMConsts.KNOWLEDGE_DOC_TYPE_TEXT);
knowledgeDoc.setContent(content);
// 将分段策略配置写入文档的metadata中EmbeddingHandler会从中读取分段配置
if (oConvertUtils.isNotEmpty(segmentConfig)) {
knowledgeDoc.setMetadata(segmentConfig);
}
Result<?> result = airagKnowledgeDocService.editDocument(knowledgeDoc);
if (!result.isSuccess()) {
throw new JeecgBootBizTipException(result.getMessage());
}
if (knowledgeDoc.getId() == null) {
throw new JeecgBootBizTipException("知识库文档ID为空");
}
log.info("[AI-KNOWLEDGE] 文档写入完成,知识库:{}, 文档ID:{}", knowledgeId, knowledgeDoc.getId());
return knowledgeDoc.getId();
}
@Autowired
private IAiragAppService airagAppService;
@Autowired
private IAiragVariableService airagVariableService;
@Autowired
private IAiragPromptsService airagPromptsService;
@Override
public String getChatVariable(String appId, String username, String name) {
return airagVariableService.getVariable(username, appId, name);
}
@Override
public void setChatVariable(String appId, String username, String name, String value) {
AssertUtils.assertNotEmpty("应用ID不能为空", appId);
AssertUtils.assertNotEmpty("用户名不能为空", username);
AssertUtils.assertNotEmpty("变量名不能为空", name);
airagVariableService.updateVariable(username, appId, name, value != null ? value : "");
}
@Override
public String getMemoryIdByAppId(String appId) {
if (oConvertUtils.isEmpty(appId)) {
return null;
}
LambdaQueryWrapper<AiragApp> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(AiragApp::getId, appId)
.eq(AiragApp::getIzOpenMemory, 1)
.isNotNull(AiragApp::getMemoryId)
.ne(AiragApp::getMemoryId, "")
.select(AiragApp::getMemoryId);
AiragApp app = airagAppService.getOne(queryWrapper);
return app != null ? app.getMemoryId() : null;
}
@Override
public String getPromptContent(String promptId) {
if (oConvertUtils.isEmpty(promptId)) {
return null;
}
AiragPrompts prompt = airagPromptsService.getById(promptId);
if (prompt == null) {
log.warn("[AiragBaseApi]提示词不存在promptId={}", promptId);
return null;
}
return prompt.getContent();
}
}

View File

@@ -64,4 +64,27 @@ public class AiAppConsts {
* AI写作redis请求前缀
*/
public static final String ARTICLE_WRITER_KEY = "airag:chat:article:write:{}";
/**
* ai绘画类型: 绘图
*/
public static final String AI_DRAW_TYPE_DRAW = "draw";
/**
* ai绘画类型: 换脸
*/
public static final String AI_DRAW_TYPE_FACE = "face";
/**
* ai绘画类型: 混图
*/
public static final String AI_DRAW_TYPE_MIX = "mix";
/**
* ai绘画 会话redis请求前缀
*/
public static final String POSTER_TASK_PREFIX = "airag:poster:task:";
/** 任务结果在 Redis 中保留 1 小时 */
public static final long POSTER_TASK_TTL = 3600L;
}

View File

@@ -173,4 +173,9 @@ public class Prompts {
*/
public static final String AI_TOUCHE_PROMPT = "请针对如下内容:[{}] 进行润色。 回复格式:{},语气:{},语言:{},长度:{}。";
/**
* ai绘画提示词
*/
public static final String AI_DRAW_PROMPT = "风格:{},视角:{},人物镜头:{},灯光:{},图片尺寸:{};";
}

View File

@@ -23,8 +23,10 @@ import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;
import java.util.List;
import java.util.stream.Collectors;
import jakarta.servlet.http.HttpServletRequest;
import org.jeecg.common.system.vo.DictModel;
/**
* @Description: AI应用
@@ -62,6 +64,25 @@ public class AiragAppController extends JeecgController<AiragApp, IAiragAppServi
return Result.OK(pageList);
}
/**
* 字典列表查询(不分页,按创建时间倒序)
*
* @param airagApp 支持通过实体字段动态过滤,如 type 等
* @param req HTTP请求
* @return 应用字典列表
*/
@GetMapping(value = "/listDict")
public Result<List<DictModel>> listDict(AiragApp airagApp, HttpServletRequest req) {
QueryWrapper<AiragApp> queryWrapper = QueryGenerator.initQueryWrapper(airagApp, req.getParameterMap());
queryWrapper.select("id", "name");
queryWrapper.orderByDesc("create_time");
List<AiragApp> list = airagAppService.list(queryWrapper);
List<DictModel> dictList = list.stream()
.map(app -> new DictModel(app.getId(), app.getName()))
.collect(Collectors.toList());
return Result.OK(dictList);
}
/**
* 新增或编辑
*
@@ -70,10 +91,24 @@ public class AiragAppController extends JeecgController<AiragApp, IAiragAppServi
*/
@RequestMapping(value = "/edit", method = {RequestMethod.PUT, RequestMethod.POST})
@RequiresPermissions("airag:app:edit")
public Result<String> edit(@RequestBody AiragApp airagApp) {
public Result<String> edit(@RequestBody AiragApp airagApp, HttpServletRequest request) {
AssertUtils.assertNotEmpty("参数异常", airagApp);
AssertUtils.assertNotEmpty("请输入应用名称", airagApp.getName());
AssertUtils.assertNotEmpty("请选择应用类型", airagApp.getType());
//update-begin---author:zhangdaihao ---date:20260415 for[issues/9462]AI应用edit接口跨租户数据写入漏洞------------
//SaaS多租户隔离禁止跨租户写入防止通过请求体伪造tenantId污染其他租户数据
if (MybatisPlusSaasConfig.OPEN_SYSTEM_TENANT_CONTROL) {
String currentTenantId = TokenUtils.getTenantIdByRequest(request);
if (airagApp.getId() != null && !airagApp.getId().isEmpty()) {
AiragApp dbApp = airagAppService.getById(airagApp.getId());
if (dbApp == null || !dbApp.getTenantId().equals(currentTenantId)) {
return Result.error("保存AI应用失败不能修改其他租户的AI应用");
}
}
//强制使用当前登录租户,忽略客户端传入值
airagApp.setTenantId(currentTenantId);
}
//update-end---author:zhangdaihao ---date:20260415 for[issues/9462]AI应用edit接口跨租户数据写入漏洞------------
airagApp.setStatus(AiAppConsts.STATUS_ENABLE);
airagAppService.saveOrUpdate(airagApp);
return Result.OK("保存完成!", airagApp.getId());

View File

@@ -8,6 +8,7 @@ import org.jeecg.common.constant.CommonConstant;
import org.jeecg.common.util.CommonUtils;
import org.jeecg.config.shiro.IgnoreAuth;
import org.jeecg.modules.airag.app.service.IAiragChatService;
import org.jeecg.modules.airag.app.vo.AiDrawGenerateVo;
import org.jeecg.modules.airag.app.vo.AiWriteGenerateVo;
import org.jeecg.modules.airag.app.vo.ChatConversation;
import org.jeecg.modules.airag.app.vo.ChatSendParams;
@@ -266,11 +267,31 @@ public class AiragChatController {
* @return
*/
@PostMapping("/genAiPoster")
public Result<String> genAiPoster(@RequestBody ChatSendParams chatSendParams){
String imageUrl = chatService.genAiPoster(chatSendParams);
public Result<String> genAiPoster(@RequestBody AiDrawGenerateVo aiDrawGenerateVo){
String imageUrl = chatService.genAiPoster(aiDrawGenerateVo);
return Result.OK(imageUrl);
}
//update-begin---author:wangshuai ---date:2026-04-15 for【QQYUN-14568】AI海报生成改为异步支持切换菜单后重新获取结果-----------
/**
* 异步提交AI海报生成任务立即返回taskId
*/
@PostMapping("/genAiPosterAsync")
public Result<String> genAiPosterAsync(@RequestBody AiDrawGenerateVo aiDrawGenerateVo) {
String taskId = chatService.genAiPosterAsync(aiDrawGenerateVo);
return Result.OK(taskId);
}
/**
* 查询AI海报异步任务结果
* status: pending / success / failed
*/
@GetMapping("/getAiPosterResult/{taskId}")
public Result<?> getAiPosterResult(@PathVariable String taskId) {
return chatService.getAiPosterResult(taskId);
}
//update-end---author:wangshuai ---date:2026-04-15 for【QQYUN-14568】AI海报生成改为异步支持切换菜单后重新获取结果-----------
/**
* 生成ai写作

View File

@@ -0,0 +1,36 @@
package org.jeecg.modules.airag.app.enums;
/**
* @Description: 图像编辑枚举
*
* @author: wangshuai
* @date: 2026/2/28 16:52
*/
public enum ImageEditEnum {
WANX2_1_IMAGEEDIT("wanx2.1-imageedit"),
WAN2_5_I2I_PREVIEW("wan2.5-i2i-preview");
private final String modelName;
ImageEditEnum(String modelName) {
this.modelName = modelName;
}
public String getModelName() {
return modelName;
}
/**
* 检查模型名称是否是图像编辑模型
* @param modelName 模型名称
* @return 是否是图像编辑模型
*/
public static boolean isImageEditModel(String modelName) {
for (ImageEditEnum model : values()) {
if (model.getModelName().equals(modelName)) {
return true;
}
}
return false;
}
}

View File

@@ -0,0 +1,57 @@
package org.jeecg.modules.airag.app.enums;
import org.apache.commons.lang3.StringUtils;
/**
* @Description: 图片大小比例枚举
*
* @author: wangshuai
* @date: 2026/2/4 19:55
*/
public enum ImageSizeEnum {
SIZE_1024_1024("1024*1024", "1:1"),
SIZE_1280_720("1280*720", "16:9"),
SIZE_720_1280("720*1280", "9:16"),
SIZE_1024_768("1024*768", "4:3"),
SIZE_768_1024("768*1024", "3:4");
ImageSizeEnum(String size, String ratio) {
this.size = size;
this.ratio = ratio;
}
/**
* 大小
*/
private String size;
/**
* 比例
*/
private String ratio;
public String getSize() {
return size;
}
public String getRatio() {
return ratio;
}
/**
* 根据size获取ratio
*
* @param size
* @return
*/
public static String getRatioBySize(String size) {
if (StringUtils.isBlank(size)) {
return "1:1";
}
for (ImageSizeEnum e : ImageSizeEnum.values()) {
if (e.size.equals(size)) {
return e.ratio;
}
}
return "1:1";
}
}

View File

@@ -1,10 +1,7 @@
package org.jeecg.modules.airag.app.service;
import org.jeecg.common.api.vo.Result;
import org.jeecg.modules.airag.app.vo.AiWriteGenerateVo;
import org.jeecg.modules.airag.app.vo.AppDebugParams;
import org.jeecg.modules.airag.app.vo.ChatConversation;
import org.jeecg.modules.airag.app.vo.ChatSendParams;
import org.jeecg.modules.airag.app.vo.*;
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;
/**
@@ -126,10 +123,26 @@ public interface IAiragChatService {
/**
* 生成海报图片
* @param chatSendParams
* @param aiDrawGenerateVo
* @return
*/
String genAiPoster(ChatSendParams chatSendParams);
String genAiPoster(AiDrawGenerateVo aiDrawGenerateVo);
//update-begin---author:wangshuai ---date:2026-04-15 for【QQYUN-14568】AI海报生成改为异步支持切换菜单后重新获取结果-----------
/**
* 异步生成海报图片立即返回taskId
* @param aiDrawGenerateVo
* @return taskId
*/
String genAiPosterAsync(AiDrawGenerateVo aiDrawGenerateVo);
/**
* 查询异步海报任务结果
* @param taskId
* @return Resultdata为图片URL成功或status=pending/failed
*/
Result<?> getAiPosterResult(String taskId);
//update-end---author:wangshuai ---date:2026-04-15 for【QQYUN-14568】AI海报生成改为异步支持切换菜单后重新获取结果-----------
/**
* 生成ai创作

View File

@@ -33,6 +33,16 @@ public interface IAiragVariableService {
*/
void initVariable(String userId, String appId, String name, String defaultValue);
/**
* 获取变量值
*
* @param username 用户名
* @param appId 应用ID
* @param name 变量名
* @return 变量值不存在返回null
*/
String getVariable(String username, String appId, String name);
/**
* 添加变量更新工具
*

View File

@@ -1,6 +1,7 @@
package org.jeecg.modules.airag.app.service.impl;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import dev.langchain4j.agent.tool.ToolExecutionRequest;
@@ -19,21 +20,23 @@ import org.jeecg.common.api.vo.Result;
import org.jeecg.common.constant.SymbolConstant;
import org.jeecg.common.exception.JeecgBootBizTipException;
import org.jeecg.common.exception.JeecgBootException;
import java.nio.file.Paths;
import org.jeecg.common.system.api.ISysBaseAPI;
import org.jeecg.common.system.util.JwtUtil;
import org.jeecg.common.util.*;
import org.jeecg.common.util.filter.SsrfFileTypeFilter;
import org.jeecg.config.AiChatConfig;
import org.jeecg.config.AiRagConfigBean;
import org.jeecg.config.JeecgBaseConfig;
import org.jeecg.config.vo.Path;
import org.jeecg.modules.airag.app.consts.AiAppConsts;
import org.jeecg.modules.airag.app.consts.Prompts;
import org.jeecg.modules.airag.app.entity.AiragApp;
import org.jeecg.modules.airag.app.enums.ImageSizeEnum;
import org.jeecg.modules.airag.app.mapper.AiragAppMapper;
import org.jeecg.modules.airag.app.service.IAiragChatService;
import org.jeecg.modules.airag.app.service.IAiragVariableService;
import org.jeecg.modules.airag.app.vo.AiWriteGenerateVo;
import org.jeecg.modules.airag.app.vo.AppDebugParams;
import org.jeecg.modules.airag.app.vo.ChatConversation;
import org.jeecg.modules.airag.app.vo.ChatSendParams;
import org.jeecg.modules.airag.app.vo.*;
import org.jeecg.modules.airag.common.consts.AiragConsts;
import org.jeecg.modules.airag.common.handler.AIChatParams;
import org.jeecg.modules.airag.common.handler.IAIChatHandler;
@@ -43,13 +46,17 @@ import org.jeecg.modules.airag.common.vo.MessageHistory;
import org.jeecg.modules.airag.common.vo.event.EventData;
import org.jeecg.modules.airag.common.vo.event.EventFlowData;
import org.jeecg.modules.airag.common.vo.event.EventMessageData;
import org.jeecg.modules.airag.flow.context.JeecgFlowContext;
import org.jeecg.modules.airag.flow.consts.FlowConsts;
import org.jeecg.modules.airag.flow.entity.AiragFlow;
import org.jeecg.modules.airag.flow.helper.JeecgTagHelper;
import org.jeecg.modules.airag.flow.service.IAiragFlowService;
import org.jeecg.modules.airag.flow.vo.api.FlowRunParams;
import org.jeecg.modules.airag.flow.vo.tool.ToolExecutionVo;
import org.jeecg.modules.airag.llm.consts.LLMConsts;
import org.jeecg.modules.airag.llm.document.TikaDocumentParser;
import org.jeecg.modules.airag.llm.entity.AiragModel;
import org.jeecg.modules.airag.flow.handler.BraveSearchToolBuilder;
import org.jeecg.modules.airag.llm.handler.AIChatHandler;
import org.jeecg.modules.airag.llm.handler.JeecgToolsProvider;
import org.jeecg.modules.airag.llm.mapper.AiragModelMapper;
@@ -60,7 +67,7 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.BoundValueOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;
import java.io.ByteArrayOutputStream;
@@ -70,6 +77,7 @@ import java.io.InputStream;
import java.util.*;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.BiConsumer;
import java.util.stream.Collectors;
@@ -117,6 +125,12 @@ public class AiragChatServiceImpl implements IAiragChatService {
@Autowired
JeecgBaseConfig jeecgBaseConfig;
@Autowired
AiChatConfig aiChatConfig;
@Autowired
AiRagConfigBean aiRagConfigBean;
/**
* 重新接收消息
@@ -193,6 +207,13 @@ public class AiragChatServiceImpl implements IAiragChatService {
@Override
public Result<?> stop(String requestId) {
AssertUtils.assertNotEmpty("requestId不能为空", requestId);
// 设置流程上下文的停止标志通知正在执行的LLM节点停止输出
JeecgFlowContext flowContext = AiragLocalCache.get(AiragConsts.CACHE_TYPE_FLOW_CONTEXT, requestId);
if (flowContext != null) {
flowContext.setStopped(true);
AiragLocalCache.remove(AiragConsts.CACHE_TYPE_FLOW_CONTEXT, requestId);
log.info("[AI-CHAT]已设置流程停止标志, requestId:{}", requestId);
}
// 从缓存中获取对应的SseEmitter
SseEmitter emitter = AiragLocalCache.get(AiragConsts.CACHE_TYPE_SSE, requestId);
if (emitter != null) {
@@ -307,26 +328,22 @@ public class AiragChatServiceImpl implements IAiragChatService {
//update-begin---author:chenrui ---date:20251106 for[issues/8545]新建AI应用的时候只能选择没有自定义参数的AI流程------------
// 返回消息列表和会话设置信息
Map<String, Object> result = new HashMap<>();
// 过滤掉工具调用相关的消息(前端不需要展示
// 解析是否显示工具调用过程默认为true
boolean showToolProcess = true;
AiragApp chatApp = chatConversation.getApp();
if (chatApp != null && oConvertUtils.isNotEmpty(chatApp.getMetadata())) {
try {
JSONObject appMetadataJson = JSONObject.parseObject(chatApp.getMetadata());
if (appMetadataJson != null && "0".equals(appMetadataJson.getString("showToolProcess"))) {
showToolProcess = false;
}
} catch (Exception ignored) {
}
}
// 合并工具调用相关的消息
List<MessageHistory> messages = chatConversation.getMessages();
if (oConvertUtils.isObjectNotEmpty(messages)) {
messages = messages.stream()
.filter(msg -> !AiragConsts.MESSAGE_ROLE_TOOL.equals(msg.getRole()))
.map(msg -> {
// 克隆消息对象,移除工具执行请求信息(前端不需要)
MessageHistory displayMsg = MessageHistory.builder()
.conversationId(msg.getConversationId())
.topicId(msg.getTopicId())
.role(msg.getRole())
.content(msg.getContent())
.images(msg.getImages())
.files(msg.getFiles())
.datetime(msg.getDatetime())
.build();
// 不设置toolExecutionRequests和toolExecutionResult
return displayMsg;
})
.collect(Collectors.toList());
messages = mergeToolMessages(messages, showToolProcess);
}
result.put("messages", messages);
result.put("flowInputs", chatConversation.getFlowInputs());
@@ -339,6 +356,104 @@ public class AiragChatServiceImpl implements IAiragChatService {
//update-end---author:chenrui ---date:20251106 for[issues/8545]新建AI应用的时候只能选择没有自定义参数的AI流程------------
}
/**
* 合并工具调用相关的历史记录生成带有工具执行标签的AI消息
*
* @param histories 历史消息列表
* @param showToolProcess 是否显示工具调用过程
* @return 合并后的历史消息列表
*/
private List<MessageHistory> mergeToolMessages(List<MessageHistory> histories, boolean showToolProcess) {
List<MessageHistory> mergedMessages = new ArrayList<>();
if (oConvertUtils.isObjectEmpty(histories)) {
return mergedMessages;
}
// 缓存工具请求,便于后续快速匹配
Map<String, MessageHistory.ToolExecutionRequestHistory> requestCache = new HashMap<>();
// 当前正在合并的AI消息
MessageHistory currentAiMsg = null;
// 合并AI消息
BiConsumer<MessageHistory, Object> mergeMsg = (cacheMsg, obj) -> {
String currContent;
if (obj instanceof MessageHistory) {
MessageHistory currMsg = (MessageHistory) obj;
currContent = currMsg.getContent();
// 合并图片
if (CollectionUtils.isNotEmpty(currMsg.getImages())) {
List<MessageHistory.ImageHistory> images = CollectionUtils.isEmpty(cacheMsg.getImages()) ? new ArrayList<>() : cacheMsg.getImages();
images.addAll(currMsg.getImages());
cacheMsg.setImages(images);
}
// 合并文件
if (CollectionUtils.isNotEmpty(currMsg.getFiles())) {
List<MessageHistory.FileHistory> files = CollectionUtils.isEmpty(cacheMsg.getImages()) ? new ArrayList<>() : cacheMsg.getFiles();
files.addAll(currMsg.getFiles());
cacheMsg.setFiles(files);
}
} else {
currContent = obj.toString();
}
cacheMsg.setContent(cacheMsg.getContent() + currContent);
};
// 遍历所有消息,根据类型的不同做出不同处理
for (MessageHistory message : histories) {
// 用户消息原样保留,不参与合并
if (AiragConsts.MESSAGE_ROLE_USER.equals(message.getRole())) {
if (currentAiMsg != null) {
mergedMessages.add(currentAiMsg);
currentAiMsg = null;
}
mergedMessages.add(message);
continue;
}
// 从当前AI消息开始向后合并工具调用与连续AI消息
if (AiragConsts.MESSAGE_ROLE_AI.equals(message.getRole())) {
if (currentAiMsg == null) {
currentAiMsg = MessageHistory.builder()
.conversationId(message.getConversationId())
.topicId(message.getTopicId())
.role(message.getRole())
.content("")
.images(message.getImages())
.files(message.getFiles())
.datetime(message.getDatetime())
.build();
}
mergeMsg.accept(currentAiMsg, message);
List<MessageHistory.ToolExecutionRequestHistory> toolReqs = message.getToolExecutionRequests();
if (CollectionUtils.isNotEmpty(toolReqs)) {
for (MessageHistory.ToolExecutionRequestHistory request : toolReqs) {
if (request != null) {
// 使用工具调用id作为唯一键方便快速匹配结果
requestCache.put(request.getId(), request);
}
}
}
continue;
}
if (AiragConsts.MESSAGE_ROLE_TOOL.equals(message.getRole())) {
if (currentAiMsg == null || !showToolProcess) {
continue;
}
String toolId = message.getContent();
MessageHistory.ToolExecutionRequestHistory request = requestCache.get(toolId);
if (request == null) {
continue;
}
String toolResult = message.getToolExecutionResult();
ToolExecutionVo vo = ToolExecutionVo.build(toolId, request.getName(), request.getArguments(), toolResult);
String execTag = JeecgTagHelper.createTag(JeecgTagHelper.TAG_JEECG_TOOL_EXEC, JSON.toJSONString(vo));
mergeMsg.accept(currentAiMsg, execTag);
}
}
// 避免最后一条消息没有放入列表
if (currentAiMsg != null) {
mergedMessages.add(currentAiMsg);
}
return mergedMessages;
}
@Override
public Result<?> clearMessage(String conversationId, String sessionType) {
AssertUtils.assertNotEmpty("请先选择会话", conversationId);
@@ -713,6 +828,8 @@ public class AiragChatServiceImpl implements IAiragChatService {
break;
case AiragConsts.MESSAGE_ROLE_AI:
// 重建AI消息包括工具执行请求
// 获取内容如果为空则使用空字符串AiMessage不允许null
String aiContent = oConvertUtils.getString(history.getContent(), "");
if (oConvertUtils.isObjectNotEmpty(history.getToolExecutionRequests())) {
// 有工具执行请求重建带工具调用的AiMessage
List<ToolExecutionRequest> toolRequests = history.getToolExecutionRequests().stream()
@@ -722,9 +839,9 @@ public class AiragChatServiceImpl implements IAiragChatService {
.arguments(toolReq.getArguments())
.build())
.collect(Collectors.toList());
chatMessage = AiMessage.from(history.getContent(), toolRequests);
chatMessage = AiMessage.from(aiContent, toolRequests);
} else {
chatMessage = new AiMessage(history.getContent());
chatMessage = new AiMessage(aiContent);
}
break;
case AiragConsts.MESSAGE_ROLE_TOOL:
@@ -735,7 +852,10 @@ public class AiragChatServiceImpl implements IAiragChatService {
.name("unknown") // 工具名称在重建时不重要因为主要用于AI理解结果
.arguments("{}")
.build();
chatMessage = ToolExecutionResultMessage.from(recreatedRequest, history.getToolExecutionResult());
//update-begin---author:scott ---date:20260416 for【PR#9539】修复通义千问API不接受null消息内容-----------
String toolResult = history.getToolExecutionResult() != null ? history.getToolExecutionResult() : "";
chatMessage = ToolExecutionResultMessage.from(recreatedRequest, toolResult);
//update-end---author:scott ---date:20260416 for【PR#9539】修复通义千问API不接受null消息内容-----------
break;
}
if (null == chatMessage) {
@@ -765,7 +885,7 @@ public class AiragChatServiceImpl implements IAiragChatService {
private void appendMessage(List<ChatMessage> messages, ChatMessage message, ChatConversation chatConversation, String topicId, List<String> files, String saveContent) {
if (message.type().equals(ChatMessageType.SYSTEM)) {
if (message instanceof SystemMessage) {
// 系统消息,放到消息列表最前面,并且不记录历史
messages.add(0, message);
return;
@@ -778,18 +898,18 @@ public class AiragChatServiceImpl implements IAiragChatService {
}
// 消息记录
MessageHistory historyMessage = MessageHistory.builder().conversationId(chatConversation.getId()).topicId(topicId).datetime(DateUtils.now()).build();
if (message.type().equals(ChatMessageType.USER)) {
if (message instanceof UserMessage) {
historyMessage.setRole(AiragConsts.MESSAGE_ROLE_USER);
StringBuilder textContent = new StringBuilder();
List<MessageHistory.ImageHistory> images = new ArrayList<>();
List<Content> contents = ((UserMessage) message).contents();
contents.forEach(content -> {
if (content.type().equals(ContentType.IMAGE)) {
if (content instanceof ImageContent) {
ImageContent imageContent = (ImageContent) content;
Image image = imageContent.image();
MessageHistory.ImageHistory imageMessage = MessageHistory.ImageHistory.from(image.url(), image.base64Data(), image.mimeType());
images.add(imageMessage);
} else if (content.type().equals(ContentType.TEXT)) {
} else if (content instanceof TextContent) {
textContent.append(((TextContent) content).text()).append("\n");
}
});
@@ -809,10 +929,12 @@ public class AiragChatServiceImpl implements IAiragChatService {
historyMessage.setFiles(fileHistories);
}
//update-end---author:wangshuai---date:2026-01-12---for:【QQYUN-14261】【AI】AI助手支持多模态能力- 文档---
} else if (message.type().equals(ChatMessageType.AI)) {
} else if (message instanceof AiMessage) {
historyMessage.setRole(AiragConsts.MESSAGE_ROLE_AI);
AiMessage aiMessage = (AiMessage) message;
historyMessage.setContent(aiMessage.text());
//update-begin---author:scott ---date:20260416 for【PR#9539】修复通义千问API不接受null消息内容-----------
historyMessage.setContent(aiMessage.text() != null ? aiMessage.text() : "");
//update-end---author:scott ---date:20260416 for【PR#9539】修复通义千问API不接受null消息内容-----------
// 处理工具执行请求
if (oConvertUtils.isObjectNotEmpty(aiMessage.toolExecutionRequests())) {
List<MessageHistory.ToolExecutionRequestHistory> toolRequests = new ArrayList<>();
@@ -825,7 +947,7 @@ public class AiragChatServiceImpl implements IAiragChatService {
}
historyMessage.setToolExecutionRequests(toolRequests);
}
} else if (message.type().equals(ChatMessageType.TOOL_EXECUTION_RESULT)) {
} else if (message instanceof ToolExecutionResultMessage) {
// 工具执行结果消息
historyMessage.setRole(AiragConsts.MESSAGE_ROLE_TOOL);
ToolExecutionResultMessage toolMessage = (ToolExecutionResultMessage) message;
@@ -941,7 +1063,7 @@ public class AiragChatServiceImpl implements IAiragChatService {
drawModelId = JSONObject.parseObject(metadata).getString("drawModelId");
}
}
AssertUtils.assertNotEmpty("请选择绘画模型", drawModelId);
//AssertUtils.assertNotEmpty("请选择绘画模型", drawModelId);
try {
List<String> images = sendParams.getImages();
List<Map<String, Object>> imageList;
@@ -1000,6 +1122,14 @@ public class AiragChatServiceImpl implements IAiragChatService {
flowRunParams.setFlowId(flowId);
flowRunParams.setConversationId(chatConversation.getId());
flowRunParams.setTopicId(topicId);
// 传入应用id变量节点需要
if (chatConversation.getApp() != null) {
flowRunParams.setAppId(chatConversation.getApp().getId());
}
// 传入记忆库id记忆节点需要
if (chatConversation.getApp() != null) {
flowRunParams.setMemoryId(chatConversation.getApp().getMemoryId());
}
// 支持流式
flowRunParams.setResponseMode(FlowConsts.FLOW_RESPONSE_MODE_STREAMING);
Map<String, Object> flowInputParams = new HashMap<>();
@@ -1138,6 +1268,14 @@ public class AiragChatServiceImpl implements IAiragChatService {
if (metadata.containsKey("maxTokens")) {
aiChatParams.setMaxTokens(metadata.getInteger("maxTokens"));
}
//update-begin---wangshuai---date:20260401 for【issues/9455】AI应用中设定的RAG参数未生效------------
if (metadata.containsKey("topNumber")) {
aiChatParams.setTopNumber(metadata.getInteger("topNumber"));
}
if (metadata.containsKey("similarity")) {
aiChatParams.setSimilarity(metadata.getDouble("similarity"));
}
//update-end---author:wangshuai ---date:20260401 for【issues/9455】AI应用中设定的RAG参数未生效------------
if (metadata.containsKey(FlowConsts.FLOW_NODE_OPTION_TIME_OUT)) {
aiChatParams.setTimeout(oConvertUtils.getInt(metadata.getInteger(FlowConsts.FLOW_NODE_OPTION_TIME_OUT), 300));
}
@@ -1163,9 +1301,9 @@ public class AiragChatServiceImpl implements IAiragChatService {
}
}
//流程不为空,构建插件
//流程不为空,构建插件(携带应用上下文参数,供变量/记忆节点使用)
if(oConvertUtils.isNotEmpty(flowId)){
Map<String, Object> result = airagFlowPluginService.getFlowsToPlugin(flowId);
Map<String, Object> result = airagFlowPluginService.getFlowsToPlugin(flowId, aiApp.getId(), memoryId);
this.addPluginToParams(aiChatParams, result);
}
@@ -1194,6 +1332,11 @@ public class AiragChatServiceImpl implements IAiragChatService {
airagVariableService.addUpdateVariableTool(aiApp,username,aiChatParams);
}
//update-begin---author:wangshuai---date:2026-03-18---for:【QQYUN-14935】Langchain4j 新版支持 Agent Skills重新定义 Java AI 应用的能力边界---
// 封装skills及上下文信息
fillSkillsParams(aiChatParams);
//update-end---author:wangshuai---date:2026-03-18---for:【QQYUN-14935】Langchain4j 新版支持 Agent Skills重新定义 Java AI 应用的能力边界---
// 打印流程耗时日志
printChatDuration(requestId, "构造应用自定义参数完成");
// 发消息
@@ -1228,6 +1371,49 @@ public class AiragChatServiceImpl implements IAiragChatService {
}
}
/**
* 封装skills参数及上下文信息
* 当配置了skillsPath时将skills路径设置到参数中并将Token、后台地址、租户ID拼接到用户消息后面
*
* @param aiChatParams AI聊天参数
*/
private void fillSkillsParams(AIChatParams aiChatParams) {
if (oConvertUtils.isEmpty(aiChatConfig.getSkillsDir()) && oConvertUtils.isEmpty(aiChatConfig.getSkillsShellDir())) {
log.info("[Skills] skillsPath OR shellSkillsDir is empty, skip skills loading");
return;
}
if (oConvertUtils.isNotEmpty(aiChatConfig.getSkillsDir())){
aiChatParams.setSkillsDir(aiChatConfig.getSkillsDir());
log.info("[Skills] skillsDir set to: {}", aiChatParams.getSkillsDir());
}
if (oConvertUtils.isNotEmpty((aiChatConfig.getSkillsShellDir()))){
aiChatParams.setSkillsShellDir(aiChatConfig.getSkillsShellDir());
log.info("[Skills] shellSkillsDir set to: {}", aiChatParams.getSkillsShellDir());
}
// 注入运行时上下文Token、后台API地址、租户ID供Skills使用
try {
HttpServletRequest request = SpringContextUtils.getHttpServletRequest();
String token = TokenUtils.getTokenByRequest(request);
String tenantId = request.getHeader("X-Tenant-Id");
// 从当前请求构造后台API地址
String apiBase = CommonUtils.getBaseUrl(request);
StringBuilder context = new StringBuilder();
context.append("以下信息由系统自动注入Skill执行时可直接使用\n");
context.append("- **API_BASE**: `").append(apiBase).append("`\n");
if (oConvertUtils.isNotEmpty(token)) {
context.append("- **X-Access-Token**: `").append(token).append("`\n");
}
if (oConvertUtils.isNotEmpty(tenantId)) {
context.append("- **X-Tenant-Id**: `").append(tenantId).append("`\n");
}
aiChatParams.setSkillsContext(context.toString());
log.info("[Skills] context injected, apiBase: {}", apiBase);
} catch (Exception e) {
log.warn("[Skills] Failed to inject context: {}", e.getMessage());
}
}
/**
* 处理聊天
* 向大模型发送消息并接受响应
@@ -1246,22 +1432,41 @@ public class AiragChatServiceImpl implements IAiragChatService {
if (null == aiChatParams) {
aiChatParams = new AIChatParams();
}
HttpServletRequest httpRequest = SpringContextUtils.getHttpServletRequest();
// 如果是默认app,加载系统默认工具
if(chatConversation.getApp().getId().equals(AiAppConsts.DEFAULT_APP_ID)){
aiChatParams.setTools(jeecgToolsProvider.getDefaultTools());
// Security fix: 仅已登录用户可加载敏感业务工具(add_user,grant_user_roles等),匿名用户仍可正常使用AI聊天
String currentUser = getUsername(httpRequest);
if (oConvertUtils.isNotEmpty(currentUser)) {
aiChatParams.setTools(jeecgToolsProvider.getDefaultTools());
}
}
//update-begin---author:wangshuai ---date:2026-04-15 forBrave Search配置迁移到AiRagConfigBean仅在联网搜索开启时注入工具-----------
// Brave Search 联网检索工具:前端 enableSearch=true 且 apiKey 已配置时才注入
if (Boolean.TRUE.equals(aiChatParams.getEnableSearch())) {
Map<ToolSpecification, ToolExecutor> braveTools = BraveSearchToolBuilder.buildTools(aiRagConfigBean.getBraveSearch());
if (!braveTools.isEmpty()) {
Map<ToolSpecification, ToolExecutor> existing = aiChatParams.getTools();
if (existing == null) {
existing = new HashMap<>();
}
existing.putAll(braveTools);
aiChatParams.setTools(existing);
}
}
//update-end---author:wangshuai ---date:2026-04-15 forBrave Search配置迁移到AiRagConfigBean仅在联网搜索开启时注入工具-----------
if(CollectionUtils.isEmpty(aiChatParams.getKnowIds())){
aiChatParams.setKnowIds(chatConversation.getApp().getKnowIds());
} else {
aiChatParams.getKnowIds().addAll(chatConversation.getApp().getKnowIds());
}
aiChatParams.setMaxMsgNumber(oConvertUtils.getInt(chatConversation.getApp().getMsgNum(), 5));
aiChatParams.setCurrentHttpRequest(SpringContextUtils.getHttpServletRequest());
HttpServletRequest httpRequest = SpringContextUtils.getHttpServletRequest();
aiChatParams.setCurrentHttpRequest(httpRequest);
// for [QQYUN-9234] MCP服务连接关闭 - 保存参数引用用于在回调中关闭MCP连接
final AIChatParams finalAiChatParams = aiChatParams;
TokenStream chatStream;
try {
aiChatParams.setTimeout(5*30*1000);
// 打印流程耗时日志
printChatDuration(requestId, "开始向LLM发送消息");
if (oConvertUtils.isNotEmpty(modelId)) {
@@ -1280,7 +1485,7 @@ public class AiragChatServiceImpl implements IAiragChatService {
return;
}
String errMsg = "调用大模型接口失败,详情请查看后台日志。";
if(e instanceof JeecgBootException){
if(e instanceof JeecgBootException || e instanceof JeecgBootBizTipException){
errMsg = e.getMessage();
}
EventData eventData = new EventData(requestId, null, EventData.EVENT_FLOW_ERROR, chatConversation.getId(), topicId);
@@ -1288,6 +1493,38 @@ public class AiragChatServiceImpl implements IAiragChatService {
closeSSE(emitter, eventData);
throw new JeecgBootBizTipException("调用大模型接口失败:" + e.getMessage());
}
// 发送消息给前端
BiConsumer<String, String> send2Client = (resMessage, eventType) -> {
eventType = oConvertUtils.isNotEmpty(eventType) ? eventType : EventData.EVENT_MESSAGE;
EventData eventData = new EventData(requestId, null, eventType, chatConversation.getId(), topicId);
EventMessageData messageEventData = EventMessageData.builder().message(resMessage).build();
eventData.setData(messageEventData);
eventData.setRequestId(requestId);
// sse
SseEmitter emitter = AiragLocalCache.get(AiragConsts.CACHE_TYPE_SSE, requestId);
if (null == emitter) {
log.warn("[AI应用]接收LLM返回会话已关闭");
return;
}
sendMessage2Client(emitter, eventData);
};
// 解析是否显示工具调用过程默认为true
boolean showToolProcess = true;
String appMetadataStr = chatConversation.getApp().getMetadata();
if (oConvertUtils.isNotEmpty(appMetadataStr)) {
try {
JSONObject appMetadataJson = JSONObject.parseObject(appMetadataStr);
if (appMetadataJson != null && "0".equals(appMetadataJson.getString("showToolProcess"))) {
showToolProcess = false;
}
} catch (Exception ignored) {
}
}
final boolean finalShowToolProcess = showToolProcess;
/**
* 是否正在思考
*/
@@ -1301,22 +1538,19 @@ public class AiragChatServiceImpl implements IAiragChatService {
isThinking.set(false);
}
//update-end---author:wangshuai---date:2025-11-07---for:[issues/8506]/[issues/8260]/[issues/8166]新增推理模型的支持---
EventData eventData = new EventData(requestId, null, EventData.EVENT_MESSAGE, chatConversation.getId(), topicId);
EventMessageData messageEventData = EventMessageData.builder().message(resMessage).build();
eventData.setData(messageEventData);
eventData.setRequestId(requestId);
// sse
SseEmitter emitter = AiragLocalCache.get(AiragConsts.CACHE_TYPE_SSE, requestId);
if (null == emitter) {
log.warn("[AI应用]接收LLM返回会话已关闭");
return;
send2Client.accept(resMessage, EventData.EVENT_MESSAGE);
}).beforeToolExecution(beforeToolExecution -> {
// 监听工具执行请求(根据配置决定是否发送给前端)
if (finalShowToolProcess) {
ToolExecutionVo vo = ToolExecutionVo.build(beforeToolExecution);
String execTag = JeecgTagHelper.createTag(JeecgTagHelper.TAG_JEECG_TOOL_EXEC, JSON.toJSONString(vo));
send2Client.accept(execTag, EventData.EVENT_TOOL_EXEC_BEFORE);
}
sendMessage2Client(emitter, eventData);
}).onToolExecuted((toolExecution) -> {
// 打印工具执行结果
log.debug("[AI应用]工具执行结果: toolName={}, toolId={}, result={}",
toolExecution.request().name(),
toolExecution.request().id(),
toolExecution.request().name(),
toolExecution.request().id(),
toolExecution.result());
// 将工具执行结果存储到消息历史中
ToolExecutionResultMessage toolResultMessage = ToolExecutionResultMessage.from(
@@ -1324,6 +1558,13 @@ public class AiragChatServiceImpl implements IAiragChatService {
toolExecution.result()
);
appendMessage(messages, toolResultMessage, chatConversation, topicId);
// 根据配置决定是否将工具调用过程发送给前端
if (finalShowToolProcess) {
ToolExecutionVo vo = ToolExecutionVo.build(toolExecution);
String execTag = JeecgTagHelper.createTag(JeecgTagHelper.TAG_JEECG_TOOL_EXEC, JSON.toJSONString(vo));
send2Client.accept(execTag, EventData.EVENT_TOOL_EXEC_DONE);
send2Client.accept(execTag, EventData.EVENT_MESSAGE);
}
}).onIntermediateResponse((chatResponse) -> {
// 中间响应包含tool_calls的AI消息
AiMessage aiMessage = chatResponse.aiMessage();
@@ -1422,14 +1663,20 @@ public class AiragChatServiceImpl implements IAiragChatService {
//update-end---author:chenrui ---date:20250425 for[QQYUN-12203]AI 聊天,超时或者服务器报错,给个友好提示------------
} else {
errMsg = "调用大模型接口失败,详情请查看后台日志。";
boolean isFindErrorMsg = false;
// 根据常见异常关键字做细致翻译
for (Map.Entry<String, String> entry : AIChatHandler.MODEL_ERROR_MAP.entrySet()) {
String key = entry.getKey();
String value = entry.getValue();
if (error.getMessage().contains(key)) {
errMsg = value;
isFindErrorMsg = true;
}
}
String message = error.getMessage();
if(!isFindErrorMsg && message.contains("error")) {
errMsg = JSONObject.parseObject(message).get("error").toString();
}
EventData eventData = new EventData(requestId, null, EventData.EVENT_FLOW_ERROR, chatConversation.getId(), topicId);
eventData.setData(EventFlowData.builder().success(false).message(errMsg).build());
closeSSE(emitter, eventData);
@@ -1693,29 +1940,87 @@ public class AiragChatServiceImpl implements IAiragChatService {
/**
* ai海报生成
*
* @param chatSendParams
* @param aiDrawGenerateVo
* @return
*/
@Override
public String genAiPoster(ChatSendParams chatSendParams) {
AssertUtils.assertNotEmpty("请选择绘画模型", chatSendParams.getDrawModelId());
AssertUtils.assertNotEmpty("请填写提示词", chatSendParams.getContent());
public String genAiPoster(AiDrawGenerateVo aiDrawGenerateVo) {
AssertUtils.assertNotEmpty("请选择绘画模型", aiDrawGenerateVo.getDrawModelId());
AssertUtils.assertNotEmpty("请填写提示词", aiDrawGenerateVo.getContent());
AIChatParams aiChatParams = new AIChatParams();
if(oConvertUtils.isNotEmpty(chatSendParams.getImageSize())){
aiChatParams.setImageSize(chatSendParams.getImageSize());
//update-begin---author:wangshuai---date:2026-02-05---for:【QQYUN-14568】AI绘画功能---
if(oConvertUtils.isNotEmpty(aiDrawGenerateVo.getImageSize())){
aiChatParams.setImageSize(aiDrawGenerateVo.getImageSize());
}
String image= chatSendParams.getImageUrl();
//aiChatParams.setNegativePrompt("面部扭曲,特征丢失,边缘模糊,比例失调,模糊,多余的手指");
//绘图
if(AiAppConsts.AI_DRAW_TYPE_DRAW.equals(aiDrawGenerateVo.getType())){
String format = StrUtil.format(Prompts.AI_DRAW_PROMPT, aiDrawGenerateVo.getStyle(), aiDrawGenerateVo.getVisualAngle(), aiDrawGenerateVo.getCharacterShot(), aiDrawGenerateVo.getLighting(), ImageSizeEnum.getRatioBySize(aiDrawGenerateVo.getImageSize()));
aiDrawGenerateVo.setContent(format + aiDrawGenerateVo.getContent());
}
if((AiAppConsts.AI_DRAW_TYPE_FACE.equals(aiDrawGenerateVo.getType()) || AiAppConsts.AI_DRAW_TYPE_MIX.equals(aiDrawGenerateVo.getType())) && oConvertUtils.isNotEmpty(aiDrawGenerateVo.getImageSize())){
aiDrawGenerateVo.setContent(aiDrawGenerateVo.getContent() + "比例:" + ImageSizeEnum.getRatioBySize(aiDrawGenerateVo.getImageSize()));
}
String image= aiDrawGenerateVo.getImageUrl();
//update-end---author:wangshuai---date:2026-02-05---for:【QQYUN-14568】AI绘画功能---
List<Map<String, Object>> imageList = new ArrayList<>();
if(oConvertUtils.isEmpty(image)) {
//生成图片
imageList = aiChatHandler.imageGenerate(chatSendParams.getDrawModelId(), chatSendParams.getContent(), aiChatParams);
imageList = aiChatHandler.imageGenerate(aiDrawGenerateVo.getDrawModelId(), aiDrawGenerateVo.getContent(), aiChatParams);
} else {
//图生图
imageList = aiChatHandler.imageEdit(chatSendParams.getDrawModelId(), chatSendParams.getContent(), Arrays.asList(image.split(SymbolConstant.COMMA)), aiChatParams);
imageList = aiChatHandler.imageEdit(aiDrawGenerateVo.getDrawModelId(), aiDrawGenerateVo.getContent(), Arrays.asList(image.split(SymbolConstant.COMMA)), aiChatParams);
}
return imageList.stream().map(this::uploadImage).collect(Collectors.joining("\n"));
}
//update-begin---author:wangshuai ---date:2026-04-15 for【QQYUN-14568】AI海报生成改为异步支持切换菜单后重新获取结果-----------
@Override
public String genAiPosterAsync(AiDrawGenerateVo aiDrawGenerateVo) {
AssertUtils.assertNotEmpty("请选择绘画模型", aiDrawGenerateVo.getDrawModelId());
AssertUtils.assertNotEmpty("请填写提示词", aiDrawGenerateVo.getContent());
String taskId = java.util.UUID.randomUUID().toString().replace("-", "");
// 写入 pending 状态
JSONObject task = new JSONObject();
task.put("status", "pending");
redisUtil.set(AiAppConsts.POSTER_TASK_PREFIX + taskId, task.toJSONString(), AiAppConsts.POSTER_TASK_TTL);
// 异步执行生成
SSE_THREAD_POOL.execute(() -> {
JSONObject result = new JSONObject();
try {
String imageUrl = genAiPoster(aiDrawGenerateVo);
result.put("status", "success");
result.put("imageUrl", imageUrl);
} catch (Exception e) {
log.error("[AI海报]异步生成失败 taskId={}", taskId, e);
result.put("status", "failed");
result.put("message", e.getMessage());
}
redisUtil.set(AiAppConsts.POSTER_TASK_PREFIX + taskId, result.toJSONString(), AiAppConsts.POSTER_TASK_TTL);
});
return taskId;
}
@Override
public Result<?> getAiPosterResult(String taskId) {
Object val = redisUtil.get(AiAppConsts.POSTER_TASK_PREFIX + taskId);
if (val == null) {
return Result.error("任务不存在或已过期");
}
JSONObject task = JSONObject.parseObject(val.toString());
String status = task.getString("status");
if ("success".equals(status)) {
return Result.OK(task.getString("imageUrl"));
}
if ("failed".equals(status)) {
return Result.error(task.getString("message"));
}
// pending
return Result.OK("pending", null);
}
//update-end---author:wangshuai ---date:2026-04-15 for【QQYUN-14568】AI海报生成改为异步支持切换菜单后重新获取结果-----------
/**
* 上传图片
*
@@ -1738,6 +2043,13 @@ public class AiragChatServiceImpl implements IAiragChatService {
data = Base64.getDecoder().decode(value);
} else {
//下载网络图片
//update-begin---author:zhangdaihao ---date:20260427 for[issues/9579]AI海报图片下载 SSRF 校验,拒绝 loopback/link-local------------
// genAiPoster -> uploadImage -> getDownInputStream攻击者可通过 imageUrl 触发服务端访问 localhost / 云元数据等敏感目标;
// 沿用与 #9553 一致的基础 SSRF 校验(拒绝 loopback / link-local保留对企业内网 MinIO/OSS 的兼容。
if (oConvertUtils.isNotEmpty(value) && value.toLowerCase().startsWith("http")) {
SsrfFileTypeFilter.checkSsrfHttpUrl(value);
}
//update-end-----author:zhangdaihao ---date:20260427 for[issues/9579]AI海报图片下载 SSRF 校验,拒绝 loopback/link-local------------
InputStream inputStream = FileDownloadUtils.getDownInputStream(value, "");
if (inputStream != null) {
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
@@ -1796,7 +2108,7 @@ public class AiragChatServiceImpl implements IAiragChatService {
* @return
*/
private String parseFilesToText(List<String> files) {
if (com.baomidou.mybatisplus.core.toolkit.CollectionUtils.isEmpty(files)) {
if (CollectionUtils.isEmpty(files)) {
return "";
}
StringBuilder sb = new StringBuilder();
@@ -1855,16 +2167,37 @@ public class AiragChatServiceImpl implements IAiragChatService {
private File ensureLocalFile(String fileRef, String fileName) {
String uploadpath = jeecgBaseConfig.getPath().getUpload();
if (LLMConsts.WEB_PATTERN.matcher(fileRef).matches()) {
//update-begin---author:wangshuai ---date:2026-04-13 for【issues/9519】AI附件处理路径遍历漏洞下载文件名做安全过滤临时目录隔离---
// 远程下载:使用 FilenameUtils.getName 剥离任何路径分隔符,再次校验防止 ..
String safeFileName = FilenameUtils.getName(fileName);
SsrfFileTypeFilter.checkPathTraversal(safeFileName);
//update-end---author:wangshuai ---date:2026-04-13 for【issues/9519】AI附件处理路径遍历漏洞下载文件名做安全过滤临时目录隔离---
String tempDir = uploadpath + File.separator + "chat" + File.separator + UUID.randomUUID() + File.separator;
File dir = new File(tempDir);
if (!dir.exists() && !dir.mkdirs()) {
return null;
}
String tempFilePath = tempDir + fileName;
String tempFilePath = tempDir + safeFileName;
//update-begin---author:zhangdaihao ---date:20260427 for[issues/9578]AI附件下载 SSRF 校验,拒绝 loopback/link-local------------
// /airag/chat/send 端点为 @IgnoreAuth 无认证AI 聊天解析附件存在 SSRF 风险;
// 沿用与 #9553 一致的基础 SSRF 校验(拒绝 loopback / link-local保留对企业内网 MinIO/OSS 的兼容。
SsrfFileTypeFilter.checkSsrfHttpUrl(fileRef);
//update-end-----author:zhangdaihao ---date:20260427 for[issues/9578]AI附件下载 SSRF 校验,拒绝 loopback/link-local------------
FileDownloadUtils.download2DiskFromNet(fileRef, tempFilePath);
return new File(tempFilePath);
}
return new File(uploadpath + File.separator + fileRef);
//update-begin---author:wangshuai ---date:2026-04-13 for【issues/9519】AI附件处理路径遍历漏洞规范化路径并强制校验沙箱范围---
// 本地附件1) 先做字符级路径遍历检查2) 规范化路径后必须仍在 uploadpath 下,阻止 ../ 逃逸
java.nio.file.Path root = Paths.get(uploadpath).toAbsolutePath().normalize();
SsrfFileTypeFilter.checkPathTraversal(fileRef);
String relativePath = fileRef.replaceAll("^[\\\\/]+", "");
java.nio.file.Path target = root.resolve(relativePath).toAbsolutePath().normalize();
if (!target.startsWith(root)) {
log.error("检测到路径遍历攻击! fileRef: {}, 解析后: {}", relativePath, target);
throw new JeecgBootException("文件路径包含非法字符");
}
return target.toFile();
//update-end---author:wangshuai ---date:2026-04-13 for【issues/9519】AI附件处理路径遍历漏洞规范化路径并强制校验沙箱范围---
}
//================================================= end【QQYUN-14261】【AI】AI助手支持多模态能力- 文档========================================
@@ -1887,7 +2220,9 @@ public class AiragChatServiceImpl implements IAiragChatService {
content = StrUtil.format(Prompts.AI_WRITER_PROMPT, aiWriteGenerateVo.getPrompt(), aiWriteGenerateVo.getFormat(), aiWriteGenerateVo.getTone(), aiWriteGenerateVo.getLanguage(), aiWriteGenerateVo.getLength());
} else if(reply.equals(aiWriteGenerateVo.getActiveMode())){
//回复
content = StrUtil.format(Prompts.AI_REPLY_PROMPT, aiWriteGenerateVo.getPrompt(), aiWriteGenerateVo.getOriginalContent(), aiWriteGenerateVo.getFormat(), aiWriteGenerateVo.getTone(), aiWriteGenerateVo.getLanguage(), aiWriteGenerateVo.getLength());
//update-begin---author:wangshuai ---date:2026-04-20 for【QQYUN-15179】ai写作 生成的内容不对,应该是以回复来生成,而不是内容-----------
content = StrUtil.format(Prompts.AI_REPLY_PROMPT, aiWriteGenerateVo.getOriginalContent(), aiWriteGenerateVo.getPrompt(), aiWriteGenerateVo.getFormat(), aiWriteGenerateVo.getTone(), aiWriteGenerateVo.getLanguage(), aiWriteGenerateVo.getLength());
//update-end---author:wangshuai ---date:2026-04-20 for【QQYUN-15179】ai写作 生成的内容不对,应该是以回复来生成,而不是内容-----------
} else {
content = StrUtil.format(Prompts.AI_TOUCHE_PROMPT, aiWriteGenerateVo.getPrompt(), aiWriteGenerateVo.getFormat(), aiWriteGenerateVo.getTone(), aiWriteGenerateVo.getLanguage(), aiWriteGenerateVo.getLength());
}

View File

@@ -3,6 +3,7 @@ package org.jeecg.modules.airag.app.service.impl;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import dev.langchain4j.agent.tool.ToolSpecification;
import dev.langchain4j.model.chat.request.json.JsonArraySchema;
import dev.langchain4j.model.chat.request.json.JsonObjectSchema;
import dev.langchain4j.service.tool.ToolExecutor;
import lombok.extern.slf4j.Slf4j;
@@ -53,6 +54,24 @@ public class AiragVariableServiceImpl implements IAiragVariableService {
redisTemplate.opsForHash().putIfAbsent(key, name, defaultValue != null ? defaultValue : "");
}
/**
* 获取变量值
*
* @param username 用户名
* @param appId 应用ID
* @param name 变量名
* @return 变量值不存在返回null
*/
@Override
public String getVariable(String username, String appId, String name) {
if (oConvertUtils.isEmpty(username) || oConvertUtils.isEmpty(appId) || oConvertUtils.isEmpty(name)) {
return null;
}
String key = CACHE_PREFIX + appId + ":" + username;
Object value = redisTemplate.opsForHash().get(key, name);
return value != null ? String.valueOf(value) : null;
}
/**
* 追加提示词
*
@@ -147,7 +166,9 @@ public class AiragVariableServiceImpl implements IAiragVariableService {
}
//工具描述
StringBuilder descriptionBuilder = new StringBuilder("更新应用变量的值。仅当检测到变量的新值与当前值不一致时调用。如果已调用过或值未变,请勿重复调用。");
//update-begin---author:wangshuai ---date:2026-04-21 for【AI变量】支持批量更新变量返回结构化结果避免LLM重复调用-----------
StringBuilder descriptionBuilder = new StringBuilder("批量更新应用变量的值。请将本次对话中所有需要更新的变量一次性传入updates数组无需多次调用。仅当变量新值与当前值确实不同时才调用本工具。");
//update-end---author:wangshuai ---date:2026-04-21 for【AI变量】支持批量更新变量返回结构化结果避免LLM重复调用-----------
if (variableList != null && !variableList.isEmpty()) {
descriptionBuilder.append("\n\n可用变量列表");
for (AppVariableVo var : variableList) {
@@ -159,17 +180,30 @@ public class AiragVariableServiceImpl implements IAiragVariableService {
descriptionBuilder.append(": ").append(var.getDescription());
}
}
descriptionBuilder.append("\n\n注意variableName必须是上述列表中的名称之一。");
//update-begin---author:wangshuai ---date:2026-04-21 for【AI变量】支持批量更新变量返回结构化结果避免LLM重复调用-----------
descriptionBuilder.append("\n\n注意variableName必须是上述列表中的名称之一且本工具每轮对话只需调用一次。");
//update-end---author:wangshuai ---date:2026-04-21 for【AI变量】支持批量更新变量返回结构化结果避免LLM重复调用-----------
}
// A: 参数改为批量数组,一次可更新多个变量
JsonObjectSchema itemSchema = JsonObjectSchema.builder()
.addStringProperty("variableName", "变量名称(必须是可用变量列表中的名称之一)")
.addStringProperty("value", "变量新值")
.required("variableName", "value")
.build();
//构建更新变量的工具
ToolSpecification spec = ToolSpecification.builder()
.name("update_variable")
.description(descriptionBuilder.toString())
.parameters(JsonObjectSchema.builder()
.addStringProperty("variableName", "变量名称")
.addStringProperty("value", "变量值")
.required("variableName", "value")
//update-begin---author:wangshuai ---date:2026-04-21 for【AI变量】支持批量更新变量返回结构化结果避免LLM重复调用-----------
.addProperty("updates", JsonArraySchema.builder()
.description("需要更新的变量列表,可包含多个变量")
.items(itemSchema)
.build())
.required("updates")
//update-end---author:wangshuai ---date:2026-04-21 for【AI变量】支持批量更新变量返回结构化结果避免LLM重复调用-----------
.build())
.build();
@@ -177,15 +211,38 @@ public class AiragVariableServiceImpl implements IAiragVariableService {
ToolExecutor executor = (toolExecutionRequest, memoryId) -> {
try {
JSONObject args = JSONObject.parseObject(toolExecutionRequest.arguments());
String name = args.getString("variableName");
String value = args.getString("value");
JSONArray updates = args.getJSONArray("updates");
IAiragVariableService variableService = SpringContextUtils.getBean(IAiragVariableService.class);
//更新变量值
variableService.updateVariable(username, aiApp.getId(), name, value);
return "变量 " + name + " 已更新为: " + value;
//update-begin---author:wangshuai ---date:2026-04-21 for【AI变量】支持批量更新变量返回结构化结果避免LLM重复调用-----------
// B: 返回结构化JSONLLM可明确感知"已全部完成"
JSONObject updatedMap = new JSONObject();
if (updates != null) {
for (int i = 0; i < updates.size(); i++) {
JSONObject item = updates.getJSONObject(i);
String name = item.getString("variableName");
String value = item.getString("value");
if (oConvertUtils.isNotEmpty(name)) {
variableService.updateVariable(username, aiApp.getId(), name, value);
updatedMap.put(name, value);
}
}
}
JSONObject result = new JSONObject();
result.put("success", true);
result.put("updated", updatedMap);
result.put("count", updatedMap.size());
result.put("message", "已成功更新 " + updatedMap.size() + " 个变量,无需再次调用");
return result.toJSONString();
//update-end---author:wangshuai ---date:2026-04-21 for【AI变量】支持批量更新变量返回结构化结果避免LLM重复调用-----------
} catch (Exception e) {
log.error("更新变量失败", e);
return "更新变量失败: " + e.getMessage();
//update-begin---author:wangshuai ---date:2026-04-21 for【AI变量】支持批量更新变量返回结构化结果避免LLM重复调用-----------
JSONObject error = new JSONObject();
error.put("success", false);
error.put("message", "更新变量失败: " + e.getMessage());
return error.toJSONString();
//update-end---author:wangshuai ---date:2026-04-21 for【AI变量】支持批量更新变量返回结构化结果避免LLM重复调用-----------
}
};

View File

@@ -0,0 +1,58 @@
package org.jeecg.modules.airag.app.vo;
import lombok.Data;
/**
* @Description: AI绘画
*
* @author: wangshuai
* @date: 2026/2/4 18:57
*/
@Data
public class AiDrawGenerateVo {
/**
* 绘画模型的id
*/
private String drawModelId;
/**
* 图片尺寸
*/
private String imageSize;
/**
* 一张图片或者多张图片,多张图片用逗号分隔
*/
private String imageUrl;
/**
* 用户输入的聊天内容
*/
private String content;
/**
* 风格
*/
private String style;
/**
* 视角
*/
private String visualAngle;
/**
* 人物镜头
*/
private String characterShot;
/**
* 灯光
*/
private String lighting;
/**
* 类型 poster: 海报draw绘图face 换脸mix 混图
*/
private String type;
}

View File

@@ -88,11 +88,52 @@ public class LLMConsts {
*/
public static final String KNOWLEDGE_DOC_METADATA_SOURCES_PATH = "sourcesPath";
/**
* 知识库:文档元数据:网页URL
*/
public static final String KNOWLEDGE_DOC_METADATA_WEBSITE = "website";
/**
* DEEPSEEK推理模型
*/
public static final String DEEPSEEK_REASONER = "deepseek-reasoner";
//update-begin---author:scott ---date:20260429 for[issues/9585]DeepSeek大模型切换为新发布deepseek-v4-flash流程中调用出现异常------------
/**
* DEEPSEEK 推理模型(返回 reasoning_content 字段、在多轮工具调用中要求把 reasoning_content 回传)集合,
* 后续 DeepSeek 新增推理模型时在此追加;非推理模型(如 deepseek-chat)不要加入。
* 触发场景:仅当对话存在工具调用导致的多轮请求时才会出现 "reasoning_content must be passed back" 错误,
* 单轮 Q&A(如 AI 应用聊天无工具)不会触发,但开启 sendThinking 也无副作用。
*/
public static final Set<String> DEEPSEEK_THINKING_MODELS = new HashSet<>(Arrays.asList(
"deepseek-reasoner",
"deepseek-v4-flash",
"deepseek-v4-pro"
));
/**
* 判断指定模型名是否为 DeepSeek 推理模型(返回 reasoning_content 字段)
* 匹配规则:先做大小写不敏感的精确匹配,再做关键字包含匹配(reasoner/v4-flash/v4-pro)
* 以兼容带版本后缀的变体(如 deepseek-v4-flash-0428)
*
* @param modelName 模型名(大小写不敏感、首尾空白容错)
* @return true=推理模型false=非推理模型或空
*/
public static boolean isDeepSeekThinkingModel(String modelName) {
if (modelName == null || modelName.trim().isEmpty()) {
return false;
}
String name = modelName.trim().toLowerCase();
if (DEEPSEEK_THINKING_MODELS.contains(name)) {
return true;
}
// 兼容带版本后缀或厂商前缀的变体
return name.contains("reasoner")
|| name.contains("v4-flash")
|| name.contains("v4-pro");
}
//update-end---author:scott ---date:20260429 for[issues/9585]DeepSeek大模型切换为新发布deepseek-v4-flash流程中调用出现异常------------
/**
* 知识库类型:知识库
*/
@@ -118,4 +159,63 @@ public class LLMConsts {
*/
public static final int CHAT_FILE_MAX_COUNT = 3;
/**
* 知识库是否开启默认分段策略
*/
public static final String ENABLE_SEGMENT = "enableSegment";
/**
* 文档分段策略:使用知识库默认分段策略
*/
public static final String USE_KNOWLEDGE_DEFAULT = "useKnowledgeDefault";
/**
* 分段策略
*/
public static final String SEGMENT_STRATEGY = "segmentStrategy";
/**
* 分段策略auto 自动分段与清洗
*/
public static final String SEGMENT_STRATEGY_AUTO = "auto";
/**
* 分段策略custom 自定义
*/
public static final String SEGMENT_STRATEGY_CUSTOM = "custom";
/**
* 分段长度
*/
public static final String MAX_SEGMENT = "maxSegment";
/**
* 重叠率 0-90%
*/
public static final String OVERLAP = "overlap";
/**
* 分段标识符(\\n:换行,\\n\\n:2个换行。:中文句号,!:中文叹号,?:中文问号,. :英文句号,! :英文叹号,? :英文问号custom:自定义)
*/
public static final String SEPARATOR = "separator";
/**
* 分段标识符自定义
*/
public static final String CUSTOM_SEPARATOR = "customSeparator";
/**
* 文本预处理规则cleanSpaces替换掉连续的空格、换行符和制表符removeUrlsEmails删除所有 URL 和电子邮箱地址)
*/
public static final String TEXT_RULES = "textRules";
/**
* 替换掉连续的空格、换行符和制表符
*/
public static final String TEXT_RULES_CLEAN_SPACES = "cleanSpaces";
/**
* 删除所有URL和电子邮箱地址
*/
public static final String TEXT_RULES_REMOVE_URLS_EMAILS = "removeUrlsEmails";
}

View File

@@ -1,7 +1,7 @@
package org.jeecg.modules.airag.llm.controller;
import org.jeecg.common.airag.api.IAiragBaseApi;
import org.jeecg.modules.airag.llm.service.impl.AiragBaseApiImpl;
import org.jeecg.modules.airag.api.AiragBaseApiImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
@@ -23,9 +23,39 @@ public class AiragBaseApiController implements IAiragBaseApi {
public String knowledgeWriteTextDocument(
@RequestParam("knowledgeId") String knowledgeId,
@RequestParam("title") String title,
@RequestParam("content") String content
@RequestParam("content") String content,
@RequestParam(value = "segmentConfig", required = false) String segmentConfig
) {
return airagBaseApi.knowledgeWriteTextDocument(knowledgeId, title, content);
return airagBaseApi.knowledgeWriteTextDocument(knowledgeId, title, content, segmentConfig);
}
@PostMapping("/airag/api/getChatVariable")
public String getChatVariable(
@RequestParam("appId") String appId,
@RequestParam("username") String username,
@RequestParam("name") String name
) {
return airagBaseApi.getChatVariable(appId, username, name);
}
@PostMapping("/airag/api/setChatVariable")
public void setChatVariable(
@RequestParam("appId") String appId,
@RequestParam("username") String username,
@RequestParam("name") String name,
@RequestParam("value") String value
) {
airagBaseApi.setChatVariable(appId, username, name, value);
}
@PostMapping("/airag/api/getMemoryIdByAppId")
public String getMemoryIdByAppId(@RequestParam("appId") String appId) {
return airagBaseApi.getMemoryIdByAppId(appId);
}
@PostMapping("/airag/api/getPromptContent")
public String getPromptContent(@RequestParam("promptId") String promptId) {
return airagBaseApi.getPromptContent(promptId);
}
}

View File

@@ -8,6 +8,7 @@ import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.system.base.controller.JeecgController;
import org.jeecg.common.system.query.QueryGenerator;
@@ -42,6 +43,7 @@ public class AiragMcpController extends JeecgController<AiragMcp, IAiragMcpServi
* @return
*/
@Operation(summary = "MCP-分页列表查询")
@RequiresPermissions("airag:mcp:list")
@GetMapping(value = "/list")
public Result<IPage<AiragMcp>> queryPageList(AiragMcp airagMcp,
@RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo,
@@ -61,6 +63,7 @@ public class AiragMcpController extends JeecgController<AiragMcp, IAiragMcpServi
* @return
*/
@Operation(summary = "MCP-保存")
@RequiresPermissions("airag:mcp:save")
@PostMapping(value = "/save")
public Result<String> save(@RequestBody AiragMcp airagMcp) {
return airagMcpService.edit(airagMcp);
@@ -77,6 +80,7 @@ public class AiragMcpController extends JeecgController<AiragMcp, IAiragMcpServi
* @date 2025/10/21 10:54
*/
@Operation(summary = "MCP-保存并同步")
@RequiresPermissions("airag:mcp:save")
@PostMapping(value = "/saveAndSync")
public Result<?> saveAndSync(@RequestBody AiragMcp airagMcp) {
Result<String> saveResult = airagMcpService.edit(airagMcp);
@@ -99,6 +103,7 @@ public class AiragMcpController extends JeecgController<AiragMcp, IAiragMcpServi
* @date 2025/10/20 20:09
*/
@Operation(summary = "MCP-同步MCP信息")
@RequiresPermissions("airag:mcp:save")
@PostMapping(value = "/sync/{id}")
public Result<?> sync(@PathVariable(name = "id", required = true) String id) {
return airagMcpService.sync(id);
@@ -114,6 +119,7 @@ public class AiragMcpController extends JeecgController<AiragMcp, IAiragMcpServi
* @date 2025/10/20 20:13
*/
@Operation(summary = "MCP-启用/禁用MCP信息")
@RequiresPermissions("airag:mcp:save")
@PostMapping(value = "/status/{id}/{action}")
public Result<?> toggleStatus(@PathVariable(name = "id",required = true) String id,
@PathVariable(name = "action", required = true) String action) {
@@ -129,6 +135,7 @@ public class AiragMcpController extends JeecgController<AiragMcp, IAiragMcpServi
* @date 2025/10/30
*/
@Operation(summary = "MCP-保存插件工具")
@RequiresPermissions("airag:mcp:save")
@PostMapping(value = "/saveTools")
public Result<String> saveTools(@RequestBody SaveToolsDTO dto) {
return airagMcpService.saveTools(dto.getId(), dto.getTools());
@@ -141,6 +148,7 @@ public class AiragMcpController extends JeecgController<AiragMcp, IAiragMcpServi
* @return
*/
@Operation(summary = "MCP-通过id删除")
@RequiresPermissions("airag:mcp:delete")
@DeleteMapping(value = "/delete")
public Result<String> delete(@RequestParam(name = "id", required = true) String id) {
airagMcpService.removeById(id);
@@ -154,6 +162,7 @@ public class AiragMcpController extends JeecgController<AiragMcp, IAiragMcpServi
* @return
*/
@Operation(summary = "MCP-通过id查询")
//@RequiresPermissions("airag:mcp:queryById")
@GetMapping(value = "/queryById")
public Result<AiragMcp> queryById(@RequestParam(name = "id", required = true) String id) {
AiragMcp airagMcp = airagMcpService.getById(id);
@@ -169,7 +178,7 @@ public class AiragMcpController extends JeecgController<AiragMcp, IAiragMcpServi
* @param request
* @param airagMcp
*/
// @RequiresPermissions("llm:airag_mcp:exportXls")
@RequiresPermissions("airag:mcp:export")
@RequestMapping(value = "/exportXls")
public ModelAndView exportXls(HttpServletRequest request, AiragMcp airagMcp) {
return super.exportXls(request, airagMcp, AiragMcp.class, "MCP");
@@ -182,7 +191,7 @@ public class AiragMcpController extends JeecgController<AiragMcp, IAiragMcpServi
* @param response
* @return
*/
// @RequiresPermissions("llm:airag_mcp:importExcel")
@RequiresPermissions("airag:mcp:import")
@RequestMapping(value = "/importExcel", method = RequestMethod.POST)
public Result<?> importExcel(HttpServletRequest request, HttpServletResponse response) {
return super.importExcel(request, response, AiragMcp.class);

View File

@@ -17,6 +17,7 @@ import org.jeecg.common.util.AssertUtils;
import org.jeecg.common.util.TokenUtils;
import org.jeecg.common.util.oConvertUtils;
import org.jeecg.config.mybatis.MybatisPlusSaasConfig;
import org.jeecg.modules.airag.app.enums.ImageEditEnum;
import org.jeecg.modules.airag.common.handler.AIChatParams;
import org.jeecg.modules.airag.llm.consts.LLMConsts;
import org.jeecg.modules.airag.llm.entity.AiragModel;
@@ -29,7 +30,9 @@ import org.springframework.web.servlet.ModelAndView;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.util.Arrays;
import java.util.ArrayList;
import java.util.List;
import java.util.Collections;
/**
@@ -82,8 +85,6 @@ public class AiragModelController extends JeecgController<AiragModel, IAiragMode
// 默认未激活
if(oConvertUtils.isObjectEmpty(airagModel.getActivateFlag())){
airagModel.setActivateFlag(0);
} else {
airagModel.setActivateFlag(1);
}
airagModelService.save(airagModel);
return Result.OK("添加成功!");
@@ -170,6 +171,8 @@ public class AiragModelController extends JeecgController<AiragModel, IAiragMode
AssertUtils.assertNotEmpty("模型名称不能为空", airagModel.getName());
AssertUtils.assertNotEmpty("模型类型不能为空", airagModel.getModelType());
AssertUtils.assertNotEmpty("基础模型不能为空", airagModel.getModelName());
//测试连接默认为已激活状态
airagModel.setActivateFlag(1);
try {
if(LLMConsts.MODEL_TYPE_LLM.equals(airagModel.getModelType())){
aiChatHandler.completions(airagModel, Collections.singletonList(UserMessage.from("To test whether it can be successfully called, simply return success")), null);
@@ -180,7 +183,16 @@ public class AiragModelController extends JeecgController<AiragModel, IAiragMode
//update-begin---author:wangshuai---date:2026-01-07---for:【QQYUN-12145】【AI】AI 绘画创作---=
}else if(LLMConsts.MODEL_TYPE_IMAGE.equals(airagModel.getModelType())){
AIChatParams aiChatParams = new AIChatParams();
aiChatHandler.imageGenerate(airagModel, "To test whether it can be successfully called, simply return success", aiChatParams);
//update-begin---author:wangshuai---date:2026-03-02---for:兼容图生图模型测试---
String modelName = airagModel.getModelName();
if(ImageEditEnum.isImageEditModel(modelName)){
List<String> images = new ArrayList<>();
images.add("https://jeecgdev.oss-cn-beijing.aliyuncs.com/upload/test/jeecg_1772268161540.jpg");
aiChatHandler.imageEdit(airagModel, "Generate a picture of a cartoon cat", images,aiChatParams);
}else{
aiChatHandler.imageGenerate(airagModel, "Generate a picture of a cartoon cat", aiChatParams);
}
//update-end---author:wangshuai---date:2026-03-02---for:兼容图生图模型测试---
}
//update-end---author:wangshuai---date:2026-01-07---for:【QQYUN-12145】【AI】AI 绘画创作---
}catch (Exception e){

Some files were not shown because too many files have changed in this diff Show More