Explorar o código

JeecgBoot 3.3.0 版本发布,开源的企业级低代码平台

zhangdaiscott %!s(int64=2) %!d(string=hai) anos
pai
achega
5ddc20ed33
Modificáronse 85 ficheiros con 3504 adicións e 451 borrados
  1. 15 7
      README.md
  2. 0 273
      docs/Vue3升级脚本_mysql.sql
  3. 0 13
      docs/从vue2切换到vue3前端文档.md
  4. 16 0
      docs/切换到vue3前端路由.md
  5. 6 9
      package.json
  6. 2 0
      src/components/Button/src/PopConfirmButton.vue
  7. 0 41
      src/components/Button/src/UploadButton.vue
  8. 1 1
      src/components/Dropdown/src/Dropdown.vue
  9. 160 0
      src/components/Form/src/components/DetailForm.vue
  10. 542 0
      src/components/Form/src/hooks/useDetailForm.ts
  11. 11 1
      src/components/Form/src/hooks/useForm.ts
  12. 5 1
      src/components/Form/src/jeecg/components/JAreaLinkage.vue
  13. 9 7
      src/components/Form/src/jeecg/components/JCategorySelect.vue
  14. 10 2
      src/components/Form/src/jeecg/components/JCheckbox.vue
  15. 14 2
      src/components/Form/src/jeecg/components/JCodeEditor.vue
  16. 1 0
      src/components/Form/src/jeecg/components/base/JSelectBiz.vue
  17. 3 1
      src/components/Form/src/jeecg/components/modal/DeptSelectModal.vue
  18. 3 1
      src/components/Form/src/jeecg/hooks/useTreeBiz.ts
  19. 17 2
      src/components/JVxeCustom/src/components/JVxeDepartSelectCell.vue
  20. 17 2
      src/components/JVxeCustom/src/components/JVxeUserSelectCell.vue
  21. 39 2
      src/components/Modal/src/BasicModal.vue
  22. 69 4
      src/components/Modal/src/components/ModalClose.vue
  23. 2 1
      src/components/Modal/src/index.less
  24. 3 0
      src/components/Modal/src/props.ts
  25. 1 1
      src/components/SimpleMenu/src/components/SubMenuItem.vue
  26. 2 0
      src/components/Table/src/types/tableAction.ts
  27. 8 2
      src/components/jeecg/AIcon.vue
  28. 154 0
      src/components/jeecg/JPrompt/JPrompt.vue
  29. 56 0
      src/components/jeecg/JPrompt/hooks/useJPrompt.ts
  30. 2 0
      src/components/jeecg/JPrompt/index.ts
  31. 15 0
      src/components/jeecg/JPrompt/typing.ts
  32. 7 3
      src/components/jeecg/JVxeTable/src/JVxeTable.ts
  33. 7 7
      src/components/jeecg/JVxeTable/src/hooks/useData.ts
  34. 5 4
      src/components/jeecg/JVxeTable/src/hooks/useJVxeComponent.ts
  35. 35 9
      src/components/jeecg/JVxeTable/src/hooks/useMethods.ts
  36. 1 1
      src/components/jeecg/JVxeTable/src/hooks/useToolbar.ts
  37. 1 1
      src/components/jeecg/JVxeTable/src/hooks/useWebSocket.ts
  38. 15 6
      src/components/jeecg/OnLine/hooks/usePopBiz.ts
  39. 401 0
      src/components/jeecg/super/superquery/SuperQuery.vue
  40. 98 0
      src/components/jeecg/super/superquery/SuperQueryValComponent.vue
  41. 524 0
      src/components/jeecg/super/superquery/useSuperQuery.ts
  42. 1 0
      src/design/index.less
  43. 30 0
      src/design/lowApp/global.less
  44. 2 0
      src/enums/httpEnum.ts
  45. 2 0
      src/enums/jeecgEnum.ts
  46. 2 0
      src/enums/pageEnum.ts
  47. 1 1
      src/hooks/web/useWebSocket.ts
  48. 6 1
      src/layouts/default/header/components/notify/index.vue
  49. 1 1
      src/layouts/default/index.vue
  50. 32 2
      src/router/guard/permissionGuard.ts
  51. 8 3
      src/router/helper/routeHelper.ts
  52. 25 1
      src/router/routes/index.ts
  53. 2 2
      src/store/modules/permission.ts
  54. 9 0
      src/utils/auth/index.ts
  55. 1 0
      src/utils/dict/JDictSelectUtil.js
  56. 15 0
      src/utils/http/axios/index.ts
  57. 19 0
      src/utils/index.ts
  58. 10 0
      src/views/dashboard/Analysis/components/QuickNav.vue
  59. 1 1
      src/views/dashboard/Analysis/homePage/IndexTask.vue
  60. 4 4
      src/views/demo/jeecg/JVxeTableDemo/func-demo/JSBCDemo.vue
  61. 22 0
      src/views/demo/jeecg/JeecgComponents.vue
  62. 14 0
      src/views/demo/jeecg/jeecgComponents.data.ts
  63. 6 2
      src/views/demo/vextable/OneToOneModal.vue
  64. 121 1
      src/views/demo/vextable/data.ts
  65. 67 0
      src/views/demo/vextable/form/JeecgOrderCustomerForm.vue
  66. 155 0
      src/views/demo/vextable/form/JeecgOrderMainForm.vue
  67. 2 1
      src/views/demo/vextable/index.vue
  68. 1 1
      src/views/demo/vextable/jvxetable/jvxetable.data.ts
  69. 56 0
      src/views/monitor/mynews/DetailModal.vue
  70. 3 3
      src/views/monitor/mynews/mynews.api.ts
  71. 86 0
      src/views/sys/login/OAuth2Login.vue
  72. 206 0
      src/views/sys/login/TokenLoginPage.vue
  73. 19 0
      src/views/sys/login/useLogin.ts
  74. 3 1
      src/views/system/address/index.vue
  75. 64 0
      src/views/system/examples/demo/DemoDetailModal.vue
  76. 39 2
      src/views/system/examples/demo/index.vue
  77. 21 0
      src/views/system/menu/MenuDrawer.vue
  78. 16 0
      src/views/system/menu/menu.data.ts
  79. 2 2
      src/views/system/message/manage/manage.data.ts
  80. 43 3
      src/views/system/message/template/index.vue
  81. 24 10
      src/views/system/message/template/template.data.ts
  82. 55 0
      src/views/system/role/components/RoleIndexModal.vue
  83. 14 3
      src/views/system/role/index.vue
  84. 15 0
      src/views/system/role/role.data.ts
  85. 2 2
      src/views/system/user/index.vue

+ 15 - 7
README.md

@@ -1,6 +1,7 @@
 JEECG BOOT 低代码开发平台(Vue3前端)
 ===============
-当前最新版本: 1.3.0(发布时间:20220627)
+当前最新版本: 3.3.0(发布时间:20220725)
+> 变更大版本号与后台同步 3.3.X,后续单独发布版本会更新小版本号。
 
 
 ## 简介
@@ -9,8 +10,15 @@ JeecgBoot-Vue3采用 Vue3.0、Vite、 Ant-Design-Vue、TypeScript 等新技术
  
 > 强大的代码生成器让前后端代码一键生成! JeecgBoot引领低代码开发模式(OnlineCoding-> 代码生成-> 手工MERGE), 帮助解决Java项目70%的重复工作,让开发更多关注业务。既能快速提高效率,节省成本,同时又不失灵活性
 
-##  项目说明
+##  项目源码
 
