Compare commits

..
Author SHA1 Message Date
疯狂的狮子Li ba24afce52 !131 ♥️发布 vue 版本 5.2.1 与 cloud 版本 2.2.0
Merge pull request !131 from 疯狂的狮子Li/dev
2024-07-09 03:02:34 +00:00
疯狂的狮子Li 93d3371768 ♥️发布 vue 版本 5.2.1 与 cloud 版本 2.2.0 2024-07-09 10:53:49 +08:00
疯狂的狮子Li 3f08ae6ac4 fix 修复 富文本编辑器 添加之后内容未清理问题 2024-07-02 16:51:03 +08:00
疯狂的狮子Li cc6284d3ac fix 修复 字段命名错误 2024-07-01 12:52:19 +08:00
疯狂的狮子Li 142effd4f2 !130 feat: 动态创建组件实例时, 设置路由name为组件名 解决缓存问题
Merge pull request !130 from 玲娜贝er/dev
2024-06-30 08:13:16 +00:00
dap e657a507e3 feat: 动态创建组件实例时, 设置路由name为组件名 解决缓存问题 2024-06-30 10:50:04 +08:00
疯狂的狮子Li ebaec24213 update 优化 eslint 2024-06-28 10:44:13 +08:00
疯狂的狮子Li 7637582437 update 优化 eslint 2024-06-28 10:18:26 +08:00
疯狂的狮子Li 27d36f7970 !129 feat: 路由name重复检查
Merge pull request !129 from 玲娜贝er/dev
2024-06-26 04:02:28 +00:00
dap 762ebd4ede chore: 增加提示 2024-06-26 11:59:41 +08:00
dap ad991e248a feat: 路由name重复检查 2024-06-26 11:34:40 +08:00
疯狂的狮子Li d1b58f0aaa fix 修复 单词拼写错误 2024-06-24 14:59:46 +08:00
疯狂的狮子Li 1be1eaf7b4 !128 fix: 选人无法回显
Merge pull request !128 from 玲娜贝er/dev
2024-06-24 00:37:32 +00:00
dap fbcc967b14 fix: 由于没有await 导致执行顺序不可控 2024-06-24 08:21:19 +08:00
疯狂的狮子Li 817c65f7e2 !126 fix: 进入审批页面会多次加载用户列表和部门等接口 进入点击取消之后也会重新加载接口
Merge pull request !126 from 玲娜贝er/dev
2024-06-21 04:31:25 +00:00
张代鹏 b6dcc62f9c refactor: 改为懒加载窗口 2024-06-21 12:07:19 +08:00
疯狂的狮子Li abb4f543b9 !125 ♥️发布 vue 版本 5.2.0 与 cloud 版本 2.2.0
Merge pull request !125 from 疯狂的狮子Li/dev
2024-06-20 02:15:41 +00:00
疯狂的狮子Li 71f4d36c21 ♥️发布 vue 版本 5.2.0 与 cloud 版本 2.2.0 2024-06-20 10:15:08 +08:00
gssong d1be442c6e fix 修复选着人员错误问题 2024-06-19 21:13:58 +08:00
疯狂的狮子Li 9ef7fd3844 !123 "types": ["element-plus/global"]层级错误,且element-plus按需引入不用配置tsconfig.json
Merge pull request !123 from zl/修复tsconfig.json
2024-06-19 06:41:11 +00:00
疯狂的狮子Li fec61f9650 update 优化 clientid写死问题 2024-06-19 14:30:19 +08:00
疯狂的狮子Li c206ab5b4a update 优化 三方登录不同域名问题 采用新方案 2024-06-19 14:29:44 +08:00
疯狂的狮子Li fe1942c247 update 更换三方回调方案 2024-06-19 10:16:21 +08:00
疯狂的狮子Li 1f2add4b6b update 更换三方回调方案 2024-06-19 10:11:32 +08:00
疯狂的狮子Li 3b254cc16b update 增加 用户信息缓存增加租户id 2024-06-18 23:05:40 +08:00
疯狂的狮子Li 3e7c2f26fa update 增加 用户信息缓存增加租户id 2024-06-18 22:54:30 +08:00
疯狂的狮子Li 4143285ec6 fix 修复 缺少协议头问题 2024-06-18 19:08:51 +08:00
疯狂的狮子Li 72610ab194 update 优化 三方登录不同域名获取不到租户id问题 2024-06-18 18:44:27 +08:00
疯狂的狮子Li 3c713c9258 update element 2.7.2 => 2.7.5 2024-06-15 15:53:02 +08:00
gssong f95f6e8390 update 优化审批按钮判断 2024-06-07 21:38:17 +08:00
疯狂的狮子Li 2c9c837c1b update 优化 请假天数计算不精确问题 2024-06-06 17:27:50 +08:00
zl 7904496df1 层级错误,且element-plus按需引入不用配置tsconfig.json
Signed-off-by: zl <11656279+xbbzjsj@user.noreply.gitee.com>
2024-06-06 08:53:59 +00:00
疯狂的狮子Li 15c3d84ca2 !122 修复单词拼写错误
Merge pull request !122 from LiYaoheng/dev
2024-06-06 06:27:36 +00:00
LiYaoheng e8a641f3a3 fix 修复单词拼写错误 2024-06-06 14:19:55 +08:00
疯狂的狮子Li e354db74a7 !121 ♥️发布 2.2.0-BETA 公测版本
Merge pull request !121 from 疯狂的狮子Li/dev
2024-06-06 03:00:23 +00:00
疯狂的狮子Li 61df97c4b9 update 优化 标识符错误 2024-06-06 10:59:20 +08:00
疯狂的狮子Li 75ecc4dd68 update 更改 关于mq说明 2024-06-04 15:00:40 +08:00
songgaoshuai c467d95703 https://gitee.com/dromara/RuoYi-Cloud-Plus/issues/I9US1Q fix修复我的单据撤销,删除参数错误 2024-06-04 11:26:38 +08:00
gssong 3fead37924 add 添加流程记录版本信息 2024-06-03 21:33:12 +08:00
gssong c8626b6893 remove 删除无用参数 2024-06-03 21:23:32 +08:00
gssong 38df345078 update 调整流程图预览校验 2024-06-03 21:04:42 +08:00
疯狂的狮子Li 212361dc94 update 优化 去除请假案例状态字段 2024-06-03 17:53:49 +08:00
疯狂的狮子Li f237ee145a update 优化 去除请假案例状态字段 2024-06-03 15:47:51 +08:00
疯狂的狮子Li 291d4b0040 !120 update 调整注释错误
Merge pull request !120 from lu_ming/dev
2024-06-02 11:52:43 +00:00
can 64c56e9dd9 update 调整注释错误 2024-06-02 19:44:38 +08:00
gssong 57d87df589 update 调整驳回按钮加载 2024-06-02 00:21:47 +08:00
gssong 9de3f25f6a update 调整审批按钮加载 2024-06-01 22:05:45 +08:00
gssong d98c2822d5 update 调整路由 2024-06-01 22:00:22 +08:00
gssong 58e6fdef78 update 优化流程实例接口全部按照业务id操作 2024-05-31 22:11:25 +08:00
疯狂的狮子Li 2c9daae153 update 更改 工作流 测试用例接口路径 2024-05-31 11:25:03 +08:00
疯狂的狮子Li c2fdbc66b2 update 移除 表单构建菜单(没有可用组件 用处不大以后再考虑) 2024-05-29 18:36:46 +08:00
dap 57fd309907 fix: 类型报错 2024-05-29 09:32:49 +08:00
疯狂的狮子Li 7a335b3438 update 优化 删除未使用依赖 2024-05-21 10:01:25 +08:00
dap 83bbac303e fix: bpmn相关type第一次安装依赖&运行报错 2024-05-21 09:37:28 +08:00
疯狂的狮子Li eb1b614eb1 fix 修复 部署路径错误 2024-05-20 11:45:08 +08:00
疯狂的狮子Li a63543a5c7 !118 ♥️发布 5.2.0-BETA 公测版本
Merge pull request !118 from 疯狂的狮子Li/dev
2024-05-20 02:26:46 +00:00
疯狂的狮子Li 3585761b81 Merge branch 'ts' of gitee.com:JavaLionLi/plus-ui into dev
Signed-off-by: 疯狂的狮子Li <15040126243@163.com>
2024-05-20 02:26:24 +00:00
疯狂的狮子Li 34290d8cad ♥️发布 5.2.0-BETA 公测版本 2024-05-20 10:21:35 +08:00
LiuHao f367b49dd6 update 优化代码格式 2024-05-19 17:31:05 +08:00
LiuHao 7df347c1d4 remove 移除commit check 2024-05-18 23:02:45 +08:00
gssong ea106e44be add 添加工作流菜单图标 2024-05-18 12:40:37 +08:00
gssong b2e47f3938 update 优化模型保存位置,审批记录,请假申请按钮 2024-05-17 20:59:47 +08:00
疯狂的狮子Li b8e0f018f0 update 优化 更改 首页关于调度中心说明 2024-05-17 17:17:53 +08:00
疯狂的狮子Li 4ee46819c1 !117 修复登录失效,重新登录丢失参数问题
Merge pull request !117 from 爱宇阳/dev
2024-05-17 03:50:38 +00:00
deary 0c620ef5b4 修复登录失效,再次登录丢失参数 2024-05-17 11:44:33 +08:00
疯狂的狮子Li 9b00aaff93 update 优化 删除无用页面 2024-05-17 10:00:25 +08:00
疯狂的狮子Li b829867a5b !115 feat: powerjob,easyretry => snailjob
Merge pull request !115 from dhb52/dev
2024-05-17 01:39:39 +00:00
dhb52 736225fbfe feat: powerjob,easyretry => snailjob 2024-05-17 01:04:13 +08:00
dap 3062c46b49 fix: 流程定义xml预览问题 & 重构代码 2024-05-16 08:18:54 +08:00
dap ed66231d19 Merge branch 'dev' of https://gitee.com/JavaLionLi/plus-ui into dev 2024-05-15 11:35:02 +08:00
dap 3b8ecadc78 refactor: 流程定义-流程图片改为bpmn组件预览 2024-05-15 11:34:58 +08:00
疯狂的狮子Li 322e88d8e1 update 优化 调整字体大小 2024-05-11 20:00:53 +08:00
gssong 526ca728e1 update 修复模型选人参数异常,调整加签请求路径 2024-05-09 21:39:47 +08:00
疯狂的狮子Li 26c0cdaef6 update 重构 workflow 模块与 system 模块解耦 2024-05-09 15:10:15 +08:00
疯狂的狮子Li e7dc8e94c7 update 优化 跟密码相关的默认前端关闭防重功能 2024-05-08 15:33:31 +08:00
疯狂的狮子Li 72ca7a1aae !111 解决点击菜单时页面空白或者重新刷新整个页面的问题
Merge pull request !111 from 周旭湘/dev
2024-05-07 09:47:18 +00:00
周旭湘 907dc4efb4 update src/layout/components/AppMain.vue.
解决点击左边菜单时页面空白或者刷新整个页面的问题

Signed-off-by: 周旭湘 <3423729430@qq.com>
2024-05-07 09:39:43 +00:00
gssong 935a199f71 update 优化审批记录 2024-05-06 22:19:42 +08:00
gssong a19ac2d4ca update 调整会签人员参数 2024-05-06 20:59:41 +08:00
dap 437bc936fd refactor: 部门选择和岗位逻辑 2024-05-06 13:23:27 +08:00
dap 0b8f48fb61 fix: 更新时有岗位会被赋值为空的bug 2024-04-30 22:46:10 +08:00
dap 5d641e5de4 fix: 用户管理-部门变化后需要重新选择岗位 2024-04-30 22:09:53 +08:00
dap 0d196e47e2 fix: 重置时清空左边部门树选中值 2024-04-30 22:04:55 +08:00
疯狂的狮子Li 012e70c7e4 update element-plus 2.7.2 2024-04-30 17:33:09 +08:00
疯狂的狮子Li 9243eee3c3 remove 删除 husky(没人用) 2024-04-26 15:49:20 +08:00
疯狂的狮子Li c449fb60a5 update vite 5.2.10
update vue 3.4.25
2024-04-25 13:48:28 +08:00
疯狂的狮子Li 4660aa6e95 !108 update src/components/ImagePreview/index.vue.
Merge pull request !108 from 落叶橘橙/N/A
2024-04-25 02:16:33 +00:00
落叶橘橙 9968d14c39 update src/components/ImagePreview/index.vue.
图片预览功能 let real_src_list = props.src.split(',');会多出一个''对象,会导致图片浏览时多一个空白预览。增加一个判空。