+| 仓库 |前端源码Vue3版 | 前端源码Vue2版 | 后端源码 |
+|-|-|-|-|
+| Github | [jeecgboot-vue3](https://github.com/jeecgboot/jeecgboot-vue3)  | [ant-design-vue-jeecg](https://github.com/jeecgboot/jeecg-boot/tree/master/ant-design-vue-jeecg) | [jeecg-boot](https://github.com/jeecgboot/jeecg-boot) |
+| 码云 | [jeecgboot-vue3](https://gitee.com/jeecg/jeecgboot-vue3)  | [ant-design-vue-jeecg](https://gitee.com/jeecg/jeecg-boot/tree/master/ant-design-vue-jeecg)  | [jeecg-boot](https://gitee.com/jeecg/jeecg-boot) |
+
+
+##### 项目说明
 
 | 项目名                | 说明                     | 传送门                                                                                                                          |
 |--------------------|------------------------|-------------------------------------------------------------------------------------------------------------------------------------|
@@ -182,11 +190,11 @@ yarn build
 │  ├─Online在线表单 - 功能已开放
 │  ├─Online代码生成器 - 功能已开放
 │  ├─Online在线报表 - 功能已开放
-│  ├─Online在线图表(商业功能)
-│  ├─Online图表模板配置(商业功能)
-│  ├─Online布局设计(商业功能)
+│  ├─Online在线图表(未开源)
+│  ├─Online图表模板配置(未开源)
+│  ├─Online布局设计(未开源)
 │  ├─多数据源管理 - 功能已开放
-│─流程模块功能 (商业功能)
+│─流程模块功能 (未开源)
 │  ├─流程设计器
 │  ├─表单设计器
 │  ├─大屏设计器
@@ -201,7 +209,7 @@ yarn build
 │  └─我的抄送
 │  └─流程委派、抄送、跳转
 │  └─。。。
-│─OA办公组件 (商业功能)
+│─OA办公组件 (未开源)
 │  ├─更多功能
 │  └─。。。
 └─其他模块 (暂不开源)

+ 0 - 273
docs/Vue3升级脚本_mysql.sql

@@ -1,273 +0,0 @@
--- 备份vue2的菜单表(修改原表名)
-alter table sys_permission rename as sys_permission_v2;
-
--- 创建vue3的所使用的菜单表
--- ----------------------------
--- Table structure for sys_permission
--- ----------------------------
-CREATE TABLE `sys_permission`  (
-  `id` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '主键id',
-  `parent_id` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '父id',
-  `name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '菜单标题',
-  `url` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '路径',
-  `component` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '组件',
-  `is_route` tinyint(1) NULL DEFAULT 1 COMMENT '是否路由菜单: 0:不是  1:是(默认值1)',
-  `component_name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '组件名字',
-  `redirect` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '一级菜单跳转地址',
-  `menu_type` int(11) NULL DEFAULT NULL COMMENT '菜单类型(0:一级菜单; 1:子菜单:2:按钮权限)',
-  `perms` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '菜单权限编码',
-  `perms_type` varchar(10) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '0' COMMENT '权限策略1显示2禁用',
-  `sort_no` int(10) NULL DEFAULT NULL COMMENT '菜单排序',
-  `always_show` tinyint(1) NULL DEFAULT NULL COMMENT '聚合子路由: 1是0否',
-  `icon` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '菜单图标',
-  `is_leaf` tinyint(1) NULL DEFAULT NULL COMMENT '是否叶子节点:    1是0否',
-  `keep_alive` tinyint(1) NULL DEFAULT NULL COMMENT '是否缓存该页面:    1:是   0:不是',
-  `hidden` int(2) NULL DEFAULT 0 COMMENT '是否隐藏路由: 0否,1是',
-  `hide_tab` int(2) NULL DEFAULT NULL COMMENT '是否隐藏tab: 0否,1是',
-  `description` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '描述',
-  `create_by` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '创建人',
-  `create_time` datetime NULL DEFAULT NULL COMMENT '创建时间',
-  `update_by` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '更新人',
-  `update_time` datetime NULL DEFAULT NULL COMMENT '更新时间',
-  `del_flag` int(11) NULL DEFAULT 0 COMMENT '删除状态 0正常 1已删除',
-  `rule_flag` int(3) NULL DEFAULT 0 COMMENT '是否添加数据权限1是0否',
-  `status` varchar(2) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '按钮权限状态(0无效1有效)',
-  `internal_or_external` tinyint(1) NULL DEFAULT NULL COMMENT '外链菜单打开方式 0/内部打开 1/外部打开',
-  PRIMARY KEY (`id`) USING BTREE,
-  INDEX `index_menu_type`(`menu_type`) USING BTREE,
-  INDEX `index_menu_hidden`(`hidden`) USING BTREE,
-  INDEX `index_menu_status`(`status`) USING BTREE
-) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '菜单权限表' ROW_FORMAT = Dynamic;
-
--- ----------------------------
--- Records of sys_permission
--- ----------------------------
-INSERT INTO `sys_permission` VALUES ('1170592628746878978', 'd7d6e2e4e2934f2c9385a623fd98c6f3', '菜单管理', '/system/menu', 'system/menu/index', 1, NULL, NULL, 1, NULL, '1', 3, 0, 'ant-design:menu-fold-outlined', 1, 0, 0, NULL, NULL, 'admin', '2019-09-08 15:00:05', 'admin', '2021-09-17 15:40:01', 0, 0, '1', 0);
-INSERT INTO `sys_permission` VALUES ('1211885237487923202', '1207203817658105858', 'btn:add', '', '', 1, NULL, NULL, 2, 'btn:add', '1', 1, 0, NULL, 1, 0, 0, NULL, NULL, 'admin', '2019-12-31 13:42:11', 'admin', '2020-01-07 20:07:53', 0, 0, '1', 0);
-INSERT INTO `sys_permission` VALUES ('1214376304951664642', '3f915b2769fc80648e92d04e84ca059d', '用户编辑', '', '', 1, NULL, NULL, 2, 'user:edit', '1', 1, 0, NULL, 1, 0, 0, NULL, NULL, 'admin', '2020-01-07 10:40:47', 'admin', '2020-01-07 10:41:04', 0, 0, '1', 0);
-INSERT INTO `sys_permission` VALUES ('1214462306546319362', '3f915b2769fc80648e92d04e84ca059d', '新增用户', '', '', 1, NULL, NULL, 2, 'user:add', '1', 1, 0, NULL, 1, 0, 0, NULL, NULL, 'admin', '2020-01-07 16:22:32', NULL, NULL, 0, 0, '1', 0);
-INSERT INTO `sys_permission` VALUES ('1280350452934307841', 'd7d6e2e4e2934f2c9385a623fd98c6f3', '租户管理', '/system/tenant', 'system/tenant/index', 1, NULL, NULL, 1, NULL, '1', 99, 0, 'ant-design:appstore-twotone', 1, 0, 0, NULL, NULL, 'admin', '2020-07-07 11:58:30', 'admin', '2021-09-17 15:40:41', 0, 0, '1', 0);
-INSERT INTO `sys_permission` VALUES ('1438108176273760258', '', 'Dashboard', '/dashboard', 'layouts/default/index', 1, NULL, '/dashboard/analysis', 0, NULL, '1', 1, 0, 'ion:grid-outline', 0, 0, 0, 0, NULL, 'admin', '2021-09-15 19:51:23', 'admin', '2021-10-22 20:39:20', 0, 1, '1', 0);
-INSERT INTO `sys_permission` VALUES ('1438108176814825473', '1438108176273760258', '工作台', '/dashboard/workbench', 'dashboard/workbench/index', 1, NULL, NULL, 1, NULL, '1', 1, 0, 'ant-design:appstore-twotone', 1, 0, 0, NULL, NULL, 'admin', '2021-09-15 19:51:23', 'admin', '2021-09-17 15:42:42', 0, 0, '1', 0);
-INSERT INTO `sys_permission` VALUES ('1438108176932265985', '1438108178010202113', '权限管理', '/permission', 'layouts/default/index', 1, NULL, '/permission/front/page', 0, NULL, '1', 2, 0, 'ion:key-outline', 0, 0, 0, NULL, NULL, 'admin', '2021-09-15 19:51:23', NULL, NULL, 0, 0, '1', 0);
-INSERT INTO `sys_permission` VALUES ('1438108177074872321', '1438108176932265985', '基于前端权限', '/permission/front', NULL, 1, NULL, NULL, 1, NULL, '1', 0, 0, NULL, 0, 0, 0, NULL, NULL, 'admin', '2021-09-15 19:51:23', NULL, NULL, 0, 0, '1', 0);
-INSERT INTO `sys_permission` VALUES ('1438108177188118529', '1438108176932265985', '基于后台权限', '/permission/back', NULL, 1, NULL, NULL, 1, NULL, '1', 1, 0, NULL, 0, 0, 0, NULL, NULL, 'admin', '2021-09-15 19:51:23', NULL, NULL, 0, 0, '1', 0);
-INSERT INTO `sys_permission` VALUES ('1438108177351696386', '1438108177074872321', '页面权限', '/permission/front/page', 'demo/permission/front/index', 1, NULL, NULL, 1, NULL, '1', 0, 0, NULL, 1, 0, 0, NULL, NULL, 'admin', '2021-09-15 19:51:23', 'admin', '2021-09-16 14:37:49', 0, 0, '1', 0);
-INSERT INTO `sys_permission` VALUES ('1438108177565605889', '1438108177074872321', '按钮权限', '/permission/front/btn', 'demo/permission/front/Btn', 1, NULL, NULL, 1, NULL, '1', 1, 0, NULL, 1, 0, 0, NULL, NULL, 'admin', '2021-09-15 19:51:23', 'admin', '2021-09-15 19:57:23', 0, 0, '1', 0);
-INSERT INTO `sys_permission` VALUES ('1438108177720795137', '1438108177188118529', '页面权限', '/permission/back/page', 'demo/permission/back/index', 1, NULL, NULL, 1, NULL, '1', 0, 0, NULL, 1, 0, 0, NULL, NULL, 'admin', '2021-09-15 19:51:23', 'admin', '2021-09-15 19:56:40', 0, 0, '1', 0);
-INSERT INTO `sys_permission` VALUES ('1438108177880178689', '1438108177188118529', '按钮权限', '/permission/back/btn', 'demo/permission/back/Btn', 1, NULL, NULL, 1, NULL, '1', 1, 0, NULL, 1, 0, 0, NULL, NULL, 'admin', '2021-09-15 19:51:23', 'admin', '2021-09-15 19:57:00', 0, 0, '1', 0);
-INSERT INTO `sys_permission` VALUES ('1438108178010202113', '1438108196993622018', '功能示例', '/feat', 'layouts/default/index', 1, NULL, '/feat/icon', 0, NULL, '1', 20, 0, 'ion:git-compare-outline', 0, 0, 0, NULL, NULL, 'admin', '2021-09-15 19:51:23', NULL, NULL, 0, 0, '1', 0);
-INSERT INTO `sys_permission` VALUES ('1438108178127642626', '1438108197958315557', '图标', '/comp/basic/icon', 'demo/feat/icon/index', 1, NULL, NULL, 1, NULL, '1', 0, 0, NULL, 1, 0, 0, NULL, NULL, 'admin', '2021-09-15 19:51:23', NULL, NULL, 0, 0, '1', 0);
-INSERT INTO `sys_permission` VALUES ('1438108178257666049', '1438108178010202113', 'websocket测试', '/feat/ws', 'demo/feat/ws/index', 1, NULL, NULL, 1, NULL, '1', 1, 0, NULL, 1, 0, 0, NULL, NULL, 'admin', '2021-09-15 19:51:23', NULL, NULL, 0, 0, '1', 0);
-INSERT INTO `sys_permission` VALUES ('1438108178421243905', '1438108178010202113', '登录过期', '/feat/session-timeout', 'demo/feat/session-timeout/index', 1, NULL, NULL, 1, NULL, '1', 2, 0, NULL, 1, 0, 0, NULL, NULL, 'admin', '2021-09-15 19:51:23', NULL, NULL, 0, 0, '1', 0);
-INSERT INTO `sys_permission` VALUES ('1438108178643542017', '1438108197958311677', '打印', '/comp/third/print', 'demo/feat/print/index', 1, NULL, NULL, 1, NULL, '1', 3, 0, NULL, 1, 0, 0, NULL, NULL, 'admin', '2021-09-15 19:51:23', NULL, NULL, 0, 0, '1', 0);
-INSERT INTO `sys_permission` VALUES ('1438108178781954049', '1438108197958315557', 'Tab操作', '/comp/basic/tabs', 'demo/feat/tabs/index', 1, NULL, NULL, 1, NULL, '1', 4, 0, NULL, 1, 0, 0, NULL, NULL, 'admin', '2021-09-15 19:51:23', NULL, NULL, 0, 0, '1', 0);
-INSERT INTO `sys_permission` VALUES ('1438108178781954050', '1438108197958315557', 'TabDetail', '/comp/basic/tabs/detail/:id', 'demo/feat/tabs/TabDetail', 1, NULL, '/comp/basic/tabs/detail', 1, NULL, '1', 4, 0, NULL, 1, 0, 1, NULL, NULL, 'admin', '2021-09-15 19:51:23', NULL, NULL, 0, 0, '1', 0);
-INSERT INTO `sys_permission` VALUES ('1438108178911977473', '1438108187455774722', '面包屑导航', '/feat/breadcrumb', 'layouts/default/index', 1, NULL, '/feat/breadcrumb/flat', 1, NULL, '1', 5, 0, 'ant-design:right-square-filled', 0, 0, 0, NULL, NULL, 'admin', '2021-09-15 19:51:23', 'admin', '2021-09-17 15:48:07', 0, 0, '1', 0);
-INSERT INTO `sys_permission` VALUES ('1438108179226550273', '1438108197958311677', '右键菜单', '/comp/third/context-menu', 'demo/feat/context-menu/index', 1, NULL, NULL, 1, NULL, '1', 6, 0, NULL, 1, 0, 0, NULL, NULL, 'admin', '2021-09-15 19:51:23', NULL, NULL, 0, 0, '1', 0);
-INSERT INTO `sys_permission` VALUES ('1438108179381739521', '1438108197958311677', '文件下载', '/comp/third/download', 'demo/feat/download/index', 1, NULL, NULL, 1, NULL, '1', 7, 0, NULL, 1, 0, 0, NULL, NULL, 'admin', '2021-09-15 19:51:23', NULL, NULL, 0, 0, '1', 0);
-INSERT INTO `sys_permission` VALUES ('1438108179599843330', '1438108197958311677', 'ClickOutSide组件', '/comp/third/click-out-side', 'demo/feat/click-out-side/index', 1, NULL, NULL, 1, NULL, '1', 8, 0, NULL, 1, 0, 0, NULL, NULL, 'admin', '2021-09-15 19:51:23', NULL, NULL, 0, 0, '1', 0);
-INSERT INTO `sys_permission` VALUES ('1438108179910221825', '1438108197958311677', '图片预览', '/comp/third/img-preview', 'demo/feat/img-preview/index', 1, NULL, NULL, 1, NULL, '1', 9, 0, NULL, 1, 0, 0, NULL, NULL, 'admin', '2021-09-15 19:51:24', NULL, NULL, 0, 0, '1', 0);
-INSERT INTO `sys_permission` VALUES ('1438108180077993985', '1438108197958311677', '剪切板', '/comp/third/copy', 'demo/feat/copy/index', 1, NULL, NULL, 1, NULL, '1', 10, 0, NULL, 1, 0, 0, NULL, NULL, 'admin', '2021-09-15 19:51:24', NULL, NULL, 0, 0, '1', 0);
-INSERT INTO `sys_permission` VALUES ('1438108180258349057', '1438108197958315557', '消息提示', '/comp/basic/msg', 'demo/feat/msg/index', 1, NULL, NULL, 1, NULL, '1', 11, 0, NULL, 1, 0, 0, NULL, NULL, 'admin', '2021-09-15 19:51:24', NULL, NULL, 0, 0, '1', 0);
-INSERT INTO `sys_permission` VALUES ('1438108180434509826', '1438108197958311677', '水印', '/comp/third/watermark', 'demo/feat/watermark/index', 1, NULL, NULL, 1, NULL, '1', 12, 0, NULL, 1, 0, 0, NULL, NULL, 'admin', '2021-09-15 19:51:24', NULL, NULL, 0, 0, '1', 0);
-INSERT INTO `sys_permission` VALUES ('1438108180631642113', '1438108197958311677', '水波纹', '/comp/third/ripple', 'demo/feat/ripple/index', 1, NULL, NULL, 1, NULL, '1', 13, 0, NULL, 1, 0, 0, NULL, NULL, 'admin', '2021-09-15 19:51:24', NULL, NULL, 0, 0, '1', 0);
-INSERT INTO `sys_permission` VALUES ('1438108180770054145', '1438108178010202113', '全屏', '/feat/full-screen', 'demo/feat/full-screen/index', 1, NULL, NULL, 1, NULL, '1', 14, 0, NULL, 1, 0, 0, NULL, NULL, 'admin', '2021-09-15 19:51:24', NULL, NULL, 0, 0, '1', 0);
-INSERT INTO `sys_permission` VALUES ('1438108182116425729', '1438108197958311677', '日历(New)', '/comp/third/fullCalendar', 'demo/fullcalendar/index', 1, NULL, NULL, 1, NULL, '1', 16, 0, NULL, 1, 0, 0, NULL, NULL, 'admin', '2021-09-15 19:51:24', NULL, NULL, 0, 0, '1', 0);
-INSERT INTO `sys_permission` VALUES ('1438108183085309954', '1438108178010202113', '错误日志', '/feat/error-log', 'sys/error-log/index', 1, NULL, NULL, 1, NULL, '1', 17, 0, NULL, 1, 0, 0, NULL, NULL, 'admin', '2021-09-15 19:51:24', NULL, NULL, 0, 0, '1', 0);
-INSERT INTO `sys_permission` VALUES ('1438108183219527682', '1438108196993622018', 'Excel', '/feat/excel', 'layouts/default/index', 1, NULL, '/feat/excel/customExport', 1, NULL, '1', 18, 0, 'ant-design:file-excel-outlined', 0, 0, 0, NULL, NULL, 'admin', '2021-09-15 19:51:24', 'admin', '2021-09-17 15:54:57', 0, 0, '1', 0);
-INSERT INTO `sys_permission` VALUES ('1438108183395688450', '1438108187455774722', 'Tab带参', '/feat/testTab/:id', 'demo/feat/tab-params/index', 1, NULL, NULL, 1, NULL, '1', 19, 0, 'ant-design:insert-row-above-outlined', 0, 0, 0, NULL, NULL, 'admin', '2021-09-15 19:51:24', 'admin', '2021-09-17 15:48:57', 0, 0, '1', 0);
-INSERT INTO `sys_permission` VALUES ('1438108183492157442', '1438108187455774722', 'Menu带参', '/feat/testParam/:id', 'layouts/default/index', 1, NULL, NULL, 1, NULL, '1', 20, 0, 'ant-design:menu-outlined', 0, 0, 0, NULL, NULL, 'admin', '2021-09-15 19:51:24', 'admin', '2021-09-17 15:49:12', 0, 0, '1', 0);
-INSERT INTO `sys_permission` VALUES ('1438108183630569474', '1438108178911977473', '平级模式', '/feat/breadcrumb/flat', 'demo/feat/breadcrumb/FlatList', 1, NULL, NULL, 1, NULL, '1', 0, 0, NULL, 1, 0, 0, NULL, NULL, 'admin', '2021-09-15 19:51:24', 'admin', '2021-09-15 20:12:01', 0, 0, '1', 0);
-INSERT INTO `sys_permission` VALUES ('1438108183630569477', '1438108178911977473', '平级详情', '/feat/breadcrumb/flatDetail', 'demo/feat/breadcrumb/FlatListDetail', 1, NULL, NULL, 1, NULL, '1', 0, 0, NULL, 1, 0, 1, 1, NULL, 'admin', '2021-09-15 19:51:24', 'admin', '2021-09-18 11:07:07', 0, 0, '1', 0);
-INSERT INTO `sys_permission` VALUES ('1438108183777370114', '1438108183630569474', '平级详情', '/feat/breadcrumb/flatDetail', 'demo/feat/breadcrumb/FlatListDetail', 1, NULL, NULL, 1, NULL, '1', 0, 0, NULL, 1, 0, 1, NULL, NULL, 'admin', '2021-09-15 19:51:24', 'admin', '2021-09-15 20:13:41', 0, 0, '1', 0);
-INSERT INTO `sys_permission` VALUES ('1438108183907393538', '1438108178911977473', '层级模式', '/feat/breadcrumb/children', 'demo/feat/breadcrumb/ChildrenList', 1, NULL, NULL, 1, NULL, '1', 1, 0, NULL, 0, 0, 0, NULL, NULL, 'admin', '2021-09-15 19:51:24', 'admin', '2021-09-15 20:11:57', 0, 0, '1', 0);
-INSERT INTO `sys_permission` VALUES ('1438108184049999873', '1438108183907393538', '层级详情', '/feat/breadcrumb/children/childrenDetail', 'demo/feat/breadcrumb/ChildrenListDetail', 1, NULL, NULL, 1, NULL, '1', 0, 0, NULL, 1, 0, 0, NULL, NULL, 'admin', '2021-09-15 19:51:24', 'admin', '2021-09-15 20:11:49', 0, 0, '1', 0);
-INSERT INTO `sys_permission` VALUES ('1438108185660612609', '1438108183219527682', '选择导出格式', '/feat/excel/customExport', 'demo/excel/CustomExport', 1, NULL, NULL, 1, NULL, '1', 0, 0, NULL, 1, 0, 0, NULL, NULL, 'admin', '2021-09-15 19:51:25', 'admin', '2021-09-15 20:15:59', 0, 0, '1', 0);
-INSERT INTO `sys_permission` VALUES ('1438108185815801858', '1438108183219527682', 'JSON数据导出', '/feat/excel/jsonExport', 'demo/excel/JsonExport', 1, NULL, NULL, 1, NULL, '1', 1, 0, NULL, 1, 0, 0, NULL, NULL, 'admin', '2021-09-15 19:51:25', 'admin', '2021-09-15 20:16:15', 0, 0, '1', 0);
-INSERT INTO `sys_permission` VALUES ('1438108185958408193', '1438108183219527682', 'Array数据导出', '/feat/excel/arrayExport', 'demo/excel/ArrayExport', 1, NULL, NULL, 1, NULL, '1', 2, 0, NULL, 1, 0, 0, NULL, NULL, 'admin', '2021-09-15 19:51:25', 'admin', '2021-09-15 20:16:32', 0, 0, '1', 0);
-INSERT INTO `sys_permission` VALUES ('1438108186289758209', '1438108183219527682', '导入', '/feat/excel/importExcel', 'demo/excel/ImportExcel', 1, NULL, NULL, 1, NULL, '1', 3, 0, NULL, 1, 0, 0, NULL, NULL, 'admin', '2021-09-15 19:51:25', 'admin', '2021-09-15 20:16:43', 0, 0, '1', 0);
-INSERT INTO `sys_permission` VALUES ('1438108186717577217', '1438108183492157442', 'Menu带参1', '/feat/testParam/:id/sub1', 'demo/feat/menu-params/index', 1, NULL, NULL, 1, NULL, '1', 0, 0, NULL, 1, 0, 0, NULL, NULL, 'admin', '2021-09-15 19:51:25', 'admin', '2021-09-15 20:17:23', 0, 0, '1', 0);
-INSERT INTO `sys_permission` VALUES ('1438108187103453186', '1438108183492157442', 'Menu带参2', '/feat/testParam/:id/sub2', 'demo/feat/menu-params/index', 1, NULL, NULL, 1, NULL, '1', 1, 0, NULL, 1, 0, 0, NULL, NULL, 'admin', '2021-09-15 19:51:25', 'admin', '2021-09-15 20:17:36', 0, 0, '1', 0);
-INSERT INTO `sys_permission` VALUES ('1438108187455774722', '', '页面&导航', '/page-demo', 'layouts/default/index', 1, NULL, '/page-demo/form/basic', 0, NULL, '1', 12, 0, 'ion:aperture-outline', 0, 0, 0, 0, NULL, 'admin', '2021-09-15 19:51:25', 'admin', '2021-11-18 10:48:15', 0, 0, '1', 0);
-INSERT INTO `sys_permission` VALUES ('1438108187678072833', '1438108187455774722', '表单页', '/page-demo/form', 'layouts/default/index', 1, NULL, '/page-demo/form/basic', 1, NULL, '1', 0, 0, 'ant-design:form-outlined', 0, 0, 0, NULL, NULL, 'admin', '2021-09-15 19:51:25', 'admin', '2021-09-17 15:45:30', 0, 0, '1', 0);
-INSERT INTO `sys_permission` VALUES ('1438108187871010818', '1438108187455774722', '详情页', '/page-demo/desc', 'layouts/default/index', 1, NULL, '/page-demo/desc/basic', 1, NULL, '1', 1, 0, 'ant-design:border-right-outlined', 0, 0, 0, NULL, NULL, 'admin', '2021-09-15 19:51:25', 'admin', '2021-09-17 15:46:10', 0, 0, '1', 0);
-INSERT INTO `sys_permission` VALUES ('1438108188034588674', '1438108187455774722', '结果页', '/page-demo/result', 'layouts/default/index', 1, NULL, '/page-demo/result/success', 1, NULL, '1', 2, 0, 'ant-design:account-book-outlined', 0, 0, 0, NULL, NULL, 'admin', '2021-09-15 19:51:25', 'admin', '2021-09-17 15:47:04', 0, 0, '1', 0);
-INSERT INTO `sys_permission` VALUES ('1438108188378521602', '1438108187455774722', '个人页', '/page-demo/account', 'layouts/default/index', 1, NULL, '/page-demo/account/setting', 1, NULL, '1', 3, 0, 'ant-design:user-outlined', 0, 0, 0, NULL, NULL, 'admin', '2021-09-15 19:51:26', 'admin', '2021-09-17 15:47:23', 0, 0, '1', 0);
-INSERT INTO `sys_permission` VALUES ('1438108188542099458', '1438108187455774722', '异常页', '/page-demo/exception', 'layouts/default/index', 1, NULL, '/page-demo/exception/404', 1, NULL, '1', 4, 0, 'ant-design:bug-twotone', 0, 0, 0, NULL, NULL, 'admin', '2021-09-15 19:51:26', 'admin', '2021-09-17 15:47:41', 0, 0, '1', 0);
-INSERT INTO `sys_permission` VALUES ('1438108188714065922', '1438108187455774722', '列表页', '/page-demo/list', 'layouts/default/index', 1, NULL, '/page-demo/list/card', 1, NULL, '1', 5, 0, 'ant-design:table-outlined', 0, 0, 0, NULL, NULL, 'admin', '2021-09-15 19:51:26', 'admin', '2021-09-17 15:48:19', 0, 0, '1', 0);
-INSERT INTO `sys_permission` VALUES ('1438108189062193153', '1438108187678072833', '基础表单', '/page-demo/form/basic', 'demo/page/form/basic/index', 1, NULL, NULL, 1, NULL, '1', 0, 0, NULL, 1, 0, 0, NULL, NULL, 'admin', '2021-09-15 19:51:26', NULL, NULL, 0, 0, '1', 0);
-INSERT INTO `sys_permission` VALUES ('1438108189427097601', '1438108187678072833', '分步表单', '/page-demo/form/step', 'demo/page/form/step/index', 1, NULL, NULL, 1, NULL, '1', 1, 0, NULL, 1, 0, 0, NULL, NULL, 'admin', '2021-09-15 19:51:26', NULL, NULL, 0, 0, '1', 0);
-INSERT INTO `sys_permission` VALUES ('1438108189754253313', '1438108187678072833', '高级表单', '/page-demo/form/high', 'demo/page/form/high/index', 1, NULL, NULL, 1, NULL, '1', 2, 0, NULL, 1, 0, 0, NULL, NULL, 'admin', '2021-09-15 19:51:26', NULL, NULL, 0, 0, '1', 0);
-INSERT INTO `sys_permission` VALUES ('1438108190110769154', '1438108187871010818', '基础详情页', '/page-demo/desc/basic', 'demo/page/desc/basic/index', 1, NULL, NULL, 1, NULL, '1', 0, 0, NULL, 1, 0, 0, NULL, NULL, 'admin', '2021-09-15 19:51:26', NULL, NULL, 0, 0, '1', 0);
-INSERT INTO `sys_permission` VALUES ('1438108190404370433', '1438108187871010818', '高级详情页', '/page-demo/desc/high', 'demo/page/desc/high/index', 1, NULL, NULL, 1, NULL, '1', 1, 0, NULL, 1, 0, 0, NULL, NULL, 'admin', '2021-09-15 19:51:26', NULL, NULL, 0, 0, '1', 0);
-INSERT INTO `sys_permission` VALUES ('1438108190777663490', '1438108188034588674', '成功页', '/page-demo/result/success', 'demo/page/result/success/index', 1, NULL, NULL, 1, NULL, '1', 0, 0, NULL, 1, 0, 0, NULL, NULL, 'admin', '2021-09-15 19:51:26', NULL, NULL, 0, 0, '1', 0);
-INSERT INTO `sys_permission` VALUES ('1438108191356477442', '1438108188034588674', '失败页', '/page-demo/result/fail', 'demo/page/result/fail/index', 1, NULL, NULL, 1, NULL, '1', 1, 0, NULL, 1, 0, 0, NULL, NULL, 'admin', '2021-09-15 19:51:26', NULL, NULL, 0, 0, '1', 0);
-INSERT INTO `sys_permission` VALUES ('1438108192623157249', '1438108188378521602', '个人中心', '/page-demo/account/center', 'demo/page/account/center/index', 1, NULL, NULL, 1, NULL, '1', 0, 0, NULL, 1, 0, 0, NULL, NULL, 'admin', '2021-09-15 19:51:27', NULL, NULL, 0, 0, '1', 0);
-INSERT INTO `sys_permission` VALUES ('1438108193701093378', '1438108188378521602', '个人设置', '/page-demo/account/setting', 'demo/page/account/setting/index', 1, NULL, NULL, 1, NULL, '1', 1, 0, NULL, 1, 0, 0, NULL, NULL, 'admin', '2021-09-15 19:51:27', NULL, NULL, 0, 0, '1', 0);
-INSERT INTO `sys_permission` VALUES ('1438108194992939010', '1438108188542099458', '403', '/page-demo/exception/403', 'sys/exception/NotAccessException', 1, NULL, NULL, 1, NULL, '1', 0, 0, NULL, 1, 0, 0, 0, NULL, 'admin', '2021-09-15 19:51:27', 'admin', '2021-09-18 18:02:47', 0, 0, '1', 0);
-INSERT INTO `sys_permission` VALUES ('1438108195307511809', '1438108188542099458', '404', '/page-demo/exception/404', 'sys/exception/Exception', 1, NULL, NULL, 1, NULL, '1', 1, 0, NULL, 1, 0, 0, NULL, NULL, 'admin', '2021-09-15 19:51:27', NULL, NULL, 0, 0, '1', 0);
-INSERT INTO `sys_permission` VALUES ('1438108195487866881', '1438108188542099458', '500', '/page-demo/exception/500', 'sys/exception/ServerErrorException', 1, NULL, NULL, 1, NULL, '1', 2, 0, NULL, 1, 0, 0, 0, NULL, 'admin', '2021-09-15 19:51:27', 'admin', '2021-09-18 18:04:34', 0, 0, '1', 0);
-INSERT INTO `sys_permission` VALUES ('1438108195638861825', '1438108188542099458', '网络错误', '/page-demo/exception/net-work-error', 'sys/exception/NetworkErrorException', 1, NULL, NULL, 1, NULL, '1', 3, 0, NULL, 1, 0, 0, 0, NULL, 'admin', '2021-09-15 19:51:27', 'admin', '2021-09-18 18:05:05', 0, 0, '1', 0);
-INSERT INTO `sys_permission` VALUES ('1438108195924074497', '1438108188542099458', '无数据', '/page-demo/exception/not-data', 'sys/exception/NotDataErrorException', 1, NULL, NULL, 1, NULL, '1', 4, 0, NULL, 1, 0, 0, 0, NULL, 'admin', '2021-09-15 19:51:27', 'admin', '2021-09-18 18:05:40', 0, 0, '1', 0);
-INSERT INTO `sys_permission` VALUES ('1438108196263813121', '1438108188714065922', '标准列表', '/page-demo/list/basic', 'demo/page/list/basic/index', 1, NULL, NULL, 1, NULL, '1', 0, 0, NULL, 1, 0, 0, NULL, NULL, 'admin', '2021-09-15 19:51:27', NULL, NULL, 0, 0, '1', 0);
-INSERT INTO `sys_permission` VALUES ('1438108196528054273', '1438108188714065922', '卡片列表', '/page-demo/list/card', 'demo/page/list/card/index', 1, NULL, NULL, 1, NULL, '1', 1, 0, NULL, 1, 0, 0, NULL, NULL, 'admin', '2021-09-15 19:51:27', NULL, NULL, 0, 0, '1', 0);
-INSERT INTO `sys_permission` VALUES ('1438108196855209985', '1438108188714065922', '搜索列表', '/page-demo/list/search', 'demo/page/list/search/index', 1, NULL, NULL, 1, NULL, '1', 2, 0, NULL, 1, 0, 0, NULL, NULL, 'admin', '2021-09-15 19:51:28', NULL, NULL, 0, 0, '1', 0);
-INSERT INTO `sys_permission` VALUES ('1438108196993622018', '', '组件&功能', '/comp', 'layouts/default/index', 1, NULL, '/comp/basic', 0, NULL, '1', 11, 0, 'ion:layers-outline', 0, 0, 0, 0, NULL, 'admin', '2021-09-15 19:51:28', 'admin', '2021-11-18 10:48:06', 0, 0, '1', 0);
-INSERT INTO `sys_permission` VALUES ('1438108197270446081', '1438108197958311537', '自定义组件示例', '/comp/jeecg/basic', 'demo/jeecg/index', 1, NULL, NULL, 1, NULL, '1', 0, 0, NULL, 0, 0, 0, NULL, NULL, 'admin', '2021-09-15 19:51:28', NULL, NULL, 0, 0, '1', 0);
-INSERT INTO `sys_permission` VALUES ('1438108197790539778', '1438108197958315557', 'Button组件', '/comp/basic/button', 'demo/comp/button/index', 1, NULL, NULL, 1, NULL, '1', 8, 0, NULL, 1, 0, 0, NULL, NULL, 'admin', '2021-09-15 19:51:28', 'admin', '2021-09-17 09:31:48', 0, 0, '1', 0);
-INSERT INTO `sys_permission` VALUES ('1438108197958311537', '1438108196993622018', 'Jeecg组件示例', '/comp/jeecg', 'layouts/default/index', 1, NULL, '/comp/jeecg/basic', 1, NULL, '1', 1, 0, 'ant-design:sketch-outlined', 0, 0, 0, NULL, NULL, 'admin', '2021-09-15 19:51:28', 'admin', '2021-09-17 15:49:57', 0, 0, '1', 0);
-INSERT INTO `sys_permission` VALUES ('1438108197958311637', '1438108196993622018', '弹框抽屉', '/comp/modal', 'layouts/default/index', 1, NULL, '/comp/modal/basic', 1, NULL, '1', 6, 0, 'ant-design:laptop-outlined', 0, 0, 0, NULL, NULL, 'admin', '2021-09-15 19:51:28', 'admin', '2021-09-17 15:53:10', 0, 0, '1', 0);
-INSERT INTO `sys_permission` VALUES ('1438108197958311677', '1438108196993622018', '第三方组件', '/comp/third', 'layouts/default/index', 1, NULL, '/comp/third/basic', 1, NULL, '1', 7, 0, 'ant-design:slack-outlined', 0, 0, 0, NULL, NULL, 'admin', '2021-09-15 19:51:28', 'admin', '2021-09-17 15:53:31', 0, 0, '1', 0);
-INSERT INTO `sys_permission` VALUES ('1438108197958311937', '1438108196993622018', 'Form示例', '/comp/form', 'layouts/default/index', 1, NULL, '/comp/form/basic', 1, NULL, '1', 2, 0, 'ant-design:pic-left-outlined', 0, 0, 0, NULL, NULL, 'admin', '2021-09-15 19:51:28', 'admin', '2021-09-17 15:50:39', 0, 0, '1', 0);
-INSERT INTO `sys_permission` VALUES ('1438108197958315557', '1438108196993622018', '基础组件', '/comp/basic', 'layouts/default/index', 1, NULL, '/comp/basic', 1, NULL, '1', 1, 0, 'ant-design:insert-row-left-outlined', 0, 0, 0, NULL, NULL, 'admin', '2021-09-15 19:51:28', 'admin', '2021-09-17 15:50:27', 0, 0, '1', 0);
-INSERT INTO `sys_permission` VALUES ('1438108198113501186', '1438108196993622018', 'Table示例', '/comp/table', 'layouts/default/index', 1, NULL, '/comp/table/basic', 1, NULL, '1', 3, 0, 'ant-design:table-outlined', 0, 0, 0, NULL, NULL, 'admin', '2021-09-15 19:51:28', 'admin', '2021-09-17 15:50:51', 0, 0, '1', 0);
-INSERT INTO `sys_permission` VALUES ('1438108198339993602', '1438108197958311677', '动画组件', '/comp/third/transition', 'demo/comp/transition/index', 1, NULL, NULL, 1, NULL, '1', 9, 0, NULL, 1, 0, 0, NULL, NULL, 'admin', '2021-09-15 19:51:28', NULL, NULL, 0, 0, '1', 0);
-INSERT INTO `sys_permission` VALUES ('1438108198679732226', '1438108197958311537', '一对多示例', '/comp/jeecg/oneToMore', 'demo/vextable/index', 1, NULL, NULL, 1, NULL, '1', 6, 0, NULL, 1, 0, 0, NULL, NULL, 'admin', '2021-09-15 19:51:28', NULL, NULL, 0, 0, '1', 0);
-INSERT INTO `sys_permission` VALUES ('1438108198855892993', '1438108197958311677', '图片裁剪', '/comp/third/basic', 'demo/comp/cropper/index', 1, NULL, NULL, 1, NULL, '1', 7, 0, NULL, 1, 0, 0, NULL, NULL, 'admin', '2021-09-15 19:51:28', NULL, NULL, 0, 0, '1', 0);
-INSERT INTO `sys_permission` VALUES ('1438108199120134145', '1438108197958311677', '相对时间', '/comp/third/timestamp', 'demo/comp/time/index', 1, NULL, NULL, 1, NULL, '1', 8, 0, NULL, 1, 0, 0, NULL, NULL, 'admin', '2021-09-15 19:51:28', NULL, NULL, 0, 0, '1', 0);
-INSERT INTO `sys_permission` VALUES ('1438108199304683521', '1438108197958311677', '数字动画', '/comp/third/countTo', 'demo/comp/count-to/index', 1, NULL, NULL, 1, NULL, '1', 9, 0, NULL, 1, 0, 0, NULL, NULL, 'admin', '2021-09-15 19:51:28', NULL, NULL, 0, 0, '1', 0);
-INSERT INTO `sys_permission` VALUES ('1438108199413735425', '1438108196993622018', 'Tree示例', '/comp/tree', 'layouts/default/index', 1, NULL, '/comp/tree/basic', 1, NULL, '1', 4, 0, 'ant-design:partition-outlined', 0, 0, 0, NULL, NULL, 'admin', '2021-09-15 19:51:28', 'admin', '2021-09-17 15:54:17', 0, 0, '1', 0);
-INSERT INTO `sys_permission` VALUES ('1438108199539564546', '1438108196993622018', '编辑器', '/comp/editor', 'layouts/default/index', 1, NULL, '/comp/editor/markdown', 1, NULL, '1', 5, 0, 'ant-design:credit-card-twotone', 0, 0, 0, NULL, NULL, 'admin', '2021-09-15 19:51:28', 'admin', '2021-09-17 15:52:47', 0, 0, '1', 0);
-INSERT INTO `sys_permission` VALUES ('1438108199631839234', '1438108196993622018', '滚动组件', '/comp/scroll', 'layouts/default/index', 1, NULL, '/comp/scroll/basic', 1, NULL, '1', 11, 0, 'ant-design:column-height-outlined', 0, 0, 0, NULL, NULL, 'admin', '2021-09-15 19:51:28', 'admin', '2021-09-17 15:53:43', 0, 0, '1', 0);
-INSERT INTO `sys_permission` VALUES ('1438108200076435458', '1438108197958311637', '弹窗扩展', '/comp/modal/basic', 'demo/comp/modal/index', 1, NULL, NULL, 1, NULL, '1', 12, 0, NULL, 1, 0, 0, NULL, NULL, 'admin', '2021-09-15 19:51:28', NULL, NULL, 0, 0, '1', 0);
-INSERT INTO `sys_permission` VALUES ('1438108200391008257', '1438108197958311637', '抽屉扩展', '/comp/modal/drawer', 'demo/comp/drawer/index', 1, NULL, NULL, 1, NULL, '1', 13, 0, NULL, 1, 0, 0, NULL, NULL, 'admin', '2021-09-15 19:51:28', NULL, NULL, 0, 0, '1', 0);
-INSERT INTO `sys_permission` VALUES ('1438108200672026626', '1438108197958315557', '详情组件', '/comp/desc', 'demo/comp/desc/index', 1, NULL, NULL, 1, NULL, '1', 14, 0, NULL, 1, 0, 0, NULL, NULL, 'admin', '2021-09-15 19:51:28', NULL, NULL, 0, 0, '1', 0);
-INSERT INTO `sys_permission` VALUES ('1438108200802050050', '1438108196993622018', '懒加载组件', '/comp/lazy', 'layouts/default/index', 1, NULL, '/comp/lazy/basic', 1, NULL, '1', 15, 0, 'ant-design:small-dash-outlined', 0, 0, 0, NULL, NULL, 'admin', '2021-09-15 19:51:28', 'admin', '2021-09-17 15:53:59', 0, 0, '1', 0);
-INSERT INTO `sys_permission` VALUES ('1438108200919490562', '1438108196993622018', '验证组件', '/comp/verify', 'layouts/default/index', 1, NULL, '/comp/verify/drag', 1, NULL, '1', 16, 0, 'ant-design:field-binary-outlined', 0, 0, 0, NULL, NULL, 'admin', '2021-09-15 19:51:29', 'admin', '2021-09-17 15:54:36', 0, 0, '1', 0);
-INSERT INTO `sys_permission` VALUES ('1438108201150177281', '1438108197958311677', '二维码组件', '/comp/third/qrcode', 'demo/comp/qrcode/index', 1, NULL, NULL, 1, NULL, '1', 17, 0, NULL, 1, 0, 0, NULL, NULL, 'admin', '2021-09-15 19:51:29', NULL, NULL, 0, 0, '1', 0);
-INSERT INTO `sys_permission` VALUES ('1438108201502498817', '1438108197958311677', '密码强度组件', '/comp/third/strength-meter', 'demo/comp/strength-meter/index', 1, NULL, NULL, 1, NULL, '1', 18, 0, NULL, 1, 0, 0, NULL, NULL, 'admin', '2021-09-15 19:51:29', NULL, NULL, 0, 0, '1', 0);
-INSERT INTO `sys_permission` VALUES ('1438108201712214018', '1438108197958311677', '上传组件', '/comp/third/upload', 'demo/comp/upload/index', 1, NULL, NULL, 1, NULL, '1', 19, 0, NULL, 1, 0, 0, NULL, NULL, 'admin', '2021-09-15 19:51:29', NULL, NULL, 0, 0, '1', 0);
-INSERT INTO `sys_permission` VALUES ('1438108202060341249', '1438108197958311677', 'Loading', '/comp/third/loading', 'demo/comp/loading/index', 1, NULL, NULL, 1, NULL, '1', 20, 0, NULL, 1, 0, 0, NULL, NULL, 'admin', '2021-09-15 19:51:29', NULL, NULL, 0, 0, '1', 0);
-INSERT INTO `sys_permission` VALUES ('1438108202366525441', '1438108197958311937', '基础表单', '/comp/form/basic', 'demo/form/index', 1, NULL, NULL, 1, NULL, '1', 0, 0, NULL, 1, 0, 0, NULL, NULL, 'admin', '2021-09-15 19:51:29', NULL, NULL, 0, 0, '1', 0);
-INSERT INTO `sys_permission` VALUES ('1438108203649982466', '1438108197958311937', 'useForm', '/comp/form/useForm', 'demo/form/UseForm', 1, NULL, NULL, 1, NULL, '1', 1, 0, NULL, 1, 0, 0, NULL, NULL, 'admin', '2021-09-15 19:51:29', NULL, NULL, 0, 0, '1', 0);
-INSERT INTO `sys_permission` VALUES ('1438108203817754625', '1438108197958311937', 'RefForm', '/comp/form/refForm', 'demo/form/RefForm', 1, NULL, NULL, 1, NULL, '1', 2, 0, NULL, 1, 0, 0, NULL, NULL, 'admin', '2021-09-15 19:51:29', NULL, NULL, 0, 0, '1', 0);
-INSERT INTO `sys_permission` VALUES ('1438108204023275521', '1438108197958311937', '可收缩表单', '/comp/form/advancedForm', 'demo/form/AdvancedForm', 1, NULL, NULL, 1, NULL, '1', 3, 0, NULL, 1, 0, 0, NULL, NULL, 'admin', '2021-09-15 19:51:29', NULL, NULL, 0, 0, '1', 0);
-INSERT INTO `sys_permission` VALUES ('1438108204232990721', '1438108197958311937', '表单验证', '/comp/form/ruleForm', 'demo/form/RuleForm', 1, NULL, NULL, 1, NULL, '1', 4, 0, NULL, 1, 0, 0, NULL, NULL, 'admin', '2021-09-15 19:51:29', NULL, NULL, 0, 0, '1', 0);
-INSERT INTO `sys_permission` VALUES ('1438108204400762881', '1438108197958311937', '动态表单', '/comp/form/dynamicForm', 'demo/form/DynamicForm', 1, NULL, NULL, 1, NULL, '1', 5, 0, NULL, 1, 0, 0, NULL, NULL, 'admin', '2021-09-15 19:51:29', NULL, NULL, 0, 0, '1', 0);
-INSERT INTO `sys_permission` VALUES ('1438108204576923649', '1438108197958311937', '自定义组件', '/comp/form/customerForm', 'demo/form/CustomerForm', 1, NULL, NULL, 1, NULL, '1', 6, 0, NULL, 1, 0, 0, NULL, NULL, 'admin', '2021-09-15 19:51:29', NULL, NULL, 0, 0, '1', 0);
-INSERT INTO `sys_permission` VALUES ('1438108204732112898', '1438108197958311937', '表单增删示例', '/comp/form/appendForm', 'demo/form/AppendForm', 1, NULL, NULL, 1, NULL, '1', 7, 0, NULL, 1, 0, 0, NULL, NULL, 'admin', '2021-09-15 19:51:29', NULL, NULL, 0, 0, '1', 0);
-INSERT INTO `sys_permission` VALUES ('1438108205004742657', '1438108198113501186', '基础表格', '/comp/table/basic', 'demo/table/Basic', 1, NULL, NULL, 1, NULL, '1', 0, 0, NULL, 1, 0, 0, NULL, NULL, 'admin', '2021-09-15 19:51:29', NULL, NULL, 0, 0, '1', 0);
-INSERT INTO `sys_permission` VALUES ('1438108205180903426', '1438108198113501186', '树形表格', '/comp/table/treeTable', 'demo/table/TreeTable', 1, NULL, NULL, 1, NULL, '1', 1, 0, NULL, 1, 0, 0, NULL, NULL, 'admin', '2021-09-15 19:51:30', NULL, NULL, 0, 0, '1', 0);
-INSERT INTO `sys_permission` VALUES ('1438108205357064193', '1438108198113501186', '远程加载示例', '/comp/table/fetchTable', 'demo/table/FetchTable', 1, NULL, NULL, 1, NULL, '1', 2, 0, NULL, 1, 0, 0, NULL, NULL, 'admin', '2021-09-15 19:51:30', NULL, NULL, 0, 0, '1', 0);
-INSERT INTO `sys_permission` VALUES ('1438108205587750914', '1438108198113501186', '固定列', '/comp/table/fixedColumn', 'demo/table/FixedColumn', 1, NULL, NULL, 1, NULL, '1', 3, 0, NULL, 1, 0, 0, NULL, NULL, 'admin', '2021-09-15 19:51:30', NULL, NULL, 0, 0, '1', 0);
-INSERT INTO `sys_permission` VALUES ('1438108205742940161', '1438108198113501186', '自定义列', '/comp/table/customerCell', 'demo/table/CustomerCell', 1, NULL, NULL, 1, NULL, '1', 4, 0, NULL, 1, 0, 0, NULL, NULL, 'admin', '2021-09-15 19:51:30', NULL, NULL, 0, 0, '1', 0);
-INSERT INTO `sys_permission` VALUES ('1438108205919100930', '1438108198113501186', '开启搜索区域', '/comp/table/formTable', 'demo/table/FormTable', 1, NULL, NULL, 1, NULL, '1', 5, 0, NULL, 1, 0, 0, NULL, NULL, 'admin', '2021-09-15 19:51:30', NULL, NULL, 0, 0, '1', 0);
-INSERT INTO `sys_permission` VALUES ('1438108206086873089', '1438108198113501186', 'UseTable', '/comp/table/useTable', 'demo/table/UseTable', 1, NULL, NULL, 1, NULL, '1', 6, 0, NULL, 1, 0, 0, NULL, NULL, 'admin', '2021-09-15 19:51:30', NULL, NULL, 0, 0, '1', 0);
-INSERT INTO `sys_permission` VALUES ('1438108206258839553', '1438108198113501186', 'RefTable', '/comp/table/refTable', 'demo/table/RefTable', 1, NULL, NULL, 1, NULL, '1', 7, 0, NULL, 1, 0, 0, NULL, NULL, 'admin', '2021-09-15 19:51:30', NULL, NULL, 0, 0, '1', 0);
-INSERT INTO `sys_permission` VALUES ('1438108206489526274', '1438108198113501186', '多级表头', '/comp/table/multipleHeader', 'demo/table/MultipleHeader', 1, NULL, NULL, 1, NULL, '1', 8, 0, NULL, 1, 0, 0, NULL, NULL, 'admin', '2021-09-15 19:51:30', NULL, NULL, 0, 0, '1', 0);
-INSERT INTO `sys_permission` VALUES ('1438108206661492738', '1438108198113501186', '合并单元格', '/comp/table/mergeHeader', 'demo/table/MergeHeader', 1, NULL, NULL, 1, NULL, '1', 9, 0, NULL, 1, 0, 0, NULL, NULL, 'admin', '2021-09-15 19:51:30', NULL, NULL, 0, 0, '1', 0);
-INSERT INTO `sys_permission` VALUES ('1438108206959288321', '1438108198113501186', '嵌套子表格', '/comp/table/nestedTable', 'demo/table/NestedTable', 1, NULL, NULL, 1, NULL, '1', 10, 0, NULL, 1, 0, 0, NULL, NULL, 'admin', '2021-09-15 19:51:30', NULL, NULL, 0, 0, '1', 0);
-INSERT INTO `sys_permission` VALUES ('1438108207160614913', '1438108198113501186', '可展开表格', '/comp/table/expandTable', 'demo/table/ExpandTable', 1, NULL, NULL, 1, NULL, '1', 11, 0, NULL, 1, 0, 0, NULL, NULL, 'admin', '2021-09-15 19:51:30', NULL, NULL, 0, 0, '1', 0);
-INSERT INTO `sys_permission` VALUES ('1438108207374524418', '1438108198113501186', '定高/头部自定义', '/comp/table/fixedHeight', 'demo/table/FixedHeight', 1, NULL, NULL, 1, NULL, '1', 12, 0, NULL, 1, 0, 0, NULL, NULL, 'admin', '2021-09-15 19:51:30', NULL, NULL, 0, 0, '1', 0);
-INSERT INTO `sys_permission` VALUES ('1438108207563268097', '1438108198113501186', '表尾行合计', '/comp/table/footerTable', 'demo/table/FooterTable', 1, NULL, NULL, 1, NULL, '1', 13, 0, NULL, 1, 0, 0, NULL, NULL, 'admin', '2021-09-15 19:51:30', NULL, NULL, 0, 0, '1', 0);
-INSERT INTO `sys_permission` VALUES ('1438108207793954818', '1438108198113501186', '可编辑单元格', '/comp/table/editCellTable', 'demo/table/EditCellTable', 1, NULL, NULL, 1, NULL, '1', 14, 0, NULL, 1, 0, 0, NULL, NULL, 'admin', '2021-09-15 19:51:30', NULL, NULL, 0, 0, '1', 0);
-INSERT INTO `sys_permission` VALUES ('1438108208024641538', '1438108198113501186', '可编辑行', '/comp/table/editRowTable', 'demo/table/EditRowTable', 1, NULL, NULL, 1, NULL, '1', 15, 0, NULL, 1, 0, 0, NULL, NULL, 'admin', '2021-09-15 19:51:30', NULL, NULL, 0, 0, '1', 0);
-INSERT INTO `sys_permission` VALUES ('1438108208297271297', '1438108198113501186', '权限列', '/comp/table/authColumn', 'demo/table/AuthColumn', 1, NULL, NULL, 1, NULL, '1', 16, 0, NULL, 1, 0, 0, NULL, NULL, 'admin', '2021-09-15 19:51:30', NULL, NULL, 0, 0, '1', 0);
-INSERT INTO `sys_permission` VALUES ('1438108208817364993', '1438108199413735425', '基础树', '/comp/tree/basic', 'demo/tree/index', 1, NULL, NULL, 1, NULL, '1', 0, 0, NULL, 1, 0, 0, NULL, NULL, 'admin', '2021-09-15 19:51:30', NULL, NULL, 0, 0, '1', 0);
-INSERT INTO `sys_permission` VALUES ('1438108208980942850', '1438108199413735425', '可搜索/工具栏', '/comp/tree/editTree', 'demo/tree/EditTree', 1, NULL, NULL, 1, NULL, '1', 1, 0, NULL, 1, 0, 0, NULL, NULL, 'admin', '2021-09-15 19:51:30', NULL, NULL, 0, 0, '1', 0);
-INSERT INTO `sys_permission` VALUES ('1438108209228406785', '1438108199413735425', '函数操作示例', '/comp/tree/actionTree', 'demo/tree/ActionTree', 1, NULL, NULL, 1, NULL, '1', 2, 0, NULL, 1, 0, 0, NULL, NULL, 'admin', '2021-09-15 19:51:30', NULL, NULL, 0, 0, '1', 0);
-INSERT INTO `sys_permission` VALUES ('1438108210117599234', '1438108199539564546', 'Json编辑器', '/comp/editor/json', 'demo/editor/json/index', 1, NULL, NULL, 1, NULL, '1', 0, 0, NULL, 1, 0, 0, NULL, NULL, 'admin', '2021-09-15 19:51:31', NULL, NULL, 0, 0, '1', 0);
-INSERT INTO `sys_permission` VALUES ('1438108210260205570', '1438108199539564546', 'markdown编辑器', '/comp/editor/markdown', NULL, 1, NULL, '/comp/editor/markdown/index', 1, NULL, '1', 1, 0, NULL, 0, 0, 0, NULL, NULL, 'admin', '2021-09-15 19:51:31', NULL, NULL, 0, 0, '1', 0);
-INSERT INTO `sys_permission` VALUES ('1438108211325558785', '1438108210260205570', '基础使用', '/comp/editor/markdown/index', 'demo/editor/markdown/index', 1, NULL, NULL, 1, NULL, '1', 0, 0, NULL, 1, 0, 0, NULL, NULL, 'admin', '2021-09-15 19:51:31', 'admin', '2021-09-16 14:40:59', 0, 0, '1', 0);
-INSERT INTO `sys_permission` VALUES ('1438108211661103106', '1438108210260205570', '嵌入form', '/comp/editor/markdown/editor', 'demo/editor/markdown/Editor', 1, NULL, NULL, 1, NULL, '1', 1, 0, NULL, 1, 0, 0, NULL, NULL, 'admin', '2021-09-15 19:51:31', 'admin', '2021-09-16 14:41:04', 0, 0, '1', 0);
-INSERT INTO `sys_permission` VALUES ('1438108211778543618', '1438108199539564546', '富文本', '/comp/editor/tinymce', NULL, 1, NULL, '/comp/editor/tinymce/index', 1, NULL, '1', 2, 0, NULL, 0, 0, 0, NULL, NULL, 'admin', '2021-09-15 19:51:31', NULL, NULL, 0, 0, '1', 0);
-INSERT INTO `sys_permission` VALUES ('1438108214882328577', '1438108211778543618', '基础使用', '/comp/editor/tinymce/index', 'demo/editor/tinymce/index', 1, NULL, NULL, 1, NULL, '1', 0, 0, NULL, 1, 0, 0, NULL, NULL, 'admin', '2021-09-15 19:51:32', NULL, NULL, 0, 0, '1', 0);
-INSERT INTO `sys_permission` VALUES ('1438108215335313409', '1438108211778543618', '嵌入form', '/comp/editor/tinymce/editor', 'demo/editor/tinymce/Editor', 1, NULL, NULL, 1, NULL, '1', 1, 0, NULL, 1, 0, 0, NULL, NULL, 'admin', '2021-09-15 19:51:32', NULL, NULL, 0, 0, '1', 0);
-INSERT INTO `sys_permission` VALUES ('1438108215511474177', '1438108199631839234', '基础滚动', '/comp/scroll/basic', 'demo/comp/scroll/index', 1, NULL, NULL, 1, NULL, '1', 0, 0, NULL, 1, 0, 0, NULL, NULL, 'admin', '2021-09-15 19:51:32', NULL, NULL, 0, 0, '1', 0);
-INSERT INTO `sys_permission` VALUES ('1438108215687634945', '1438108199631839234', '滚动函数', '/comp/scroll/action', 'demo/comp/scroll/Action', 1, NULL, NULL, 1, NULL, '1', 1, 0, NULL, 1, 0, 0, NULL, NULL, 'admin', '2021-09-15 19:51:32', NULL, NULL, 0, 0, '1', 0);
-INSERT INTO `sys_permission` VALUES ('1438108215989624834', '1438108199631839234', '虚拟滚动', '/comp/scroll/virtualScroll', 'demo/comp/scroll/VirtualScroll', 1, NULL, NULL, 1, NULL, '1', 2, 0, NULL, 1, 0, 0, NULL, NULL, 'admin', '2021-09-15 19:51:32', NULL, NULL, 0, 0, '1', 0);
-INSERT INTO `sys_permission` VALUES ('1438108216300003330', '1438108200802050050', '基础示例', '/comp/lazy/basic', 'demo/comp/lazy/index', 1, NULL, NULL, 1, NULL, '1', 0, 0, NULL, 1, 0, 0, NULL, NULL, 'admin', '2021-09-15 19:51:32', NULL, NULL, 0, 0, '1', 0);
-INSERT INTO `sys_permission` VALUES ('1438108216597798914', '1438108200802050050', '动画效果', '/comp/lazy/transition', 'demo/comp/lazy/Transition', 1, NULL, NULL, 1, NULL, '1', 1, 0, NULL, 1, 0, 0, NULL, NULL, 'admin', '2021-09-15 19:51:32', NULL, NULL, 0, 0, '1', 0);
-INSERT INTO `sys_permission` VALUES ('1438108216971091969', '1438108200919490562', '拖拽校验', '/comp/verify/drag', 'demo/comp/verify/index', 1, NULL, NULL, 1, NULL, '1', 0, 0, NULL, 1, 0, 0, NULL, NULL, 'admin', '2021-09-15 19:51:32', NULL, NULL, 0, 0, '1', 0);
-INSERT INTO `sys_permission` VALUES ('1438108217449242626', '1438108200919490562', '图片还原', '/comp/verify/rotate', 'demo/comp/verify/Rotate', 1, NULL, NULL, 1, NULL, '1', 1, 0, NULL, 1, 0, 0, NULL, NULL, 'admin', '2021-09-15 19:51:32', NULL, NULL, 0, 0, '1', 0);
-INSERT INTO `sys_permission` VALUES ('1438108217562488834', '1438108187455774722', '图表', '/charts', 'layouts/default/index', 1, NULL, '/charts/echarts/map', 0, NULL, '1', 7, 0, 'ion:bar-chart-outline', 0, 0, 0, NULL, NULL, 'admin', '2021-09-15 19:51:32', NULL, NULL, 0, 0, '1', 0);
-INSERT INTO `sys_permission` VALUES ('1438108217860284417', '1438108217562488834', '百度地图', '/charts/baiduMap', 'demo/charts/map/Baidu', 1, NULL, NULL, 1, NULL, '1', 0, 0, NULL, 1, 0, 0, NULL, NULL, 'admin', '2021-09-15 19:51:33', NULL, NULL, 0, 0, '1', 0);
-INSERT INTO `sys_permission` VALUES ('1438108218049028097', '1438108217562488834', '高德地图', '/charts/aMap', 'demo/charts/map/Gaode', 1, NULL, NULL, 1, NULL, '1', 1, 0, NULL, 1, 0, 0, NULL, NULL, 'admin', '2021-09-15 19:51:33', NULL, NULL, 0, 0, '1', 0);
-INSERT INTO `sys_permission` VALUES ('1438108218409738242', '1438108217562488834', 'Echarts', '/charts/echarts', NULL, 1, NULL, '/charts/echarts/map', 1, NULL, '1', 3, 0, NULL, 0, 0, 0, NULL, NULL, 'admin', '2021-09-15 19:51:33', NULL, NULL, 0, 0, '1', 0);
-INSERT INTO `sys_permission` VALUES ('1438108218787225601', '1438108218409738242', '地图', '/charts/echarts/map', 'demo/charts/Map', 1, NULL, NULL, 1, NULL, '1', 0, 0, NULL, 1, 0, 0, NULL, NULL, 'admin', '2021-09-15 19:51:33', NULL, NULL, 0, 0, '1', 0);
-INSERT INTO `sys_permission` VALUES ('1438108219034689538', '1438108218409738242', '折线图', '/charts/echarts/line', 'demo/charts/Line', 1, NULL, NULL, 1, NULL, '1', 1, 0, NULL, 1, 0, 0, NULL, NULL, 'admin', '2021-09-15 19:51:33', NULL, NULL, 0, 0, '1', 0);
-INSERT INTO `sys_permission` VALUES ('1438108219240210434', '1438108218409738242', '饼图', '/charts/echarts/pie', 'demo/charts/Pie', 1, NULL, NULL, 1, NULL, '1', 2, 0, NULL, 1, 0, 0, NULL, NULL, 'admin', '2021-09-15 19:51:33', NULL, NULL, 0, 0, '1', 0);
-INSERT INTO `sys_permission` VALUES ('1438108219445731330', '1438108187455774722', '外部页面', '/frame', 'layouts/default/index', 1, NULL, '/frame/doc', 0, NULL, '1', 8, 0, 'ion:tv-outline', 0, 0, 0, NULL, NULL, 'admin', '2021-09-15 19:51:33', NULL, NULL, 0, 0, '1', 0);
-INSERT INTO `sys_permission` VALUES ('1438108219592531970', '1438108219445731330', '项目文档(内嵌)', '/frame/doc', 'http://vue3.jeecg.com', 1, NULL, NULL, 1, NULL, '1', 0, 0, NULL, 1, 0, 0, 0, NULL, 'admin', '2021-09-15 19:51:33', 'admin', '2021-11-15 17:59:32', 0, 0, '1', 0);
-INSERT INTO `sys_permission` VALUES ('1438108219793858561', '1438108219445731330', 'antVue文档(内嵌)', '/frame/antv', 'https://2x.antdv.com/docs/vue/introduce-cn', 1, NULL, NULL, 1, NULL, '1', 1, 0, NULL, 1, 0, 0, 0, NULL, 'admin', '2021-09-15 19:51:33', 'admin', '2021-11-11 17:11:10', 0, 0, '1', 0);
-INSERT INTO `sys_permission` VALUES ('1438108220137791489', '1438108219445731330', '项目文档(外链)', '/', 'http://vue3.jeecg.com/', 1, NULL, NULL, 1, NULL, '1', 2, 0, NULL, 1, 0, 0, 0, NULL, 'admin', '2021-09-15 19:51:33', 'admin', '2021-10-25 13:46:59', 0, 0, '1', 1);
-INSERT INTO `sys_permission` VALUES ('1438108220418809857', '1438108187455774722', '多级菜单', '/level', 'layouts/default/index', 1, NULL, '/level/menu1/menu1-1/menu1-1-1', 0, NULL, '1', 9, 0, 'ion:menu-outline', 0, 0, 0, NULL, NULL, 'admin', '2021-09-15 19:51:33', NULL, NULL, 0, 0, '1', 0);
-INSERT INTO `sys_permission` VALUES ('1438108220523667458', '1438108220418809857', 'Menu1', '/level/menu1', NULL, 1, NULL, '/level/menu1/menu1-1/menu1-1-1', 1, NULL, '1', 0, 0, NULL, 0, 0, 0, NULL, NULL, 'admin', '2021-09-15 19:51:33', NULL, NULL, 0, 0, '1', 0);
-INSERT INTO `sys_permission` VALUES ('1438108220724994049', '1438108220418809857', 'Menu2', '/level/menu2', 'demo/level/Menu2', 1, NULL, NULL, 1, NULL, '1', 1, 0, NULL, 1, 0, 0, NULL, NULL, 'admin', '2021-09-15 19:51:33', NULL, NULL, 0, 0, '1', 0);
-INSERT INTO `sys_permission` VALUES ('1438108220896960513', '1438108220523667458', 'Menu1-1', '/level/menu1/menu1-1', NULL, 1, NULL, '/level/menu1/menu1-1/menu1-1-1', 1, NULL, '1', 0, 0, NULL, 0, 0, 0, NULL, NULL, 'admin', '2021-09-15 19:51:33', NULL, NULL, 0, 0, '1', 0);
-INSERT INTO `sys_permission` VALUES ('1438108221127647234', '1438108220896960513', 'Menu1-1-1', '/level/menu1/menu1-1/menu1-1-1', 'demo/level/Menu111', 1, NULL, NULL, 1, NULL, '1', 0, 0, NULL, 1, 0, 0, NULL, NULL, 'admin', '2021-09-15 19:51:33', NULL, NULL, 0, 0, '1', 0);
-INSERT INTO `sys_permission` VALUES ('1438108221270253570', '1438108220523667458', 'Menu1-2', '/level/menu1/menu1-2', 'demo/level/Menu12', 1, NULL, NULL, 1, NULL, '1', 1, 0, NULL, 1, 0, 0, NULL, NULL, 'admin', '2021-09-15 19:51:33', NULL, NULL, 0, 0, '1', 0);
-INSERT INTO `sys_permission` VALUES ('1438108221551271937', '', 'Mock示例', '/system', 'layouts/default/index', 1, NULL, '/system/account', 0, NULL, '1', 10, 0, 'ion:settings-outline', 0, 0, 0, NULL, NULL, 'admin', '2021-09-15 19:51:33', NULL, NULL, 0, 0, '1', 0);
-INSERT INTO `sys_permission` VALUES ('1438108221849067522', '1438108221551271937', '测试功能', '/system/test', 'demo/system/test/index', 1, NULL, NULL, 1, NULL, '1', 0, 0, 'ant-design:bulb-outlined', 1, 0, 0, NULL, NULL, 'admin', '2021-09-15 19:51:34', 'admin', '2021-09-17 15:55:36', 0, 0, '1', 0);
-INSERT INTO `sys_permission` VALUES ('1438108222218166273', '1438108221551271937', '账号管理', '/system/account', 'demo/system/account/index', 1, NULL, NULL, 1, NULL, '1', 1, 0, 'ant-design:user-outlined', 1, 0, 0, NULL, NULL, 'admin', '2021-09-15 19:51:34', 'admin', '2021-09-17 15:55:46', 0, 0, '1', 0);
-INSERT INTO `sys_permission` VALUES ('1438108222721482753', '1438108221551271937', '账号详情', '/system/account_detail/:id', 'demo/system/account/AccountDetail', 1, NULL, NULL, 1, NULL, '1', 2, 0, 'ant-design:idcard-twotone', 1, 0, 0, NULL, NULL, 'admin', '2021-09-15 19:51:34', 'admin', '2021-09-17 15:56:12', 0, 0, '1', 0);
-INSERT INTO `sys_permission` VALUES ('1438108223489040385', '1438108221551271937', '部门管理', '/system/dept', 'demo/system/dept/index', 1, NULL, NULL, 1, NULL, '1', 5, 0, 'ant-design:usergroup-add-outlined', 1, 0, 0, NULL, NULL, 'admin', '2021-09-15 19:51:34', 'admin', '2021-09-17 15:56:34', 0, 0, '1', 0);
-INSERT INTO `sys_permission` VALUES ('1438108223661006850', '1438108221551271937', '修改密码', '/system/changePassword', 'demo/system/password/index', 1, NULL, NULL, 1, NULL, '1', 6, 0, 'ant-design:field-number-outlined', 1, 0, 0, NULL, NULL, 'admin', '2021-09-15 19:51:34', 'admin', '2021-09-17 15:56:46', 0, 0, '1', 0);
-INSERT INTO `sys_permission` VALUES ('1438108225263230978', '1438108178010202113', '引导页', '/setup/index', 'demo/setup/index', 1, NULL, NULL, 1, NULL, '1', 12, 0, 'whh:paintroll', 1, 0, 0, NULL, NULL, 'admin', '2021-09-15 19:51:34', 'admin', '2021-09-17 09:02:19', 0, 0, '1', 0);
-INSERT INTO `sys_permission` VALUES ('1438108225451974658', '', '关于', '/about/index', 'sys/about/index', 1, NULL, NULL, 0, NULL, '1', 13, 0, 'simple-icons:about-dot-me', 1, 0, 0, NULL, NULL, 'admin', '2021-09-15 19:51:34', NULL, NULL, 0, 0, '1', 0);
-INSERT INTO `sys_permission` VALUES ('1438115924159881218', '1438108183395688450', 'Tab带参1', '/testTab/id1', 'demo/feat/tab-params/index', 1, NULL, NULL, 1, NULL, '0', 0, 0, NULL, 1, 0, 0, NULL, NULL, 'admin', '2021-09-15 20:22:10', 'admin', '2021-09-16 14:38:32', 0, 0, '1', 0);
-INSERT INTO `sys_permission` VALUES ('1438116003012796418', '1438108183395688450', 'Tab带参2', '/feat/testTab/id2', 'demo/feat/tab-params/index', 1, NULL, NULL, 1, NULL, '0', 1, 0, NULL, 1, 0, 0, NULL, NULL, 'admin', '2021-09-15 20:22:29', NULL, NULL, 0, 0, '1', 0);
-INSERT INTO `sys_permission` VALUES ('1438469604861403137', 'd7d6e2e4e2934f2c9385a623fd98c6f3', '职务管理', '/system/position', 'system/position/index', 1, NULL, NULL, 1, NULL, '0', 5, 0, 'ant-design:database-filled', 1, 0, 0, NULL, NULL, 'admin', '2021-09-16 19:47:33', 'admin', '2021-09-17 15:58:22', 0, 0, NULL, 0);
-INSERT INTO `sys_permission` VALUES ('1438782530717495298', 'd7d6e2e4e2934f2c9385a623fd98c6f3', '分类字典', '/system/category', 'system/category/index', 1, NULL, NULL, 1, NULL, '0', 9, 0, 'ant-design:group-outlined', 1, 0, 0, NULL, NULL, 'admin', '2021-09-17 16:31:01', NULL, NULL, 0, 0, NULL, 0);
-INSERT INTO `sys_permission` VALUES ('1438782641187074050', 'd7d6e2e4e2934f2c9385a623fd98c6f3', '数据字典', '/system/dict', 'system/dict/index', 1, NULL, NULL, 1, NULL, '0', 10, 0, 'ant-design:hdd-twotone', 1, 0, 0, NULL, NULL, 'admin', '2021-09-17 16:31:27', NULL, NULL, 0, 0, NULL, 0);
-INSERT INTO `sys_permission` VALUES ('1438782851980210178', 'd7d6e2e4e2934f2c9385a623fd98c6f3', '通知公告', '/system/notice', 'system/notice/index', 1, NULL, NULL, 1, NULL, '0', 8, 0, 'ant-design:bell-outlined', 1, 0, 0, NULL, NULL, 'admin', '2021-09-17 16:32:17', 'admin', '2021-09-17 16:36:15', 0, 0, NULL, 0);
-INSERT INTO `sys_permission` VALUES ('1438783058792951810', '1438108197958311537', '单表示例', '/system/examples/demo', 'system/examples/demo/index', 1, NULL, NULL, 1, NULL, '0', 1, 0, NULL, 1, 0, 0, 0, NULL, 'admin', '2021-09-17 16:33:07', 'admin', '2021-12-08 14:10:47', 0, 0, NULL, 0);
-INSERT INTO `sys_permission` VALUES ('1439398677984878593', '', '系统监控', '/monitor', 'layouts/RouteView', 1, NULL, NULL, 0, NULL, '0', 3, 0, 'ant-design:video-camera-filled', 0, 0, 0, 0, NULL, 'admin', '2021-09-19 09:19:22', 'admin', '2021-11-15 18:21:14', 0, 0, NULL, 0);
-INSERT INTO `sys_permission` VALUES ('1439399179791409153', '1439398677984878593', '网关路由', '/monitor/route', 'monitor/route/index', 1, NULL, NULL, 1, NULL, '0', 1, 0, 'ant-design:branches-outlined', 1, 0, 0, 0, NULL, 'admin', '2021-09-19 09:21:21', 'admin', '2021-09-19 09:26:42', 0, 0, NULL, 0);
-INSERT INTO `sys_permission` VALUES ('1439488251473993730', '1439398677984878593', '定时任务', '/monitor/quartz', 'monitor/quartz/index', 1, NULL, NULL, 1, NULL, '0', 1, 0, 'ant-design:history-outlined', 1, 0, 0, 0, NULL, 'admin', '2021-09-19 15:15:18', NULL, NULL, 0, 0, NULL, 0);
-INSERT INTO `sys_permission` VALUES ('1439511654494937090', '1439398677984878593', '数据源管理', '/monitor/datasource', 'monitor/datasource/index', 1, NULL, NULL, 1, NULL, '0', 3, 0, 'ant-design:hdd-filled', 1, 0, 0, 0, NULL, 'admin', '2021-09-19 16:48:17', NULL, NULL, 0, 0, NULL, 0);
-INSERT INTO `sys_permission` VALUES ('1439531077792473089', '1439398677984878593', '数据日志', '/monitor/datalog', 'monitor/datalog/index', 1, NULL, NULL, 1, NULL, '0', 4, 0, 'ant-design:funnel-plot-twotone', 1, 0, 0, 0, NULL, 'admin', '2021-09-19 18:05:28', NULL, NULL, 0, 0, NULL, 0);
-INSERT INTO `sys_permission` VALUES ('1439533711676973057', '1439398677984878593', '日志管理', '/monitor/log', 'monitor/log/index', 1, NULL, NULL, 1, NULL, '0', 5, 0, 'ant-design:interaction-outlined', 1, 0, 0, 0, NULL, 'admin', '2021-09-19 18:15:56', 'admin', '2021-09-19 18:16:56', 0, 0, NULL, 0);
-INSERT INTO `sys_permission` VALUES ('1439542701152575489', '1443390062919208961', '我的消息', '/monitor/mynews', 'monitor/mynews/index', 1, NULL, NULL, 1, NULL, '0', 6, 0, 'ant-design:wechat-outlined', 1, 0, 0, 0, NULL, 'admin', '2021-09-19 18:51:40', 'admin', '2021-09-19 18:53:23', 0, 0, NULL, 0);
-INSERT INTO `sys_permission` VALUES ('1439784356766064642', '1439398677984878593', 'SQL监控', '/monitor/druid', '{{ window._CONFIG[\'domianURL\'] }}/druid', 1, NULL, NULL, 1, NULL, '0', 8, 0, 'ant-design:rocket-filled', 1, 0, 0, 0, NULL, 'admin', '2021-09-20 10:51:55', 'admin', '2021-11-15 18:21:20', 0, 0, NULL, 0);
-INSERT INTO `sys_permission` VALUES ('1439797053314342913', '1439398677984878593', '性能监控', '/monitor/server', 'monitor/server/index', 1, NULL, NULL, 1, NULL, '0', 9, 0, 'ant-design:thunderbolt-filled', 1, 0, 0, 0, NULL, 'admin', '2021-09-20 11:42:22', 'admin', '2021-09-20 14:13:14', 0, 0, NULL, 0);
-INSERT INTO `sys_permission` VALUES ('1439839507094740994', '1439398677984878593', 'Redis监控', '/monitor/redis', 'monitor/redis/index', 1, NULL, NULL, 1, NULL, '0', 10, 0, 'ant-design:trademark-outlined', 1, 0, 0, 0, NULL, 'admin', '2021-09-20 14:31:04', NULL, NULL, 0, 0, NULL, 0);
-INSERT INTO `sys_permission` VALUES ('1439842640030113793', '1439398677984878593', '请求追踪', '/monitor/trace', 'monitor/trace/index', 1, NULL, NULL, 1, NULL, '0', 11, 0, 'ant-design:ie-circle-filled', 1, 0, 0, 0, NULL, 'admin', '2021-09-20 14:43:31', NULL, NULL, 0, 0, NULL, 0);
-INSERT INTO `sys_permission` VALUES ('1441340399835742209', '1438108197958311537', '打印示例', '/jeecg/PrintDemo', 'demo/jeecg/PrintDemo', 1, NULL, NULL, 1, NULL, '0', 7, 0, NULL, 1, 0, 0, 0, NULL, 'admin', '2021-09-24 17:55:05', 'admin', '2021-09-24 17:55:20', 0, 0, NULL, 0);
-INSERT INTO `sys_permission` VALUES ('1441357157443371009', '1438108197958311537', '表格合计', '/jeecg/tableTotal', 'demo/jeecg/TableTotal', 1, NULL, NULL, 1, NULL, '0', 8, 0, NULL, 1, 0, 0, 0, NULL, 'admin', '2021-09-24 19:01:40', NULL, NULL, 0, 0, NULL, 0);
-INSERT INTO `sys_permission` VALUES ('1441361249200832513', '1438108197958311537', '异步树表格', '/jeecg/AsyncTreeTable', 'demo/jeecg/AsyncTreeTable', 1, NULL, NULL, 1, NULL, '0', 9, 0, NULL, 1, 0, 0, 0, NULL, 'admin', '2021-09-24 19:17:56', 'admin', '2021-09-26 16:05:55', 0, 0, NULL, 0);
-INSERT INTO `sys_permission` VALUES ('1442055284830769154', 'd7d6e2e4e2934f2c9385a623fd98c6f3', '对象存储', '/system/ossfile', 'system/ossfile/index', 1, NULL, NULL, 1, NULL, '0', 11, 0, 'ant-design:file-add-outlined', 1, 0, 0, 0, NULL, 'jeecg', '2021-09-26 17:15:47', 'jeecg', '2021-09-26 17:18:01', 0, 0, NULL, 0);
-INSERT INTO `sys_permission` VALUES ('1443390062919208961', '', '消息中心', '/message', 'layouts/default/index', 1, NULL, '/message/manage', 0, NULL, '0', 4, 0, 'ant-design:message-outlined', 0, 0, 0, 0, NULL, 'admin', '2021-09-30 09:39:43', 'admin', '2021-11-18 10:47:28', 0, 0, '1', 0);
-INSERT INTO `sys_permission` VALUES ('1443391428723003394', '1443390062919208961', '消息管理', '/message/manage', 'system/message/manage/index', 1, NULL, NULL, 1, NULL, '0', 1, 0, NULL, 1, 0, 0, 0, NULL, 'admin', '2021-09-30 09:45:08', NULL, NULL, 0, 0, NULL, 0);
-INSERT INTO `sys_permission` VALUES ('1443391584864358402', '1443390062919208961', '消息模板管理', '/message/template', 'system/message/template/index', 1, NULL, NULL, 1, NULL, '0', 2, 0, NULL, 1, 0, 0, 0, NULL, 'admin', '2021-09-30 09:45:45', NULL, NULL, 0, 0, NULL, 0);
-INSERT INTO `sys_permission` VALUES ('1446778415130722306', '1438108219445731330', 'JEECG官网', '/', 'http://www.jeecg.com', 0, NULL, NULL, 1, NULL, '0', 1, 0, NULL, 1, 0, 0, 0, NULL, 'jeecg', '2021-10-09 18:03:49', 'admin', '2021-11-15 18:01:26', 0, 0, NULL, 1);
-INSERT INTO `sys_permission` VALUES ('1447535997560909826', '1438108197270446081', '禁用', NULL, NULL, 0, NULL, NULL, 2, 'demo.dbarray', '2', NULL, 0, NULL, 1, 0, 0, 0, NULL, 'admin', '2021-10-11 20:14:10', 'admin', '2021-10-11 20:18:48', 0, 0, '1', 0);
-INSERT INTO `sys_permission` VALUES ('1447763172274495489', '', '统计报表', '/report', 'layouts/default/index', 1, NULL, NULL, 0, NULL, '0', 7, 0, 'ant-design:bar-chart-outlined', 0, 0, 0, 0, NULL, 'jeecg', '2021-10-12 11:16:53', 'jeecg', '2021-10-12 11:17:05', 0, 0, NULL, 0);
-INSERT INTO `sys_permission` VALUES ('1447763517847396354', '1447763172274495489', 'EChartDemo', '/report/chartDemo', 'report/chartdemo/index', 1, NULL, NULL, 1, NULL, '0', 1, 0, NULL, 1, 0, 0, 0, NULL, 'jeecg', '2021-10-12 11:18:15', 'jeecg', '2021-10-14 14:36:38', 0, 0, NULL, 0);
-INSERT INTO `sys_permission` VALUES ('1448252726202859522', '1447763172274495489', '布局统计报表', '/statisticst', 'report/statisticst/index', 1, NULL, NULL, 1, NULL, '0', 2, 0, NULL, 1, 0, 0, 0, NULL, 'jeecg', '2021-10-13 19:42:12', NULL, NULL, 0, 0, NULL, 0);
-INSERT INTO `sys_permission` VALUES ('1449995470942593026', '1438108221551271937', '测试tree', '/system/testtree', 'demo/system/zyf/index', 1, NULL, NULL, 1, NULL, '0', 1, 0, 'ant-design:alert-filled', 1, 0, 0, 0, NULL, 'admin', '2021-10-18 15:07:14', 'admin', '2021-10-18 15:09:16', 0, 0, NULL, 0);
-INSERT INTO `sys_permission` VALUES ('1450308897429536769', '1438108197958311537', 'JVxeTable示例', '/jeecg/j-vxe-table-demo', 'demo/jeecg/JVxeTableDemo/index', 1, NULL, NULL, 1, NULL, '0', 10, 0, NULL, 0, 0, 0, 0, NULL, 'admin', '2021-10-19 11:52:41', 'admin', '2021-10-19 11:54:46', 0, 0, NULL, 0);
-INSERT INTO `sys_permission` VALUES ('1452508868884353026', '1456520526287917057', '报表设计', '/report', '{{ window._CONFIG[\'domianURL\'] }}/jmreport/list?token=${token}', 1, NULL, NULL, 1, NULL, '0', 1, 0, 'ant-design:radar-chart-outlined', 1, 0, 0, 0, NULL, 'admin', '2021-10-25 13:34:35', 'admin', '2021-11-05 15:19:33', 0, 0, '1', 1);
-INSERT INTO `sys_permission` VALUES ('1453250018282573826', '1438108197958311537', '一对多内嵌', '/innerTable', 'demo/jeecg/InnerExpandTable', 1, NULL, NULL, 1, NULL, '0', 12, 0, NULL, 1, 0, 0, 0, NULL, 'admin', '2021-10-27 14:39:39', 'admin', '2021-10-27 14:40:29', 0, 0, NULL, 0);
-INSERT INTO `sys_permission` VALUES ('1454031324835807233', '1450308897429536769', '综合示例', '/jeecg/j-vxe-table-demo/normal', 'demo/jeecg/JVxeTableDemo/index', 1, NULL, NULL, 1, NULL, '0', 1, 0, NULL, 1, 0, 0, 0, NULL, 'admin', '2021-10-29 18:24:17', 'admin', '2021-10-29 18:25:28', 0, 0, NULL, 0);
-INSERT INTO `sys_permission` VALUES ('1454031820661260289', '1450308897429536769', '即时保存', '/jeecg/j-vxe-table-demo/jsbc', 'demo/jeecg/JVxeTableDemo/func-demo/JSBCDemo', 1, NULL, NULL, 1, NULL, '0', 2, 0, NULL, 1, 0, 0, 0, NULL, 'admin', '2021-10-29 18:26:15', NULL, NULL, 0, 0, NULL, 0);
-INSERT INTO `sys_permission` VALUES ('1454034512171302914', '1450308897429536769', '无痕刷新', '/jeecg/j-vxe-table-demo/whsx', 'demo/jeecg/JVxeTableDemo/func-demo/SocketReload', 1, NULL, NULL, 1, NULL, '0', 3, 0, NULL, 1, 0, 0, 0, NULL, 'admin', '2021-10-29 18:36:57', NULL, NULL, 0, 0, NULL, 0);
-INSERT INTO `sys_permission` VALUES ('1455019819440021505', '1450308897429536769', '弹出子表', '/jeecg/j-vxe-table-demo/tczb', 'demo/jeecg/JVxeTableDemo/func-demo/PopupSubTable', 1, NULL, NULL, 1, NULL, '0', 4, 0, NULL, 1, 0, 0, 0, NULL, 'admin', '2021-11-01 11:52:13', 'admin', '2021-11-01 11:52:19', 0, 0, NULL, 0);
-INSERT INTO `sys_permission` VALUES ('1455067599277662209', '1450308897429536769', '布局模板', '/jeecg/j-vxe-table-demo/layout', 'demo/jeecg/JVxeTableDemo/layout-demo/index', 1, NULL, NULL, 1, NULL, '0', 5, 0, NULL, 1, 0, 0, 0, NULL, 'admin', '2021-11-01 15:02:04', NULL, NULL, 0, 0, NULL, 0);
-INSERT INTO `sys_permission` VALUES ('1455735714507472898', 'd7d6e2e4e2934f2c9385a623fd98c6f3', '通讯录', '/address', 'system/address/index', 1, NULL, NULL, 1, NULL, '0', 10, 0, 'ant-design:book-outlined', 1, 0, 0, 0, NULL, 'admin', '2021-11-03 11:16:55', 'admin', '2021-11-04 19:40:19', 0, 0, NULL, 0);
-INSERT INTO `sys_permission` VALUES ('1456520526287917057', '', '报表设计', '/report', 'layouts/default/index', 1, NULL, NULL, 0, NULL, '0', 4, 0, 'ant-design:project-outlined', 0, 0, 0, 0, NULL, 'admin', '2021-11-05 15:15:28', 'admin', '2021-11-05 15:17:33', 0, 0, NULL, 0);
-INSERT INTO `sys_permission` VALUES ('1458389305235984385', '1438108197958311537', '一对多ERP', '/erplist', 'demo/jeecg/erplist/index', 1, NULL, NULL, 1, NULL, '0', 11, 0, '', 1, 0, 0, 0, NULL, 'admin', '2021-11-10 19:01:21', 'admin', '2021-11-30 14:06:53', 0, 0, NULL, 0);
-INSERT INTO `sys_permission` VALUES ('190c2b43bec6a5f7a4194a85db67d96a', 'd7d6e2e4e2934f2c9385a623fd98c6f3', '角色管理', '/system/role', 'system/role/index', 1, NULL, NULL, 1, NULL, NULL, 2, 0, 'ant-design:solution', 1, 1, 0, NULL, NULL, NULL, '2018-12-25 20:34:38', 'admin', '2021-09-17 15:58:00', 0, 0, NULL, 0);
-INSERT INTO `sys_permission` VALUES ('1a0811914300741f4e11838ff37a1d3a', '3f915b2769fc80648e92d04e84ca059d', '手机号禁用', '', '', 0, NULL, NULL, 2, 'user:form:phone', '2', 1, 0, NULL, 1, NULL, 0, NULL, NULL, 'admin', '2019-05-11 17:19:30', 'admin', '2019-05-11 18:00:22', 0, 0, '1', NULL);
-INSERT INTO `sys_permission` VALUES ('3f915b2769fc80648e92d04e84ca059d', 'd7d6e2e4e2934f2c9385a623fd98c6f3', '用户管理', '/system/user', 'system/user/index', 1, NULL, NULL, 1, NULL, NULL, 1, 0, 'ant-design:user', 0, 1, 0, NULL, NULL, NULL, '2018-12-25 20:34:38', 'sunjianlei', '2021-05-08 09:57:31', 0, 0, NULL, 0);
-INSERT INTO `sys_permission` VALUES ('45c966826eeff4c99b8f8ebfe74511fc', 'd7d6e2e4e2934f2c9385a623fd98c6f3', '部门管理', '/system/depart', 'system/depart/index', 1, NULL, NULL, 1, NULL, NULL, 3, 0, 'ant-design:team', 1, 0, 0, NULL, NULL, 'admin', '2019-01-29 18:47:40', 'admin', '2021-09-17 15:58:13', 0, 0, NULL, 0);
-INSERT INTO `sys_permission` VALUES ('5c2f42277948043026b7a14692456828', 'd7d6e2e4e2934f2c9385a623fd98c6f3', '我的部门', '/system/depart-user', 'system/departUser/index', 1, NULL, NULL, 1, NULL, NULL, 4, 0, 'ant-design:home-outlined', 1, 0, 0, NULL, NULL, 'admin', '2019-04-17 15:12:24', 'admin', '2021-09-17 15:58:41', 0, 0, NULL, 0);
-INSERT INTO `sys_permission` VALUES ('9502685863ab87f0ad1134142788a385', '1438108176273760258', '首页', '/dashboard/analysis', 'dashboard/Analysis', 1, NULL, NULL, 1, NULL, NULL, 1, 0, 'ant-design:bank-filled', 1, 1, 0, NULL, NULL, NULL, '2018-12-25 20:34:38', 'admin', '2021-09-17 15:43:16', 0, 0, NULL, 0);
-INSERT INTO `sys_permission` VALUES ('d7d6e2e4e2934f2c9385a623fd98c6f3', '', '系统管理', '/isystem', 'layouts/RouteView', 1, NULL, NULL, 0, NULL, NULL, 2, 0, 'ant-design:setting', 0, 0, 0, NULL, NULL, NULL, '2018-12-25 20:34:38', 'admin', '2020-01-07 11:00:45', 0, 0, NULL, 0);
-
-delete from sys_permission where id = '1449995470942593026';
-
--- 角色授权vue3的菜单
-
-
--- online低代码菜单(online表单、online报表)
-INSERT INTO `sys_permission` (`id`, `parent_id`, `name`, `url`, `component`, `is_route`, `component_name`, `redirect`, `menu_type`, `perms`, `perms_type`, `sort_no`, `always_show`, `icon`, `is_leaf`, `keep_alive`, `hidden`, `hide_tab`, `description`, `create_by`, `create_time`, `update_by`, `update_time`, `del_flag`, `rule_flag`, `status`, `internal_or_external`) VALUES ('1455100420297859074', '', '在线开发', '/online', 'layouts/default/index', 1, NULL, '/online/cgform', 0, NULL, '0', 2.00, 0, 'ant-design:cloud-outlined', 0, 0, 0, 0, NULL, 'admin', '2021-11-01 17:12:29', 'admin', '2022-05-11 16:38:26', 0, 0, NULL, 0);
-INSERT INTO `sys_permission` (`id`, `parent_id`, `name`, `url`, `component`, `is_route`, `component_name`, `redirect`, `menu_type`, `perms`, `perms_type`, `sort_no`, `always_show`, `icon`, `is_leaf`, `keep_alive`, `hidden`, `hide_tab`, `description`, `create_by`, `create_time`, `update_by`, `update_time`, `del_flag`, `rule_flag`, `status`, `internal_or_external`) VALUES ('1455101470794850305', '1455100420297859074', 'Online表单开发', '/online/cgform', 'super/online/cgform/index', 1, NULL, NULL, 1, NULL, '0', 1.00, 0, NULL, 1, 0, 0, 0, NULL, 'admin', '2021-11-01 17:16:40', 'admin', '2022-04-04 18:36:25', 0, 0, NULL, 0);
-INSERT INTO `sys_permission` (`id`, `parent_id`, `name`, `url`, `component`, `is_route`, `component_name`, `redirect`, `menu_type`, `perms`, `perms_type`, `sort_no`, `always_show`, `icon`, `is_leaf`, `keep_alive`, `hidden`, `hide_tab`, `description`, `create_by`, `create_time`, `update_by`, `update_time`, `del_flag`, `rule_flag`, `status`, `internal_or_external`) VALUES ('1457678003102879745', '1455100420297859074', '系统编码规则', '/system/fillrule', 'system/fillRule/index', 1, NULL, NULL, 1, NULL, '0', 9.00, 0, NULL, 1, 0, 0, 0, NULL, 'admin', '2021-11-08 19:54:53', 'admin', '2021-11-18 10:49:40', 0, 0, NULL, 0);
-INSERT INTO `sys_permission` (`id`, `parent_id`, `name`, `url`, `component`, `is_route`, `component_name`, `redirect`, `menu_type`, `perms`, `perms_type`, `sort_no`, `always_show`, `icon`, `is_leaf`, `keep_alive`, `hidden`, `hide_tab`, `description`, `create_by`, `create_time`, `update_by`, `update_time`, `del_flag`, `rule_flag`, `status`, `internal_or_external`) VALUES ('1458353686530232321', '1455100420297859074', '系统校验规则', '/system/checkrule', 'system/checkRule/index', 1, NULL, NULL, 1, NULL, '0', 15.00, 0, NULL, 1, 0, 0, 0, NULL, 'admin', '2021-11-10 16:39:48', 'admin', '2021-11-18 10:49:48', 0, 0, NULL, 0);
-INSERT INTO `sys_permission` (`id`, `parent_id`, `name`, `url`, `component`, `is_route`, `component_name`, `redirect`, `menu_type`, `perms`, `perms_type`, `sort_no`, `always_show`, `icon`, `is_leaf`, `keep_alive`, `hidden`, `hide_tab`, `description`, `create_by`, `create_time`, `update_by`, `update_time`, `del_flag`, `rule_flag`, `status`, `internal_or_external`) VALUES ('1460888189937176577', '1455100420297859074', 'Online报表配置', '/online/cgreport', 'super/online/cgreport/index', 1, NULL, NULL, 1, NULL, '0', 2.00, 0, NULL, 1, 0, 0, 0, NULL, 'admin', '2021-11-17 16:31:01', 'admin', '2021-12-08 10:55:32', 0, 0, NULL, 0);
-INSERT INTO `sys_permission` (`id`, `parent_id`, `name`, `url`, `component`, `is_route`, `component_name`, `redirect`, `menu_type`, `perms`, `perms_type`, `sort_no`, `always_show`, `icon`, `is_leaf`, `keep_alive`, `hidden`, `hide_tab`, `description`, `create_by`, `create_time`, `update_by`, `update_time`, `del_flag`, `rule_flag`, `status`, `internal_or_external`) VALUES ('1461270075543347202', '1455100420297859074', 'Online表单视图', '/online/copyform/:code', 'super/online/cgform/CgformCopyList', 1, NULL, NULL, 1, NULL, '0', 99.00, 0, NULL, 1, 0, 1, 0, NULL, 'admin', '2021-11-18 17:48:30', NULL, NULL, 0, 0, NULL, 0);
-INSERT INTO `sys_permission` (`id`, `parent_id`, `name`, `url`, `component`, `is_route`, `component_name`, `redirect`, `menu_type`, `perms`, `perms_type`, `sort_no`, `always_show`, `icon`, `is_leaf`, `keep_alive`, `hidden`, `hide_tab`, `description`, `create_by`, `create_time`, `update_by`, `update_time`, `del_flag`, `rule_flag`, `status`, `internal_or_external`) VALUES ('1461291438825558017', '1455100420297859074', 'AUTO在线报表', '/online/cgreport/:id', 'super/online/cgreport/auto/OnlCgReportList', 1, NULL, NULL, 1, NULL, '0', 2.00, 0, NULL, 1, 0, 1, 0, NULL, 'admin', '2021-11-18 19:13:23', 'admin', '2021-11-19 20:16:13', 0, 0, NULL, 0);
-INSERT INTO `sys_permission` (`id`, `parent_id`, `name`, `url`, `component`, `is_route`, `component_name`, `redirect`, `menu_type`, `perms`, `perms_type`, `sort_no`, `always_show`, `icon`, `is_leaf`, `keep_alive`, `hidden`, `hide_tab`, `description`, `create_by`, `create_time`, `update_by`, `update_time`, `del_flag`, `rule_flag`, `status`, `internal_or_external`) VALUES ('1465686870713782273', '1455100420297859074', 'AUTO在线表单', '/online/cgformList/:id', 'super/online/cgform/auto/default/OnlineAutoList', 1, NULL, NULL, 1, NULL, '0', 5.00, 0, NULL, 1, 0, 1, 0, NULL, 'admin', '2021-11-30 22:19:16', NULL, NULL, 0, 0, NULL, 0);
-INSERT INTO `sys_permission` (`id`, `parent_id`, `name`, `url`, `component`, `is_route`, `component_name`, `redirect`, `menu_type`, `perms`, `perms_type`, `sort_no`, `always_show`, `icon`, `is_leaf`, `keep_alive`, `hidden`, `hide_tab`, `description`, `create_by`, `create_time`, `update_by`, `update_time`, `del_flag`, `rule_flag`, `status`, `internal_or_external`) VALUES ('1509417558230999041', '1455100420297859074', 'AUTO树表单列表', '/online/cgformTreeList/:id', 'super/online/cgform/auto/tree/OnlineAutoTreeList', 1, NULL, NULL, 1, NULL, '0', 5.00, 0, NULL, 1, 0, 1, 0, NULL, 'admin', '2022-03-31 14:29:24', NULL, NULL, 0, 0, NULL, 0);

+ 0 - 13
docs/从vue2切换到vue3前端文档.md

@@ -1,13 +0,0 @@
-## 如何切换到 Vue3前端
-
-- 第一步:执行执行脚本 `Vue3升级脚本_mysql.sql`。
-
-> 这个sql脚本做了什么?
-> - 1、把原来的表名sys_permission改为sys_permission_v2
-> - 2、插入了新的sys_permission数据
->
-> 因为vue3和vue2的菜单路由配置不一样,所以当前是通过切换表来实现vue3和vue2的切换。
-
-
-- 第二步:登录进系统,给admin角色分配所有的菜单
-- 第三步:退出登录即可

+ 16 - 0
docs/切换到vue3前端路由.md

@@ -0,0 +1,16 @@
+## 切换到 Vue3菜单路由
+
+- 第一步:执行SQL脚本
+```
+alter table sys_permission rename as sys_permission_v2;
+alter table sys_permission_v3 rename as sys_permission;
+```
+
+> 这个 sql 脚本做了什么?
+> - 1、把表名 sys_permission 备份改为 sys_permission_v2
+> - 2、把 sys_permission_v3 改为 sys_permission
+> 说明:因为 vue3 和 vue2 的菜单配置不一样,所以通过切换表来实现 vue3 和 vue2 的切换。
+
+- 第二步:登录进系统
+
+> 从 jeecgboot3.3.0 版本默认 vue3 和 vue2 的权限都已经分配好, 不需要再手工授权。

+ 6 - 9
package.json

@@ -1,6 +1,6 @@
 {
   "name": "jeecgboot-vue3",
-  "version": "1.3.0",
+  "version": "3.3.0",
   "author": {
     "name": "jeecg",
     "email": "jeecgos@163.com",
@@ -70,14 +70,15 @@
     "vue-cropperjs": "^5.0.0",
     "vue-i18n": "^9.1.9",
     "vue-infinite-scroll": "^2.0.2",
-    "vue-print-nb-jeecg": "^1.0.10",
+    "vue-print-nb-jeecg": "^1.0.11",
     "vue-router": "^4.0.12",
     "vue-types": "^4.1.1",
     "vuedraggable": "^4.1.0",
     "vxe-table": "4.1.0",
     "vxe-table-plugin-antd": "^3.0.3",
     "xe-utils": "^3.3.1",
-    "vue-json-pretty": "^2.0.4"
+    "vue-json-pretty": "^2.0.4",
+    "xss": "^1.0.13"
   },
   "devDependencies": {
     "@commitlint/cli": "^13.2.1",
@@ -195,10 +196,7 @@
         "codemirror/addon/hint/show-hint.js",
         "codemirror/addon/selection/active-line.js",
         "codemirror/mode/clike/clike.js",
-        "codemirror/mode/css/css",
         "codemirror/mode/css/css.js",
-        "codemirror/mode/htmlmixed/htmlmixed",
-        "codemirror/mode/javascript/javascript",
         "codemirror/mode/javascript/javascript.js",
         "codemirror/mode/markdown/markdown.js",
         "codemirror/mode/python/python.js",
@@ -275,14 +273,13 @@
         "vite-plugin-theme/es/colorUtils",
         "vue",
         "vue-i18n",
-        "vue-json-pretty",
         "vue-print-nb-jeecg/src/printarea",
         "vue-router",
         "vue-types",
-        "vuedraggable",
         "vxe-table",
         "vxe-table-plugin-antd",
-        "xe-utils"
+        "xe-utils",
+        "xss"
       ]
     }
   }

+ 2 - 0
src/components/Button/src/PopConfirmButton.vue

@@ -6,8 +6,10 @@
   import { omit } from 'lodash-es';
   import { useAttrs } from '/@/hooks/core/useAttrs';
   import { useI18n } from '/@/hooks/web/useI18n';
+  import { propTypes } from '/@/utils/propTypes';
 
   const props = {
+    class: propTypes.any,
     /**
      * Whether to enable the drop-down menu
      * @default: true

+ 0 - 41
src/components/Button/src/UploadButton.vue

@@ -1,41 +0,0 @@
-<template>
-  <a-upload name="file" :showUploadList="false" :customRequest="(file) => onClick(file)">
-    <Button :type="type" :class="getButtonClass">
-      <template #default="data">
-        <Icon :icon="preIcon" v-if="preIcon" :size="iconSize" />
-        <slot v-bind="data || {}"></slot>
-        <Icon :icon="postIcon" v-if="postIcon" :size="iconSize" />
-      </template>
-    </Button>
-  </a-upload>
-</template>
-
-<script lang="ts">
-  import { defineComponent } from 'vue';
-  export default defineComponent({
-    name: 'JUploadButton',
-    inheritAttrs: false,
-  });
-</script>
-<script lang="ts" setup>
-  import { computed, unref } from 'vue';
-  import { Button } from 'ant-design-vue';
-  import Icon from '/@/components/Icon/src/Icon.vue';
-  import { buttonProps } from './props';
-  import { useAttrs } from '/@/hooks/core/useAttrs';
-  const props = defineProps(buttonProps);
-  // get component class
-  const attrs = useAttrs({ excludeDefaultKeys: false });
-  const getButtonClass = computed(() => {
-    const { color, disabled } = props;
-    return [
-      {
-        [`ant-btn-${color}`]: !!color,
-        [`is-disabled`]: disabled,
-      },
-    ];
-  });
-
-  // get inherit binding value
-  const getBindValue = computed(() => ({ ...unref(attrs), ...props }));
-</script>

+ 1 - 1
src/components/Dropdown/src/Dropdown.vue

@@ -6,7 +6,7 @@
     <template #overlay>
       <a-menu :class="[`${prefixCls}-menu`]" :selectedKeys="selectedKeys">
         <template v-for="item in dropMenuList" :key="`${item.event}`">
-          <a-menu-item v-bind="getAttr(item.event)" @click="handleClickMenu(item)" :disabled="item.disabled" :class="[{ 'is-pop-confirm': item.popConfirm }]">
+          <a-menu-item v-bind="getAttr(item.event)" @click="handleClickMenu(item)" :disabled="item.disabled" :class="[{ 'is-pop-confirm': item.popConfirm }, item.class ?? []]">
             <a-popconfirm v-if="popconfirm && item.popConfirm" v-bind="getPopConfirmAttrs(item.popConfirm)">
               <template #icon v-if="item.popConfirm.icon">
                 <Icon :icon="item.popConfirm.icon" />

+ 160 - 0
src/components/Form/src/components/DetailForm.vue

@@ -0,0 +1,160 @@
+<template>
+  <div :class="formContainerClass">
+    <a-row>
+      <a-col v-for="(item, index) in schemas" :key="index" :span="getItemSpan(item)">
+        <div class="detail-item">
+          <div class="item-title" :title="item.label"> {{ item.label }}: </div>
+          <div class="item-content" v-if="item.isHtml" v-html="detailFormData[item.field]"></div>
+          <div class="item-content" v-else-if="item.isImage">
+            <div class="ant-upload-list ant-upload-list-picture-card">
+              <template v-for="url in detailFormData[item.field]">
+                <div class="ant-upload-list-picture-card-container" style="margin-top: 8px">
+                  <span>
+                    <div class="ant-upload-list-item ant-upload-list-item-done ant-upload-list-item-list-type-picture-card" data-has-actions="true">
+                      <div class="ant-upload-list-item-info">
+                        <img :src="url" alt="图片不存在" class="ant-upload-list-item-image" />
+                      </div>
+                      <span class="ant-upload-list-item-actions">
+                        <download-outlined @click="handleDownloadFile(url)" />
+                        <eye-outlined @click="handleViewImage(item.field)" />
+                      </span>
+                    </div>
+                  </span>
+                </div>
+              </template>
+            </div>
+          </div>
+          <div class="item-content" v-else-if="item.isFile">
+            <div class="ant-upload-list ant-upload-list-text">
+              <template v-for="url in detailFormData[item.field]">
+                <div class="">
+                  <span>
+                    <div class="ant-upload-list-item ant-upload-list-item-done ant-upload-list-item-list-type-text">
+                      <div class="ant-upload-list-item-info">
+                        <span>
+                          <paper-clip-outlined />
+                          <a :href="url" target="_blank" rel="noopener noreferrer" class="ant-upload-list-item-name ant-upload-list-item-name-icon-count-1">
+                            {{ getFilename(url) }}
+                          </a>
+                          <span class="ant-upload-list-item-card-actions">
+                            <download-outlined @click="handleDownloadFile(url)" />
+                          </span>
+                        </span>
+                      </div>
+                    </div>
+                  </span>
+                </div>
+              </template>
+            </div>
+          </div>
+          <div v-else class="item-content">
+            {{ detailFormData[item.field] }}
+          </div>
+        </div>
+      </a-col>
+    </a-row>
+  </div>
+</template>
+
+<script lang="ts">
+  import { defineComponent } from 'vue';
+  import { propTypes } from '/@/utils/propTypes';
+  import { useDetailForm } from '../hooks/useDetailForm';
+  import { DownloadOutlined, EyeOutlined, PaperClipOutlined } from '@ant-design/icons-vue';
+
+  export default defineComponent({
+    name: 'DetailForm',
+    components: {
+      DownloadOutlined,
+      EyeOutlined,
+      PaperClipOutlined,
+    },
+    props: {
+      span: propTypes.number.def(24),
+      //表单配置
+      schemas: propTypes.array.def([]),
+      //表单数据
+      data: propTypes.object.def({}),
+      containerClass: propTypes.string.def(''),
+    },
+    setup(props) {
+      const { formContainerClass, detailFormData, getItemSpan, handleDownloadFile, handleViewImage, getFilename } = useDetailForm(props);
+      return {
+        formContainerClass,
+        detailFormData,
+        getItemSpan,
+        handleDownloadFile,
+        handleViewImage,
+        getFilename,
+      };
+    },
+  });
+</script>
+
+<style scoped lang="less">
+  .jeecg-detail-form {
+    border: 1px solid #f0f0f0;
+    border-left: none;
+    border-bottom: none;
+    .detail-item {
+      display: flex;
+      flex-direction: row;
+      align-items: stretch;
+      line-height: 24px;
+      border-bottom: 1px solid #f0f0f0;
+      height: 100%;
+      .item-title {
+        display: flex;
+        align-items: center;
+        justify-content: flex-end;
+        flex-shrink: 0;
+        flex-grow: 0;
+        min-width: 100px;
+        width: 20%;
+        max-width: 220px;
+        background-color: #fafafa;
+        border-right: 1px solid #f0f0f0;
+        /* border-left: 1px solid #f0f0f0;*/
+        padding: 10px 0;
+        white-space: nowrap;
+        text-overflow: ellipsis;
+        overflow: hidden;
+      }
+      .item-content {
+        border-right: 1px solid #f0f0f0;
+        flex-grow: 1;
+        padding-left: 10px;
+        display: flex;
+        align-items: center;
+        justify-content: flex-start;
+        .anticon {
+          &:hover {
+            color: #40a9ff;
+          }
+        }
+
+        .detail-image-container {
+          box-sizing: border-box;
+          margin: 0;
+          padding: 0;
+          color: #000000d9;
+          font-size: 14px;
+          font-variant: tabular-nums;
+          list-style: none;
+          font-feature-settings: 'tnum';
+          line-height: 1.5715;
+          .image-item {
+            display: inline-block;
+            width: 104px;
+            height: 104px;
+            margin: 5px;
+            border: 1px solid #f0f0f0;
+            vertical-align: top;
+            img {
+            }
+          }
+        }
+      }
+    }
+  }
+</style>

+ 542 - 0
src/components/Form/src/hooks/useDetailForm.ts

@@ -0,0 +1,542 @@
+import { FormSchema, RenderCallbackParams } from '/@/components/Form';
+import { computed, ref, watch } from 'vue';
+import { getDictItemsByCode } from '/@/utils/dict';
+import { filterMultiDictText } from '/@/utils/dict/JDictSelectUtil';
+import { initDictOptions } from '/@/utils/dict/index';
+import { loadDictItem, queryDepartTreeSync, getUserList } from '/@/api/common/api';
+import { defHttp } from '/@/utils/http/axios';
+import { FieldExtends } from '/@/views/super/online/cgform/types/onlineRender';
+import { getAreaTextByCode } from '/@/components/Form/src/utils/Area';
+import { JVxeTableInstance } from '/@/components/jeecg/JVxeTable/types';
+import { handleLinkDown, LINK_DOWN, OnlSubTab, useOnlineVxeTableColumns } from '/@/views/super/online/cgform/hooks/auto/useAutoForm';
+import { pick } from 'lodash-es';
+import { getFileAccessHttpUrl } from '/@/utils/common/compUtils';
+import { createImgPreview } from '/@/components/Preview/index';
+import { useMessage } from '/@/hooks/web/useMessage';
+
+export interface DetailFormSchema {
+  field: string;
+  label: string;
+  span?: number;
+  view?: string;
+  isHtml?: boolean;
+  isImage?: boolean;
+  isFile?: boolean;
+  order?: any;
+  dictTable?: string;
+  dictText?: string;
+  dictCode?: string;
+  dict?: string;
+  fieldExtendJson?: string;
+  ifShow?: boolean | ((renderCallbackParams: RenderCallbackParams) => boolean);
+}
+
+/*interface DetailFormProps {
+  span?: number;
+  schemas?: DetailFormSchema[];
+  data?: any;
+  containerClass?: string;
+}*/
+
+export function useDetailForm(props: any) {
+  console.log(props);
+  const dictOptionsMap = {};
+  const currentLinkFields: string[] = [];
+  const detailFormData = ref({});
+  const { createMessage } = useMessage();
+
+  const formContainerClass = computed(() => {
+    if (props.containerClass) {
+      return `jeecg-detail-form ${props.containerClass}`;
+    } else {
+      return 'jeecg-detail-form';
+    }
+  });
+
+  watch(
+    () => props.data,
+    async (formData) => {
+      if (formData) {
+        let arr = props.schemas;
+        let temp = {};
+        if (arr && arr.length > 0) {
+          for (let item of arr) {
+            let field = item.field;
+            try {
+              temp[field] = await getItemContent(item);
+            } catch (e) {
+              console.error('字段【' + field + '】文本获取失败', e);
+            }
+          }
+        }
+        detailFormData.value = temp;
+        console.log('23345', detailFormData.value);
+      }
+    },
+    { deep: true, immediate: true }
+  );
+
+  async function getItemContent(item) {
+    let formData = props.data;
+    if (formData) {
+      let value = formData[item.field];
+      if (!value && value !== '0' && value !== 0) {
+        return '';
+      }
+      let str = value;
+      let view = item.view;
+      if (view == 'list' || view == 'radio' || view == 'checkbox' || view == 'list_multi') {
+        str = await getSelectText(item, formData);
+      } else if (view == 'sel_search') {
+        str = await getTableDataText(item, formData);
+      } else if (view == 'cat_tree') {
+        //分类字典树
+        str = await getCategoryDataText(item, formData);
+      } else if (view == 'sel_depart') {
+        //部门选择
+        str = await getDepartDataText(item, formData);
+      } else if (view == 'sel_user') {
+        // 用户选择
+        str = await getUserDataText(item, formData);
+      } else if (view == 'pca') {
+        //省市区
+        str = getAreaTextByCode(value);
+      } else if (view == 'link_down') {
+        //联动组件
+        str = await getLinkDownDataText(item, formData);
+      } else if (view == 'sel_tree') {
+        //自定义树控件
+        str = await getTreeDataText(item, formData);
+      } else if (view == 'switch') {
+        //开关组件
+        str = await getSwitchDataText(item, formData);
+      } else if (view == 'image' || view == 'file') {
+        str = getFileList(item, formData);
+      } else {
+        if (currentLinkFields.indexOf(item.field) >= 0) {
+          let arr = dictOptionsMap[item.field];
+          if (arr && arr.length > 0) {
+            str = filterMultiDictText(arr, value);
+          }
+        }
+      }
+      return str;
+    }
+    return '';
+  }
+
+  // 数据字典/表字典
+  async function getSelectText(item, formData) {
+    // 先从缓存取
+    let dictCode = getRequestDictCode(item);
+    let value = formData[item.field];
+    if (!dictCode) {
+      return value;
+    }
+    let options = getDictItemsByCode(dictCode);
+    if (options && options.length > 0) {
+      return filterMultiDictText(options, value);
+    } else {
+      let dictRes = [];
+      if (dictOptionsMap[dictCode]) {
+        dictRes = dictOptionsMap[dictCode];
+      } else {
+        //取不到再请求
+        dictRes = (await initDictOptions(dictCode)) || [];
+      }
+      if (dictRes && dictRes.length > 0) {
+        dictOptionsMap[dictCode] = dictRes;
+        return filterMultiDictText(dictRes, value);
+      }
+    }
+    return '';
+  }
+
+  function getRequestDictCode(item) {
+    let temp = '';
+    let { dictCode, dictTable, dictText } = item;
+    if (!dictTable) {
+      temp = dictCode;
+    } else {
+      temp = `${dictTable},${dictText},${dictCode}`;
+    }
+    return temp;
+  }
+
+  // 表字典-下拉搜索
+  async function getTableDataText(item, formData) {
+    let dictCode = getRequestDictCode(item);
+    let value = formData[item.field];
+    if (!value) {
+      return '';
+    }
+
+    let arr: any[] = [];
+    if (dictOptionsMap[dictCode + value]) {
+      arr = dictOptionsMap[dictCode + value];
+    } else {
+      //取不到再请求
+      arr = (await defHttp.get({ url: `/sys/dict/loadDictItem/${dictCode}`, params: { key: value } })) || [];
+    }
+    if (arr && arr.length > 0) {
+      dictOptionsMap[dictCode + value] = arr;
+      return arr.join(',');
+      //return filterMultiDictText(arr, value);
+    }
+    return '';
+  }
+
+  // 分类字典
+  async function getCategoryDataText(item, formData) {
+    let value = formData[item.field];
+    if (!value) {
+      return '';
+    }
+    let arr = (await loadDictItem({ ids: value })) || [];
+    if (arr && arr.length > 0) {
+      return arr.join(',');
+    }
+    return '';
+  }
+
+  // 部门数据
+  async function getDepartDataText(item, formData) {
+    let value = formData[item.field];
+    if (!value) {
+      return '';
+    }
+    let extend = getExtendConfig(item);
+    let storeField = extend.store || 'id';
+    let arr = (await queryDepartTreeSync({ ids: value, primaryKey: storeField })) || [];
+    if (arr && arr.length > 0) {
+      let temp: string[] = [];
+      for (let item of arr) {
+        temp.push(item.title);
+      }
+      return temp.join(',');
+    }
+    return '';
+  }
+
+  //用户数据
+  async function getUserDataText(item, formData) {
+    let value = formData[item.field];
+    if (!value) {
+      return '';
+    }
+    let extend = getExtendConfig(item);
+    let storeField = extend.store || 'username';
+    let params = {
+      [storeField]: value,
+    };
+    let res = (await getUserList(params)) || {};
+    let arr = res.records || [];
+    if (arr && arr.length > 0) {
+      let temp: string[] = [];
+      console.log('getUserDataText', arr);
+      let textField = extend.text || 'realname';
+      for (let item of arr) {
+        temp.push(item[textField]);
+      }
+      return temp.join(',');
+    }
+    return '';
+  }
+
+  function getExtendConfig(item) {
+    let extend: FieldExtends = {};
+    let { fieldExtendJson } = item;
+    if (fieldExtendJson) {
+      if (typeof fieldExtendJson == 'string') {
+        try {
+          let json = JSON.parse(fieldExtendJson);
+          extend = { ...json };
+        } catch (e) {
+          console.error(e);
+        }
+      }
+    }
+    return extend;
+  }
+
+  // 联动组件
+  async function getLinkDownDataText(item, formData) {
+    let { dictTable, field } = item;
+    let arr: any[] = [];
+    if (dictOptionsMap[field]) {
+      arr = dictOptionsMap[field];
+    } else {
+      if (dictTable) {
+        let json = JSON.parse(dictTable);
+        if (json) {
+          let { table, txt, key, linkField } = json;
+          let dictCode = `${table},${txt},${key}`;
+          let temp: any[] = (await initDictOptions(dictCode)) || [];
+          arr = [...temp];
+          if (arr && arr.length > 0) {
+            dictOptionsMap[field] = arr;
+            if (linkField) {
+              let fieldArray = linkField.split(',');
+              for (let item of fieldArray) {
+                dictOptionsMap[item] = arr;
+                currentLinkFields.push(item);
+              }
+            }
+          }
+        }
+      }
+    }
+    if (arr && arr.length > 0) {
+      let value = formData[field];
+      return filterMultiDictText(arr, value);
+    }
+    return '';
+  }
+
+  //自定义树
+  async function getTreeDataText(item, formData) {
+    let { dict, field } = item;
+    let arr = [];
+    if (dictOptionsMap[field]) {
+      arr = dictOptionsMap[field];
+    } else {
+      if (dict) {
+        arr = await initDictOptions(dict);
+      }
+    }
+    if (arr && arr.length > 0) {
+      let value = formData[field];
+      return filterMultiDictText(arr, value);
+    }
+    return '';
+  }
+
+  //开关
+  async function getSwitchDataText(item, formData) {
+    let { fieldExtendJson, field } = item;
+    let options = ['Y', 'N'];
+    if (fieldExtendJson) {
+      options = JSON.parse(fieldExtendJson);
+    }
+    let arr: any[] = [
+      { value: options[0], text: '是' },
+      { value: options[1], text: '否' },
+    ];
+    let value = formData[field];
+    return filterMultiDictText(arr, value);
+  }
+
+  function getItemSpan(item) {
+    if (item.span) {
+      return item.span;
+    }
+    return props.span;
+  }
+
+  function getFileList(item, formData) {
+    let str = formData[item.field];
+    if (!str) {
+      return [];
+    }
+    let arr = str.split(',');
+    let result: string[] = [];
+    for (let item of arr) {
+      let src = getFileAccessHttpUrl(item) || '';
+      if (src) {
+        result.push(src);
+      }
+    }
+    return result;
+  }
+
+  function handleDownloadFile(url) {
+    if (url) {
+      window.open(url);
+    }
+  }
+
+  function handleViewImage(field) {
+    let values = detailFormData.value[field];
+    if (!values || values.length == 0) {
+      createMessage.warning('无图片!');
+      return;
+    }
+    createImgPreview({ imageList: values });
+  }
+
+  function getFilename(url) {
+    if (!url) {
+      return '';
+    }
+    return url.substring(url.lastIndexOf('/') + 1);
+  }
+
+  return {
+    formContainerClass,
+    detailFormData,
+    getItemSpan,
+    handleDownloadFile,
+    handleViewImage,
+    getFilename,
+  };
+}
+
+/**
+ * 获取 DetailFormSchema[online用]
+ */
+export function getDetailFormSchemas(props) {
+  const detailFormSchemas = ref<DetailFormSchema[]>([]);
+  const refMap = {};
+  const hasSubTable = ref(false);
+  const subTabInfo = ref<OnlSubTab[]>([]);
+  const subDataSource = ref({});
+  const formSpan = computed(() => {
+    let temp = props.formTemplate;
+    if (temp == '2') {
+      return 12;
+    } else if (temp == '3') {
+      return 8;
+    } else if (temp == '4') {
+      return 6;
+    } else {
+      return 24;
+    }
+  });
+
+  function createFormSchemas(properties: any[]) {
+    //let properties:any[] = result.schema.properties
+    let subInfo: OnlSubTab[] = [];
+    console.log('111', properties);
+    let arr: DetailFormSchema[] = [];
+    let dataSourceObj = {};
+    Object.keys(properties).map((key) => {
+      const item = properties[key];
+      // uiSchema 无用
+      //const uiItem = this.uiSchema[key];// method、formTemplate、url
+      if (item.view == 'tab') {
+        hasSubTable.value = true;
+        let temp: OnlSubTab = {
+          key,
+          // 这个foreignKey是主表的字段
+          foreignKey: item['foreignKey'],
+          describe: item.describe,
+          relationType: item.relationType,
+          requiredFields: item.required || [],
+          order: item.order,
+        };
+        if (item.relationType == 1) {
+          refMap[key] = ref(null);
+          temp['properties'] = item.properties;
+        } else {
+          dealSubProerties(item);
+          refMap[key] = ref<JVxeTableInstance>();
+          temp['columns'] = item.columns;
+          dataSourceObj[key] = [];
+        }
+        subInfo.push(temp);
+      } else {
+        if (item.view === LINK_DOWN) {
+          let array = handleLinkDown(item, key);
+          for (let linkDownItem of array) {
+            let tempIndex = getFieldIndex(arr, linkDownItem.key);
+            let temp = {
+              field: linkDownItem.key,
+              label: linkDownItem.title,
+              view: linkDownItem.view,
+              order: linkDownItem.order,
+            };
+            if (tempIndex == -1) {
+              arr.push(temp);
+            } else {
+              arr[tempIndex] = temp;
+            }
+          }
+        } else if (item.view == 'hidden') {
+          //隐藏的不处理
+        } else {
+          let tempIndex = getFieldIndex(arr, key);
+          if (tempIndex == -1) {
+            let temp = Object.assign(
+              {
+                field: key,
+                label: item.title,
+              },
+              pick(item, ['view', 'order', 'fieldExtendJson', 'dictTable', 'dictText', 'dictCode', 'dict'])
+            );
+            if (item.view == 'file') {
+              temp['span'] = 24;
+              temp['isFile'] = true;
+            }
+            if (item.view == 'image') {
+              temp['span'] = 24;
+              temp['isImage'] = true;
+            }
+            if (item.view == 'umeditor' || item.view == 'markdown') {
+              temp['isHtml'] = true;
+              temp['span'] = 24;
+            }
+            arr.push(temp);
+          }
+        }
+      }
+    });
+    // 1.对arr排序
+    arr.sort(function (a, b) {
+      return a.order - b.order;
+    });
+    // 2.对子表排序
+    subInfo.sort(function (a, b) {
+      return a.order - b.order;
+    });
+    subTabInfo.value = subInfo;
+    for (let i = 0; i < arr.length; i++) {
+      let temp = arr[i];
+      if (temp.isFile === true || temp.isImage === true || temp.isHtml === true) {
+        if (i > 0) {
+          let last = arr[i - 1];
+          let span = last.span || formSpan.value;
+          last.span = span;
+        }
+      }
+    }
+    detailFormSchemas.value = arr;
+    subDataSource.value = dataSourceObj;
+    console.log('adadad', arr);
+  }
+
+  function dealSubProerties(subInfo) {
+    useOnlineVxeTableColumns(subInfo);
+  }
+
+  function getFieldIndex(arr: DetailFormSchema[], key: string) {
+    let index = -1;
+    for (let i = 0; i < arr.length; i++) {
+      let item = arr[i];
+      if (item.field === key) {
+        index = i;
+        break;
+      }
+    }
+    return index;
+  }
+
+  return {
+    detailFormSchemas,
+    hasSubTable,
+    subTabInfo,
+    refMap,
+    createFormSchemas,
+    formSpan,
+    subDataSource,
+  };
+}
+
+/**
+ * TODO 尚未实现
+ * 获取 DetailFormSchema[自定义开发用]
+ */
+export function transDetailFormSchemas(formSchemas: FormSchema[]) {
+  const detailFormSchemas = ref<DetailFormSchema[]>([]);
+  console.log(formSchemas);
+  return detailFormSchemas;
+}