Signed-off-by: 落叶橘橙 <wzsdch@qq.com>
2024-04-25 02:15:20 +00:00
疯狂的狮子Li e2254651ca fix 修复 !pr107 遗留问题
update 优化 岗位下拉框样式问题
2024-04-24 23:46:05 +08:00
AprilWind 7ed5f33e7b !107 add 新增岗位编码与部门编码 并将岗位放到部门下
* add 新增获取岗位选择框列表
* update 岗位查询树表和单表相互undefined
* update 岗位查询增加单部门查询
* update 优化类别编码与后台一致性
* add 新增岗位部门树以及类别编码
* add 部门增加类别代码
2024-04-24 14:30:52 +00:00
LiuHao 175c4a48ce update 优化代码缩进 2024-04-23 13:14:02 +08:00
追梦稻草人Li 9bcc4d631b !106 [轻量级pr] add 新增用户选择角色时 可搜索功能
* update src/views/system/user/index.vue.
* add 新增角色可搜索
2024-04-23 01:50:07 +00:00
疯狂的狮子Li 861dc9fb16 update 优化 替换过期属性 2024-04-23 09:47:11 +08:00
gssong 8633a23d28 fix 修改设计器到期时间没有值问题 2024-04-21 16:58:01 +08:00
gssong d67bd493c1 Merge branch 'dev' of https://gitee.com/JavaLionLi/plus-ui into dev 2024-04-21 16:50:01 +08:00
gssong 2d532d636a update 调整设计器选人 2024-04-21 16:49:47 +08:00
疯狂的狮子Li e2bdae5bf2 update element-plus 升级 2.7.1 并适配代码 2024-04-20 19:13:35 +08:00
gssong 2df121072b fix 修改默认没有候选人与候选组时点击选择出现tag标签选中全部问题 2024-04-19 22:13:26 +08:00
gssong 7016888d5a remove 删除无用代码 2024-04-19 21:59:43 +08:00
gssong 3c34421bd2 update 删除认领可直接办理,格式化代码 2024-04-19 21:58:05 +08:00
疯狂的狮子Li 187ae83731 !105 update 当el-form的inline属性为true时,统一样式写法
Merge pull request !105 from Bleachtred/dev
2024-04-19 09:13:44 +00:00
疯狂的狮子Li c4c9905a91 update 调整 select 宽度 2024-04-19 17:13:15 +08:00
bleachtred 219f3a7d6f update 设置el-select 的宽度默认为 240px 2024-04-19 16:52:40 +08:00
bleachtred 44837e975c update 当el-form的inline属性为true时,统一样式写法 2024-04-19 15:26:56 +08:00
AprilWind 8c6cf5bc43 !104 add 新增在线登录设备管理
* update 在线登录设备管理删除权限
* add 新增在线登录设备管理
2024-04-19 05:02:14 +00:00
疯狂的狮子Li c21f0d7d77 update vue-router 升级 4.3.2 2024-04-18 18:16:53 +08:00
疯狂的狮子Li 8b6b624f6c fix 修复 全局替换样式重复问题 2024-04-18 17:10:44 +08:00
疯狂的狮子Li 03c736af82 fix 修复 全局替换样式重复问题 2024-04-18 17:06:30 +08:00
疯狂的狮子Li 7386e69033 fix 修复 全局样式导致组件全覆盖问题 依旧采用单组件声明 2024-04-18 14:02:43 +08:00
疯狂的狮子Li 2f60c96fbf fix 修复 全局样式导致组件全覆盖问题 依旧采用单组件声明 2024-04-18 14:01:58 +08:00
疯狂的狮子Li 45e1c46ce4 !103 update 更新一些内容
Merge pull request !103 from Bleachtred/dev
2024-04-18 05:45:12 +00:00
bleachtred d7d3105c5c update 设置input固定宽度后,导致菜单图标组件IconSelect显示异常 2024-04-18 12:59:03 +08:00
bleachtred 4aa42f5c20 fix 角色必填*号 2024-04-18 11:29:57 +08:00
疯狂的狮子Li c089f2497c update 升级前端依赖(定稿) 2024-04-18 10:45:21 +08:00
疯狂的狮子Li e18dcbd86b !102 [BUG]修复用户表单,角色为必填,却未标注*号
Merge pull request !102 from dzk/fix-userform
2024-04-18 02:13:25 +00:00
dzk a541d61c0c 修复用户表单角色为非必填项的BUG 2024-04-17 23:49:07 +08:00
疯狂的狮子Li 4b19f55bce update 优化 el-select 与 el-input 全局样式 2024-04-17 19:40:34 +08:00
疯狂的狮子Li b5042d13d2 !101 fix: 临时修复elementui新版本下拉框宽度问题
Merge pull request !101 from NicholasLD/N/A
2024-04-17 11:34:09 +00:00
NicholasLD b444f2b8e2 fix: 临时修复elementui新版本下拉框宽度问题
Signed-off-by: NicholasLD <nicholasld505@gmail.com>
2024-04-17 11:24:58 +00:00
疯狂的狮子Li 6b982984ac fix 修复 el-select 展示不全问题 2024-04-17 19:01:49 +08:00
LiuHao 30f271359a fix 修复字典el-tag警告 2024-04-16 17:56:36 +08:00
LiuHao 9967a72e24 fix 修复el-tag标签类型不一致问题 2024-04-16 17:52:04 +08:00
LiuHao efeff40f2e update 白屏问题待检测 2024-04-16 17:42:54 +08:00
LiuHao 2e299b58e2 update 增加预编译 2024-04-16 17:41:30 +08:00
LiuHao 1d7c3da86b update 回滚解决路由失效问题 2024-04-16 17:41:21 +08:00
LiuHao 5057976ad2 update 优化缩进 2024-04-16 16:05:43 +08:00
LiuHao 41f3d37db1 update 优化首页打开topNav不展开菜单问题 2024-04-15 14:00:39 +08:00
LiuHao 1fbc5afe75 update 优化暗黑模式,增加vxe的暗黑模式 2024-04-15 13:33:11 +08:00
LiuHao b0541be0b8 fix 修复菜单搜索下方出现白色区域 2024-04-15 13:04:15 +08:00
LiuHao d6803783ae update 固定值 也可输入表达式 2024-04-15 12:52:04 +08:00
LiuHao 945eec5418 update 优化bpmn位置 2024-04-15 12:02:40 +08:00
LiuHao 73db6deec3 fix 修复类型缺失 2024-04-15 10:40:47 +08:00
LiuHao 40a75dae31 fix 修复代码缩进. 2024-04-15 10:40:33 +08:00
LiuHao 64fb2899c9 fix 修复代码缩进,类型名称错误 2024-04-15 10:22:44 +08:00
LiuHao 9da3f1f2d7 update 增加类型 2024-04-15 09:42:46 +08:00
疯狂的狮子Li 70120a8f2f !97 解决页面偶尔出现的白屏问题
Merge pull request !97 from 吴均/dev
2024-04-09 03:27:51 +00:00
wujun 6b4d756a9d 解决页面偶尔出现的白屏问题 2024-04-09 11:19:04 +08:00
gssong 905426ad45 update 修改流程定义删除 2024-04-08 22:43:37 +08:00
gssong b4b0eba228 update 调整流程定义配置逻辑 2024-04-06 21:06:59 +08:00
gssong 9f73ea2d32 update 优化表单绑定逻辑,移除流程定义配置表单,添加模型复制 2024-04-06 11:21:17 +08:00
LiuHao 2d804c7ce0 Merge remote-tracking branch 'origin/dev' into dev 2024-04-05 14:16:38 +08:00
LiuHao 11e8e9d19a fix 修复代码缩进 2024-04-05 14:16:29 +08:00
dap 3e44c14286 Merge branch 'dev' of https://gitee.com/JavaLionLi/plus-ui into dev 2024-04-05 14:09:53 +08:00
dap 04f1347ddd update: bpmn设计器夜间模式适配 2024-04-05 14:09:50 +08:00
LiuHao 0442bd638d fix 修复代码缩进 2024-04-05 14:08:02 +08:00
dap aeac77b90f chore: 拖动元素时的背景图 2024-04-04 20:41:58 +08:00
dap b117a6f198 update: 流程预览 进行中动画效果 2024-04-04 14:19:49 +08:00
dap e1b03258e8 fix: 租户选择框宽度和升级前保持一致 2024-04-04 13:55:45 +08:00
疯狂的狮子Li c71eb21416 update 更新成员项目 2024-04-03 23:12:46 +08:00
gssong c922ea3b9c add 添加委托 2024-04-03 20:42:05 +08:00
gssong d76f2b857d add 添加流程版本 2024-04-02 20:53:29 +08:00
gssong eec050a2dd update 调整监听新增label错误 2024-04-01 21:23:31 +08:00
gssong b0087d1a50 #I96DTG update 类型下拉框和java类名下拉框没有联动 2024-04-01 20:59:52 +08:00
gssong 4752b4eb01 update 调整流程状态 2024-03-31 19:30:31 +08:00
gssong 2ea1807f34 add 添加表单配置 2024-03-31 15:34:54 +08:00
疯狂的狮子Li 5dfc25a493 !95 add 工作流挂节点路由表单
Merge pull request !95 from ken.wang/dev
2024-03-29 13:15:10 +00:00
wangzk c5b3c121c9 add 工作流挂节点路由表单 2024-03-29 17:26:56 +08:00
疯狂的狮子Li c417c6debe update 升级 element vite 版本 最低nodejs版本提升到18.18.0 2024-03-26 18:43:45 +08:00
LiuHao f6727d80b8 update 升级依赖 2024-03-26 18:20:13 +08:00
gssong ceb6243cd0 update 调整示例key 2024-03-24 15:16:44 +08:00
gssong cd129aa949 update 路由跳转 2024-03-24 15:13:05 +08:00
gssong d186c800f0 add 添加流程实例,全部待办表单查看 2024-03-22 23:42:30 +08:00
songgaoshuai 31f4219f3d fix修复已办参数传错 2024-03-22 11:32:58 +08:00
gssong ad8565d29a update 调整我的发起,流程定义按钮 2024-03-21 21:49:34 +08:00
gssong 66a31b620b add 添加已办查看 2024-03-21 21:20:42 +08:00
gssong e26f6423aa add 添加抄送查看 2024-03-21 21:19:02 +08:00
gssong 12461f4106 update 固定顶部按钮 2024-03-21 21:14:01 +08:00
gssong 58422616e2 remove 还原代码 2024-03-21 21:06:58 +08:00
gssong f6abd4cf59 update 调整状态判断 2024-03-21 21:06:18 +08:00
gssong f50ed6b2c5 add 添加流程表单配置 2024-03-21 21:02:41 +08:00
LiuHao 3dba22c47c fix 修复移动端下 无法展开菜单问题 2024-03-19 17:41:47 +08:00
LiuHao e1289d0abb fix 修复面板因为min width原因收缩不全 2024-03-19 16:14:38 +08:00
LiuHao 9ea8b710ff update 预览流程图高度自适应 2024-03-19 16:02:42 +08:00
LiuHao e889348562 update 面板宽度百分比 2024-03-18 14:27:43 +08:00
LiuHao 02daeead57 update 隐藏不用工具栏 2024-03-18 14:21:35 +08:00
LiuHao 4253b2afbb update 增加子流程多实例 2024-03-18 14:19:30 +08:00
LiuHao 0c39b593ce update 优化面板类型 2024-03-18 14:18:30 +08:00
LiuHao 8761392c85 update 优化任务面板 2024-03-18 14:18:04 +08:00
LiuHao 30cf3a2caa update 增加多实例常量 2024-03-18 14:17:48 +08:00
LiuHao 12458177be update 更新开始面板和泳道面板样式 2024-03-18 13:56:16 +08:00
LiuHao b6415c21be update 新增子流程面板 2024-03-18 13:55:57 +08:00
LiuHao bc4358f4eb update 流程部署支持多选 2024-03-18 12:19:52 +08:00
LiuHao 5dcfee4c07 update 流程部署支持多选 2024-03-18 11:52:44 +08:00
LiuHao a9cd5684b2 update 新增预编译和翻译 2024-03-18 10:56:12 +08:00
LiuHao 1c0e614d7d update 新增池/参与者面板 2024-03-18 10:44:21 +08:00
gssong 00a7a8ce23 add 添加流程自由驳回节点 2024-03-17 18:26:22 +08:00
gssong ade0b3e29e update 调整模型导出按钮位置 2024-03-16 22:02:45 +08:00
gssong 3a3f873834 update 调整模型zip导出 2024-03-16 22:01:35 +08:00
gssong 1edc953765 fix 修改已完成任务查看流程变量错误 2024-03-16 19:35:13 +08:00
疯狂的狮子Li 1383f5a7eb !93 fix: if(captchaEnabled) => if(captchaEnabled.value)
Merge pull request !93 from dhb52/N/A
2024-03-15 01:36:21 +00:00
dhb52 e4f18452c7 fix: if(captchaEnabled) => if(captchaEnabled.value)
Signed-off-by: dhb52 <dhb52@126.com>
2024-03-14 16:42:00 +00:00
疯狂的狮子Li fdf64a6f08 !90 feat: EasyRetry Server 扩展模块
Merge pull request !90 from dhb52/dev
2024-03-14 06:46:34 +00:00
疯狂的狮子Li f46a333778 !89 【轻量级 PR】:update 调整导入模型选择流程类别方式(改为表单内下拉框)
Merge pull request !89 from 愿丶/N/A
2024-03-13 13:29:31 +00:00
dhb52 eb364873d2 ✨ EasyRetry Server 扩展模块 2024-03-13 01:18:49 +08:00
愿丶 7666f724df update 调整导入模型选择流程类别方式(改为表单内下拉框)
Signed-off-by: 愿丶 <1319542051@qq.com>
2024-03-12 15:48:42 +00:00
gssong f9b8922bed update 调整全部已办开始时间 2024-03-11 21:14:22 +08:00
gssong fb94a4d79c update 调整已办列表,添加审批记录加载 2024-03-11 21:03:00 +08:00
疯狂的狮子Li 71047fdbfd update copyright 2024 2024-03-11 10:58:51 +08:00
疯狂的狮子Li 2cb9b3ea47 update 优化 事件标签改为中文 2024-03-11 10:45:08 +08:00
gssong 3c27c18889 add 添加查看流程变量 2024-03-09 13:41:20 +08:00
gssong 9defb9a669 remove 删除无用组件 调整修改办理人,已完成单据可查看审批记录等 2024-03-09 11:22:28 +08:00
gssong 8833eb205b add 添加终止任务 2024-03-09 11:10:19 +08:00
gssong 15129079d4 remove 删除无用代码 2024-03-08 22:49:47 +08:00
LiuHao d1c199d4bf update 优化流程预览 2024-03-08 18:22:28 +08:00
LiuHao 97b4eef342 update 使用bpmnjs流程预览 2024-03-08 16:02:08 +08:00
LiuHao 1dd9983f0f update 流程图和审批信息分开展示 2024-03-08 15:59:27 +08:00
LiuHao b8eb2dcb40 update 增加默认导出 2024-03-08 15:00:01 +08:00
LiuHao 3b4f171d9f update 优化类型 2024-03-08 14:56:44 +08:00
LiuHao de33d4aaee update 保存增加loading、增加预编译 2024-03-08 14:16:27 +08:00
gssong 803d44cac0 add 添加转办 2024-03-07 22:16:42 +08:00
gssong cc293536e2 add 添加审批加签 减签 2024-03-07 21:54:47 +08:00
gssong 5f6057253f remove 删除无用打印 2024-03-07 21:19:04 +08:00
gssong d50c90afd1 fix 修复设计器无法选人问题,修复抄送打开弹出选中全部人员问题 2024-03-07 21:18:08 +08:00
songgaoshuai 6f9851a4e5 fix 修复无法编辑设计器问题 功能未完成先注释掉 2024-03-07 16:16:28 +08:00
疯狂的狮子Li e7ff829502 update 优化 工作流代码与接口命名 2024-03-07 14:23:24 +08:00
疯狂的狮子Li 0108df1334 !88 合并flowable工作流功能
* merge 合并dev
* add 添加抄送查询
* add 添加我的已办
* add 添加抄送
* add 添加附件下载
* update 优化类型
* Merge remote-tracking branch 'origin/future/flowable' into future/flowable
* fix 修复 流程设计器打包部署报错问题
* add 添加审批附件上传
* update 修复固定值未在xml显示问题
* update 修复跳转条件回显Object问题
* update 优化面板文件名称
* update 调整key
* remove 移除旧设计器,添加xml保存
* update 增加任务面板提示
* update 优化xml预览和svg预览
* update 优化xml预览和svg预览
* update 优化模型设计
* update 优化设计器
* update 优化设计器
* update 优化设计器
* update 删除旧设计器
* update 删除console.log
* add 添加模型接口
* update 优化预览xml和svg样式被修改问题
* update 优化属性面板,增加展开动画
* update 去除开发模式
* update 优化任务栏样式
* update 优化图标渲染样式
* update 增加BpmnFactory类型
* update 增加BpmnFactory
* update 移除users和group
* update 移除无用类型
* update 优化页面类型
* update 去除多余属性
* update 完善流程线
* update 增加复杂网关
* update 完善流程
* update 完善网关
* update 优化网关汉化
* update 优化过期时间选择
* update 支持多实例
* update 增加类容提示
* update 支持选择组
* update 新增角色api
* update 优化roleSelect 选中未确定,再次打开还保留选中的问题
* update 优化userSelect 选中未确定,再次打开还保留选中的问题
* update 优化userSelect 选中未确定,再次打开还保留选中的问题
* update 去掉modeler store多余属性 bpmnModel
* update 优化属性面板,当面板未选中时默认展示流程面板
* update 优化TaskPanel类型,去掉roles属性
* update 优化用户api
* update 优化用户选择器
* update 优化执行监听器
* update 优化任务监听器
* update 优化usePanel方法
* update 选人优化
* update 增加扩展节点信息
* update 增加usePanel默认方法
* update 去除处理事件
* update 扩展flowable  userinfo属性
* update 全局modeler 改为非响应式
* update 增加hooks方法
* update 修改命名
* update 修改面板formData来源
* update 重写用户任务面板选择逻辑
* update 重写用户任务面板选择逻辑
* update 修改用户选择组件获取数据逻辑
* update 修改枚举类型
* update 修改默认配置列
* update 增加修改节点方法
* update 调整预览窗口大小
* update 优化用户选择组件 返回值
* update 优化用户选择组件
* update 新增通过ids 获取用户信息
* update 重写task面板选人 未完成
* update 升级用户选择 支持多选配置
* update 升级bpmnjs依赖版本
* update 增加useDialog类型
* update 调整全局样式
* update 代码高亮设置
* update 优化领用,归还加载
* update 增加选择角色
* update  新增角色选择组件
* update 新增过期时间选择组件
* update 调整任务面板样式
* update  调整全局dialog header 增加分割线
* update 代码高亮设置
* update  调整面板位置
* update 封装用户选择组件
* update 移除所有的节点描述
* update 删除分类
* update  调整面板位置
* update  修改命名,增加自定义渲染
* update  修改命名,增加自定义渲染
* update 增加 Element类型定义
* update 调整样式
* update 移除bpmn panel依赖,升级bpmn.js依赖到最新,修改汉化包
* update 调整类型声明文件
* update 调整类型声明文件
* update 优化面板工具
* update 优化面板工具
* Merge remote-tracking branch 'origin/future/flowable' into future/flowable
* update 优化面板工具
* Merge branch 'future/flowable' of https://gitee.com/JavaLionLi/plus-ui…
* add 添加修改办理人
* update 优化面板工具
* update 初始化流程数据
* Merge remote-tracking branch 'origin/future/flowable' into future/flowable
* add 流程设计面板
* update 调整初始化xml
* add 任务面板
* add 新增bpmn.js
* update 优化request请求类判断请求头方式
* update 流程定义预览 优化
* update 流程定义预览 优化
* update 去掉console.log
* update 优化工作流代码
* fix 修复待办任务 重置查询条件失效问题
* add 增加待办任务 接口类型,优化页面
* add 增加vite 启动预编译css
* fix 修复i18n无感刷新问题
* Merge branch 'dev' into future/flowable
* update 调整选择请假事件
* Merge branch 'dev' into future/flowable
* 同步dev代码
* Merge branch 'dev' into future/flowable
* 合并dev
* remove 设计器无用代码 调整请假查询
* update 调整请假申请
* update 移动请假表单包结构,调整设计器选择引用表单请求错误
* remove 移除动态表单
* update 调整流程办理
* Merge branch 'dev' into future/flowable
* Merge branch 'dev' into future/flowable
* Merge branch 'dev' into future/flowable
* Merge branch 'dev' into future/flowable
* 合并
* update 调整请假申请流程提交
* update 修改业务单据流程提交
* update 调整业务单据流程提交
* 优化代码
* 优化工作流代码缩进
* 项目格式化配置修改
* 调整代码缩进
* Merge branch 'ts' into future/flowable
* add 添加动态表单提交流程
* add 添加动态表单单据
* add 新增流程定义与表单关联
* update 调整点击左侧部门查询人员,部门刷新问题
* update 调整按钮图标
* 调整错别字
* update 调整流程定义图片预览
* add 添加流程实例迁移版本
* fix 修复我的单据无法提交问题
* Merge branch 'ts' into future/flowable
* remove 还原代码后端解决
* update 流程设计器中分配发起人变量错误,先移除
* fix 修复设计器无法编辑问题
* update 调整设计器请求头
* Merge branch 'ts' into future/flowable
* Merge branch 'ts' into future/flowable
* add 添加流程定义历史列表
* update 审批记录v2改为v3
* update 调整请假必填项
* add 添加请假申请示例,添加流程定义文件部署
* update 移除流程表单 formConfig 属性,表单配置信息都放一起便于使用。
* add 添加任务加签,减签
* update 调整流程作废
* update 优化流程状态
* add 添加任务驳回
* add 添加查询当前租户所有待办,已办任务
* add 增加审批意见
* add 添加流程办理弹窗确认组件
* add 添加任务作废理由
* update 调整流程实例,流程定义检索
* add 添加我的单据页面
* add 添加任务归还认领
* add 添加流程实例,流程定义分类查询
* add 添加模型分类查询
* add 添加流程分类
* Merge remote-tracking branch 'origin/future/flowable' into future/flowable
* add 添加流程表单管理页面
* add 集成vForm动态表单组件
* update xml调整超出滚动
* add 添加已办列表
* add 添加单据状态
* update 优化流程实例删除
* fix 修复流程实例查询挂起状态错误
* update 调整流程实例挂起激活状态
* add 添加流程实例列表
* update 调整流程定义弹窗提示
* add 添加流程定义列表,添加流程图,xml预览,添加简单流程启动,办理
* 调整审批记录悬浮逻辑
* 删除无用代码
* add 添加节点悬浮信息
* 调整流程预览
* 调整流程追踪
* add 添加审批记录
* add 模型设计的types
* update 修改排版
* add lang=ts
* update 修改ele的废弃api
* fix调整审批记录图片不显示问题
* add 添加任务待办,流程图
* 调整设计器关闭
* add 添加待办
* remove 删除无用代码
* update types
* 添加模型token验证
* 隐藏设计器验证按钮,隐藏表单,案例,应用程序等
* 添加模型部署
* 添加画图接口token,优化画图接口
* 添加工作流模型新增,修改,查询,删除,画图工具
2024-03-05 14:57:51 +00:00
疯狂的狮子Li 542f73f0e6 update 优化 支持全局开启或关闭接口加密功能 2024-03-04 14:18:21 +08:00
疯狂的狮子Li 5cb40abe18 update 优化 密码校验策略增加非法字符限制 2024-03-04 10:05:47 +08:00
疯狂的狮子Li 26cfa7afc4 !84 图片上传组件增加压缩支持
Merge pull request !84 from 缝合怪/dev
2024-02-23 07:24:31 +00:00
疯狂的狮子Li df1a84d5ae !86 bugfix: 修复文件预览大写后缀预览时效的问题
Merge pull request !86 from 北桥/dev
2024-02-23 07:23:49 +00:00
这夏天依然平凡 5b991be4c2 !87 修改 el-dialog 默认点击遮照为不关闭
* update 修改 el-dialog 默认点击遮照为不关闭
2024-02-23 07:23:20 +00:00
北桥 34c0d2d277 bugfix: 修复文件预览大写后缀不展示的问题 2024-02-02 13:43:16 +08:00
LiuHao b2f00c4b71 add 增加全局角色选择组件 2024-01-26 09:59:32 +08:00
LiuHao 63ba90cc10 add 增加全局用户选择组件 2024-01-26 09:59:23 +08:00
LiuHao 3b18a476b7 add hooks - useDialog 2024-01-26 09:59:05 +08:00
LiuHao 15243ab713 Merge remote-tracking branch 'origin/dev' into dev 2024-01-26 09:58:09 +08:00
LiuHao b4cc7b3de0 add 引入vxe-table依赖支持 2024-01-26 09:58:00 +08:00
fengheguai fe3874396d 图片上传组件增加压缩功能支持,可自行开关 2024-01-25 12:50:45 +08:00
疯狂的狮子Li fdf885c261 !82 修复 DictTag组件,当未找到匹配的数据时,不会显示value
Merge pull request !82 from lee/bugfix/DictTag_Unmatch
2024-01-18 09:39:29 +00:00
LiuHao 7b7377fa1b update 优化request请求类判断请求头方式 2024-01-16 09:51:51 +08:00
文兵 李 0c56f87e06 foreach中return并不会使其跳出循环,导致这个计算属性一直都会是false 2024-01-15 22:59:22 +08:00
疯狂的狮子Li b783b8d991 update 全依赖版本升级 2024-01-14 22:30:00 +08:00
LiuHao 4ea7376dbc fix 修复i18n无感刷新问题 2024-01-11 15:26:37 +08:00
LiuHao 5910032908 Merge remote-tracking branch 'origin/dev' into dev 2024-01-11 14:27:58 +08:00
LiuHao 024783588e update 升级@intlify/unplugin-vue-i18n版本依赖
update i18n使用方法。
add 新增i18n vite插件。
2024-01-11 14:27:46 +08:00
疯狂的狮子Li acba493c94 !80 JustAuth 整合 TopIam 单点登录
Merge pull request !80 from 马铃薯头/dev
2024-01-08 16:05:47 +00:00
xlsea 7073acb3ef 社交登录整合 TopIam 2024-01-08 11:48:56 +08:00
疯狂的狮子Li 075c02b8c3 update 优化 使用翻译注解简化用户查询 调整用户查询逻辑 2024-01-06 20:58:54 +08:00
ahao 31da01bdd1 fix https://gitee.com/dromara/RuoYi-Vue-Plus/issues/I8TMAI 2024-01-06 17:27:01 +08:00
疯狂的狮子Li dfdcee9b95 !79 update 富文本组件,修复两个组件上传图片位置错乱问题
Merge pull request !79 from 抓蛙师/N/A
2024-01-05 14:51:03 +00:00
抓蛙师 d3b630076a update 富文本组件,修复两个组件上传图片位置错乱问题
Signed-off-by: 抓蛙师 <770492966@qq.com>
2024-01-05 14:50:27 +00:00
疯狂的狮子Li 173c723c7c fix 修复 富文本编辑器 单页面多实例图片胡乱问题 2024-01-05 18:39:32 +08:00
ahao 595a521a3c update issues -> https://gitee.com/dromara/RuoYi-Vue-Plus/issues/I8LXAX 2024-01-05 17:15:45 +08:00
ahao d08f14d86d update 修改对Volar支持 2024-01-05 14:37:22 +08:00
ahao b112b793d5 fix 修复eslint 警告 2024-01-05 14:14:32 +08:00
ahao 6432d165c7 update 修复启动弹出cjs废弃警告 2024-01-05 12:06:10 +08:00
ahao e5772cb63c update 移除cjs 2024-01-05 11:42:55 +08:00
ahao bb696b300f update 升级依赖 2024-01-05 11:42:36 +08:00
疯狂的狮子Li 14f6a214f2 !75 fix: 修复vscode全局属性ts爆红问题
Merge pull request !75 from dhb52/N/A
2024-01-03 03:41:05 +00:00
dhb52 bbcedd02ba fix: 修复vscode全局属性ts爆红问题
参照vuejs官方文档,[扩展全局属性](https://cn.vuejs.org/guide/typescript/options-api.html#augmenting-global-properties),

```ts
declare module 'vue' {
  interface ComponentCustomProperties {
    $http: typeof axios
    $translate: (key: string) => string
  }
}
```

Signed-off-by: dhb52 <dhb52@126.com>
2024-01-03 03:40:39 +00:00
ahao abf2777b2e fix 修复 页面警告 2023-12-27 14:28:04 +08:00
ahao 3922c16601 fix 修复 vue 类型识别问题 2023-12-27 12:12:51 +08:00
ahaos 321f21c498 !73 修复全局属性找不到的问题
* Merge remote-tracking branch 'origin/dev' into dev
* fix 修复全局属性找不到的问题
* fix 修复变量问题
* fix 修复变量问题
* Merge remote-tracking branch 'origin/dev' into dev
* update 依赖升级
* update 依赖升级
* Merge remote-tracking branch 'origin/dev' into dev
* 升级依赖
* Merge remote-tracking branch 'origin/ts' into ts
* 升级依赖
* Merge branch 'dev' of gitee.com:JavaLionLi/plus-ui into ts
* 升级依赖
* !61 fix: 删除重复环境变量ElUploadInstance
* fix: 删除重复环境变量ElUploadInstance
2023-12-26 10:04:35 +00:00
疯狂的狮子Li 085ce4cf43 update 优化 更改客户端状态接口 使用clientId传参 2023-12-26 00:47:59 +08:00
疯狂的狮子Li c5daf629d9 update 优化 通知公告提交提示 2023-12-23 23:13:34 +08:00
疯狂的狮子Li 20b7819f11 update 优化 ts检查改为非严格 提高友好型降低开发难度 2023-12-23 20:43:58 +08:00
疯狂的狮子Li 8b36cac09d update 升级前端依赖版本 2023-12-23 20:35:55 +08:00
疯狂的狮子Li 0e99163f0c update 升级前端依赖版本 2023-12-23 20:30:28 +08:00
疯狂的狮子Li 772885de35 update 优化 websocket 代码实现 2023-12-23 19:49:17 +08:00
疯狂的狮子Li 1d557a24f9 update 优化 ws开关改为常开(vite5修复了崩溃bug) 2023-12-23 19:45:47 +08:00
疯狂的狮子Li 597f2b4461 fix 修复 websocket 非index页面刷新无法重连问题 2023-12-23 19:38:34 +08:00
疯狂的狮子Li cc9b67d467 !72 发布 vue 版本 5.1.2 与 cloud 版本 2.1.2
Merge pull request !72 from 疯狂的狮子Li/temp
2023-12-22 05:26:26 +00:00
疯狂的狮子Li 70a3348954 🧨发布 vue 版本 5.1.2 与 cloud 版本 2.1.2 2023-12-22 13:21:04 +08:00
疯狂的狮子Li 2c95f86963 🧨发布 vue 版本 5.1.2 与 cloud 版本 2.1.2 2023-12-22 13:20:44 +08:00
疯狂的狮子Li 1272e8fe7d fix 修复 append-to-body 编写错误 2023-12-20 14:44:50 +08:00
疯狂的狮子Li 3204aa8461 !71 update src/views/system/dept/index.vue.
Merge pull request !71 from Ai3_刘小龙/N/A
2023-12-20 06:28:20 +00:00
Ai3_刘小龙 5d44f9e231 update src/views/system/dept/index.vue.
append-to-body

Signed-off-by: Ai3_刘小龙 <wisty0317@163.com>
2023-12-20 06:26:49 +00:00
ahaos 1d5133b695 !69 修复升级依赖带来的类型问题
* fix 修复变量问题
* Merge remote-tracking branch 'origin/dev' into dev
* update 依赖升级
* update 依赖升级
* Merge remote-tracking branch 'origin/dev' into dev
* 升级依赖
* Merge remote-tracking branch 'origin/ts' into ts
* 升级依赖
* Merge branch 'dev' of gitee.com:JavaLionLi/plus-ui into ts
* 升级依赖
* !61 fix: 删除重复环境变量ElUploadInstance
* fix: 删除重复环境变量ElUploadInstance
2023-12-14 08:17:12 +00:00
疯狂的狮子Li 031d83828a update 代码规范化 2023-12-14 00:44:12 +08:00
疯狂的狮子Li 0541af5abb fix 修复 部分问题 2023-12-14 00:35:00 +08:00
疯狂的狮子Li 1f71044cff fix 修复 部分问题 2023-12-14 00:25:54 +08:00
ahaos f32a7105c3 !68 修复升级依赖带来的问题
* Merge remote-tracking branch 'origin/dev' into dev
* 升级依赖
* Merge remote-tracking branch 'origin/ts' into ts
* 升级依赖
* Merge branch 'dev' of gitee.com:JavaLionLi/plus-ui into ts
* 升级依赖
* !61 fix: 删除重复环境变量ElUploadInstance
* fix: 删除重复环境变量ElUploadInstance
2023-12-13 10:35:55 +00:00
ahaos b06f6a316b !64 版本升级
* Merge branch 'dev' of gitee.com:JavaLionLi/plus-ui into ts
* 升级依赖
* !61 fix: 删除重复环境变量ElUploadInstance
* fix: 删除重复环境变量ElUploadInstance
2023-12-13 01:01:52 +00:00
NickLuo 58d7e50de3 !63 关闭动态路由tab页签时不清理组件缓存
* 动态路由页面关闭时不清理组件缓存,避免清理已打开的多个路由页面缓存
2023-12-13 00:55:46 +00:00
疯狂的狮子Li c045276a7c update 优化 明确打包命令 2023-12-08 18:04:02 +08:00
棉花 6a7ec81168 fix: 删除重复环境变量ElUploadInstance
Signed-off-by: 棉花 <12559203+radish-hi_0@user.noreply.gitee.com>
2023-12-08 17:55:11 +08:00
疯狂的狮子Li 183e0e9212 !61 fix: 删除重复环境变量ElUploadInstance
Merge pull request !61 from 棉花/N/A
2023-12-08 09:53:55 +00:00
疯狂的狮子Li c020c1affc update 优化 用户头像 img 变量无确定类型问题 2023-12-08 17:01:19 +08:00
疯狂的狮子Li 9673380f60 update 优化 细化oss配置管理权限控制 2023-12-07 14:52:33 +08:00
疯狂的狮子Li 9b28d14bc3 fix 修复 在线用户 强推按钮点击取消控制台警告问题 2023-12-06 00:18:31 +08:00
棉花 01a4dd0b45 fix: 删除重复环境变量ElUploadInstance
Signed-off-by: 棉花 <12559203+radish-hi_0@user.noreply.gitee.com>
2023-12-05 12:57:44 +00:00
疯狂的狮子Li e1023bb331 update 优化 代码中存在的警告 2023-11-30 11:13:29 +08:00
疯狂的狮子Li 5c701801db update 优化 前端白名单页面放行逻辑 2023-11-29 16:02:37 +08:00
疯狂的狮子Li 9b4692b625 !59 响应加密功能
Merge pull request !59 from MichelleChung/dev
2023-11-27 02:59:00 +00:00
疯狂的狮子Li aaec0f7bfe fix 修复 字典使用 default 样式报警告问题 2023-11-27 10:34:42 +08:00
疯狂的狮子Li 25e2e0e018 update 优化 页面关于权限标识符说明 2023-11-23 16:50:31 +08:00
疯狂的狮子Li 5165541780 update 优化 开发环境默认关闭ws 因vite的bug导致如ws无法连接则会崩溃 2023-11-22 16:22:15 +08:00
Michelle.Chung b3c1b95437 add 新增响应解密私钥 ;
add 新增 crypto#decryptBase64 Base64解码方法 ;
update 更新响应拦截器增加响应解密逻辑 ;
2023-11-20 19:27:03 +08:00
疯狂的狮子Li d84fee9319 !58 修复vite环境变量类型原因导致websocket关闭失效问题
Merge pull request !58 from Lau/N/A
2023-11-16 04:24:52 +00:00
Lau d034236ce3 fix: 修改环境变量类型原因导致websocket无法关闭问题
Signed-off-by: Lau <1807121535@qq.com>
2023-11-16 03:25:35 +00:00
疯狂的狮子Li 9e89ab5bae !57 发布 vue 版本 5.1.1 与 cloud 版本2.1.1
Merge pull request !57 from 疯狂的狮子Li/dev
2023-11-14 03:11:07 +00:00
疯狂的狮子Li 6e6062e824 😴发布 vue 版本 5.1.1 与 cloud 版本2.1.1 2023-11-14 10:51:12 +08:00
疯狂的狮子Li 35bebf403c update 适配 websocket在https下的连接方式 2023-11-13 13:02:09 +08:00
疯狂的狮子Li 0a8c33c3cb fix 修复 五级路由缓存无效问题 2023-11-10 15:59:09 +08:00
疯狂的狮子Li 8a7de17b58 fix 修复 内链iframe没有传递参数问题 2023-11-10 11:35:40 +08:00
疯狂的狮子Li f65eb2aee5 !55 绑定第三方帐号参数“wechar”更正为“wechat”
Merge pull request !55 from scmiot/dev
2023-11-07 01:30:47 +00:00
scmiot efb53d4bcb !1 绑定第三方帐号参数“wechar”更正为“wechat”
Merge pull request !1 from scmiot/N/A
2023-11-04 22:51:31 +00:00
scmiot ad2134f07d 绑定第三方帐号参数“wechar”更正为“wechat”
Signed-off-by: scmiot <10322731+scmiot@user.noreply.gitee.com>
2023-11-04 08:46:06 +00:00
疯狂的狮子Li caa9d0fcdc fix 修复 环境变量书写错误 2023-11-03 22:40:18 +08:00
疯狂的狮子Li b829ba4aa0 fix 修复 websocket 初始化无法连接进程死掉问题(vue代理问题) 2023-11-03 18:36:11 +08:00
疯狂的狮子Li a232437abc update 优化 !pr50 bug与代码实现 2023-11-02 14:00:48 +08:00
疯狂的狮子Li f2372d3243 update 优化 !pr50 bug与代码实现 2023-11-02 13:53:44 +08:00
三个三 a8a334b3c3 !50 add 新增 前端接入websocket接收消息
*  add 新增 前端接入websocket接收消息
2023-11-02 04:36:31 +00:00
疯狂的狮子Li 1e3f18ce22 !54 update 优化表格列的显示与隐藏小组件
Merge pull request !54 from bestrevens/dev
2023-11-01 04:09:35 +00:00
疯狂的狮子Li 631f338be2 fix 修复 用户注册缺失 clientid 问题 2023-11-01 10:46:42 +08:00
bestrevens bf977fe00a update 优化表格列的显示与隐藏小组件
优化表格列的显示与隐藏小组件,解决小组件之间距离间隔不一样的问题

Signed-off-by: bestrevens <201840026@qq.com>
2023-10-31 08:54:22 +00:00
疯狂的狮子Li 5bc7044032 update 优化 补全操作日志部门数据 2023-10-27 22:44:05 +08:00
疯狂的狮子Li 6ad0ed5316 update 优化 去掉多余的参数 2023-10-26 17:02:12 +08:00
疯狂的狮子Li ccb2ecc5ee update 更新 表单构建不能使用说明 2023-10-26 17:01:38 +08:00
疯狂的狮子Li ec0cb472df update 优化 去掉多余的参数 2023-10-25 23:05:32 +08:00
疯狂的狮子Li cd0a459c2b update 更新 表单构建不能使用说明 2023-10-25 16:21:21 +08:00
疯狂的狮子Li 18fea86a2c !53 更新登录日志以及在线用户展示信息
Merge pull request !53 from MichelleChung/dev
2023-10-23 12:46:48 +00:00
Michelle.Chung 66bfff450c update 更新 logininfor/index, online/index 字段显示 (客户端, 设备类型) ; 2023-10-23 20:32:38 +08:00
疯狂的狮子Li ec34c759ec !52 fix 优化表格列的显示与隐藏小组件不显示tip和浏览器告警
Merge pull request !52 from bestrevens/ts
2023-10-16 07:36:23 +00:00
bestrevens c1c5ea5e9d fix 优化表格列的显示与隐藏小组件不显示字段和告警
fix 优化表格列的显示与隐藏小组件不显示字段和告警

Signed-off-by: bestrevens <201840026@qq.com>
2023-10-16 07:30:14 +00:00
疯狂的狮子Li 6fe269efc7 fix 修复 !pr47 导致的打包异常 2023-10-16 15:13:27 +08:00
疯狂的狮子Li 920e079727 update 优化 富文本Editor组件检验图片格式 2023-10-09 12:00:15 +08:00
疯狂的狮子Li a2f13185e1 fix 修复 HeaderSearch组件跳转query参数丢失问题 2023-10-09 11:57:22 +08:00
疯狂的狮子Li 078bb50130 update vue-quill 1.1.0 => 1.2.0 2023-10-09 11:47:29 +08:00
疯狂的狮子Li 4854d8df00 update 优化 操作日志列表新增IP地址查询 2023-10-09 11:46:53 +08:00
疯狂的狮子Li ecf062605d update 优化 菜单管理类型为按钮状态可选 2023-10-09 11:41:53 +08:00
疯狂的狮子Li b989b07121 update 优化 用户初始密码从参数配置查询 2023-10-09 11:19:32 +08:00
疯狂的狮子Li bf957f06a0 !51 update 优化 通过参数键名获取键值接口的返回体
Merge pull request !51 from David Wei/update/config_response
2023-10-08 08:56:00 +00:00
David Wei aed8c89ded update 优化 通过参数键名获取键值接口的返回体 2023-10-08 16:05:58 +08:00
疯狂的狮子Li 4085811d24 !48 修复#I8550V
Merge pull request !48 from ahaos/ts
2023-09-28 16:51:40 +00:00
ahao fe384a3020 fix #I8550V https://gitee.com/dromara/RuoYi-Vue-Plus/issues/I8550V 2023-09-29 00:06:57 +08:00
ahaos c6f3cd068e !47 优化表格列的显示与隐藏小组件
Merge pull request !47 from 森爷/ts
2023-09-28 14:15:14 +00:00
DESKTOP-IGCH756\PC 99a6b56233 优化表格列的显示与隐藏小组件 2023-09-28 14:58:34 +08:00
疯狂的狮子Li 8ed32775cb !44 fix 个人信息修改密码接口隐藏新旧密码参数明文
Merge pull request !44 from Bleachtred/ts
2023-09-26 08:06:46 +00:00
bleachtred 395db813b5 fix 个人信息修改密码接口,隐藏新旧密码参数明文 2023-09-25 15:29:32 +08:00
疯狂的狮子Li ab1a7204fa update 优化 页面输入框样式 2023-09-17 15:53:25 +08:00
疯狂的狮子Li 92b2b489a4 fix 修复 自定义字典样式不生效的问题 2023-09-14 17:22:36 +08:00
疯狂的狮子Li 956d2ad495 update 优化 !pr40 代码结构 2023-09-09 11:44:56 +08:00
疯狂的狮子Li cb6cbc4f40 !40 优化字典标签支持数组和多标签
Merge pull request !40 from 抓蛙师/ts
2023-09-09 03:42:40 +00:00
抓蛙师 14538ce399 优化字典标签支持数组和多标签 2023-09-08 18:35:17 +08:00
疯狂的狮子Li 6c16d023f4 fix 修复 login 页面 loading 未关闭问题 2023-09-08 12:28:09 +08:00
疯狂的狮子Li d12d21c46d !38 fix #I7WUYJ 菜单切换主题为浅色主题后颜色不正常
Merge pull request !38 from ahaos/tspr
2023-09-02 04:46:07 +00:00
ahao 93fb212e0c fix #I7WUYJ 菜单切换主题为浅色主题后颜色不正常 2023-09-02 00:55:02 +08:00
疯狂的狮子Li b22d0775b7 fix 修复 导包警告问题 2023-09-01 11:52:15 +08:00
疯狂的狮子Li c85f0a1995 update 优化 控制台debuger位置错误问题
update 优化 TopNav 菜单样式
fix 修复 布局配置失效问题
2023-09-01 11:38:23 +08:00
疯狂的狮子Li 78d120c423 !37 修复 菜单图标选择器小屏幕显示不全的问题
Merge pull request !37 from David Wei/ts_fix_iconselect
2023-08-29 08:10:41 +00:00
David Wei e43149f8e6 fix 菜单图标选择器显示不全 2023-08-29 15:48:03 +08:00
疯狂的狮子Li 1d8664ab1d fix 修复 租户与套餐管理 搜索框长度变化问题 2023-08-28 17:21:01 +08:00
疯狂的狮子Li e7529fbb8f update 优化 登录页面redirect重定向功能 2023-08-25 12:58:52 +08:00
疯狂的狮子Li e10f112fa0 fix 修复 使用 localStorage 返回值为null问题 2023-08-15 13:53:34 +08:00
疯狂的狮子Li e906b8ad0a update 优化 全局移除cookie使用 避免安全问题 2023-08-14 12:56:31 +08:00
疯狂的狮子Li 1690563ef0 update 优化 涉及到用户密码的接口 均设置请求加密 2023-08-14 11:25:19 +08:00
疯狂的狮子Li 9087fad3fe update 优化 涉及到用户密码的接口 均设置请求加密 2023-08-14 10:36:59 +08:00
疯狂的狮子Li f3195be732 update 优化 整体代码结构 2023-08-11 17:59:10 +08:00
疯狂的狮子Li 73df6a1b30 !34 修复编译报类型错误问题
Merge pull request !34 from VergLsm/ts
2023-08-09 07:18:25 +00:00
lishanming b221ff2566 fix 修复编译报类型错误问题 2023-08-09 15:15:10 +08:00
疯狂的狮子Li 50891e99ac fix 修复 无法获取token问题 将 globalHeaders 改为函数 2023-08-09 12:59:18 +08:00
疯狂的狮子Li 53ac5fb43c !33 将部门管理 负责人选项改为下拉框选择
Merge pull request !33 from Lionel./deptHead
2023-08-09 02:47:41 +00:00
Lionel 7e54fe7921 将部门管理 负责人选项改为下拉框选择
从当前部门的用户列表选择一个人做绑定 后端接收用户ID
2023-08-08 11:43:11 +08:00
疯狂的狮子Li 3637c16d86 update 优化 删除字典无用状态字段(基本用不上 禁用后还会导致回显问题) 2023-08-07 17:23:27 +08:00
疯狂的狮子Li b045cb4239 fix 修复 注册页验证码不显示问题 2023-08-01 11:00:41 +08:00
疯狂的狮子Li 0c791a1efc update 优化 封装全局统一请求头 2023-07-25 15:59:35 +08:00
疯狂的狮子Li 0082354aba fix 修复 oss上传与zip下载未传输clientid问题 2023-07-25 11:40:29 +08:00
MichelleChung acbdfc4639 !31 【轻量级 PR】新增全局请求头 clientid 适配后端 token 校验
Merge pull request !31 from MichelleChung/ts
2023-07-24 11:22:20 +00:00
疯狂的狮子Li f801f4fb11 fix 修复 固定页面header穿模问题 2023-07-24 16:47:51 +08:00
疯狂的狮子Li d532dc6fc0 !30 【轻量级 PR】修改验证码路径适配 cloud
Merge pull request !30 from MichelleChung/ts
2023-07-20 14:36:06 +00:00
Michelle.Chung 452972c1e4 update 修改验证码路径适配 cloud ; 2023-07-20 18:35:04 +08:00
ahaos ac3ad63894 !29 修改列表打开对话框和接口请求顺序
Merge pull request !29 from ahaos/tspr
2023-07-19 14:48:30 +00:00
三个三 d69f0992c7 !27 修复,[VueTypes warn]: VueTypes.extend is deprecated.警告问题
Merge pull request !27 from 三个三/ts
2023-07-14 16:09:34 +00:00
疯狂的狮子Li e64f4b83c8 update 优化 toggleRowSelection 缺失一个参数警告问题 2023-07-14 22:39:34 +08:00
疯狂的狮子Li 2b1cbaf8a0 update 优化 login 页面编辑器类型警告问题 2023-07-14 22:32:21 +08:00
疯狂的狮子Li 6c86aa42fd update 优化 无用加密前端加密没意义 2023-07-14 15:28:15 +08:00
疯狂的狮子Li e79a9cf797 !26 update src/api/types.ts.
Merge pull request !26 from Admin/N/A
2023-07-13 12:42:32 +00:00
Admin 4af9f025b0 update src/api/types.ts.
修改符号

Signed-off-by: Admin <zhangchong@chenzhimr.com>
2023-07-13 12:40:37 +00:00
疯狂的狮子Li 2a1d0edd4e update 优化 三方按钮 可能无法点击到的问题 2023-07-13 16:28:59 +08:00
疯狂的狮子Li 75e72bf974 update 优化 三方授权页面 延迟跳转避免无法查看错误信息 2023-07-13 16:19:29 +08:00
疯狂的狮子Li 1d33b01c66 add 新增 对接 maxkey 三方单点登录 优化三方登录按钮位置 2023-07-13 15:38:32 +08:00
疯狂的狮子Li 73c14596ed update 优化 将公钥放置到配置文件方便修改 删除私钥避免泄漏 2023-07-12 16:57:22 +08:00
疯狂的狮子Li 5fa3f9a350 reset 回滚 错误修复 并增加正确修复 2023-07-12 13:52:59 +08:00
疯狂的狮子Li 64aea65cef fix 修复 删除无用的参数获取 2023-07-12 11:14:18 +08:00
疯狂的狮子Li a681353fe1 fix 修复 解绑三方应用不刷新页面数据问题 2023-07-12 10:48:33 +08:00
疯狂的狮子Li 9719d6d75c fix 修复 部门搜索框使用错误问题 2023-07-12 10:32:31 +08:00
疯狂的狮子Li c13c622eac !25 部分优化以及新增功能
Merge pull request !25 from ahaos/tspr
2023-07-11 13:03:01 +00:00
LiuHao d160c3a61c merge 2023-07-10 22:56:42 +08:00
疯狂的狮子Li 81195fd9c8 add 新增 请求加密传输 合并优化 !pr377 2023-07-10 18:21:52 +08:00
疯狂的狮子Li d0d67b90bc add 新增 请求加密传输 合并优化 !pr377 2023-07-10 18:20:38 +08:00
疯狂的狮子Li 9e3dd2c6e3 update 优化 页签在Firefox浏览器被遮挡 2023-07-06 09:48:36 +08:00
疯狂的狮子Li 5920b10514 发布 5.1.0-BETA 公测版本 2023-07-05 16:37:17 +08:00
疯狂的狮子Li 617dfe3161 update 优化替换过期的文档地址 2023-07-04 17:46:32 +08:00
疯狂的狮子Li 40175c150c update 优化 下载zip方法增加遮罩层 2023-07-04 16:39:05 +08:00
疯狂的狮子Li d930b15104 fix 修复 缓存监控图表 支持跟随屏幕大小自适应调整 2023-07-04 15:50:36 +08:00
疯狂的狮子Li cc69786fd1 update 优化 !pr382 修复一些问题 完事流程逻辑 2023-07-02 16:48:57 +08:00
疯狂的狮子Li 4cf836055a !23 统一登录,授权
Merge pull request !23 from 三个三/auth
2023-07-02 07:40:13 +00:00
疯狂的狮子Li 88b376bbc2 !21 回退 'Pull Request !20 : 统一登录授权'
Merge pull request !21 from 疯狂的狮子Li/revert-merge-20-dev
2023-07-02 07:33:26 +00:00
疯狂的狮子Li 3fb8f1c251 回退 'Pull Request !20 : 统一登录授权' 2023-07-02 07:32:58 +00:00
三个三 a8f575fe6f !20 统一登录授权
* 统一授权登录
* 对接后端更改做了适配,
* 前端实现切换租户选择第三方授权登录,和优化第三方页面登录注册
2023-07-02 07:29:28 +00:00
thiszhc 14cf3be392 统一授权登录 2023-07-01 16:24:48 +08:00
thiszhc 6e3aec7c50 对接后端更改做了适配, 2023-07-01 15:05:48 +08:00
thiszhc 2b7ffdf19c 前端实现切换租户选择第三方授权登录,和优化第三方页面登录注册 2023-07-01 02:26:58 +08:00
疯狂的狮子Li db6e95bb96 fix 修复 菜单管理字段不对应问题 2023-06-30 14:54:32 +08:00
疯狂的狮子Li 7b6078a178 !15 适配登录重构的修改
Merge pull request !15 from MichelleChung/ts
2023-06-28 06:28:45 +00:00
Michelle.Chung 892c84f32a update 更新字段命名 activityTimeout -> activeTimeout ;
update 新增字段设备类型 deviceType ;
2023-06-27 09:03:51 +08:00
疯狂的狮子Li 9b6dc3e844 fix 修复 三方调用跳转白屏问题(临时修复) 2023-06-27 08:33:06 +08:00
疯狂的狮子Li 3b4950e0e3 fix 修复 前端参数漏改导致三方跳转失败问题 2023-06-27 08:33:06 +08:00
疯狂的狮子Li 7340997cf5 update 优化 !pr370 完成三方登录授权功能 2023-06-27 08:33:06 +08:00
三个三 3b4ac3e525 !16 扩展第三方登录授权功能
* add 第三方授权
* add 第三方授权登录
2023-06-27 08:33:06 +08:00
yhan219 cab430a428 !12 [需求认领] 对接 powerjob 实现分布式任务调度 集成方式参考框架内 xxl-job
* [需求认领] 对接 powerjob 实现分布式任务调度 集成方式参考框架内 xxl-job
2023-06-27 08:33:06 +08:00
LiuHao 538c52a3ad add 增加cache类型声明 2023-06-23 20:56:42 +08:00
LiuHao 25e80590f6 update modal各方法参数类型 2023-06-23 20:49:22 +08:00
LiuHao 7f68832edd add auth类型声明 2023-06-23 20:45:50 +08:00
LiuHao 374ee5d1a8 update 删除alertSuccess方法参数 2023-06-23 20:40:00 +08:00
LiuHao d557602f2d update 关闭标签参数可选 2023-06-23 20:22:36 +08:00
疯狂的狮子Li 18dd68edd5 fix 修复 三方调用跳转白屏问题(临时修复) 2023-06-21 17:03:26 +08:00
疯狂的狮子Li 13bb23c717 fix 修复 前端参数漏改导致三方跳转失败问题 2023-06-21 16:08:50 +08:00
LiuHao 319b37fe98 合并 ts 2023-06-20 19:15:58 +08:00
LiuHao a8ed066d8d update 修改删除tag方法 增加无参refreshPage 2023-06-20 18:57:27 +08:00
疯狂的狮子Li 40e3bcb391 update 优化 !pr370 完成三方登录授权功能 2023-06-20 15:00:29 +08:00
三个三 aae6bb7505 !16 扩展第三方登录授权功能
* add 第三方授权
* add 第三方授权登录
2023-06-20 04:12:49 +00:00
Michelle.Chung 952a2ba906 fix 修正注释错误 ; 2023-06-19 08:49:55 +08:00
LiuHao 3b3fb80231 add 新增路由跳转自定义title 2023-06-18 23:47:10 +08:00
LiuHao a46c511f1f add 新增ElScrollbarInstance 2023-06-18 22:31:35 +08:00
Michelle.Chung ed84745897 update 更新列表授权类型展示 ; 2023-06-18 19:58:58 +08:00
Michelle.Chung 44ea10d9c7 add 新增客户端管理页面 ; 2023-06-18 16:58:28 +08:00
yhan219 41d140af11 !12 [需求认领] 对接 powerjob 实现分布式任务调度 集成方式参考框架内 xxl-job
* [需求认领] 对接 powerjob 实现分布式任务调度 集成方式参考框架内 xxl-job
2023-06-16 15:58:13 +00:00
Michelle.Chung 0f54604435 update 适配登录重构的修改(修改token命名, 修改接口传参) ; 2023-06-16 20:32:46 +08:00
LiuHao d43ae50abc update 修改组件 去除无用引用和代码缩进 2023-06-06 22:52:24 +08:00
LiuHao 9f038ad181 add 新增ele类型声明 2023-06-06 22:52:02 +08:00
LiuHao dbfe263681 update 修改代码缩进格式 2023-06-06 22:27:31 +08:00
LiuHao 6af68085ff update 修改页面代码 去除ele的引入以及vue的类型声明 2023-06-06 22:23:43 +08:00
LiuHao 490d4ef47e add 新增全局ele类型声明 2023-06-06 22:20:50 +08:00
LiuHao bc48b224eb update 修改默认导入 2023-06-06 20:55:50 +08:00
LiuHao 9cd7f6cabb update 修改类型声明 2023-06-06 20:55:23 +08:00
LiuHao 3267f59603 add vue全局声明、Ele全局实例、类型声明 2023-06-06 20:54:52 +08:00
LiuHao bc4554baeb add 相关全局属性 2023-06-06 20:45:34 +08:00
LiuHao e6a3b6360f add 相关全局属性 2023-06-06 20:44:40 +08:00
LiuHao 548550bb42 add propTypes工具以及vue-types 2023-06-06 20:41:44 +08:00
LiuHao 7c09eb50a7 update 去掉el的引入 2023-06-06 20:06:57 +08:00
LiuHao d6cb1c6634 update 操纵日志和登录日志 card的shadow -> hover 2023-06-06 16:50:32 +08:00
LiuHao cbff04778b update 代码生成列表card展示风格。 2023-06-06 16:47:40 +08:00
LiuHao f6994e5908 update 菜单列表去掉表格 2023-06-06 16:33:19 +08:00
LiuHao 06bc04c04c Merge remote-tracking branch 'origin/dev' into dev
# Conflicts:
#	src/views/tool/gen/index.vue
2023-06-06 16:27:48 +08:00
疯狂的狮子Li 226e0f3494 !10 update vite/plugins/unocss.ts.
Merge pull request !10 from running0503/N/A
2023-05-31 14:55:02 +00:00
running0503 7757d96f34 update vite/plugins/unocss.ts.
因低浏览器不支持 top-level await,会报 __uno.css:9 Uncaught SyntaxError: Unexpected reserved word

hmrTopLevelAwait
unocss默认是true,低版本浏览器是不支持启动后会报错

Signed-off-by: running0503 <xiangdeshan_120@sina.com>
2023-05-31 07:27:16 +00:00
疯狂的狮子Li a8ad928324 !9 代码生成,数据名称从后台加载
Merge pull request !9 from WangBQ/ts
2023-05-29 02:26:23 +00:00
疯狂的狮子li f0df76aa8b fix 修复 角色数据覆盖问题 2023-05-26 11:26:47 +08:00
LiuHao 0ede92a2e5 Merge branch 'ts' into dev 2023-05-24 11:20:52 +08:00
疯狂的狮子li 21ab064cf7 fix 修复 oss 配置 预览开关点×关闭控制台报错问题 2023-05-19 17:40:53 +08:00
疯狂的狮子li 84212c0a1b ✨发布 5.0.0 SpringBoot3 携手多租户强势来袭 2023-05-19 09:45:06 +08:00
LiuHao 6de98250cc fix issues #I7657W 2023-05-19 01:32:24 +08:00
LiuHao 997f565add update contextmenu color 2023-05-17 13:49:33 +08:00
BQ·Wong a326e663cd 代码生成,数据名称从后台加载 2023-05-13 11:45:51 +08:00
LiuHao bf4a8543ca Merge branch 'ts' into dev
# Conflicts:
#	package.json
#	src/layout/components/TagsView/index.vue
2023-05-06 09:25:05 +08:00
LiuHao 9b6cd8b047 DictTag组件,当value没有匹配的值时,展示value 2023-05-05 11:34:55 +08:00
LiuHao 46e7d070a2 恢复翻页/切换路由滚动功能 2023-05-05 11:06:32 +08:00
LiuHao ec29c057c4 修复开启TopNav后一级菜单路由参数设置无效问题 2023-05-05 10:36:21 +08:00
LiuHao 2885d7e31c Merge remote-tracking branch 'origin/ts' into ts 2023-05-05 10:25:41 +08:00
LiuHao 0e736c889f 优化已选择下拉图标高亮回显 2023-05-05 10:23:41 +08:00
疯狂的狮子li d192f73ca4 update 优化 避免鼠标移出时无法隐藏滚动条的问题 2023-05-04 19:48:40 +08:00
疯狂的狮子Li 351eedacec fix 修复 角色与用户 无法分页问题 2023-04-28 22:40:55 +08:00
疯狂的狮子li 67864e67b3 fix 修复 oss 路径漏改问题 2023-04-26 22:47:28 +08:00
疯狂的狮子Li f5a21c9b6f !7 修改oss模块路由地址
Merge pull request !7 from Yjoioooo/ts
2023-04-25 02:49:40 +00:00
Yjoioooo b9dccb325f update 修改oss模块路由地址 2023-04-25 10:13:27 +08:00
LiuHao 7cfaeb5531 fix ElSelect导入包 2023-04-24 13:50:25 +08:00
LiuHao 94f96181f3 add DarkMode 2023-04-22 01:05:11 +08:00
LiuHao 5dda9da40d update 升级vite版本4.1.4->4.3.1 2023-04-21 11:24:26 +08:00
LiuHao 1eda36201a update code style 2023-04-21 11:17:07 +08:00
LiuHao 4722a8ef9b fix 升级vite版本4.1.4->4.3.1 2023-04-21 11:14:58 +08:00
LiuHao 0ba7e31e09 fix 部门管理 上级菜单问题 2023-04-20 22:57:33 +08:00
疯狂的狮子li 61417032b7 fix 修复 代码生成菜单选项回显问题 2023-04-20 18:45:29 +08:00
疯狂的狮子li a0bcdf0cde fix 修复 oss配置 页面权限标识符错误 2023-04-20 18:02:51 +08:00
LiuHao b263918426 update searchMenu style 2023-04-19 23:25:34 +08:00
LiuHao 771f49354a update 修改列表搜索面板组件类型 2023-04-19 21:29:25 +08:00
LiuHao ab12c9cc94 update 修改列表搜索面板组件类型 2023-04-19 21:26:07 +08:00
LiuHao 2976130876 add form build 2023-04-19 21:04:42 +08:00
LiuHao 2ddd42bbab update 修改列表搜索面板style 2023-04-19 21:04:24 +08:00
LiuHao f2d1522c34 update 列表搜索面板组件类型 2023-04-19 21:04:01 +08:00
LiuHao fda317b628 update 修改非时效性数据存入Local中 2023-04-19 14:41:15 +08:00
LiuHao f153da4390 fix 修复参数遗漏 2023-04-19 14:30:30 +08:00
LiuHao 20f64b54d5 fix 修改国际化文件名称不规范问题,增加reqeust 国际化配置 2023-04-19 11:05:30 +08:00
LiuHao 4775803427 优化 样式 2023-04-18 23:44:54 +08:00
LiuHao d2bce3fcbe add i18n 2023-04-18 23:36:26 +08:00
疯狂的狮子li 55e29ce697 add 增加 租户套餐下拉选接口 过滤掉已经关闭的套餐 2023-04-18 13:24:51 +08:00
疯狂的狮子li 802f6240d4 update 优化 套餐新增 状态被覆盖为空问题 2023-04-18 13:08:35 +08:00
LiuHao 91bb79e29f update search style 2023-04-17 23:11:08 +08:00
LiuHao fb14197b0e update 修改card --hover 2023-04-17 22:36:26 +08:00
LiuHao e2bc12d186 update 修改 el-card shadow='hover' 2023-04-17 22:23:18 +08:00
LiuHao b88a09dd7f update 修改dialog弹窗在窗内滚动 2023-04-17 21:56:16 +08:00
LiuHao 2ede1095a3 fix 代码生成-生成信息-上级菜单的数据回显问题 2023-04-17 21:39:21 +08:00
LiuHao c32e3ce2c9 update 修改tree-select选择器为ele官网选择器 2023-04-17 21:26:23 +08:00
LiuHao c25842a0e5 remove console.log 2023-04-17 20:50:00 +08:00
疯狂的狮子Li e7c777ac50 fix 修复 DemoTree 实体缺少属性 2023-04-16 15:42:56 +08:00
疯狂的狮子Li 1a5ed27067 fix 修复 prod 配置文件监控中心路径不正确问题 2023-04-16 15:39:34 +08:00
疯狂的狮子Li fed8eb76f6 fix 修复 取消oss预览状态修改 图标变化不正常问题 2023-04-14 22:29:42 +08:00
疯狂的狮子Li f9298a3f41 add 项目代码格式化工具 2023-04-13 22:21:45 +08:00
LiuHao 155f22b72c fix 用户头像上传失败问题 2023-04-13 18:59:33 +08:00
LiuHao dd01200e2a fix 防重实效问题 2023-04-13 18:38:35 +08:00
LiuHao 35eafbb065 add editorconfig 2023-04-13 18:19:15 +08:00
疯狂的狮子li a05a782ef5 fix 修复 用户管理权限标识符不正确问题 2023-04-12 16:49:33 +08:00
LiuHao 14b4508b91 fix 用户状态修改按钮显示问题 2023-04-12 10:29:51 +08:00
LiuHao 8111ed9a84 fix 自定义数据权限部门丢失 2023-04-12 10:23:18 +08:00
疯狂的狮子li 9a070b0074 add 增加预编译 2023-04-06 11:28:38 +08:00
疯狂的狮子li a79fa2527a update 修复页面切换时布局错乱的问题(I6LR1D) 2023-04-06 11:19:43 +08:00
疯狂的狮子li c65536ee6f update 优化弹窗后导航栏偏移的问题(I3YMWW) 2023-04-06 11:19:31 +08:00
疯狂的狮子li ccbe849103 update 关闭页签后存在其他页签时不应该跳转首页 2023-04-06 11:14:23 +08:00
疯狂的狮子li f0b52d7abb update 优化固定头部页签滚动条被隐藏的问题 2023-04-06 11:12:24 +08:00
疯狂的狮子li d37e031014 update 移除vue-multiselect样式 2023-04-06 11:10:22 +08:00
疯狂的狮子Li 07a9b6e612 update 优化 demo 界面代码 2023-04-05 20:12:11 +08:00
LiuHao f4522d2caa add 增加预编译tabs css 2023-04-04 14:36:24 +08:00
LiuHao 582df2e467 add plugin vue-setup-extend 2023-04-04 14:28:56 +08:00
LiuHao 8c866f4596 fix name 2023-04-04 14:28:24 +08:00
LiuHao 3b3f26f610 fix import 2023-04-04 14:28:02 +08:00
疯狂的狮子Li d4ffd28ffb !5 新增预编译配置
Merge pull request !5 from MichelleChung/ts
2023-04-03 04:00:58 +00:00
zlyx ee59b3be8b update 更新 vite.config.ts 预编译内容 (thanks: 基哥) ; 2023-04-03 11:48:39 +08:00
疯狂的狮子Li 97187b246b update 调整代码格式 2023-04-03 00:26:04 +08:00
疯狂的狮子Li a7a31b011a update 删除编译生成的文件 调整忽略策略 2023-04-03 00:09:17 +08:00
疯狂的狮子Li 1595cb282a update 调整代码格式 2023-04-03 00:05:09 +08:00
疯狂的狮子Li 8b01bfd2a0 Merge remote-tracking branch 'origin/ts' into ts 2023-04-02 23:54:03 +08:00
LiuHao 60d064b319 fix type error 2023-04-02 23:33:28 +08:00
疯狂的狮子Li cc0bedffb9 update 默认端口修改为80 2023-04-02 22:40:36 +08:00
LiuHao 3b93c8ac56 perf hide userPage and rolePage id field 2023-04-02 22:11:47 +08:00
LiuHao 631a831609 fix button style 2023-04-02 22:01:28 +08:00
LiuHao 327e60d9f3 fix profile 2023-04-02 21:52:22 +08:00
LiuHao 457b443404 fix animation and router type 2023-04-02 21:40:03 +08:00
LiuHao 0408b67d6d fix Copyright 2023-04-02 18:08:48 +08:00
LiuHao c7c63c51de fix style and add plugin 2023-04-02 15:07:14 +08:00
LiuHao d95fab75a7 perf element global config 2023-04-02 14:15:47 +08:00
LiuHao 251d2411f2 refactor ts 2023-04-02 01:01:56 +08:00
疯狂的狮子li 5c87f1cb2c update 项目正式入驻 dromara 开源社区 更改项目地址 2023-03-23 17:28:43 +08:00
疯狂的狮子li d2a44d682d update 全新文档 全面上线 2023-03-23 14:20:41 +08:00
疯狂的狮子Li 4a5ba86e38 !1 修复后台验证码获取接口地址
Merge pull request !1 from scmiot/master
2023-03-21 10:36:08 +00:00
scmiot eec0fd43a3 修复后台验证码获取接口地址,源地址为短信验证码接口。
Signed-off-by: scmiot <scmiot@qq.com>
2023-03-21 10:24:09 +00:00
疯狂的狮子li 8fec6cc405 update 更新 readme 说明 更改框架定位 2023-03-15 17:17:48 +08:00
疯狂的狮子li 6b6c78fa02 update 更新 readme 说明 2023-03-15 16:08:14 +08:00
疯狂的狮子li d68654327a 合并 vue与cloud vue3 前端项目 2023-03-15 15:59:21 +08:00
483 changed files with 33508 additions and 40415 deletions
-60
View File
@@ -1,60 +0,0 @@
---
name: frontend-api-types
description: 前端 API 与类型定义专家。用于当前 plus-ui-react 项目中的 src/api 层、types.ts、返回结构、Query/Form/VO/InfoVO 定义,以及前后端接口映射任务。
---
你负责当前 plus-ui-react 项目中的 API 层和类型定义。
## 核心原则
1. 先看当前模块已有 `src/api/<module>/<business>`。
2. API 路径、返回类型、函数命名、导出风格与当前模块保持一致。
3. 能明确写出类型时,不要偷懒用 `any`。
4. 如果当前模块已有特殊返回结构或聚合导出,继续保持一致。
5. 不创建页面,不改路由,除非用户明确要求。
6. 如果用户要求维护代码生成模板,优先同步当前仓库 `gen/api.ts.ftl`、`gen/types.ts.ftl`,必要时再看 boot4 后端 generator 字段定义。
## API 规则
- 标准 import:
`import type { PageResult, R } from '@/api/types';`
`import request from '@/api/request';`
`import type { XxxForm, XxxQuery, XxxVO } from './types';`
- 分页列表:`GET /<module>/<business>/list`,返回 `R<PageResult<XxxVO>>`。
- 树表列表:返回 `R<XxxVO[]>`。
- 详情:`GET /<module>/<business>/{id}`,返回 `R<XxxVO>` 或业务 `InfoVO`。
- 新增:`POST /<module>/<business>`,请求体用 `data`。
- 修改:`PUT /<module>/<business>`,请求体用 `data`。
- 删除:`DELETE /<module>/<business>/{id or ids}`。
- 状态切换:`PUT /<module>/<business>/changeStatus`,参数形态参考后端和相邻模块。
- query string 用 `params`,请求体用 `data`。
- 不要从 `axios` 引入 `AxiosPromise`。
## 类型规则
- 标准类型定义 `VO`、`Form`、`Query`。
- 必要时补 `InfoVO`、`TreeVO`、`ResetPwdForm`、`OptionVO` 等扩展类型。
- `Form` 通常继承 `BaseEntity`。
- 非树表 `Query` 通常继承 `PageQuery`。
- 树表 `Query` 通常不继承 `PageQuery`。
- ID 字段通常使用 `string | number`。
- 批量删除参数使用 `string | number | Array<string | number>`。
- Java 数值类型映射为 `number`,Boolean 映射为 `boolean`,日期和文本默认 `string`。
- 日期范围查询保留 `params?: Record<string, unknown>` 或跟随相邻模块,不要无故删除。
- 列表对象、表单对象、查询对象职责分开;字段不一致时不要强行复用一个接口。
## gen 模板规则
- `gen/api.ts.ftl` 和 `gen/types.ts.ftl` 是当前 React 项目内置模板,优先于外部后端模板。
- 保持 Velocity 变量、宏和输出路径约定,不要破坏后端 generator 可替换变量。
- 输出类型应继续使用 `R`、`PageResult`、`PageQuery`、`BaseEntity` from `@/api/types` 和 `request` from `@/api/request`。
- 不输出 Vue 版 `AxiosPromise`、`@/utils/request` 或 `src/views` 约定。
## 自检
- API 路径是否与后端一致。
- 类型是否覆盖接口真实结构。
- 是否不必要地把类型写宽了。
- 是否保留了当前模块的命名和导出风格。
- 是否同步维护了当前项目内置 `gen/*.ftl` 模板中对应 API/types 输出。
- 是否误用了 Vue 版 `AxiosPromise`、`@/utils/request` 或 `src/views` 约定。
-39
View File
@@ -1,39 +0,0 @@
---
name: frontend-crud-coding
description: 前端总入口。用于当前 plus-ui-react 项目中的标准 React CRUD 页面、新增 API/types、复杂列表页增强、树筛选、导入导出、权限按钮、状态切换、弹窗表单和项目内置 gen/*.ftl React 代码生成模板维护任务,并根据任务类型选择合适的前端子 agent。
---
你是当前 plus-ui-react 前端项目的总入口 agent。
先判断任务类型,再按下面规则处理:
1. 如果是新增标准 CRUD 页面、补 `src/api`、`types.ts`、`index.tsx`,优先使用 `frontend-crud-page.md`。
2. 如果是修改已有列表页、增强导入导出、树筛选、详情抽屉、更多操作、状态切换,优先使用 `frontend-page-enhancement.md`。
3. 如果只改接口层和类型定义,优先使用 `frontend-api-types.md`。
4. 如果是维护代码生成模板,优先读取当前仓库 `gen/api.ts.ftl`、`gen/types.ts.ftl`、`gen/index.tsx.ftl`、`gen/index-tree.tsx.ftl`,再按 React 项目真实工具和页面规则修改模板。
通用要求:
- 先读当前目录下最近似页面和 API,再动代码。
- 优先参考 `.codex/skills/frontend-crud-coding/SKILL.md` 和 `references/frontend.md`,保持 Claude agent 与 Codex skill 规则一致。
- 冲突时优先相信当前项目真实页面,其次是公共组件、hooks、工具和请求封装,再其次是当前仓库 `gen/*.ftl` React 模板,最后才是 Vue 参考项目和关联后端工程 generator 模板。
- 默认直接产出可落地代码,而不是只给抽象建议。
- 不要照搬 Vue 项目的 `src/views`、Element Plus、`AxiosPromise`、`v-hasPermi`、`ref/reactive` 写法。
当前项目关键约定:
- 页面目录是 `src/pages`。
- 请求封装是 `@/api/request`。
- API 外层类型是 `R<T>`,分页类型是 `PageResult<T>`,都来自 `@/api/types`。
- 标准页面优先使用 `PageContainer`、`ProTable`、`ModalForm`、ProForm 组件。
- 权限通过 `useUserStore` 和 `hasPermi` 计算布尔值。
- 多选通过 `useTableSelection`,导出通过 `useTableExport`。
- 行操作优先使用 `RowActions` 和 `@ant-design/icons`。
- 日期范围、字典 options、树表展开、loading、搜索重置和确认弹窗优先使用 `useDateRangeQuery`、`dictOptions`、`useTreeTableExpand`、`useLoading`、`useSearchReset`、`confirmAction`/`confirmTitleSafe`。
- `gen/index.tsx.ftl`、`gen/index-tree.tsx.ftl` 内容必须生成 React TSX 页面。
验证要求:
- 改 TS/TSX/API/types 后优先运行 `pnpm lint` 或 `pnpm exec tsc --noEmit`。
- 改公共组件、hooks、构建配置或较大范围页面后运行 `pnpm build`。
- 如果验证失败或无法运行,交付时说明命令和原因。
-73
View File
@@ -1,73 +0,0 @@
---
name: frontend-crud-page
description: 前端标准 React CRUD 页面专家。用于当前 plus-ui-react 项目中的新建列表页、弹窗表单页、标准 API/types/index.tsx 骨架、项目内置 gen/*.ftl React 模板维护,以及后端 generator 字段到 React + ProTable 项目风格的落地任务。
---
你负责当前 plus-ui-react 项目中的标准 CRUD 页面实现。
## 核心原则
1. 先看当前模块最近似页面。
2. 再参考 `.codex/skills/frontend-crud-coding/references/frontend.md`。
3. 维护或新增生成能力时,优先参考当前仓库 `gen/api.ts.ftl`、`gen/types.ts.ftl`、`gen/index.tsx.ftl`、`gen/index-tree.tsx.ftl`。
4. 必要时参考关联后端工程 generator 模板确认接口、字段、权限和导出能力。
5. 默认同时维护:
`src/api/<module>/<business>/index.ts`
`src/api/<module>/<business>/types.ts`
`src/pages/<module>/<business>/index.tsx`
## 优先参考
- 标准单表:`src/pages/demo/demo/index.tsx`、`src/api/demo/demo/*`。
- 树表:`src/pages/demo/tree/index.tsx`、`src/pages/workflow/category/index.tsx`。
- 系统管理:`src/pages/system/user/index.tsx`、`system/role`、`system/post`、`system/config`。
- workflow:`src/pages/workflow/*`、`src/api/workflow/*`。
## 页面规则
- 页面默认导出函数组件,命名如 `SystemClientPage`、`DemoDemoPage`、`WorkflowCategoryPage`。
- 标准结构通常包含 `PageContainer`、`ProTable`、工具栏按钮、`ModalForm`。
- 常见状态:
`actionRef`、`form`、`modalOpen`、`modalTitle`、`ids`、`selectedOne`、权限布尔值。
- 表格列使用 `ProColumns<XxxVO>[]`。
- 分页列表的 `request` 中使用 `toPageQuery(params)`、`updateExportParams(query)`、`listXxx(query)`、`toTableData(res)`。
- 多选使用 `useTableSelection<XxxVO>(row => row.id)`。
- 导出使用 `useTableExport()` 和 `exportFile('/module/business/export', () => 'business_timestamp.xlsx')`。
- 行操作使用 `RowActions`,行内删除确认放在 `confirm`。
- 新增/编辑弹窗使用 `ModalForm<XxxForm>`,字段优先使用 ProForm 组件。
- 日期范围使用 `useDateRangeQuery`,字典 options 使用 `dictOptions`。
- 状态切换等 Promise 式确认使用 `confirmAction` 或 `confirmTitleSafe`。
- 异步 loading 优先使用 `useLoading`,带额外筛选状态的重置优先使用 `useSearchReset`。
## API / types 规则
- 请求统一通过 `@/api/request`。
- 同目录维护 `index.ts` 与 `types.ts`。
- 标准 CRUD 通常包含:列表、详情、新增、修改、删除。
- 列表分页接口通常返回 `request<R<PageResult<XxxVO>>>`。
- 树表列表接口通常返回 `request<R<XxxVO[]>>`。
- 不要从 `axios` 引入 `AxiosPromise`。
## 树表规则
- 判断树表后不要生成分页 `PageResult` 页面。
- `Query` 通常不继承 `PageQuery`。
- 使用 `handleTree`、`pagination={false}`、`useTreeTableExpand`、`ProFormTreeSelect`。
- 树表展开/折叠优先使用 `useTreeTableExpand`,不要在页面或模板里重复手写收集 key 的状态逻辑。
- 新增子节点时从当前行带入 `parentId`。
## gen 模板规则
- `gen/index.tsx.ftl`、`gen/index-tree.tsx.ftl` 内容生成 React TSX。
- 保持 Velocity 变量、宏和后端 generator 可识别结构,不为了格式美化破坏模板语法。
- 模板应输出当前项目公共工具写法:`useTableSelection`、`useTableExport`、`useDateRangeQuery`、`dictOptions`、`useTreeTableExpand`、`confirmAction`、`toPageQuery`、`toTableData`、`handleTree`。
- 不把 Vue `src/views`、Element Plus、`AxiosPromise`、`v-hasPermi` 写入模板。
## 自检
- API 路径是否与后端一致。
- `index.ts` 与 `types.ts` 是否同步补齐。
- 页面是否使用 React 项目的 ProTable/ModalForm 骨架。
- 权限标识是否与后端和相邻页面一致。
- 是否同步使用当前项目公共 hooks/工具,避免生成重复代码。
- 是否误用了 Vue/Element Plus/`src/views` 规则。
@@ -1,58 +0,0 @@
---
name: frontend-page-enhancement
description: 复杂前端页面增强专家。用于修改当前 plus-ui-react 项目中已经存在的列表页、树筛选页、带导入导出、详情抽屉、更多操作和状态切换的页面,强调增量修改和保留现有交互能力。
---
你负责当前 plus-ui-react 项目中已有页面的增强,不是重写页面。
## 核心原则
1. 优先阅读当前页面完整实现和相关子组件。
2. 增量修改,不重写整页。
3. 保留已有树筛选、导入导出、列显隐、详情抽屉、更多操作、状态切换、路由跳转、权限控制和样式壳。
4. 不要把复杂页面退化成 demo/generator 式基础列表页。
5. 修改前先看 `.codex/skills/frontend-crud-coding/references/frontend.md` 中对应规则。
## 常见任务
- 调整工具栏按钮和行操作。
- 增加筛选条件和日期范围。
- 增加导入、导出能力。
- 增加状态切换、快捷操作、确认弹窗。
- 增加详情抽屉或增强现有抽屉。
- 补复杂页面的小型子功能。
- 接入新 API 并保持现有页面状态流。
## React 项目约定
- 表格页通常使用 `PageContainer` + `ProTable`。
- 复杂系统页可包含 `TreePanel`、子组件弹窗、抽屉、授权路由跳转。
- 权限通过 `useUserStore` + `hasPermi` 计算,不使用 Vue 指令。
- 字典通过 `useDict` 加载,按现有页面映射为 Ant Design options。
- 字典 options 优先使用 `dictOptions` from `@/utils/dict`。
- 导出通过 `useTableExport`,不要另写下载封装。
- 多选通过 `useTableSelection`,不要手写一套重复状态。
- 日期范围优先使用 `useDateRangeQuery`,底层保持 `addDateRange` 参数格式。
- 树表展开优先使用 `useTreeTableExpand`。
- 异步 loading 优先使用 `useLoading`。
- 额外筛选状态的重置优先使用 `useSearchReset`。
- Promise 式确认框优先使用 `confirmAction` 或 `confirmTitleSafe`。
- 状态切换失败时回滚或刷新,参考 `system/user`。
## 增量修改规则
- 如果页面已有子组件,如 `UserFormModal`、`UserImportModal`、`UserDetailDrawer`,优先修改或复用子组件,不把所有逻辑堆回主页面。
- 如果页面已有权限布尔值,沿用同一命名风格补新权限。
- 如果页面已有导出参数缓存,继续通过 `updateExportParams` 更新。
- 如果页面已有树筛选状态,查询参数要合并该状态,不要覆盖掉。
- 如果页面已有特殊禁用规则、超级管理员保护或业务状态判断,必须保留。
- 如果增强的是标准 CRUD 能力或公共工具约定,要评估当前仓库 `gen/*.ftl` 是否也应同步更新。
## 自检
- 是否破坏了原页面结构和样式。
- 是否误删了已有权限控制或交互能力。
- 是否保留了树筛选、导入导出、抽屉、路由跳转等复杂能力。
- 是否应该拆成子组件而不是继续堆主页面。
- 是否使用了当前项目已有工具,避免重复手写日期范围、字典 options、树展开、loading、确认框。
- 是否误用了 Vue/Element Plus/generator 的简化逻辑。
-162
View File
@@ -1,162 +0,0 @@
---
name: frontend-crud-coding
description: 在当前 plus-ui-react 前端项目中按真实 React + TypeScript + Umi Max + Ant Design ProComponents + oxlint/oxfmt 代码风格生成或修改页面、API、types、hooks 接入、样式和项目内置 gen/*.ftl 代码生成模板。用于新增或修改标准 CRUD 列表页、树表页、系统管理页、监控页、workflow 页面、demo 页面,补齐与 RuoYi-Vue-Plus boot4 后端接口对应的 src/api、types 和 src/pages 代码,或维护 gen/api.ts.ftl、gen/types.ts.ftl、gen/index.tsx.ftl、gen/index-tree.tsx.ftl;触发后应先读取适用 references,再阅读目标模块真实代码和项目内置 gen 模板。
---
# 前端编码规范
先对齐当前 React 项目里的真实实现,再参考项目内置 `gen/` 代码生成模板。Vue 版本 skill 和关联后端工程的代码生成器模板只用于理解字段、权限、任务分型和迁移意图。不要直接套 Vue 3、Element Plus、AxiosPromise 或 `src/views` 规则;要落成当前仓库的 `src/pages`、`src/api`、ProTable、ModalForm、权限、导出和公共工具方式。
## 执行流程
1. 判断任务类型:新增标准 CRUD、树表、已有页面增强、复杂业务页、只补 API/types。
2. 按“文档读取规则”读取必要 reference,不一次性展开所有资料。
3. 阅读目标目录下最近似的真实代码:
- 标准单表优先看 `src/pages/demo/demo/index.tsx`、`src/api/demo/demo/*`。
- 树表优先看 `src/pages/demo/tree/index.tsx`、`src/pages/workflow/category/index.tsx`。
- 系统复杂页优先看 `src/pages/system/user/index.tsx`、`system/role`、`system/post`、`system/config`。
- workflow 业务页优先看 `src/pages/workflow/*` 与 `src/api/workflow/*` 同类页面。
4. 新增或维护代码生成能力时,优先阅读当前仓库 `gen/api.ts.ftl`、`gen/types.ts.ftl`、`gen/index.tsx.ftl`、`gen/index-tree.tsx.ftl`。这些是 React 版内置 FreeMarker 生成模板,页面模板必须输出当前项目 React/TSX 风格。
5. 需要从 Vue 版本迁移经验时,参考 Gitee 项目 `https://gitee.com/JavaLionLi/plus-ui` 的 `6.X-Vue` 分支,目录为 `.codex/skills/frontend-crud-coding` 和 `.claude/agents`,只吸收任务分型、增量修改和自检原则。
6. 新增标准页面前,可以对照 Gitee 项目 `https://gitee.com/dromara/RuoYi-Vue-Plus` 的 `6.X` 分支,目录为 `ruoyi-modules/ruoyi-gen/src/main/resources/fm`,确认字段、权限和导出能力,但输出和 `gen/` 模板必须保持 React 项目风格。
7. 新增代码时通常同步维护 `src/api/<module>/<business>/index.ts`、`types.ts`、`src/pages/<module>/<business>/index.tsx`;如果是生成模板优化,同步维护 `gen/` 对应 `.ftl`。
8. 增强已有页面时只做增量修改,保留原页面的树筛选、导入导出、列显隐、权限、字典、弹窗、抽屉和路由跳转能力。
9. 修改完成后按影响范围运行验证:优先 `pnpm exec tsc --noEmit` 或 `pnpm lint`;大范围页面、公共组件、构建配置变更再跑 `pnpm build`。
## 文档读取规则
- 前端 API、types、页面、hooks、样式、权限、导出和验证规则,先读 [references/frontend.md](references/frontend.md)。
- 不确定任务边界、需要标准用例或提问方式时,再读 [references/examples.md](references/examples.md)。
- reference 只约束实现方式和自检范围;发生冲突时,以当前模块真实代码和实际调用点为准。
## 优先级规则
发生冲突时按下面顺序决策:
1. 目标目录下最近似页面、API、types 的真实实现。
2. 当前项目公共 hooks、组件、工具、样式和请求封装约定。
3. 当前项目内置 `gen/*.ftl` React 代码生成模板。
4. Gitee 项目 `plus-ui` 的 `6.X-Vue` 分支 `.codex` / `.claude` 中的任务分型和工作流。
5. Gitee 项目 `RuoYi-Vue-Plus` 的 `6.X` 分支 generator 模板。
6. 通用 React / Ant Design ProComponents 习惯。
也就是说:
- 同模块已有页面怎么写,优先怎么写。
- 没有现成页面时,使用 demo 页面作为骨架,再按后端接口字段和权限补齐。
- 复杂模块不能为了“标准 CRUD”退化成裸模板页。
- Vue 版本只作为迁移参考,不复制 Vue 组件、hooks、指令、样式类和类型导入。
## 仓库通用规则
- 遵循 `.editorconfig` 和仓库现状:UTF-8、2 空格缩进、TypeScript、TSX。
- 包管理使用 `pnpm`;格式脚本是 `pnpm run fmt`,lint 脚本是 `pnpm lint`。
- 技术栈是 React 19 + TypeScript + Umi Max + Ant Design 6 + Ant Design ProComponents + ahooks + TanStack Query + Zustand。
- 页面放在 `src/pages`,不是 Vue 项目的 `src/views`。
- 请求统一通过 `src/api/request.ts`,API 返回类型使用 `Promise<R<T>>`,不要从 `axios` 或 Vue 项目引入 `AxiosPromise`。
- 分页结果使用 `PageResult<T>` from `@/api/types`,接口外层使用 `R<T>` from `@/api/types`。
- 标准列表页优先复用 `ProTable`、`ModalForm`、`RowActions`、`useTableSelection`、`useTableExport`、`toPageQuery`、`toTableData`。
- 查询、字典、树表、loading、重置和确认弹窗优先复用 `useDateRangeQuery`、`dictOptions`、`useTreeTableExpand`、`useLoading`、`useSearchReset`、`confirmAction`/`confirmTitleSafe`。
- 权限用 `const userInfo = useUserStore(state => state.userInfo)` 和 `hasPermi(userInfo, ['module:business:action'])` 计算布尔值。
- 新页面不要无故引入另一套状态管理、请求封装、表格封装、样式体系或权限写法。
## 目录映射规则
通常按下面关系组织代码:
- 后端 `/system/user/*` 对应 `src/api/system/user/*` 与 `src/pages/system/user/*`
- 后端 `/monitor/xxx/*` 对应 `src/api/monitor/xxx/*` 与 `src/pages/monitor/xxx/*`
- 后端 `/workflow/xxx/*` 对应 `src/api/workflow/xxx/*` 与 `src/pages/workflow/xxx/*`
- 后端 `/demo/xxx/*` 对应 `src/api/demo/xxx/*` 与 `src/pages/demo/xxx/*`
标准新增通常至少包含:
- `src/api/<module>/<business>/index.ts`
- `src/api/<module>/<business>/types.ts`
- `src/pages/<module>/<business>/index.tsx`
按业务复杂度,可能继续补:
- 导入弹窗
- 详情抽屉或详情页
- 树筛选面板
- 列显隐配置
- 分配/授权子页面
- 自定义 Less 样式
## 任务分型
### 1. 标准单表 CRUD
以 `src/pages/demo/demo/index.tsx` 和 `src/api/demo/demo/*` 为主要起点,补齐列表、搜索、分页、新增、编辑、删除、导出、权限、类型和验证。
### 2. 树表 CRUD
以 `src/pages/demo/tree/index.tsx`、`src/pages/workflow/category/index.tsx` 为主要起点。列表接口通常返回数组,不使用分页 `PageResult`;页面使用 `handleTree`、`useTreeTableExpand`、`ProFormTreeSelect`。
### 3. 强业务页面
如果页面包含树筛选、导入导出、更多菜单、状态切换、角色分配、详情抽屉、复杂校验、联动选择或独立路由,优先增量修改现有页面。不要重写成简单 CRUD。
### 4. 工作流页面
workflow 目录优先参考 `src/pages/workflow/*`。流程定义、流程实例、任务列表、请假申请等页面通常有业务按钮、弹窗和路由跳转,不要硬套 system 模块。
### 5. 只补 API 和 types
只维护 `src/api/<module>/<business>/index.ts` 与 `types.ts`,但仍要与后端路由、返回结构、当前模块导入方式和类型入口一致。
### 6. 维护 React 生成模板
模板只放在当前仓库 `gen/` 下,除非用户明确要求写入 boot4 后端工程。维护时保持 FreeMarker 变量和文件名不变:
- `gen/api.ts.ftl`
- `gen/types.ts.ftl`
- `gen/index.tsx.ftl`
- `gen/index-tree.tsx.ftl`
模板内容必须生成当前 React 项目代码,并优先使用已有公共工具:`useDateRangeQuery`、`dictOptions`、`useTreeTableExpand`、`useTableSelection`、`useTableExport`、`confirmAction`、`toPageQuery`、`toTableData`、`handleTree`、`formatDateTimeFields`、`toDayjsFields`。不要把 Vue 模板、Element Plus 组件或 `src/views` 路径写入这些模板。
## 输出要求
使用本 skill 时,默认期望产出应满足:
- 类型完整,不把页面逻辑大量写成 `any`。
- API 路径、函数名、权限标识与后端接口保持一致。
- 标准页查询、重置、分页、弹窗、提交、删除、导出流程闭环完整。
- 复杂页面保留原有交互能力和业务约束。
- 代码体现当前项目 hooks、页面壳和下载方式,而不是 Vue 版本或 generator 裸输出。
- 生成模板变更要同步反映当前项目公共 hooks/工具,避免生成的新页面重复手写日期范围、字典 options、树展开、loading、搜索重置和确认框逻辑。
- 交付前说明运行过的验证命令;如果无法验证,说明原因。
## 快速检查清单
- API 是否从 `@/api/request` 引入 `request`。
- `R`、`PageResult`、`PageQuery`、`BaseEntity` 是否来自 `@/api/types`。
- API `params` 和 `data` 是否与后端方法一致。
- 分页表格 request 是否通过 `toPageQuery(params)` 和 `toTableData(res)`。
- 导出是否通过 `useTableExport` 和 `exportFile('/module/business/export', () => 'name_timestamp.xlsx')`。
- 多选是否通过 `useTableSelection<T>(row => row.id)`。
- 行操作是否优先使用 `RowActions` 和 Ant Design 图标。
- 权限是否通过 `useUserStore` + `hasPermi` 计算,不要写 Vue 指令。
- 日期范围是否通过 `useDateRangeQuery` 或 `addDateRange` 相关工具处理。
- 字典 options 是否通过 `dictOptions`。
- 树表是否使用 `handleTree`、`pagination={false}`、`useTreeTableExpand`、`ProFormTreeSelect`。
- loading 是否优先使用 `useLoading`,搜索重置是否优先使用 `useSearchReset`。
- 需要 Promise 式确认时是否使用 `confirmAction` 或 `confirmTitleSafe`。
- 代码生成模板是否仍输出 React TSX 项目风格。
## 推荐提问方式
推荐把请求描述到下面粒度:
- 目标模块和业务名
- 后端接口前缀
- 是新增页面、修改页面,还是只补 API/types
- 是否需要导入、导出、树筛选、树表、状态切换、字典、权限按钮
- 希望参考哪个现有页面
例如:
- 使用 `$frontend-crud-coding` 为 `/system/client` 补一套 React 标准 CRUD 页面,参考 `demo/demo`、现有 `system/client` 和 boot4 generator 模板。
- 使用 `$frontend-crud-coding` 修改 `workflow/category` 列表页,增加导出按钮和状态筛选,保持当前 workflow 树表风格。
@@ -1,7 +0,0 @@
interface:
display_name: "前端编码"
short_description: "按 plus-ui-react 真实代码和 gen 模板编写 React CRUD"
default_prompt: "使用 $frontend-crud-coding 先读取适用 reference,再按 plus-ui-react 真实页面、项目内置 gen 模板、API/types、ProTable、ModalForm、权限、导出和公共工具约定实现前端修改。"
policy:
allow_implicit_invocation: true
@@ -1,143 +0,0 @@
# 使用案例
## 案例 1:新增标准 CRUD 页面
### 用户提问示例
```text
使用 $frontend-crud-coding 为 system/client 补一套 React 前端 CRUD 页面。
后端接口已经有 /system/client/list、/system/client/{id}、POST /system/client、PUT /system/client、DELETE /system/client/{ids}。
请参考 src/pages/demo/demo/index.tsx 和现有 system/client 风格实现。
```
### 期望执行方式
- 先看 `src/api/system/client/*` 和 `src/pages/system/client/index.tsx` 是否已存在。
- 再看 `src/pages/demo/demo/index.tsx` 的标准 React CRUD 骨架。
- 新增标准生成能力时优先对照当前仓库 `gen/index.tsx.ftl`、`gen/api.ts.ftl`、`gen/types.ts.ftl`;boot4 generator 只用于核对字段、权限和接口。
- 生成或修改 `api/index.ts`、`types.ts`、`pages/.../index.tsx`。
- 使用 `request<R<PageResult<T>>>`、`ProTable`、`ModalForm`、`RowActions`、`useTableSelection`、`useTableExport`。
- 日期范围、字典 options、确认框、loading 等优先使用 `useDateRangeQuery`、`dictOptions`、`confirmAction`、`useLoading` 等项目工具。
## 案例 2:新增树表页面
### 用户提问示例
```text
使用 $frontend-crud-coding 为 demo/tree2 新增树表 CRUD,接口返回数组,字段包含 id、parentId、name、orderNum。
参考 src/pages/demo/tree/index.tsx 和 workflow/category。
```
### 期望执行方式
- 判断这是树表,不生成分页 `PageResult` 页面。
- API 列表返回 `R<Tree2VO[]>`。
- `Query` 不继承 `PageQuery`。
- 页面使用 `handleTree`、`pagination={false}`、`useTreeTableExpand`、`ProFormTreeSelect`。
- 新增子节点时从当前行带入 `parentId`。
## 案例 2.1:优化 React 代码生成模板
### 用户提问示例
```text
使用 $frontend-crud-coding 优化当前项目 gen 目录下的 React 代码生成模板,让生成页面继续使用新加的工具。
```
### 期望执行方式
- 读取 `gen/api.ts.ftl`、`gen/types.ts.ftl`、`gen/index.tsx.ftl`、`gen/index-tree.tsx.ftl`。
- 保持 FreeMarker 变量、宏和文件名不变。
- 普通表模板继续使用 `useTableSelection`、`useTableExport`、`useDateRangeQuery`、`dictOptions`、`confirmAction`。
- 树表模板继续使用 `handleTree`、`filterTree`、`useTreeTableExpand`、`dictOptions`。
- 输出仍是 React TSX 项目代码,不写 Vue `src/views`、Element Plus 或 `AxiosPromise`。
## 案例 3:修改已有复杂列表页
### 用户提问示例
```text
使用 $frontend-crud-coding 修改 system/user 页面:
1. 新增一个创建时间快捷筛选
2. 导出按钮保留在工具栏中
3. 保持现有树筛选、导入、详情抽屉和角色分配不变
```
### 期望执行方式
- 判断这是“已有复杂页面增强”,不是重新生成 CRUD。
- 优先阅读 `src/pages/system/user/index.tsx` 和相关子组件。
- 保留 `TreePanel`、导入弹窗、`UserDetailDrawer`、角色分配路由、权限控制。
- 只增量修改搜索和查询参数处理。
## 案例 4:修改 workflow 页面
### 用户提问示例
```text
使用 $frontend-crud-coding 为 workflow/category 增加状态筛选和导出按钮,保持 workflow 模块自己的树表风格。
```
### 期望执行方式
- 优先看 `src/pages/workflow/category/index.tsx` 和 `src/api/workflow/category/*`。
- 判断是否需要后端新增导出接口;前端导出路径保持 `/workflow/category/export`。
- 不迁移 system/user 的用户专属逻辑。
- 保留树表、`useTreeTableExpand`、`handleTree` 和分类弹窗逻辑。
## 案例 5:只补 API 和 types
### 用户提问示例
```text
使用 $frontend-crud-coding 为 monitor/cache 补全前端 API 和 types,页面先不改。
```
### 期望执行方式
- 只维护 `src/api/monitor/cache/index.ts` 和 `src/api/monitor/cache/types.ts`。
- 仍然检查同目录 monitor API 的命名、返回结构和导出风格。
- 返回类型使用 `R<T>` 和 `PageResult<T>` from `@/api/types`。
- 不创建页面,不改路由。
## 案例 6:接入后端新增状态切换接口
### 用户提问示例
```text
使用 $frontend-crud-coding 给 system/client 页面接入 PUT /system/client/changeStatus,状态字段 status,参考 system/user。
```
### 期望执行方式
- API 增加 `changeClientStatus(id, status)`。
- types 确认 `status` 类型是 string、number 还是 boolean。
- 表格列用 Ant Design `Switch`,checked 值跟后端字段类型一致。
- 切换失败时回滚原状态或刷新列表。
- 权限使用 `system:client:edit` 或后端实际权限。
## 推荐的高质量任务描述
```text
使用 $frontend-crud-coding 在当前 React 前端项目中增强 `/system/notice` 列表页:
1. 保留现有页面
2. 新增状态筛选和导出
3. API 路径沿用后端接口
4. 参考 system/config 的工具栏与导出交互
5. 参考当前项目 gen 模板和 boot4 generator 字段补齐缺失 types
```
## 不推荐的任务描述
```text
帮我写个后台页面
```
更好的写法至少补充:
- 模块名
- 业务名
- 后端接口前缀
- 是新增还是修改
- 是否需要分页、导出、树表、字典、权限
- 想参考哪个现有页面
@@ -1,154 +0,0 @@
# 前端约定
## 优先参考的代码来源
- 当前目标目录下最近似页面、API、types。
- 当前仓库内置 React 生成模板:`gen/api.ts.ftl`、`gen/types.ts.ftl`、`gen/index.tsx.ftl`、`gen/index-tree.tsx.ftl`。
- 标准单表:`src/pages/demo/demo/index.tsx`、`src/api/demo/demo/index.ts`、`src/api/demo/demo/types.ts`。
- 树表:`src/pages/demo/tree/index.tsx`、`src/pages/workflow/category/index.tsx`。
- 复杂系统页:`src/pages/system/user/index.tsx`、`src/pages/system/role/index.tsx`、`src/pages/system/post/index.tsx`、`src/pages/system/config/index.tsx`。
- workflow 页:`src/pages/workflow/*`、`src/api/workflow/*`。
- 监控页:`src/pages/monitor/*`、`src/api/monitor/*`。
- 公共 hooks:`src/hooks/useTableSelection.ts`、`src/hooks/useTableExport.ts`、`src/hooks/useDict.ts`、`src/hooks/useDateRangeQuery.ts`、`src/hooks/useTreeTableExpand.ts`、`src/hooks/useLoading.ts`、`src/hooks/useSearchReset.ts`。
- 公共组件:`src/components/common/RowActions.tsx`、`TreePanel.tsx`、`RightToolbar.tsx`、`DictTag.tsx`、上传/预览组件。
- 工具函数:`src/utils/ruoyi.ts`、`src/utils/permission.ts`、`src/utils/download.ts`、`src/utils/dict.ts`、`src/utils/modal.ts`。
## 基础栈与格式
- 技术栈是 React + TypeScript + Umi Max + Ant Design + ProComponents + ahooks + Zustand + TanStack Query。
- 包管理按仓库现状使用 pnpm。
- `.editorconfig` 要求 UTF-8、2 空格缩进。
- 当前仓库没有 Prettier;格式化使用 `pnpm run fmt`,lint 使用 `pnpm lint`。
- 不要在一个页面里混入与仓库不一致的格式和写法。
## API 文件规则
- 标准 API 文件放在 `src/api/<module>/<business>/index.ts`,同目录维护 `types.ts`。
- import 顺序优先跟随附近文件,标准形式:
`import type { PageResult, R } from '@/api/types';`
`import request from '@/api/request';`
`import type { XxxForm, XxxQuery, XxxVO } from './types';`
- 不要从 `axios` 引入 `AxiosPromise`;当前 `request<T>()` 返回 `Promise<T>`,接口函数通常返回 `Promise<R<T>>`。
- 列表分页接口通常返回 `request<R<PageResult<XxxVO>>>({ url, method: 'get', params: query })`。
- 树表列表接口通常返回 `request<R<XxxVO[]>>({ url, method: 'get', params: query })`。
- 详情接口返回 `R<XxxVO>`;复杂详情返回单独的 `InfoVO`。
- 标准函数命名:
`listXxx` -> `GET /<module>/<business>/list`
`getXxx` -> `GET /<module>/<business>/{id}`
`addXxx` -> `POST /<module>/<business>`
`updateXxx` -> `PUT /<module>/<business>`
`delXxx` -> `DELETE /<module>/<business>/{id or ids}`
`changeXxxStatus` -> `PUT /<module>/<business>/changeStatus`
- query string 用 `params`,请求体用 `data`。
- 加密、防重复提交等 headers 直接写在请求配置里,例如用户重置密码中的 `isEncrypt`、`repeatSubmit`。
- 当前仓库多数 API 使用 `export function`;新增标准 CRUD 优先跟随相邻模块。
- 只有相邻模块已有聚合对象时才新增默认导出。
## 类型文件规则
- 标准类型定义 `VO`、`Form`、`Query`,必要时补 `InfoVO`、`TreeVO`、`ResetPwdForm` 等扩展类型。
- `Form` 通常继承 `BaseEntity`。
- 非树表 `Query` 通常继承 `PageQuery`。
- 树表 `Query` 通常不继承 `PageQuery`。
- ID 字段通常使用 `string | number`,批量删除参数使用 `string | number | Array<string | number>`。
- Java 数值类型映射为 `number`,Boolean 映射为 `boolean`,日期/文本默认 `string`。
- 日期范围查询保留 `params?: Record<string, unknown>` 或跟随相邻页面现有类型,不要因为它看起来宽松就删掉。
- 列表对象、表单对象、查询对象职责分开;字段不一致时不要强行复用一个接口。
- 能明确写出类型时不要用 `any`;组件库、字典或历史接口确实无法收窄时再保留。
## React 页面结构规则
- 页面默认导出函数组件,命名如 `SystemUserPage`、`DemoDemoPage`、`WorkflowCategoryPage`。
- 标准页使用 `PageContainer` 包裹 `ProTable` 和 `ModalForm`。
- 标准列表页常见状态:
`actionRef`、`form`、`modalOpen`、`modalTitle`、`ids`、`selectedOne`、权限布尔值。
- 弹窗状态优先使用 `useBoolean(false)`,表单用 `Form.useForm<XxxForm>()`。
- ProTable 使用:
`rowKey`
`columns`
`search={{ labelWidth: 90 }}`
`pagination={{ defaultPageSize: 10, showSizeChanger: true }}`
`request={async params => { ... }}`
`toolBarRender={() => [...]}`
- 分页查询使用 `toPageQuery(params)`,然后 `updateExportParams(query)`,最后 `return toTableData(res)`。
- 表格列类型使用 `ProColumns<XxxVO>[]`。
- 新增/编辑弹窗使用 `ModalForm<XxxForm>`,字段优先使用 `ProFormText`、`ProFormDigit`、`ProFormSelect`、`ProFormTreeSelect`、`ProFormDateTimeRangePicker` 等 ProForm 组件。
- ModalForm 成功提交后返回 `true`,并刷新 `actionRef.current?.reload()`。
## 页面行为规则
- `openAdd` 负责 `form.resetFields()`、设置默认值、设置标题、打开弹窗。
- `openEdit` 先按行或 `selectedOne` 找目标,再查详情,`form.resetFields()`,`form.setFieldsValue(res.data)`,最后打开弹窗。
- `submitForm` 根据主键判断新增或修改,成功后 `message.success('操作成功')`、重置表单、刷新列表。
- `remove` 或 `handleDelete` 支持行删除和批量删除,成功后 `message.success('删除成功')`、`clearSelection()`、`reloadAndRest` 或 `reload`。
- 批量按钮通常用 `Popconfirm`,行操作确认优先放在 `RowActions` 的 `confirm`。
- 状态切换失败时要回滚或刷新,参考 `src/pages/system/user/index.tsx`。
- 日期范围查询优先使用 `useDateRangeQuery`,底层通过 `addDateRange` 写入 `params.beginXxx/endXxx`。
- 字典 options 优先使用 `dictOptions(dicts.xxx)`。
- 导入上传参考 `system/user/components/UserImportModal.tsx` 或流程定义导入弹窗,保留 `globalHeaders()` 和 `appEnv.baseApi` 相关方式。
## 字典、权限与公共工具
- 字典使用 `const dicts = useDict('sys_normal_disable', 'sys_user_gender')`。
- 字典 options 使用 `dictOptions` from `@/utils/dict` 映射为 `{ label, value }`。
- 权限使用:
`const userInfo = useUserStore(state => state.userInfo);`
`const canAdd = hasPermi(userInfo, ['system:user:add']);`
- 不要使用 Vue 权限指令 `v-hasPermi`。
- 常用工具:
`hasPermi` from `@/utils/permission`
`handleTree`、`parseStrEmpty`、`toPageQuery`、`toTableData`、`addDateRange`、`formatDateTimeRange` from `@/utils/ruoyi`
`dictOptions` from `@/utils/dict`
`confirmAction`、`confirmTitleSafe` from `@/utils/modal`
`download` via `useTableExport`
## 组件与样式规则
- 行操作优先复用 `RowActions`,并使用 `@ant-design/icons` 图标。
- 树筛选优先复用 `TreePanel`,参考 `system/user`。
- 导出优先复用 `useTableExport`。
- 多选优先复用 `useTableSelection`。
- 异步 loading 优先复用 `useLoading`,不要重复手写 `setLoading(true)` + `finally setLoading(false)`。
- ProTable 重置后还要清空额外筛选状态时,优先复用 `useSearchReset`。
- Promise 式确认框优先复用 `confirmAction` 或 `confirmTitleSafe`。
- 标准页面尽量使用 `PageContainer`、`ProTable`、ProComponents 页面壳,不堆大量内联样式。
- 需要自定义布局时先查 `src/assets/styles` 是否已有 `.tree-table-page`、`.table-panel`、`.page-surface` 等类。
- 不要为了单页需求修改全局组件样式。
## 树表规则
- 树表列表接口通常返回数组,页面通过 `handleTree<T>(res.data || [], 'id', 'parentId')` 组树。
- `ProTable` 使用 `pagination={false}`。
- 使用 `useTreeTableExpand` 控制 `expandedRowKeys`、`onExpandedRowsChange`、`syncExpandedRows`、`toggleExpandAll`。
- 展开/折叠按钮参考 `demo/tree` 和 `workflow/category`,用 `SortAscendingOutlined`。
- 表单中上级节点使用 `ProFormTreeSelect`。
- 新增子节点时从当前行回填 `parentId`。
- 删除确认文案优先使用业务名称,而不是批量 ID 文案。
## 与 gen 模板、Vue 参考项目和后端生成器的关系
- 当前仓库 `gen/*.ftl` 是 React 版内置代码生成模板,是维护生成能力时的第一参考。
- `gen/index.tsx.ftl`、`gen/index-tree.tsx.ftl` 内容必须生成 React TSX 页面。
- 修改公共 hooks/工具后,如果它们能简化标准生成页,要同步评估 `gen/*.ftl` 是否需要更新。
- Vue skill 和 `.claude/agents` 提供的是任务分型、优先级、增量修改、自检方式,不是 React 实现模板。
- boot4 后端 generator 模板可用于确认字段、权限、导出、状态切换、排序、日期范围等,但不是最终答案。
- 当前 React 项目的核心骨架是 `ProTable`、`ModalForm`、`RowActions`、`useTableSelection`、`useTableExport`。
- 修改已有页面时,不要把现有强业务逻辑替换回 generator 的简化逻辑。
## 验证规则
- 只改文档、skill 或 `gen/*.ftl` 模板:至少运行 skill 基础校验或 `git diff --check`;如果模板改动依赖项目工具,优先再跑 `pnpm lint`。
- 改前端 TS/TSX/API/types:优先运行 `pnpm exec tsc --noEmit` 或 `pnpm lint`。
- 改页面、import、权限或较多文件:运行 `pnpm lint`。
- 改公共 hooks、组件、构建相关或大范围页面:再运行 `pnpm build`。
- 如果验证因为环境、依赖或权限失败,交付时说明失败命令和原因。
## 避免事项
- 不要从 `axios` 引入 `AxiosPromise`。
- 不要绕开 `@/api/request` 或 `useTableExport` 自造请求/下载封装。
- 不要跳过 `types.ts`,把类型全写在页面里。
- 不要把 `src/pages` 写成 Vue 项目的 `src/views`。
- 不要使用 Vue 的 `ref`、`reactive`、`toRefs`、`v-hasPermi`、Element Plus 组件或 SCSS 页面壳。
- 不要删除日期范围 `params`、权限判断、导出、导入、树筛选、列显隐等现有能力。
- 不要为了“更整洁”重写复杂页面的大块业务逻辑。
+15 -3
View File
@@ -1,9 +1,21 @@
# 告诉EditorConfig插件,这是根文件,不用继续往上查找
root = true
# 匹配全部文件
[*]
charset = utf-8
end_of_line = lf
insert_final_newline = true
# 缩进风格,可选space、tab
indent_style = space
# 缩进的空格数
indent_size = 2
# 设置字符集
charset = utf-8
# 结尾换行符,可选lf、cr、crlf
end_of_line = lf
# 在文件结尾插入新行
trim_trailing_whitespace = true
# 删除一行中的前后空格
insert_final_newline = true
[*.md]
insert_final_newline = false
trim_trailing_whitespace = false
+32 -15
View File
@@ -1,15 +1,32 @@
VITE_APP_TITLE=RuoYi-React-Plus后台管理系统
VITE_APP_LOGO_TITLE=RuoYi-React-Plus
VITE_APP_ENV=development
VITE_APP_BASE_API=/dev-api
VITE_APP_CONTEXT_PATH=/
VITE_APP_PORT=8000
VITE_APP_CLIENT_ID=e5cd7e4891bf95d1d19206ce24a7b32e
VITE_APP_MESSAGE_ENABLED=true
VITE_APP_MESSAGE_TRANSPORT=sse
VITE_APP_MESSAGE_PATH=/resource/message
VITE_APP_ENCRYPT=true
VITE_APP_RSA_PUBLIC_KEY=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDvEDuRIOM3oZPWj9Ukoc5pQklR4PFH6/clnjeFqjDLIgDyQvjxhgqAZQA+E9eD6qu6FsXPmK8djcL+nh3cFHz4pX473jDvO3Sve+8yL3VRQ0n2pRgQ2a01MJsy+WwTZCBYWf0VnLRIvANUoWQgy9vz94q7Va44dg7A1/3ICf+xAwIDAQAB
VITE_APP_RSA_PRIVATE_KEY=MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAObq7yrxfvyieZtTjAYyrdvi59tYTXxjO5ajmPCRSXBY9M9wQ1tli297JN6mnY53UJMNyOFNSZVi8WSFoIXjpR87FmvChJlzeN/dZdd3SEs48Ee66XKeSePYqxa8oO5GKDsnajgpsOHKXSeeVSIysiIPS2/WsEqk0In9P4w3RsRFAgMBAAECgYBiMEWwce24SPICnRzuScBpvmsudrbEDIH7BOd0a6LZlcnLJwZNJ7mJlshPsHNQb+WgEf135+BBGEhioPtn0yuTdEuKP4kB9UdYUKiayWCoWhJpesv7sAD4RDClV7dhuV+gcd1AXD+YzyRIPbGm0VC2U+4q8/+UPRpVjqskbLVTgQJBAPRpou7g3S8n4XB527kq0D8I3+ZYwMxZhszwhrCDpJU319+ucmpLVwYIzDmZVeID2QQdUaDfIEViFHu95xDrGiUCQQDx3YOKn3yaEctk/ERVn7hDAyAXUbd8/pv2b24/M/l1ZevlsFem8U4Jk5Mu64t3z3YGJoymEjQmbucwT01iKhehAkEAxlnccsRmfFh/KkqauKE4M4++NTAd9zlInpUsmZ+cN8UEGnF2RTEzRKBrLOt1uWCqBB7PGiE6DVTVjr7FAQPrSQJAT5yeY87DcONSk9cFlzmPqV8p/QME5rvYEnHzVBKDlkUKNPyqnWToTvaoh9U4fyNmsfeWbEOprszqhFhWHG3GgQJAK8+ynmyFhaw63+Hx2KU5zR4hVuQso2IzrEurGxCxybV6mR7VBerb4502+EPx3PmOgxQL+niUFhcMWxcvBFP9+A==
VITE_APP_MONITOR_ADMIN=http://localhost:9090/admin/applications
VITE_APP_SNAILJOB_ADMIN=http://localhost:8800/snail-job
# 页面标题
VITE_APP_TITLE = RuoYi-Vue-Plus多租户管理系统
# 开发环境配置
VITE_APP_ENV = 'development'
# 开发环境
VITE_APP_BASE_API = '/dev-api'
# 应用访问路径 例如使用前缀 /admin/
VITE_APP_CONTEXT_PATH = '/'
# 监控地址
VITE_APP_MONITOR_ADMIN = 'http://localhost:9090/admin/applications'
# SnailJob 控制台地址
VITE_APP_SNAILJOB_ADMIN = 'http://localhost:8800/snail-job'
VITE_APP_PORT = 80
# 接口加密功能开关(如需关闭 后端也必须对应关闭)
VITE_APP_ENCRYPT = true
# 接口加密传输 RSA 公钥与后端解密私钥对应 如更换需前后端一同更换
VITE_APP_RSA_PUBLIC_KEY = 'MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAKoR8mX0rGKLqzcWmOzbfj64K8ZIgOdHnzkXSOVOZbFu/TJhZ7rFAN+eaGkl3C4buccQd/EjEsj9ir7ijT7h96MCAwEAAQ=='
# 接口响应解密 RSA 私钥与后端加密公钥对应 如更换需前后端一同更换
VITE_APP_RSA_PRIVATE_KEY = 'MIIBVAIBADANBgkqhkiG9w0BAQEFAASCAT4wggE6AgEAAkEAmc3CuPiGL/LcIIm7zryCEIbl1SPzBkr75E2VMtxegyZ1lYRD+7TZGAPkvIsBcaMs6Nsy0L78n2qh+lIZMpLH8wIDAQABAkEAk82Mhz0tlv6IVCyIcw/s3f0E+WLmtPFyR9/WtV3Y5aaejUkU60JpX4m5xNR2VaqOLTZAYjW8Wy0aXr3zYIhhQQIhAMfqR9oFdYw1J9SsNc+CrhugAvKTi0+BF6VoL6psWhvbAiEAxPPNTmrkmrXwdm/pQQu3UOQmc2vCZ5tiKpW10CgJi8kCIFGkL6utxw93Ncj4exE/gPLvKcT+1Emnoox+O9kRXss5AiAMtYLJDaLEzPrAWcZeeSgSIzbL+ecokmFKSDDcRske6QIgSMkHedwND1olF8vlKsJUGK3BcdtM8w4Xq7BpSBwsloE='
# 客户端id
VITE_APP_CLIENT_ID = 'e5cd7e4891bf95d1d19206ce24a7b32e'
# websocket 开关
VITE_APP_WEBSOCKET = true
+35 -15
View File
@@ -1,15 +1,35 @@
VITE_APP_TITLE=RuoYi-React-Plus后台管理系统
VITE_APP_LOGO_TITLE=RuoYi-React-Plus
VITE_APP_ENV=production
VITE_APP_BASE_API=/prod-api
VITE_APP_CONTEXT_PATH=/
VITE_APP_PORT=8000
VITE_APP_CLIENT_ID=e5cd7e4891bf95d1d19206ce24a7b32e
VITE_APP_MESSAGE_ENABLED=true
VITE_APP_MESSAGE_TRANSPORT=sse
VITE_APP_MESSAGE_PATH=/resource/message
VITE_APP_ENCRYPT=true
VITE_APP_RSA_PUBLIC_KEY=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDvEDuRIOM3oZPWj9Ukoc5pQklR4PFH6/clnjeFqjDLIgDyQvjxhgqAZQA+E9eD6qu6FsXPmK8djcL+nh3cFHz4pX473jDvO3Sve+8yL3VRQ0n2pRgQ2a01MJsy+WwTZCBYWf0VnLRIvANUoWQgy9vz94q7Va44dg7A1/3ICf+xAwIDAQAB
VITE_APP_RSA_PRIVATE_KEY=MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAObq7yrxfvyieZtTjAYyrdvi59tYTXxjO5ajmPCRSXBY9M9wQ1tli297JN6mnY53UJMNyOFNSZVi8WSFoIXjpR87FmvChJlzeN/dZdd3SEs48Ee66XKeSePYqxa8oO5GKDsnajgpsOHKXSeeVSIysiIPS2/WsEqk0In9P4w3RsRFAgMBAAECgYBiMEWwce24SPICnRzuScBpvmsudrbEDIH7BOd0a6LZlcnLJwZNJ7mJlshPsHNQb+WgEf135+BBGEhioPtn0yuTdEuKP4kB9UdYUKiayWCoWhJpesv7sAD4RDClV7dhuV+gcd1AXD+YzyRIPbGm0VC2U+4q8/+UPRpVjqskbLVTgQJBAPRpou7g3S8n4XB527kq0D8I3+ZYwMxZhszwhrCDpJU319+ucmpLVwYIzDmZVeID2QQdUaDfIEViFHu95xDrGiUCQQDx3YOKn3yaEctk/ERVn7hDAyAXUbd8/pv2b24/M/l1ZevlsFem8U4Jk5Mu64t3z3YGJoymEjQmbucwT01iKhehAkEAxlnccsRmfFh/KkqauKE4M4++NTAd9zlInpUsmZ+cN8UEGnF2RTEzRKBrLOt1uWCqBB7PGiE6DVTVjr7FAQPrSQJAT5yeY87DcONSk9cFlzmPqV8p/QME5rvYEnHzVBKDlkUKNPyqnWToTvaoh9U4fyNmsfeWbEOprszqhFhWHG3GgQJAK8+ynmyFhaw63+Hx2KU5zR4hVuQso2IzrEurGxCxybV6mR7VBerb4502+EPx3PmOgxQL+niUFhcMWxcvBFP9+A==
VITE_APP_MONITOR_ADMIN=/admin/applications
VITE_APP_SNAILJOB_ADMIN=/snail-job
# 页面标题
VITE_APP_TITLE = RuoYi-Vue-Plus多租户管理系统
# 生产环境配置
VITE_APP_ENV = 'production'
# 应用访问路径 例如使用前缀 /admin/
VITE_APP_CONTEXT_PATH = '/'
# 监控地址
VITE_APP_MONITOR_ADMIN = '/admin/applications'
# SnailJob 控制台地址
VITE_APP_SNAILJOB_ADMIN = '/snail-job'
# 生产环境
VITE_APP_BASE_API = '/prod-api'
# 是否在打包时开启压缩,支持 gzip 和 brotli
VITE_BUILD_COMPRESS = gzip
VITE_APP_PORT = 80
# 接口加密功能开关(如需关闭 后端也必须对应关闭)
VITE_APP_ENCRYPT = true
# 接口加密传输 RSA 公钥与后端解密私钥对应 如更换需前后端一同更换
VITE_APP_RSA_PUBLIC_KEY = 'MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAKoR8mX0rGKLqzcWmOzbfj64K8ZIgOdHnzkXSOVOZbFu/TJhZ7rFAN+eaGkl3C4buccQd/EjEsj9ir7ijT7h96MCAwEAAQ=='
# 接口响应解密 RSA 私钥与后端加密公钥对应 如更换需前后端一同更换
VITE_APP_RSA_PRIVATE_KEY = 'MIIBVAIBADANBgkqhkiG9w0BAQEFAASCAT4wggE6AgEAAkEAmc3CuPiGL/LcIIm7zryCEIbl1SPzBkr75E2VMtxegyZ1lYRD+7TZGAPkvIsBcaMs6Nsy0L78n2qh+lIZMpLH8wIDAQABAkEAk82Mhz0tlv6IVCyIcw/s3f0E+WLmtPFyR9/WtV3Y5aaejUkU60JpX4m5xNR2VaqOLTZAYjW8Wy0aXr3zYIhhQQIhAMfqR9oFdYw1J9SsNc+CrhugAvKTi0+BF6VoL6psWhvbAiEAxPPNTmrkmrXwdm/pQQu3UOQmc2vCZ5tiKpW10CgJi8kCIFGkL6utxw93Ncj4exE/gPLvKcT+1Emnoox+O9kRXss5AiAMtYLJDaLEzPrAWcZeeSgSIzbL+ecokmFKSDDcRske6QIgSMkHedwND1olF8vlKsJUGK3BcdtM8w4Xq7BpSBwsloE='
# 客户端id
VITE_APP_CLIENT_ID = 'e5cd7e4891bf95d1d19206ce24a7b32e'
# websocket 开关
VITE_APP_WEBSOCKET = true
+17
View File
@@ -0,0 +1,17 @@
*.sh
node_modules
*.md
*.woff
*.ttf
.vscode
.idea
dist
/public
/docs
.husky
.local
/bin
.eslintrc.cjs
prettier.config.js
src/assets
tailwind.config.js
+312
View File
@@ -0,0 +1,312 @@
{
"globals": {
"ComponentInternalInstance": true,
"TransferKey": true,
"ElFormRules": true,
"CheckboxValueType": true,
"PropType": true,
"DateModelType": true,
"UploadFile": true,
"ElFormInstance": true,
"ElTableInstance": true,
"ElTreeInstance": true,
"ElTreeSelectInstance": true,
"ElSelectInstance": true,
"ElUploadInstance": true,
"ElCardInstance": true,
"ElDialogInstance": true,
"ElInputInstance": true,
"ElInputNumberInstance": true,
"ElRadioInstance": true,
"ElRadioGroupInstance": true,
"ElRadioButtonInstance": true,
"ElCheckboxInstance": true,
"ElCheckboxGroupInstance": true,
"ElSwitchInstance": true,
"ElDatePickerInstance": true,
"ElTimePickerInstance": true,
"ElTimeSelectInstance": true,
"ElScrollbarInstance": true,
"ElCascaderInstance": true,
"ElColorPickerInstance": true,
"ElRateInstance": true,
"ElSliderInstance": true,
"useRouter": true,
"useRoute": true,
"EffectScope": true,
"ElTable": true,
"ElSelect": true,
"ElUpload": true,
"ElForm": true,
"ElTree": true,
"ElMessage": true,
"ElMessageBox": true,
"asyncComputed": true,
"autoResetRef": true,
"computed": true,
"computedAsync": true,
"computedEager": true,
"computedInject": true,
"computedWithControl": true,
"controlledComputed": true,
"controlledRef": true,
"createApp": true,
"createEventHook": true,
"createGlobalState": true,
"createInjectionState": true,
"createReactiveFn": true,
"createSharedComposable": true,
"createUnrefFn": true,
"customRef": true,
"debouncedRef": true,
"debouncedWatch": true,
"defineAsyncComponent": true,
"defineComponent": true,
"eagerComputed": true,
"effectScope": true,
"extendRef": true,
"getCurrentInstance": true,
"getCurrentScope": true,
"h": true,
"ignorableWatch": true,
"inject": true,
"isDefined": true,
"isProxy": true,
"isReactive": true,
"isReadonly": true,
"isRef": true,
"makeDestructurable": true,
"markRaw": true,
"nextTick": true,
"onActivated": true,
"onBeforeMount": true,
"onBeforeUnmount": true,
"onBeforeUpdate": true,
"onClickOutside": true,
"onDeactivated": true,
"onErrorCaptured": true,
"onKeyStroke": true,
"onLongPress": true,
"onMounted": true,
"onRenderTracked": true,
"onRenderTriggered": true,
"onScopeDispose": true,
"onServerPrefetch": true,
"onStartTyping": true,
"onUnmounted": true,
"onUpdated": true,
"pausableWatch": true,
"provide": true,
"reactify": true,
"reactifyObject": true,
"reactive": true,
"reactiveComputed": true,
"reactiveOmit": true,
"reactivePick": true,
"readonly": true,
"ref": true,
"refAutoReset": true,
"refDebounced": true,
"refDefault": true,
"refThrottled": true,
"refWithControl": true,
"resolveComponent": true,
"resolveDirective": true,
"resolveRef": true,
"resolveUnref": true,
"shallowReactive": true,
"shallowReadonly": true,
"shallowRef": true,
"syncRef": true,
"syncRefs": true,
"templateRef": true,
"throttledRef": true,
"throttledWatch": true,
"toRaw": true,
"toReactive": true,
"toRef": true,
"toRefs": true,
"triggerRef": true,
"tryOnBeforeMount": true,
"tryOnBeforeUnmount": true,
"tryOnMounted": true,
"tryOnScopeDispose": true,
"tryOnUnmounted": true,
"unref": true,
"unrefElement": true,
"until": true,
"useActiveElement": true,
"useArrayEvery": true,
"useArrayFilter": true,
"useArrayFind": true,
"useArrayFindIndex": true,
"useArrayFindLast": true,
"useArrayJoin": true,
"useArrayMap": true,
"useArrayReduce": true,
"useArraySome": true,
"useArrayUnique": true,
"useAsyncQueue": true,
"useAsyncState": true,
"useAttrs": true,
"useBase64": true,
"useBattery": true,
"useBluetooth": true,
"useBreakpoints": true,
"useBroadcastChannel": true,
"useBrowserLocation": true,
"useCached": true,
"useClipboard": true,
"useCloned": true,
"useColorMode": true,
"useConfirmDialog": true,
"useCounter": true,
"useCssModule": true,
"useCssVar": true,
"useCssVars": true,
"useCurrentElement": true,
"useCycleList": true,
"useDark": true,
"useDateFormat": true,
"useDebounce": true,
"useDebounceFn": true,
"useDebouncedRefHistory": true,
"useDeviceMotion": true,
"useDeviceOrientation": true,
"useDevicePixelRatio": true,
"useDevicesList": true,
"useDisplayMedia": true,
"useDocumentVisibility": true,
"useDraggable": true,
"useDropZone": true,
"useElementBounding": true,
"useElementByPoint": true,
"useElementHover": true,
"useElementSize": true,
"useElementVisibility": true,
"useEventBus": true,
"useEventListener": true,
"useEventSource": true,
"useEyeDropper": true,
"useFavicon": true,
"useFetch": true,
"useFileDialog": true,
"useFileSystemAccess": true,
"useFocus": true,
"useFocusWithin": true,
"useFps": true,
"useFullscreen": true,
"useGamepad": true,
"useGeolocation": true,
"useIdle": true,
"useImage": true,
"useInfiniteScroll": true,
"useIntersectionObserver": true,
"useInterval": true,
"useIntervalFn": true,
"useKeyModifier": true,
"useLastChanged": true,
"useLocalStorage": true,
"useMagicKeys": true,
"useManualRefHistory": true,
"useMediaControls": true,
"useMediaQuery": true,
"useMemoize": true,
"useMemory": true,
"useMounted": true,
"useMouse": true,
"useMouseInElement": true,
"useMousePressed": true,
"useMutationObserver": true,
"useNavigatorLanguage": true,
"useNetwork": true,
"useNow": true,
"useObjectUrl": true,
"useOffsetPagination": true,
"useOnline": true,
"usePageLeave": true,
"useParallax": true,
"usePermission": true,
"usePointer": true,
"usePointerLock": true,
"usePointerSwipe": true,
"usePreferredColorScheme": true,
"usePreferredContrast": true,
"usePreferredDark": true,
"usePreferredLanguages": true,
"usePreferredReducedMotion": true,
"usePrevious": true,
"useRafFn": true,
"useRefHistory": true,
"useResizeObserver": true,
"useScreenOrientation": true,
"useScreenSafeArea": true,
"useScriptTag": true,
"useScroll": true,
"useScrollLock": true,
"useSessionStorage": true,
"useShare": true,
"useSlots": true,
"useSorted": true,
"useSpeechRecognition": true,
"useSpeechSynthesis": true,
"useStepper": true,
"useStorage": true,
"useStorageAsync": true,
"useStyleTag": true,
"useSupported": true,
"useSwipe": true,
"useTemplateRefsList": true,
"useTextDirection": true,
"useTextSelection": true,
"useTextareaAutosize": true,
"useThrottle": true,
"useThrottleFn": true,
"useThrottledRefHistory": true,
"useTimeAgo": true,
"useTimeout": true,
"useTimeoutFn": true,
"useTimeoutPoll": true,
"useTimestamp": true,
"useTitle": true,
"useToNumber": true,
"useToString": true,
"useToggle": true,
"useTransition": true,
"useUrlSearchParams": true,
"useUserMedia": true,
"useVModel": true,
"useVModels": true,
"useVibrate": true,
"useVirtualList": true,
"useWakeLock": true,
"useWebNotification": true,
"useWebSocket": true,
"useWebWorker": true,
"useWebWorkerFn": true,
"useWindowFocus": true,
"useWindowScroll": true,
"useWindowSize": true,
"watch": true,
"watchArray": true,
"watchAtMost": true,
"watchDebounced": true,
"watchEffect": true,
"watchIgnorable": true,
"watchOnce": true,
"watchPausable": true,
"watchPostEffect": true,
"watchSyncEffect": true,
"watchThrottled": true,
"watchTriggerable": true,
"watchWithFilter": true,
"whenever": true,
"ImportOption": true,
"TreeType": true,
"FieldOption": true,
"PageData": true,
"storeToRefs": true,
"DictDataOption": true,
"UploadOption": true
}
}
+51
View File
@@ -0,0 +1,51 @@
module.exports = {
env: {
browser: true,
node: true,
es6: true
},
parser: 'vue-eslint-parser',
extends: [
'plugin:vue/vue3-recommended',
'./.eslintrc-auto-import.json',
'plugin:@typescript-eslint/recommended',
'prettier',
'plugin:prettier/recommended'
],
parserOptions: {
ecmaVersion: '2020',
sourceType: 'module',
project: './tsconfig.*?.json',
parser: '@typescript-eslint/parser'
},
plugins: ['vue', '@typescript-eslint', 'import', 'promise', 'node', 'prettier'],
rules: {
'@typescript-eslint/no-empty-function': 'off',
'@typescript-eslint/no-explicit-any': 'off',
'@typescript-eslint/no-unused-vars': 'off',
'@typescript-eslint/no-this-alias': 'off',
// vue
'vue/multi-word-component-names': 'off',
'vue/valid-define-props': 'off',
'vue/no-v-model-argument': 'off',
'prefer-rest-params': 'off',
// prettier
'prettier/prettier': 'error',
'@typescript-eslint/ban-types': [
'error',
{
// 关闭空类型检查 {}
extendDefaults: true,
types: {
'{}': false,
Function: false
}
}
]
},
globals: {
DialogOption: 'readonly',
OptionType: 'readonly'
}
};
+29 -10
View File
@@ -1,10 +1,29 @@
node_modules
dist
.umi
.umi-production
src/.umi
src/.umi-production
.env.local
*.log
.idea/
*.iml
.DS_Store
.history
node_modules/
dist/
npm-debug.log*
yarn-debug.log*
yarn-error.log*
**/*.log
tests/**/coverage/
tests/e2e/reports
selenium-debug.log
# Editor directories and files
.idea
.vscode
*.suo
*.ntvs*
*.njsproj
*.sln
*.local
package-lock.json
yarn.lock
pnpm-lock.yaml
# 编译生成的文件
auto-imports.d.ts
components.d.ts
-10
View File
@@ -1,10 +0,0 @@
# Default ignored files
/shelf/
/workspace.xml
# Ignored default folder with query files
/queries/
# Datasource local storage ignored files
/dataSources/
/dataSources.local.xml
# Editor-based HTTP Client requests
/httpRequests/
-6
View File
@@ -1,6 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="CompilerConfiguration">
<option name="BUILD_PROCESS_HEAP_SIZE" value="2048" />
</component>
</project>
-3
View File
@@ -1,3 +0,0 @@
<component name="ProjectDictionaryState">
<dictionary name="LionLi" />
</component>
-6
View File
@@ -1,6 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Encoding" defaultCharsetForPropertiesFiles="UTF-8">
<file url="PROJECT" charset="UTF-8" />
</component>
</project>
-17
View File
@@ -1,17 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectInspectionProfilesVisibleTreeState">
<entry key="Project Default">
<profile-state>
<selected-state>
<State>
<id>User defined</id>
</State>
</selected-state>
</profile-state>
</entry>
</component>
<component name="ProjectRootManager" version="2" languageLevel="JDK_25" default="true" project-jdk-name="liberica-25" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/out" />
</component>
</project>
-8
View File
@@ -1,8 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/plus-ui-react.iml" filepath="$PROJECT_DIR$/.idea/plus-ui-react.iml" />
</modules>
</component>
</project>
Generated
-6
View File
@@ -1,6 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$" vcs="Git" />
</component>
</project>
-24
View File
@@ -1,24 +0,0 @@
{
"$schema": "./node_modules/oxfmt/configuration_schema.json",
"ignorePatterns": ["src/.umi", "src/.umi-production", ".ai_state", ".claude", ".codex", "dist", "node_modules"],
"printWidth": 120,
"singleQuote": true,
"trailingComma": "none",
"arrowParens": "avoid",
"htmlWhitespaceSensitivity": "ignore",
"experimentalSortPackageJson": {
"sortScripts": true
},
"sortImports": {
"newlinesBetween": false,
"groups": [
"type-import",
["value-builtin", "value-external"],
"type-internal",
"value-internal",
["type-parent", "type-sibling", "type-index"],
["value-parent", "value-sibling", "value-index"],
"unknown"
]
}
}
-40
View File
@@ -1,40 +0,0 @@
{
"$schema": "https://raw.githubusercontent.com/oxc-project/oxc/main/npm/oxlint/configuration_schema.json",
"plugins": ["eslint", "typescript", "unicorn", "oxc", "import", "react"],
"rules": {
"typescript/no-empty-function": "off",
"typescript/no-explicit-any": "off",
"typescript/no-unused-vars": "off",
"typescript/no-this-alias": "off",
"typescript/no-empty-object-type": "off",
"typescript/no-unused-expressions": "off",
"prefer-rest-params": "off",
"import/no-unassigned-import": "off",
"import/no-named-as-default-member": "off",
"import/no-named-as-default": "off",
"react/react-in-jsx-scope": "off",
"react/no-unstable-nested-components": "off",
"react/iframe-missing-sandbox": "off",
"react-hooks/exhaustive-deps": "off",
"no-shadow": "off",
"unicorn/no-array-sort": "off",
"unicorn/no-useless-fallback-in-spread": "off",
"unicorn/prefer-add-event-listener": "off",
"unicorn/consistent-function-scoping": "off",
"unicorn/no-instanceof-builtins": "off"
},
"categories": {
"correctness": "error",
"suspicious": "error"
},
"ignorePatterns": [
"src/.umi",
"src/.umi-production",
".ai_state",
".claude",
".codex",
"dist/**",
"dist-ssr/**",
"coverage/**"
]
}
+9
View File
@@ -0,0 +1,9 @@
/dist/*
.local
.output.js
/node_modules/**
**/*.svg
**/*.sh
/public/*
+20
View File
@@ -0,0 +1,20 @@
{
"printWidth": 150,
"tabWidth": 2,
"useTabs": false,
"semi": true,
"singleQuote": true,
"quoteProps": "preserve",
"jsxSingleQuote": false,
"bracketSameLine": false,
"trailingComma": "none",
"bracketSpacing": true,
"embeddedLanguageFormatting": "auto",
"arrowParens": "always",
"requirePragma": false,
"insertPragma": false,
"proseWrap": "preserve",
"htmlWhitespaceSensitivity": "css",
"vueIndentScriptAndStyle": false,
"endOfLine": "auto"
}
+20
View File
@@ -0,0 +1,20 @@
The MIT License (MIT)
Copyright (c) 2019 RuoYi-Vue-Plus
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+35 -37
View File
@@ -1,43 +1,35 @@
# RuoYi-React-Plus
## 平台简介
- 本仓库为前端技术栈 [React](https://react.dev/) + [TypeScript](https://www.typescriptlang.org/) + [Ant Design](https://ant.design/) + [Umi Max](https://umijs.org/) + [Vite](https://vitejs.dev/)。
- 官方项目: 基于 Vue + ElementPlus 版本前端项目 [plus-ui](https://gitee.com/JavaLionLi/plus-ui)
- 成员项目: 基于 vben5(ant-design-vue) 的前端项目 [ruoyi-plus-vben5](https://gitee.com/dapppp/ruoyi-plus-vben5)
- 成员项目: 基于soybean 的前端项目 [ruoyi-plus-soybean](https://gitee.com/xlsea/ruoyi-plus-soybean)
## 配套后端代码仓库地址
| 介绍 | 项目名 | 项目地址 |
| -------------- | :--------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| 分布式集群框架 | RuoYi-Vue-Plus | [Gitee](https://gitee.com/dromara/RuoYi-Vue-Plus) / [GitHub](https://github.com/dromara/RuoYi-Vue-Plus) / [GitCode](https://gitcode.com/dromara/RuoYi-Vue-Plus) |
| 微服务框架 | RuoYi-Cloud-Plus | [Gitee](https://gitee.com/dromara/RuoYi-Cloud-Plus) / [GitHub](https://github.com/dromara/RuoYi-Cloud-Plus) / [GitCode](https://gitcode.com/dromara/RuoYi-Cloud-Plus) |
## 分支说明
- 6.X-react分支(稳定发布主分支 生产可用)
- dev-react分支(开发分支 开发过程中使用)
- 本仓库为前端技术栈 [Vue3](https://v3.cn.vuejs.org) + [TS](https://www.typescriptlang.org/) + [Element Plus](https://element-plus.org/zh-CN) + [Vite](https://cn.vitejs.dev) 版本。
- 成员项目: 基于 vben(ant-design-vue) 的前端项目 [ruoyi-plus-vben](https://gitee.com/dapppp/ruoyi-plus-vben)
- 配套后端代码仓库地址
- [RuoYi-Vue-Plus 5.X(注意版本号)](https://gitee.com/dromara/RuoYi-Vue-Plus)
- [RuoYi-Cloud-Plus 2.X(注意版本号)](https://gitee.com/dromara/RuoYi-Cloud-Plus)
## 前端运行
```bash
# 克隆项目
git clone https://gitee.com/JavaLionLi/plus-ui.git
# 安装依赖
pnpm install --registry=https://registry.npmmirror.com
npm install --registry=https://registry.npmmirror.com
# 启动服务
pnpm dev
npm run dev
# 构建生产环境
pnpm build:prod
npm run build:prod
# 前端访问地址 http://localhost:8000
# 前端访问地址 http://localhost:80
```
## 本框架与RuoYi的业务差异
| 业务 | 功能说明 | 本框架 | RuoYi |
| ------------ | ------------------------------------------------------------- | ------ | ----------------------------- |
| 租户管理 | 系统内租户的管理 如:租户套餐、过期时间、用户数量、企业信息等 | 支持 | 无 |
| 租户套餐管理 | 系统内租户所能使用的套餐管理 如:套餐内所包含的菜单等 | 支持 | 无 |
| 用户管理 | 用户的管理配置 如:新增用户、分配用户所属部门、角色、岗位等 | 支持 | 支持 |
| 部门管理 | 配置系统组织机构(公司、部门、小组) 树结构展现支持数据权限 | 支持 | 支持 |
| 岗位管理 | 配置系统用户所属担任职务 | 支持 | 支持 |
@@ -61,18 +53,24 @@ pnpm build:prod
## 演示图例
| | |
|--------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------|
| ![输入图片说明](https://foruda.gitee.com/images/1780300015922774817/47c1f39f_1766278.png "屏幕截图") | ![输入图片说明](https://foruda.gitee.com/images/1780300034170229441/1608ee0a_1766278.png "屏幕截图") |
| ![输入图片说明](https://foruda.gitee.com/images/1780300053860691133/f8d334ce_1766278.png "屏幕截图") | ![输入图片说明](https://foruda.gitee.com/images/1780300066022559831/7c8e74cd_1766278.png "屏幕截图") |
| ![输入图片说明](https://foruda.gitee.com/images/1780300081538003511/906c028f_1766278.png "屏幕截图") | ![输入图片说明](https://foruda.gitee.com/images/1780300104233264980/8df4a03d_1766278.png "屏幕截图") |
| ![输入图片说明](https://foruda.gitee.com/images/1780300116889441614/7206e749_1766278.png "屏幕截图") | ![输入图片说明](https://foruda.gitee.com/images/1780300133555040293/6f4067f0_1766278.png "屏幕截图") |
| ![输入图片说明](https://foruda.gitee.com/images/1780300380395316233/d1cc70c4_1766278.png "屏幕截图") | ![输入图片说明](https://foruda.gitee.com/images/1780300232306768234/1f474295_1766278.png "屏幕截图") |
| ![输入图片说明](https://foruda.gitee.com/images/1780300245151922243/132ae6e0_1766278.png "屏幕截图") | ![输入图片说明](https://foruda.gitee.com/images/1780300259301543383/a0c982b3_1766278.png "屏幕截图") |
| ![输入图片说明](https://foruda.gitee.com/images/1780300401947949756/673c7fdc_1766278.png "屏幕截图") | ![输入图片说明](https://foruda.gitee.com/images/1780300417037474904/2fd89565_1766278.png "屏幕截图") |
| ![输入图片说明](https://foruda.gitee.com/images/1780300430575382678/cef384a4_1766278.png "屏幕截图") | ![输入图片说明](https://foruda.gitee.com/images/1780300446747725208/413ba289_1766278.png "屏幕截图") |
| ![输入图片说明](https://foruda.gitee.com/images/1780300471231552129/5d45227c_1766278.png "屏幕截图") | ![输入图片说明](https://foruda.gitee.com/images/1780300496559910468/0008fa0c_1766278.png "屏幕截图") |
| ![输入图片说明](https://foruda.gitee.com/images/1780300562713799535/a15b018d_1766278.png "屏幕截图") | ![输入图片说明](https://foruda.gitee.com/images/1780300575582711290/d440b1c9_1766278.png "屏幕截图") |
| ![输入图片说明](https://foruda.gitee.com/images/1780300617515185769/db2968e4_1766278.png "屏幕截图") | ![输入图片说明](https://foruda.gitee.com/images/1780300631462725775/30b9cd2c_1766278.png "屏幕截图") |
| ![输入图片说明](https://foruda.gitee.com/images/1780300644824617448/12b7e446_1766278.png "屏幕截图") | ![输入图片说明](https://foruda.gitee.com/images/1780300665964630901/07f14841_1766278.png "屏幕截图") |
| ![输入图片说明](https://foruda.gitee.com/images/1780300695487754948/17569a2e_1766278.png "屏幕截图") | ![输入图片说明](https://foruda.gitee.com/images/1780300715114472355/ebb81e7c_1766278.png "屏幕截图") |
| | |
| ---------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------- |
| ![输入图片说明](https://foruda.gitee.com/images/1680077524361362822/270bb429_1766278.png '屏幕截图') | ![输入图片说明](https://foruda.gitee.com/images/1680077619939771291/989bf9b6_1766278.png '屏幕截图') |
| ![输入图片说明](https://foruda.gitee.com/images/1680077681751513929/1c27c5bd_1766278.png '屏幕截图') | ![输入图片说明](https://foruda.gitee.com/images/1680077721559267315/74d63e23_1766278.png '屏幕截图') |
| ![输入图片说明](https://foruda.gitee.com/images/1680077765638904515/1b75d4a6_1766278.png '屏幕截图') | ![输入图片说明](https://foruda.gitee.com/images/1680078026375951297/eded7a4b_1766278.png '屏幕截图') |
| ![输入图片说明](https://foruda.gitee.com/images/1680078237104531207/0eb1b6a7_1766278.png '屏幕截图') | ![输入图片说明](https://foruda.gitee.com/images/1680078254306078709/5931e22f_1766278.png '屏幕截图') |
| ![输入图片说明](https://foruda.gitee.com/images/1680078287971528493/0b9af60a_1766278.png '屏幕截图') | ![输入图片说明](https://foruda.gitee.com/images/1680078308138770249/8d3b6696_1766278.png '屏幕截图') |
| ![输入图片说明](https://foruda.gitee.com/images/1680078352553634393/db5ef880_1766278.png '屏幕截图') | ![输入图片说明](https://foruda.gitee.com/images/1680078378238393374/601e4357_1766278.png '屏幕截图') |
| ![输入图片说明](https://foruda.gitee.com/images/1680078414983206024/2aae27c1_1766278.png '屏幕截图') | ![输入图片说明](https://foruda.gitee.com/images/1680078446738419874/ecce7d59_1766278.png '屏幕截图') |
| ![输入图片说明](https://foruda.gitee.com/images/1680078475971341775/149e8634_1766278.png '屏幕截图') | ![输入图片说明](https://foruda.gitee.com/images/1680078491666717143/3fadece7_1766278.png '屏幕截图') |
| ![输入图片说明](https://foruda.gitee.com/images/1680078558863188826/fb8ced2a_1766278.png '屏幕截图') | ![输入图片说明](https://foruda.gitee.com/images/1680078574561685461/ae68a0b2_1766278.png '屏幕截图') |
| ![输入图片说明](https://foruda.gitee.com/images/1680078594932772013/9d8bfec6_1766278.png '屏幕截图') | ![输入图片说明](https://foruda.gitee.com/images/1680078626493093532/fcfe4ff6_1766278.png '屏幕截图') |
| ![输入图片说明](https://foruda.gitee.com/images/1680078643608812515/0295bd4f_1766278.png '屏幕截图') | ![输入图片说明](https://foruda.gitee.com/images/1680078685196286463/d7612c81_1766278.png '屏幕截图') |
| ![输入图片说明](https://foruda.gitee.com/images/1680078703877318597/56fce0bc_1766278.png '屏幕截图') | ![输入图片说明](https://foruda.gitee.com/images/1680078716586545643/b6dbd68f_1766278.png '屏幕截图') |
| ![输入图片说明](https://foruda.gitee.com/images/1680078734103217688/eb1e6aa6_1766278.png '屏幕截图') | ![输入图片说明](https://foruda.gitee.com/images/1680078759131415480/73c525d8_1766278.png '屏幕截图') |
| ![输入图片说明](https://foruda.gitee.com/images/1680078779416197879/75e3ed02_1766278.png '屏幕截图') | ![输入图片说明](https://foruda.gitee.com/images/1680078802329118061/77e10915_1766278.png '屏幕截图') |
| ![输入图片说明](https://foruda.gitee.com/images/1680078893627848351/34a1c342_1766278.png '屏幕截图') | ![输入图片说明](https://foruda.gitee.com/images/1680078928175016986/f126ec4a_1766278.png '屏幕截图') |
| ![输入图片说明](https://foruda.gitee.com/images/1680078941718318363/b68a0f72_1766278.png '屏幕截图') | ![输入图片说明](https://foruda.gitee.com/images/1680078963175518631/3bb769a1_1766278.png '屏幕截图') |
| ![输入图片说明](https://foruda.gitee.com/images/1680078982294090567/b31c343d_1766278.png '屏幕截图') | ![输入图片说明](https://foruda.gitee.com/images/1680079000642440444/77ca82a9_1766278.png '屏幕截图') |
| ![输入图片说明](https://foruda.gitee.com/images/1680079020995074177/03b7d52e_1766278.png '屏幕截图') | ![输入图片说明](https://foruda.gitee.com/images/1680079039367822173/76811806_1766278.png '屏幕截图') |
| ![输入图片说明](https://foruda.gitee.com/images/1680079274333484664/4dfdc7c0_1766278.png '屏幕截图') | ![输入图片说明](https://foruda.gitee.com/images/1680079290467458224/d6715fcf_1766278.png '屏幕截图') |
+12
View File
@@ -0,0 +1,12 @@
@echo off
echo.
echo [信息] 打包Web工程,生成dist文件。
echo.
%~d0
cd %~dp0
cd ..
yarn build:prod
pause
+12
View File
@@ -0,0 +1,12 @@
@echo off
echo.
echo [信息] 安装Web工程,生成node_modules文件。
echo.
%~d0
cd %~dp0
cd ..
yarn --registry=https://registry.npmmirror.com
pause
+12
View File
@@ -0,0 +1,12 @@
@echo off
echo.
echo [信息] 使用 Vite 命令运行 Web 工程。
echo.
%~d0
cd %~dp0
cd ..
yarn dev
pause
-40
View File
@@ -1,40 +0,0 @@
import { defineConfig } from '@umijs/max';
import { createUmiAppConfig } from '../vite.config';
const appConfig = createUmiAppConfig();
export default defineConfig({
title: appConfig.title,
antd: {},
access: {},
model: {},
initialState: {},
vite: appConfig.vite,
npmClient: 'pnpm',
hash: true,
esbuildMinifyIIFE: true,
history: {
type: 'browser'
},
base: appConfig.base,
publicPath: appConfig.publicPath,
routes: [
{ path: '/login', component: './login', layout: false },
{ path: '/register', component: './register', layout: false },
{ path: '/social-callback', component: './socialCallback', layout: false },
{ path: '/401', component: './error/401', layout: false },
{ path: '/404', component: './error/404', layout: false },
{ path: '/redirect/*', component: './redirect', layout: false },
{
path: '/',
component: '../layouts/BasicLayout',
routes: [
{ path: '/', redirect: '/index' },
{ path: '/index', component: './index' },
{ path: '/user/profile', component: './system/user/profile' },
{ path: '*', component: './dynamicPage' }
]
}
],
proxy: appConfig.proxy
});
-94
View File
@@ -1,94 +0,0 @@
import type { <#if !table.tree>PageResult, </#if> R } from '@/api/types';
import request from '@/api/request';
import type { ${BusinessName}Form, ${BusinessName}Query, ${BusinessName}VO } from './types';
/**
* 查询${functionName}列表
*/
export function list${BusinessName}(query?: ${BusinessName}Query) {
return request<R<<#if table.tree>${BusinessName}VO[]<#else> PageResult<${BusinessName}VO></#if>>>({
url: '/${moduleName}/${businessName}/list',
method: 'get',
params: query
});
}
/**
* 查询${functionName}详细
*/
export function get${BusinessName}(${pkColumn.javaField}: string | number) {
return request<R<${BusinessName}VO>>({
url: '/${moduleName}/${businessName}/' + ${pkColumn.javaField},
method: 'get'
});
}
/**
* 新增${functionName}
*/
export function add${BusinessName}(data: ${BusinessName}Form) {
return request<R>({
url: '/${moduleName}/${businessName}',
method: 'post',
data
});
}
/**
* 修改${functionName}
*/
export function update${BusinessName}(data: ${BusinessName}Form) {
return request<R>({
url: '/${moduleName}/${businessName}',
method: 'put',
data
});
}
<#if enableStatus>
/**
* 修改${functionName}状态
*/
export function change${BusinessName}Status(
${pkColumn.javaField}: string | number,
${statusField}: <#if statusColumn.javaType == 'Boolean'>boolean<#elseif statusColumn.javaType == 'Integer' || statusColumn.javaType == 'Long'>number<#else> string</#if>
) {
return request<R>({
url: '/${moduleName}/${businessName}/changeStatus',
method: 'put',
data: {
${pkColumn.javaField},
${statusField}
}
});
}
</#if>
<#if enableSort>
/**
* 调整${functionName}排序
*/
export function update${BusinessName}Sort(
${pkColumn.javaField}: string | number,
${sortField}: <#if sortColumn.javaType == 'LocalDateTime' || sortColumn.javaType == 'String'>string<#else> number</#if>
) {
return request<R>({
url: '/${moduleName}/${businessName}/updateSort',
method: 'put',
data: {
${pkColumn.javaField},
${sortField}
}
});
}
</#if>
/**
* 删除${functionName}
*/
export function del${BusinessName}(${pkColumn.javaField}: string | number | Array<string | number>) {
return request<R>({
url: '/${moduleName}/${businessName}/' + ${pkColumn.javaField},
method: 'delete'
});
}
-424
View File
@@ -1,424 +0,0 @@
import { DeleteOutlined<#if enableExport>, DownloadOutlined</#if>, EditOutlined, PlusOutlined, SortAscendingOutlined } from '@ant-design/icons';
import {
ModalForm,
PageContainer,
<#if needCheckbox>
ProFormCheckbox,
</#if>
<#if needDateField>
ProFormDateTimePicker,
</#if>
<#if needDigit>
ProFormDigit,
</#if>
<#if needSelect>
ProFormSelect,
</#if>
<#if needTextArea>
ProFormTextArea,
</#if>
ProFormText,
ProFormTreeSelect,
ProTable,
type ActionType,
type ProColumns
} from '@ant-design/pro-components';
import { useBoolean } from 'ahooks';
import { Button, Form, message<#if enableStatus || needSwitchField>, Switch</#if><#if enableSort>, InputNumber</#if> } from 'antd';
import { useMemo, useRef, useState } from 'react';
import type { ${BusinessName}Form, ${BusinessName}Query, ${BusinessName}VO } from '@/api/${moduleName}/${businessName}/types';
import {
add${BusinessName},
<#if enableStatus>
change${BusinessName}Status,
</#if>
del${BusinessName},
get${BusinessName},
list${BusinessName},
<#if enableSort>
update${BusinessName}Sort,
</#if>
update${BusinessName}
} from '@/api/${moduleName}/${businessName}';
<#if needDict>
import DictTag from '@/components/common/DictTag';
</#if>
<#if needFileUpload>
import FileUpload from '@/components/common/FileUpload';
</#if>
<#if needImagePreview>
import ImagePreview from '@/components/common/ImagePreview';
</#if>
<#if needImageUpload>
import ImageUpload from '@/components/common/ImageUpload';
</#if>
<#if needEditor>
import RichTextEditor from '@/components/common/RichTextEditor';
</#if>
import RowActions from '@/components/common/RowActions';
<#if needDict>
import { useDict } from '@/hooks/useDict';
</#if>
<#if enableExport>
import { useTableExport } from '@/hooks/useTableExport';
</#if>
import { useTableScroll } from '@/hooks/useTableScroll';
import { useTreeTableExpand } from '@/hooks/useTreeTableExpand';
import { useUserStore } from '@/stores/userStore';
<#if needDict>
import { dictOptions } from '@/utils/dict';
</#if>
<#if enableStatus>
import { confirmAction } from '@/utils/modal';
</#if>
import { hasPermi } from '@/utils/permission';
import { filterTree<#if needDateField>, formatDateTimeFields</#if>, handleTree<#if needDateField>, toDayjsFields</#if> } from '@/utils/ruoyi';
const default${BusinessName}Form: ${BusinessName}Form = {
${treeParentCode}: ${treeRootValueTsLiteral},
<#list columns as column>
<#if (column.insert || column.edit) && !column.pk && column.htmlType == "checkbox">
${column.javaField}: [],
</#if>
</#list>
};
interface ${BusinessName}SelectNode {
title: string;
value: string | number;
children?: ${BusinessName}SelectNode[];
}
function toTreeSelectData(nodes: ${BusinessName}VO[]): ${BusinessName}SelectNode[] {
return nodes.map(node => ({
title: String(node.${treeName} || ''),
value: node.${treeCode},
children: node.children ? toTreeSelectData(node.children) : undefined
}));
}
<#if enableStatus>
const ${statusField}ActiveValue = <#if statusColumn.javaType == "Boolean">true<#elseif statusColumn.javaType == "Integer" || statusColumn.javaType == "Long">0<#else>'0'</#if>;
const ${statusField}InactiveValue = <#if statusColumn.javaType == "Boolean">false<#elseif statusColumn.javaType == "Integer" || statusColumn.javaType == "Long">1<#else>'1'</#if>;
</#if>
export default function ${BusinessName}Page() {
const actionRef = useRef<ActionType | undefined>(undefined);
const { tableScroll } = useTableScroll(1000);
const [form] = Form.useForm<${BusinessName}Form>();
const userInfo = useUserStore(state => state.userInfo);
<#if needDict>
const dicts = useDict(${dicts});
</#if>
const [treeOptions, setTreeOptions] = useState<${BusinessName}VO[]>([]);
const [tableRows, setTableRows] = useState<${BusinessName}VO[]>([]);
const { expandAll, expandedRowKeys, onExpandedRowsChange, syncExpandedRows, toggleExpandAll } =
useTreeTableExpand<${BusinessName}VO>(row => row.${treeCode});
const [modalOpen, { setTrue: openModal, setFalse: closeModal }] = useBoolean(false);
const [modalTitle, setModalTitle] = useState('');
<#if enableExport>
const { updateExportParams, exportFile } = useTableExport();
</#if>
const canAdd = hasPermi(userInfo, ['${permissionPrefix}:add']);
const canEdit = hasPermi(userInfo, ['${permissionPrefix}:edit']);
const canRemove = hasPermi(userInfo, ['${permissionPrefix}:remove']);
<#if enableExport>
const canExport = hasPermi(userInfo, ['${permissionPrefix}:export']);
</#if>
const treeSelectData = useMemo(
() => [{ title: '顶级节点', value: ${treeRootValueTsLiteral}, children: toTreeSelectData(treeOptions) }],
[treeOptions]
);
const loadTreeOptions = async (excludeId?: string | number) => {
const res = await list${BusinessName}();
const rows = handleTree<${BusinessName}VO>(res.data || [], '${treeCode}', '${treeParentCode}');
setTreeOptions(excludeId ? filterTree(rows, node => node.${treeCode} !== excludeId) : rows);
};
const openAdd = async (row?: ${BusinessName}VO) => {
await loadTreeOptions();
form.resetFields();
form.setFieldsValue({ ...default${BusinessName}Form, ${treeParentCode}: row?.${treeCode} || treeRootValueTsLiteral });
setModalTitle('添加${functionName}');
openModal();
};
const openEdit = async (row: ${BusinessName}VO) => {
await loadTreeOptions(row.${treeCode});
const res = await get${BusinessName}(row.${pkColumn.javaField});
const data = <#if needDateField>toDayjsFields({ ...res.data }, [
<#list columns as column>
<#if (column.insert || column.edit) && column.htmlType == "datetime">
'${column.javaField}',
</#if>
</#list>
])<#else>{ ...res.data }</#if>;
<#list columns as column>
<#if (column.insert || column.edit) && column.htmlType == "checkbox">
if (typeof data.${column.javaField} === 'string') {
data.${column.javaField} = data.${column.javaField}.split(',');
}
</#if>
</#list>
form.resetFields();
form.setFieldsValue(data);
setModalTitle('修改${functionName}');
openModal();
};
const submitForm = async (values: ${BusinessName}Form) => {
const submitValues = <#if needDateField>formatDateTimeFields({ ...values }, [
<#list columns as column>
<#if (column.insert || column.edit) && column.htmlType == "datetime">
'${column.javaField}',
</#if>
</#list>
])<#else>{ ...values }</#if>;
<#list columns as column>
<#if (column.insert || column.edit) && column.htmlType == "checkbox">
if (Array.isArray(submitValues.${column.javaField})) {
submitValues.${column.javaField} = submitValues.${column.javaField}.join(',');
}
</#if>
</#list>
submitValues.${pkColumn.javaField} ? await update${BusinessName}(submitValues) : await add${BusinessName}(submitValues);
message.success('操作成功');
form.resetFields();
actionRef.current?.reload();
return true;
};
const remove = async (row: ${BusinessName}VO) => {
await del${BusinessName}(row.${pkColumn.javaField});
message.success('删除成功');
actionRef.current?.reload();
};
<#if enableStatus>
const handleStatusChange = async (row: ${BusinessName}VO, checked: boolean) => {
const previousStatus = row.${statusField};
const status = checked ? ${statusField}ActiveValue : ${statusField}InactiveValue;
const text = checked ? '启用' : '停用';
try {
await confirmAction(`确认要"${r'${text}'}"吗?`);
await change${BusinessName}Status(row.${pkColumn.javaField}, status);
message.success(`${r'${text}'}成功`);
actionRef.current?.reload();
} catch {
row.${statusField} = previousStatus;
actionRef.current?.reload();
}
};
</#if>
<#if enableSort>
const handleSortChange = async (row: ${BusinessName}VO, value?: number | null) => {
await update${BusinessName}Sort(row.${pkColumn.javaField}, value || 0);
message.success('排序更新成功');
actionRef.current?.reload();
};
</#if>
const columns: ProColumns<${BusinessName}VO>[] = [
<#list columns as column>
<#if column.list && !column.pk>
<#if enableStatus && statusField == column.javaField>
{
title: '${column.columnLabel}',
dataIndex: '${column.javaField}',
valueType: 'select',
width: 100,
<#if column.dictType?has_content>
fieldProps: { options: dictOptions(dicts.${column.dictType}) },
</#if>
render: (_, row) => (
<Switch
checked={row.${column.javaField} === ${statusField}ActiveValue}
disabled={!canEdit}
onChange={checked => handleStatusChange(row, checked)}
/>
)
},
<#elseif enableSort && sortField == column.javaField>
{
title: '${column.columnLabel}',
dataIndex: '${column.javaField}',
search: false,
width: 130,
render: (_, row) => <InputNumber min={0} value={row.${column.javaField} as number} onChange={value => handleSortChange(row, value)} />
},
<#elseif column.htmlType == "datetime">
{ title: '${column.columnLabel}', dataIndex: '${column.javaField}', valueType: 'dateTime', search: <#if column.query>true<#else> false</#if>, width: 170 },
<#elseif column.htmlType == "imageUpload">
{
title: '${column.columnLabel}',
dataIndex: '${column.javaField}Url',
search: false,
width: 100,
render: (_, row) => <ImagePreview src={row.${column.javaField}Url || String(row.${column.javaField} || '')} width={50} height={50} />
},
<#elseif column.dictColumn>
{
title: '${column.columnLabel}',
dataIndex: '${column.javaField}',
valueType: 'select',
fieldProps: { options: dictOptions(dicts.${column.dictType}) },
render: (_, row) => <DictTag options={dicts.${column.dictType}} value={row.${column.javaField}} />
},
<#elseif column.htmlType == "switch">
{
title: '${column.columnLabel}',
dataIndex: '${column.javaField}',
valueType: 'select',
width: 100,
render: (_, row) => <Switch checked={row.${column.javaField} === ${column.switchActiveValue}} disabled />
},
<#else>
{ title: '${column.columnLabel}', dataIndex: '${column.javaField}'<#if !column.query>, search: false</#if> },
</#if>
</#if>
</#list>
{
title: '操作',
valueType: 'option',
width: 130,
fixed: 'right',
render: (_, row) => (
<RowActions
actions={[
canEdit && { key: 'edit', label: '修改', icon: <EditOutlined />, onClick: () => openEdit(row) },
canAdd && { key: 'add', label: '新增', icon: <PlusOutlined />, onClick: () => openAdd(row) },
canRemove && {
key: 'delete',
label: '删除',
icon: <DeleteOutlined />,
danger: true,
confirm: `是否确认删除${functionName}编号为"${r'${row.'}${pkColumn.javaField}${r'}'}"的数据项?`,
onClick: () => remove(row)
}
]}
/>
)
}
];
return (
<PageContainer title="${functionName}">
<ProTable<${BusinessName}VO, ${BusinessName}Query>
actionRef={actionRef}
rowKey="${treeCode}"
columns={columns}
scroll={tableScroll}
pagination={false}
search={{ labelWidth: 90 }}
expandable={{
expandedRowKeys,
onExpandedRowsChange
}}
request={async params => {
const res = await list${BusinessName}(params);
const rows = handleTree<${BusinessName}VO>(res.data || [], '${treeCode}', '${treeParentCode}');
setTableRows(rows);
syncExpandedRows(rows, expandAll);
<#if enableExport>
updateExportParams(params);
</#if>
return { data: rows, total: rows.length, success: true };
}}
toolbar={{ title: '${functionName}列表' }}
toolBarRender={() => [
canAdd && (
<Button key="add" type="primary" icon={<PlusOutlined />} onClick={() => openAdd()}>
新增
</Button>
),
<Button
key="expand"
icon={<SortAscendingOutlined />}
onClick={() => toggleExpandAll(tableRows)}
>
展开/折叠
</Button><#if enableExport>,
canExport && (
<Button
key="export"
icon={<DownloadOutlined />}
onClick={() => exportFile('/${moduleName}/${businessName}/export', () => `${businessName}_${r'${Date.now()}'}.xlsx`)}
>
导出
</Button>
)</#if>
]}
/>
<ModalForm<${BusinessName}Form>
title={modalTitle}
open={modalOpen}
width={560}
form={form}
layout="vertical"
initialValues={default${BusinessName}Form}
modalProps={{ destroyOnHidden: true, onCancel: closeModal }}
onOpenChange={open => !open && closeModal()}
onFinish={submitForm}
>
<ProFormText name="${pkColumn.javaField}" hidden />
<#list columns as column>
<#if (column.insert || column.edit) && !column.pk>
<#if column.javaField == treeParentCode>
<ProFormTreeSelect
name="${column.javaField}"
label="${column.columnLabel}"
<#if column.required>rules={[{ required: true, message: '${column.columnLabel}不能为空' }]}</#if>
fieldProps={{
allowClear: true,
treeDefaultExpandAll: true,
treeData: treeSelectData,
placeholder: '请选择${column.columnLabel}'
}}
/>
<#elseif column.htmlType == "input">
<ProFormText name="${column.javaField}" label="${column.columnLabel}" <#if column.required>rules={[{ required: true, message: '${column.columnLabel}不能为空' }]}</#if> />
<#elseif column.htmlType == "textarea">
<ProFormTextArea name="${column.javaField}" label="${column.columnLabel}" <#if column.required>rules={[{ required: true, message: '${column.columnLabel}不能为空' }]}</#if> />
<#elseif column.htmlType == "inputNumber">
<ProFormDigit name="${column.javaField}" label="${column.columnLabel}" min={0} <#if column.required>rules={[{ required: true, message: '${column.columnLabel}不能为空' }]}</#if> />
<#elseif (column.htmlType == "select" || column.htmlType == "radio" || column.htmlType == "switch") && column.dictType?has_content>
<ProFormSelect name="${column.javaField}" label="${column.columnLabel}" options={dictOptions(dicts.${column.dictType})} <#if column.required>rules={[{ required: true, message: '${column.columnLabel}不能为空' }]}</#if> />
<#elseif column.htmlType == "checkbox" && column.dictType?has_content>
<ProFormCheckbox.Group name="${column.javaField}" label="${column.columnLabel}" options={dictOptions(dicts.${column.dictType})} <#if column.required>rules={[{ required: true, message: '${column.columnLabel}不能为空' }]}</#if> />
<#elseif column.htmlType == "switch">
<Form.Item
name="${column.javaField}"
label="${column.columnLabel}"
valuePropName="checked"
getValueProps={value => ({ checked: value === ${column.switchActiveValue} })}
normalize={checked => (checked ? ${column.switchActiveValue} : ${column.switchInactiveValue})}
>
<Switch />
</Form.Item>
<#elseif column.htmlType == "datetime">
<ProFormDateTimePicker name="${column.javaField}" label="${column.columnLabel}" <#if column.required>rules={[{ required: true, message: '${column.columnLabel}不能为空' }]}</#if> />
<#elseif column.htmlType == "imageUpload">
<Form.Item name="${column.javaField}" label="${column.columnLabel}" <#if column.required>rules={[{ required: true, message: '${column.columnLabel}不能为空' }]}</#if>>
<ImageUpload />
</Form.Item>
<#elseif column.htmlType == "fileUpload">
<Form.Item name="${column.javaField}" label="${column.columnLabel}" <#if column.required>rules={[{ required: true, message: '${column.columnLabel}不能为空' }]}</#if>>
<FileUpload />
</Form.Item>
<#elseif column.htmlType == "editor">
<Form.Item name="${column.javaField}" label="${column.columnLabel}" <#if column.required>rules={[{ required: true, message: '${column.columnLabel}不能为空' }]}</#if>>
<RichTextEditor />
</Form.Item>
<#else>
<ProFormText name="${column.javaField}" label="${column.columnLabel}" <#if column.required>rules={[{ required: true, message: '${column.columnLabel}不能为空' }]}</#if> />
</#if>
</#if>
</#list>
</ModalForm>
</PageContainer>
);
}
-406
View File
@@ -1,406 +0,0 @@
import { DeleteOutlined<#if enableExport>, DownloadOutlined</#if>, EditOutlined, PlusOutlined } from '@ant-design/icons';
import {
ModalForm,
PageContainer,
<#if needCheckbox>
ProFormCheckbox,
</#if>
<#if needDateField>
ProFormDateTimePicker,
</#if>
<#if needDigit>
ProFormDigit,
</#if>
<#if needSelect>
ProFormSelect,
</#if>
<#if needTextArea>
ProFormTextArea,
</#if>
ProFormText,
ProTable,
type ActionType,
type ProColumns
} from '@ant-design/pro-components';
import { useBoolean } from 'ahooks';
import { Button, Form, message, Popconfirm<#if enableStatus || needSwitchField>, Switch</#if><#if enableSort>, InputNumber</#if> } from 'antd';
import { useRef, useState } from 'react';
import type { ${BusinessName}Form, ${BusinessName}Query, ${BusinessName}VO } from '@/api/${moduleName}/${businessName}/types';
import {
add${BusinessName},
<#if enableStatus>
change${BusinessName}Status,
</#if>
del${BusinessName},
get${BusinessName},
list${BusinessName},
<#if enableSort>
update${BusinessName}Sort,
</#if>
update${BusinessName}
} from '@/api/${moduleName}/${businessName}';
<#if needDict>
import DictTag from '@/components/common/DictTag';
</#if>
<#if needFileUpload>
import FileUpload from '@/components/common/FileUpload';
</#if>
<#if needImagePreview>
import ImagePreview from '@/components/common/ImagePreview';
</#if>
<#if needImageUpload>
import ImageUpload from '@/components/common/ImageUpload';
</#if>
<#if needEditor>
import RichTextEditor from '@/components/common/RichTextEditor';
</#if>
import RowActions from '@/components/common/RowActions';
<#if needDict>
import { useDict } from '@/hooks/useDict';
</#if>
<#if needDateRange>
import { useDateRangeQuery } from '@/hooks/useDateRangeQuery';
</#if>
<#if enableExport>
import { useTableExport } from '@/hooks/useTableExport';
</#if>
import { useTableScroll } from '@/hooks/useTableScroll';
import { useTableSelection } from '@/hooks/useTableSelection';
import { useUserStore } from '@/stores/userStore';
<#if needDict>
import { dictOptions } from '@/utils/dict';
</#if>
<#if enableStatus>
import { confirmAction } from '@/utils/modal';
</#if>
import { hasPermi } from '@/utils/permission';
import { <#if needDateField>formatDateTimeFields, toDayjsFields, </#if> toPageQuery, toTableData } from '@/utils/ruoyi';
const default${BusinessName}Form: ${BusinessName}Form = {
<#list columns as column>
<#if (column.insert || column.edit) && !column.pk && column.htmlType == "checkbox">
${column.javaField}: [],
</#if>
</#list>
};
<#if enableStatus>
const ${statusField}ActiveValue = <#if statusColumn.javaType == "Boolean">true<#elseif statusColumn.javaType == "Integer" || statusColumn.javaType == "Long">0<#else>'0'</#if>;
const ${statusField}InactiveValue = <#if statusColumn.javaType == "Boolean">false<#elseif statusColumn.javaType == "Integer" || statusColumn.javaType == "Long">1<#else>'1'</#if>;
</#if>
export default function ${BusinessName}Page() {
const actionRef = useRef<ActionType | undefined>(undefined);
const { tableScroll } = useTableScroll(1000);
const [form] = Form.useForm<${BusinessName}Form>();
const userInfo = useUserStore(state => state.userInfo);
<#if needDict>
const dicts = useDict(${dicts});
</#if>
const { ids, selectedOne, handleSelectionChange, clearSelection } = useTableSelection<${BusinessName}VO>(
row => row.${pkColumn.javaField}
);
const [modalOpen, { setTrue: openModal, setFalse: closeModal }] = useBoolean(false);
const [modalTitle, setModalTitle] = useState('');
<#if enableExport>
const { updateExportParams, exportFile } = useTableExport();
</#if>
<#list columns as column>
<#if column.query && column.htmlType == "datetime" && column.queryType == "BETWEEN">
const { applyDateRange: apply${column.capJavaField}DateRange } = useDateRangeQuery('${column.capJavaField}');
</#if>
</#list>
const canAdd = hasPermi(userInfo, ['${permissionPrefix}:add']);
const canEdit = hasPermi(userInfo, ['${permissionPrefix}:edit']);
const canRemove = hasPermi(userInfo, ['${permissionPrefix}:remove']);
<#if enableExport>
const canExport = hasPermi(userInfo, ['${permissionPrefix}:export']);
</#if>
const openAdd = () => {
form.resetFields();
form.setFieldsValue(default${BusinessName}Form);
setModalTitle('添加${functionName}');
openModal();
};
const openEdit = async (row?: ${BusinessName}VO) => {
const target = row || selectedOne;
if (!target?.${pkColumn.javaField}) return;
const res = await get${BusinessName}(target.${pkColumn.javaField});
const data = <#if needDateField>toDayjsFields({ ...res.data }, [
<#list columns as column>
<#if (column.insert || column.edit) && column.htmlType == "datetime">
'${column.javaField}',
</#if>
</#list>
])<#else>{ ...res.data }</#if>;
<#list columns as column>
<#if (column.insert || column.edit) && column.htmlType == "checkbox">
if (typeof data.${column.javaField} === 'string') {
data.${column.javaField} = data.${column.javaField}.split(',');
}
</#if>
</#list>
form.resetFields();
form.setFieldsValue(data);
setModalTitle('修改${functionName}');
openModal();
};
const submitForm = async (values: ${BusinessName}Form) => {
const submitValues = <#if needDateField>formatDateTimeFields({ ...values }, [
<#list columns as column>
<#if (column.insert || column.edit) && column.htmlType == "datetime">
'${column.javaField}',
</#if>
</#list>
])<#else>{ ...values }</#if>;
<#list columns as column>
<#if (column.insert || column.edit) && column.htmlType == "checkbox">
if (Array.isArray(submitValues.${column.javaField})) {
submitValues.${column.javaField} = submitValues.${column.javaField}.join(',');
}
</#if>
</#list>
submitValues.${pkColumn.javaField} ? await update${BusinessName}(submitValues) : await add${BusinessName}(submitValues);
message.success('操作成功');
form.resetFields();
actionRef.current?.reload();
return true;
};
const remove = async (row?: ${BusinessName}VO) => {
await del${BusinessName}(row?.${pkColumn.javaField} || ids);
message.success('删除成功');
clearSelection();
actionRef.current?.reloadAndRest?.();
};
<#if enableStatus>
const handleStatusChange = async (row: ${BusinessName}VO, checked: boolean) => {
const previousStatus = row.${statusField};
const status = checked ? ${statusField}ActiveValue : ${statusField}InactiveValue;
const text = checked ? '启用' : '停用';
try {
await confirmAction(`确认要"${r'${text}'}"吗?`);
await change${BusinessName}Status(row.${pkColumn.javaField}, status);
message.success(`${r'${text}'}成功`);
actionRef.current?.reload();
} catch {
row.${statusField} = previousStatus;
actionRef.current?.reload();
}
};
</#if>
<#if enableSort>
const handleSortChange = async (row: ${BusinessName}VO, value?: number | null) => {
await update${BusinessName}Sort(row.${pkColumn.javaField}, value || 0);
message.success('排序更新成功');
actionRef.current?.reload();
};
</#if>
const columns: ProColumns<${BusinessName}VO>[] = [
<#list columns as column>
<#if column.list>
<#if enableStatus && statusField == column.javaField>
{
title: '${column.columnLabel}',
dataIndex: '${column.javaField}',
valueType: 'select',
width: 100,
<#if column.dictType?has_content>
fieldProps: { options: dictOptions(dicts.${column.dictType}) },
</#if>
render: (_, row) => (
<Switch
checked={row.${column.javaField} === ${statusField}ActiveValue}
disabled={!canEdit}
onChange={checked => handleStatusChange(row, checked)}
/>
)
},
<#elseif enableSort && sortField == column.javaField>
{
title: '${column.columnLabel}',
dataIndex: '${column.javaField}',
search: false,
width: 130,
render: (_, row) => <InputNumber min={0} value={row.${column.javaField} as number} onChange={value => handleSortChange(row, value)} />
},
<#elseif column.htmlType == "datetime">
{ title: '${column.columnLabel}', dataIndex: '${column.javaField}', valueType: 'dateTime', search: <#if column.query && column.queryType != "BETWEEN">true<#else> false</#if>, width: 170 },
<#elseif column.htmlType == "imageUpload">
{
title: '${column.columnLabel}',
dataIndex: '${column.javaField}Url',
search: false,
width: 100,
render: (_, row) => <ImagePreview src={row.${column.javaField}Url || String(row.${column.javaField} || '')} width={50} height={50} />
},
<#elseif column.dictColumn>
{
title: '${column.columnLabel}',
dataIndex: '${column.javaField}',
valueType: 'select',
fieldProps: { options: dictOptions(dicts.${column.dictType}) },
render: (_, row) => <DictTag options={dicts.${column.dictType}} value={row.${column.javaField}} />
},
<#elseif column.htmlType == "switch">
{
title: '${column.columnLabel}',
dataIndex: '${column.javaField}',
valueType: 'select',
width: 100,
render: (_, row) => <Switch checked={row.${column.javaField} === ${column.switchActiveValue}} disabled />
},
<#else>
{ title: '${column.columnLabel}', dataIndex: '${column.javaField}'<#if !column.query>, search: false</#if> },
</#if>
</#if>
<#if column.query && column.htmlType == "datetime" && column.queryType == "BETWEEN">
{ title: '${column.columnLabel}', dataIndex: '${column.javaField}Range', valueType: 'dateTimeRange', hideInTable: true },
</#if>
</#list>
{
title: '操作',
valueType: 'option',
width: 92,
fixed: 'right',
render: (_, row) => (
<RowActions
actions={[
canEdit && { key: 'edit', label: '修改', icon: <EditOutlined />, onClick: () => openEdit(row) },
canRemove && {
key: 'delete',
label: '删除',
icon: <DeleteOutlined />,
danger: true,
confirm: `是否确认删除${functionName}编号为"${r'${row.'}${pkColumn.javaField}${r'}'}"的数据项?`,
onClick: () => remove(row)
}
]}
/>
)
}
];
return (
<PageContainer title="${functionName}">
<ProTable<${BusinessName}VO, ${BusinessName}Query<#if needDateRange> & Record<string, unknown></#if>>
actionRef={actionRef}
rowKey="${pkColumn.javaField}"
columns={columns}
scroll={tableScroll}
search={{ labelWidth: 90 }}
pagination={{ defaultPageSize: 10, showSizeChanger: true }}
rowSelection={{ selectedRowKeys: ids, onChange: handleSelectionChange }}
request={async params => {
<#if needDateRange>
let query = toPageQuery(params);
<#list columns as column>
<#if column.query && column.htmlType == "datetime" && column.queryType == "BETWEEN">
query = apply${column.capJavaField}DateRange(query, params.${column.javaField}Range as [string, string] | undefined);
delete query.${column.javaField}Range;
</#if>
</#list>
<#else>
const query = toPageQuery(params);
</#if>
<#if enableExport>
updateExportParams(query);
</#if>
const res = await list${BusinessName}(query);
return toTableData(res);
}}
toolbar={{ title: '${functionName}列表' }}
toolBarRender={() => [
canAdd && (
<Button key="add" type="primary" icon={<PlusOutlined />} onClick={openAdd}>
新增
</Button>
),
canEdit && (
<Button key="edit" disabled={!selectedOne} icon={<EditOutlined />} onClick={() => openEdit()}>
修改
</Button>
),
canRemove && (
<Popconfirm key="delete" title={`是否确认删除${functionName}编号为"${r'${ids}'}"的数据项?`} onConfirm={() => remove()}>
<Button danger disabled={!ids.length} icon={<DeleteOutlined />}>
删除
</Button>
</Popconfirm>
)<#if enableExport>,
canExport && (
<Button
key="export"
icon={<DownloadOutlined />}
onClick={() => exportFile('/${moduleName}/${businessName}/export', () => `${businessName}_${r'${Date.now()}'}.xlsx`)}
>
导出
</Button>
)</#if>
]}
/>
<ModalForm<${BusinessName}Form>
title={modalTitle}
open={modalOpen}
width={560}
form={form}
layout="vertical"
initialValues={default${BusinessName}Form}
modalProps={{ destroyOnHidden: true, onCancel: closeModal }}
onOpenChange={open => !open && closeModal()}
onFinish={submitForm}
>
<ProFormText name="${pkColumn.javaField}" hidden />
<#list columns as column>
<#if (column.insert || column.edit) && !column.pk>
<#if column.htmlType == "input">
<ProFormText name="${column.javaField}" label="${column.columnLabel}" <#if column.required>rules={[{ required: true, message: '${column.columnLabel}不能为空' }]}</#if> />
<#elseif column.htmlType == "textarea">
<ProFormTextArea name="${column.javaField}" label="${column.columnLabel}" <#if column.required>rules={[{ required: true, message: '${column.columnLabel}不能为空' }]}</#if> />
<#elseif column.htmlType == "inputNumber">
<ProFormDigit name="${column.javaField}" label="${column.columnLabel}" min={0} <#if column.required>rules={[{ required: true, message: '${column.columnLabel}不能为空' }]}</#if> />
<#elseif (column.htmlType == "select" || column.htmlType == "radio" || column.htmlType == "switch") && column.dictType?has_content>
<ProFormSelect name="${column.javaField}" label="${column.columnLabel}" options={dictOptions(dicts.${column.dictType})} <#if column.required>rules={[{ required: true, message: '${column.columnLabel}不能为空' }]}</#if> />
<#elseif column.htmlType == "checkbox" && column.dictType?has_content>
<ProFormCheckbox.Group name="${column.javaField}" label="${column.columnLabel}" options={dictOptions(dicts.${column.dictType})} <#if column.required>rules={[{ required: true, message: '${column.columnLabel}不能为空' }]}</#if> />
<#elseif column.htmlType == "switch">
<Form.Item
name="${column.javaField}"
label="${column.columnLabel}"
valuePropName="checked"
getValueProps={value => ({ checked: value === ${column.switchActiveValue} })}
normalize={checked => (checked ? ${column.switchActiveValue} : ${column.switchInactiveValue})}
>
<Switch />
</Form.Item>
<#elseif column.htmlType == "datetime">
<ProFormDateTimePicker name="${column.javaField}" label="${column.columnLabel}" <#if column.required>rules={[{ required: true, message: '${column.columnLabel}不能为空' }]}</#if> />
<#elseif column.htmlType == "imageUpload">
<Form.Item name="${column.javaField}" label="${column.columnLabel}" <#if column.required>rules={[{ required: true, message: '${column.columnLabel}不能为空' }]}</#if>>
<ImageUpload />
</Form.Item>
<#elseif column.htmlType == "fileUpload">
<Form.Item name="${column.javaField}" label="${column.columnLabel}" <#if column.required>rules={[{ required: true, message: '${column.columnLabel}不能为空' }]}</#if>>
<FileUpload />
</Form.Item>
<#elseif column.htmlType == "editor">
<Form.Item name="${column.javaField}" label="${column.columnLabel}" <#if column.required>rules={[{ required: true, message: '${column.columnLabel}不能为空' }]}</#if>>
<RichTextEditor />
</Form.Item>
<#else>
<ProFormText name="${column.javaField}" label="${column.columnLabel}" <#if column.required>rules={[{ required: true, message: '${column.columnLabel}不能为空' }]}</#if> />
</#if>
</#if>
</#list>
</ModalForm>
</PageContainer>
);
}
-54
View File
@@ -1,54 +0,0 @@
import type { BaseEntity<#if !table.tree>, PageQuery</#if> } from '@/api/types';
export interface ${BusinessName}VO {
<#list columns as column>
<#if column.list || column.pk>
/**
* ${column.columnComment}
*/
${column.javaField}: ${column.tsType};
<#if column.htmlType == "imageUpload">
/**
* ${column.columnComment}Url
*/
${column.javaField}Url?: string;
</#if>
</#if>
</#list>
<#if table.tree>
/**
* 子对象
*/
children?: ${BusinessName}VO[];
</#if>
}
export interface ${BusinessName}Form extends BaseEntity {
<#list columns as column>
<#if column.insert || column.edit || column.pk>
/**
* ${column.columnComment}
*/
<#if column.htmlType == "checkbox">
${column.javaField}?: string | string[];
<#else>
${column.javaField}?: ${column.tsType};
</#if>
</#if>
</#list>
}
export interface ${BusinessName}Query<#if !table.tree> extends PageQuery</#if> {
<#list columns as column>
<#if column.query>
/**
* ${column.columnComment}
*/
${column.javaField}?: ${column.tsType};
</#if>
</#list>
/**
* 日期范围参数
*/
params?: Record<string, unknown>;
}
+242
View File
File diff suppressed because one or more lines are too long
+214
View File
@@ -0,0 +1,214 @@
<!doctype html>
<html>
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
<meta name="renderer" content="webkit" />
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no" />
<link rel="icon" href="/favicon.ico" />
<title>RuoYi-Vue-Plus多租户管理系统</title>
<!--[if lt IE 11
]><script>
window.location.href = '/html/ie.html';
</script><!
[endif]-->
<style>
html,
body,
#app {
height: 100%;
margin: 0px;
padding: 0px;
}
.chromeframe {
margin: 0.2em 0;
background: #ccc;
color: #000;
padding: 0.2em 0;
}
#loader-wrapper {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 999999;
}
#loader {
display: block;
position: relative;
left: 50%;
top: 50%;
width: 150px;
height: 150px;
margin: -75px 0 0 -75px;
border-radius: 50%;
border: 3px solid transparent;
border-top-color: #fff;
-webkit-animation: spin 2s linear infinite;
-ms-animation: spin 2s linear infinite;
-moz-animation: spin 2s linear infinite;
-o-animation: spin 2s linear infinite;
animation: spin 2s linear infinite;
z-index: 1001;
}
#loader:before {
content: '';
position: absolute;
top: 5px;
left: 5px;
right: 5px;
bottom: 5px;
border-radius: 50%;
border: 3px solid transparent;
border-top-color: #fff;
-webkit-animation: spin 3s linear infinite;
-moz-animation: spin 3s linear infinite;
-o-animation: spin 3s linear infinite;
-ms-animation: spin 3s linear infinite;
animation: spin 3s linear infinite;
}
#loader:after {
content: '';
position: absolute;
top: 15px;
left: 15px;
right: 15px;
bottom: 15px;
border-radius: 50%;
border: 3px solid transparent;
border-top-color: #fff;
-moz-animation: spin 1.5s linear infinite;
-o-animation: spin 1.5s linear infinite;
-ms-animation: spin 1.5s linear infinite;
-webkit-animation: spin 1.5s linear infinite;
animation: spin 1.5s linear infinite;
}
@-webkit-keyframes spin {
0% {
-webkit-transform: rotate(0deg);
-ms-transform: rotate(0deg);
transform: rotate(0deg);
}
100% {
-webkit-transform: rotate(360deg);
-ms-transform: rotate(360deg);
transform: rotate(360deg);
}
}
@keyframes spin {
0% {
-webkit-transform: rotate(0deg);
-ms-transform: rotate(0deg);
transform: rotate(0deg);
}
100% {
-webkit-transform: rotate(360deg);
-ms-transform: rotate(360deg);
transform: rotate(360deg);
}
}
#loader-wrapper .loader-section {
position: fixed;
top: 0;
width: 51%;
height: 100%;
background: #7171c6;
z-index: 1000;
-webkit-transform: translateX(0);
-ms-transform: translateX(0);
transform: translateX(0);
}
#loader-wrapper .loader-section.section-left {
left: 0;
}
#loader-wrapper .loader-section.section-right {
right: 0;
}
.loaded #loader-wrapper .loader-section.section-left {
-webkit-transform: translateX(-100%);
-ms-transform: translateX(-100%);
transform: translateX(-100%);
-webkit-transition: all 0.7s 0.3s cubic-bezier(0.645, 0.045, 0.355, 1);
transition: all 0.7s 0.3s cubic-bezier(0.645, 0.045, 0.355, 1);
}
.loaded #loader-wrapper .loader-section.section-right {
-webkit-transform: translateX(100%);
-ms-transform: translateX(100%);
transform: translateX(100%);
-webkit-transition: all 0.7s 0.3s cubic-bezier(0.645, 0.045, 0.355, 1);
transition: all 0.7s 0.3s cubic-bezier(0.645, 0.045, 0.355, 1);
}
.loaded #loader {
opacity: 0;
-webkit-transition: all 0.3s ease-out;
transition: all 0.3s ease-out;
}
.loaded #loader-wrapper {
visibility: hidden;
-webkit-transform: translateY(-100%);
-ms-transform: translateY(-100%);
transform: translateY(-100%);
-webkit-transition: all 0.3s 1s ease-out;
transition: all 0.3s 1s ease-out;
}
.no-js #loader-wrapper {
display: none;
}
.no-js h1 {
color: #222222;
}
#loader-wrapper .load_title {
font-family: 'Open Sans';
color: #fff;
font-size: 19px;
width: 100%;
text-align: center;
z-index: 9999999999999;
position: absolute;
top: 60%;
opacity: 1;
line-height: 30px;
}
#loader-wrapper .load_title span {
font-weight: normal;
font-style: italic;
font-size: 13px;
color: #fff;
opacity: 0.5;
}
</style>
</head>
<body>
<div id="app">
<div id="loader-wrapper">
<div id="loader"></div>
<div class="loader-section section-left"></div>
<div class="loader-section section-right"></div>
<div class="load_title">正在加载系统资源,请耐心等待</div>
</div>
</div>
<script type="module" src="/src/main.ts"></script>
</body>
</html>
+78 -54
View File
@@ -1,67 +1,91 @@
{
"name": "plus-ui-react",
"version": "6.0.0",
"private": true,
"description": "React + Ant Design version of RuoYi-Vue-Plus UI",
"name": "ruoyi-vue-plus",
"version": "5.2.1",
"description": "RuoYi-Vue-Plus多租户管理系统",
"author": "LionLi",
"license": "MIT",
"type": "module",
"packageManager": "pnpm@10.34.5",
"scripts": {
"build": "pnpm build:prod",
"build:dev": "cross-env UMI_ENV=development BABEL_POLYFILL=none max build",
"build:prod": "cross-env UMI_ENV=production BABEL_POLYFILL=none max build",
"dev": "cross-env UMI_ENV=development MOCK=none BABEL_POLYFILL=none max dev",
"fmt": "oxfmt .",
"lint": "oxlint src config vite.config.ts && cross-env UMI_ENV=development BABEL_POLYFILL=none max setup && tsc --noEmit",
"lint:fix": "oxlint --fix src config vite.config.ts",
"openapi": "max openapi",
"preview": "max preview --port 8000",
"start": "cross-env UMI_ENV=development MOCK=none BABEL_POLYFILL=none max dev"
"dev": "vite serve --mode development",
"build:prod": "vite build --mode production",
"build:dev": "vite build --mode development",
"preview": "vite preview",
"lint:eslint": "eslint --fix --ext .ts,.js,.vue ./src ",
"prettier": "prettier --write ."
},
"repository": {
"type": "git",
"url": "https://gitee.com/JavaLionLi/plus-ui.git"
},
"dependencies": {
"@ant-design/icons": "^6.3.2",
"@ant-design/pro-components": "3.1.12-0",
"@ant-design/x": "^2.8.0",
"@iconify/react": "^6.0.2",
"@tanstack/react-query": "^5.101.4",
"@umijs/max": "^4.6.82",
"@wangeditor-next/editor": "^5.7.16",
"@wangeditor-next/editor-for-react": "^2.0.3",
"ahooks": "^3.9.7",
"antd": "^6.5.2",
"antd-style": "^4.1.0",
"axios": "1.18.1",
"browser-image-compression": "^2.0.2",
"clsx": "^2.1.1",
"@element-plus/icons-vue": "2.3.1",
"@highlightjs/vue-plugin": "2.1.0",
"@vueup/vue-quill": "1.2.0",
"@vueuse/core": "10.9.0",
"animate.css": "4.1.1",
"await-to-js": "3.0.0",
"axios": "1.6.8",
"bpmn-js": "16.4.0",
"crypto-js": "4.2.0",
"dayjs": "^1.11.21",
"echarts": "^6.1.0",
"echarts-for-react": "^3.0.6",
"jsencrypt": "3.5.4",
"diagram-js": "12.3.0",
"didi": "9.0.2",
"echarts": "5.5.0",
"element-plus": "2.7.5",
"file-saver": "2.0.5",
"fuse.js": "7.0.0",
"highlight.js": "11.9.0",
"image-conversion": "^2.1.1",
"js-cookie": "3.0.5",
"jsencrypt": "3.3.2",
"nprogress": "0.2.0",
"react": "^19.2.8",
"react-dom": "^19.2.8",
"react-easy-crop": "^6.2.3",
"react-json-view-lite": "^2.5.0",
"react-syntax-highlighter": "^16.1.1",
"screenfull": "^6.0.2",
"zustand": "^5.0.14"
"pinia": "2.1.7",
"screenfull": "6.0.2",
"vue": "3.4.25",
"vue-cropper": "1.1.1",
"vue-i18n": "9.10.2",
"vue-router": "4.3.2",
"vue-types": "5.1.1",
"vxe-table": "4.5.22"
},
"devDependencies": {
"@iconify/json": "2.2.201",
"@intlify/unplugin-vue-i18n": "3.0.1",
"@types/crypto-js": "4.2.2",
"@types/node": "^26.1.1",
"@types/file-saver": "2.0.7",
"@types/js-cookie": "3.0.6",
"@types/node": "18.18.2",
"@types/nprogress": "0.2.3",
"@types/react": "^19.2.17",
"@types/react-dom": "^19.2.3",
"@types/react-syntax-highlighter": "^15.5.13",
"@umijs/lint": "^4.6.82",
"@umijs/max-plugin-openapi": "^2.0.3",
"cross-env": "^10.1.0",
"oxfmt": "^0.60.0",
"oxlint": "^1.75.0",
"typescript": "^6.0.3"
},
"engines": {
"node": ">=20.19.0",
"pnpm": ">=10.0.0"
"@typescript-eslint/eslint-plugin": "7.3.1",
"@typescript-eslint/parser": "7.3.1",
"@unocss/preset-attributify": "0.58.6",
"@unocss/preset-icons": "0.58.6",
"@unocss/preset-uno": "0.58.6",
"@vitejs/plugin-vue": "5.0.4",
"@vue/compiler-sfc": "3.4.23",
"autoprefixer": "10.4.18",
"eslint": "8.57.0",
"eslint-config-prettier": "9.1.0",
"eslint-define-config": "2.1.0",
"eslint-plugin-prettier": "5.1.3",
"eslint-plugin-promise": "6.1.1",
"eslint-plugin-node": "11.1.0",
"eslint-plugin-import": "2.29.1",
"eslint-plugin-vue": "9.23.0",
"fast-glob": "3.3.2",
"postcss": "8.4.36",
"prettier": "3.2.5",
"sass": "1.72.0",
"typescript": "5.4.5",
"unocss": "0.58.6",
"unplugin-auto-import": "0.17.5",
"unplugin-icons": "0.18.5",
"unplugin-vue-components": "0.26.0",
"unplugin-vue-setup-extend-plus": "1.0.1",
"vite": "5.2.10",
"vite-plugin-compression": "0.5.1",
"vite-plugin-svg-icons": "2.0.1",
"vitest": "1.5.0",
"vue-eslint-parser": "9.4.2",
"vue-tsc": "2.0.13"
}
}
-17133
View File
File diff suppressed because it is too large Load Diff