+ 11 - 1
src/components/Form/src/hooks/useForm.ts

@@ -84,7 +84,17 @@ export function useForm(props?: Props): UseFormReturnType {
 
     // TODO promisify
     getFieldsValue: <T>() => {
-      return unref(formRef)?.getFieldsValue() as T;
+      //update-begin-author:taoyan date:2022-7-5 for: VUEN-1341【流程】编码方式 流程节点编辑表单时,填写数据报错 包括用户组件、部门组件、省市区
+      let values = unref(formRef)?.getFieldsValue() as T;
+      if (values) {
+        Object.keys(values).map((key) => {
+          if (values[key] instanceof Array) {
+            values[key] = values[key].join(',');
+          }
+        });
+      }
+      return values;
+      //update-end-author:taoyan date:2022-7-5 for: VUEN-1341【流程】编码方式 流程节点编辑表单时,填写数据报错 包括用户组件、部门组件、省市区
     },
 
     setFieldsValue: async <T>(values: T) => {

+ 5 - 1
src/components/Form/src/jeecg/components/JAreaLinkage.vue

@@ -57,9 +57,13 @@
         }
       }
 
-      function handleChange(_, ...args) {
+      function handleChange(array, ...args) {
         emitData.value = args;
         console.info(emitData);
+        //update-begin-author:taoyan date:2022-6-27 for: VUEN-1424【vue3】树表、单表、jvxe、erp 、内嵌子表省市县 选择不上
+        // 上面改的v-model:value导致选中数据没有显示
+        state.value = array;
+        //update-end-author:taoyan date:2022-6-27 for: VUEN-1424【vue3】树表、单表、jvxe、erp 、内嵌子表省市县 选择不上
       }
       return {
         state,

+ 9 - 7
src/components/Form/src/jeecg/components/JCategorySelect.vue

@@ -102,15 +102,17 @@
         };
         console.info(param);
         loadTreeData(param).then((res) => {
-          for (let i of res) {
-            i.value = i.key;
-            if (i.leaf == false) {
-              i.isLeaf = false;
-            } else if (i.leaf == true) {
-              i.isLeaf = true;
+          if (res && res.length > 0) {
+            for (let i of res) {
+              i.value = i.key;
+              if (i.leaf == false) {
+                i.isLeaf = false;
+              } else if (i.leaf == true) {
+                i.isLeaf = true;
+              }
             }
+            treeData.value = res;
           }
-          treeData.value = res;
         });
       }
 

+ 10 - 2
src/components/Form/src/jeecg/components/JCheckbox.vue

@@ -11,7 +11,7 @@
   export default defineComponent({
     name: 'JCheckbox',
     props: {
-      value: propTypes.string,
+      value: propTypes.oneOfType([propTypes.string, propTypes.number]),
       dictCode: propTypes.string,
       options: {
         type: Array,
@@ -29,7 +29,15 @@
        * 监听value
        */
       watchEffect(() => {
-        props.value && (checkboxArray.value = props.value ? props.value.split(',') : []);
+        //update-begin-author:taoyan date:2022-7-4 for:issues/I5E7YX AUTO在线表单进入功能测试之后一直卡在功能测试界面
+        let temp = props.value;
+        if (!temp && temp !== 0) {
+          checkboxArray.value = [];
+        } else {
+          temp = temp + '';
+          checkboxArray.value = temp.split(',');
+        }
+        //update-end-author:taoyan date:2022-7-4 for:issues/I5E7YX AUTO在线表单进入功能测试之后一直卡在功能测试界面
         //update-begin-author:taoyan date:20220401 for: 调用表单的 resetFields不会清空当前信息,界面显示上一次的数据
         if (props.value === '' || props.value === undefined) {
           checkboxArray.value = [];

+ 14 - 2
src/components/Form/src/jeecg/components/JCodeEditor.vue

@@ -15,7 +15,7 @@
   // 核心样式
   import 'codemirror/lib/codemirror.css';
   // 引入主题后还需要在 options 中指定主题才会生效
-  import 'codemirror/theme/cobalt.css';
+  import 'codemirror/theme/idea.css';
   // 需要引入具体的语法高亮库才会有对应的语法高亮效果
   import 'codemirror/mode/javascript/javascript.js';
   import 'codemirror/mode/css/css.js';
@@ -59,6 +59,8 @@
       fullScreen: propTypes.bool.def(false),
       // 全屏以后的z-index
       zIndex: propTypes.any.def(999),
+      theme: propTypes.string.def('idea'),
+      language: propTypes.string.def(''),
     },
     emits: ['change', 'update:value'],
     setup(props, { emit }) {
@@ -75,7 +77,7 @@
         // 缩进格式
         tabSize: 2,
         // 主题,对应主题库 JS 需要提前引入
-        theme: 'cobalt',
+        theme: props.theme,
         smartIndent: true, // 是否智能缩进
         // 显示行号
         lineNumbers: true,
@@ -187,6 +189,16 @@
       );
       //update-end-author:taoyan date:2022-5-9 for: codeEditor禁用功能
 
+      // 支持动态设置语言
+      watch(
+        () => props.language,
+        (val) => {
+          if (val && coder) {
+            coder.setOption('mode', val);
+          }
+        }
+      );
+
       const getBindValue = Object.assign({}, unref(props), unref(attrs));
       return {
         state,

+ 1 - 0
src/components/Form/src/jeecg/components/base/JSelectBiz.vue

@@ -21,6 +21,7 @@
           @change="handleChange"
           style="width: 100%"
           @click="!disabled && openModal(false)"
+          v-bind="attrs"
         ></a-select>
       </a-col>
       <a-col v-if="showButton" class="right">

+ 3 - 1
src/components/Form/src/jeecg/components/modal/DeptSelectModal.vue

@@ -83,7 +83,9 @@
       /** 获取查询数据方法 */
       function getQueryUrl() {
         let queryFn = props.sync ? queryDepartTreeSync : queryTreeList;
-        return (params) => queryFn(Object.assign({}, params, { primaryKey: props.primaryKey }));
+        //update-begin-author:taoyan date:2022-7-4 for: issues/I5F3P4 online配置部门选择后编辑,查看数据应该显示部门名称,不是部门代码
+        return (params) => queryFn(Object.assign({}, params, { primaryKey: props.rowKey }));
+        //update-end-author:taoyan date:2022-7-4 for: issues/I5F3P4 online配置部门选择后编辑,查看数据应该显示部门名称,不是部门代码
       }
 
       return {

+ 3 - 1
src/components/Form/src/jeecg/hooks/useTreeBiz.ts

@@ -171,7 +171,9 @@ export function useTreeBiz(treeRef, getList, props) {
     } else {
       const options = <any[]>[];
       optionData.forEach((item) => {
-        options.push({ label: item[props.titleKey], value: item[props.primaryKey] });
+        //update-begin-author:taoyan date:2022-7-4 for: issues/I5F3P4 online配置部门选择后编辑,查看数据应该显示部门名称,不是部门代码
+        options.push({ label: item[props.titleKey], value: item[props.rowKey] });
+        //update-end-author:taoyan date:2022-7-4 for: issues/I5F3P4 online配置部门选择后编辑,查看数据应该显示部门名称,不是部门代码
       });
       selectOptions.value = options;
     }

+ 17 - 2
src/components/JVxeCustom/src/components/JVxeDepartSelectCell.vue

@@ -24,7 +24,7 @@
   <!--    </span>-->
   <!--  </div>-->
   <div :class="[prefixCls]">
-    <JSelectDept :value="selectedValue" :maxTagCount="1" :showButton="false" v-bind="cellProps" @change="handleChange" />
+    <JSelectDept v-bind="getProps" @change="handleChange" />
   </div>
 </template>
 
@@ -65,6 +65,20 @@
 
       const multiple = computed(() => cellProps.value['multi'] != false);
 
+      const getProps = computed(() => {
+        return {
+          ...cellProps.value,
+          value: selectedValue.value,
+          showButton: false,
+          // 不允许搜索
+          showSearch: false,
+          // 设置最大的显示个数
+          maxTagCount: 1,
+          // 显示提示重写,去掉省略号
+          maxTagPlaceholder: ({ length }) => '+' + length,
+        };
+      });
+
       function handleChange(values) {
         handleChangeCommon(values.join(','));
       }
@@ -74,6 +88,7 @@
         selectedValue,
         multiple,
         cellProps,
+        getProps,
         handleChange,
       };
     },
@@ -191,7 +206,7 @@
   .@{prefix-cls} {
     // 限制tag最大长度为100px,防止选中文字过多的选项时换行
     .ant-select .ant-select-selection-overflow-item {
-      max-width: 100px;
+      max-width: 80px;
     }
   }
 </style>

+ 17 - 2
src/components/JVxeCustom/src/components/JVxeUserSelectCell.vue

@@ -1,6 +1,6 @@
 <template>
   <div :class="[prefixCls]">
-    <JSelectUser :value="selectedValue" :maxTagCount="1" :showButton="false" v-bind="cellProps" @change="handleChange" />
+    <JSelectUser v-bind="getProps" @change="handleChange" />
   </div>
 </template>
 
@@ -40,6 +40,20 @@
       // @ts-ignore
       const multiple = computed(() => cellProps.value.multi != false);
 
+      const getProps = computed(() => {
+        return {
+          ...cellProps.value,
+          value: selectedValue.value,
+          showButton: false,
+          // 不允许搜索
+          showSearch: false,
+          // 设置最大的显示个数
+          maxTagCount: 1,
+          // 显示提示重写,去掉省略号
+          maxTagPlaceholder: ({ length }) => '+' + length,
+        };
+      });
+
       function handleChange(values) {
         handleChangeCommon(values.join(','));
       }
@@ -49,6 +63,7 @@
         selectedValue,
         multiple,
         cellProps,
+        getProps,
         handleChange,
       };
     },
@@ -80,7 +95,7 @@
   .@{prefix-cls} {
     // 限制tag最大长度为100px,防止选中文字过多的选项时换行
     .ant-select .ant-select-selection-overflow-item {
-      max-width: 100px;
+      max-width: 80px;
     }
   }
 </style>

+ 39 - 2
src/components/Modal/src/BasicModal.vue

@@ -1,7 +1,15 @@
 <template>
   <Modal v-bind="getBindValue" @cancel="handleCancel">
     <template #closeIcon v-if="!$slots.closeIcon">
-      <ModalClose :canFullscreen="getProps.canFullscreen" :fullScreen="fullScreenRef" @cancel="handleCancel" @fullscreen="handleFullScreen" />
+      <ModalClose
+        :canFullscreen="getProps.canFullscreen"
+        :fullScreen="fullScreenRef"
+        :commentSpan="commentSpan"
+        :enableComment="getProps.enableComment"
+        @comment="handleComment"
+        @cancel="handleCancel"
+        @fullscreen="handleFullScreen"
+      />
     </template>
 
     <template #title v-if="!$slots.title">
@@ -31,7 +39,16 @@
       @ext-height="handleExtHeight"
       @height-change="handleHeightChange"
     >
-      <slot></slot>
+      <!-- update-begin-author:taoyan date:2022-7-18 for:  modal弹窗 支持评论 slot -->
+      <a-row>
+        <a-col :span="24 - commentSpan">
+          <slot></slot>
+        </a-col>
+        <a-col :span="commentSpan">
+          <slot name="comment"></slot>
+        </a-col>
+      </a-row>
+      <!-- update-end-author:taoyan date:2022-7-18 for:  modal弹窗 支持评论 slot -->
     </ModalWrapper>
 
     <template #[item]="data" v-for="item in Object.keys(omit($slots, 'default'))">
@@ -200,6 +217,24 @@
         handleFullScreen(e);
       }
 
+      //update-begin-author:taoyan date:2022-7-18 for: modal支持评论 slot
+      const commentSpan = ref(0);
+      watch(
+        () => props.enableComment,
+        (flag) => {
+          handleComment(flag);
+        },
+        { immediate: true }
+      );
+      function handleComment(flag) {
+        if (flag === true) {
+          commentSpan.value = 6;
+        } else {
+          commentSpan.value = 0;
+        }
+      }
+      //update-end-author:taoyan date:2022-7-18 for: modal支持评论 slot
+
       return {
         handleCancel,
         getBindValue,
@@ -215,6 +250,8 @@
         handleHeightChange,
         handleTitleDbClick,
         getWrapperHeight,
+        commentSpan,
+        handleComment,
       };
     },
   });

+ 69 - 4
src/components/Modal/src/components/ModalClose.vue

@@ -1,5 +1,5 @@
 <template>
-  <div :class="getClass">
+  <div :class="getClass" :style="{ width: closeWidth + 'px' }">
     <template v-if="canFullscreen">
       <Tooltip :title="t('component.modal.restore')" placement="bottom" v-if="fullScreen">
         <FullscreenExitOutlined role="full" @click="handleFullScreen" />
@@ -8,6 +8,17 @@
         <FullscreenOutlined role="close" @click="handleFullScreen" />
       </Tooltip>
     </template>
+
+    <!-- 是否开启评论区域 -->
+    <template v-if="enableComment">
+      <Tooltip title="关闭" placement="bottom" v-if="commentSpan > 0">
+        <RightSquareOutlined @click="handleCloseComment" />
+      </Tooltip>
+      <Tooltip title="展开" placement="bottom" v-else>
+        <LeftSquareOutlined @click="handleOpenComment" />
+      </Tooltip>
+    </template>
+
     <Tooltip :title="t('component.modal.close')" placement="bottom">
       <CloseOutlined @click="handleCancel" />
     </Tooltip>
@@ -15,19 +26,21 @@
 </template>
 <script lang="ts">
   import { defineComponent, computed } from 'vue';
-  import { FullscreenExitOutlined, FullscreenOutlined, CloseOutlined } from '@ant-design/icons-vue';
+  import { FullscreenExitOutlined, FullscreenOutlined, CloseOutlined, LeftSquareOutlined, RightSquareOutlined } from '@ant-design/icons-vue';
   import { useDesign } from '/@/hooks/web/useDesign';
   import { Tooltip } from 'ant-design-vue';
   import { useI18n } from '/@/hooks/web/useI18n';
 
   export default defineComponent({
     name: 'ModalClose',
-    components: { Tooltip, FullscreenExitOutlined, FullscreenOutlined, CloseOutlined },
+    components: { Tooltip, FullscreenExitOutlined, FullscreenOutlined, CloseOutlined, LeftSquareOutlined, RightSquareOutlined },
     props: {
       canFullscreen: { type: Boolean, default: true },
       fullScreen: { type: Boolean },
+      enableComment: { type: Boolean, default: false },
+      commentSpan: { type: Number, default: 0 },
     },
-    emits: ['cancel', 'fullscreen'],
+    emits: ['cancel', 'fullscreen', 'comment'],
     setup(props, { emit }) {
       const { prefixCls } = useDesign('basic-modal-close');
       const { t } = useI18n();
@@ -52,12 +65,45 @@
         emit('fullscreen');
       }
 
+      //update-begin-author:taoyan date:2022-7-18 for: 关闭按钮的区域宽度 取决于是否有其他图标
+      const closeWidth = computed(() => {
+        if (props.canFullscreen && props.enableComment) {
+          return 140;
+        } else {
+          return 96;
+        }
+      });
+      //update-end-author:taoyan date:2022-7-18 for: 关闭按钮的区域宽度 取决于是否有其他图标
+
+      /**
+       * 开启评论区域
+       * @param e
+       */
+      function handleOpenComment(e: Event) {
+        e?.stopPropagation();
+        e?.preventDefault();
+        emit('comment', true);
+      }
+
+      /**
+       * 关闭评论区域
+       * @param e
+       */
+      function handleCloseComment(e: Event) {
+        e?.stopPropagation();
+        e?.preventDefault();
+        emit('comment', false);
+      }
+
       return {
         t,
         getClass,
         prefixCls,
         handleCancel,
         handleFullScreen,
+        closeWidth,
+        handleOpenComment,
+        handleCloseComment,
       };
     },
   });
@@ -69,6 +115,10 @@
     height: 95%;
     align-items: center;
 
+    .ant-modal-close-x {
+      width: 140px !important;
+    }
+
     > span {
       margin-left: 48px;
       font-size: 16px;
@@ -86,6 +136,12 @@
           font-weight: 700;
         }
       }
+      /** 展开/关闭 评论图标样式*/
+      > span:nth-child(2) {
+        &:hover {
+          font-weight: 700;
+        }
+      }
     }
 
     & span:nth-child(1) {
@@ -96,6 +152,15 @@
         color: @primary-color;
       }
     }
+    /** 展开/关闭 评论图标样式*/
+    & span:nth-child(2) {
+      display: inline-block;
+      padding: 10px 10px 10px 0;
+
+      &:hover {
+        color: @primary-color;
+      }
+    }
 
     & span:last-child {
       &:hover {

+ 2 - 1
src/components/Modal/src/index.less

@@ -70,7 +70,8 @@
 
   &-close-x {
     display: inline-block;
-    width: 96px;
+    /*width: 96px;*/
+    width: auto;
     height: 56px;
     line-height: 56px;
   }

+ 3 - 0
src/components/Modal/src/props.ts

@@ -80,4 +80,7 @@ export const basicProps = Object.assign({}, modalProps, {
   wrapClassName: { type: String },
 
   zIndex: { type: Number },
+
+  // 是否开启评论区域
+  enableComment: { type: Boolean, default: false },
 });

+ 1 - 1
src/components/SimpleMenu/src/components/SubMenuItem.vue

@@ -2,7 +2,7 @@
   <li :class="getClass">
     <template v-if="!getCollapse">
       <div :class="`${prefixCls}-submenu-title`" @click.stop="handleClick" :style="getItemStyle">
-        <slot name="title"></slot>
+        <slot name="title" :getIsOpened="getIsOpend"></slot>
         <Icon icon="eva:arrow-ios-downward-outline" :size="14" :class="`${prefixCls}-submenu-title-icon`" />
       </div>
       <CollapseTransition>

+ 2 - 0
src/components/Table/src/types/tableAction.ts

@@ -14,6 +14,8 @@ export interface ActionItem extends ButtonProps {
   // 业务控制是否显示
   ifShow?: boolean | ((action: ActionItem) => boolean);
   tooltip?: string | TooltipProps;
+  // 自定义类名
+  class?: string | Record<string, boolean> | any[];
 }
 
 export interface PopConfirm {

+ 8 - 2
src/components/jeecg/AIcon.vue

@@ -1,11 +1,12 @@
 <template>
-  <Icon :icon="icon"></Icon>
+  <Icon :icon="icon" :size="size"></Icon>
 </template>
 
 <script lang="ts">
   import { computed, defineComponent } from 'vue';
   import { Icon } from '/@/components/Icon';
   import { isEmpty } from '/@/utils/is';
+  import { propTypes } from '/@/utils/propTypes';
 
   export default defineComponent({
     name: 'AIcon',
@@ -13,13 +14,18 @@
     props: {
       icon: String,
       type: String,
+      // 图标大小,默认 16
+      size: propTypes.any,
+      // 样式
+      theme: propTypes.any,
     },
     setup(props) {
       const icon = computed(() => {
         if (props.icon && !isEmpty(props.icon)) {
           return props.icon;
         }
-        return `ant-design:${props.type}`;
+        let iconTheme = props.theme ? `-${props.theme}` : '';
+        return `ant-design:${props.type}${iconTheme}`;
       });
 
       return {

+ 154 - 0
src/components/jeecg/JPrompt/JPrompt.vue

@@ -0,0 +1,154 @@
+<template>
+  <Modal v-bind="getProps">
+    <Spin :spinning="loading">
+      <div style="padding: 20px">
+        <div v-html="options.content" style="margin-bottom: 8px"></div>
+        <BasicForm @register="registerForm">
+          <template #customInput="{ model, field }">
+            <Input ref="inputRef" v-model:value="model[field]" :placeholder="placeholder" @pressEnter="onSubmit" @input="onChange" />
+          </template>
+        </BasicForm>
+      </div>
+    </Spin>
+  </Modal>
+</template>
+
+<script lang="ts">
+  import type { JPromptProps } from './typing';
+  import type { ModalProps } from '/@/components/Modal';
+  import { ref, defineComponent, computed, unref, onMounted, nextTick } from 'vue';
+  import { BasicForm, useForm } from '/@/components/Form';
+  import { Modal, Spin, Input } from 'ant-design-vue';
+
+  export default defineComponent({
+    name: 'JPrompt',
+    components: {
+      Modal,
+      Spin,
+      Input,
+      BasicForm,
+    },
+    emits: ['register'],
+    setup(props, { emit }) {
+      const inputRef = ref();
+      const visible = ref(false);
+      // 当前是否正在加载中
+      const loading = ref(false);
+      const options = ref<JPromptProps>({});
+      const placeholder = computed(() => options.value.placeholder ?? '请输入内容');
+      // 注册表单
+      const [registerForm, { clearValidate, setFieldsValue, validate, updateSchema }] = useForm({
+        compact: true,
+        wrapperCol: { span: 24 },
+        schemas: [
+          {
+            label: '',
+            field: 'input',
+            component: 'Input',
+            slot: 'customInput',
+          },
+        ],
+        showActionButtonGroup: false,
+      });
+
+      // 弹窗最终props
+      const getProps = computed(() => {
+        let opt = options.value;
+        let modalProps: Partial<ModalProps> = {
+          width: (opt.width ?? 500) as number,
+          title: (opt.title ?? 'prompt') as string,
+          visible: unref(visible),
+          confirmLoading: unref(loading),
+        };
+        let finalProps: Recordable = {
+          ...modalProps,
+          ...props,
+          ...opt,
+          onOk: onSubmit,
+          onCancel() {
+            if (typeof options.value.onCancel === 'function') {
+              options.value.onCancel();
+            }
+            close();
+          },
+        };
+        return finalProps;
+      });
+
+      onMounted(() => {
+        emit('register', {
+          openModal,
+          setLoading,
+          getVisible: visible,
+        });
+      });
+
+      /** 弹窗开启 */
+      async function openModal(opt: any) {
+        document.body.focus();
+
+        options.value = opt;
+        visible.value = true;
+        await nextTick();
+        await updateSchema({
+          field: 'input',
+          required: options.value.required,
+          rules: options.value.rules,
+          dynamicRules: options.value.dynamicRules,
+        } as any);
+        await setFieldsValue({
+          input: options.value.defaultValue ?? '',
+        });
+        await clearValidate();
+        inputRef.value?.focus();
+      }
+
+      /** 弹窗关闭 */
+      function close() {
+        visible.value = false;
+      }
+
+      function onChange() {
+        validate();
+      }
+
+      /** 提交表单 */
+      async function onSubmit() {
+        try {
+          const { onOk } = options.value;
+          // 表单验证
+          let values = await validate();
+          setLoading(true);
+          if (typeof onOk === 'function') {
+            let flag = await onOk(values.input);
+            // 只有返回 false 才阻止关闭弹窗
+            if (!(flag === false)) {
+              close();
+            }
+          } else {
+            close();
+          }
+        } finally {
+          setLoading(false);
+        }
+      }
+
+      /** 设置加载状态*/
+      function setLoading(flag) {
+        loading.value = flag;
+      }
+
+      return {
+        inputRef,
+        getProps,
+        loading,
+        options,
+        placeholder,
+        onChange,
+        onSubmit,
+
+        registerForm,
+      };
+    },
+  });
+</script>

+ 56 - 0
src/components/jeecg/JPrompt/hooks/useJPrompt.ts

@@ -0,0 +1,56 @@
+import type { JPromptProps } from '../typing';
+import { render, createVNode, nextTick } from 'vue';
+import { error } from '/@/utils/log';
+import JPrompt from '../JPrompt.vue';
+
+export function useJPrompt() {
+  function createJPrompt(options: JPromptProps) {
+    let instance = null;
+    const box = document.createElement('div');
+    const vm = createVNode(JPrompt, {
+      // 注册
+      async onRegister(ins) {
+        instance = ins;
+        await nextTick();
+        ins.openModal(options);
+      },
+      // 销毁
+      afterClose() {
+        render(null, box);
+        document.body.removeChild(box);
+      },
+    });
+    // 挂载到 body
+    render(vm, box);
+    document.body.appendChild(box);
+
+    function getInstance(): any {
+      if (instance == null) {
+        error('useJPrompt instance is undefined!');
+      }
+      return instance;
+    }
+
+    function updateModal(options: JPromptProps) {
+      getInstance()?.updateModal(options);
+    }
+
+    function closeModal() {
+      getInstance()?.closeModal();
+    }
+
+    function setLoading(loading) {
+      getInstance()?.setLoading(loading);
+    }
+
+    return {
+      closeModal,
+      updateModal,
+      setLoading,
+    };
+  }
+
+  return {
+    createJPrompt,
+  };
+}

+ 2 - 0
src/components/jeecg/JPrompt/index.ts

@@ -0,0 +1,2 @@
+export { useJPrompt } from './hooks/useJPrompt';
+export { default as JPrompt } from './JPrompt.vue';

+ 15 - 0
src/components/jeecg/JPrompt/typing.ts

@@ -0,0 +1,15 @@
+import { ModalOptionsPartial } from '/@/hooks/web/useMessage';
+import { RenderCallbackParams, Rule } from '/@/components/Form';
+
+export interface JPromptProps extends ModalOptionsPartial {
+  // 输入框是否必填
+  required?: boolean;
+  // 校验
+  rules?: Rule[];
+  // 动态校验
+  dynamicRules?: (renderCallbackParams: RenderCallbackParams) => Rule[];
+  // 占位字符
+  placeholder?: string;
+  // 输入框默认值
+  defaultValue?: string;
+}

+ 7 - 3
src/components/jeecg/JVxeTable/src/JVxeTable.ts

@@ -1,4 +1,4 @@
-import { useSlots, defineComponent, getCurrentInstance, h } from 'vue';
+import { defineComponent, h, ref, useSlots } from 'vue';
 import { vxeEmits, vxeProps } from './vxe.data';
 import { useData, useRefs, useResolveComponent as rc } from './hooks/useData';
 import { useColumns } from './hooks/useColumns';
@@ -16,11 +16,11 @@ export default defineComponent({
   props: vxeProps(),
   emits: [...vxeEmits],
   setup(props: JVxeTableProps, context) {
-    const instance = getCurrentInstance();
+    const instanceRef = ref();
     const refs = useRefs();
     const slots = useSlots();
     const data = useData(props);
-    const { methods, publicMethods, created } = useMethods(props, context, data, refs, instance);
+    const { methods, publicMethods, created } = useMethods(props, context, data, refs, instanceRef);
     created();
     useColumns(props, data, methods, slots);
     useDataSource(props, data, methods, refs);
@@ -30,6 +30,7 @@ export default defineComponent({
     // 渲染子组件
     const renderComponents = useRenderComponents(props, data, methods, slots);
     return {
+      instanceRef,
       ...refs,
       ...publicMethods,
       ...finallyProps,
@@ -69,4 +70,7 @@ export default defineComponent({
       )
     );
   },
+  created() {
+    this.instanceRef = this;
+  },
 });

+ 7 - 7
src/components/jeecg/JVxeTable/src/hooks/useData.ts

@@ -32,13 +32,13 @@ export function useData(props: JVxeTableProps): JVxeDataProps {
         iconClose: 'ant-table-row-expand-icon ant-table-row-collapsed',
         iconOpen: 'ant-table-row-expand-icon ant-table-row-expanded',
       },
-      // 虚拟滚动配置,y轴大于30条数据时启用虚拟滚动
-      // 'scroll-y': {
-      //   gt: 30
-      // },
-      // 'scroll-x': {
-      //   gt: 15
-      // },
+      // 虚拟滚动配置,y轴大于xx条数据时启用虚拟滚动
+      scrollY: {
+        gt: 30,
+      },
+      scrollX: {
+        gt: 20,
+      },
       radioConfig: { highlight: true },
       checkboxConfig: { highlight: true },
       mouseConfig: { selected: false },

+ 5 - 4
src/components/jeecg/JVxeTable/src/hooks/useJVxeComponent.ts

@@ -138,13 +138,14 @@ export function useJVxeComponent(props: JVxeComponent.Props) {
 
   /** 通用处理 change 事件 */
   function handleChangeCommon($value) {
-    let getValue = enhanced.getValue($value, ctx);
-    trigger('change', { value: getValue });
+    let newValue = enhanced.getValue($value, ctx);
+    let oldValue = value.value;
+    trigger('change', { value: newValue });
     // 触发valueChange事件
     parentTrigger('valueChange', {
       type: props.type,
-      value: getValue,
-      oldValue: value.value,
+      value: newValue,
+      oldValue: oldValue,
       col: originColumn.value,
       rowIndex: rowIndex.value,
       columnIndex: columnIndex.value,

+ 35 - 9
src/components/jeecg/JVxeTable/src/hooks/useMethods.ts

@@ -1,4 +1,4 @@
-import { watch } from 'vue';
+import { Ref, watch } from 'vue';
 import XEUtils from 'xe-utils';
 import { simpleDebounce } from '/@/utils/common/compUtils';
 import { JVxeDataProps, JVxeRefs, JVxeTableProps, JVxeTypes } from '../types';
@@ -10,7 +10,7 @@ import { useLinkage } from './useLinkage';
 import { useWebSocket } from './useWebSocket';
 import { getPrefix, getJVxeAuths } from '../utils/authUtils';
 
-export function useMethods(props: JVxeTableProps, { emit }, data: JVxeDataProps, refs: JVxeRefs, instance) {
+export function useMethods(props: JVxeTableProps, { emit }, data: JVxeDataProps, refs: JVxeRefs, instanceRef: Ref) {
   let xTableTemp: VxeTableInstance & VxeTablePrivateMethods;
 
   function getXTable() {
@@ -37,6 +37,7 @@ export function useMethods(props: JVxeTableProps, { emit }, data: JVxeDataProps,
     getNewRowById,
     getDeleteData,
     getSelectionData,
+    getSelectedData,
     removeRows,
     removeRowsById,
     removeSelection,
@@ -159,13 +160,13 @@ export function useMethods(props: JVxeTableProps, { emit }, data: JVxeDataProps,
   // 单元格被激活编辑时会触发该事件
   function handleEditActived({ column }) {
     // 执行增强
-    getEnhanced(column.params.type).aopEvents.editActived!.apply(instance, arguments as any);
+    getEnhanced(column.params.type).aopEvents.editActived!.apply(instanceRef.value, arguments as any);
   }
 
   // 单元格编辑状态下被关闭时会触发该事件
   function handleEditClosed({ column }) {
     // 执行增强
-    getEnhanced(column.params.type).aopEvents.editClosed!.apply(instance, arguments as any);
+    getEnhanced(column.params.type).aopEvents.editClosed!.apply(instanceRef.value, arguments as any);
   }
 
   // 返回值决定行是否可选中
@@ -189,7 +190,7 @@ export function useMethods(props: JVxeTableProps, { emit }, data: JVxeDataProps,
         return false;
       }
       // 执行增强
-      return getEnhanced(column.params.type).aopEvents.activeMethod!.apply(instance, arguments as any) ?? true;
+      return getEnhanced(column.params.type).aopEvents.activeMethod!.apply(instanceRef.value, arguments as any) ?? true;
     })();
     if (!flag) {
       getXTable().clearActived();
@@ -351,7 +352,7 @@ export function useMethods(props: JVxeTableProps, { emit }, data: JVxeDataProps,
             rows: result.rows,
             insertIndex: index,
             $table: xTable,
-            target: instance,
+            target: instanceRef.value,
           });
         }
       }
@@ -579,7 +580,7 @@ export function useMethods(props: JVxeTableProps, { emit }, data: JVxeDataProps,
   /** 清空选择行 */
   async function clearSelection() {
     const xTable = getXTable();
-    let event = { $table: xTable, target: instance };
+    let event = { $table: xTable, target: instanceRef.value };
     if (props.rowSelectionType === JVxeTypes.rowRadio) {
       await xTable.clearRadioRow();
       handleVxeRadioChange(event);
@@ -745,13 +746,38 @@ export function useMethods(props: JVxeTableProps, { emit }, data: JVxeDataProps,
 
   // 触发事件
   function trigger(name, event: any = {}) {
-    event.$target = instance;
+    event.$target = instanceRef.value;
     event.$table = getXTable();
     //online增强参数兼容
-    event.target = instance;
+    event.target = instanceRef.value;
     emit(name, event);
   }
 
+  /**
+   * 获取选中的行-和 getSelectionData 区别在于对于新增的行也会返回ID
+   * 用于onlinePopForm
+   * @param isFull
+   */
+  function getSelectedData(isFull?: boolean) {
+    const xTable = getXTable();
+    let rows: any[] = [];
+    if (props.rowSelectionType === JVxeTypes.rowRadio) {
+      let row = xTable.getRadioRecord(isFull);
+      if (isNull(row)) {
+        return [];
+      }
+      rows = [row];
+    } else {
+      rows = xTable.getCheckboxRecords(isFull);
+    }
+    let records: Recordable[] = [];
+    for (let row of rows) {
+      let item = cloneDeep(row);
+      records.push(item);
+    }
+    return records;
+  }
+
   return {
     methods: {
       trigger,

+ 1 - 1
src/components/jeecg/JVxeTable/src/hooks/useToolbar.ts

@@ -24,7 +24,7 @@ export function useToolbar(props: JVxeTableProps, data: JVxeDataProps, methods:
             let deleteRows = methods.filterNewRows(data.selectedRows.value);
             // 触发删除事件
             if (deleteRows.length > 0) {
-              let removeEvent: any = { deleteRows, $table, target: this };
+              let removeEvent: any = { deleteRows, $table };
               if (props.asyncRemove) {
                 // 确认删除,只有调用这个方法才会真删除
                 removeEvent.confirmRemove = () => methods.removeSelection();

+ 1 - 1
src/components/jeecg/JVxeTable/src/hooks/useWebSocket.ts

@@ -58,7 +58,7 @@ const vs = {
       const url = `${domain}/vxeSocket/${userId}/${this.pageId}`;
       //update-begin-author:taoyan date:2022-4-24 for: v2.4.6 的 websocket 服务端,存在性能和安全问题。 #3278
       let token = (getToken() || '') as string;
-      this.ws = new WebSocket(url);
+      this.ws = new WebSocket(url, [token]);
       //update-end-author:taoyan date:2022-4-24 for: v2.4.6 的 websocket 服务端,存在性能和安全问题。 #3278
       this.ws.onopen = this.on.open.bind(this);
       this.ws.onerror = this.on.error.bind(this);

+ 15 - 6
src/components/jeecg/OnLine/hooks/usePopBiz.ts

@@ -40,7 +40,7 @@ export function usePopBiz(props, tableRef?) {
     getColumns: '/online/cgreport/api/getRpColumns/',
     getData: '/online/cgreport/api/getData/',
     getQueryInfo: '/online/cgreport/api/getQueryInfo/',
-    export: '/online/cgreport/api/exportXls/',
+    export: '/online/cgreport/api/exportManySheetXls/',
   });
   //已选择的值
   const checkedKeys = ref<Array<string | number>>([]);
@@ -289,11 +289,12 @@ export function usePopBiz(props, tableRef?) {
     for (let column of columns) {
       if (column.isTotal === '1') {
         arr.push(column.dataIndex!);
-        if (column.children && column.children.length > 0) {
-          let subArray = getNeedSumColumns(column.children);
-          if (subArray.length > 0) {
-            arr.push(...subArray);
-          }
+      }
+      // 【VUEN-1569】【online报表】合计无效
+      if (column.children && column.children.length > 0) {
+        let subArray = getNeedSumColumns(column.children);
+        if (subArray.length > 0) {
+          arr.push(...subArray);
         }
       }
     }
@@ -445,6 +446,14 @@ export function usePopBiz(props, tableRef?) {
     const { handleExportXls } = useMethods();
     let url = `${configUrl.export}${cgRpConfigId.value}`;
     let params = getQueryParams(); //查询条件
+    // 【VUEN-1568】如果选中了某些行,就只导出选中的行
+    let keys = unref(checkedKeys);
+    if (keys.length > 0) {
+      params['force_id'] = keys
+        .map((i) => (getRowByKey(i) as any)?.id)
+        .filter((i) => i != null && i !== '')
+        .join(',');
+    }
     handleExportXls(title.value, url, params);
   }
 

+ 401 - 0
src/components/jeecg/super/superquery/SuperQuery.vue

@@ -0,0 +1,401 @@
+<template>
+  <!-- 按钮区域 -->
+  <div class="j-super-query-button">
+    <a-tooltip v-if="superQueryFlag" :mouseLeaveDelay="0.2">
+      <template #title>
+        <span>已有高级查询条件生效</span>
+        <divider type="vertical" style="background-color: #fff" />
+        <a @click="handleReset">清空</a>
+      </template>
+      <a-button-group>
+        <a-button type="primary" @click="handleOpen">
+          <AppstoreTwoTone :spin="true" />
+          <span>高级查询</span>
+        </a-button>
+      </a-button-group>
+    </a-tooltip>
+    <a-button v-else type="primary" preIcon="ant-design:filter-outlined" @click="handleOpen"> 高级查询 </a-button>
+  </div>
+
+  <!-- 高级查询弹框 -->
+  <teleport to="body">
+    <BasicModal title="高级查询构造器" :canFullscreen="false" :width="1050" @register="registerFormModal" @ok="handleSubmit">
+      <template #footer>
+        <div style="float: left">
+          <a-button :loading="loading" @click="handleReset">重置</a-button>
+          <a-button :loading="loading" @click="handleSave">保存查询条件</a-button>
+        </div>
+
+        <a-button key="submit" type="primary" @click="handleSubmit">确定</a-button>
+        <a-button key="back" @click="handleCancel">关闭</a-button>
+      </template>
+
+      <a-empty v-if="dynamicRowValues.values.length == 0">
+        <div slot="description">
+          <span>没有任何查询条件</span>
+          <a-divider type="vertical" />
+          <a @click="addOne(-1)">点击新增</a>
+        </div>
+      </a-empty>
+
+      <a-row :class="'j-super-query-modal-content'">
+        <a-col :sm="24" :md="18">
+          <a-row v-show="dynamicRowValues.values.length > 0">
+            <a-col :md="12" :xs="24">
+              <a-form-item label="过滤条件匹配" :labelCol="{ md: 6, xs: 24 }" :wrapperCol="{ md: 18, xs: 24 }" style="width: 100%">
+                <a-select v-model:value="matchType" :getPopupContainer="(node) => node.parentNode" style="width: 100%">
+                  <a-select-option value="and">AND(所有条件都要求匹配)</a-select-option>
+                  <a-select-option value="or">OR(条件中的任意一个匹配)</a-select-option>
+                </a-select>
+              </a-form-item>
+            </a-col>
+          </a-row>
+
+          <a-form v-show="dynamicRowValues.values.length > 0" ref="formRef" :class="'jee-super-query-form'" :model="dynamicRowValues" @finish="onFinish">
+            <a-space v-for="(item, index) in dynamicRowValues.values" :key="item.key" style="display: flex; margin-bottom: 8px" align="baseline">
+              <a-form-item :name="['values', index, 'field']" style="width: 180px">
+                <a-tree-select
+                  style="width: 100%"
+                  placeholder="请选择字段"
+                  v-model:value="item.field"
+                  show-search
+                  tree-node-filter-prop="title"
+                  allow-clear
+                  tree-default-expand-all
+                  :dropdown-style="{ maxHeight: '180px', overflow: 'auto' }"
+                  @change="handleChangeField(item)"
+                  :tree-data="fieldTreeData"
+                >
+                </a-tree-select>
+              </a-form-item>
+              <a-form-item :name="['values', index, 'rule']" style="width: 180px">
+                <a-select style="width: 100%" placeholder="请选择匹配规则" v-model:value="item.rule">
+                  <a-select-option value="eq">等于</a-select-option>
+                  <a-select-option value="like">模糊</a-select-option>
+                  <a-select-option value="right_like">以..开始</a-select-option>
+                  <a-select-option value="left_like">以..结尾</a-select-option>
+                  <a-select-option value="in">在...中</a-select-option>
+                  <a-select-option value="ne">不等于</a-select-option>
+                  <a-select-option value="gt">大于</a-select-option>
+                  <a-select-option value="ge">大于等于</a-select-option>
+                  <a-select-option value="lt">小于</a-select-option>
+                  <a-select-option value="le">小于等于</a-select-option>
+                </a-select>
+              </a-form-item>
+              <a-form-item :name="['values', index, 'val']" style="width: 280px">
+                <online-super-query-val-component
+                  style="width: 100%"
+                  :schema="getSchema(item, index)"
+                  :formModel="item"
+                  :setFormModel="
+                    (key, value) => {
+                      setFormModel(key, value, item);
+                    }
+                  "
+                />
+              </a-form-item>
+
+              <a-form-item>
+                <a-button @click="addOne(index)" style="margin-right: 6px">
+                  <PlusOutlined #icon />
+                </a-button>
+                <a-button @click="removeOne(item)">
+                  <MinusCircleOutlined #icon />
+                </a-button>
+              </a-form-item>
+            </a-space>
+          </a-form>
+        </a-col>
+
+        <a-col :sm="24" :md="6">
+          <!-- 查询记录 -->
+          <a-card class="j-super-query-history-card" :bordered="true">
+            <template #title><div>保存的查询</div></template>
+            <a-empty v-if="saveTreeData.length === 0" class="j-super-query-history-empty" description="没有保存任何查询" />
+            <a-tree v-else class="j-super-query-history-tree" :treeData="saveTreeData" :selectedKeys="[]" :show-icon="true" @select="handleTreeSelect">
+              <template #title="{ title }">
+                <div>
+                  <span :title="title">{{ title.length > 10 ? title.substring(0, 10) + '...' : title }}</span>
+                  <span class="icon-cancle"><close-circle-outlined @click="handleRemoveSaveInfo(title)" /></span>
+                </div>
+              </template>
+              <!-- antd-2是这么写的 升级到3会也许会改变写法 -->
+              <template #custom>
+                <file-text-outlined />
+              </template>
+            </a-tree>
+          </a-card>
+        </a-col>
+      </a-row>
+    </BasicModal>
+  </teleport>
+
+  <!-- 保存信息弹框 -->
+  <a-modal title="请输入保存的名称" :visible="saveInfo.visible" @cancel="saveInfo.visible = false" @ok="doSaveQueryInfo">
+    <div style="height: 80px; line-height: 75px; width: 100%; text-align: center">
+      <a-input v-model:value="saveInfo.title" style="width: 90%" placeholder="请输入保存的名称"></a-input>
+    </div>
+  </a-modal>
+</template>
+
+<script lang="ts">
+  import { ref, watch } from 'vue';
+  import { BasicModal, useModal } from '/@/components/Modal';
+  import { useSuperQuery } from './useSuperQuery';
+  import OnlineSuperQueryValComponent from './SuperQueryValComponent.vue';
+  import { MinusCircleOutlined, PlusOutlined, FileTextOutlined, CloseCircleOutlined, AppstoreTwoTone } from '@ant-design/icons-vue';
+  import { Divider } from 'ant-design-vue';
+  import { useMessage } from '/@/hooks/web/useMessage';
+
+  export default {
+    name: 'OnlineSuperQuery',
+    props: {
+      config: {
+        type: Object,
+        default: [],
+      },
+      status: {
+        type: Boolean,
+        default: false,
+      },
+    },
+    components: {
+      BasicModal,
+      MinusCircleOutlined,
+      PlusOutlined,
+      OnlineSuperQueryValComponent,
+      FileTextOutlined,
+      CloseCircleOutlined,
+      AppstoreTwoTone,
+      Divider,
+    },
+    emits: ['search'],
+    setup(props, { emit }) {
+      const [registerFormModal, formModal] = useModal();
+      const { createMessage: $message } = useMessage();
+      /**
+       * 关闭按钮事件
+       */
+      function handleCancel() {
+        formModal.closeModal();
+      }
+
+      /**
+       * 确认按钮事件
+       */
+      function handleSubmit() {
+        //console.log('handleSubmit', dynamicRowValues.values)
+        let dataArray = getQueryInfo(true);
+        if (dataArray && dataArray.length > 0) {
+          let result = getSuperQueryParams(dataArray);
+          //console.log('查询数据1', dataArray)
+          //console.log('查询数据2', result)
+          emit('search', result);
+        } else {
+          $message.warning('空条件无法查询!');
+        }
+      }
+
+      function getSuperQueryParams(dataArray) {
+        let arr: any = [];
+        for (let item of dataArray) {
+          let field = item.field;
+          let val = item.val;
+          if (val instanceof Array) {
+            val = val.join(',');
+          }
+          arr.push({
+            ...item,
+            field,
+            val,
+          });
+        }
+        if (arr.length > 0) {
+          superQueryFlag.value = true;
+        } else {
+          superQueryFlag.value = false;
+        }
+        let result = {
+          superQueryMatchType: matchType.value,
+          superQueryParams: encodeURI(JSON.stringify(arr)),
+        };
+        return result;
+      }
+
+      /**
+       * 重置按钮事件
+       */
+      function handleReset() {
+        dynamicRowValues.values = [];
+        addOne(false);
+        let result = getSuperQueryParams([]);
+        emit('search', result);
+      }
+
+      const {
+        formRef,
+        init,
+        dynamicRowValues,
+        matchType,
+        registerModal,
+
+        handleSave,
+        doSaveQueryInfo,
+        saveInfo,
+        saveTreeData,
+        handleTreeSelect,
+        handleRemoveSaveInfo,
+        fieldTreeData,
+        addOne,
+        removeOne,
+        setFormModel,
+        getSchema,
+        loading,
+        getQueryInfo,
+        initDefaultValues,
+      } = useSuperQuery();
+
+      /*--------------------按钮区域-beign------------------*/
+      const superQueryFlag = ref(false);
+      watch(
+        () => props.status,
+        (val) => {
+          superQueryFlag.value = val;
+        },
+        { immediate: true }
+      );
+
+      function handleOpen() {
+        formModal.openModal();
+        addOne(true);
+      }
+      /*--------------------按钮区域-end------------------*/
+
+      function getPopupContainer() {
+        return document.getElementsByClassName('jee-super-query-form')[0];
+      }
+      function onFinish(a) {
+        console.log('onfinish', a);
+      }
+
+      function handleChangeField(item) {
+        item['val'] = '';
+      }
+
+      watch(
+        () => props.config,
+        (val) => {
+          if (val) {
+            console.log('123', val);
+            console.log('123', val);
+            console.log('123', val);
+            Object.keys(val).map((k) => {
+              console.log(k, val[k]);
+            });
+            console.log('123', val);
+            console.log('123', val);
+            console.log('123', val);
+            init(val);
+          }
+        },
+        { immediate: true }
+      );
+
+      return {
+        formRef,
+        registerFormModal,
+        init,
+        handleChangeField,
+        dynamicRowValues,
+        matchType,
+        registerModal,
+        handleSubmit,
+        handleCancel,
+        handleSave,
+        handleReset,
+        doSaveQueryInfo,
+        saveInfo,
+        saveTreeData,
+        handleTreeSelect,
+        handleRemoveSaveInfo,
+        fieldTreeData,
+        addOne,
+        removeOne,
+        setFormModel,
+        getSchema,
+        loading,
+        onFinish,
+        getPopupContainer,
+        superQueryFlag,
+        handleOpen,
+        initDefaultValues,
+      };
+    },
+  };
+</script>
+
+<style scoped lang="less">
+  .jee-super-query-form .ant-form-item {
+    margin-bottom: 9px;
+  }
+  .j-super-query-history-tree {
+    ::v-deep .ant-tree-switcher {
+      width: 0px;
+    }
+    ::v-deep .ant-tree-node-content-wrapper {
+      width: 100%;
+      &:hover {
+        background-color: #e6f7ff !important;
+        border-radius: 0;
+      }
+    }
+    ::v-deep .ant-tree-treenode-switcher-close {
+      .ant-tree-title {
+        display: inline-block;
+        width: calc(100% - 30px);
+        > div {
+          display: flex;
+          justify-content: space-between;
+          .icon-cancle {
+            display: none;
+            color: #666666;
+            &:hover {
+              color: black;
+            }
+          }
+        }
+      }
+      &:hover {
+        .icon-cancle {
+          display: inline-block !important;
+        }
+      }
+    }
+    ::v-deep .ant-card-body {
+      padding: 0;
+    }
+  }
+  .j-super-query-history-card {
+    ::v-deep .ant-card-body,
+    ::v-deep.ant-card-head-title {
+      padding: 0;
+    }
+  }
+
+  /*VUEN-1087 【移动端】高级查询显示不全 */
+  @media only screen and(max-width: 1050px) {
+    ::v-deep .jee-super-query-form {
+      .ant-space {
+        flex-direction: column;
+        gap: 0 !important;
+        margin-bottom: 16px !important;
+      }
+      .ant-space-item {
+        width: 100%;
+      }
+      .ant-form-item {
+        width: 100% !important;
+      }
+    }
+  }
+</style>

+ 98 - 0
src/components/jeecg/super/superquery/SuperQueryValComponent.vue

@@ -0,0 +1,98 @@
+<script lang="tsx">
+  import { computed, defineComponent, PropType, unref } from 'vue';
+  import { FormSchema } from '/@/components/Form';
+  import { upperFirst } from 'lodash-es';
+  import { componentMap } from '/@/components/Form/src/componentMap';
+  import { createPlaceholderMessage } from '/@/components/Form/src/helper';
+  import { isFunction } from '/@/utils/is';
+
+  export default defineComponent({
+    name: 'OnlineSuperQueryValComponent',
+    inheritAttrs: false,
+    props: {
+      schema: {
+        type: Object as PropType<FormSchema>,
+        default: () => ({}),
+      },
+      formModel: {
+        type: Object as PropType<Recordable>,
+        default: () => ({}),
+      },
+      setFormModel: {
+        type: Function as PropType<(key: string, value: any) => void>,
+        default: null,
+      },
+    },
+    setup(props) {
+      const getComponentsProps = computed(() => {
+        const { schema, formModel } = props;
+        let { componentProps = {} } = schema;
+        if (isFunction(componentProps)) {
+          componentProps = componentProps({ schema, formModel }) ?? {};
+        }
+        return componentProps as Recordable;
+      });
+
+      const getValues = computed(() => {
+        const { formModel, schema } = props;
+        let obj = {
+          field: schema.field,
+          model: formModel,
+          values: {
+            ...formModel,
+          } as Recordable,
+          schema: schema,
+        };
+        return obj;
+      });
+
+      function renderComponent() {
+        const { component, changeEvent = 'change', valueField } = props.schema;
+        const field = 'val';
+        const isCheck = component && ['Switch', 'Checkbox'].includes(component);
+        const eventKey = `on${upperFirst(changeEvent)}`;
+        const on = {
+          [eventKey]: (...args: Nullable<Recordable>[]) => {
+            const [e] = args;
+            if (propsData[eventKey]) {
+              propsData[eventKey](...args);
+            }
+            const target = e ? e.target : null;
+            const value = target ? (isCheck ? target.checked : target.value) : e;
+            props.setFormModel(field, value);
+          },
+        };
+        const Comp = componentMap.get(component) as ReturnType<typeof defineComponent>;
+
+        const propsData: Recordable = {
+          allowClear: true,
+          getPopupContainer: (trigger: Element) => trigger.parentNode,
+          ...unref(getComponentsProps),
+        };
+
+        const isCreatePlaceholder = !propsData.disabled;
+
+        // RangePicker place是一个数组
+        if (isCreatePlaceholder && component !== 'RangePicker' && component) {
+          //自动设置placeholder
+          propsData.placeholder = unref(getComponentsProps)?.placeholder || createPlaceholderMessage(component) + props.schema.label;
+        }
+        propsData.codeField = field;
+        propsData.formValues = unref(getValues);
+        const bindValue: Recordable = {
+          [valueField || (isCheck ? 'checked' : 'value')]: props.formModel[field],
+        };
+        const compAttr: Recordable = {
+          ...propsData,
+          ...on,
+          ...bindValue,
+          allowClear: true,
+        };
+        return <Comp {...compAttr} />;
+      }
+      return () => {
+        return <div style="width:100%">{renderComponent()}</div>;
+      };
+    },
+  });
+</script>

+ 524 - 0
src/components/jeecg/super/superquery/useSuperQuery.ts

@@ -0,0 +1,524 @@
+import { useModalInner } from '/@/components/Modal';
+import { randomString } from '/@/utils/common/compUtils';
+import { reactive, ref, toRaw, watch } from 'vue';
+import { useMessage } from '/@/hooks/web/useMessage';
+import { Modal } from 'ant-design-vue';
+import { createLocalStorage } from '/@/utils/cache';
+import { useRoute } from 'vue-router';
+import FormSchemaFactory from '/@/views/super/online/cgform/auto/comp/factory/FormSchemaFactory';
+/**
+ * 表单类型转换成查询类型
+ * 普通查询和高级查询组件区别 :高级查询不支持联动组件
+ */
+const FORM_VIEW_TO_QUERY_VIEW = {
+  password: 'text',
+  file: 'text',
+  image: 'text',
+  textarea: 'text',
+  umeditor: 'text',
+  markdown: 'text',
+  checkbox: 'list_multi',
+  radio: 'list',
+};
+
+// 查询条件存储编码前缀
+const SAVE_CODE_PRE = 'JSuperQuerySaved_';
+
+/**
+ * 查询项
+ * */
+interface SuperQueryItem {
+  field: string | undefined;
+  rule: string | undefined;
+  val: string | number;
+  key: string;
+}
+/**
+ * 查询项-第一个控件树model
+ * */
+interface TreeModel {
+  title: string;
+  value: string;
+  isLeaf?: boolean;
+  disabled?: boolean;
+  children?: TreeModel[];
+  order?: number;
+}
+
+/**
+ * 查询信息保存结构
+ * */
+interface SaveModel {
+  title: string;
+  content: string;
+  type: string;
+}
+
+export function useSuperQuery() {
+  const { createMessage: $message } = useMessage();
+  /** 表单ref*/
+  const formRef = ref<any>();
+
+  /** 数据*/
+  const dynamicRowValues = reactive<{ values: SuperQueryItem[] }>({
+    values: [],
+  });
+  /** and/or */
+  const matchType = ref('and');
+
+  // 弹框显示
+  const [registerModal, { setModalProps }] = useModalInner(() => {
+    setModalProps({ confirmLoading: false });
+  });
+
+  // 高级查询类型不支持联动组件,需要额外设置联动组件的view为text
+  const view2QueryViewMap = Object.assign({}, { link_down: 'text' }, FORM_VIEW_TO_QUERY_VIEW);
+
+  /**
+   * 确认按钮事件
+   */
+  function handleSubmit() {
+    console.log('handleSubmit', dynamicRowValues.values);
+  }
+
+  /**
+   * 关闭按钮事件
+   */
+  function handleCancel() {
+    //closeModal();
+  }
+
+  /**
+   * val组件赋值
+   */
+  function setFormModel(key: string, value: any, item: any) {
+    console.log('setFormModel', key, value);
+    // formModel[key] = value;
+    item['val'] = value;
+  }
+
+  // 字段-Properties
+  const fieldProperties = ref<any>({});
+  // 字段-左侧查询项-树控件数据
+  const fieldTreeData = ref<any>([]);
+
+  /**
+   * 初始化数据-最开始的方法
+   * 1.获取 表名@字段名-->配置 这样的一个map
+   * 2.获取树形结构的数据 显示:文本; 存储:表名@字段名
+   * 当树改变时,及时获取配置更新表单
+   * @param json
+   */
+  function init(json) {
+    let { allFields, treeData } = getAllFields(json);
+    fieldProperties.value = allFields;
+    fieldTreeData.value = treeData;
+  }
+
+  /**
+   * 左侧查询项 添加一行
+   * @param index
+   */
+  function addOne(index) {
+    let item = {
+      field: undefined,
+      rule: 'eq',
+      val: '',
+      key: randomString(16),
+    };
+    if (index === false) {
+      // 重置后需要调用
+      dynamicRowValues.values = [];
+      dynamicRowValues.values.push(item);
+    } else if (index === true) {
+      // 打开弹框是需要调用
+      if (dynamicRowValues.values.length == 0) {
+        dynamicRowValues.values.push(item);
+      }
+    } else {
+      // 其余就是 正常的点击加号增加行
+      dynamicRowValues.values.splice(++index, 0, item);
+    }
+  }
+
+  /**
+   * 左侧查询项 删除一行
+   */
+  function removeOne(item: SuperQueryItem) {
+    let arr = toRaw(dynamicRowValues.values);
+    let index = -1;
+    for (let i = 0; i < arr.length; i++) {
+      if (item.key == arr[i].key) {
+        index = i;
+        break;
+      }
+    }
+    if (index != -1) {
+      dynamicRowValues.values.splice(index, 1);
+    }
+  }
+
+  // 默认的输入框
+  const defaultInput = {
+    field: 'val',
+    label: '测试',
+    component: 'Input',
+  };
+
+  /**
+   * 左侧查询项 val组件 schema获取, 替代左侧字段树的change事件
+   * @param item
+   * @param index
+   */
+  function getSchema(item, index) {
+    let map = fieldProperties.value;
+    let prop = map[item.field];
+    if (!prop) {
+      return defaultInput;
+    }
+    if (view2QueryViewMap[prop.view]) {
+      // 如果出现查询条件联动组件出来的场景,请跟踪此处
+      prop.view = view2QueryViewMap[prop.view];
+    }
+    let temp = FormSchemaFactory.createFormSchema(item.field, prop);
+    // temp.setFormRef(formRef)
+    temp.noChange();
+    // 查询条件中的 下拉框popContainer为parentNode
+    temp.asSearchForm();
+    temp.updateField(item.field + index);
+    const setFieldValue = (values) => {
+      item['val'] = values[item.field];
+    };
+    temp.setFunctionForFieldValue(setFieldValue);
+    let schema = temp.getFormItemSchema();
+    //schema['valueField'] = 'val'
+    return schema;
+  }
+
+  /*-----------------------右侧保存信息相关-begin---------------------------*/
+
+  /**
+   * 右侧树 的 数据
+   */
+  const saveTreeData = ref<any>('');
+  // 本地缓存
+  const $ls = createLocalStorage();
+  //需要保存的信息(一条)
+  const saveInfo = reactive({
+    visible: false,
+    title: '',
+    content: '',
+    saveCode: '',
+  });
+  //按钮loading
+  const loading = ref(false);
+
+  // 当前页面路由
+  const route = useRoute();
+  // 监听路由信息,路由发生改变,则重新获取保存的查询信息-->currentPageSavedArray
+  watch(
+    () => route.fullPath,
+    (val) => {
+      console.log('fullpath', val);
+      initSaveQueryInfoCode();
+    }
+  );
+
+  // 当前页面存储的 查询信息
+  const currentPageSavedArray = ref<SaveModel[]>([]);
+  // 监听当前页面是否有新的数据保存了,然后更新右侧数据->saveTreeData
+  watch(
+    () => currentPageSavedArray.value,
+    (val) => {
+      let temp: any[] = [];
+      if (val && val.length > 0) {
+        val.map((item) => {
+          let key = randomString(16);
+          temp.push({
+            title: item.title,
+            slots: { icon: 'custom' },
+            value: key,
+          });
+        });
+      }
+      saveTreeData.value = temp;
+    },
+    { immediate: true, deep: true }
+  );
+
+  // 重新获取保存的查询信息
+  function initSaveQueryInfoCode() {
+    let code = SAVE_CODE_PRE + route.fullPath;
+    saveInfo.saveCode = code;
+    let list = $ls.get(code);
+    if (list && list instanceof Array) {
+      currentPageSavedArray.value = list;
+    }
+  }
+
+  // 执行一次 获取保存的查询信息
+  initSaveQueryInfoCode();
+
+  /**
+   * 保存按钮事件
+   */
+  function handleSave() {
+    // 获取实际数据转成字符串
+    let fieldArray = getQueryInfo();
+    if (!fieldArray) {
+      $message.warning('空条件不能保存');
+      return;
+    }
+    let content = JSON.stringify(fieldArray);
+    openSaveInfoModal(content);
+  }
+
+  // 输入保存标题 弹框显示
+  function openSaveInfoModal(content) {
+    saveInfo.visible = true;
+    saveInfo.title = '';
+    saveInfo.content = content;
+  }
+
+  /**
+   * 确认保存查询信息
+   */
+  function doSaveQueryInfo() {
+    let { title, content, saveCode } = saveInfo;
+    let index = getTitleIndex(title);
+    if (index >= 0) {
+      // 已存在是否覆盖
+      Modal.confirm({
+        title: '提示',
+        content: `${title} 已存在,是否覆盖?`,
+        okText: '确认',
+        cancelText: '取消',
+        onOk: () => {
+          currentPageSavedArray.value.splice(index, 1, {
+            content,
+            title,
+            type: matchType.value,
+          });
+          $ls.set(saveCode, currentPageSavedArray.value);
+          saveInfo.visible = false;
+        },
+      });
+    } else {
+      currentPageSavedArray.value.push({
+        content,
+        title,
+        type: matchType.value,
+      });
+      $ls.set(saveCode, currentPageSavedArray.value);
+      saveInfo.visible = false;
+    }
+  }
+
+  // 根据填入的 title找本地存储的信息,如果有需要询问是否覆盖
+  function getTitleIndex(title) {
+    let savedArray = currentPageSavedArray.value;
+    let index = -1;
+    for (let i = 0; i < savedArray.length; i++) {
+      if (savedArray[i].title == title) {
+        index = i;
+        break;
+      }
+    }
+    return index;
+  }
+
+  /**
+   * 获取左侧所有查询条件,如果没有/或者条件无效则返回false
+   */
+  function getQueryInfo(isEmit = false) {
+    let arr = dynamicRowValues.values;
+    if (!arr || arr.length == 0) {
+      return false;
+    }
+    let fieldArray: any = [];
+    let fieldProps = fieldProperties.value;
+    for (let item of arr) {
+      if (item.field && (item.val || item.val === 0) && item.rule) {
+        let tempVal: any = toRaw(item.val);
+        if (tempVal instanceof Array) {
+          tempVal = tempVal.join(',');
+        }
+        let fieldName = getRealFieldName(item);
+        let obj = {
+          field: fieldName,
+          rule: item.rule,
+          val: tempVal,
+        };
+        if (isEmit === true) {
+          //如果当前数据用于emit事件,需要设置dbtype和type
+          let prop = fieldProps[item.field];
+          if (prop) {
+            obj['type'] = prop.view;
+            obj['dbType'] = prop.type;
+          }
+        }
+        fieldArray.push(obj);
+      }
+    }
+    if (fieldArray.length == 0) {
+      return false;
+    }
+    return fieldArray;
+  }
+
+  //update-begin-author:taoyan date:2022-5-31 for: VUEN-1148 主子联动下,高级查询查子表数据,无效
+  /**
+   * 高级查询参数 字段名
+   * 获取后台需要的 字段名格式:表名,字段名
+   * @param item
+   */
+  function getRealFieldName(item) {
+    let fieldName = item.field;
+    if (fieldName.indexOf('@') > 0) {
+      fieldName = fieldName.replace('@', ',');
+    }
+    return fieldName;
+  }
+  //update-end-author:taoyan date:2022-5-31 for: VUEN-1148 主子联动下,高级查询查子表数据,无效
+
+  /**
+   * 右侧数据 点击事件,重新将数据显示到左侧
+   * @param key
+   * @param node
+   */
+  function handleTreeSelect(key, { node }) {
+    console.log(key, node);
+    let title = node.dataRef.title;
+    let arr = currentPageSavedArray.value.filter((item) => item.title == title);
+    if (arr && arr.length > 0) {
+      // 拿到数据渲染
+      let { content, type } = arr[0];
+      let data = JSON.parse(content);
+      let rowsValues: SuperQueryItem[] = [];
+      for (let item of data) {
+        rowsValues.push(Object.assign({}, { key: randomString(16) }, item));
+      }
+      dynamicRowValues.values = rowsValues;
+      matchType.value = type;
+    }
+  }
+
+  /**
+   * 右侧数据 删除事件
+   */
+  function handleRemoveSaveInfo(title) {
+    console.log(title);
+    let index = getTitleIndex(title);
+    if (index >= 0) {
+      currentPageSavedArray.value.splice(index, 1);
+      $ls.set(saveInfo.saveCode, currentPageSavedArray.value);
+    }
+  }
+
+  /*-----------------------右侧保存信息相关-end---------------------------*/
+
+  // 获取所有字段配置信息
+  function getAllFields(properties) {
+    // 获取所有配置 查询字段 是否联合查询
+    // const {properties, table, title } = json;
+    let allFields = {};
+    let order = 1;
+    let treeData: TreeModel[] = [];
+    /*   let mainNode:TreeModel = {
+      title,
+      value: table,
+      disabled: true,
+      children: []
+    };*/
+    //treeData.push(mainNode)
+    Object.keys(properties).map((field) => {
+      let item = properties[field];
+      if (item.view == 'table') {
+        // 子表字段
+        // 联合查询开启才需要子表字段作为查询条件
+        let subProps = item['properties'] || item['fields'];
+        let subTableOrder = order * 100;
+        let subNode: TreeModel = {
+          title: item.title,
+          value: field,
+          disabled: true,
+          children: [],
+          order: subTableOrder,
+        };
+        Object.keys(subProps).map((subField) => {
+          let subItem = subProps[subField];
+          // 保证排序统一
+          subItem['order'] = subTableOrder + subItem['order'];
+          let subFieldKey = field + '@' + subField;
+          allFields[subFieldKey] = subItem;
+          subNode.children!.push({
+            title: subItem.title,
+            value: subFieldKey,
+            isLeaf: true,
+            order: subItem['order'],
+          });
+        });
+        orderField(subNode);
+        treeData.push(subNode);
+        order++;
+      } else {
+        // 主表字段
+        //let fieldKey = table+'@'+field
+        let fieldKey = field;
+        allFields[fieldKey] = item;
+        treeData.push({
+          title: item.title,
+          value: fieldKey,
+          isLeaf: true,
+          order: item.order,
+        });
+      }
+    });
+    orderField(treeData);
+    return { allFields, treeData };
+  }
+
+  //根据字段的order重新排序
+  function orderField(data) {
+    let arr = data.children || data;
+    arr.sort(function (a, b) {
+      return a.order - b.order;
+    });
+  }
+
+  function initDefaultValues(values) {
+    const { params, matchType } = values;
+    if (params) {
+      let rowsValues: SuperQueryItem[] = [];
+      for (let item of params) {
+        rowsValues.push(Object.assign({}, { key: randomString(16) }, item));
+      }
+      dynamicRowValues.values = rowsValues;
+      matchType.value = matchType;
+    }
+  }
+
+  return {
+    formRef,
+    init,
+    dynamicRowValues,
+    matchType,
+    registerModal,
+    handleSubmit,
+    handleCancel,
+    handleSave,
+    doSaveQueryInfo,
+    saveInfo,
+    saveTreeData,
+    handleRemoveSaveInfo,
+    handleTreeSelect,
+    fieldTreeData,
+    addOne,
+    removeOne,
+    setFormModel,
+    getSchema,
+    loading,
+    getQueryInfo,
+    initDefaultValues,
+  };
+}

+ 1 - 0
src/design/index.less

@@ -3,6 +3,7 @@
 @import 'public.less';
 @import 'ant/index.less';
 @import './theme.less';
+@import './lowApp/global.less';
 
 input:-webkit-autofill {
   -webkit-box-shadow: 0 0 0 1000px white inset !important;

+ 30 - 0
src/design/lowApp/global.less

@@ -0,0 +1,30 @@
+// ---------------
+//  lowApp全局样式
+// ---------------
+
+// 生成display样式
+.low-app-display(@type) {
+  display: @type !important;
+
+  & + .ant-divider,
+  & + .ant-dropdown-menu-item-divider {
+    display: @type !important;
+  }
+}
+
+// lowApp外隐藏
+.low-app-show {
+  .low-app-display(none);
+}
+
+[data-low-app] {
+  // lowApp内隐藏
+  .low-app-hide {
+    .low-app-display(none);
+  }
+
+  // lowApp内显示
+  .low-app-show {
+    .low-app-display(block);
+  }
+}

+ 2 - 0
src/enums/httpEnum.ts

@@ -45,4 +45,6 @@ export enum ConfigEnum {
   TENANT_ID = 'tenant-id',
   // 版本
   VERSION = 'X-Version',
+  // 低代码应用ID
+  X_LOW_APP_ID = 'X-Low-App-ID',
 }

+ 2 - 0
src/enums/jeecgEnum.ts

@@ -18,4 +18,6 @@ export enum JInputTypeEnum {
 export enum JDragConfigEnum {
   //baseURL
   DRAG_BASE_URL = 'drag-base-url',
+  //拖拽缓存前缀
+  DRAG_CACHE_PREFIX = 'drag-cache:',
 }

+ 2 - 0
src/enums/pageEnum.ts

@@ -7,4 +7,6 @@ export enum PageEnum {
   ERROR_PAGE = '/exception',
   // error log page path
   ERROR_LOG_PAGE = '/error-log/list',
+  // auth2登录路由路径
+  OAUTH2_LOGIN_PAGE_PATH = '/oauth2-app/login',
 }

+ 1 - 1
src/hooks/web/useWebSocket.ts

@@ -28,7 +28,7 @@ export function connectWebSocket(url: string) {
       autoReconnect: true,
       // 心跳检测
       heartbeat: false,
-      //protocols: [token],
+      protocols: [token],
     });
     //update-end-author:taoyan date:2022-4-24 for: v2.4.6 的 websocket 服务端,存在性能和安全问题。 #3278
     result.value.open();

+ 6 - 1
src/layouts/default/header/components/notify/index.vue

@@ -144,7 +144,12 @@
 
       function onWebSocketMessage(data) {
         if (data.cmd === 'topic' || data.cmd === 'user') {
-          loadData();
+          //update-begin-author:taoyan date:2022-7-13 for: VUEN-1674【严重bug】系统通知,为什么必须刷新右上角才提示
+          //后台保存数据太慢 前端延迟刷新消息
+          setTimeout(() => {
+            loadData();
+          }, 1000);
+          //update-end-author:taoyan date:2022-7-13 for: VUEN-1674【严重bug】系统通知,为什么必须刷新右上角才提示
         }
       }
 

+ 1 - 1
src/layouts/default/index.vue

@@ -14,7 +14,7 @@
 </template>
 
 <script lang="ts">
-  import { defineComponent, computed, unref } from 'vue';
+  import { defineComponent, computed, unref, ref } from 'vue';
   import { Layout } from 'ant-design-vue';
   import { createAsyncComponent } from '/@/utils/factory/createAsyncComponent';
 

+ 32 - 2
src/router/guard/permissionGuard.ts

@@ -9,11 +9,17 @@ import { PAGE_NOT_FOUND_ROUTE } from '/@/router/routes/basic';
 
 import { RootRoute } from '/@/router/routes';
 
+import { isOAuth2AppEnv } from '/@/views/sys/login/useLogin';
+
 const LOGIN_PATH = PageEnum.BASE_LOGIN;
+//auth2登录路由
+const OAUTH2_LOGIN_PAGE_PATH = PageEnum.OAUTH2_LOGIN_PAGE_PATH;
 
 const ROOT_PATH = RootRoute.path;
 
-const whitePathList: PageEnum[] = [LOGIN_PATH];
+//update-begin---author:wangshuai ---date:20220629  for:[issues/I5BG1I]vue3不支持auth2登录------------
+const whitePathList: PageEnum[] = [LOGIN_PATH, OAUTH2_LOGIN_PAGE_PATH];
+//update-end---author:wangshuai ---date:20220629  for:[issues/I5BG1I]vue3不支持auth2登录------------
 
 export function createPermissionGuard(router: Router) {
   const userStore = useUserStoreWithOut();
@@ -37,6 +43,13 @@ export function createPermissionGuard(router: Router) {
             return;
           }
         } catch {}
+        //update-begin---author:wangshuai ---date:20220629  for:[issues/I5BG1I]vue3不支持auth2登录------------
+      } else if (to.path === LOGIN_PATH && isOAuth2AppEnv() && !token) {
+        //退出登录进入此逻辑
+        //如果进入的页面是login页面并且当前是OAuth2app环境,并且token为空,就进入OAuth2登录页面
+        next({ path: OAUTH2_LOGIN_PAGE_PATH });
+        return;
+        //update-end---author:wangshuai ---date:20220629  for:[issues/I5BG1I]vue3不支持auth2登录------------
       }
       next();
       return;
@@ -50,9 +63,26 @@ export function createPermissionGuard(router: Router) {
         return;
       }
 
+      //update-begin---author:wangshuai ---date:20220629  for:[issues/I5BG1I]vue3 Auth2未实现------------
+      let path = LOGIN_PATH;
+      if (whitePathList.includes(to.path as PageEnum)) {
+        // 在免登录白名单,如果进入的页面是login页面并且当前是OAuth2app环境,就进入OAuth2登录页面
+        if (to.path === LOGIN_PATH && isOAuth2AppEnv()) {
+          next({ path: OAUTH2_LOGIN_PAGE_PATH });
+        } else {
+          //在免登录白名单,直接进入
+          next();
+        }
+      } else {
+        // 如果当前是在OAuth2APP环境,就跳转到OAuth2登录页面,否则跳转到登录页面
+        path = isOAuth2AppEnv() ? OAUTH2_LOGIN_PAGE_PATH : LOGIN_PATH;
+      }
+      //update-end---author:wangshuai ---date:20220629  for:[issues/I5BG1I]vue3 Auth2未实现------------
       // redirect login page
       const redirectData: { path: string; replace: boolean; query?: Recordable<string> } = {
-        path: LOGIN_PATH,
+        //update-begin---author:wangshuai ---date:20220629  for:[issues/I5BG1I]vue3 Auth2未实现------------
+        path: path,
+        //update-end---author:wangshuai ---date:20220629  for:[issues/I5BG1I]vue3 Auth2未实现------------
         replace: true,
       };
       if (to.path) {

+ 8 - 3
src/router/helper/routeHelper.ts

@@ -5,7 +5,7 @@ import { getParentLayout, LAYOUT, EXCEPTION_COMPONENT } from '/@/router/constant
 import { cloneDeep, omit } from 'lodash-es';
 import { warn } from '/@/utils/log';
 import { createRouter, createWebHashHistory } from 'vue-router';
-import { getToken } from '/@/utils/auth';
+import { getTenantId, getToken } from '/@/utils/auth';
 import { URL_HASH_TAB } from '/@/utils';
 import { packageViews } from '/@/utils/monorepo/dynamicRouter';
 
@@ -45,9 +45,14 @@ function asyncImportRoute(routes: AppRouteRecordRaw[] | undefined) {
     // @ts-ignore 添加是否缓存路由配置
     item.meta.ignoreKeepAlive = !item?.meta.keepAlive;
     let token = getToken();
+    let tenantId = getTenantId();
     // URL支持{{ window.xxx }}占位符变量
-    item.component = (item.component || '').replace(/{{([^}}]+)?}}/g, (s1, s2) => eval(s2)).replace('${token}', token);
-
+    //update-begin---author:wangshuai ---date:20220711  for:[VUEN-1638]菜单tenantId需要动态生成------------
+    item.component = (item.component || '')
+      .replace(/{{([^}}]+)?}}/g, (s1, s2) => eval(s2))
+      .replace('${token}', token)
+      .replace('${tenantId}', tenantId);
+    //update-end---author:wangshuai ---date:20220711  for:[VUEN-1638]菜单tenantId需要动态生成------------
     // 适配 iframe
     if (/^\/?http(s)?/.test(item.component as string)) {
       item.component = item.component.substring(1, item.component.length);

+ 25 - 1
src/router/routes/index.ts

@@ -36,5 +36,29 @@ export const LoginRoute: AppRouteRecordRaw = {
   },
 };
 
+//update-begin---author:wangshuai ---date:20220629  for:auth2登录页面路由------------
+export const Oauth2LoginRoute: AppRouteRecordRaw = {
+  path: '/oauth2-app/login',
+  name: 'oauth2-app-login',
+  component: () => import('/@/views/sys/login/OAuth2Login.vue'),
+  meta: {
+    title: t('routes.oauth2.login'),
+  },
+};
+//update-end---author:wangshuai ---date:20220629  for:auth2登录页面路由------------
+
+/**
+ * 【通过token直接静默登录】流程办理登录页面 中转跳转
+ */
+export const TokenLoginRoute: AppRouteRecordRaw = {
+  path: '/tokenLogin',
+  name: 'TokenLoginRoute',
+  component: () => import('/@/views/sys/login/TokenLoginPage.vue'),
+  meta: {
+    title: '带token登录页面',
+    ignoreAuth: true,
+  },
+};
+
 // Basic routing without permission
-export const basicRoutes = [LoginRoute, RootRoute, ...mainOutRoutes, REDIRECT_ROUTE, PAGE_NOT_FOUND_ROUTE];
+export const basicRoutes = [LoginRoute, RootRoute, ...mainOutRoutes, REDIRECT_ROUTE, PAGE_NOT_FOUND_ROUTE, TokenLoginRoute, Oauth2LoginRoute];

+ 2 - 2
src/store/modules/permission.ts

@@ -244,8 +244,8 @@ export const usePermissionStore = defineStore({
                   createWarningModal({
                     title: '提示',
                     content:
-                      '检测到你可能使用了<b>非vue3版本</b>的数据库表,这将会导致菜单或其他功能出现异常,请更换成vue3版本的数据库表后刷新。' +
-                      '<br>文档地址:<a href="http://vue3.jeecg.com/2671576" target="_blank">http://vue3.jeecg.com/2671576</a>',
+                      '检测到当前菜单表是 <b>Vue2版本</b> 的,这将导致菜单加载异常,请更换成vue3版本的表!' +
+                      '<br>切换文档:<a href="http://vue3.jeecg.com/2671576" target="_blank">http://vue3.jeecg.com/2671576</a>',
                   }),
                 1500
               );

+ 9 - 0
src/utils/auth/index.ts

@@ -53,6 +53,15 @@ export function getCacheByDynKey<T>(key) {
   const fn = isLocal ? Persistent.getLocal : Persistent.getSession;
   return fn(key) as T;
 }
+
+/**
+ * 移除动态key
+ * @param key
+ */
+export function removeCacheByDynKey<T>(key) {
+  const fn = isLocal ? Persistent.removeLocal : Persistent.removeSession;
+  return fn(key) as T;
+}
 /**
  * 移除缓存中的某个属性
  * @param key

+ 1 - 0
src/utils/dict/JDictSelectUtil.js

@@ -8,6 +8,7 @@ import { ajaxGetDictItems, getDictItemsByCode } from './index';
 
 /**
  * 获取字典数组
+ * 【目前仅表单设计器页面使用该方法】
  * @param dictCode 字典Code
  * @param isTransformResponse 是否转换返回结果
  * @return List<Map>

+ 15 - 0
src/utils/http/axios/index.ts

@@ -6,6 +6,7 @@ import type { RequestOptions, Result } from '/#/axios';
 import type { AxiosTransform, CreateAxiosOptions } from './axiosTransform';
 import { VAxios } from './Axios';
 import { checkStatus } from './checkStatus';
+import { router } from '/@/router';
 import { useGlobSetting } from '/@/hooks/setting';
 import { useMessage } from '/@/hooks/web/useMessage';
 import { RequestEnum, ResultEnum, ContentTypeEnum, ConfigEnum } from '/@/enums/httpEnum';
@@ -160,6 +161,20 @@ const transform: AxiosTransform = {
       config.headers[ConfigEnum.VERSION] = 'v3';
       //--update-end--author:liusq---date:20220325---for:增加vue3标记
       //--update-end--author:liusq---date:20211105---for:将多租户id,添加在请求接口 Header
+
+      // ========================================================================================
+      // update-begin--author:sunjianlei---date:20220624--for: 添加低代码应用ID
+      let routeParams = router.currentRoute.value.params;
+      if (routeParams.appId) {
+        config.headers[ConfigEnum.X_LOW_APP_ID] = routeParams.appId;
+        // lowApp自定义筛选条件
+        if (routeParams.lowAppFilter) {
+          config.params = { ...config.params, ...JSON.parse(routeParams.lowAppFilter as string) };
+          delete routeParams.lowAppFilter;
+        }
+      }
+      // update-end--author:sunjianlei---date:20220624--for: 添加低代码应用ID
+      // ========================================================================================
     }
     return config;
   },

+ 19 - 0
src/utils/index.ts

@@ -292,3 +292,22 @@ export function importViewsFile(path): Promise<any> {
   });
 }
 //update-end-author:taoyan date:2022-6-8 for:解决老的vue2动态导入文件语法 vite不支持的问题
+
+/**
+ * 跳转至积木报表的 预览页面
+ * @param url
+ * @param id
+ * @param token
+ */
+export function goJmReportViewPage(url, id, token) {
+  // URL支持{{ window.xxx }}占位符变量
+  url = url.replace(/{{([^}]+)?}}/g, (_s1, s2) => eval(s2));
+  if (url.includes('?')) {
+    url += '&';
+  } else {
+    url += '?';
+  }
+  url += `id=${id}`;
+  url += `&token=${token}`;
+  window.open(url);
+}

+ 10 - 0
src/views/dashboard/Analysis/components/QuickNav.vue

@@ -38,6 +38,16 @@
       icon: 'ion:settings-outline',
       color: '#3fb27f',
     },
+    {
+      title: '通知公告',
+      icon: 'ion:notifications',
+      color: '#13b0ff',
+    },
+    {
+      title: '我的任务',
+      icon: 'ion:person-stalker',
+      color: '#b27315',
+    },
   ];
 
   function goPage() {

+ 1 - 1
src/views/dashboard/Analysis/homePage/IndexTask.vue

@@ -259,7 +259,7 @@
     dataSource1.value = tempSs1;
     dataSource2.value = tempSs2;
     dataSource3.value = tempSs1;
-    dataSource4.value = [];
+    dataSource4.value = tempSs2;
     ifNullDataSource(dataSource4, '.tytable4');
   }
 

+ 4 - 4
src/views/demo/jeecg/JVxeTableDemo/func-demo/JSBCDemo.vue

@@ -19,7 +19,7 @@
       :dataSource="dataSource"
       :pagination="pagination"
       @save="handleTableSave"
-      @remove="handleTableRemove"
+      @removed="handleTableRemove"
       @edit-closed="handleEditClosed"
       @pageChange="handlePageChange"
       @selectRowChange="handleSelectRowChange"
@@ -132,13 +132,13 @@
       // 校验通过
       if (!errMap) {
         // 获取所有数据
-        let tableData = target.ctx.getTableData();
+        let tableData = target.getTableData();
         console.log('当前保存的数据是:', tableData);
         // 获取新增的数据
-        let newData = target.ctx.getNewData();
+        let newData = target.getNewData();
         console.log('-- 新增的数据:', newData);
         // 获取删除的数据
-        let deleteData = target.ctx.getDeleteData();
+        let deleteData = target.getDeleteData();
         console.log('-- 删除的数据:', deleteData);
         // 【模拟保存】
         loading.value = true;

+ 22 - 0
src/views/demo/jeecg/JeecgComponents.vue

@@ -33,6 +33,9 @@
     <template #dargVerify="{ model, field }">
       <BasicDragVerify v-model:value="model[field]" />
     </template>
+    <template #superQuery="{ model, field }">
+      <super-query :config="superQueryConfig" @search="(value) => handleSuperQuery(value, model, field)" />
+    </template>
   </BasicForm>
 </template>
 <script lang="ts">
@@ -44,6 +47,7 @@
   import { schemas } from './jeecgComponents.data.ts';
   import { usePermission } from '/@/hooks/web/usePermission';
   import { BasicDragVerify } from '/@/components/Verify/index';
+  import SuperQuery from '/@/components/jeecg/super/superquery/SuperQuery.vue';
 
   export default defineComponent({
     components: {
@@ -56,6 +60,7 @@
       JInput,
       JEllipsis,
       BasicDragVerify,
+      SuperQuery,
     },
     name: 'JeecgComponents',
     setup() {
@@ -75,6 +80,21 @@
         keyword.value = value;
       }
 
+      const superQueryConfig = {
+        name: { title: '名称', view: 'text', type: 'string', order: 1 },
+        birthday: { title: '生日', view: 'date', type: 'string', order: 2 },
+        age: { title: '年龄', view: 'number', type: 'number', order: 4 },
+        sex: { title: '性别', view: 'list', type: 'string', dictCode: 'sex', order: 5 },
+        bpmStatus: { title: '流程状态', view: 'list_multi', type: 'string', dictCode: 'bpm_status', order: 6 },
+      };
+      function handleSuperQuery(value, model, field) {
+        if (value) {
+          let str = decodeURI(value.superQueryParams);
+          console.log(str);
+          model[field] = str;
+        }
+      }
+
       return {
         schemas,
         formElRef,
@@ -83,6 +103,8 @@
         submitButtonOptions,
         onSearch: useDebounceFn(onSearch, 300),
         searchParams,
+        superQueryConfig,
+        handleSuperQuery,
         handleReset: () => {
           keyword.value = '';
         },

+ 14 - 0
src/views/demo/jeecg/jeecgComponents.data.ts

@@ -621,4 +621,18 @@ export const schemas: FormSchema[] = [
     label: '选中值',
     colProps: { span: 12 },
   },
+  {
+    field: 'superQuery',
+    component: 'Input',
+    label: '高级查询',
+    helpMessage: ['插槽模式'],
+    slot: 'superQuery',
+    colProps: { span: 12 },
+  },
+  {
+    field: 'superQuery',
+    component: 'JEllipsis',
+    label: '选中值',
+    colProps: { span: 12 },
+  },
 ];

+ 6 - 2
src/views/demo/vextable/OneToOneModal.vue

@@ -117,9 +117,13 @@
           Object.assign(orderMainModel, data.record);
           let params = { id: orderMainModel.id };
           const customerList = await orderCustomerList(params);
-          orderMainModel.jeecgOrderCustomerList = customerList[0];
+          //update-begin---author:wangshuai ---date:20220629  for:[VUEN-1484]在一对多示例页面,编辑一行(青岛订单A0001),客户信息无法填入------------
+          orderMainModel.jeecgOrderCustomerList = customerList[0] ? customerList[0] : {};
+          //update-end---author:wangshuai ---date:20220629  for:[VUEN-1484]在一对多示例页面,编辑一行(青岛订单A0001),客户信息无法填入--------------
           const ticketList = await orderTicketList(params);
-          orderMainModel.jeecgOrderTicketList = ticketList[0];
+          //update-begin---author:wangshuai ---date:20220629  for:[VUEN-1484]在一对多示例页面,编辑一行(青岛订单A0001),客户信息无法填入------------
+          orderMainModel.jeecgOrderTicketList = ticketList[0] ? ticketList[0] : {};
+          //update-end---author:wangshuai ---date:20220629  for:[VUEN-1484]在一对多示例页面,编辑一行(青岛订单A0001),客户信息无法填入--------------
         }
       });
       const getTitle = computed(() => (!unref(isUpdate) ? '新增' : '编辑'));

+ 121 - 1
src/views/demo/vextable/data.ts

@@ -1,4 +1,6 @@
-import { BasicColumn } from '/@/components/Table';
+import { BasicColumn, FormSchema } from '/@/components/Table';
+import { usePermission } from '/@/hooks/web/usePermission';
+import { JVxeColumn, JVxeTypes } from '/@/components/jeecg/JVxeTable/types';
 
 export const columns: BasicColumn[] = [
   {
@@ -26,4 +28,122 @@ export const columns: BasicColumn[] = [
     width: 200,
     dataIndex: 'content',
   },
+  {
+    title: '流程状态',
+    width: 200,
+    dataIndex: 'bpmStatus',
+    customRender: ({ text }) => {
+      if (!text || text == '1') {
+        return '待提交';
+      } else if (text == '2') {
+        return '处理中';
+      } else if (text == '2') {
+        return '已完成';
+      } else {
+        return text;
+      }
+    },
+  },
+];
+
+export function getBpmFormSchema(formData) {
+  const { isDisabledAuth, hasPermission } = usePermission(formData);
+  const formSchema2: FormSchema[] = [
+    {
+      label: '订单号',
+      field: 'orderCode',
+      component: 'Input',
+      show: ({ values }) => {
+        return hasPermission('order:orderCode');
+      },
+    },
+    {
+      label: '订单类型',
+      field: 'ctype',
+      component: 'Select',
+      componentProps: {
+        options: [
+          { label: '国内订单', value: '1', key: '1' },
+          { label: '国际订单', value: '2', key: '2' },
+        ],
+      },
+    },
+    {
+      label: '订单日期',
+      field: 'orderDate',
+      component: 'DatePicker',
+      componentProps: {
+        valueFormat: 'YYYY-MM-DD HH:mm:ss',
+        style: {
+          width: '100%',
+        },
+      },
+    },
+    {
+      label: '订单金额',
+      field: 'orderMoney',
+      component: 'Input',
+    },
+    {
+      label: '订单备注',
+      field: 'content',
+      component: 'Input',
+    },
+  ];
+  return formSchema2;
+}
+
+export function getOrderCustomerFormSchema(formData) {
+  const { isDisabledAuth, hasPermission } = usePermission(formData);
+  const formSchema2: FormSchema[] = [
+    {
+      label: '客户名',
+      field: 'name',
+      component: 'Input',
+      dynamicDisabled: ({ values }) => {
+        return isDisabledAuth('order:name');
+      },
+    },
+    {
+      label: '性别',
+      field: 'sex',
+      component: 'Select',
+      componentProps: {
+        options: [
+          { label: '男', value: '1', key: '1' },
+          { label: '女', value: '2', key: '2' },
+        ],
+      },
+    },
+    {
+      label: '身份证号',
+      field: 'idcard',
+      component: 'Input',
+    },
+    {
+      label: '手机号',
+      field: 'telphone',
+      component: 'Input',
+    },
+  ];
+  return formSchema2;
+}
+
+export const jeecgOrderTicketColumns: JVxeColumn[] = [
+  {
+    title: '航班号',
+    key: 'ticketCode',
+    width: 180,
+    type: JVxeTypes.input,
+    placeholder: '请输入${title}',
+    defaultValue: '',
+  },
+  {
+    title: '航班时间',
+    key: 'tickectDate',
+    width: 180,
+    type: JVxeTypes.date,
+    placeholder: '请选择${title}',
+    defaultValue: '',
+  },
 ];

+ 67 - 0
src/views/demo/vextable/form/JeecgOrderCustomerForm.vue

@@ -0,0 +1,67 @@
+<template>
+  <BasicForm @register="registerForm"></BasicForm>
+</template>
+
+<script>
+  import { BasicForm, useForm } from '/@/components/Form/index';
+  import { computed, defineComponent, toRaw } from 'vue';
+  import { defHttp } from '/@/utils/http/axios';
+  import { propTypes } from '/@/utils/propTypes';
+  import { getOrderCustomerFormSchema } from '../data';
+
+  export default defineComponent({
+    name: 'JeecgOrderCustomerForm',
+    components: {
+      BasicForm,
+    },
+    props: {
+      formData: propTypes.object.def({}),
+    },
+    setup(props) {
+      const [registerForm, { setFieldsValue, setProps, getFieldsValue, updateSchema }] = useForm({
+        labelWidth: 150,
+        schemas: getOrderCustomerFormSchema(props.formData),
+        showActionButtonGroup: false,
+        baseColProps: { span: 8 },
+      });
+
+      const formDisabled = computed(() => {
+        if (props.formData.disabled === false) {
+          return false;
+        }
+        return true;
+      });
+
+      let orderCustomerFormData = {};
+      const queryByIdUrl = '/test/jeecgOrderMain/queryOrderCustomerListByMainId';
+      async function initFormData(mainId) {
+        let params = { id: mainId };
+        const data = await defHttp.get({ url: queryByIdUrl, params });
+        console.log('data', data);
+        if (data && data.length > 0) {
+          let temp = data[0];
+          orderCustomerFormData = { ...temp };
+          //设置表单的值
+          await setFieldsValue(orderCustomerFormData);
+          await setProps({ disabled: formDisabled.value });
+        }
+      }
+      async function getFormData() {
+        let subFormData = { ...orderCustomerFormData };
+        if (Object.keys(subFormData).length > 0) {
+          return subFormData;
+        }
+        return false;
+      }
+
+      return {
+        registerForm,
+        formDisabled,
+        initFormData,
+        getFormData,
+      };
+    },
+  });
+</script>
+
+<style scoped></style>

+ 155 - 0
src/views/demo/vextable/form/JeecgOrderMainForm.vue

@@ -0,0 +1,155 @@
+<template>
+  <div class="jeecg-flow-demo">
+    <BasicForm @register="registerForm"></BasicForm>
+    <a-tabs v-model:activeKey="activeKey" @change="handleChangeTabs">
+      <a-tab-pane tab="客户信息" key="jeecgOrderCustomerForm" :forceRender="true">
+        <JeecgOrderCustomerForm ref="jeecgOrderCustomerFormRef" :formData="formData"></JeecgOrderCustomerForm>
+      </a-tab-pane>
+
+      <a-tab-pane tab="机票信息" key="jeecgOrderTicket" :forceRender="true">
+        <JVxeTable v-if="ok" ref="jeecgOrderTicketRef" stripe rowSelection keepSource :maxHeight="300" :loading="table2.loading" :columns="table2.columns" :dataSource="table2.dataSource"> </JVxeTable>
+      </a-tab-pane>
+    </a-tabs>
+  </div>
+</template>
+
+<script>
+  import { BasicForm, useForm } from '/@/components/Form/index';
+  import { computed, defineComponent, ref, reactive } from 'vue';
+  import { defHttp } from '/@/utils/http/axios';
+  import { propTypes } from '/@/utils/propTypes';
+  import { getBpmFormSchema, jeecgOrderTicketColumns } from '../data';
+  import JeecgOrderCustomerForm from './JeecgOrderCustomerForm.vue';
+
+  export default defineComponent({
+    name: 'JeecgOrderMainForm',
+    components: {
+      BasicForm,
+      JeecgOrderCustomerForm,
+    },
+    props: {
+      formData: propTypes.object.def({}),
+      formBpm: propTypes.bool.def(true),
+    },
+    setup(props) {
+      const [registerForm, { setFieldsValue, setProps, getFieldsValue, updateSchema }] = useForm({
+        labelWidth: 150,
+        schemas: getBpmFormSchema(props.formData),
+        showActionButtonGroup: false,
+        baseColProps: { span: 8 },
+      });
+
+      const formDisabled = computed(() => {
+        if (props.formData.disabled === false) {
+          return false;
+        }
+        return true;
+      });
+
+      const jeecgOrderCustomerFormRef = ref();
+      const jeecgOrderTicketRef = ref();
+      const ok = ref(false);
+
+      let formData = {};
+      const queryByIdUrl = '/test/jeecgOrderMain/queryById';
+      async function initFormData() {
+        console.log('props.formData', props.formData);
+        let params = { id: props.formData.dataId };
+        const data = await defHttp.get({ url: queryByIdUrl, params });
+        console.log('data', data);
+        formData = { ...data };
+        //设置表单的值
+        await setFieldsValue(formData);
+        await setProps({ disabled: formDisabled.value });
+
+        await jeecgOrderCustomerFormRef.value.initFormData(props.formData.dataId);
+        await loadOrderTicketData(props.formData.dataId);
+        ok.value = true;
+      }
+
+      async function submitForm() {
+        let data = getFieldsValue();
+        let params = Object.assign({}, formData, data);
+        console.log('表单数据', params);
+        await saveOrUpdate(params, true);
+      }
+
+      initFormData();
+
+      const activeKey = ref('jeecgOrderCustomerForm');
+      function handleChangeTabs() {}
+      // 机票信息
+      const table2 = reactive({
+        loading: false,
+        dataSource: [],
+        columns: filterSubTableColnmns(jeecgOrderTicketColumns, 'order:'),
+      });
+
+      async function loadOrderTicketData(mainId) {
+        const queryByIdUrl = '/test/jeecgOrderMain/queryOrderTicketListByMainId';
+        let params = { id: mainId };
+        table2.dataSource = [];
+        const data = await defHttp.get({ url: queryByIdUrl, params });
+        if (data && data.length > 0) {
+          table2.dataSource = [...data];
+        }
+      }
+
+      //新增权限处理方法
+      function filterSubTableColnmns(columns, pre) {
+        let authList = props.formData.permissionList;
+        //注意:如果子表配置显示反向 这里不处理其逻辑  即隐藏无法在流程表单中实现,请使用全局表单权限实现
+        let temp = columns.filter((item) => {
+          let oneAuth = authList.find((auth) => {
+            return auth.action === pre + item.key;
+          });
+          if (!oneAuth) {
+            return true;
+          }
+
+          //代码严谨处理,防止一个授权标识,配置多次
+          if (oneAuth instanceof Array) {
+            oneAuth = oneAuth[0];
+          }
+
+          //禁用逻辑
+          if (oneAuth.type == '2' && !oneAuth.isAuth) {
+            item['disabled'] = true;
+            return true;
+          }
+          //隐藏逻辑逻辑
+          if (oneAuth.type == '1' && !oneAuth.isAuth) {
+            return false;
+          }
+          return true;
+        });
+        return temp;
+      }
+
+      return {
+        registerForm,
+        formDisabled,
+        submitForm,
+        jeecgOrderCustomerFormRef,
+        activeKey,
+        handleChangeTabs,
+        table2,
+        jeecgOrderTicketRef,
+        ok,
+      };
+    },
+  });
+</script>
+
+<style lang="less">
+  /*.jeecg-flow-demo{
+    .vxe-header--row{
+        .vxe-header--column .vxe-cell{
+            width: 180px !important;
+        }
+        .vxe-header--column:first-child .vxe-cell{
+            width: 40px !important;
+        }
+    }
+}*/
+</style>

+ 2 - 1
src/views/demo/vextable/index.vue

@@ -56,7 +56,7 @@
   };
 
   const getDropDownActions = (record) => {
-    return [
+    let arr = [
       {
         label: '删除',
         popConfirm: {
@@ -65,6 +65,7 @@
         },
       },
     ];
+    return arr;
   };
 
   // 列表页面公共参数、方法

+ 1 - 1
src/views/demo/vextable/jvxetable/jvxetable.data.ts

@@ -1,4 +1,4 @@
-import { JVxeTypes, JVxeColumn } from '/src/components/jeecg/JVxeTable/types';
+import { JVxeTypes, JVxeColumn } from '/@/components/jeecg/JVxeTable/types';
 
 export const columns: JVxeColumn[] = [
   {

+ 56 - 0
src/views/monitor/mynews/DetailModal.vue

@@ -4,12 +4,21 @@
       <a-card-meta :title="content.titile" :description="'发布人:' + content.sender + ' 发布时间: ' + content.sendTime"> </a-card-meta>
       <a-divider />
       <span v-html="content.msgContent" class="article-content"></span>
+
+      <div>
+        <a-button v-if="hasHref" @click="jumpToHandlePage">前往办理<ArrowRightOutlined /></a-button>
+      </div>
     </a-card>
   </BasicModal>
 </template>
 <script lang="ts" setup>
   import { BasicModal, useModalInner } from '/@/components/Modal';
   import { propTypes } from '/@/utils/propTypes';
+  import { ArrowRightOutlined } from '@ant-design/icons-vue';
+  import { useRouter } from 'vue-router';
+  import xss from 'xss';
+  const router = useRouter();
+
   import { ref, unref } from 'vue';
   const isUpdate = ref(true);
   const content = ref({});
@@ -17,9 +26,56 @@
   const [registerModal, { setModalProps, closeModal }] = useModalInner(async (data) => {
     isUpdate.value = !!data?.isUpdate;
     if (unref(isUpdate)) {
+      //data.record.msgContent = '<p>2323</p><input onmouseover=alert(1)>xss test';
+      //update-begin-author:taoyan date:2022-7-14 for: VUEN-1702 【禁止问题】sql注入漏洞
+      if (data.record.msgContent) {
+        data.record.msgContent = xss(data.record.msgContent);
+      }
+      //update-end-author:taoyan date:2022-7-14 for: VUEN-1702 【禁止问题】sql注入漏洞
       content.value = data.record;
+      showHrefButton();
     }
   });
+
+  const hasHref = ref(false);
+  //查看消息详情可以跳转
+  function showHrefButton() {
+    if (content.value.busId) {
+      hasHref.value = true;
+    }
+  }
+  //跳转至办理页面
+  function jumpToHandlePage() {
+    let temp: any = content.value;
+    if (temp.busId) {
+      //这个busId是 任务ID
+      let jsonStr = temp.msgAbstract;
+      let query = {};
+      try {
+        if (jsonStr) {
+          let temp = JSON.parse(jsonStr);
+          if (temp) {
+            Object.keys(temp).map((k) => {
+              query[k] = temp[k];
+            });
+          }
+        }
+      } catch (e) {
+        console.log('参数解析异常', e);
+      }
+
+      console.log('query', query, jsonStr);
+      console.log('busId', temp.busId);
+
+      if (Object.keys(query).length > 0) {
+        // taskId taskDefKey procInsId
+        router.push({ path: '/task/handle/' + temp.busId, query: query });
+      } else {
+        router.push({ path: '/task/handle/' + temp.busId });
+      }
+    }
+    closeModal();
+  }
 </script>
 
 <style scoped lang="less">

+ 3 - 3
src/views/monitor/mynews/mynews.api.ts

@@ -3,9 +3,9 @@ import { Modal } from 'ant-design-vue';
 
 enum Api {
   list = '/sys/sysAnnouncementSend/getMyAnnouncementSend',
-  editCementSend = 'sys/sysAnnouncementSend/editByAnntIdAndUserId',
-  readAllMsg = 'sys/sysAnnouncementSend/readAll',
-  syncNotic = 'sys/annountCement/syncNotic',
+  editCementSend = '/sys/sysAnnouncementSend/editByAnntIdAndUserId',
+  readAllMsg = '/sys/sysAnnouncementSend/readAll',
+  syncNotic = '/sys/annountCement/syncNotic',
 }
 
 /**

+ 86 - 0
src/views/sys/login/OAuth2Login.vue

@@ -0,0 +1,86 @@
+<template>
+  <div> </div>
+</template>
+
+<script setup lang="ts">
+  import { ref } from 'vue';
+  import { isOAuth2AppEnv, sysOAuth2Login } from '/@/views/sys/login/useLogin';
+  import { useRouter } from 'vue-router';
+  import { PageEnum } from '/@/enums/pageEnum';
+  import { router } from '/@/router';
+  import { useUserStore } from '/@/store/modules/user';
+  import { useMessage } from '/@/hooks/web/useMessage';
+  import { useI18n } from '/@/hooks/web/useI18n';
+
+  const isOAuth = ref<boolean>(isOAuth2AppEnv());
+  const env = ref<any>({ thirdApp: false, wxWork: false, dingtalk: false });
+  const { currentRoute } = useRouter();
+  const route = currentRoute.value;
+  if (!isOAuth2AppEnv()) {
+    router.replace({ path: PageEnum.BASE_LOGIN, query: route.query });
+  }
+
+  if (isOAuth.value) {
+    checkEnv();
+  }
+
+  /**
+   * 检测当前的环境
+   */
+  function checkEnv() {
+    // 判断当时是否是企业微信环境
+    if (/wxwork/i.test(navigator.userAgent)) {
+      env.value.thirdApp = true;
+      env.value.wxWork = true;
+    }
+    // 判断当时是否是钉钉环境
+    if (/dingtalk/i.test(navigator.userAgent)) {
+      env.value.thirdApp = true;
+      env.value.dingtalk = true;
+    }
+    doOAuth2Login();
+  }
+
+  /**
+   * 进行OAuth2登录操作
+   */
+  function doOAuth2Login() {
+    if (env.value.thirdApp) {
+      // 判断是否携带了Token,是就说明登录成功
+      if (route.query.oauth2LoginToken) {
+        let token = route.query.oauth2LoginToken;
+        //执行登录操作
+        thirdLogin({ token, thirdType: route.query.thirdType });
+      } else if (env.value.wxWork) {
+        sysOAuth2Login('wechat_enterprise');
+      } else if (env.value.dingtalk) {
+        sysOAuth2Login('dingtalk');
+      }
+    }
+  }
+
+  /**
+   * 第三方登录
+   * @param params
+   */
+  function thirdLogin(params) {
+    const userStore = useUserStore();
+    const { notification } = useMessage();
+    const { t } = useI18n();
+    userStore.ThirdLogin(params).then((res) => {
+      if (res && res.userInfo) {
+        notification.success({
+          message: t('sys.login.loginSuccessTitle'),
+          description: `${t('sys.login.loginSuccessDesc')}: ${res.userInfo.realname}`,
+          duration: 3,
+        });
+      } else {
+        notification.error({
+          message: '登录失败',
+          description: ((res.response || {}).data || {}).message || res.message || '请求出现错误,请稍后再试',
+          duration: 4,
+        });
+      }
+    });
+  }
+</script>

+ 206 - 0
src/views/sys/login/TokenLoginPage.vue

@@ -0,0 +1,206 @@
+<template>
+  <div class="app-loading">
+    <div class="app-loading-wrap">
+      <img src="/resource/img/logo.png" class="app-loading-logo" alt="Logo" />
+      <div class="app-loading-dots">
+        <span class="dot dot-spin"><i></i><i></i><i></i><i></i></span>
+      </div>
+      <div class="app-loading-title">JeecgBoot 企业级低代码平台</div>
+    </div>
+  </div>
+</template>
+
+<script lang="ts">
+  /**
+   * 地址中携带token,跳转至此页面进行登录操作
+   */
+  import { useRoute, useRouter } from 'vue-router';
+  import { useMessage } from '/@/hooks/web/useMessage';
+  import { useUserStore } from '/@/store/modules/user';
+  import { useI18n } from '/@/hooks/web/useI18n';
+
+  export default {
+    name: 'TokenLogin',
+    setup() {
+      const route = useRoute();
+      let router = useRouter();
+      const { createMessage, notification } = useMessage();
+      const { t } = useI18n();
+      const routeQuery: any = route.query;
+      if (!routeQuery) {
+        createMessage.warning('参数无效');
+      }
+
+      const token = routeQuery['loginToken'];
+      if (!token) {
+        createMessage.warning('token无效');
+      }
+      const userStore = useUserStore();
+      userStore.ThirdLogin({ token, thirdType: 'email' }).then((res) => {
+        console.log('res====>doThirdLogin', res);
+        if (res && res.userInfo) {
+          requestSuccess(res);
+        } else {
+          requestFailed(res);
+        }
+      });
+
+      function requestFailed(err) {
+        notification.error({
+          message: '登录失败',
+          description: ((err.response || {}).data || {}).message || err.message || '请求出现错误,请稍后再试',
+          duration: 4,
+        });
+      }
+
+      function requestSuccess(res) {
+        let info = routeQuery.info;
+        if (info) {
+          let query = JSON.parse(info);
+          let taskId = query.taskId;
+          let path = '/task/handle/' + taskId;
+          router.replace({ path, query });
+          notification.success({
+            message: t('sys.login.loginSuccessTitle'),
+            description: `${t('sys.login.loginSuccessDesc')}: ${res.userInfo.realname}`,
+            duration: 3,
+          });
+        } else {
+          notification.error({
+            message: '参数失效',
+            description: '页面跳转参数丢失,请查看日志',
+            duration: 4,
+          });
+        }
+      }
+    },
+  };
+</script>
+
+<style scoped>
+  html[data-theme='dark'] .app-loading {
+    background-color: #2c344a;
+  }
+
+  html[data-theme='dark'] .app-loading .app-loading-title {
+    color: rgba(255, 255, 255, 0.85);
+  }
+
+  .app-loading {
+    display: flex;
+    width: 100%;
+    height: 100%;
+    justify-content: center;
+    align-items: center;
+    flex-direction: column;
+    background-color: #f4f7f9;
+  }
+
+  .app-loading .app-loading-wrap {
+    position: absolute;
+    top: 50%;
+    left: 50%;
+    display: flex;
+    -webkit-transform: translate3d(-50%, -50%, 0);
+    transform: translate3d(-50%, -50%, 0);
+    justify-content: center;
+    align-items: center;
+    flex-direction: column;
+  }
+
+  .app-loading .dots {
+    display: flex;
+    padding: 98px;
+    justify-content: center;
+    align-items: center;
+  }
+
+  .app-loading .app-loading-title {
+    display: flex;
+    margin-top: 30px;
+    font-size: 30px;
+    color: rgba(0, 0, 0, 0.85);
+    justify-content: center;
+    align-items: center;
+  }
+
+  .app-loading .app-loading-logo {
+    display: block;
+    width: 90px;
+    margin: 0 auto;
+    margin-bottom: 20px;
+  }
+
+  .dot {
+    position: relative;
+    display: inline-block;
+    width: 48px;
+    height: 48px;
+    margin-top: 30px;
+    font-size: 32px;
+    transform: rotate(45deg);
+    box-sizing: border-box;
+    animation: antRotate 1.2s infinite linear;
+  }
+
+  .dot i {
+    position: absolute;
+    display: block;
+    width: 20px;
+    height: 20px;
+    background-color: #0065cc;
+    border-radius: 100%;
+    opacity: 0.3;
+    transform: scale(0.75);
+    animation: antSpinMove 1s infinite linear alternate;
+    transform-origin: 50% 50%;
+  }
+
+  .dot i:nth-child(1) {
+    top: 0;
+    left: 0;
+  }
+
+  .dot i:nth-child(2) {
+    top: 0;
+    right: 0;
+    -webkit-animation-delay: 0.4s;
+    animation-delay: 0.4s;
+  }
+
+  .dot i:nth-child(3) {
+    right: 0;
+    bottom: 0;
+    -webkit-animation-delay: 0.8s;
+    animation-delay: 0.8s;
+  }
+
+  .dot i:nth-child(4) {
+    bottom: 0;
+    left: 0;
+    -webkit-animation-delay: 1.2s;
+    animation-delay: 1.2s;
+  }
+  @keyframes antRotate {
+    to {
+      -webkit-transform: rotate(405deg);
+      transform: rotate(405deg);
+    }
+  }
+  @-webkit-keyframes antRotate {
+    to {
+      -webkit-transform: rotate(405deg);
+      transform: rotate(405deg);
+    }
+  }
+  @keyframes antSpinMove {
+    to {
+      opacity: 1;
+    }
+  }
+  @-webkit-keyframes antSpinMove {
+    to {
+      opacity: 1;
+    }
+  }
+</style>

+ 19 - 0
src/views/sys/login/useLogin.ts

@@ -163,3 +163,22 @@ async function checkPhone(rule, value, callback) {
     });
   }
 }
+
+//update-begin---author:wangshuai ---date:20220629  for:[issues/I5BG1I]vue3不支持auth2登录------------
+/**
+ * 判断是否是OAuth2APP环境
+ */
+export function isOAuth2AppEnv() {
+  return /wxwork|dingtalk/i.test(navigator.userAgent);
+}
+
+/**
+ * 后台构造oauth2登录地址
+ * @param source
+ */
+export function sysOAuth2Login(source) {
+  let url = `${window._CONFIG['domianURL']}/sys/thirdLogin/oauth2/${source}/login`;
+  url += `?state=${encodeURIComponent(window.location.origin)}`;
+  window.location.href = url;
+}
+//update-end---author:wangshuai ---date:20220629  for:[issues/I5BG1I]vue3不支持auth2登录------------

+ 3 - 1
src/views/system/address/index.vue

@@ -45,7 +45,9 @@
     tableProps: {
       api: list,
       columns,
-      rowKey: 'id',
+      //update-begin---author:wangshuai ---date:20220629  for:[VUEN-1485]进入系统管理--通讯录页面后,网页命令行报错------------
+      rowKey: 'userId',
+      //update-end---author:wangshuai ---date:20220629  for:[VUEN-1485]进入系统管理--通讯录页面后,网页命令行报错--------------
       showIndexColumn: true,
       formConfig: {
         labelWidth: 200,

+ 64 - 0
src/views/system/examples/demo/DemoDetailModal.vue

@@ -0,0 +1,64 @@
+<template>
+  <BasicModal v-bind="$attrs" @register="registerModal" width="40%" title="详情" :showOkBtn="false" cancelText="关闭">
+    <detail-form :schemas="detailFormSchemas" :data="formData" :span="12"></detail-form>
+  </BasicModal>
+</template>
+<script lang="ts" setup>
+  import { ref } from 'vue';
+  import { BasicModal, useModalInner } from '/@/components/Modal';
+  import { getDemoById } from './demo.api';
+  import DetailForm from '/@/components/Form/src/components/DetailForm.vue';
+
+  // 声明Emits
+  const emit = defineEmits(['register']);
+  //表单数据
+  const formData = ref({});
+  //表单配置
+  const detailFormSchemas = [
+    {
+      field: 'name',
+      label: '名字',
+    },
+    {
+      field: 'keyWord',
+      label: '关键词',
+    },
+    {
+      field: 'punchTime',
+      label: '打卡时间',
+    },
+    {
+      field: 'salaryMoney',
+      label: '工资',
+    },
+    {
+      field: 'sex',
+      label: '性别',
+      view: 'list',
+      dictCode: 'sex',
+    },
+    {
+      field: 'age',
+      label: '年龄',
+    },
+    {
+      field: 'birthday',
+      label: '生日',
+    },
+    {
+      field: 'email',
+      label: '邮箱',
+    },
+    {
+      field: 'content',
+      label: '个人简介',
+      span: 24,
+    },
+  ];
+
+  //表单赋值
+  const [registerModal, { setModalProps }] = useModalInner(async (data) => {
+    setModalProps({ confirmLoading: false });
+    formData.value = await getDemoById({ id: data.record.id });
+  });
+</script>

+ 39 - 2
src/views/system/examples/demo/index.vue

@@ -52,12 +52,14 @@
         <a-upload name="file" :showUploadList="false" :customRequest="(file) => handleImportXls(file, getImportUrl, reload)">
           <a-button preIcon="ant-design:import-outlined" type="primary">导入</a-button>
         </a-upload>
-        <a-button preIcon="ant-design:export-outlined" type="primary" @click="handleExportXls('单表示例', getExportUrl)">导出</a-button>
+        <a-button preIcon="ant-design:export-outlined" type="primary" @click="handleExportXls('单表示例', getExportUrl, exportParams)">导出</a-button>
         <a-button preIcon="ant-design:filter" type="primary" @click="">高级查询?</a-button>
         <a-button preIcon="ant-design:plus-outlined" type="primary" @click="openTab">打开Tab页</a-button>
         <a-button preIcon="ant-design:retweet-outlined" type="primary" @click="customSearch = !customSearch">{{ customSearch ? '表单配置查询' : '自定义查询' }}</a-button>
         <a-button preIcon="ant-design:import-outlined" type="primary" @click="handleImport">弹窗导入</a-button>
 
+        <super-query :config="superQueryConfig" @search="handleSuperQuery" />
+
         <a-dropdown v-if="checkedKeys.length > 0">
           <template #overlay>
             <a-menu>
@@ -78,11 +80,12 @@
       </template>
     </BasicTable>
     <DemoModal @register="registerModal" @success="reload" />
+    <DemoDetailModal @register="registerDetailModal" />
     <JImportModal @register="registerModal1" :url="getImportUrl" online />
   </div>
 </template>
 <script lang="ts" setup>
-  import { ref, unref, reactive, toRaw, watch } from 'vue';
+  import { ref, unref, reactive, toRaw, watch, computed } from 'vue';
   import { BasicTable, useTable, TableAction } from '/@/components/Table';
   import { useModal } from '/@/components/Modal';
   import DemoModal from './DemoModal.vue';
@@ -94,11 +97,15 @@
   import { columns, searchFormSchema } from './demo.data';
   import { useGo } from '/@/hooks/web/usePage';
   import { router } from '/@/router';
+  import { filterObj } from '/@/utils/common/compUtils';
+  import DemoDetailModal from './DemoDetailModal.vue';
+  import SuperQuery from '/@/components/jeecg/super/superquery/SuperQuery.vue';
 
   const go = useGo();
   const checkedKeys = ref<Array<string | number>>([]);
   const [registerModal, { openModal }] = useModal();
   const [registerModal1, { openModal: openModal1 }] = useModal();
+  const [registerDetailModal, { openModal: openDetailModal }] = useModal();
   const { handleExportXls, handleImportXls } = useMethods();
   const min = ref();
   const max = ref();
@@ -147,6 +154,13 @@
     openModal1(true);
   }
 
+  const exportParams = computed(() => {
+    let paramsForm = {};
+    if (checkedKeys.value && checkedKeys.value.length > 0) {
+      paramsForm['selections'] = checkedKeys.value.join(',');
+    }
+    return filterObj(paramsForm);
+  });
   /**
    * 操作列定义
    * @param record
@@ -164,13 +178,24 @@
           confirm: handleDelete.bind(null, record),
         },
       },
+      {
+        label: '详情',
+        onClick: handleDetail.bind(null, record),
+      },
     ];
   }
 
+  function handleDetail(record) {
+    openDetailModal(true, {
+      record,
+    });
+  }
+
   /**
    * 选择事件
    */
   function onSelectChange(selectedRowKeys: (string | number)[]) {
+    console.log('checkedKeys------>', checkedKeys);
     checkedKeys.value = selectedRowKeys;
   }
 
@@ -250,6 +275,18 @@
     reload();
   }
   //自定义查询----end---------
+
+  const superQueryConfig = reactive({
+    name: { title: '名称', view: 'text', type: 'string', order: 1 },
+    sex: { title: '性别', view: 'list', type: 'string', dictCode: 'sex', order: 2 },
+  });
+
+  function handleSuperQuery(params) {
+    Object.keys(params).map((k) => {
+      queryParam[k] = params[k];
+    });
+    searchQuery();
+  }
 </script>
 <style lang="less" scoped>
   .jeecg-basic-table-form-container {

+ 21 - 0
src/views/system/menu/MenuDrawer.vue

@@ -50,6 +50,9 @@
       {
         field: 'url',
         required: !isButton(unref(menuType)),
+        componentProps: {
+          onChange: (e) => onUrlChange(e.target.value),
+        },
       },
     ]);
 
@@ -57,6 +60,7 @@
     if (typeof data.record === 'object') {
       let values = { ...data.record };
       setFieldsValue(values);
+      onUrlChange(values.url);
     }
     //禁用表单
     setProps({ disabled: !attrs.showFooter });
@@ -80,4 +84,21 @@
       setDrawerProps({ confirmLoading: false });
     }
   }
+
+  /** url 变化时,动态设置组件名称placeholder */
+  function onUrlChange(url) {
+    let placeholder = '';
+    if (url != null && url != '') {
+      if (url.startsWith('/')) {
+        url = url.substring(1);
+      }
+      url = url.replaceAll('/', '-');
+      // 特殊标记
+      url = url.replaceAll(':', '@');
+      placeholder = `${url}`;
+    } else {
+      placeholder = '请输入组件名称';
+    }
+    updateSchema([{ field: 'componentName', componentProps: { placeholder } }]);
+  }
 </script>

+ 16 - 0
src/views/system/menu/menu.data.ts

@@ -152,6 +152,22 @@ export const formSchema: FormSchema[] = [
     ifShow: ({ values }) => !isButton(values.menuType),
   },
   {
+    field: 'componentName',
+    label: '组件名称',
+    component: 'Input',
+    componentProps: {
+      placeholder: '请输入组件名称',
+    },
+    helpMessage: [
+      '此处名称应和vue组件的name属性保持一致。',
+      '组件名称不能重复,主要用于路由缓存功能。',
+      '如果组件名称和vue组件的name属性不一致,则会导致路由缓存失效。',
+      '非必填,留空则会根据访问路径自动生成。',
+    ],
+    defaultValue: '',
+    ifShow: ({ values }) => !isButton(values.menuType),
+  },
+  {
     field: 'frameSrc',
     label: 'Iframe地址',
     component: 'Input',

+ 2 - 2
src/views/system/message/manage/manage.data.ts

@@ -58,7 +58,7 @@ export const searchFormSchema: FormSchema[] = [
     field: 'esType',
     component: 'JDictSelectTag',
     componentProps: {
-      dictCode: 'msgType',
+      dictCode: 'messageType',
     },
   },
 ];
@@ -99,7 +99,7 @@ export const formSchemas: FormSchema[] = [
     label: '发送方式',
     field: 'esType',
     component: 'JDictSelectTag',
-    componentProps: { disabled: true, dictCode: 'msgType' },
+    componentProps: { disabled: true, dictCode: 'messageType' },
   },
   {
     label: '发送时间',

+ 43 - 3
src/views/system/message/template/index.vue

@@ -33,14 +33,16 @@
 </template>
 
 <script lang="ts" setup name="message-template">
-  import { unref, computed } from 'vue';
+  import { unref, computed, toRaw } from 'vue';
   import { ActionItem, BasicTable, TableAction } from '/@/components/Table';
   import { useModal } from '/@/components/Modal';
   import { useListPage } from '/@/hooks/system/useListPage';
   import TemplateModal from './TemplateModal.vue';
   import TemplateTestModal from './TemplateTestModal.vue';
-  import { Api, list, deleteBatch } from './template.api';
+  import { Api, saveOrUpdate, list, deleteBatch } from './template.api';
   import { columns, searchFormSchema } from './template.data';
+  import { useMessage } from '/@/hooks/web/useMessage';
+  const { createMessage } = useMessage();
 
   // 列表页面公共参数、方法
   const { prefixCls, onExportXls, onImportXls, tableContext } = useListPage({
@@ -64,7 +66,7 @@
   });
 
   // 注册 ListTable
-  const [registerTable, { reload, setLoading }, { rowSelection, selectedRowKeys }] = tableContext;
+  const [registerTable, { reload, setLoading }, { rowSelection, selectedRowKeys, selectedRows }] = tableContext;
   const [registerModal, { openModal }] = useModal();
   const [registerTestModal, testModal] = useModal();
   const showBatchBtn = computed(() => selectedRowKeys.value.length > 0);
@@ -78,6 +80,10 @@
   }
 
   function onEdit(record) {
+    if (record.useStatus === '1') {
+      createMessage.warning('此模板已被应用,禁止编辑!');
+      return;
+    }
     openModal(true, {
       title: '修改消息模板',
       isUpdate: true,
@@ -87,6 +93,12 @@
 
   function onDelete(record) {
     if (record) {
+      //update-begin-author:taoyan date:2022-7-14 for: VUEN-1652【bug】应用状态下不允许删除
+      if (record.useStatus == '1') {
+        createMessage.warning('该模板已被应用禁止删除!');
+        return;
+      }
+      //update-end-author:taoyan date:2022-7-14 for: VUEN-1652【bug】应用状态下不允许删除
       doDeleteDepart([record.id], false);
     }
   }
@@ -111,6 +123,14 @@
 
   async function onDeleteBatch() {
     try {
+      //update-begin-author:taoyan date:2022-7-14 for: VUEN-1652【bug】应用状态下不允许删除
+      let arr = toRaw(selectedRows.value);
+      let temp = arr.filter((item) => item.useStatus == '1');
+      if (temp.length > 0) {
+        createMessage.warning('选中的模板已被应用禁止删除!');
+        return;
+      }
+      //update-end-author:taoyan date:2022-7-14 for: VUEN-1652【bug】应用状态下不允许删除
       await doDeleteDepart(selectedRowKeys);
       selectedRowKeys.value = [];
     } finally {
@@ -134,6 +154,8 @@
    */
   function getDropDownAction(record): ActionItem[] {
     return [
+      { label: '应用', onClick: handleUse.bind(null, record) },
+      { label: '停用', onClick: handleNotUse.bind(null, record) },
       { label: '发送测试', onClick: onSendTest.bind(null, record) },
       {
         label: '删除',
@@ -145,6 +167,24 @@
       },
     ];
   }
+
+  /**
+   * 应用
+   */
+  async function handleUse(record) {
+    let param = { id: record.id, useStatus: '1' };
+    await saveOrUpdate(param, true);
+    await reload();
+  }
+
+  /**
+   * 停用
+   */
+  async function handleNotUse(record) {
+    let param = { id: record.id, useStatus: '0' };
+    await saveOrUpdate(param, true);
+    await reload();
+  }
 </script>
 
 <style lang="less">

+ 24 - 10
src/views/system/message/template/template.data.ts

@@ -13,7 +13,7 @@ export const columns: BasicColumn[] = [
     width: 100,
   },
   {
-    title: '模板内容',
+    title: '通知模板',
     dataIndex: 'templateContent',
     width: 150,
   },
@@ -23,20 +23,26 @@ export const columns: BasicColumn[] = [
     width: 100,
     customRender: function ({ text }) {
       if (text == '1') {
-        return '短信';
+        return '文本';
       }
       if (text == '2') {
-        return '邮件';
-      }
-      if (text == '3') {
-        return '微信';
-      }
-      if (text == '4') {
-        return '系统';
+        return '富文本';
       }
       return text;
     },
   },
+  {
+    title: '是否应用',
+    dataIndex: 'useStatus',
+    width: 90,
+    customRender: function ({ text }) {
+      if (text == '1') {
+        return '是';
+      } else {
+        return '否';
+      }
+    },
+  },
 ];
 
 export const searchFormSchema: FormSchema[] = [
@@ -94,6 +100,14 @@ export const formSchemas: FormSchema[] = [
     required: true,
   },
   {
+    label: '是否应用',
+    field: 'useStatus',
+    component: 'JSwitch',
+    componentProps: {
+      options: ['1', '0'],
+    },
+  },
+  {
     label: '模板内容',
     field: 'templateContent',
     component: 'InputTextArea',
@@ -153,7 +167,7 @@ export const sendTestFormSchemas: FormSchema[] = [
     field: 'msgType',
     component: 'JDictSelectTag',
     required: true,
-    componentProps: { dictCode: 'msgType' },
+    componentProps: { dictCode: 'messageType' },
   },
   {
     label: '消息接收方',

+ 55 - 0
src/views/system/role/components/RoleIndexModal.vue

@@ -0,0 +1,55 @@
+<template>
+  <BasicModal v-bind="$attrs" @register="registerModal" title="首页配置" @ok="handleSubmit" width="40%">
+    <BasicForm @register="registerForm" />
+  </BasicModal>
+</template>
+
+<script lang="ts" setup>
+  import { ref, computed, unref } from 'vue';
+  import { BasicModal, useModalInner } from '/@/components/Modal';
+  import { BasicForm, useForm } from '/@/components/Form/index';
+  import { roleIndexFormSchema } from '../role.data';
+  import { saveOrUpdateRoleIndex, queryIndexByCode } from '../role.api';
+  // Emits声明
+  const emit = defineEmits(['register', 'success']);
+  const isUpdate = ref(true);
+  //表单配置
+  const [registerForm, { resetFields, setFieldsValue, validate }] = useForm({
+    labelWidth: 150,
+    schemas: roleIndexFormSchema,
+    showActionButtonGroup: false,
+  });
+  //表单赋值
+  const [registerModal, { setModalProps, closeModal }] = useModalInner(async (data) => {
+    //重置表单
+    await resetFields();
+    setModalProps({ confirmLoading: false });
+    setFieldsValue({ roleCode: data.roleCode });
+    let res = await queryIndexByCode({ roleCode: data.roleCode });
+    isUpdate.value = !!res.result?.id;
+    if (unref(isUpdate)) {
+      //表单赋值
+      await setFieldsValue({
+        ...res.result,
+      });
+    }
+  });
+
+  //表单提交事件
+  async function handleSubmit(v) {
+    try {
+      let values = await validate();
+      setModalProps({ confirmLoading: true });
+      //提交表单
+      await saveOrUpdateRoleIndex(values, isUpdate.value);
+      //关闭弹窗
+      closeModal();
+      //刷新列表
+      emit('success', { isUpdate: isUpdate.value, values });
+    } finally {
+      setModalProps({ confirmLoading: false });
+    }
+  }
+</script>
+
+<style lang="less" scoped></style>

+ 14 - 3
src/views/system/role/index.vue

@@ -30,8 +30,8 @@
   <RoleDesc @register="registerDesc"></RoleDesc>
   <!--角色菜单授权抽屉-->
   <RolePermissionDrawer @register="rolePermissionDrawer" />
-  <!--角色工单授权-->
-  <RoleDesignModal @register="registerModal" />
+  <!--角色首页配置-->
+  <RoleIndexModal @register="registerIndexModal" />
 </template>
 <script lang="ts" name="system-role" setup>
   import { ref } from 'vue';
@@ -41,6 +41,7 @@
   import RoleDrawer from './components/RoleDrawer.vue';
   import RoleDesc from './components/RoleDesc.vue';
   import RolePermissionDrawer from './components/RolePermissionDrawer.vue';
+  import RoleIndexModal from './components/RoleIndexModal.vue';
   import RoleUserTable from './components/RoleUserTable.vue';
   import { columns, searchFormSchema } from './role.data';
   import { list, deleteRole, batchDeleteRole, getExportUrl, getImportUrl } from './role.api';
@@ -48,7 +49,7 @@
   const showFooter = ref(true);
   const [roleUserDrawer, { openDrawer: openRoleUserDrawer }] = useDrawer();
   const [registerDrawer, { openDrawer }] = useDrawer();
-  const [registerModal, { openModal }] = useModal();
+  const [registerIndexModal, { openModal: openIndexModal }] = useModal();
   const [rolePermissionDrawer, { openDrawer: openRolePermissionDrawer }] = useDrawer();
   const [registerDesc, { openDrawer: openRoleDesc }] = useDrawer();
 
@@ -125,6 +126,12 @@
     openRolePermissionDrawer(true, { roleId: record.id });
   }
   /**
+   * 首页配置弹窗
+   */
+  function handleIndexConfig(roleCode) {
+    openIndexModal(true, { roleCode });
+  }
+  /**
    * 角色用户
    */
   function handleUser(record) {
@@ -167,6 +174,10 @@
           confirm: handleDelete.bind(null, record),
         },
       },
+      {
+        label: '首页配置',
+        onClick: handleIndexConfig.bind(null, record.roleCode),
+      },
     ];
   }
 </script>

+ 15 - 0
src/views/system/role/role.data.ts

@@ -144,6 +144,21 @@ export const roleIndexFormSchema: FormSchema[] = [
     required: true,
   },
   {
+    label: '组件地址',
+    field: 'component',
+    component: 'Input',
+    componentProps: {
+      placeholder: '请输入前端组件',
+    },
+    required: true,
+  },
+  {
+    field: 'route',
+    label: '是否路由菜单',
+    component: 'Switch',
+    defaultValue: true,
+  },
+  {
     label: '优先级',
     field: 'priority',
     component: 'InputNumber',

+ 2 - 2
src/views/system/user/index.vue

@@ -4,7 +4,7 @@
     <BasicTable @register="registerTable" :rowSelection="rowSelection">
       <!--插槽:table标题-->
       <template #tableTitle>
-        <a-button type="primary" preIcon="ant-design:plus-outlined" v-auth="'user:add'" @click="handleCreate"> 新增</a-button>
+        <a-button type="primary" preIcon="ant-design:plus-outlined" @click="handleCreate"> 新增</a-button>
         <a-button type="primary" preIcon="ant-design:export-outlined" @click="onExportXls"> 导出</a-button>
         <j-upload-button type="primary" preIcon="ant-design:import-outlined" @click="onImportXls">导入</j-upload-button>
         <a-button type="primary" @click="handleSyncUser" preIcon="ant-design:sync-outlined"> 同步流程</a-button>
@@ -236,7 +236,7 @@
       {
         label: '编辑',
         onClick: handleEdit.bind(null, record),
-        // ifShow: () => hasPermission('user:edit'),
+        // ifShow: () => hasPermission('system:user:edit'),
       },
     ];
   }