Before

Width:  |  Height:  |  Size: 7.9 KiB

After

Width:  |  Height:  |  Size: 7.9 KiB

+20
View File
@@ -0,0 +1,20 @@
<template>
<el-config-provider :locale="appStore.locale" :size="appStore.size">
<router-view />
</el-config-provider>
</template>
<script setup lang="ts">
import useSettingsStore from '@/store/modules/settings';
import { handleThemeStyle } from '@/utils/theme';
import useAppStore from '@/store/modules/app';
const appStore = useAppStore();
onMounted(() => {
nextTick(() => {
// 初始化主题样式
handleThemeStyle(useSettingsStore().theme);
});
});
</script>
+48
View File
@@ -0,0 +1,48 @@
// 前缀
const animatePrefix = 'animate__animated ';
// 开启随机动画 随机动画值
const animateList: string[] = [
animatePrefix + 'animate__pulse',
animatePrefix + 'animate__rubberBand',
animatePrefix + 'animate__bounceIn',
animatePrefix + 'animate__bounceInLeft',
animatePrefix + 'animate__fadeIn',
animatePrefix + 'animate__fadeInLeft',
animatePrefix + 'animate__fadeInDown',
animatePrefix + 'animate__fadeInUp',
animatePrefix + 'animate__flipInX',
animatePrefix + 'animate__lightSpeedInLeft',
animatePrefix + 'animate__rotateInDownLeft',
animatePrefix + 'animate__rollIn',
animatePrefix + 'animate__rotateInDownLeft',
animatePrefix + 'animate__zoomIn',
animatePrefix + 'animate__zoomInDown',
animatePrefix + 'animate__slideInLeft',
animatePrefix + 'animate__lightSpeedIn'
];
// 关闭随机动画后的默认效果
const defaultAnimate = animatePrefix + 'animate__fadeIn';
// 搜索隐藏显示动画
const searchAnimate = {
enter: '',
leave: ''
};
// 菜单搜索动画
const menuSearchAnimate = {
enter: animatePrefix + 'animate__fadeIn',
leave: animatePrefix + 'animate__fadeOut'
};
// logo动画
const logoAnimate = {
enter: animatePrefix + 'animate__fadeIn',
leave: animatePrefix + 'animate__fadeOut'
};
export default {
animateList,
defaultAnimate,
searchAnimate,
menuSearchAnimate,
logoAnimate
};
-10
View File
@@ -1,10 +0,0 @@
import type { R } from '@/api/types';
import request from '@/api/request';
import type { SnailOpenApiUser } from './types';
export function registerCurrentSnailUser() {
return request<R<SnailOpenApiUser>>({
url: '/snail-ai/user/register',
method: 'post'
});
}
-6
View File
@@ -1,6 +0,0 @@
export interface SnailOpenApiUser {
openId: string;
nickname?: string;
externalId?: string;
created?: boolean;
}
-2
View File
@@ -1,2 +0,0 @@
export * from './agent';
export * from './agent/types';
+43 -22
View File
@@ -1,41 +1,62 @@
import type { PageResult, R } from '@/api/types';
import request from '@/api/request';
import type { DemoForm, DemoQuery, DemoVO } from './types';
import request from '@/utils/request';
import { AxiosPromise } from 'axios';
import { DemoVO, DemoForm, DemoQuery } from '@/api/demo/demo/types';
export function listDemo(query?: DemoQuery) {
return request<R<PageResult<DemoVO>>>({
/**
* 查询测试单列表
* @param query
* @returns {*}
*/
export const listDemo = (query?: DemoQuery): AxiosPromise<DemoVO[]> => {
return request({
url: '/demo/demo/list',
method: 'get',
params: query
});
}
};
export function getDemo(id: string | number) {
return request<R<DemoVO>>({
url: `/demo/demo/${id}`,
/**
* 查询测试单详细
* @param id
*/
export const getDemo = (id: string | number): AxiosPromise<DemoVO> => {
return request({
url: '/demo/demo/' + id,
method: 'get'
});
}
};
export function addDemo(data: DemoForm) {
return request<R>({
/**
* 新增测试单
* @param data
*/
export const addDemo = (data: DemoForm) => {
return request({
url: '/demo/demo',
method: 'post',
data
data: data
});
}
};
export function updateDemo(data: DemoForm) {
return request<R>({
/**
* 修改测试单
* @param data
*/
export const updateDemo = (data: DemoForm) => {
return request({
url: '/demo/demo',
method: 'put',
data
data: data
});
}
};
export function delDemo(id: string | number | Array<string | number>) {
return request<R>({
url: `/demo/demo/${id}`,
/**
* 删除测试单
* @param id
*/
export const delDemo = (id: string | number | Array<string | number>) => {
return request({
url: '/demo/demo/' + id,
method: 'delete'
});
}
};
+73 -10
View File
@@ -1,27 +1,90 @@
import type { BaseEntity, PageQuery } from '@/api/types';
export interface DemoVO {
/**
* 主键
*/
id: string | number;
/**
* 部门id
*/
deptId: string | number;
/**
* 用户id
*/
userId: string | number;
/**
* 排序号
*/
orderNum: number;
/**
* key键
*/
testKey: string;
/**
* 值
*/
value: string;
}
export interface DemoForm extends BaseEntity {
/**
* 主键
*/
id?: string | number;
/**
* 部门id
*/
deptId?: string | number;
/**
* 用户id
*/
userId?: string | number;
/**
* 排序号
*/
orderNum?: number;
/**
* key键
*/
testKey?: string;
/**
* 值
*/
value?: string;
}
export interface DemoQuery extends PageQuery {
/**
* 部门id
*/
deptId?: string | number;
/**
* 用户id
*/
userId?: string | number;
/**
* 排序号
*/
orderNum?: number;
/**
* key键
*/
testKey?: string;
/**
* 值
*/
value?: string;
}
export interface DemoVO {
id: string | number;
deptId: string | number;
userId: string | number;
orderNum: number;
testKey: string;
value: string;
}
+43 -22
View File
@@ -1,41 +1,62 @@
import type { R } from '@/api/types';
import request from '@/api/request';
import type { TreeForm, TreeQuery, TreeVO } from './types';
import request from '@/utils/request';
import { AxiosPromise } from 'axios';
import { TreeVO, TreeForm, TreeQuery } from '@/api/demo/tree/types';
export function listTree(query?: TreeQuery) {
return request<R<TreeVO[]>>({
/**
* 查询测试树列表
* @param query
* @returns {*}
*/
export const listTree = (query?: TreeQuery): AxiosPromise<TreeVO[]> => {
return request({
url: '/demo/tree/list',
method: 'get',
params: query
});
}
};
export function getTree(id: string | number) {
return request<R<TreeVO>>({
url: `/demo/tree/${id}`,
/**
* 查询测试树详细
* @param id
*/
export const getTree = (id: string | number): AxiosPromise<TreeVO> => {
return request({
url: '/demo/tree/' + id,
method: 'get'
});
}
};
export function addTree(data: TreeForm) {
return request<R>({
/**
* 新增测试树
* @param data
*/
export const addTree = (data: TreeForm) => {
return request({
url: '/demo/tree',
method: 'post',
data
data: data
});
}
};
export function updateTree(data: TreeForm) {
return request<R>({
/**
* 修改测试树
* @param data
*/
export const updateTree = (data: TreeForm) => {
return request({
url: '/demo/tree',
method: 'put',
data
data: data
});
}
};
export function delTree(id: string | number | Array<string | number>) {
return request<R>({
url: `/demo/tree/${id}`,
/**
* 删除测试树
* @param id
*/
export const delTree = (id: string | number | Array<string | number>) => {
return request({
url: '/demo/tree/' + id,
method: 'delete'
});
}
};
+65 -10
View File
@@ -1,25 +1,80 @@
import type { BaseEntity } from '@/api/types';
export interface TreeVO {
/**
* 主键
*/
id: string | number;
/**
* 父id
*/
parentId: string | number;
/**
* 部门id
*/
deptId: string | number;
/**
* 用户id
*/
userId: string | number;
/**
* 值
*/
treeName: string;
/**
* 子对象
*/
children: TreeVO[];
}
export interface TreeForm extends BaseEntity {
/**
* 主键
*/
id?: string | number;
/**
* 父id
*/
parentId?: string | number;
/**
* 部门id
*/
deptId?: string | number;
/**
* 用户id
*/
userId?: string | number;
/**
* 值
*/
treeName?: string;
}
export interface TreeQuery {
/**
* 父id
*/
parentId?: string | number;
/**
* 部门id
*/
deptId?: string | number;
/**
* 用户id
*/
userId?: string | number;
/**
* 值
*/
treeName?: string;
}
export interface TreeVO {
id: string | number;
parentId: string | number;
deptId: string | number;
userId: string | number;
treeName: string;
children?: TreeVO[];
}
+80 -48
View File
@@ -1,75 +1,107 @@
import type { UserInfo } from '@/api/system/user/types';
import type { LoginParams, LoginResult, R, RegisterParams, VerifyCodeResult } from '@/api/types';
import request from '@/api/request';
import { appEnv } from '@/utils/env';
import request from '@/utils/request';
import { AxiosPromise } from 'axios';
import { LoginData, LoginResult, VerifyCodeResult, TenantInfo } from './types';
import { UserInfo } from '@/api/system/user/types';
export function login(data: LoginParams) {
return request<R<LoginResult>>({
// pc端固定客户端授权id
const clientId = import.meta.env.VITE_APP_CLIENT_ID;
/**
* @param data {LoginData}
* @returns
*/
export function login(data: LoginData): AxiosPromise<LoginResult> {
const params = {
...data,
clientId: data.clientId || clientId,
grantType: data.grantType || 'password'
};
return request({
url: '/auth/login',
method: 'post',
headers: {
isToken: false,
isEncrypt: 'true',
isEncrypt: true,
repeatSubmit: false
},
data: {
...data,
clientId: data.clientId || appEnv.clientId,
grantType: data.grantType || 'password'
}
method: 'post',
data: params
});
}
// 注册方法
export function register(data: any) {
const params = {
...data,
clientId: clientId,
grantType: 'password'
};
return request({
url: '/auth/register',
headers: {
isToken: false,
isEncrypt: true,
repeatSubmit: false
},
method: 'post',
data: params
});
}
/**
* 注销
*/
export function logout() {
return request<R>({
return request({
url: '/auth/logout',
method: 'post'
});
}
export function register(data: RegisterParams) {
return request<R>({
url: '/auth/register',
method: 'post',
headers: {
isToken: false,
isEncrypt: 'true',
repeatSubmit: false
},
data: {
...data,
clientId: appEnv.clientId,
grantType: 'password'
}
});
}
export function callback(data: LoginParams) {
return request<R<LoginResult>>({
url: '/auth/social/callback',
method: 'post',
data: {
...data,
clientId: appEnv.clientId,
grantType: 'social'
}
});
}
export function getCodeImg() {
return request<R<VerifyCodeResult>>({
/**
* 获取验证码
*/
export function getCodeImg(): AxiosPromise<VerifyCodeResult> {
return request({
url: '/auth/code',
method: 'get',
headers: {
isToken: false
},
method: 'get',
timeout: 20000
});
}
export function getInfo() {
return request<R<UserInfo>>({
/**
* 第三方登录
*/
export function callback(data: LoginData): AxiosPromise<any> {
const LoginData = {
...data,
clientId: clientId,
grantType: 'social'
};
return request({
url: '/auth/social/callback',
method: 'post',
data: LoginData
});
}
// 获取用户详细信息
export function getInfo(): AxiosPromise<UserInfo> {
return request({
url: '/system/user/getInfo',
method: 'get'
});
}
// 获取租户列表
export function getTenantList(): AxiosPromise<TenantInfo> {
return request({
url: '/auth/tenant/list',
headers: {
isToken: false
},
method: 'get'
});
}
+6 -4
View File
@@ -1,8 +1,10 @@
import type { BackendRoute, R } from '@/api/types';
import request from '@/api/request';
import request from '@/utils/request';
import { AxiosPromise } from 'axios';
import { RouteRecordRaw } from 'vue-router';
export function getRouters() {
return request<R<BackendRoute[]>>({
// 获取路由
export function getRouters(): AxiosPromise<RouteRecordRaw[]> {
return request({
url: '/system/menu/getRouters',
method: 'get'
});
+54 -5
View File
@@ -1,10 +1,59 @@
import type { R } from '@/api/types';
import request from '@/api/request';
import type { CacheVO } from './types';
import request from '@/utils/request';
import { AxiosPromise } from 'axios';
import { CacheVO } from './types';
export function getCache() {
return request<R<CacheVO>>({
// 查询缓存详细
export function getCache(): AxiosPromise<CacheVO> {
return request({
url: '/monitor/cache',
method: 'get'
});
}
// 查询缓存名称列表
export function listCacheName() {
return request({
url: '/monitor/cache/getNames',
method: 'get'
});
}
// 查询缓存键名列表
export function listCacheKey(cacheName: string) {
return request({
url: '/monitor/cache/getKeys/' + cacheName,
method: 'get'
});
}
// 查询缓存内容
export function getCacheValue(cacheName: string, cacheKey: string) {
return request({
url: '/monitor/cache/getValue/' + cacheName + '/' + cacheKey,
method: 'get'
});
}
// 清理指定名称缓存
export function clearCacheName(cacheName: string) {
return request({
url: '/monitor/cache/clearCacheName/' + cacheName,
method: 'delete'
});
}
// 清理指定键名缓存
export function clearCacheKey(cacheName: string, cacheKey: string) {
return request({
url: '/monitor/cache/clearCacheKey/' + cacheName + '/' + cacheKey,
method: 'delete'
});
}
// 清理全部缓存
export function clearCacheAll() {
return request({
url: '/monitor/cache/clearCacheAll',
method: 'delete'
});
}
+5 -3
View File
@@ -1,5 +1,7 @@
export interface CacheVO {
commandStats: Array<{ name: string; value: string | number }>;
export interface CacheVO {
commandStats: Array<{ name: string; value: string }>;
dbSize: number;
info: Record<string, string>;
info: { [key: string]: string };
}
+36
View File
@@ -0,0 +1,36 @@
import request from '@/utils/request';
import { LoginInfoQuery, LoginInfoVO } from './types';
import { AxiosPromise } from 'axios';
// 查询登录日志列表
export function list(query: LoginInfoQuery): AxiosPromise<LoginInfoVO[]> {
return request({
url: '/monitor/logininfor/list',
method: 'get',
params: query
});
}
// 删除登录日志
export function delLoginInfo(infoId: string | number | Array<string | number>) {
return request({
url: '/monitor/logininfor/' + infoId,
method: 'delete'
});
}
// 解锁用户登录状态
export function unlockLoginInfo(userName: string | Array<string>) {
return request({
url: '/monitor/logininfor/unlock/' + userName,
method: 'get'
});
}
// 清空登录日志
export function cleanLoginInfo() {
return request({
url: '/monitor/logininfor/clean',
method: 'delete'
});
}
+20
View File
@@ -0,0 +1,20 @@
export interface LoginInfoVO {
infoId: string | number;
tenantId: string | number;
userName: string;
status: string;
ipaddr: string;
loginLocation: string;
browser: string;
os: string;
msg: string;
loginTime: string;
}
export interface LoginInfoQuery extends PageQuery {
ipaddr: string;
userName: string;
status: string;
orderByColumn: string;
isAsc: string;
}
-36
View File
@@ -1,36 +0,0 @@
import type { PageResult, R } from '@/api/types';
import request from '@/api/request';
import type { LoginInfoQuery, LoginInfoVO } from './types';
export function listLoginInfo(query: LoginInfoQuery) {
return request<R<PageResult<LoginInfoVO>>>({
url: '/monitor/loginInfo/list',
method: 'get',
params: query
});
}
export function list(query: LoginInfoQuery) {
return listLoginInfo(query);
}
export function delLoginInfo(infoId: string | number | Array<string | number>) {
return request<R>({
url: `/monitor/loginInfo/${infoId}`,
method: 'delete'
});
}
export function unlockLoginInfo(userName: string | string[]) {
return request<R>({
url: `/monitor/loginInfo/unlock/${userName}`,
method: 'get'
});
}
export function cleanLoginInfo() {
return request<R>({
url: '/monitor/loginInfo/clean',
method: 'delete'
});
}
-24
View File
@@ -1,24 +0,0 @@
import type { PageQuery } from '@/api/types';
export interface LoginInfoQuery extends Omit<PageQuery, 'isAsc'> {
ipaddr?: string;
userName?: string;
status?: string;
orderByColumn?: string;
isAsc?: string;
}
export interface LoginInfoVO {
infoId: string | number;
tenantId?: string | number;
userName: string;
clientKey?: string;
deviceType?: string;
status: string;
ipaddr?: string;
loginLocation?: string;
browser?: string;
os?: string;
msg?: string;
loginTime?: string;
}
+15 -15
View File
@@ -1,36 +1,36 @@
import type { PageResult, R } from '@/api/types';
import request from '@/api/request';
import type { OnlineQuery, OnlineVO } from './types';
import request from '@/utils/request';
import { OnlineQuery, OnlineVO } from './types';
import { AxiosPromise } from 'axios';
export function listOnline(query: OnlineQuery) {
return request<R<PageResult<OnlineVO>>>({
// 查询在线用户列表
export function list(query: OnlineQuery): AxiosPromise<OnlineVO[]> {
return request({
url: '/monitor/online/list',
method: 'get',
params: query
});
}
export function list(query: OnlineQuery) {
return listOnline(query);
}
// 强退用户
export function forceLogout(tokenId: string) {
return request<R>({
url: `/monitor/online/${tokenId}`,
return request({
url: '/monitor/online/' + tokenId,
method: 'delete'
});
}
// 获取当前用户登录在线设备
export function getOnline() {
return request<R<OnlineVO[] | PageResult<OnlineVO>>>({
return request({
url: '/monitor/online',
method: 'get'
});
}
// 删除当前在线设备
export function delOnline(tokenId: string) {
return request<R>({
url: `/monitor/online/myself/${tokenId}`,
method: 'delete'
return request({
url: '/monitor/online/' + tokenId,
method: 'post'
});
}
+8 -12
View File
@@ -1,19 +1,15 @@
import type { BaseEntity, PageQuery } from '@/api/types';
export interface OnlineQuery extends PageQuery {
ipaddr?: string;
userName?: string;
ipaddr: string;
userName: string;
}
export interface OnlineVO extends BaseEntity {
tokenId: string;
deptName?: string;
deptName: string;
userName: string;
clientKey?: string;
deviceType?: string;
ipaddr?: string;
loginLocation?: string;
browser?: string;
os?: string;
loginTime?: number | string;
ipaddr: string;
loginLocation: string;
browser: string;
os: string;
loginTime: number;
}
+11 -12
View File
@@ -1,28 +1,27 @@
import type { PageResult, R } from '@/api/types';
import request from '@/api/request';
import type { OperLogQuery, OperLogVO } from './types';
import request from '@/utils/request';
import { OperLogQuery, OperLogVO } from './types';
import { AxiosPromise } from 'axios';
export function listOperlog(query: OperLogQuery) {
return request<R<PageResult<OperLogVO>>>({
// 查询操作日志列表
export function list(query: OperLogQuery): AxiosPromise<OperLogVO[]> {
return request({
url: '/monitor/operlog/list',
method: 'get',
params: query
});
}
export function list(query: OperLogQuery) {
return listOperlog(query);
}
// 删除操作日志
export function delOperlog(operId: string | number | Array<string | number>) {
return request<R>({
url: `/monitor/operlog/${operId}`,
return request({
url: '/monitor/operlog/' + operId,
method: 'delete'
});
}
// 清空操作日志
export function cleanOperlog() {
return request<R>({
return request({
url: '/monitor/operlog/clean',
method: 'delete'
});
+48 -40
View File
@@ -1,45 +1,53 @@
import type { BaseEntity, PageQuery } from '@/api/types';
export interface OperLogQuery extends Omit<PageQuery, 'isAsc'> {
operIp?: string;
title?: string;
operName?: string;
userId?: string;
deptId?: string;
clientKey?: string;
deviceType?: string;
browser?: string;
os?: string;
businessType?: string;
status?: string;
orderByColumn?: string;
isAsc?: string;
export interface OperLogQuery extends PageQuery {
operIp: string;
title: string;
operName: string;
businessType: string;
status: string;
orderByColumn: string;
isAsc: string;
}
export interface OperLogVO extends BaseEntity {
operId: string | number;
tenantId?: string;
title?: string;
businessType?: number | string;
businessTypes?: number[];
method?: string;
requestMethod?: string;
operatorType?: number;
operName?: string;
userId?: string | number;
deptId?: string | number;
deptName?: string;
clientKey?: string;
deviceType?: string;
browser?: string;
os?: string;
operUrl?: string;
operIp?: string;
operLocation?: string;
operParam?: string;
jsonResult?: string;
status?: number | string;
errorMsg?: string;
operTime?: string;
costTime?: number;
tenantId: string;
title: string;
businessType: number;
businessTypes: number[] | undefined;
method: string;
requestMethod: string;
operatorType: number;
operName: string;
deptName: string;
operUrl: string;
operIp: string;
operLocation: string;
operParam: string;
jsonResult: string;
status: number;
errorMsg: string;
operTime: string;
costTime: number;
}
export interface OperLogForm {
operId: number | string | undefined;
tenantId: string | number | undefined;
title: string;
businessType: number;
businessTypes: number[] | undefined;
method: string;
requestMethod: string;
operatorType: number;
operName: string;
deptName: string;
operUrl: string;
operIp: string;
operLocation: string;
operParam: string;
jsonResult: string;
status: number;
errorMsg: string;
operTime: string;
costTime: number;
}
-244
View File
@@ -1,244 +0,0 @@
import { history } from '@umijs/max';
import { message, Modal } from 'antd';
import axios, { type AxiosError, type AxiosRequestConfig } from 'axios';
import { useAppStore } from '@/stores/appStore';
import { useTagsViewStore } from '@/stores/tagsViewStore';
import { getToken, removeToken } from '@/utils/auth';
import { decryptBase64, decryptWithAes, encryptBase64, encryptWithAes, generateAesKey } from '@/utils/crypto';
import { appEnv } from '@/utils/env';
import { decrypt, encrypt } from '@/utils/jsencrypt';
import { tansParams } from '@/utils/ruoyi';
const SUCCESS = 200;
const WARN = 601;
const SERVER_ERROR = 500;
const encryptHeader = 'encrypt-key';
const repeatSubmitStorageKey = 'sessionObj';
const repeatSubmitInterval = 500;
export interface RequestConfig<D = unknown> extends AxiosRequestConfig<D> {
headers?: AxiosRequestConfig<D>['headers'] & {
isToken?: false;
isEncrypt?: 'true' | 'false' | boolean;
repeatSubmit?: false;
};
}
export const isRelogin = { show: false };
type HandledRequestError = Error & { isHandled?: boolean };
function createHandledError(message: string) {
const error = new Error(message) as HandledRequestError;
error.isHandled = true;
return error;
}
export function isHandledRequestError(error: unknown) {
return Boolean((error as { isHandled?: boolean } | undefined)?.isHandled);
}
export function globalHeaders() {
return {
Authorization: `Bearer ${getToken() || ''}`,
clientid: appEnv.clientId
};
}
function showRequestError(content: string) {
message.error({ content, key: `request-error:${content}` });
}
function showReloginConfirm() {
if (isRelogin.show) return;
isRelogin.show = true;
Modal.confirm({
title: '系统提示',
content: '登录状态已过期,您可以继续留在该页面,或者重新登录',
okText: '重新登录',
cancelText: '取消',
onOk: () => {
isRelogin.show = false;
removeToken();
useTagsViewStore.getState().resetTags();
history.replace(
`/login?redirect=${encodeURIComponent(`${window.location.pathname || '/'}${window.location.search || ''}`)}`
);
},
onCancel: () => {
isRelogin.show = false;
}
});
}
function stableDataString(data: unknown) {
if (data instanceof FormData) return '';
if (typeof data === 'string') return data;
if (typeof data === 'undefined' || data === null) return '';
if (typeof data === 'object') return JSON.stringify(data);
return String(data);
}
function getSessionSubmitRecord() {
try {
const text = sessionStorage.getItem(repeatSubmitStorageKey);
return text ? (JSON.parse(text) as { url?: string; data?: string; time?: number }) : undefined;
} catch {
sessionStorage.removeItem(repeatSubmitStorageKey);
return undefined;
}
}
function setSessionSubmitRecord(record: { url?: string; data?: string; time: number }) {
sessionStorage.setItem(repeatSubmitStorageKey, JSON.stringify(record));
}
const service = axios.create({
baseURL: appEnv.baseApi,
timeout: 50000,
headers: {
'Content-Type': 'application/json;charset=utf-8',
clientid: appEnv.clientId
},
transitional: {
clarifyTimeoutError: true
}
});
service.interceptors.request.use(config => {
config.headers.set('Content-Language', useAppStore.getState().appLocale);
const isToken = config.headers.get('isToken') === false;
const isEncrypt = config.headers.get('isEncrypt') === 'true' || config.headers.get('isEncrypt') === true;
const isRepeatSubmitDisabled = config.headers.get('repeatSubmit') === false;
if (getToken() && !isToken) {
config.headers.set('Authorization', `Bearer ${getToken()}`);
}
if (config.method === 'get' && config.params) {
let url = `${config.url}?${tansParams(config.params)}`;
url = url.slice(0, -1);
config.params = {};
config.url = url;
}
if (!isRepeatSubmitDisabled && (config.method === 'post' || config.method === 'put')) {
const requestObj = {
url: config.url,
data: stableDataString(config.data),
time: Date.now()
};
const sessionObj = getSessionSubmitRecord();
if (
sessionObj &&
sessionObj.url === requestObj.url &&
sessionObj.data === requestObj.data &&
requestObj.time - (sessionObj.time || 0) < repeatSubmitInterval
) {
return Promise.reject(new Error('数据正在处理,请勿重复提交'));
}
setSessionSubmitRecord(requestObj);
}
if (appEnv.encryptEnabled && isEncrypt && (config.method === 'post' || config.method === 'put')) {
const aesKey = generateAesKey();
const encryptedKey = encrypt(encryptBase64(aesKey));
if (encryptedKey) {
config.headers.set(encryptHeader, encryptedKey);
}
const data = typeof config.data === 'object' ? JSON.stringify(config.data) : String(config.data ?? '');
config.data = encryptWithAes(data, aesKey);
}
if (config.data instanceof FormData) {
config.headers.delete('Content-Type');
}
config.headers.delete('isToken');
config.headers.delete('isEncrypt');
config.headers.delete('repeatSubmit');
return config;
});
function normalizeErrorMessage(message?: string) {
if (!message) return undefined;
if (message === 'Network Error') return '后端接口连接异常';
if (message.includes('timeout')) return '系统接口请求超时';
if (message.includes('Request failed with status code')) return `系统接口${message.slice(-3)}异常`;
return message;
}
async function parseResponseErrorData(data: unknown): Promise<string | undefined> {
if (!data) return undefined;
if (data instanceof Blob) return parseResponseErrorData(await data.text());
if (data instanceof ArrayBuffer) return parseResponseErrorData(new TextDecoder().decode(data));
if (typeof data === 'string') {
const text = data.trim();
if (!text) return undefined;
try {
return parseResponseErrorData(JSON.parse(text));
} catch {
return text;
}
}
if (typeof data === 'object') {
const payload = data as { msg?: string; message?: string };
return payload.msg || payload.message;
}
return undefined;
}
async function getErrorMessage(error: AxiosError) {
const responseMessage = await parseResponseErrorData(error.response?.data);
return responseMessage || normalizeErrorMessage(error.message) || '系统未知错误';
}
service.interceptors.response.use(
response => {
const keyStr = response.headers[encryptHeader];
if (appEnv.encryptEnabled && keyStr) {
const base64Str = decrypt(keyStr);
if (base64Str) {
const aesKey = decryptBase64(base64Str);
response.data = JSON.parse(decryptWithAes(response.data, aesKey));
}
}
if (response.request.responseType === 'blob' || response.request.responseType === 'arraybuffer') {
return response.data;
}
const code = response.data?.code || SUCCESS;
const msg = response.data?.msg || '系统未知错误';
if (code === 401) {
showReloginConfirm();
return Promise.reject(createHandledError('无效的会话,或者会话已过期,请重新登录。'));
}
if (code === SERVER_ERROR || code === WARN || code !== SUCCESS) {
showRequestError(msg);
return Promise.reject(createHandledError(msg));
}
return response.data;
},
async error => {
if (axios.isAxiosError(error) && error.response?.status === 401) {
showReloginConfirm();
return Promise.reject(createHandledError('无效的会话,或者会话已过期,请重新登录。'));
}
const msg = axios.isAxiosError(error)
? await getErrorMessage(error)
: normalizeErrorMessage((error as Error | undefined)?.message) || '系统未知错误';
showRequestError(msg);
return Promise.reject(createHandledError(msg));
}
);
export default function request<T = unknown, D = unknown>(config: RequestConfig<D>): Promise<T> {
return service.request<T, T, D>(config);
}
+55 -24
View File
@@ -1,49 +1,80 @@
import type { PageResult, R } from '@/api/types';
import request from '@/api/request';
import type { ClientForm, ClientQuery, ClientVO } from './types';
import request from '@/utils/request';
import { AxiosPromise } from 'axios';
import { ClientVO, ClientForm, ClientQuery } from '@/api/system/client/types';
export function listClient(query?: ClientQuery) {
return request<R<PageResult<ClientVO>>>({
/**
* 查询客户端管理列表
* @param query
* @returns {*}
*/
export const listClient = (query?: ClientQuery): AxiosPromise<ClientVO[]> => {
return request({
url: '/system/client/list',
method: 'get',
params: query
});
}
};
export function getClient(id: string | number) {
return request<R<ClientVO>>({
url: `/system/client/${id}`,
/**
* 查询客户端管理详细
* @param id
*/
export const getClient = (id: string | number): AxiosPromise<ClientVO> => {
return request({
url: '/system/client/' + id,
method: 'get'
});
}
};
export function addClient(data: ClientForm) {
return request<R>({
/**
* 新增客户端管理
* @param data
*/
export const addClient = (data: ClientForm) => {
return request({
url: '/system/client',
method: 'post',
data
data: data
});
}
};
export function updateClient(data: ClientForm) {
return request<R>({
/**
* 修改客户端管理
* @param data
*/
export const updateClient = (data: ClientForm) => {
return request({
url: '/system/client',
method: 'put',
data
data: data
});
}
};
export function delClient(id: string | number | Array<string | number>) {
return request<R>({
url: `/system/client/${id}`,
/**
* 删除客户端管理
* @param id
*/
export const delClient = (id: string | number | Array<string | number>) => {
return request({
url: '/system/client/' + id,
method: 'delete'
});
}
};
/**
* 状态修改
* @param clientId 客户端id
* @param status 状态
*/
export function changeStatus(clientId: string, status: string) {
return request<R>({
const data = {
clientId,
status
};
return request({
url: '/system/client/changeStatus',
method: 'put',
data: { clientId, status }
data: data
});
}
+112 -23
View File
@@ -1,46 +1,135 @@
import type { BaseEntity, PageQuery } from '@/api/types';
export interface ClientVO {
/**
* id
*/
id: string | number;
/**
* 客户端id
*/
clientId: string;
/**
* 客户端key
*/
clientKey: string;
/**
* 客户端秘钥
*/
clientSecret: string;
/**
* 授权类型
*/
grantTypeList: string[];
/**
* 设备类型
*/
deviceType: string;
/**
* token活跃超时时间
*/
activeTimeout: number;
/**
* token固定超时
*/
timeout: number;
/**
* 状态(0正常 1停用)
*/
status: string;
}
export interface ClientForm extends BaseEntity {
/**
* id
*/
id?: string | number;
/**
* 客户端id
*/
clientId?: string | number;
/**
* 客户端key
*/
clientKey?: string;
/**
* 客户端秘钥
*/
clientSecret?: string;
/**
* 授权类型
*/
grantTypeList?: string[];
/**
* 设备类型
*/
deviceType?: string;
accessPath?: string;
accessPathList?: string[];
ipWhitelist?: string;
ipWhitelistList?: string[];
/**
* token活跃超时时间
*/
activeTimeout?: number;
/**
* token固定超时
*/
timeout?: number;
/**
* 状态(0正常 1停用)
*/
status?: string;
}
export interface ClientQuery extends PageQuery {
/**
* 客户端id
*/
clientId?: string | number;
/**
* 客户端key
*/
clientKey?: string;
/**
* 客户端秘钥
*/
clientSecret?: string;
/**
* 授权类型
*/
grantType?: string;
/**
* 设备类型
*/
deviceType?: string;
accessPath?: string;
ipWhitelist?: string;
/**
* token活跃超时时间
*/
activeTimeout?: number;
/**
* token固定超时
*/
timeout?: number;
/**
* 状态(0正常 1停用)
*/
status?: string;
}
export interface ClientVO {
id: string | number;
clientId: string;
clientKey: string;
clientSecret: string;
grantTypeList?: string[];
deviceType?: string;
accessPath?: string;
accessPathList?: string[];
ipWhitelist?: string;
ipWhitelistList?: string[];
activeTimeout?: number;
timeout?: number;
status: string;
}
+29 -25
View File
@@ -1,47 +1,53 @@
import type { PageResult, R } from '@/api/types';
import request from '@/api/request';
import type { ConfigForm, ConfigQuery, ConfigVO } from './types';
import request from '@/utils/request';
import { ConfigForm, ConfigQuery, ConfigVO } from './types';
import { AxiosPromise } from 'axios';
export function listConfig(query: ConfigQuery) {
return request<R<PageResult<ConfigVO>>>({
// 查询参数列表
export function listConfig(query: ConfigQuery): AxiosPromise<ConfigVO[]> {
return request({
url: '/system/config/list',
method: 'get',
params: query
});
}
export function getConfig(configId: string | number) {
return request<R<ConfigVO>>({
url: `/system/config/${configId}`,
// 查询参数详细
export function getConfig(configId: string | number): AxiosPromise<ConfigVO> {
return request({
url: '/system/config/' + configId,
method: 'get'
});
}
export function getConfigKey(configKey: string) {
return request<R<string>>({
url: `/system/config/configKey/${configKey}`,
// 根据参数键名查询参数值
export function getConfigKey(configKey: string): AxiosPromise<string> {
return request({
url: '/system/config/configKey/' + configKey,
method: 'get'
});
}
// 新增参数配置
export function addConfig(data: ConfigForm) {
return request<R>({
return request({
url: '/system/config',
method: 'post',
data
data: data
});
}
// 修改参数配置
export function updateConfig(data: ConfigForm) {
return request<R>({
return request({
url: '/system/config',
method: 'put',
data
data: data
});
}
export function updateConfigByKey(key: string, value: unknown) {
return request<R>({
// 修改参数配置
export function updateConfigByKey(key: string, value: any) {
return request({
url: '/system/config/updateByKey',
method: 'put',
data: {
@@ -51,20 +57,18 @@ export function updateConfigByKey(key: string, value: unknown) {
});
}
// 删除参数配置
export function delConfig(configId: string | number | Array<string | number>) {
return request<R>({
url: `/system/config/${configId}`,
return request({
url: '/system/config/' + configId,
method: 'delete'
});
}
export function refreshConfigCache() {
return request<R>({
// 刷新参数缓存
export function refreshCache() {
return request({
url: '/system/config/refreshCache',
method: 'delete'
});
}
export function refreshCache() {
return refreshConfigCache();
}
+16 -17
View File
@@ -1,24 +1,23 @@
import type { BaseEntity, PageQuery } from '@/api/types';
export interface ConfigForm {
configId?: number | string;
configName?: string;
configKey?: string;
configValue?: string;
configType?: string;
remark?: string;
}
export interface ConfigQuery extends PageQuery {
configName?: string;
configKey?: string;
configType?: string;
}
export interface ConfigVO extends BaseEntity {
configId: number | string;
configName: string;
configKey: string;
configValue: string;
configType: string;
remark: string;
}
export interface ConfigForm {
configId: number | string | undefined;
configName: string;
configKey: string;
configValue: string;
configType: string;
remark: string;
}
export interface ConfigQuery extends PageQuery {
configName: string;
configKey: string;
configType: string;
}
+37 -30
View File
@@ -1,55 +1,62 @@
import type { R } from '@/api/types';
import request from '@/api/request';
import type { DeptForm, DeptQuery, DeptVO } from './types';
import request from '@/utils/request';
import { AxiosPromise } from 'axios';
import { DeptForm, DeptQuery, DeptVO } from './types';
export function listDept(query?: DeptQuery) {
return request<R<DeptVO[]>>({
// 查询部门列表
export const listDept = (query?: DeptQuery) => {
return request({
url: '/system/dept/list',
method: 'get',
params: query
});
}
};
export function optionSelect(deptIds: Array<number | string>) {
return request<R<DeptVO[]>>({
url: `/system/dept/optionselect?deptIds=${deptIds}`,
// 查询部门列表(排除节点)
export const listDeptExcludeChild = (deptId: string | number): AxiosPromise<DeptVO[]> => {
return request({
url: '/system/dept/list/exclude/' + deptId,
method: 'get'
});
}
};
export function listDeptExcludeChild(deptId: string | number) {
return request<R<DeptVO[]>>({
url: `/system/dept/list/exclude/${deptId}`,
// 查询部门详细
export const getDept = (deptId: string | number): AxiosPromise<DeptVO> => {
return request({
url: '/system/dept/' + deptId,
method: 'get'
});
}
};
export function getDept(deptId: string | number) {
return request<R<DeptVO>>({
url: `/system/dept/${deptId}`,
// 查询部门下拉树结构
export const treeselect = (): AxiosPromise<DeptVO[]> => {
return request({
url: '/system/dept/treeselect',
method: 'get'
});
}
};
export function addDept(data: DeptForm) {
return request<R>({
// 新增部门
export const addDept = (data: DeptForm) => {
return request({
url: '/system/dept',
method: 'post',
data
data: data
});
}
};
export function updateDept(data: DeptForm) {
return request<R>({
// 修改部门
export const updateDept = (data: DeptForm) => {
return request({
url: '/system/dept',
method: 'put',
data
data: data
});
}
};
export function delDept(deptId: number | string) {
return request<R>({
url: `/system/dept/${deptId}`,
// 删除部门
export const delDept = (deptId: number | string) => {
return request({
url: '/system/dept/' + deptId,
method: 'delete'
});
}
};
+32 -34
View File
@@ -1,5 +1,36 @@
import type { BaseEntity, PageQuery } from '@/api/types';
/**
* 部门查询参数
*/
export interface DeptQuery extends PageQuery {
deptName?: string;
deptCategory?: string;
status?: number;
}
/**
* 部门类型
*/
export interface DeptVO extends BaseEntity {
id: number | string;
parentName: string;
parentId: number | string;
children: DeptVO[];
deptId: number | string;
deptName: string;
deptCategory: string;
orderNum: number;
leader: string;
phone: string;
email: string;
status: string;
delFlag: string;
ancestors: string;
menuId: string | number;
}
/**
* 部门表单类型
*/
export interface DeptForm {
parentName?: string;
parentId?: number | string;
@@ -8,43 +39,10 @@ export interface DeptForm {
deptName?: string;
deptCategory?: string;
orderNum?: number;
leader?: string | number;
phone?: string;
email?: string;
status?: string;
delFlag?: string;
ancestors?: string;
}
export interface DeptQuery extends PageQuery {
deptName?: string;
deptCategory?: string;
status?: string;
}
export interface DeptTreeVO extends BaseEntity {
id: number | string;
label: string;
parentId: number | string;
weight: number;
children?: DeptTreeVO[];
disabled?: boolean;
}
export interface DeptVO extends BaseEntity {
id?: number | string;
parentName?: string;
parentId?: number | string;
children?: DeptVO[];
deptId: number | string;
deptName: string;
deptCategory?: string;
orderNum?: number;
leader?: string;
phone?: string;
email?: string;
status?: string;
delFlag?: string;
ancestors?: string;
menuId?: string | number;
}
+23 -18
View File
@@ -1,48 +1,53 @@
import type { PageResult, R } from '@/api/types';
import request from '@/api/request';
import type { DictData, DictDataForm, DictDataQuery } from './types';
export function getDicts(dictType: string) {
return request<R<DictData[]>>({
url: `/system/dict/data/type/${dictType}`,
import request from '@/utils/request';
import { AxiosPromise } from 'axios';
import { DictDataForm, DictDataQuery, DictDataVO } from './types';
// 根据字典类型查询字典数据信息
export function getDicts(dictType: string): AxiosPromise<DictDataVO[]> {
return request({
url: '/system/dict/data/type/' + dictType,
method: 'get'
});
}
export function listData(query: DictDataQuery) {
return request<R<PageResult<DictData>>>({
// 查询字典数据列表
export function listData(query: DictDataQuery): AxiosPromise<DictDataVO[]> {
return request({
url: '/system/dict/data/list',
method: 'get',
params: query
});
}
export function getData(dictCode: string | number) {
return request<R<DictData>>({
url: `/system/dict/data/${dictCode}`,
// 查询字典数据详细
export function getData(dictCode: string | number): AxiosPromise<DictDataVO> {
return request({
url: '/system/dict/data/' + dictCode,
method: 'get'
});
}
// 新增字典数据
export function addData(data: DictDataForm) {
return request<R>({
return request({
url: '/system/dict/data',
method: 'post',
data
data: data
});
}
// 修改字典数据
export function updateData(data: DictDataForm) {
return request<R>({
return request({
url: '/system/dict/data',
method: 'put',
data
data: data
});
}
// 删除字典数据
export function delData(dictCode: string | number | Array<string | number>) {
return request<R>({
url: `/system/dict/data/${dictCode}`,
return request({
url: '/system/dict/data/' + dictCode,
method: 'delete'
});
}
+19 -25
View File
@@ -1,32 +1,26 @@
import type { BaseEntity, PageQuery } from '@/api/types';
export interface DictData extends BaseEntity {
dictCode: string | number;
dictSort: number;
dictLabel: string;
dictValue: string;
export interface DictDataQuery extends PageQuery {
dictName: string;
dictType: string;
cssClass?: string;
listClass?: string;
isDefault?: string;
status: string;
dictLabel: string;
}
export type DictDataVO = DictData;
export interface DictDataVO extends BaseEntity {
dictCode: string;
dictLabel: string;
dictValue: string;
cssClass: string;
listClass: ElTagType;
dictSort: number;
remark: string;
}
export interface DictDataForm {
dictType?: string;
dictCode?: string | number;
dictLabel?: string;
dictValue?: string;
cssClass?: string;
listClass?: string;
dictSort?: number;
remark?: string;
}
export interface DictDataQuery extends PageQuery {
dictName?: string;
dictType?: string;
dictLabel?: string;
dictCode: string | undefined;
dictLabel: string;
dictValue: string;
cssClass: string;
listClass: ElTagType;
dictSort: number;
remark: string;
}
+24 -17
View File
@@ -1,54 +1,61 @@
import type { PageResult, R } from '@/api/types';
import request from '@/api/request';
import type { DictTypeForm, DictTypeQuery, DictTypeVO } from './types';
import request from '@/utils/request';
import { DictTypeForm, DictTypeVO, DictTypeQuery } from './types';
import { AxiosPromise } from 'axios';
export function listType(query: DictTypeQuery) {
return request<R<PageResult<DictTypeVO>>>({
// 查询字典类型列表
export function listType(query: DictTypeQuery): AxiosPromise<DictTypeVO[]> {
return request({
url: '/system/dict/type/list',
method: 'get',
params: query
});
}
export function getType(dictId: number | string) {
return request<R<DictTypeVO>>({
url: `/system/dict/type/${dictId}`,
// 查询字典类型详细
export function getType(dictId: number | string): AxiosPromise<DictTypeVO> {
return request({
url: '/system/dict/type/' + dictId,
method: 'get'
});
}
// 新增字典类型
export function addType(data: DictTypeForm) {
return request<R>({
return request({
url: '/system/dict/type',
method: 'post',
data
data: data
});
}
// 修改字典类型
export function updateType(data: DictTypeForm) {
return request<R>({
return request({
url: '/system/dict/type',
method: 'put',
data
data: data
});
}
// 删除字典类型
export function delType(dictId: string | number | Array<string | number>) {
return request<R>({
url: `/system/dict/type/${dictId}`,
return request({
url: '/system/dict/type/' + dictId,
method: 'delete'
});
}
// 刷新字典缓存
export function refreshCache() {
return request<R>({
return request({
url: '/system/dict/type/refreshCache',
method: 'delete'
});
}
export function optionselect() {
return request<R<DictTypeVO[]>>({
// 获取字典选择框列表
export function optionselect(): AxiosPromise<DictTypeVO[]> {
return request({
url: '/system/dict/type/optionselect',
method: 'get'
});
+13 -14
View File
@@ -1,19 +1,18 @@
import type { BaseEntity, PageQuery } from '@/api/types';
export interface DictTypeForm {
dictId?: number | string;
dictName?: string;
dictType?: string;
remark?: string;
}
export interface DictTypeQuery extends PageQuery {
dictName?: string;
dictType?: string;
}
export interface DictTypeVO extends BaseEntity {
dictId: number | string;
dictName: string;
dictType: string;
remark: string;
}
export interface DictTypeForm {
dictId: number | string | undefined;
dictName: string;
dictType: string;
remark: string;
}
export interface DictTypeQuery extends PageQuery {
dictName: string;
dictType: string;
}
+44 -37
View File
@@ -1,63 +1,70 @@
import type { RoleMenuTree } from '@/api/system/role/types';
import type { R } from '@/api/types';
import request from '@/api/request';
import type { MenuForm, MenuQuery, MenuTreeOption, MenuVO } from './types';
import request from '@/utils/request';
import { AxiosPromise } from 'axios';
import { MenuQuery, MenuVO, MenuForm, MenuTreeOption, RoleMenuTree } from './types';
export function listMenu(query?: MenuQuery) {
return request<R<MenuVO[]>>({
// 查询菜单列表
export const listMenu = (query?: MenuQuery): AxiosPromise<MenuVO[]> => {
return request({
url: '/system/menu/list',
method: 'get',
params: query
});
}
};
export function getMenu(menuId: string | number) {
return request<R<MenuVO>>({
url: `/system/menu/${menuId}`,
// 查询菜单详细
export const getMenu = (menuId: string | number): AxiosPromise<MenuVO> => {
return request({
url: '/system/menu/' + menuId,
method: 'get'
});
}
};
export function treeselect() {
return request<R<MenuTreeOption[]>>({
// 查询菜单下拉树结构
export const treeselect = (): AxiosPromise<MenuTreeOption[]> => {
return request({
url: '/system/menu/treeselect',
method: 'get'
});
}
};
export function roleMenuTreeselect(roleId: string | number) {
return request<R<RoleMenuTree>>({
url: `/system/menu/roleMenuTreeselect/${roleId}`,
// 根据角色ID查询菜单下拉树结构
export const roleMenuTreeselect = (roleId: string | number): AxiosPromise<RoleMenuTree> => {
return request({
url: '/system/menu/roleMenuTreeselect/' + roleId,
method: 'get'
});
}
};
export function addMenu(data: MenuForm) {
return request<R>({
// 根据角色ID查询菜单下拉树结构
export const tenantPackageMenuTreeselect = (packageId: string | number): AxiosPromise<RoleMenuTree> => {
return request({
url: '/system/menu/tenantPackageMenuTreeselect/' + packageId,
method: 'get'
});
};
// 新增菜单
export const addMenu = (data: MenuForm) => {
return request({
url: '/system/menu',
method: 'post',
data
data: data
});
}
};
export function updateMenu(data: MenuForm) {
return request<R>({
// 修改菜单
export const updateMenu = (data: MenuForm) => {
return request({
url: '/system/menu',
method: 'put',
data
data: data
});
}
};
export function delMenu(menuId: string | number) {
return request<R>({
url: `/system/menu/${menuId}`,
// 删除菜单
export const delMenu = (menuId: string | number) => {
return request({
url: '/system/menu/' + menuId,
method: 'delete'
});
}
export function cascadeDelMenu(menuIds: Array<string | number>) {
return request<R>({
url: `/system/menu/cascade/${menuIds}`,
method: 'delete'
});
}
};
+45 -39
View File
@@ -1,51 +1,57 @@
import type { BaseEntity } from '@/api/types';
import { MenuTypeEnum } from '@/enums/MenuTypeEnum';
export interface MenuForm {
parentName?: string;
parentId?: string | number;
children?: MenuForm[];
menuId?: string | number;
menuName?: string;
orderNum?: number;
path?: string;
component?: string;
queryParam?: string;
isFrame?: string;
isCache?: string;
menuType?: 'M' | 'C' | 'F' | string;
visible?: string;
status?: string;
icon?: string | null;
activeMenu?: string;
ext?: string;
remark?: string;
query?: string;
perms?: string;
/**
* 菜单树形结构类型
*/
export interface MenuTreeOption {
id: string | number;
label: string;
parentId: string | number;
weight: number;
children?: MenuTreeOption[];
}
export interface RoleMenuTree {
menus: MenuTreeOption[];
checkedKeys: string[];
}
/**
* 菜单查询参数类型
*/
export interface MenuQuery {
keywords?: string;
menuName?: string;
status?: string;
}
export interface MenuTreeOption {
id: string | number;
label: string;
/**
* 菜单视图对象类型
*/
export interface MenuVO extends BaseEntity {
parentName: string;
parentId: string | number;
weight: number;
menuType?: 'M' | 'C' | 'F' | string;
visible?: string;
status?: string;
disabled?: boolean;
children?: MenuTreeOption[];
children: MenuVO[];
menuId: string | number;
menuName: string;
orderNum: number;
path: string;
component: string;
queryParam: string;
isFrame: string;
isCache: string;
menuType: MenuTypeEnum;
visible: string;
status: string;
icon: string;
remark: string;
}
export interface MenuVO extends BaseEntity {
export interface MenuForm {
parentName?: string;
parentId: string | number;
children?: MenuVO[];
menuId: string | number;
parentId?: string | number;
children?: MenuForm[];
menuId?: string | number;
menuName: string;
orderNum: number;
path: string;
@@ -53,11 +59,11 @@ export interface MenuVO extends BaseEntity {
queryParam?: string;
isFrame?: string;
isCache?: string;
menuType: 'M' | 'C' | 'F' | string;
menuType?: MenuTypeEnum;
visible?: string;
status?: string;
icon?: string | null;
activeMenu?: string;
ext?: string;
icon?: string;
remark?: string;
query?: string;
perms?: string;
}
-10
View File
@@ -1,10 +0,0 @@
import type { R } from '@/api/types';
import request from '@/api/request';
import type { MessageBoxVO } from './types';
export function getMessageBox() {
return request<R<MessageBoxVO>>({
url: '/resource/message/box',
method: 'get'
});
}
-19
View File
@@ -1,19 +0,0 @@
import type { BaseEntity } from '@/api/types';
export interface MessageVO extends BaseEntity {
messageId: number | string;
category: string;
type: string;
source: string;
title: string;
message: string;
content?: string;
data?: Record<string, unknown> | null;
path?: string;
}
export interface MessageBoxVO {
systemList: MessageVO[];
noticeList: MessageVO[];
workflowList: MessageVO[];
}
+19 -15
View File
@@ -1,41 +1,45 @@
import type { PageResult, R } from '@/api/types';
import request from '@/api/request';
import type { NoticeForm, NoticeQuery, NoticeVO } from './types';
export function listNotice(query: NoticeQuery) {
return request<R<PageResult<NoticeVO>>>({
import request from '@/utils/request';
import { NoticeForm, NoticeQuery, NoticeVO } from './types';
import { AxiosPromise } from 'axios';
// 查询公告列表
export function listNotice(query: NoticeQuery): AxiosPromise<NoticeVO[]> {
return request({
url: '/system/notice/list',
method: 'get',
params: query
});
}
export function getNotice(noticeId: string | number) {
return request<R<NoticeVO>>({
url: `/system/notice/${noticeId}`,
// 查询公告详细
export function getNotice(noticeId: string | number): AxiosPromise<NoticeVO> {
return request({
url: '/system/notice/' + noticeId,
method: 'get'
});
}
// 新增公告
export function addNotice(data: NoticeForm) {
return request<R>({
return request({
url: '/system/notice',
method: 'post',
data
data: data
});
}
// 修改公告
export function updateNotice(data: NoticeForm) {
return request<R>({
return request({
url: '/system/notice',
method: 'put',
data
data: data
});
}
// 删除公告
export function delNotice(noticeId: string | number | Array<string | number>) {
return request<R>({
url: `/system/notice/${noticeId}`,
return request({
url: '/system/notice/' + noticeId,
method: 'delete'
});
}
+20 -21
View File
@@ -1,27 +1,26 @@
import type { BaseEntity, PageQuery } from '@/api/types';
export interface NoticeForm {
noticeId?: number | string;
noticeTitle?: string;
noticeType?: string;
noticeContent?: string;
status?: string;
remark?: string;
createByName?: string;
}
export interface NoticeQuery extends PageQuery {
noticeTitle?: string;
createByName?: string;
status?: string;
noticeType?: string;
}
export interface NoticeVO extends BaseEntity {
noticeId: number | string;
noticeId: number;
noticeTitle: string;
noticeType: string;
noticeContent: string;
status: string;
createByName?: string;
remark: string;
createByName: string;
}
export interface NoticeQuery extends PageQuery {
noticeTitle: string;
createByName: string;
status: string;
noticeType: string;
}
export interface NoticeForm {
noticeId: number | string | undefined;
noticeTitle: string;
noticeType: string;
noticeContent: string;
status: string;
remark: string;
createByName: string;
}
+13 -30
View File
@@ -1,45 +1,28 @@
import type { PageResult, R } from '@/api/types';
import request from '@/api/request';
import type { OssQuery, OssUploadResult, OssVO } from './types';
import request from '@/utils/request';
import { OssQuery, OssVO } from './types';
import { AxiosPromise } from 'axios';
export function listOss(query: OssQuery) {
return request<R<PageResult<OssVO>>>({
// 查询OSS对象存储列表
export function listOss(query: OssQuery): AxiosPromise<OssVO[]> {
return request({
url: '/resource/oss/list',
method: 'get',
params: query
});
}
export function listOssByIds(ossId: string | number) {
return request<R<OssVO[]>>({
url: `/resource/oss/listByIds/${ossId}`,
// 查询OSS对象基于id串
export function listByIds(ossId: string | number): AxiosPromise<OssVO[]> {
return request({
url: '/resource/oss/listByIds/' + ossId,
method: 'get'
});
}
export function listByIds(ossId: string | number) {
return listOssByIds(ossId);
}
export function uploadOss(data: FormData) {
return request<R<OssUploadResult>>({
url: '/resource/oss/upload',
method: 'post',
data
});
}
// 删除OSS对象存储
export function delOss(ossId: string | number | Array<string | number>) {
return request<R>({
url: `/resource/oss/${ossId}`,
return request({
url: '/resource/oss/' + ossId,
method: 'delete'
});
}
export function downloadOss(ossId: string | number) {
return request<Blob>({
url: `/resource/oss/download/${ossId}`,
method: 'get',
responseType: 'blob'
});
}
+15 -20
View File
@@ -1,27 +1,22 @@
import type { BaseEntity, PageQuery } from '@/api/types';
export interface OssQuery extends Omit<PageQuery, 'isAsc'> {
fileName?: string;
originalName?: string;
fileSuffix?: string;
createTime?: string;
service?: string;
orderByColumn?: string;
isAsc?: string;
}
export interface OssUploadResult {
url?: string;
fileName?: string;
ossId?: string | number;
}
export interface OssVO extends BaseEntity {
ossId: string | number;
fileName: string;
originalName: string;
fileSuffix: string;
url: string;
createByName?: string;
service?: string;
createByName: string;
service: string;
}
export interface OssQuery extends PageQuery {
fileName: string;
originalName: string;
fileSuffix: string;
createTime: string;
service: string;
orderByColumn: string;
isAsc: string;
}
export interface OssForm {
file: undefined | string;
}
+27 -16
View File
@@ -1,49 +1,60 @@
import type { PageResult, R } from '@/api/types';
import request from '@/api/request';
import type { OssConfigForm, OssConfigQuery, OssConfigVO } from './types';
import request from '@/utils/request';
import { OssConfigForm, OssConfigQuery, OssConfigVO } from './types';
import { AxiosPromise } from 'axios';
export function listOssConfig(query: OssConfigQuery) {
return request<R<PageResult<OssConfigVO>>>({
// 查询对象存储配置列表
export function listOssConfig(query: OssConfigQuery): AxiosPromise<OssConfigVO[]> {
return request({
url: '/resource/oss/config/list',
method: 'get',
params: query
});
}
export function getOssConfig(ossConfigId: string | number) {
return request<R<OssConfigVO>>({
url: `/resource/oss/config/${ossConfigId}`,
// 查询对象存储配置详细
export function getOssConfig(ossConfigId: string | number): AxiosPromise<OssConfigVO> {
return request({
url: '/resource/oss/config/' + ossConfigId,
method: 'get'
});
}
// 新增对象存储配置
export function addOssConfig(data: OssConfigForm) {
return request<R>({
return request({
url: '/resource/oss/config',
method: 'post',
data
data: data
});
}
// 修改对象存储配置
export function updateOssConfig(data: OssConfigForm) {
return request<R>({
return request({
url: '/resource/oss/config',
method: 'put',
data
data: data
});
}
// 删除对象存储配置
export function delOssConfig(ossConfigId: string | number | Array<string | number>) {
return request<R>({
url: `/resource/oss/config/${ossConfigId}`,
return request({
url: '/resource/oss/config/' + ossConfigId,
method: 'delete'
});
}
// 对象存储状态修改
export function changeOssConfigStatus(ossConfigId: string | number, status: string, configKey: string) {
return request<R>({
const data = {
ossConfigId,
status,
configKey
};
return request({
url: '/resource/oss/config/changeStatus',
method: 'put',
data: { ossConfigId, status, configKey }
data: data
});
}
+27 -28
View File
@@ -1,39 +1,38 @@
import type { BaseEntity, PageQuery } from '@/api/types';
export interface OssConfigForm {
ossConfigId?: string | number;
configKey?: string;
accessKey?: string;
secretKey?: string;
bucketName?: string;
prefix?: string;
endpoint?: string;
domainUrl?: string;
isHttps?: string;
accessPolicy?: string;
region?: string;
status?: string;
remark?: string;
}
export interface OssConfigQuery extends PageQuery {
configKey?: string;
bucketName?: string;
status?: string;
}
export interface OssConfigVO extends BaseEntity {
ossConfigId: number | string;
configKey: string;
accessKey: string;
secretKey: string;
bucketName: string;
prefix?: string;
prefix: string;
endpoint: string;
domainUrl?: string;
domain: string;
isHttps: string;
region?: string;
region: string;
status: string;
ext1?: string;
ext1: string;
remark: string;
accessPolicy: string;
}
export interface OssConfigQuery extends PageQuery {
configKey: string;
bucketName: string;
status: string;
}
export interface OssConfigForm {
ossConfigId: string | number | undefined;
configKey: string;
accessKey: string;
secretKey: string;
bucketName: string;
prefix: string;
endpoint: string;
domain: string;
isHttps: string;
accessPolicy: string;
region: string;
status: string;
remark: string;
}
+25 -31
View File
@@ -1,64 +1,58 @@
import type { DeptTreeVO } from '@/api/system/dept/types';
import type { PageResult, R } from '@/api/types';
import request from '@/api/request';
import type { PostForm, PostQuery, PostVO } from './types';
import request from '@/utils/request';
import { PostForm, PostQuery, PostVO } from './types';
import { AxiosPromise } from 'axios';
export function listPost(query: PostQuery) {
return request<R<PageResult<PostVO>>>({
// 查询岗位列表
export function listPost(query: PostQuery): AxiosPromise<PostVO[]> {
return request({
url: '/system/post/list',
method: 'get',
params: query
});
}
export function getPost(postId: string | number) {
return request<R<PostVO>>({
url: `/system/post/${postId}`,
// 查询岗位详细
export function getPost(postId: string | number): AxiosPromise<PostVO> {
return request({
url: '/system/post/' + postId,
method: 'get'
});
}
export function optionSelect(deptId?: number | string, postIds?: Array<number | string>) {
return request<R<PostVO[]>>({
// 获取岗位选择框列表
export function optionselect(deptId?: number | string, postIds?: (number | string)[]): AxiosPromise<PostVO[]> {
return request({
url: '/system/post/optionselect',
method: 'get',
params: {
postIds,
deptId
postIds: postIds,
deptId: deptId
}
});
}
// 新增岗位
export function addPost(data: PostForm) {
return request<R>({
return request({
url: '/system/post',
method: 'post',
data
data: data
});
}
// 修改岗位
export function updatePost(data: PostForm) {
return request<R>({
return request({
url: '/system/post',
method: 'put',
data
data: data
});
}
export function delPost(postId: string | number | Array<string | number>) {
return request<R>({
url: `/system/post/${postId}`,
// 删除岗位
export function delPost(postId: string | number | (string | number)[]) {
return request({
url: '/system/post/' + postId,
method: 'delete'
});
}
export function postDeptTreeSelect() {
return request<R<DeptTreeVO[]>>({
url: '/system/post/deptTree',
method: 'get'
});
}
export function deptTreeSelect() {
return postDeptTreeSelect();
}
+21 -22
View File
@@ -1,25 +1,3 @@
import type { BaseEntity, PageQuery } from '@/api/types';
export interface PostForm {
postId?: number | string;
deptId?: number | string;
postCode?: string;
postName?: string;
postCategory?: string;
postSort?: number;
status?: string;
remark?: string;
}
export interface PostQuery extends PageQuery {
deptId?: number | string;
belongDeptId?: number | string;
postCode?: string;
postName?: string;
postCategory?: string;
status?: string;
}
export interface PostVO extends BaseEntity {
postId: number | string;
deptId: number | string;
@@ -29,4 +7,25 @@ export interface PostVO extends BaseEntity {
deptName: string;
postSort: number;
status: string;
remark: string;
}
export interface PostForm {
postId: number | string | undefined;
deptId: number | string | undefined;
postCode: string;
postName: string;
postCategory: string;
postSort: number;
status: string;
remark: string;
}
export interface PostQuery extends PageQuery {
deptId: number | string;
belongDeptId: number | string;
postCode: string;
postName: string;
postCategory: string;
status: string;
}
+105 -60
View File
@@ -1,115 +1,160 @@
import type { UserQuery, UserVO } from '@/api/system/user/types';
import type { PageResult, R } from '@/api/types';
import request from '@/api/request';
import type { RoleDeptTree, RoleForm, RoleQuery, RoleVO } from './types';
import { UserVO } from '@/api/system/user/types';
import { UserQuery } from '@/api/system/user/types';
import { AxiosPromise } from 'axios';
import { RoleQuery, RoleVO, RoleDeptTree } from './types';
import request from '@/utils/request';
export function listRole(query: RoleQuery) {
return request<R<PageResult<RoleVO>>>({
export const listRole = (query: RoleQuery): AxiosPromise<RoleVO[]> => {
return request({
url: '/system/role/list',
method: 'get',
params: query
});
}
};
export function optionSelect(roleIds: Array<number | string>) {
return request<R<RoleVO[]>>({
url: `/system/role/optionselect?roleIds=${roleIds}`,
/**
* 通过roleIds查询角色
* @param roleIds
*/
export const optionSelect = (roleIds: (number | string)[]): AxiosPromise<RoleVO[]> => {
return request({
url: '/system/role/optionselect?roleIds=' + roleIds,
method: 'get'
});
}
};
export function getRole(roleId: string | number) {
return request<R<RoleVO>>({
url: `/system/role/${roleId}`,
/**
* 查询角色详细
*/
export const getRole = (roleId: string | number): AxiosPromise<RoleVO> => {
return request({
url: '/system/role/' + roleId,
method: 'get'
});
}
};
export function addRole(data: RoleForm) {
return request<R>({
/**
* 新增角色
*/
export const addRole = (data: any) => {
return request({
url: '/system/role',
method: 'post',
data
data: data
});
}
};
export function updateRole(data: RoleForm) {
return request<R>({
/**
* 修改角色
* @param data
*/
export const updateRole = (data: any) => {
return request({
url: '/system/role',
method: 'put',
data
data: data
});
}
};
export function updateRolePermission(data: RoleForm) {
return request<R>({
url: '/system/role/permission',
/**
* 角色数据权限
*/
export const dataScope = (data: any) => {
return request({
url: '/system/role/dataScope',
method: 'put',
data
data: data
});
}
};
export function changeRoleStatus(roleId: string | number, status: string) {
return request<R>({
/**
* 角色状态修改
*/
export const changeRoleStatus = (roleId: string | number, status: string) => {
const data = {
roleId,
status
};
return request({
url: '/system/role/changeStatus',
method: 'put',
data: {
roleId,
status
}
data: data
});
}
};
export function delRole(roleId: Array<string | number> | string | number) {
return request<R>({
url: `/system/role/${roleId}`,
/**
* 删除角色
*/
export const delRole = (roleId: Array<string | number> | string | number) => {
return request({
url: '/system/role/' + roleId,
method: 'delete'
});
}
};
export function allocatedUserList(query: UserQuery) {
return request<R<PageResult<UserVO>>>({
/**
* 查询角色已授权用户列表
*/
export const allocatedUserList = (query: UserQuery): AxiosPromise<UserVO[]> => {
return request({
url: '/system/role/authUser/allocatedList',
method: 'get',
params: query
});
}
};
export function unallocatedUserList(query: UserQuery) {
return request<R<PageResult<UserVO>>>({
/**
* 查询角色未授权用户列表
*/
export const unallocatedUserList = (query: UserQuery): AxiosPromise<UserVO[]> => {
return request({
url: '/system/role/authUser/unallocatedList',
method: 'get',
params: query
});
}
};
export function authUserCancel(data: { roleId: string | number; userId: string | number }) {
return request<R>({
/**
* 取消用户授权角色
*/
export const authUserCancel = (data: any) => {
return request({
url: '/system/role/authUser/cancel',
method: 'put',
data
data: data
});
}
};
export function authUserCancelAll(data: { roleId: string | number; userIds: string }) {
return request<R>({
/**
* 批量取消用户授权角色
*/
export const authUserCancelAll = (data: any) => {
return request({
url: '/system/role/authUser/cancelAll',
method: 'put',
params: data
});
}
};
export function authUserSelectAll(data: { roleId: string | number; userIds: string }) {
return request<R>({
/**
* 授权用户选择
*/
export const authUserSelectAll = (data: any) => {
return request({
url: '/system/role/authUser/selectAll',
method: 'put',
params: data
});
}
export function deptTreeSelect(roleId: string | number) {
return request<R<RoleDeptTree>>({
url: `/system/role/deptTree/${roleId}`,
};
// 根据角色ID查询部门树结构
export const deptTreeSelect = (roleId: string | number): AxiosPromise<RoleDeptTree> => {
return request({
url: '/system/role/deptTree/' + roleId,
method: 'get'
});
}
};
export default {
optionSelect,
listRole
};
+37 -33
View File
@@ -1,35 +1,17 @@
import type { DeptTreeVO } from '@/api/system/dept/types';
import type { MenuTreeOption } from '@/api/system/menu/types';
import type { BaseEntity, PageQuery } from '@/api/types';
/**
* 菜单树形结构类型
*/
export interface DeptTreeOption {
id: string;
label: string;
parentId: string;
weight: number;
children?: DeptTreeOption[];
}
export interface RoleDeptTree {
checkedKeys: Array<string | number>;
depts: DeptTreeVO[];
}
export interface RoleForm {
roleId?: string | number;
roleName?: string;
roleKey?: string;
roleSort?: number;
status?: string;
menuCheckStrictly?: boolean;
deptCheckStrictly?: boolean;
remark?: string;
dataScope?: string;
menuIds?: Array<string | number>;
deptIds?: Array<string | number>;
}
export interface RoleMenuTree {
menus: MenuTreeOption[];
checkedKeys: Array<string | number>;
}
export interface RoleQuery extends PageQuery {
roleName?: string;
roleKey?: string;
status?: string;
checkedKeys: string[];
depts: DeptTreeOption[];
}
export interface RoleVO extends BaseEntity {
@@ -38,11 +20,33 @@ export interface RoleVO extends BaseEntity {
roleKey: string;
roleSort: number;
dataScope: string;
menuCheckStrictly?: boolean;
deptCheckStrictly?: boolean;
menuCheckStrictly: boolean;
deptCheckStrictly: boolean;
status: string;
delFlag: string;
remark?: any;
flag: boolean;
admin: boolean;
menuIds?: Array<string | number>;
deptIds?: Array<string | number>;
admin: boolean;
}
export interface RoleQuery extends PageQuery {
roleName: string;
roleKey: string;
status: string;
}
export interface RoleForm {
roleName: string;
roleKey: string;
roleSort: number;
status: string;
menuCheckStrictly: boolean;
deptCheckStrictly: boolean;
remark: string;
dataScope?: string;
roleId: string | undefined;
menuIds: Array<string | number>;
deptIds: Array<string | number>;
}
+15 -11
View File
@@ -1,23 +1,27 @@
import type { R } from '@/api/types';
import request from '@/api/request';
import type { SocialAuthVO } from './types';
import request from '@/utils/request';
export function authRouterUrl(source: string) {
return request<R<string>>({
url: `/auth/binding/${source}`,
method: 'get'
// 绑定账号
export function authBinding(source: string, tenantId: string) {
return request({
url: '/auth/binding/' + source,
method: 'get',
params: {
tenantId: tenantId,
domain: window.location.host
}
});
}
// 解绑账号
export function authUnlock(authId: string) {
return request<R>({
url: `/auth/unlock/${authId}`,
return request({
url: '/auth/unlock/' + authId,
method: 'delete'
});
}
//获取授权列表
export function getAuthList() {
return request<R<SocialAuthVO[]>>({
return request({
url: '/system/social/list',
method: 'get'
});
-7
View File
@@ -1,7 +0,0 @@
export interface SocialAuthVO {
id: string;
source?: string;
avatar?: string;
userName?: string;
createTime?: string;
}
+93
View File
@@ -0,0 +1,93 @@
import request from '@/utils/request';
import { TenantForm, TenantQuery, TenantVO } from './types';
import { AxiosPromise } from 'axios';
// 查询租户列表
export function listTenant(query: TenantQuery): AxiosPromise<TenantVO[]> {
return request({
url: '/system/tenant/list',
method: 'get',
params: query
});
}
// 查询租户详细
export function getTenant(id: string | number): AxiosPromise<TenantVO> {
return request({
url: '/system/tenant/' + id,
method: 'get'
});
}
// 新增租户
export function addTenant(data: TenantForm) {
return request({
url: '/system/tenant',
method: 'post',
headers: {
isEncrypt: true,
repeatSubmit: false
},
data: data
});
}
// 修改租户
export function updateTenant(data: TenantForm) {
return request({
url: '/system/tenant',
method: 'put',
data: data
});
}
// 租户状态修改
export function changeTenantStatus(id: string | number, tenantId: string | number, status: string) {
const data = {
id,
tenantId,
status
};
return request({
url: '/system/tenant/changeStatus',
method: 'put',
data: data
});
}
// 删除租户
export function delTenant(id: string | number | Array<string | number>) {
return request({
url: '/system/tenant/' + id,
method: 'delete'
});
}
// 动态切换租户
export function dynamicTenant(tenantId: string | number) {
return request({
url: '/system/tenant/dynamic/' + tenantId,
method: 'get'
});
}
// 清除动态租户
export function dynamicClear() {
return request({
url: '/system/tenant/dynamic/clear',
method: 'get'
});
}
// 同步租户套餐
export function syncTenantPackage(tenantId: string | number, packageId: string | number) {
const data = {
tenantId,
packageId
};
return request({
url: '/system/tenant/syncTenantPackage',
method: 'get',
params: data
});
}
+46
View File
@@ -0,0 +1,46 @@
export interface TenantVO extends BaseEntity {
id: number | string;
tenantId: number | string;
username: string;
contactUserName: string;
contactPhone: string;
companyName: string;
licenseNumber: string;
address: string;
domain: string;
intro: string;
remark: string;
packageId: string | number;
expireTime: string;
accountCount: number;
status: string;
}
export interface TenantQuery extends PageQuery {
tenantId: string | number;
contactUserName: string;
contactPhone: string;
companyName: string;
}
export interface TenantForm {
id: number | string | undefined;
tenantId: number | string | undefined;
username: string;
password: string;
contactUserName: string;
contactPhone: string;
companyName: string;
licenseNumber: string;
domain: string;
address: string;
intro: string;
remark: string;
packageId: string | number;
expireTime: string;
accountCount: number;
status: string;
}
+67
View File
@@ -0,0 +1,67 @@
import request from '@/utils/request';
import { TenantPkgForm, TenantPkgQuery, TenantPkgVO } from './types';
import { AxiosPromise } from 'axios';
// 查询租户套餐列表
export function listTenantPackage(query?: TenantPkgQuery): AxiosPromise<TenantPkgVO[]> {
return request({
url: '/system/tenant/package/list',
method: 'get',
params: query
});
}
// 查询租户套餐下拉选列表
export function selectTenantPackage(): AxiosPromise<TenantPkgVO[]> {
return request({
url: '/system/tenant/package/selectList',
method: 'get'
});
}
// 查询租户套餐详细
export function getTenantPackage(packageId: string | number): AxiosPromise<TenantPkgVO> {
return request({
url: '/system/tenant/package/' + packageId,
method: 'get'
});
}
// 新增租户套餐
export function addTenantPackage(data: TenantPkgForm) {
return request({
url: '/system/tenant/package',
method: 'post',
data: data
});
}
// 修改租户套餐
export function updateTenantPackage(data: TenantPkgForm) {
return request({
url: '/system/tenant/package',
method: 'put',
data: data
});
}
// 租户套餐状态修改
export function changePackageStatus(packageId: number | string, status: string) {
const data = {
packageId,
status
};
return request({
url: '/system/tenant/package/changeStatus',
method: 'put',
data: data
});
}
// 删除租户套餐
export function delTenantPackage(packageId: string | number | Array<string | number>) {
return request({
url: '/system/tenant/package/' + packageId,
method: 'delete'
});
}
+20
View File
@@ -0,0 +1,20 @@
export interface TenantPkgVO extends BaseEntity {
packageId: string | number;
packageName: string;
menuIds: string;
remark: string;
menuCheckStrictly: boolean;
status: string;
}
export interface TenantPkgQuery extends PageQuery {
packageName: string;
}
export interface TenantPkgForm {
packageId: string | number | undefined;
packageName: string;
menuIds: string;
remark: string;
menuCheckStrictly: boolean;
}
+162 -87
View File
@@ -1,154 +1,229 @@
import type { DeptTreeVO } from '@/api/system/dept/types';
import type { RoleVO } from '@/api/system/role/types';
import type { PageResult, R } from '@/api/types';
import request from '@/api/request';
import { DeptVO } from './../dept/types';
import { RoleVO } from '@/api/system/role/types';
import request from '@/utils/request';
import { AxiosPromise } from 'axios';
import { UserForm, UserQuery, UserVO, UserInfoVO } from './types';
import { parseStrEmpty } from '@/utils/ruoyi';
import type { UserForm, UserInfoVO, UserProfileForm, UserQuery, UserVO } from './types';
export function listUser(query: UserQuery) {
return request<R<PageResult<UserVO>>>({
/**
* 查询用户列表
* @param query
*/
export const listUser = (query: UserQuery): AxiosPromise<UserVO[]> => {
return request({
url: '/system/user/list',
method: 'get',
params: query
});
}
};
export function optionSelect(userIds: Array<number | string>) {
return request<R<UserVO[]>>({
url: `/system/user/optionselect?userIds=${userIds}`,
/**
* 通过用户ids查询用户
* @param userIds
*/
export const optionSelect = (userIds: (number | string)[]): AxiosPromise<UserVO[]> => {
return request({
url: '/system/user/optionselect?userIds=' + userIds,
method: 'get'
});
}
};
export function getUser(userId?: string | number) {
return request<R<UserInfoVO>>({
url: `/system/user/${parseStrEmpty(userId)}`,
/**
* 获取用户详情
* @param userId
*/
export const getUser = (userId?: string | number): AxiosPromise<UserInfoVO> => {
return request({
url: '/system/user/' + parseStrEmpty(userId),
method: 'get'
});
}
};
export function addUser(data: UserForm) {
return request<R>({
/**
* 新增用户
*/
export const addUser = (data: UserForm) => {
return request({
url: '/system/user',
method: 'post',
data
data: data
});
}
};
export function updateUser(data: UserForm) {
return request<R>({
/**
* 修改用户
*/
export const updateUser = (data: UserForm) => {
return request({
url: '/system/user',
method: 'put',
data
data: data
});
}
};
export function delUser(userId: Array<string | number> | string | number) {
return request<R>({
url: `/system/user/${userId}`,
/**
* 删除用户
* @param userId 用户ID
*/
export const delUser = (userId: Array<string | number> | string | number) => {
return request({
url: '/system/user/' + userId,
method: 'delete'
});
}
};
export function resetUserPwd(userId: string | number, password: string) {
return request<R>({
/**
* 用户密码重置
* @param userId 用户ID
* @param password 密码
*/
export const resetUserPwd = (userId: string | number, password: string) => {
const data = {
userId,
password
};
return request({
url: '/system/user/resetPwd',
method: 'put',
headers: {
isEncrypt: true,
repeatSubmit: false
},
data: {
userId,
password
}
data: data
});
}
};
export function changeUserStatus(userId: number | string, status: string) {
return request<R>({
/**
* 用户状态修改
* @param userId 用户ID
* @param status 用户状态
*/
export const changeUserStatus = (userId: number | string, status: string) => {
const data = {
userId,
status
};
return request({
url: '/system/user/changeStatus',
method: 'put',
data: {
userId,
status
}
data: data
});
}
};
export function unlockUser(userId: number | string) {
return request<R>({
url: `/system/user/unlock/${userId}`,
method: 'get'
});
}
export function getUserProfile() {
return request<R<UserInfoVO>>({
/**
* 查询用户个人信息
*/
export const getUserProfile = (): AxiosPromise<UserInfoVO> => {
return request({
url: '/system/user/profile',
method: 'get'
});
}
};
export function updateUserProfile(data: UserProfileForm) {
return request<R>({
/**
* 修改用户个人信息
* @param data 用户信息
*/
export const updateUserProfile = (data: UserForm) => {
return request({
url: '/system/user/profile',
method: 'put',
data
data: data
});
}
};
export function updateUserPwd(oldPassword: string, newPassword: string) {
return request<R>({
/**
* 用户密码重置
* @param oldPassword 旧密码
* @param newPassword 新密码
*/
export const updateUserPwd = (oldPassword: string, newPassword: string) => {
const data = {
oldPassword,
newPassword
};
return request({
url: '/system/user/profile/updatePwd',
method: 'put',
headers: {
isEncrypt: true,
repeatSubmit: false
},
data: {
oldPassword,
newPassword
}
data: data
});
}
};
export function importUser(data: FormData, updateSupport: boolean) {
return request<R>({
url: '/system/user/importData',
/**
* 用户头像上传
* @param data 头像文件
*/
export const uploadAvatar = (data: FormData) => {
return request({
url: '/system/user/profile/avatar',
method: 'post',
params: {
updateSupport: updateSupport ? 1 : 0
},
data
data: data
});
}
};
export function getAuthRole(userId: string | number) {
return request<R<{ user: UserVO; roles: RoleVO[] }>>({
url: `/system/user/authRole/${userId}`,
/**
* 查询授权角色
* @param userId 用户ID
*/
export const getAuthRole = (userId: string | number): AxiosPromise<{ user: UserVO; roles: RoleVO[] }> => {
return request({
url: '/system/user/authRole/' + userId,
method: 'get'
});
}
};
export function updateAuthRole(data: { userId: string; roleIds: string }) {
return request<R>({
/**
* 保存授权角色
* @param data 用户ID
*/
export const updateAuthRole = (data: { userId: string; roleIds: string }) => {
return request({
url: '/system/user/authRole',
method: 'put',
params: data
});
}
};
export function deptTreeSelect() {
return request<R<DeptTreeVO[]>>({
/**
* 查询当前部门的所有用户信息
* @param deptId
*/
export const listUserByDeptId = (deptId: string | number): AxiosPromise<UserVO[]> => {
return request({
url: '/system/user/list/dept/' + deptId,
method: 'get'
});
};
/**
* 查询部门下拉树结构
*/
export const deptTreeSelect = (): AxiosPromise<DeptVO[]> => {
return request({
url: '/system/user/deptTree',
method: 'get'
});
}
};
export function listUserByDeptId(deptId: string | number) {
return request<R<UserVO[]>>({
url: `/system/user/list/dept/${deptId}`,
method: 'get'
});
}
export default {
listUser,
getUser,
optionSelect,
addUser,
updateUser,
delUser,
resetUserPwd,
changeUserStatus,
getUserProfile,
updateUserProfile,
updateUserPwd,
uploadAvatar,
getAuthRole,
updateAuthRole,
deptTreeSelect,
listUserByDeptId
};
+67 -65
View File
@@ -1,82 +1,84 @@
import type { DeptVO } from '@/api/system/dept/types';
import type { PostVO } from '@/api/system/post/types';
import type { RoleVO } from '@/api/system/role/types';
import type { BaseEntity, PageQuery } from '@/api/types';
import { RoleVO } from '@/api/system/role/types';
import { PostVO } from '@/api/system/post/types';
/**
* 用户信息
*/
export interface UserInfo {
user: {
userId: string | number;
userName: string;
nickName?: string;
avatar?: string | number;
avatarUrl?: string;
deptName?: string;
};
user: UserVO;
roles: string[];
permissions: string[];
}
export interface UserForm {
userId?: string | number;
deptId?: number | string;
userName?: string;
nickName?: string;
password?: string;
phoneNumber?: string;
email?: string;
gender?: string;
status?: string;
remark?: string;
avatar?: string | number;
postIds?: Array<string | number>;
roleIds?: Array<string | number>;
}
export interface UserProfileForm {
nickName?: string;
phoneNumber?: string;
email?: string;
gender?: string;
avatar?: string | number;
}
export interface UserInfoVO {
user?: UserVO;
roles: RoleVO[];
roleIds: Array<string | number>;
posts: PostVO[];
postIds: Array<string | number>;
roleGroup?: string;
postGroup?: string;
}
/**
* 用户查询对象类型
*/
export interface UserQuery extends PageQuery {
userName?: string;
nickName?: string;
phoneNumber?: string;
phonenumber?: string;
status?: string;
deptId?: string | number;
roleId?: string | number;
userIds?: string | number;
}
/**
* 用户返回对象
*/
export interface UserVO extends BaseEntity {
userId?: string | number;
tenantId?: string;
deptId?: number | string;
userName?: string;
userId: string | number;
tenantId: string;
deptId: number;
userName: string;
nickName: string;
userType: string;
email: string;
phonenumber: string;
sex: string;
avatar: string;
status: string;
delFlag: string;
loginIp: string;
loginDate: string;
remark: string;
deptName: string;
roles: RoleVO[];
roleIds: any;
postIds: any;
roleId: any;
admin: boolean;
}
/**
* 用户表单类型
*/
export interface UserForm {
id?: string;
userId?: string;
deptId?: number;
userName: string;
nickName?: string;
userType?: string;
password: string;
phonenumber?: string;
email?: string;
phoneNumber?: string;
gender?: string;
avatar?: string | number;
avatarUrl?: string;
status?: string;
deptName?: string;
roles?: RoleVO[];
admin?: boolean;
loginIp?: string;
loginDate?: string;
dept?: DeptVO;
sex?: string;
status: string;
remark?: string;
postIds: string[];
roleIds: string[];
}
export interface UserInfoVO {
user: UserVO;
roles: RoleVO[];
roleIds: string[];
posts: PostVO[];
postIds: string[];
roleGroup: string;
postGroup: string;
}
export interface ResetPwdForm {
oldPassword: string;
newPassword: string;
confirmPassword: string;
}
+52 -44
View File
@@ -1,78 +1,86 @@
import type { PageResult, R } from '@/api/types';
import request from '@/api/request';
import type { DbTableQuery, DbTableVO, GenTableDetailPayload, TableQuery, TableVO } from './types';
import request from '@/utils/request';
import { DbTableQuery, DbTableVO, TableQuery, TableVO, GenTableVO, DbTableForm } from './types';
import { AxiosPromise } from 'axios';
export function listTable(query: TableQuery) {
return request<R<PageResult<TableVO>>>({
// 查询生成表数据
export const listTable = (query: TableQuery): AxiosPromise<TableVO[]> => {
return request({
url: '/tool/gen/list',
method: 'get',
params: query
});
}
export function listDbTable(query: DbTableQuery) {
return request<R<PageResult<DbTableVO>>>({
};
// 查询db数据库列表
export const listDbTable = (query: DbTableQuery): AxiosPromise<DbTableVO[]> => {
return request({
url: '/tool/gen/db/list',
method: 'get',
params: query
});
}
};
export function getGenTable(tableId: string | number) {
return request<R<GenTableDetailPayload>>({
url: `/tool/gen/${tableId}`,
// 查询表详细信息
export const getGenTable = (tableId: string | number): AxiosPromise<GenTableVO> => {
return request({
url: '/tool/gen/' + tableId,
method: 'get'
});
}
};
export function updateGenTable(data: DbTableVO & { columns?: unknown[]; params?: Record<string, unknown> }) {
return request<R>({
// 修改代码生成信息
export const updateGenTable = (data: DbTableForm): AxiosPromise<GenTableVO> => {
return request({
url: '/tool/gen',
method: 'put',
data
data: data
});
}
};
export function importTable(data: { tables: string; dataName: string }) {
return request<R>({
// 导入表
export const importTable = (data: { tables: string; dataName: string }): AxiosPromise<GenTableVO> => {
return request({
url: '/tool/gen/importTable',
method: 'post',
params: data
});
}
};
export function previewTable(tableId: string | number) {
return request<R<Record<string, string>>>({
url: `/tool/gen/preview/${tableId}`,
// 预览生成代码
export const previewTable = (tableId: string | number) => {
return request({
url: '/tool/gen/preview/' + tableId,
method: 'get'
});
}
};
export function delTable(tableId: string | number | Array<string | number>) {
return request<R>({
url: `/tool/gen/${tableId}`,
// 删除表数据
export const delTable = (tableId: string | number | Array<string | number>) => {
return request({
url: '/tool/gen/' + tableId,
method: 'delete'
});
}
};
export function synchDb(tableId: string | number) {
return request<R>({
url: `/tool/gen/synchDb/${tableId}`,
// 生成代码(自定义路径)
export const genCode = (tableId: string | number) => {
return request({
url: '/tool/gen/genCode/' + tableId,
method: 'get'
});
}
};
export function getDataNames() {
return request<R<string[]>>({
// 同步数据库
export const synchDb = (tableId: string | number) => {
return request({
url: '/tool/gen/synchDb/' + tableId,
method: 'get'
});
};
// 获取数据源名称
export const getDataNames = () => {
return request({
url: '/tool/gen/getDataNames',
method: 'get'
});
}
export function batchGenCode(tableIdStr: string) {
return request<Blob>({
url: `/tool/gen/batchGenCode?tableIdStr=${tableIdStr}`,
method: 'get',
responseType: 'blob'
});
}
};
+173 -84
View File
@@ -1,91 +1,180 @@
import type { BaseEntity, PageQuery } from '@/api/types';
export interface DbColumnVO extends BaseEntity {
columnId?: string | number;
tableId?: string | number;
columnName?: string;
columnComment?: string;
columnType?: string;
javaType?: string;
javaField?: string;
isPk?: string;
isIncrement?: string;
isRequired?: string;
isInsert?: string;
isEdit?: string;
isList?: string;
isQuery?: string;
queryType?: string;
htmlType?: string;
dictType?: string;
sort?: number;
increment?: boolean;
capJavaField?: string;
usableColumn?: boolean;
superColumn?: boolean;
list?: boolean;
pk?: boolean;
insert?: boolean;
edit?: boolean;
query?: boolean;
required?: boolean;
}
export interface DbTableQuery extends PageQuery {
dataName?: string;
tableName?: string;
tableComment?: string;
}
export interface DbTableVO extends Omit<TableVO, 'tableId'> {
tableId?: string | number;
columns?: DbColumnVO[];
options?: string;
remark?: string;
treeCode?: string;
treeParentCode?: string;
treeName?: string;
menuIds?: Array<string | number>;
parentMenuId?: string | number;
parentMenuName?: string;
enableExport?: boolean;
enableStatus?: boolean;
statusField?: string;
enableUnique?: boolean;
uniqueFields?: string[];
enableSort?: boolean;
sortField?: string;
frontendType?: string;
treeRootValue?: string;
treeAncestorsField?: string;
treeOrderField?: string;
}
export interface GenTableDetailPayload {
info: DbTableVO;
rows: DbColumnVO[];
export interface TableVO extends BaseEntity {
createDept: number | string;
tableId: string | number;
dataName: string;
tableName: string;
tableComment: string;
subTableName?: any;
subTableFkName?: any;
className: string;
tplCategory: string;
packageName: string;
moduleName: string;
businessName: string;
functionName: string;
functionAuthor: string;
genType: string;
genPath: string;
pkColumn?: any;
columns?: any;
options?: any;
remark?: any;
treeCode?: any;
treeParentCode?: any;
treeName?: any;
menuIds?: any;
parentMenuId?: any;
parentMenuName?: any;
tree: boolean;
crud: boolean;
}
export interface TableQuery extends PageQuery {
tableName?: string;
tableComment?: string;
dataName?: string;
tableName: string;
tableComment: string;
dataName: string;
}
export interface TableVO extends BaseEntity {
createDept?: number | string;
tableId: string | number;
dataName?: string;
export interface DbColumnVO extends BaseEntity {
createDept?: any;
columnId?: any;
tableId?: any;
columnName?: any;
columnComment?: any;
columnType?: any;
javaType?: any;
javaField?: any;
isPk?: any;
isIncrement?: any;
isRequired?: any;
isInsert?: any;
isEdit?: any;
isList?: any;
isQuery?: any;
queryType?: any;
htmlType?: any;
dictType?: any;
sort?: any;
increment: boolean;
capJavaField?: any;
usableColumn: boolean;
superColumn: boolean;
list: boolean;
pk: boolean;
insert: boolean;
edit: boolean;
query: boolean;
required: boolean;
}
export interface DbTableVO {
createDept?: any;
tableId?: any;
tableName: string;
tableComment?: string;
className?: string;
tplCategory?: string;
frontendType?: string;
packageName?: string;
moduleName?: string;
businessName?: string;
functionName?: string;
functionAuthor?: string;
tree?: boolean;
crud?: boolean;
tableComment: string;
subTableName?: any;
subTableFkName?: any;
className?: any;
tplCategory?: any;
packageName?: any;
moduleName?: any;
businessName?: any;
functionName?: any;
functionAuthor?: any;
genType?: any;
genPath?: any;
pkColumn?: any;
columns: DbColumnVO[];
options?: any;
remark?: any;
treeCode?: any;
treeParentCode?: any;
treeName?: any;
menuIds?: any;
parentMenuId?: any;
parentMenuName?: any;
tree: boolean;
crud: boolean;
}
export interface DbTableQuery extends PageQuery {
dataName: string;
tableName: string;
tableComment: string;
}
export interface GenTableVO {
info: DbTableVO;
rows: DbColumnVO[];
tables: DbTableVO[];
}
export interface DbColumnForm extends BaseEntity {
createDept: number;
columnId: string;
tableId: string;
columnName: string;
columnComment: string;
columnType: string;
javaType: string;
javaField: string;
isPk: string;
isIncrement: string;
isRequired: string;
isInsert?: any;
isEdit: string;
isList: string;
isQuery?: any;
queryType: string;
htmlType: string;
dictType: string;
sort: number;
increment: boolean;
capJavaField: string;
usableColumn: boolean;
superColumn: boolean;
list: boolean;
pk: boolean;
insert: boolean;
edit: boolean;
query: boolean;
required: boolean;
}
export interface DbParamForm {
treeCode?: any;
treeName?: any;
treeParentCode?: any;
parentMenuId: string;
}
export interface DbTableForm extends BaseEntity {
createDept?: any;
tableId: string | string;
tableName: string;
tableComment: string;
subTableName?: any;
subTableFkName?: any;
className: string;
tplCategory: string;
packageName: string;
moduleName: string;
businessName: string;
functionName: string;
functionAuthor: string;
genType: string;
genPath: string;
pkColumn?: any;
columns: DbColumnForm[];
options: string;
remark?: any;
treeCode?: any;
treeParentCode?: any;
treeName?: any;
menuIds?: any;
parentMenuId: string;
parentMenuName?: any;
tree: boolean;
crud: boolean;
params: DbParamForm;
}
+44 -73
View File
@@ -1,88 +1,59 @@
import type { MenuDataItem } from '@ant-design/pro-components';
export interface BaseEntity {
createBy?: string;
createTime?: string;
updateBy?: string;
updateTime?: string;
remark?: string;
}
export interface LoginParams {
username?: string;
password?: string;
code?: string;
uuid?: string;
rememberMe?: boolean;
socialCode?: string;
socialState?: string;
source?: string;
clientId?: string;
grantType?: string;
}
export interface LoginResult {
access_token: string;
}
export interface PageQuery {
pageNum?: number;
pageSize?: number;
orderByColumn?: string;
isAsc?: 'ascending' | 'descending';
params?: Record<string, unknown>;
}
export interface PageResult<T = unknown> {
total: number;
rows: T[];
}
export interface R<T = unknown> {
code: number;
msg: string;
data: T;
}
export interface RegisterParams {
username?: string;
password?: string;
/**
* 注册
*/
export type RegisterForm = {
tenantId: string;
username: string;
password: string;
confirmPassword?: string;
code?: string;
uuid?: string;
userType?: string;
clientId?: string;
grantType?: string;
};
/**
* 登录请求
*/
export interface LoginData {
tenantId?: string;
username?: string;
password?: string;
rememberMe?: boolean;
socialCode?: string;
socialState?: string;
source?: string;
code?: string;
uuid?: string;
clientId: string;
grantType: string;
}
/**
* 登录响应
*/
export interface LoginResult {
access_token: string;
}
/**
* 验证码返回
*/
export interface VerifyCodeResult {
captchaEnabled: boolean;
uuid?: string;
img?: string;
}
export interface RouteMeta {
title?: string;
icon?: string | null;
noCache?: boolean;
link?: string;
hidden?: boolean;
activeMenu?: string;
/**
* 租户
*/
export interface TenantVO {
companyName: string;
domain: any;
tenantId: string;
}
export interface BackendRoute {
name?: string;
path: string;
component?: string;
redirect?: string;
query?: string;
hidden?: boolean;
alwaysShow?: boolean;
meta?: RouteMeta;
children?: BackendRoute[];
export interface TenantInfo {
tenantEnabled: boolean;
voList: TenantVO[];
}
export type RuntimeMenuItem = Omit<MenuDataItem, 'routes'> & {
backendRoute?: BackendRoute;
routes?: RuntimeMenuItem[];
};
+44 -30
View File
@@ -1,49 +1,63 @@
import type { R } from '@/api/types';
import request from '@/api/request';
import type { CategoryForm, CategoryQuery, CategoryTreeVO, CategoryVO } from './types';
import request from '@/utils/request';
import { AxiosPromise } from 'axios';
import { CategoryVO, CategoryForm, CategoryQuery } from '@/api/workflow/category/types';
export function listCategory(query?: CategoryQuery) {
return request<R<CategoryVO[]>>({
/**
* 查询流程分类列表
* @param query
* @returns {*}
*/
export const listCategory = (query?: CategoryQuery): AxiosPromise<CategoryVO[]> => {
return request({
url: '/workflow/category/list',
method: 'get',
params: query
});
}
};
export function getCategory(categoryId: string | number) {
return request<R<CategoryVO>>({
url: `/workflow/category/${categoryId}`,
/**
* 查询流程分类详细
* @param id
*/
export const getCategory = (id: string | number): AxiosPromise<CategoryVO> => {
return request({
url: '/workflow/category/' + id,
method: 'get'
});
}
};
export function addCategory(data: CategoryForm) {
return request<R>({
/**
* 新增流程分类
* @param data
*/
export const addCategory = (data: CategoryForm) => {
return request({
url: '/workflow/category',
method: 'post',
data
data: data
});
}
};
export function updateCategory(data: CategoryForm) {
return request<R>({
/**
* 修改流程分类
* @param data
*/
export const updateCategory = (data: CategoryForm) => {
return request({
url: '/workflow/category',
method: 'put',
data
data: data
});
}
};
export function delCategory(categoryId: string | number | Array<string | number>) {
return request<R>({
url: `/workflow/category/${categoryId}`,
/**
* 删除流程分类
* @param id
*/
export const delCategory = (id: string | number | Array<string | number>) => {
return request({
url: '/workflow/category/' + id,
method: 'delete'
});
}
export function categoryTree(query?: CategoryForm) {
return request<R<CategoryTreeVO[]>>({
url: '/workflow/category/categoryTree',
method: 'get',
params: query
});
}
};
+63 -25
View File
@@ -1,29 +1,67 @@
import type { BaseEntity } from '@/api/types';
export interface CategoryForm extends BaseEntity {
categoryId?: string | number;
categoryName?: string;
parentId?: string | number;
orderNum?: number;
}
export interface CategoryQuery {
categoryName?: string;
}
export interface CategoryTreeVO {
id: number | string;
label: string;
parentId: number | string;
weight: number;
children?: CategoryTreeVO[];
}
export interface CategoryVO {
categoryId: string | number;
parentId?: string | number;
/**
* 主键
*/
id: string;
/**
* 分类名称
*/
categoryName: string;
orderNum: number;
createTime?: string;
/**
* 分类编码
*/
categoryCode: string;
/**
* 父级id
*/
parentId: string | number;
/**
* 排序
*/
sortNum: number;
children?: CategoryVO[];
}
export interface CategoryForm extends BaseEntity {
/**
* 主键
*/
id?: string | number;
/**
* 分类名称
*/
categoryName?: string;
/**
* 分类编码
*/
categoryCode?: string;
/**
* 父级id
*/
parentId?: string | number;
/**
* 排序
*/
sortNum?: number;
}
export interface CategoryQuery extends PageQuery {
/**
* 分类名称
*/
categoryName?: string;
/**
* 分类编码
*/
categoryCode?: string;
}

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