Browse Source

Merge remote-tracking branch 'origin/feature/vue3' into feature/vue3

YunaiV 2 năm trước cách đây
mục cha
commit
32986ca284
51 tập tin đã thay đổi với 1174 bổ sung1234 xóa
  1. 0 6
      yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/handler/GlobalExceptionHandler.java
  2. 68 61
      yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3/views/data.ts.vm
  3. 24 0
      yudao-server/src/main/java/cn/iocoder/yudao/server/controller/DefaultController.java
  4. 2 2
      yudao-server/src/main/resources/application.yaml
  5. 4 4
      yudao-ui-admin-vue3/package.json
  6. 69 67
      yudao-ui-admin-vue3/pnpm-lock.yaml
  7. 9 0
      yudao-ui-admin-vue3/src/api/login/index.ts
  8. 27 13
      yudao-ui-admin-vue3/src/api/system/dept/index.ts
  9. 6 9
      yudao-ui-admin-vue3/src/components/Crontab/src/Crontab.vue
  10. 3 7
      yudao-ui-admin-vue3/src/components/Form/src/Form.vue
  11. 4 4
      yudao-ui-admin-vue3/src/components/Form/src/components/useRenderCheckbox.tsx
  12. 2 2
      yudao-ui-admin-vue3/src/components/Form/src/components/useRenderRadio.tsx
  13. 1 1
      yudao-ui-admin-vue3/src/components/Form/src/components/useRenderSelect.tsx
  14. 10 5
      yudao-ui-admin-vue3/src/components/Verifition/src/Verify.vue
  15. 3 3
      yudao-ui-admin-vue3/src/components/Verifition/src/Verify/VerifyPoints.vue
  16. 4 4
      yudao-ui-admin-vue3/src/components/Verifition/src/Verify/VerifySlide.vue
  17. 0 26
      yudao-ui-admin-vue3/src/components/Verifition/src/api/index.ts
  18. 0 26
      yudao-ui-admin-vue3/src/components/Verifition/src/utils/axios.ts
  19. 4 0
      yudao-ui-admin-vue3/src/config/axios/index.ts
  20. 1 0
      yudao-ui-admin-vue3/src/config/axios/service.ts
  21. 23 10
      yudao-ui-admin-vue3/src/hooks/web/useCrudSchemas.ts
  22. 15 6
      yudao-ui-admin-vue3/src/hooks/web/useVxeCrudSchemas.ts
  23. 1 1
      yudao-ui-admin-vue3/src/router/index.ts
  24. 3 4
      yudao-ui-admin-vue3/src/views/Error/403.vue
  25. 4 4
      yudao-ui-admin-vue3/src/views/Error/404.vue
  26. 4 4
      yudao-ui-admin-vue3/src/views/Error/500.vue
  27. 164 263
      yudao-ui-admin-vue3/src/views/Home/Index.vue
  28. 130 130
      yudao-ui-admin-vue3/src/views/Home/Index2.vue
  29. 17 18
      yudao-ui-admin-vue3/src/views/Login/Login.vue
  30. 139 138
      yudao-ui-admin-vue3/src/views/Login/components/LoginForm.vue
  31. 5 5
      yudao-ui-admin-vue3/src/views/Login/components/LoginFormTitle.vue
  32. 87 86
      yudao-ui-admin-vue3/src/views/Login/components/MobileForm.vue
  33. 13 14
      yudao-ui-admin-vue3/src/views/Login/components/QrCodeForm.vue
  34. 36 36
      yudao-ui-admin-vue3/src/views/Login/components/RegisterForm.vue
  35. 2 1
      yudao-ui-admin-vue3/src/views/Profile/components/BasicInfo.vue
  36. 10 28
      yudao-ui-admin-vue3/src/views/infra/codegen/codegen.data.ts
  37. 1 1
      yudao-ui-admin-vue3/src/views/infra/codegen/components/ImportTable.vue
  38. 1 2
      yudao-ui-admin-vue3/src/views/system/dept/dept.data.ts
  39. 235 176
      yudao-ui-admin-vue3/src/views/system/dept/index.vue
  40. 14 2
      yudao-ui-admin-vue3/src/views/system/dict/index.vue
  41. 1 2
      yudao-ui-admin-vue3/src/views/system/tenant/tenant.data.ts
  42. 1 0
      yudao-ui-admin-vue3/src/views/system/user/user.data.ts
  43. 3 1
      yudao-ui-admin-vue3/vite.config.ts
  44. 18 0
      yudao-ui-admin/src/api/login.js
  45. 2 2
      yudao-ui-admin/src/components/RightToolbar/index.vue
  46. 1 1
      yudao-ui-admin/src/components/Verifition/Verify/VerifyPoints.vue
  47. 1 1
      yudao-ui-admin/src/components/Verifition/Verify/VerifySlide.vue
  48. 0 27
      yudao-ui-admin/src/components/Verifition/api/index.js
  49. 0 29
      yudao-ui-admin/src/components/Verifition/utils/axios.js
  50. 1 1
      yudao-ui-admin/src/views/mall/trade/order/detail.vue
  51. 1 1
      yudao-ui-admin/src/views/mall/trade/order/index.vue

+ 0 - 6
yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/handler/GlobalExceptionHandler.java

@@ -168,12 +168,6 @@ public class GlobalExceptionHandler {
      */
     @ExceptionHandler(NoHandlerFoundException.class)
     public CommonResult<?> noHandlerFoundExceptionHandler(HttpServletRequest req, NoHandlerFoundException ex) {
-        // 情况一:部分功能未开启
-        if (req.getRequestURI().contains("/bpm/")) {
-            return CommonResult.error(NOT_IMPLEMENTED.getCode(), "[工作流模块 yudao-module-bpm - 已禁用][参考 https://doc.iocoder.cn/bpm/ 开启]");
-        }
-
-        // 情况二:正常情况下的 404
         log.warn("[noHandlerFoundExceptionHandler]", ex);
         return CommonResult.error(NOT_FOUND.getCode(), String.format("请求地址不存在:%s", ex.getRequestURL()));
     }

+ 68 - 61
yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3/views/data.ts.vm

@@ -21,71 +21,78 @@ const crudSchemas = reactive<VxeCrudSchema>({
   action: true,
   actionWidth: '200', // 3个按钮默认200,如有删减对应增减即可
   columns: [
-#foreach($column in $columns)
-  #if ($column.listOperation || $column.listOperationResult || $column.createOperation || $column.updateOperation)
-  #set ($dictType = $column.dictType)
-  #if(!$column.primaryKey)
-  {
-    title: '${column.columnComment}',
-    field: '${column.javaField}',
-    #if ("" != $dictType)## 有数据字典
-    dictType: DICT_TYPE.$dictType.toUpperCase(),
-    #end
-    #if (!$column.createOperation && !$column.updateOperation)
-    isForm: false
-    #elseif(!("" != $column.dictType))
-    #if ($column.htmlType == "datetime")## 时间框
-    form: {
-      show: true,
-      component: 'DatePicker',
-      componentProps: {
-        type: 'datetime',
-        valueFormat: 'YYYY-MM-DD HH:mm:ss'
-      }
-    }
-    #elseif($column.htmlType == "editor")## 文本编辑器
-    form: {
-      show: true,
-      component: 'Editor',
-      colProps: {
-        span: 24
+  #foreach($column in $columns)
+    #if ($column.listOperation || $column.listOperationResult || $column.createOperation || $column.updateOperation)
+    #set ($dictType = $column.dictType)
+    #if(!$column.primaryKey)
+    {
+      title: '${column.columnComment}',
+      field: '${column.javaField}',
+      #if ("" != $dictType)## 有数据字典
+      dictType: DICT_TYPE.$dictType.toUpperCase(),
+      #if (${column.javaType.toLowerCase()} == "long" || ${column.javaType.toLowerCase()} == "integer")
+      dictData: 'number',
+      #else
+      dictData: 'string',
+      #end
+      #end
+      #if (!$column.createOperation && !$column.updateOperation)
+      isForm: false,
+      #elseif(!("" != $column.dictType))
+      #if ($column.htmlType == "datetime")## 时间框
+      form: {
+        component: 'DatePicker',
+        componentProps: {
+          type: 'datetime',
+          valueFormat: 'YYYY-MM-DD HH:mm:ss'
+        }
       },
-      componentProps: {
-        valueHtml: ''
-      }
-    }
-    #elseif($column.htmlType == "textarea")## 文本框
-    form: {
-      show: true,
-      component: 'Input',
-      componentProps: {
-        type: 'textarea',
-        rows: 4
+      #elseif($column.htmlType == "editor")## 文本编辑器
+      form: {
+        component: 'Editor',
+        colProps: {
+          span: 24
+        },
+        componentProps: {
+          valueHtml: ''
+        }
       },
-      colProps: {
-        span: 24
-      }
-    }
-    #end
-    #end
-    #if ($column.listOperationResult)
-    #if($column.htmlType == "input")
-    isSearch: true
-    #elseif("" != $dictType)
-    isSearch: true
-    #elseif($column.htmlType == "datetime")
-    search: {
-      show: true,
-      itemRender: {
-        name: 'XDataTimePicker'
-      }
-    }
-    #end
-    #end
+      #elseif($column.htmlType == "textarea")## 文本框
+      form: {
+        component: 'Input',
+        componentProps: {
+          type: 'textarea',
+          rows: 4
+        },
+        colProps: {
+          span: 24
+        }
+      },
+      #elseif(${column.javaType.toLowerCase()} == "long" || ${column.javaType.toLowerCase()} == "integer")## 数字类型
+      form: {
+        component: 'InputNumber',
+        value: 0
+      },
+      #end
+      #end
+      #if ($column.listOperationResult)
+      #if($column.htmlType == "input")
+      isSearch: true,
+      #elseif("" != $dictType)
+      isSearch: true,
+      #elseif($column.htmlType == "datetime")
+      search: {
+        show: true,
+        itemRender: {
+          name: 'XDataTimePicker'
+        }
+      },
+      #end
+      #end
+      #end
+    },
     #end
-  },
   #end
-#end
   ]
 })
 export const { allSchemas } = useVxeCrudSchemas(crudSchemas)

+ 24 - 0
yudao-server/src/main/java/cn/iocoder/yudao/server/controller/DefaultController.java

@@ -0,0 +1,24 @@
+package cn.iocoder.yudao.server.controller;
+
+import cn.iocoder.yudao.framework.common.pojo.CommonResult;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import static cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants.NOT_IMPLEMENTED;
+
+/**
+ * 默认 Controller,解决部分 module 未开启时的 404 提示。
+ * 例如说,/bpm/** 路径,工作流
+ *
+ * @author 芋道源码
+ */
+@RestController
+public class DefaultController {
+
+    @RequestMapping("/admin-api/bpm/**")
+    public CommonResult<Boolean> bpm404() {
+        return CommonResult.error(NOT_IMPLEMENTED.getCode(),
+                "[工作流模块 yudao-module-bpm - 已禁用][参考 https://doc.iocoder.cn/bpm/ 开启]");
+    }
+
+}

+ 2 - 2
yudao-server/src/main/resources/application.yaml

@@ -17,8 +17,8 @@ spring:
   mvc:
     pathmatch:
       matching-strategy: ANT_PATH_MATCHER # 解决 SpringFox 与 SpringBoot 2.6.x 不兼容的问题,参见 SpringFoxHandlerProviderBeanPostProcessor 类
-    throw-exception-if-no-handler-found: true # 404 错误时抛出异常,方便统一处理
-    static-path-pattern: /static/** # 静态资源路径; 注意:如果不配置,则 throw-exception-if-no-handler-found 不生效!!!
+#    throw-exception-if-no-handler-found: true # 404 错误时抛出异常,方便统一处理
+#    static-path-pattern: /static/** # 静态资源路径; 注意:如果不配置,则 throw-exception-if-no-handler-found 不生效!!! TODO 芋艿:不能配置,会导致 swagger 不生效
 
   # Jackson 配置项
   jackson:

+ 4 - 4
yudao-ui-admin-vue3/package.json

@@ -1,6 +1,6 @@
 {
   "name": "ruoyi-vue-pro-vue3",
-  "version": "1.6.4.1841",
+  "version": "1.6.4.1851",
   "description": "基于vue3、vite3、element-plus、typesScript",
   "author": "xingyu",
   "private": false,
@@ -43,7 +43,7 @@
     "lodash-es": "^4.17.21",
     "mitt": "^3.0.0",
     "nprogress": "^0.2.0",
-    "pinia": "^2.0.23",
+    "pinia": "^2.0.24",
     "qrcode": "^1.5.1",
     "qs": "^6.11.0",
     "url": "^0.11.0",
@@ -59,7 +59,7 @@
   "devDependencies": {
     "@commitlint/cli": "^17.2.0",
     "@commitlint/config-conventional": "^17.2.0",
-    "@iconify/json": "^2.1.138",
+    "@iconify/json": "^2.1.139",
     "@intlify/vite-plugin-vue-i18n": "^6.0.3",
     "@purge-icons/generated": "^0.9.0",
     "@types/intro.js": "^5.1.0",
@@ -95,7 +95,7 @@
     "stylelint-order": "^5.0.0",
     "typescript": "4.8.4",
     "unplugin-vue-macros": "^0.16.3",
-    "vite": "3.2.3",
+    "vite": "3.2.4",
     "vite-plugin-compression": "^0.5.1",
     "vite-plugin-eslint": "^1.8.1",
     "vite-plugin-html": "^3.2.0",

+ 69 - 67
yudao-ui-admin-vue3/pnpm-lock.yaml

@@ -4,7 +4,7 @@ specifiers:
   '@commitlint/cli': ^17.2.0
   '@commitlint/config-conventional': ^17.2.0
   '@iconify/iconify': ^3.0.0
-  '@iconify/json': ^2.1.138
+  '@iconify/json': ^2.1.139
   '@intlify/vite-plugin-vue-i18n': ^6.0.3
   '@purge-icons/generated': ^0.9.0
   '@types/intro.js': ^5.1.0
@@ -42,7 +42,7 @@ specifiers:
   lodash-es: ^4.17.21
   mitt: ^3.0.0
   nprogress: ^0.2.0
-  pinia: ^2.0.23
+  pinia: ^2.0.24
   plop: ^3.1.1
   postcss: ^8.4.19
   postcss-html: ^1.5.0
@@ -61,7 +61,7 @@ specifiers:
   typescript: 4.8.4
   unplugin-vue-macros: ^0.16.3
   url: ^0.11.0
-  vite: 3.2.3
+  vite: 3.2.4
   vite-plugin-compression: ^0.5.1
   vite-plugin-eslint: ^1.8.1
   vite-plugin-html: ^3.2.0
@@ -99,7 +99,7 @@ dependencies:
   lodash-es: 4.17.21
   mitt: 3.0.0
   nprogress: 0.2.0
-  pinia: 2.0.23_zwu2zepfy3m6u2gunxlolp35gi
+  pinia: 2.0.24_zwu2zepfy3m6u2gunxlolp35gi
   qrcode: 1.5.1
   qs: 6.11.0
   url: 0.11.0
@@ -115,8 +115,8 @@ dependencies:
 devDependencies:
   '@commitlint/cli': 17.2.0
   '@commitlint/config-conventional': 17.2.0
-  '@iconify/json': 2.1.138
-  '@intlify/vite-plugin-vue-i18n': 6.0.3_vite@3.2.3+vue-i18n@9.2.2
+  '@iconify/json': 2.1.139
+  '@intlify/vite-plugin-vue-i18n': 6.0.3_vite@3.2.4+vue-i18n@9.2.2
   '@purge-icons/generated': 0.9.0
   '@types/intro.js': 5.1.0
   '@types/lodash-es': 4.17.6
@@ -126,8 +126,8 @@ devDependencies:
   '@types/qs': 6.9.7
   '@typescript-eslint/eslint-plugin': 5.43.0_yy4vf4gcvxiubmg7fqa55dqe2i
   '@typescript-eslint/parser': 5.43.0_rmayb2veg2btbq6mbmnyivgasy
-  '@vitejs/plugin-vue': 3.2.0_vite@3.2.3+vue@3.2.45
-  '@vitejs/plugin-vue-jsx': 2.1.1_vite@3.2.3+vue@3.2.45
+  '@vitejs/plugin-vue': 3.2.0_vite@3.2.4+vue@3.2.45
+  '@vitejs/plugin-vue-jsx': 2.1.1_vite@3.2.4+vue@3.2.45
   autoprefixer: 10.4.13_postcss@8.4.19
   eslint: 8.27.0
   eslint-config-prettier: 8.5.0_eslint@8.27.0
@@ -150,15 +150,15 @@ devDependencies:
   stylelint-config-standard: 29.0.0_stylelint@14.15.0
   stylelint-order: 5.0.0_stylelint@14.15.0
   typescript: 4.8.4
-  unplugin-vue-macros: 0.16.3_mghlipbkxnxld5kp6aysmuv2fa
-  vite: 3.2.3_mp5lu76ee5qtwstsyca37sdhqi
-  vite-plugin-compression: 0.5.1_vite@3.2.3
-  vite-plugin-eslint: 1.8.1_eslint@8.27.0+vite@3.2.3
-  vite-plugin-html: 3.2.0_vite@3.2.3
-  vite-plugin-purge-icons: 0.9.1_vite@3.2.3
-  vite-plugin-style-import: 2.0.0_vite@3.2.3
-  vite-plugin-svg-icons: 2.0.1_vite@3.2.3
-  vite-plugin-windicss: 1.8.8_vite@3.2.3
+  unplugin-vue-macros: 0.16.3_drqowttw7xgwfzqyhu6wuedde4
+  vite: 3.2.4_mp5lu76ee5qtwstsyca37sdhqi
+  vite-plugin-compression: 0.5.1_vite@3.2.4
+  vite-plugin-eslint: 1.8.1_eslint@8.27.0+vite@3.2.4
+  vite-plugin-html: 3.2.0_vite@3.2.4
+  vite-plugin-purge-icons: 0.9.1_vite@3.2.4
+  vite-plugin-style-import: 2.0.0_vite@3.2.4
+  vite-plugin-svg-icons: 2.0.1_vite@3.2.4
+  vite-plugin-windicss: 1.8.8_vite@3.2.4
   vue-tsc: 1.0.9_typescript@4.8.4
   windicss: 3.5.6
 
@@ -574,11 +574,11 @@ packages:
       '@types/node': 14.18.31
       chalk: 4.1.2
       cosmiconfig: 7.0.1
-      cosmiconfig-typescript-loader: 4.1.1_gpl3msxjb2n3qdkii2jvdrcxxe
+      cosmiconfig-typescript-loader: 4.1.1_kjtesrzmdzjxgbmvhf7rq2qmfi
       lodash: 4.17.21
       resolve-from: 5.0.0
-      ts-node: 10.9.1_fk6arlf3j7tudlucddpzvj2plq
-      typescript: 4.8.4
+      ts-node: 10.9.1_zdwmxzc3s32eishk7hircltqdy
+      typescript: 4.9.3
     transitivePeerDependencies:
       - '@swc/core'
       - '@swc/wasm'
@@ -760,8 +760,8 @@ packages:
     dependencies:
       '@iconify/types': 2.0.0
 
-  /@iconify/json/2.1.138:
-    resolution: {integrity: sha512-migiXo9NKjkc3ob3qRzjdfecyFo39eziD9IY+LbNooQwyU8CS+WoeNtoI34Sf2+3DrV69H0kxeLf3bFQ+nKvew==}
+  /@iconify/json/2.1.139:
+    resolution: {integrity: sha512-H/DQ/yVgdUk4x4hU696fy0mZOkvLQaR6REQU/okFLgaiIFOS+EWw6GV5JDSKbbkh0YVaxUrAUaqB8XTSFVrFeA==}
     dependencies:
       '@iconify/types': 2.0.0
       pathe: 0.3.9
@@ -829,7 +829,7 @@ packages:
     engines: {node: '>= 14'}
     dev: true
 
-  /@intlify/vite-plugin-vue-i18n/6.0.3_vite@3.2.3+vue-i18n@9.2.2:
+  /@intlify/vite-plugin-vue-i18n/6.0.3_vite@3.2.4+vue-i18n@9.2.2:
     resolution: {integrity: sha512-6SgNzPAOCR90wvt368lKzi7f/5ZEWJn22UCGvhFsP3XvKqlF3cVzojahgQ6o+LTdCkExeM6wPgd+haFf28E9VQ==}
     engines: {node: '>= 14.6'}
     peerDependencies:
@@ -850,7 +850,7 @@ packages:
       debug: 4.3.4
       fast-glob: 3.2.12
       source-map: 0.6.1
-      vite: 3.2.3_mp5lu76ee5qtwstsyca37sdhqi
+      vite: 3.2.4_mp5lu76ee5qtwstsyca37sdhqi
       vue-i18n: 9.2.2_vue@3.2.45
     transitivePeerDependencies:
       - supports-color
@@ -1263,7 +1263,7 @@ packages:
       nanoid: 3.3.4
     dev: false
 
-  /@vitejs/plugin-vue-jsx/2.1.1_vite@3.2.3+vue@3.2.45:
+  /@vitejs/plugin-vue-jsx/2.1.1_vite@3.2.4+vue@3.2.45:
     resolution: {integrity: sha512-JgDhxstQlwnHBvZ1BSnU5mbmyQ14/t5JhREc6YH5kWyu2QdAAOsLF6xgHoIWarj8tddaiwFrNzLbWJPudpXKYA==}
     engines: {node: ^14.18.0 || >=16.0.0}
     peerDependencies:
@@ -1273,20 +1273,20 @@ packages:
       '@babel/core': 7.19.6
       '@babel/plugin-transform-typescript': 7.20.2_@babel+core@7.19.6
       '@vue/babel-plugin-jsx': 1.1.1_@babel+core@7.19.6
-      vite: 3.2.3_mp5lu76ee5qtwstsyca37sdhqi
+      vite: 3.2.4_mp5lu76ee5qtwstsyca37sdhqi
       vue: 3.2.45
     transitivePeerDependencies:
       - supports-color
     dev: true
 
-  /@vitejs/plugin-vue/3.2.0_vite@3.2.3+vue@3.2.45:
+  /@vitejs/plugin-vue/3.2.0_vite@3.2.4+vue@3.2.45:
     resolution: {integrity: sha512-E0tnaL4fr+qkdCNxJ+Xd0yM31UwMkQje76fsDVBBUCoGOUPexu2VDUYHL8P4CwV+zMvWw6nlRw19OnRKmYAJpw==}
     engines: {node: ^14.18.0 || >=16.0.0}
     peerDependencies:
       vite: ^3.0.0
       vue: ^3.2.25
     dependencies:
-      vite: 3.2.3_mp5lu76ee5qtwstsyca37sdhqi
+      vite: 3.2.4_mp5lu76ee5qtwstsyca37sdhqi
       vue: 3.2.45
     dev: true
 
@@ -1418,16 +1418,16 @@ packages:
       unplugin: 0.10.2
     dev: true
 
-  /@vue-macros/named-template/0.0.5_poefzxy2vtculed3kqru6isufm:
+  /@vue-macros/named-template/0.0.5_ygspmtsr7jejaf6wke2f4dns5a:
     resolution: {integrity: sha512-bZRUljNyvOOqeE9dyqXvKPQCLUCcPt1EkThmXqSbxagV29ohyviF8+CCs/8OdmNygLTBIChjP8DexQ3nUIFzUg==}
     engines: {node: '>=14.19.0'}
     dependencies:
       '@rollup/pluginutils': 4.2.1
-      '@vitejs/plugin-vue': 3.2.0_vite@3.2.3+vue@3.2.45
+      '@vitejs/plugin-vue': 3.2.0_vite@3.2.4+vue@3.2.45
       '@vue-macros/common': 0.13.3
       '@vue/compiler-dom': 3.2.45
       unplugin: 0.10.2
-      unplugin-combine: 0.2.8_rollup@3.3.0+vite@3.2.3
+      unplugin-combine: 0.2.8_rollup@3.3.0+vite@3.2.4
     transitivePeerDependencies:
       - esbuild
       - rollup
@@ -1436,14 +1436,14 @@ packages:
       - webpack
     dev: true
 
-  /@vue-macros/setup-component/0.12.7_rollup@3.3.0+vite@3.2.3:
+  /@vue-macros/setup-component/0.12.7_rollup@3.3.0+vite@3.2.4:
     resolution: {integrity: sha512-L0WkJgw0QDwZh4tOjjKIDR0DMIybiOunsaxVqkJjicTb2YaiRUSLq4Wadl8Ttrsd0IEfI51CSlg7Sx0/dKLrlQ==}
     engines: {node: '>=14.19.0'}
     dependencies:
       '@rollup/pluginutils': 4.2.1
       '@vue-macros/common': 0.13.3
       unplugin: 0.10.2
-      unplugin-combine: 0.2.8_rollup@3.3.0+vite@3.2.3
+      unplugin-combine: 0.2.8_rollup@3.3.0+vite@3.2.4
     transitivePeerDependencies:
       - esbuild
       - rollup
@@ -1565,10 +1565,6 @@ packages:
   /@vue/devtools-api/6.4.3:
     resolution: {integrity: sha512-9WCRwdROJvWcHAdyrR7SZMM/qUvllDZnpndHXokThkUsjnJ2xe4/pvsH9FZrxFe22L+JmDKczL79HjLJ7DK9rg==}
 
-  /@vue/devtools-api/6.4.4:
-    resolution: {integrity: sha512-Ku31WzpOV/8cruFaXaEZKF81WkNnvCSlBY4eOGtz5WMSdJvX1v1WWlSMGZeqUwPtQ27ZZz7B62erEMq8JDjcXw==}
-    dev: false
-
   /@vue/devtools-api/6.4.5:
     resolution: {integrity: sha512-JD5fcdIuFxU4fQyXUu3w2KpAJHzTVdN+p4iOX2lMWSHMOoQdMAcpFLZzm9Z/2nmsoZ1a96QEhZ26e50xLBsgOQ==}
     dev: false
@@ -2615,7 +2611,7 @@ packages:
       vary: 1.1.2
     dev: true
 
-  /cosmiconfig-typescript-loader/4.1.1_gpl3msxjb2n3qdkii2jvdrcxxe:
+  /cosmiconfig-typescript-loader/4.1.1_kjtesrzmdzjxgbmvhf7rq2qmfi:
     resolution: {integrity: sha512-9DHpa379Gp0o0Zefii35fcmuuin6q92FnLDffzdZ0l9tVd3nEobG3O+MZ06+kuBvFTSVScvNb/oHA13Nd4iipg==}
     engines: {node: '>=12', npm: '>=6'}
     peerDependencies:
@@ -2626,8 +2622,8 @@ packages:
     dependencies:
       '@types/node': 14.18.31
       cosmiconfig: 7.0.1
-      ts-node: 10.9.1_fk6arlf3j7tudlucddpzvj2plq
-      typescript: 4.8.4
+      ts-node: 10.9.1_zdwmxzc3s32eishk7hircltqdy
+      typescript: 4.9.3
     dev: true
 
   /cosmiconfig/7.0.1:
@@ -5564,8 +5560,8 @@ packages:
     dev: true
     optional: true
 
-  /pinia/2.0.23_zwu2zepfy3m6u2gunxlolp35gi:
-    resolution: {integrity: sha512-N15hFf4o5STrxpNrib1IEb1GOArvPYf1zPvQVRGOO1G1d74Ak0J0lVyalX/SmrzdT4Q0nlEFjbURsmBmIGUR5Q==}
+  /pinia/2.0.24_zwu2zepfy3m6u2gunxlolp35gi:
+    resolution: {integrity: sha512-DDLd4Iphyc+6PYYYbx7jkb6WP9gecgu9bz9huyB5rb7CdJI3DhzYiZI+/Ih8MLewRrP9DSpslF/BgSNrJtZU7A==}
     peerDependencies:
       '@vue/composition-api': ^1.4.0
       typescript: '>=4.4.4'
@@ -5576,7 +5572,7 @@ packages:
       typescript:
         optional: true
     dependencies:
-      '@vue/devtools-api': 6.4.4
+      '@vue/devtools-api': 6.4.5
       typescript: 4.8.4
       vue: 3.2.45
       vue-demi: 0.13.11_vue@3.2.45
@@ -6673,7 +6669,7 @@ packages:
     engines: {node: '>=8'}
     dev: true
 
-  /ts-node/10.9.1_fk6arlf3j7tudlucddpzvj2plq:
+  /ts-node/10.9.1_zdwmxzc3s32eishk7hircltqdy:
     resolution: {integrity: sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==}
     hasBin: true
     peerDependencies:
@@ -6699,7 +6695,7 @@ packages:
       create-require: 1.1.1
       diff: 4.0.2
       make-error: 1.3.6
-      typescript: 4.8.4
+      typescript: 4.9.3
       v8-compile-cache-lib: 3.0.1
       yn: 3.1.1
     dev: true
@@ -6771,6 +6767,12 @@ packages:
     engines: {node: '>=4.2.0'}
     hasBin: true
 
+  /typescript/4.9.3:
+    resolution: {integrity: sha512-CIfGzTelbKNEnLpLdGFgdyKhG23CKdKgQPOBc+OUNrkJ2vr+KSzsSV5kq5iWhEQbok+quxgGzrAtGWCyU7tHnA==}
+    engines: {node: '>=4.2.0'}
+    hasBin: true
+    dev: true
+
   /uglify-js/3.17.3:
     resolution: {integrity: sha512-JmMFDME3iufZnBpyKL+uS78LRiC+mK55zWfM5f/pWBJfpOttXAqYfdDGRukYhJuyRinvPVAtUhvy7rlDybNtFg==}
     engines: {node: '>=0.8.0'}
@@ -6799,7 +6801,7 @@ packages:
     engines: {node: '>= 10.0.0'}
     dev: true
 
-  /unplugin-combine/0.2.8_rollup@3.3.0+vite@3.2.3:
+  /unplugin-combine/0.2.8_rollup@3.3.0+vite@3.2.4:
     resolution: {integrity: sha512-Z38AC/TEjXbVyZ5HjVqo+lADj0/dcfwWC0Z4y0LNhybJzJQwmcMxm+ZsqHY3faauj4YigmlRMdptR5JEW9RuLg==}
     engines: {node: '>=14.19.0'}
     peerDependencies:
@@ -6820,7 +6822,7 @@ packages:
       '@antfu/utils': 0.6.0
       rollup: 3.3.0
       unplugin: 0.10.2
-      vite: 3.2.3_mp5lu76ee5qtwstsyca37sdhqi
+      vite: 3.2.4_mp5lu76ee5qtwstsyca37sdhqi
     dev: true
 
   /unplugin-vue-define-options/0.12.7:
@@ -6833,7 +6835,7 @@ packages:
       unplugin: 0.10.2
     dev: true
 
-  /unplugin-vue-macros/0.16.3_mghlipbkxnxld5kp6aysmuv2fa:
+  /unplugin-vue-macros/0.16.3_drqowttw7xgwfzqyhu6wuedde4:
     resolution: {integrity: sha512-ADdDS5EjHRZ2esEHSNBw7CS7QLWpqvNJIW0H5EqKgSvtQ+2Hnb8IeRVT0f4mR+wyQvl/ZrlpTs1GvZdsh8eSlw==}
     engines: {node: '>=14.19.0'}
     peerDependencies:
@@ -6846,12 +6848,12 @@ packages:
       '@vue-macros/define-render': 0.13.8_vue@3.2.45
       '@vue-macros/define-slots': 0.0.5_vue@3.2.45
       '@vue-macros/hoist-static': 0.12.7
-      '@vue-macros/named-template': 0.0.5_poefzxy2vtculed3kqru6isufm
-      '@vue-macros/setup-component': 0.12.7_rollup@3.3.0+vite@3.2.3
+      '@vue-macros/named-template': 0.0.5_ygspmtsr7jejaf6wke2f4dns5a
+      '@vue-macros/setup-component': 0.12.7_rollup@3.3.0+vite@3.2.4
       '@vue-macros/setup-sfc': 0.12.7
       '@vue-macros/short-emits': 0.12.8
       local-pkg: 0.4.2
-      unplugin-combine: 0.2.8_rollup@3.3.0+vite@3.2.3
+      unplugin-combine: 0.2.8_rollup@3.3.0+vite@3.2.4
       unplugin-vue-define-options: 0.12.7
       vue: 3.2.45
     transitivePeerDependencies:
@@ -6954,7 +6956,7 @@ packages:
     engines: {node: '>= 0.8'}
     dev: true
 
-  /vite-plugin-compression/0.5.1_vite@3.2.3:
+  /vite-plugin-compression/0.5.1_vite@3.2.4:
     resolution: {integrity: sha512-5QJKBDc+gNYVqL/skgFAP81Yuzo9R+EAf19d+EtsMF/i8kFUpNi3J/H01QD3Oo8zBQn+NzoCIFkpPLynoOzaJg==}
     peerDependencies:
       vite: '>=2.0.0'
@@ -6962,12 +6964,12 @@ packages:
       chalk: 4.1.2
       debug: 4.3.4
       fs-extra: 10.1.0
-      vite: 3.2.3_mp5lu76ee5qtwstsyca37sdhqi
+      vite: 3.2.4_mp5lu76ee5qtwstsyca37sdhqi
     transitivePeerDependencies:
       - supports-color
     dev: true
 
-  /vite-plugin-eslint/1.8.1_eslint@8.27.0+vite@3.2.3:
+  /vite-plugin-eslint/1.8.1_eslint@8.27.0+vite@3.2.4:
     resolution: {integrity: sha512-PqdMf3Y2fLO9FsNPmMX+//2BF5SF8nEWspZdgl4kSt7UvHDRHVVfHvxsD7ULYzZrJDGRxR81Nq7TOFgwMnUang==}
     peerDependencies:
       eslint: '>=7'
@@ -6977,10 +6979,10 @@ packages:
       '@types/eslint': 8.4.6
       eslint: 8.27.0
       rollup: 2.79.1
-      vite: 3.2.3_mp5lu76ee5qtwstsyca37sdhqi
+      vite: 3.2.4_mp5lu76ee5qtwstsyca37sdhqi
     dev: true
 
-  /vite-plugin-html/3.2.0_vite@3.2.3:
+  /vite-plugin-html/3.2.0_vite@3.2.4:
     resolution: {integrity: sha512-2VLCeDiHmV/BqqNn5h2V+4280KRgQzCFN47cst3WiNK848klESPQnzuC3okH5XHtgwHH/6s1Ho/YV6yIO0pgoQ==}
     peerDependencies:
       vite: '>=2.0.0'
@@ -6997,10 +6999,10 @@ packages:
       html-minifier-terser: 6.1.0
       node-html-parser: 5.4.2
       pathe: 0.2.0
-      vite: 3.2.3_mp5lu76ee5qtwstsyca37sdhqi
+      vite: 3.2.4_mp5lu76ee5qtwstsyca37sdhqi
     dev: true
 
-  /vite-plugin-purge-icons/0.9.1_vite@3.2.3:
+  /vite-plugin-purge-icons/0.9.1_vite@3.2.4:
     resolution: {integrity: sha512-oS0Y9Iq6vGnTDVRzB8xJNhA/gGlyR0lfCICU6+9FRKdrO5PnT34fRjvd8YWEsegCrk91+w3GVZc0HJDj/dPp5Q==}
     engines: {node: '>= 12'}
     peerDependencies:
@@ -7009,13 +7011,13 @@ packages:
       '@purge-icons/core': 0.9.1
       '@purge-icons/generated': 0.9.0
       rollup-plugin-purge-icons: 0.9.1
-      vite: 3.2.3_mp5lu76ee5qtwstsyca37sdhqi
+      vite: 3.2.4_mp5lu76ee5qtwstsyca37sdhqi
     transitivePeerDependencies:
       - encoding
       - supports-color
     dev: true
 
-  /vite-plugin-style-import/2.0.0_vite@3.2.3:
+  /vite-plugin-style-import/2.0.0_vite@3.2.4:
     resolution: {integrity: sha512-qtoHQae5dSUQPo/rYz/8p190VU5y19rtBaeV7ryLa/AYAU/e9CG89NrN/3+k7MR8mJy/GPIu91iJ3zk9foUOSA==}
     peerDependencies:
       vite: '>=2.0.0'
@@ -7027,10 +7029,10 @@ packages:
       fs-extra: 10.1.0
       magic-string: 0.25.9
       pathe: 0.2.0
-      vite: 3.2.3_mp5lu76ee5qtwstsyca37sdhqi
+      vite: 3.2.4_mp5lu76ee5qtwstsyca37sdhqi
     dev: true
 
-  /vite-plugin-svg-icons/2.0.1_vite@3.2.3:
+  /vite-plugin-svg-icons/2.0.1_vite@3.2.4:
     resolution: {integrity: sha512-6ktD+DhV6Rz3VtedYvBKKVA2eXF+sAQVaKkKLDSqGUfnhqXl3bj5PPkVTl3VexfTuZy66PmINi8Q6eFnVfRUmA==}
     peerDependencies:
       vite: '>=2.0.0'
@@ -7043,12 +7045,12 @@ packages:
       pathe: 0.2.0
       svg-baker: 1.7.0
       svgo: 2.8.0
-      vite: 3.2.3_mp5lu76ee5qtwstsyca37sdhqi
+      vite: 3.2.4_mp5lu76ee5qtwstsyca37sdhqi
     transitivePeerDependencies:
       - supports-color
     dev: true
 
-  /vite-plugin-windicss/1.8.8_vite@3.2.3:
+  /vite-plugin-windicss/1.8.8_vite@3.2.4:
     resolution: {integrity: sha512-iyu+ZX0NmhNEUaLPv7xtC+EFRBpWMmw0nhd9a9upayfuNG/thwslKiQKmRB7U/dG0k/2oWLvPDvN/B9i7oRgSA==}
     peerDependencies:
       vite: ^2.0.1 || ^3.0.0
@@ -7056,14 +7058,14 @@ packages:
       '@windicss/plugin-utils': 1.8.8
       debug: 4.3.4
       kolorist: 1.6.0
-      vite: 3.2.3_mp5lu76ee5qtwstsyca37sdhqi
+      vite: 3.2.4_mp5lu76ee5qtwstsyca37sdhqi
       windicss: 3.5.6
     transitivePeerDependencies:
       - supports-color
     dev: true
 
-  /vite/3.2.3_mp5lu76ee5qtwstsyca37sdhqi:
-    resolution: {integrity: sha512-h8jl1TZ76eGs3o2dIBSsvXDLb1m/Ec1iej8ZMdz+PsaFUsftZeWe2CZOI3qogEsMNaywc17gu0q6cQDzh/weCQ==}
+  /vite/3.2.4_mp5lu76ee5qtwstsyca37sdhqi:
+    resolution: {integrity: sha512-Z2X6SRAffOUYTa+sLy3NQ7nlHFU100xwanq1WDwqaiFiCe+25zdxP1TfCS5ojPV2oDDcXudHIoPnI1Z/66B7Yw==}
     engines: {node: ^14.18.0 || >=16.0.0}
     hasBin: true
     peerDependencies:

+ 9 - 0
yudao-ui-admin-vue3/src/api/login/index.ts

@@ -62,3 +62,12 @@ export const socialAuthRedirectApi = (type: string, redirectUri: string) => {
     url: '/system/auth/social-auth-redirect?type=' + type + '&redirectUri=' + redirectUri
   })
 }
+// 获取验证图片  以及token
+export const getCodeApi = (data) => {
+  return request.postOriginal({ url: 'system/captcha/get', data })
+}
+
+// 滑动或者点选验证
+export const reqCheckApi = (data) => {
+  return request.postOriginal({ url: 'system/captcha/check', data })
+}

+ 27 - 13
yudao-ui-admin-vue3/src/api/system/dept/index.ts

@@ -1,32 +1,46 @@
 import request from '@/config/axios'
-import type { DeptVO, DeptListReqVO } from './types'
+export type DeptVO = {
+  id: number
+  name: string
+  parentId: number
+  status: number
+  sort: number
+  leaderUserId: number
+  phone: string
+  email: string
+}
+
+export interface DeptPageReqVO {
+  name?: string
+  status?: number
+}
 
 // 查询部门(精简)列表
-export const listSimpleDeptApi = () => {
-  return request.get({ url: '/system/dept/list-all-simple' })
+export const listSimpleDeptApi = async () => {
+  return await request.get({ url: '/system/dept/list-all-simple' })
 }
 
 // 查询部门列表
-export const getDeptPageApi = (params: DeptListReqVO) => {
-  return request.get({ url: '/system/dept/list', params })
+export const getDeptPageApi = async (params: DeptPageReqVO) => {
+  return await request.get({ url: '/system/dept/list', params })
 }
 
 // 查询部门详情
-export const getDeptApi = (id: number) => {
-  return request.get({ url: '/system/dept/get?id=' + id })
+export const getDeptApi = async (id: number) => {
+  return await request.get({ url: '/system/dept/get?id=' + id })
 }
 
 // 新增部门
-export const createDeptApi = (data: DeptVO) => {
-  return request.post({ url: '/system/dept/create', data: data })
+export const createDeptApi = async (data: DeptVO) => {
+  return await request.post({ url: '/system/dept/create', data: data })
 }
 
 // 修改部门
-export const updateDeptApi = (params: DeptVO) => {
-  return request.put({ url: '/system/dept/update', data: params })
+export const updateDeptApi = async (params: DeptVO) => {
+  return await request.put({ url: '/system/dept/update', data: params })
 }
 
 // 删除部门
-export const deleteDeptApi = (id: number) => {
-  return request.delete({ url: '/system/dept/delete?id=' + id })
+export const deleteDeptApi = async (id: number) => {
+  return await request.delete({ url: '/system/dept/delete?id=' + id })
 }

+ 6 - 9
yudao-ui-admin-vue3/src/components/Crontab/src/Crontab.vue

@@ -1,11 +1,3 @@
-<!--
- * @Descripttion: cron规则生成器
- * @version: 1.0
- * @Author: sakuya
- * @Date: 2021年12月29日15:23:54
- * @LastEditors:
- * @LastEditTime:
--->
 <script setup lang="ts">
 import {
   ElInput,
@@ -520,7 +512,12 @@ const submit = () => {
 <template>
   <el-input v-model="defaultValue" v-bind="$attrs">
     <template #append>
-      <el-dropdown split-button trigger="click" @command="handleShortcuts">
+      <el-dropdown
+        split-button
+        type="text"
+        @command="handleShortcuts"
+        style="width: 35px; margin-left: 5px; margin-right: 2px"
+      >
         生成器
         <template #dropdown>
           <el-dropdown-menu>

+ 3 - 7
yudao-ui-admin-vue3/src/components/Form/src/Form.vue

@@ -226,11 +226,7 @@ export default defineComponent({
                   vModel={formModel.value[item.field]}
                   {...(autoSetPlaceholder && setTextPlaceholder(item))}
                   {...setComponentProps(item)}
-                  style={
-                    item?.component === 'Input'
-                      ? { width: '189.5px', ...item.componentProps?.style }
-                      : { ...item.componentProps?.style }
-                  }
+                  style={item.componentProps?.style}
                   {...(notRenderOptions.includes(item?.component as string) &&
                   item?.componentProps?.options
                     ? { options: item?.componentProps?.options || [] }
@@ -258,8 +254,8 @@ export default defineComponent({
           return renderRadioOptions(item)
         case 'Checkbox':
         case 'CheckboxButton':
-          const { renderChcekboxOptions } = useRenderCheckbox()
-          return renderChcekboxOptions(item)
+          const { renderCheckboxOptions } = useRenderCheckbox()
+          return renderCheckboxOptions(item)
         default:
           break
       }

+ 4 - 4
yudao-ui-admin-vue3/src/components/Form/src/components/useRenderCheckbox.tsx

@@ -3,7 +3,7 @@ import { ElCheckbox, ElCheckboxButton } from 'element-plus'
 import { defineComponent } from 'vue'
 
 export const useRenderCheckbox = () => {
-  const renderChcekboxOptions = (item: FormSchema) => {
+  const renderCheckboxOptions = (item: FormSchema) => {
     // 如果有别名,就取别名
     const labelAlias = item?.componentProps?.optionsAlias?.labelField
     const valueAlias = item?.componentProps?.optionsAlias?.valueField
@@ -13,14 +13,14 @@ export const useRenderCheckbox = () => {
     return item?.componentProps?.options?.map((option) => {
       const { ...other } = option
       return (
-        <Com label={option[labelAlias || 'value']} {...other}>
-          {option[valueAlias || 'label']}
+        <Com {...other} label={option[valueAlias || 'value']}>
+          {option[labelAlias || 'label']}
         </Com>
       )
     })
   }
 
   return {
-    renderChcekboxOptions
+    renderCheckboxOptions
   }
 }

+ 2 - 2
yudao-ui-admin-vue3/src/components/Form/src/components/useRenderRadio.tsx

@@ -13,8 +13,8 @@ export const useRenderRadio = () => {
     return item?.componentProps?.options?.map((option) => {
       const { ...other } = option
       return (
-        <Com label={option[labelAlias || 'value']} {...other}>
-          {option[valueAlias || 'label']}
+        <Com {...other} label={option[valueAlias || 'value']}>
+          {option[labelAlias || 'label']}
         </Com>
       )
     })

+ 1 - 1
yudao-ui-admin-vue3/src/components/Form/src/components/useRenderSelect.tsx

@@ -36,9 +36,9 @@ export const useRenderSelect = (slots: Slots) => {
 
     return (
       <ElOption
+        {...other}
         label={labelAlias ? option[labelAlias] : label}
         value={valueAlias ? option[valueAlias] : value}
-        {...other}
       >
         {{
           default: () =>

+ 10 - 5
yudao-ui-admin-vue3/src/components/Verifition/src/Verify.vue

@@ -2,7 +2,7 @@
   <div :class="mode == 'pop' ? 'mask' : ''" v-show="showBox">
     <div
       :class="mode == 'pop' ? 'verifybox' : ''"
-      :style="{ 'max-width': parseInt(imgSize.width) + 30 + 'px' }"
+      :style="{ 'max-width': parseInt(imgSize.width) + 20 + 'px' }"
     >
       <div class="verifybox-top" v-if="mode == 'pop'">
         {{ t('captcha.verification') }}
@@ -10,7 +10,7 @@
           <i class="iconfont icon-close"></i>
         </span>
       </div>
-      <div class="verifybox-bottom" :style="{ padding: mode == 'pop' ? '15px' : '0' }">
+      <div class="verifybox-bottom" :style="{ padding: mode == 'pop' ? '10px' : '0' }">
         <!-- 验证码容器 -->
         <component
           v-if="componentType"
@@ -153,12 +153,13 @@ export default {
   box-shadow: 0 0 10px rgba(0, 0, 0, 0.3);
   left: 50%;
   top: 50%;
+  border-radius: 5px;
   transform: translate(-50%, -50%);
 }
 .verifybox-top {
   padding: 0 15px;
-  height: 50px;
-  line-height: 50px;
+  height: 40px;
+  line-height: 40px;
   text-align: left;
   font-size: 16px;
   color: #45494c;
@@ -166,7 +167,7 @@ export default {
   box-sizing: border-box;
 }
 .verifybox-bottom {
-  padding: 15px;
+  padding: 10px;
   box-sizing: border-box;
 }
 .verifybox-close {
@@ -262,6 +263,7 @@ export default {
   color: #ffffff;
   border: none;
   margin-top: 10px;
+  border-radius: 8px;
 }
 
 /*滑动验证码*/
@@ -273,6 +275,7 @@ export default {
   -moz-box-sizing: content-box;
   box-sizing: content-box;
   border: 1px solid #ddd;
+  border-radius: 8px;
 }
 
 .verify-bar-area .verify-move-block {
@@ -285,6 +288,7 @@ export default {
   -moz-box-sizing: content-box;
   box-sizing: content-box;
   box-shadow: 0 0 2px #888888;
+  border-radius: 8px;
 }
 
 .verify-bar-area .verify-move-block:hover {
@@ -302,6 +306,7 @@ export default {
   -moz-box-sizing: content-box;
   box-sizing: content-box;
   border: 1px solid #ddd;
+  border-radius: 8px;
 }
 
 .verify-img-panel {

+ 3 - 3
yudao-ui-admin-vue3/src/components/Verifition/src/Verify/VerifyPoints.vue

@@ -64,7 +64,7 @@
  * */
 import { resetSize } from './../utils/util'
 import { aesEncrypt } from './../utils/ase'
-import { reqGet, reqCheck } from './../api/index'
+import { getCodeApi, reqCheckApi } from '@/api/login'
 import { onMounted, reactive, ref, nextTick, toRefs, getCurrentInstance } from 'vue'
 import { useI18n } from '@/hooks/web/useI18n'
 export default {
@@ -172,7 +172,7 @@ export default {
               : JSON.stringify(checkPosArr),
             token: backToken.value
           }
-          reqCheck(data).then((res) => {
+          reqCheckApi(data).then((res) => {
             if (res.repCode == '0000') {
               barAreaColor.value = '#4cae4c'
               barAreaBorderColor.value = '#5cb85c'
@@ -230,7 +230,7 @@ export default {
       let data = {
         captchaType: captchaType.value
       }
-      reqGet(data).then((res) => {
+      getCodeApi(data).then((res) => {
         if (res.repCode == '0000') {
           pointBackImgBase.value = res.repData.originalImageBase64
           backToken.value = res.repData.token

+ 4 - 4
yudao-ui-admin-vue3/src/components/Verifition/src/Verify/VerifySlide.vue

@@ -78,7 +78,7 @@
  * */
 import { aesEncrypt } from './../utils/ase'
 import { resetSize } from './../utils/util'
-import { reqGet, reqCheck } from './../api/index'
+import { getCodeApi, reqCheckApi } from '@/api/login'
 import { useI18n } from '@/hooks/web/useI18n'
 import {
   computed,
@@ -137,7 +137,7 @@ export default {
       default() {
         return {
           width: '310px',
-          height: '40px'
+          height: '30px'
         }
       }
     }
@@ -302,7 +302,7 @@ export default {
             : JSON.stringify({ x: moveLeftDistance, y: 5.0 }),
           token: backToken.value
         }
-        reqCheck(data).then((res) => {
+        reqCheckApi(data).then((res) => {
           if (res.repCode == '0000') {
             moveBlockBackgroundColor.value = '#5cb85c'
             leftBarBorderColor.value = '#5cb85c'
@@ -379,7 +379,7 @@ export default {
       let data = {
         captchaType: captchaType.value
       }
-      reqGet(data).then((res) => {
+      getCodeApi(data).then((res) => {
         if (res.repCode == '0000') {
           backImgBase.value = res.repData.originalImageBase64
           blockBackImgBase.value = res.repData.jigsawImageBase64

+ 0 - 26
yudao-ui-admin-vue3/src/components/Verifition/src/api/index.ts

@@ -1,26 +0,0 @@
-/**
- * 此处可直接引用自己项目封装好的 axios 配合后端联调
- */
-
-import request from './../utils/axios' //组件内部封装的axios
-// import request from "@/api/axios.js"       //调用项目封装的axios
-
-//获取验证图片  以及token
-export function reqGet(data) {
-  return request({
-    // url: '/captcha/get',
-    url: '/admin-api/system/captcha/get', // 使用项目自定义的 /admin-api/ 前缀
-    method: 'post',
-    data
-  })
-}
-
-//滑动或者点选验证
-export function reqCheck(data) {
-  return request({
-    // url: '/captcha/check',
-    url: '/admin-api/system/captcha/check', // 使用项目自定义的 /admin-api/ 前缀
-    method: 'post',
-    data
-  })
-}

+ 0 - 26
yudao-ui-admin-vue3/src/components/Verifition/src/utils/axios.ts

@@ -1,26 +0,0 @@
-import axios from 'axios'
-
-axios.defaults.baseURL = import.meta.env.VITE_BASE_URL
-
-const service = axios.create({
-  timeout: 40000,
-  headers: {
-    'X-Requested-With': 'XMLHttpRequest',
-    'Content-Type': 'application/json; charset=UTF-8'
-  }
-})
-service.interceptors.request.use(
-  (config) => {
-    return config
-  },
-  (error) => {
-    Promise.reject(error)
-  }
-)
-
-// response interceptor
-service.interceptors.response.use((response) => {
-  const res = response.data
-  return res
-})
-export default service

+ 4 - 0
yudao-ui-admin-vue3/src/config/axios/index.ts

@@ -26,6 +26,10 @@ export default {
     const res = await request({ method: 'POST', ...option })
     return res.data as unknown as T
   },
+  postOriginal: async (option: any) => {
+    const res = await request({ method: 'POST', ...option })
+    return res
+  },
   delete: async <T = any>(option: any) => {
     const res = await request({ method: 'DELETE', ...option })
     return res.data as unknown as T

+ 1 - 0
yudao-ui-admin-vue3/src/config/axios/service.ts

@@ -206,6 +206,7 @@ service.interceptors.response.use(
 )
 
 const refreshToken = async () => {
+  axios.defaults.headers.common['tenant-id'] = getTenantId()
   return await axios.post(base_url + '/system/auth/refresh-token?refreshToken=' + getRefreshToken())
 }
 const handleAuthorized = () => {

+ 23 - 10
yudao-ui-admin-vue3/src/hooks/web/useCrudSchemas.ts

@@ -7,10 +7,14 @@ import { DescriptionsSchema } from '@/types/descriptions'
 import { ComponentOptions } from '@/types/components'
 
 export type CrudSchema = Omit<TableColumn, 'children'> & {
-  search?: CrudSearchParams
-  table?: CrudTableParams
-  form?: CrudFormParams
-  detail?: CrudDescriptionsParams
+  isSearch?: boolean // 是否在查询显示
+  search?: CrudSearchParams // 查询的详细配置
+  isTable?: boolean // 是否在列表显示
+  table?: CrudTableParams // 列表的详细配置
+  isForm?: boolean // 是否在表单显示
+  form?: CrudFormParams // 表单的详细配置
+  isDetail?: boolean // 是否在详情显示
+  detail?: CrudDescriptionsParams // 详情的详细配置
   children?: CrudSchema[]
   dictType?: string // 字典类型
   dictData?: 'string' | 'number' | 'boolean' // 字典数据类型 string | number | boolean
@@ -80,7 +84,7 @@ const filterSearchSchema = (crudSchema: CrudSchema[]): FormSchema[] => {
 
   eachTree(crudSchema, (schemaItem: CrudSchema) => {
     // 判断是否显示
-    if (schemaItem?.search?.show) {
+    if (schemaItem?.isSearch || schemaItem.search?.show) {
       let component = schemaItem?.search?.component || 'Input'
       const options: ComponentOptions[] = []
       let comonentProps = {}
@@ -93,7 +97,7 @@ const filterSearchSchema = (crudSchema: CrudSchema[]): FormSchema[] => {
         comonentProps = {
           options: options
         }
-        if (!schemaItem.search.component) component = 'Select'
+        if (!schemaItem.search?.component) component = 'Select'
       }
       const searchSchemaItem = {
         // 默认为 input
@@ -116,7 +120,7 @@ const filterSearchSchema = (crudSchema: CrudSchema[]): FormSchema[] => {
 const filterTableSchema = (crudSchema: CrudSchema[]): TableColumn[] => {
   const tableColumns = treeMap<CrudSchema>(crudSchema, {
     conversion: (schema: CrudSchema) => {
-      if (schema?.table?.show !== false) {
+      if (schema?.isTable !== false || schema?.table?.show !== false) {
         return {
           ...schema.table,
           ...schema
@@ -140,11 +144,19 @@ const filterFormSchema = (crudSchema: CrudSchema[]): FormSchema[] => {
 
   eachTree(crudSchema, (schemaItem: CrudSchema) => {
     // 判断是否显示
-    if (schemaItem?.form?.show !== false) {
+    if (schemaItem?.isForm !== false || schemaItem?.form?.show == true) {
       let component = schemaItem?.form?.component || 'Input'
-      const options: ComponentOptions[] = []
+      let defaultValue: any = ''
+      if (schemaItem.form?.value) {
+        defaultValue = schemaItem.form?.value
+      } else {
+        if (component === 'InputNumber') {
+          defaultValue = 0
+        }
+      }
       let comonentProps = {}
       if (schemaItem.dictType) {
+        const options: ComponentOptions[] = []
         if (schemaItem.dictData && schemaItem.dictData === 'number') {
           getIntDictOptions(schemaItem.dictType).forEach((dict) => {
             options.push(dict)
@@ -167,6 +179,7 @@ const filterFormSchema = (crudSchema: CrudSchema[]): FormSchema[] => {
         // 默认为 input
         component: component,
         componentProps: comonentProps,
+        value: defaultValue,
         ...schemaItem.form,
         field: schemaItem.field,
         label: schemaItem.form?.label || schemaItem.label
@@ -188,7 +201,7 @@ const filterDescriptionsSchema = (crudSchema: CrudSchema[]): DescriptionsSchema[
 
   eachTree(crudSchema, (schemaItem: CrudSchema) => {
     // 判断是否显示
-    if (schemaItem?.detail?.show !== false) {
+    if (schemaItem?.isDetail !== false || schemaItem.detail?.show !== false) {
       const descriptionsSchemaItem = {
         ...schemaItem.detail,
         field: schemaItem.field,

+ 15 - 6
yudao-ui-admin-vue3/src/hooks/web/useVxeCrudSchemas.ts

@@ -181,7 +181,7 @@ const filterTableSchema = (crudSchema: VxeCrudSchema): VxeGridPropTypes.Columns
   }
   eachTree(crudSchema.columns, (schemaItem: VxeCrudColumns) => {
     // 判断是否显示
-    if (schemaItem?.isTable !== false) {
+    if (schemaItem?.isTable !== false && schemaItem?.table?.show !== false) {
       const tableSchemaItem = {
         ...schemaItem.table,
         field: schemaItem.field,
@@ -227,9 +227,17 @@ const filterFormSchema = (crudSchema: VxeCrudSchema): FormSchema[] => {
     if (schemaItem?.isForm !== false || schemaItem?.form?.show == true) {
       // 默认为 input
       let component = schemaItem?.form?.component || 'Input'
-      const options: ComponentOptions[] = []
+      let defaultValue: any = ''
+      if (schemaItem.form?.value) {
+        defaultValue = schemaItem.form?.value
+      } else {
+        if (component === 'InputNumber') {
+          defaultValue = 0
+        }
+      }
       let comonentProps = {}
       if (schemaItem.dictType) {
+        const options: ComponentOptions[] = []
         if (schemaItem.dictData && schemaItem.dictData === 'number') {
           getIntDictOptions(schemaItem.dictType).forEach((dict) => {
             options.push(dict)
@@ -249,11 +257,12 @@ const filterFormSchema = (crudSchema: VxeCrudSchema): FormSchema[] => {
         if (!(schemaItem.form && schemaItem.form.component)) component = 'Select'
       }
       const formSchemaItem = {
+        component: component,
+        componentProps: comonentProps,
+        value: defaultValue,
         ...schemaItem.form,
         field: schemaItem.field,
-        label: schemaItem.form?.label || schemaItem.title,
-        component: component,
-        componentProps: comonentProps
+        label: schemaItem.form?.label || schemaItem.title
       }
 
       formSchema.push(formSchemaItem)
@@ -269,7 +278,7 @@ const filterDescriptionsSchema = (crudSchema: VxeCrudSchema): DescriptionsSchema
 
   eachTree(crudSchema.columns, (schemaItem: VxeCrudColumns) => {
     // 判断是否显示
-    if (schemaItem?.isDetail !== false) {
+    if (schemaItem?.isDetail !== false || schemaItem.detail?.show !== false) {
       const descriptionsSchemaItem = {
         ...schemaItem.detail,
         field: schemaItem.field,

+ 1 - 1
yudao-ui-admin-vue3/src/router/index.ts

@@ -14,7 +14,7 @@ import { isRelogin } from '@/config/axios/service'
 import { getInfoApi } from '@/api/login'
 import { useCache } from '@/hooks/web/useCache'
 
-const { wsCache } = useCache()
+const { wsCache } = useCache('sessionStorage')
 
 const { start, done } = useNProgress()
 

+ 3 - 4
yudao-ui-admin-vue3/src/views/Error/403.vue

@@ -1,3 +1,6 @@
+<template>
+  <Error type="403" @error-click="errorClick" />
+</template>
 <script setup lang="ts">
 import { Error } from '@/components/Error'
 import { useRouter } from 'vue-router'
@@ -8,7 +11,3 @@ const errorClick = () => {
   push('/')
 }
 </script>
-
-<template>
-  <Error type="403" @error-click="errorClick" />
-</template>

+ 4 - 4
yudao-ui-admin-vue3/src/views/Error/404.vue

@@ -1,3 +1,7 @@
+<template>
+  <Error @error-click="errorClick" />
+</template>
+
 <script setup lang="ts">
 import { Error } from '@/components/Error'
 import { useRouter } from 'vue-router'
@@ -8,7 +12,3 @@ const errorClick = () => {
   push('/')
 }
 </script>
-
-<template>
-  <Error @error-click="errorClick" />
-</template>

+ 4 - 4
yudao-ui-admin-vue3/src/views/Error/500.vue

@@ -1,3 +1,7 @@
+<template>
+  <Error type="500" @error-click="errorClick" />
+</template>
+
 <script setup lang="ts">
 import { Error } from '@/components/Error'
 import { useRouter } from 'vue-router'
@@ -8,7 +12,3 @@ const errorClick = () => {
   push('/')
 }
 </script>
-
-<template>
-  <Error type="500" @error-click="errorClick" />
-</template>

+ 164 - 263
yudao-ui-admin-vue3/src/views/Home/Index.vue

@@ -1,3 +1,165 @@
+<template>
+  <div>
+    <el-card shadow="never">
+      <el-skeleton :loading="loading" animated>
+        <el-row :gutter="20" justify="space-between">
+          <el-col :xl="12" :lg="12" :md="12" :sm="24" :xs="24">
+            <div class="flex items-center">
+              <img :src="avatar" alt="" class="w-70px h-70px rounded-[50%] mr-20px" />
+              <div>
+                <div class="text-20px text-700">
+                  {{ t('workplace.welcome') }} {{ username }} {{ t('workplace.happyDay') }}
+                </div>
+                <div class="mt-10px text-14px text-gray-500">
+                  {{ t('workplace.toady') }},20℃ - 32℃!
+                </div>
+              </div>
+            </div>
+          </el-col>
+          <el-col :xl="12" :lg="12" :md="12" :sm="24" :xs="24">
+            <div class="flex h-70px items-center justify-end <sm:mt-10px">
+              <div class="px-8px text-right">
+                <div class="text-14px text-gray-400 mb-20px">{{ t('workplace.project') }}</div>
+                <CountTo
+                  class="text-20px"
+                  :start-val="0"
+                  :end-val="totalSate.project"
+                  :duration="2600"
+                />
+              </div>
+              <el-divider direction="vertical" />
+              <div class="px-8px text-right">
+                <div class="text-14px text-gray-400 mb-20px">{{ t('workplace.toDo') }}</div>
+                <CountTo
+                  class="text-20px"
+                  :start-val="0"
+                  :end-val="totalSate.todo"
+                  :duration="2600"
+                />
+              </div>
+              <el-divider direction="vertical" border-style="dashed" />
+              <div class="px-8px text-right">
+                <div class="text-14px text-gray-400 mb-20px">{{ t('workplace.access') }}</div>
+                <CountTo
+                  class="text-20px"
+                  :start-val="0"
+                  :end-val="totalSate.access"
+                  :duration="2600"
+                />
+              </div>
+            </div>
+          </el-col>
+        </el-row>
+      </el-skeleton>
+    </el-card>
+  </div>
+
+  <el-row class="mt-5px" :gutter="20" justify="space-between">
+    <el-col :xl="16" :lg="16" :md="24" :sm="24" :xs="24" class="mb-10px">
+      <el-card shadow="never">
+        <template #header>
+          <div class="flex justify-between h-3">
+            <span>{{ t('workplace.project') }}</span>
+            <el-link type="primary" :underline="false">{{ t('workplace.more') }}</el-link>
+          </div>
+        </template>
+        <el-skeleton :loading="loading" animated>
+          <el-row>
+            <el-col
+              v-for="(item, index) in projects"
+              :key="`card-${index}`"
+              :xl="8"
+              :lg="8"
+              :md="8"
+              :sm="24"
+              :xs="24"
+            >
+              <el-card shadow="hover">
+                <div class="flex items-center">
+                  <Icon :icon="item.icon" :size="25" class="mr-10px" />
+                  <span class="text-16px">{{ item.name }}</span>
+                </div>
+                <div class="mt-15px text-14px text-gray-400">{{ t(item.message) }}</div>
+                <div class="mt-20px text-12px text-gray-400 flex justify-between">
+                  <span>{{ item.personal }}</span>
+                  <span>{{ formatTime(item.time, 'yyyy-MM-dd') }}</span>
+                </div>
+              </el-card>
+            </el-col>
+          </el-row>
+        </el-skeleton>
+      </el-card>
+
+      <el-card shadow="never" class="mt-5px">
+        <el-skeleton :loading="loading" animated>
+          <el-row :gutter="20" justify="space-between">
+            <el-col :xl="10" :lg="10" :md="24" :sm="24" :xs="24">
+              <el-card shadow="hover" class="mb-10px">
+                <el-skeleton :loading="loading" animated>
+                  <Echart :options="pieOptionsData" :height="280" />
+                </el-skeleton>
+              </el-card>
+            </el-col>
+            <el-col :xl="14" :lg="14" :md="24" :sm="24" :xs="24">
+              <el-card shadow="hover" class="mb-10px">
+                <el-skeleton :loading="loading" animated>
+                  <Echart :options="barOptionsData" :height="280" />
+                </el-skeleton>
+              </el-card>
+            </el-col>
+          </el-row>
+        </el-skeleton>
+      </el-card>
+    </el-col>
+    <el-col :xl="8" :lg="8" :md="24" :sm="24" :xs="24" class="mb-10px">
+      <el-card shadow="never">
+        <template #header>
+          <div class="flex justify-between h-3">
+            <span>{{ t('workplace.shortcutOperation') }}</span>
+          </div>
+        </template>
+        <el-skeleton :loading="loading" animated>
+          <el-row>
+            <el-col v-for="item in shortcut" :key="`team-${item.name}`" :span="8" class="mb-10px">
+              <div class="flex items-center">
+                <Icon :icon="item.icon" class="mr-10px" />
+                <el-link type="default" :underline="false" :href="item.url">
+                  {{ item.name }}
+                </el-link>
+              </div>
+            </el-col>
+          </el-row>
+        </el-skeleton>
+      </el-card>
+      <el-card shadow="never" class="mt-10px">
+        <template #header>
+          <div class="flex justify-between h-3">
+            <span>{{ t('workplace.notice') }}</span>
+            <el-link type="primary" :underline="false">{{ t('workplace.more') }}</el-link>
+          </div>
+        </template>
+        <el-skeleton :loading="loading" animated>
+          <div v-for="(item, index) in notice" :key="`dynamics-${index}`">
+            <div class="flex items-center">
+              <img :src="avatar" alt="" class="w-35px h-35px rounded-[50%] mr-20px" />
+              <div>
+                <div class="text-14px">
+                  <Highlight :keys="item.keys.map((v) => t(v))">
+                    {{ item.type }} : {{ item.title }}
+                  </Highlight>
+                </div>
+                <div class="mt-15px text-12px text-gray-400">
+                  {{ formatTime(item.date, 'yyyy-MM-dd') }}
+                </div>
+              </div>
+            </div>
+            <el-divider />
+          </div>
+        </el-skeleton>
+      </el-card>
+    </el-col>
+  </el-row>
+</template>
 <script setup lang="ts">
 import { ElRow, ElCol, ElSkeleton, ElCard, ElDivider, ElLink } from 'element-plus'
 import { useI18n } from '@/hooks/web/useI18n'
@@ -6,12 +168,11 @@ import { CountTo } from '@/components/CountTo'
 import { formatTime } from '@/utils'
 import { Echart } from '@/components/Echart'
 import { EChartsOption } from 'echarts'
-import { radarOption } from './echarts-data'
 import { Highlight } from '@/components/Highlight'
 import type { WorkplaceTotal, Project, Notice, Shortcut } from './types'
 import { set } from 'lodash-es'
 import { useCache } from '@/hooks/web/useCache'
-import { pieOptions, barOptions, lineOptions } from './echarts-data'
+import { pieOptions, barOptions } from './echarts-data'
 
 const { t } = useI18n()
 const { wsCache } = useCache()
@@ -156,44 +317,6 @@ const getShortcut = async () => {
   shortcut = Object.assign(shortcut, data)
 }
 
-// 获取指数
-let radarOptionData = reactive<EChartsOption>(radarOption) as EChartsOption
-
-const getRadar = async () => {
-  const data = [
-    { name: 'workplace.quote', max: 65, personal: 42, team: 50 },
-    { name: 'workplace.contribution', max: 160, personal: 30, team: 140 },
-    { name: 'workplace.hot', max: 300, personal: 20, team: 28 },
-    { name: 'workplace.yield', max: 130, personal: 35, team: 35 },
-    { name: 'workplace.follow', max: 100, personal: 80, team: 90 }
-  ]
-  set(
-    radarOptionData,
-    'radar.indicator',
-    data.map((v) => {
-      return {
-        name: t(v.name),
-        max: v.max
-      }
-    })
-  )
-  set(radarOptionData, 'series', [
-    {
-      name: '指数',
-      type: 'radar',
-      data: [
-        {
-          value: data.map((v) => v.personal),
-          name: t('workplace.personal')
-        },
-        {
-          value: data.map((v) => v.team),
-          name: t('workplace.team')
-        }
-      ]
-    }
-  ])
-}
 // 用户来源
 const getUserAccessSource = async () => {
   const data = [
@@ -242,239 +365,17 @@ const getWeeklyUserActivity = async () => {
   ])
 }
 
-const lineOptionsData = reactive<EChartsOption>(lineOptions) as EChartsOption
-
-// 每月销售总额
-const getMonthlySales = async () => {
-  const data = [
-    { estimate: 100, actual: 120, name: 'analysis.january' },
-    { estimate: 120, actual: 82, name: 'analysis.february' },
-    { estimate: 161, actual: 91, name: 'analysis.march' },
-    { estimate: 134, actual: 154, name: 'analysis.april' },
-    { estimate: 105, actual: 162, name: 'analysis.may' },
-    { estimate: 160, actual: 140, name: 'analysis.june' },
-    { estimate: 165, actual: 145, name: 'analysis.july' },
-    { estimate: 114, actual: 250, name: 'analysis.august' },
-    { estimate: 163, actual: 134, name: 'analysis.september' },
-    { estimate: 185, actual: 56, name: 'analysis.october' },
-    { estimate: 118, actual: 99, name: 'analysis.november' },
-    { estimate: 123, actual: 123, name: 'analysis.december' }
-  ]
-  set(
-    lineOptionsData,
-    'xAxis.data',
-    data.map((v) => t(v.name))
-  )
-  set(lineOptionsData, 'series', [
-    {
-      name: t('analysis.estimate'),
-      smooth: true,
-      type: 'line',
-      data: data.map((v) => v.estimate),
-      animationDuration: 2800,
-      animationEasing: 'cubicInOut'
-    },
-    {
-      name: t('analysis.actual'),
-      smooth: true,
-      type: 'line',
-      itemStyle: {},
-      data: data.map((v) => v.actual),
-      animationDuration: 2800,
-      animationEasing: 'quadraticOut'
-    }
-  ])
-}
-
 const getAllApi = async () => {
   await Promise.all([
     getCount(),
     getProject(),
     getNotice(),
     getShortcut(),
-    getRadar(),
     getUserAccessSource(),
-    getWeeklyUserActivity(),
-    getMonthlySales()
+    getWeeklyUserActivity()
   ])
   loading.value = false
 }
 
 getAllApi()
 </script>
-
-<template>
-  <div>
-    <el-card shadow="never">
-      <el-skeleton :loading="loading" animated>
-        <el-row :gutter="20" justify="space-between">
-          <el-col :xl="12" :lg="12" :md="12" :sm="24" :xs="24">
-            <div class="flex items-center">
-              <img :src="avatar" alt="" class="w-70px h-70px rounded-[50%] mr-20px" />
-              <div>
-                <div class="text-20px text-700">
-                  {{ t('workplace.welcome') }} {{ username }} {{ t('workplace.happyDay') }}
-                </div>
-                <div class="mt-10px text-14px text-gray-500">
-                  {{ t('workplace.toady') }},20℃ - 32℃!
-                </div>
-              </div>
-            </div>
-          </el-col>
-          <el-col :xl="12" :lg="12" :md="12" :sm="24" :xs="24">
-            <div class="flex h-70px items-center justify-end <sm:mt-10px">
-              <div class="px-8px text-right">
-                <div class="text-14px text-gray-400 mb-20px">{{ t('workplace.project') }}</div>
-                <CountTo
-                  class="text-20px"
-                  :start-val="0"
-                  :end-val="totalSate.project"
-                  :duration="2600"
-                />
-              </div>
-              <el-divider direction="vertical" />
-              <div class="px-8px text-right">
-                <div class="text-14px text-gray-400 mb-20px">{{ t('workplace.toDo') }}</div>
-                <CountTo
-                  class="text-20px"
-                  :start-val="0"
-                  :end-val="totalSate.todo"
-                  :duration="2600"
-                />
-              </div>
-              <el-divider direction="vertical" border-style="dashed" />
-              <div class="px-8px text-right">
-                <div class="text-14px text-gray-400 mb-20px">{{ t('workplace.access') }}</div>
-                <CountTo
-                  class="text-20px"
-                  :start-val="0"
-                  :end-val="totalSate.access"
-                  :duration="2600"
-                />
-              </div>
-            </div>
-          </el-col>
-        </el-row>
-      </el-skeleton>
-    </el-card>
-  </div>
-
-  <el-row class="mt-10px" :gutter="20" justify="space-between">
-    <el-col :xl="16" :lg="16" :md="24" :sm="24" :xs="24" class="mb-20px">
-      <el-card shadow="never">
-        <template #header>
-          <div class="flex justify-between">
-            <span>{{ t('workplace.project') }}</span>
-            <el-link type="primary" :underline="false">{{ t('workplace.more') }}</el-link>
-          </div>
-        </template>
-        <el-skeleton :loading="loading" animated>
-          <el-row>
-            <el-col
-              v-for="(item, index) in projects"
-              :key="`card-${index}`"
-              :xl="8"
-              :lg="8"
-              :md="12"
-              :sm="24"
-              :xs="24"
-            >
-              <el-card shadow="hover">
-                <div class="flex items-center">
-                  <Icon :icon="item.icon" :size="25" class="mr-10px" />
-                  <span class="text-16px">{{ item.name }}</span>
-                </div>
-                <div class="mt-15px text-14px text-gray-400">{{ t(item.message) }}</div>
-                <div class="mt-20px text-12px text-gray-400 flex justify-between">
-                  <span>{{ item.personal }}</span>
-                  <span>{{ formatTime(item.time, 'yyyy-MM-dd') }}</span>
-                </div>
-              </el-card>
-            </el-col>
-          </el-row>
-        </el-skeleton>
-      </el-card>
-
-      <el-card shadow="never" class="mt-10px">
-        <el-skeleton :loading="loading" animated>
-          <el-row :gutter="20" justify="space-between">
-            <el-col :xl="10" :lg="10" :md="24" :sm="24" :xs="24">
-              <el-card shadow="hover" class="mb-20px">
-                <el-skeleton :loading="loading" animated>
-                  <Echart :options="pieOptionsData" :height="300" />
-                </el-skeleton>
-              </el-card>
-            </el-col>
-            <el-col :xl="14" :lg="14" :md="24" :sm="24" :xs="24">
-              <el-card shadow="hover" class="mb-20px">
-                <el-skeleton :loading="loading" animated>
-                  <Echart :options="barOptionsData" :height="300" />
-                </el-skeleton>
-              </el-card>
-            </el-col>
-            <el-col :span="24">
-              <el-card shadow="hover" class="mb-20px">
-                <el-skeleton :loading="loading" animated :rows="4">
-                  <Echart :options="lineOptionsData" :height="350" />
-                </el-skeleton>
-              </el-card>
-            </el-col>
-          </el-row>
-        </el-skeleton>
-      </el-card>
-    </el-col>
-    <el-col :xl="8" :lg="8" :md="24" :sm="24" :xs="24" class="mb-20px">
-      <el-card shadow="never">
-        <template #header>
-          <span>{{ t('workplace.shortcutOperation') }}</span>
-        </template>
-        <el-skeleton :loading="loading" animated>
-          <el-row>
-            <el-col v-for="item in shortcut" :key="`team-${item.name}`" :span="8" class="mb-20px">
-              <div class="flex items-center">
-                <Icon :icon="item.icon" class="mr-10px" />
-                <el-link type="default" :underline="false" :href="item.url">
-                  {{ item.name }}
-                </el-link>
-              </div>
-            </el-col>
-          </el-row>
-        </el-skeleton>
-      </el-card>
-      <el-card shadow="never" class="mt-10px">
-        <template #header>
-          <div class="flex justify-between">
-            <span>{{ t('workplace.notice') }}</span>
-            <el-link type="primary" :underline="false">{{ t('workplace.more') }}</el-link>
-          </div>
-        </template>
-        <el-skeleton :loading="loading" animated>
-          <div v-for="(item, index) in notice" :key="`dynamics-${index}`">
-            <div class="flex items-center">
-              <img :src="avatar" alt="" class="w-35px h-35px rounded-[50%] mr-20px" />
-              <div>
-                <div class="text-14px">
-                  <Highlight :keys="item.keys.map((v) => t(v))">
-                    {{ item.type }} : {{ item.title }}
-                  </Highlight>
-                </div>
-                <div class="mt-15px text-12px text-gray-400">
-                  {{ formatTime(item.date, 'yyyy-MM-dd') }}
-                </div>
-              </div>
-            </div>
-            <el-divider />
-          </div>
-        </el-skeleton>
-      </el-card>
-      <el-card shadow="never" class="mt-10px">
-        <template #header>
-          <span>{{ t('workplace.index') }}</span>
-        </template>
-        <el-skeleton :loading="loading" animated>
-          <Echart :options="radarOptionData" :height="400" />
-        </el-skeleton>
-      </el-card>
-    </el-col>
-  </el-row>
-</template>

+ 130 - 130
yudao-ui-admin-vue3/src/views/Home/Index2.vue

@@ -1,133 +1,3 @@
-<script setup lang="ts">
-import { ref, reactive } from 'vue'
-import { set } from 'lodash-es'
-import { EChartsOption } from 'echarts'
-import { Echart } from '@/components/Echart'
-import { useI18n } from '@/hooks/web/useI18n'
-import { CountTo } from '@/components/CountTo'
-import type { AnalysisTotalTypes } from './types'
-import { useDesign } from '@/hooks/web/useDesign'
-import { ElRow, ElCol, ElCard, ElSkeleton } from 'element-plus'
-import { pieOptions, barOptions, lineOptions } from './echarts-data'
-
-const { t } = useI18n()
-const loading = ref(true)
-const { getPrefixCls } = useDesign()
-const prefixCls = getPrefixCls('panel')
-const pieOptionsData = reactive<EChartsOption>(pieOptions) as EChartsOption
-
-let totalState = reactive<AnalysisTotalTypes>({
-  users: 0,
-  messages: 0,
-  moneys: 0,
-  shoppings: 0
-})
-
-const getCount = async () => {
-  const data = {
-    users: 102400,
-    messages: 81212,
-    moneys: 9280,
-    shoppings: 13600
-  }
-  totalState = Object.assign(totalState, data)
-}
-
-// 用户来源
-const getUserAccessSource = async () => {
-  const data = [
-    { value: 335, name: 'analysis.directAccess' },
-    { value: 310, name: 'analysis.mailMarketing' },
-    { value: 234, name: 'analysis.allianceAdvertising' },
-    { value: 135, name: 'analysis.videoAdvertising' },
-    { value: 1548, name: 'analysis.searchEngines' }
-  ]
-  set(
-    pieOptionsData,
-    'legend.data',
-    data.map((v) => t(v.name))
-  )
-  set(pieOptionsData, 'series.data', data)
-}
-const barOptionsData = reactive<EChartsOption>(barOptions) as EChartsOption
-
-// 周活跃量
-const getWeeklyUserActivity = async () => {
-  const data = [
-    { value: 13253, name: 'analysis.monday' },
-    { value: 34235, name: 'analysis.tuesday' },
-    { value: 26321, name: 'analysis.wednesday' },
-    { value: 12340, name: 'analysis.thursday' },
-    { value: 24643, name: 'analysis.friday' },
-    { value: 1322, name: 'analysis.saturday' },
-    { value: 1324, name: 'analysis.sunday' }
-  ]
-  set(
-    barOptionsData,
-    'xAxis.data',
-    data.map((v) => t(v.name))
-  )
-  set(barOptionsData, 'series', [
-    {
-      name: t('analysis.activeQuantity'),
-      data: data.map((v) => v.value),
-      type: 'bar'
-    }
-  ])
-}
-
-const lineOptionsData = reactive<EChartsOption>(lineOptions) as EChartsOption
-
-// 每月销售总额
-const getMonthlySales = async () => {
-  const data = [
-    { estimate: 100, actual: 120, name: 'analysis.january' },
-    { estimate: 120, actual: 82, name: 'analysis.february' },
-    { estimate: 161, actual: 91, name: 'analysis.march' },
-    { estimate: 134, actual: 154, name: 'analysis.april' },
-    { estimate: 105, actual: 162, name: 'analysis.may' },
-    { estimate: 160, actual: 140, name: 'analysis.june' },
-    { estimate: 165, actual: 145, name: 'analysis.july' },
-    { estimate: 114, actual: 250, name: 'analysis.august' },
-    { estimate: 163, actual: 134, name: 'analysis.september' },
-    { estimate: 185, actual: 56, name: 'analysis.october' },
-    { estimate: 118, actual: 99, name: 'analysis.november' },
-    { estimate: 123, actual: 123, name: 'analysis.december' }
-  ]
-  set(
-    lineOptionsData,
-    'xAxis.data',
-    data.map((v) => t(v.name))
-  )
-  set(lineOptionsData, 'series', [
-    {
-      name: t('analysis.estimate'),
-      smooth: true,
-      type: 'line',
-      data: data.map((v) => v.estimate),
-      animationDuration: 2800,
-      animationEasing: 'cubicInOut'
-    },
-    {
-      name: t('analysis.actual'),
-      smooth: true,
-      type: 'line',
-      itemStyle: {},
-      data: data.map((v) => v.actual),
-      animationDuration: 2800,
-      animationEasing: 'quadraticOut'
-    }
-  ])
-}
-
-const getAllApi = async () => {
-  await Promise.all([getCount(), getUserAccessSource(), getWeeklyUserActivity(), getMonthlySales()])
-  loading.value = false
-}
-
-getAllApi()
-</script>
-
 <template>
   <el-row :gutter="20" justify="space-between" :class="prefixCls">
     <el-col :xl="6" :lg="6" :md="12" :sm="12" :xs="24">
@@ -270,6 +140,136 @@ getAllApi()
     </el-col>
   </el-row>
 </template>
+<script setup lang="ts">
+import { ref, reactive } from 'vue'
+import { set } from 'lodash-es'
+import { EChartsOption } from 'echarts'
+import { Echart } from '@/components/Echart'
+import { useI18n } from '@/hooks/web/useI18n'
+import { CountTo } from '@/components/CountTo'
+import type { AnalysisTotalTypes } from './types'
+import { useDesign } from '@/hooks/web/useDesign'
+import { ElRow, ElCol, ElCard, ElSkeleton } from 'element-plus'
+import { pieOptions, barOptions, lineOptions } from './echarts-data'
+
+const { t } = useI18n()
+const loading = ref(true)
+const { getPrefixCls } = useDesign()
+const prefixCls = getPrefixCls('panel')
+const pieOptionsData = reactive<EChartsOption>(pieOptions) as EChartsOption
+
+let totalState = reactive<AnalysisTotalTypes>({
+  users: 0,
+  messages: 0,
+  moneys: 0,
+  shoppings: 0
+})
+
+const getCount = async () => {
+  const data = {
+    users: 102400,
+    messages: 81212,
+    moneys: 9280,
+    shoppings: 13600
+  }
+  totalState = Object.assign(totalState, data)
+}
+
+// 用户来源
+const getUserAccessSource = async () => {
+  const data = [
+    { value: 335, name: 'analysis.directAccess' },
+    { value: 310, name: 'analysis.mailMarketing' },
+    { value: 234, name: 'analysis.allianceAdvertising' },
+    { value: 135, name: 'analysis.videoAdvertising' },
+    { value: 1548, name: 'analysis.searchEngines' }
+  ]
+  set(
+    pieOptionsData,
+    'legend.data',
+    data.map((v) => t(v.name))
+  )
+  set(pieOptionsData, 'series.data', data)
+}
+const barOptionsData = reactive<EChartsOption>(barOptions) as EChartsOption
+
+// 周活跃量
+const getWeeklyUserActivity = async () => {
+  const data = [
+    { value: 13253, name: 'analysis.monday' },
+    { value: 34235, name: 'analysis.tuesday' },
+    { value: 26321, name: 'analysis.wednesday' },
+    { value: 12340, name: 'analysis.thursday' },
+    { value: 24643, name: 'analysis.friday' },
+    { value: 1322, name: 'analysis.saturday' },
+    { value: 1324, name: 'analysis.sunday' }
+  ]
+  set(
+    barOptionsData,
+    'xAxis.data',
+    data.map((v) => t(v.name))
+  )
+  set(barOptionsData, 'series', [
+    {
+      name: t('analysis.activeQuantity'),
+      data: data.map((v) => v.value),
+      type: 'bar'
+    }
+  ])
+}
+
+const lineOptionsData = reactive<EChartsOption>(lineOptions) as EChartsOption
+
+// 每月销售总额
+const getMonthlySales = async () => {
+  const data = [
+    { estimate: 100, actual: 120, name: 'analysis.january' },
+    { estimate: 120, actual: 82, name: 'analysis.february' },
+    { estimate: 161, actual: 91, name: 'analysis.march' },
+    { estimate: 134, actual: 154, name: 'analysis.april' },
+    { estimate: 105, actual: 162, name: 'analysis.may' },
+    { estimate: 160, actual: 140, name: 'analysis.june' },
+    { estimate: 165, actual: 145, name: 'analysis.july' },
+    { estimate: 114, actual: 250, name: 'analysis.august' },
+    { estimate: 163, actual: 134, name: 'analysis.september' },
+    { estimate: 185, actual: 56, name: 'analysis.october' },
+    { estimate: 118, actual: 99, name: 'analysis.november' },
+    { estimate: 123, actual: 123, name: 'analysis.december' }
+  ]
+  set(
+    lineOptionsData,
+    'xAxis.data',
+    data.map((v) => t(v.name))
+  )
+  set(lineOptionsData, 'series', [
+    {
+      name: t('analysis.estimate'),
+      smooth: true,
+      type: 'line',
+      data: data.map((v) => v.estimate),
+      animationDuration: 2800,
+      animationEasing: 'cubicInOut'
+    },
+    {
+      name: t('analysis.actual'),
+      smooth: true,
+      type: 'line',
+      itemStyle: {},
+      data: data.map((v) => v.actual),
+      animationDuration: 2800,
+      animationEasing: 'quadraticOut'
+    }
+  ])
+}
+
+const getAllApi = async () => {
+  await Promise.all([getCount(), getUserAccessSource(), getWeeklyUserActivity(), getMonthlySales()])
+  loading.value = false
+}
+
+getAllApi()
+</script>
+
 <style lang="less" scoped>
 @prefix-cls: ~'@{namespace}-panel';
 

+ 17 - 18
yudao-ui-admin-vue3/src/views/Login/Login.vue

@@ -1,21 +1,3 @@
-<script setup lang="ts">
-import { LoginForm, MobileForm, RegisterForm, QrCodeForm } from './components'
-import { ThemeSwitch } from '@/components/ThemeSwitch'
-import { LocaleDropdown } from '@/components/LocaleDropdown'
-import { useI18n } from '@/hooks/web/useI18n'
-import { underlineToHump } from '@/utils'
-import { useAppStore } from '@/store/modules/app'
-import { useDesign } from '@/hooks/web/useDesign'
-
-const { t } = useI18n()
-
-const { getPrefixCls } = useDesign()
-
-const prefixCls = getPrefixCls('login')
-
-const appStore = useAppStore()
-</script>
-
 <template>
   <div
     :class="prefixCls"
@@ -76,6 +58,23 @@ const appStore = useAppStore()
     </div>
   </div>
 </template>
+<script setup lang="ts">
+import { LoginForm, MobileForm, RegisterForm, QrCodeForm } from './components'
+import { ThemeSwitch } from '@/components/ThemeSwitch'
+import { LocaleDropdown } from '@/components/LocaleDropdown'
+import { useI18n } from '@/hooks/web/useI18n'
+import { underlineToHump } from '@/utils'
+import { useAppStore } from '@/store/modules/app'
+import { useDesign } from '@/hooks/web/useDesign'
+
+const { t } = useI18n()
+
+const { getPrefixCls } = useDesign()
+
+const prefixCls = getPrefixCls('login')
+
+const appStore = useAppStore()
+</script>
 
 <style lang="less" scoped>
 @prefix-cls: ~'@{namespace}-login';

+ 139 - 138
yudao-ui-admin-vue3/src/views/Login/components/LoginForm.vue

@@ -1,3 +1,141 @@
+<template>
+  <el-form
+    :model="loginData.loginForm"
+    :rules="LoginRules"
+    label-position="top"
+    class="login-form"
+    label-width="120px"
+    size="large"
+    v-show="getShow"
+    ref="formLogin"
+  >
+    <el-row style="maring-left: -10px; maring-right: -10px">
+      <el-col :span="24" style="padding-left: 10px; padding-right: 10px">
+        <el-form-item>
+          <LoginFormTitle style="width: 100%" />
+        </el-form-item>
+      </el-col>
+      <el-col :span="24" style="padding-left: 10px; padding-right: 10px">
+        <el-form-item prop="tenantName">
+          <el-input
+            type="text"
+            v-model="loginData.loginForm.tenantName"
+            :placeholder="t('login.tenantNamePlaceholder')"
+            :prefix-icon="iconHouse"
+          />
+        </el-form-item>
+      </el-col>
+      <el-col :span="24" style="padding-left: 10px; padding-right: 10px">
+        <el-form-item prop="username">
+          <el-input
+            v-model="loginData.loginForm.username"
+            :placeholder="t('login.usernamePlaceholder')"
+            :prefix-icon="iconAvatar"
+          />
+        </el-form-item>
+      </el-col>
+      <el-col :span="24" style="padding-left: 10px; padding-right: 10px">
+        <el-form-item prop="password">
+          <el-input
+            v-model="loginData.loginForm.password"
+            type="password"
+            :placeholder="t('login.passwordPlaceholder')"
+            show-password
+            @keyup.enter="getCode()"
+            :prefix-icon="iconLock"
+          />
+        </el-form-item>
+      </el-col>
+      <el-col
+        :span="24"
+        style="padding-left: 10px; padding-right: 10px; margin-top: -20px; margin-bottom: -20px"
+      >
+        <el-form-item>
+          <el-row justify="space-between" style="width: 100%">
+            <el-col :span="6">
+              <el-checkbox v-model="loginData.loginForm.rememberMe">
+                {{ t('login.remember') }}
+              </el-checkbox>
+            </el-col>
+            <el-col :span="12" :offset="6">
+              <el-link type="primary" style="float: right">{{ t('login.forgetPassword') }}</el-link>
+            </el-col>
+          </el-row>
+        </el-form-item>
+      </el-col>
+      <el-col :span="24" style="padding-left: 10px; padding-right: 10px">
+        <el-form-item>
+          <el-button :loading="loginLoading" type="primary" class="w-[100%]" @click="getCode()">
+            {{ t('login.login') }}
+          </el-button>
+        </el-form-item>
+      </el-col>
+      <Verify
+        ref="verify"
+        mode="pop"
+        :captchaType="captchaType"
+        :imgSize="{ width: '400px', height: '200px' }"
+        @success="handleLogin"
+      />
+      <el-col :span="24" style="padding-left: 10px; padding-right: 10px">
+        <el-form-item>
+          <el-row justify="space-between" style="width: 100%" :gutter="5">
+            <el-col :span="8">
+              <el-button class="w-[100%]" @click="setLoginState(LoginStateEnum.MOBILE)">
+                {{ t('login.btnMobile') }}
+              </el-button>
+            </el-col>
+            <el-col :span="8">
+              <el-button class="w-[100%]" @click="setLoginState(LoginStateEnum.QR_CODE)">
+                {{ t('login.btnQRCode') }}
+              </el-button>
+            </el-col>
+            <el-col :span="8">
+              <el-button class="w-[100%]" @click="setLoginState(LoginStateEnum.REGISTER)">
+                {{ t('login.btnRegister') }}
+              </el-button>
+            </el-col>
+          </el-row>
+        </el-form-item>
+      </el-col>
+      <el-divider content-position="center">{{ t('login.otherLogin') }}</el-divider>
+      <el-col :span="24" style="padding-left: 10px; padding-right: 10px">
+        <el-form-item>
+          <div class="flex justify-between w-[100%]">
+            <Icon
+              icon="ant-design:github-filled"
+              :size="iconSize"
+              class="cursor-pointer anticon"
+              :color="iconColor"
+              @click="doSocialLogin('github')"
+            />
+            <Icon
+              icon="ant-design:wechat-filled"
+              :size="iconSize"
+              class="cursor-pointer anticon"
+              :color="iconColor"
+              @click="doSocialLogin('wechat')"
+            />
+            <Icon
+              icon="ant-design:alipay-circle-filled"
+              :size="iconSize"
+              :color="iconColor"
+              class="cursor-pointer anticon"
+              @click="doSocialLogin('alipay')"
+            />
+            <Icon
+              icon="ant-design:dingtalk-circle-filled"
+              :size="iconSize"
+              :color="iconColor"
+              class="cursor-pointer anticon"
+              @click="doSocialLogin('dingtalk')"
+            />
+          </div>
+        </el-form-item>
+      </el-col>
+    </el-row>
+  </el-form>
+</template>
 <script setup lang="ts">
 import { useIcon } from '@/hooks/web/useIcon'
 import LoginFormTitle from './LoginFormTitle.vue'
@@ -153,144 +291,7 @@ onMounted(() => {
   getCookie()
 })
 </script>
-<template>
-  <el-form
-    :model="loginData.loginForm"
-    :rules="LoginRules"
-    label-position="top"
-    class="login-form"
-    label-width="120px"
-    size="large"
-    v-show="getShow"
-    ref="formLogin"
-  >
-    <el-row style="maring-left: -10px; maring-right: -10px">
-      <el-col :span="24" style="padding-left: 10px; padding-right: 10px">
-        <el-form-item>
-          <LoginFormTitle style="width: 100%" />
-        </el-form-item>
-      </el-col>
-      <el-col :span="24" style="padding-left: 10px; padding-right: 10px">
-        <el-form-item prop="tenantName">
-          <el-input
-            type="text"
-            v-model="loginData.loginForm.tenantName"
-            :placeholder="t('login.tenantNamePlaceholder')"
-            :prefix-icon="iconHouse"
-          />
-        </el-form-item>
-      </el-col>
-      <el-col :span="24" style="padding-left: 10px; padding-right: 10px">
-        <el-form-item prop="username">
-          <el-input
-            v-model="loginData.loginForm.username"
-            :placeholder="t('login.usernamePlaceholder')"
-            :prefix-icon="iconAvatar"
-          />
-        </el-form-item>
-      </el-col>
-      <el-col :span="24" style="padding-left: 10px; padding-right: 10px">
-        <el-form-item prop="password">
-          <el-input
-            v-model="loginData.loginForm.password"
-            type="password"
-            :placeholder="t('login.passwordPlaceholder')"
-            show-password
-            @keyup.enter="getCode()"
-            :prefix-icon="iconLock"
-          />
-        </el-form-item>
-      </el-col>
-      <el-col
-        :span="24"
-        style="padding-left: 10px; padding-right: 10px; margin-top: -20px; margin-bottom: -20px"
-      >
-        <el-form-item>
-          <el-row justify="space-between" style="width: 100%">
-            <el-col :span="6">
-              <el-checkbox v-model="loginData.loginForm.rememberMe">
-                {{ t('login.remember') }}
-              </el-checkbox>
-            </el-col>
-            <el-col :span="12" :offset="6">
-              <el-link type="primary" style="float: right">{{ t('login.forgetPassword') }}</el-link>
-            </el-col>
-          </el-row>
-        </el-form-item>
-      </el-col>
-      <el-col :span="24" style="padding-left: 10px; padding-right: 10px">
-        <el-form-item>
-          <el-button :loading="loginLoading" type="primary" class="w-[100%]" @click="getCode()">
-            {{ t('login.login') }}
-          </el-button>
-        </el-form-item>
-      </el-col>
-      <Verify
-        ref="verify"
-        mode="pop"
-        :captchaType="captchaType"
-        :imgSize="{ width: '400px', height: '200px' }"
-        @success="handleLogin"
-      />
-      <el-col :span="24" style="padding-left: 10px; padding-right: 10px">
-        <el-form-item>
-          <el-row justify="space-between" style="width: 100%" :gutter="5">
-            <el-col :span="8">
-              <el-button class="w-[100%]" @click="setLoginState(LoginStateEnum.MOBILE)">
-                {{ t('login.btnMobile') }}
-              </el-button>
-            </el-col>
-            <el-col :span="8">
-              <el-button class="w-[100%]" @click="setLoginState(LoginStateEnum.QR_CODE)">
-                {{ t('login.btnQRCode') }}
-              </el-button>
-            </el-col>
-            <el-col :span="8">
-              <el-button class="w-[100%]" @click="setLoginState(LoginStateEnum.REGISTER)">
-                {{ t('login.btnRegister') }}
-              </el-button>
-            </el-col>
-          </el-row>
-        </el-form-item>
-      </el-col>
-      <el-divider content-position="center">{{ t('login.otherLogin') }}</el-divider>
-      <el-col :span="24" style="padding-left: 10px; padding-right: 10px">
-        <el-form-item>
-          <div class="flex justify-between w-[100%]">
-            <Icon
-              icon="ant-design:github-filled"
-              :size="iconSize"
-              class="cursor-pointer anticon"
-              :color="iconColor"
-              @click="doSocialLogin('github')"
-            />
-            <Icon
-              icon="ant-design:wechat-filled"
-              :size="iconSize"
-              class="cursor-pointer anticon"
-              :color="iconColor"
-              @click="doSocialLogin('wechat')"
-            />
-            <Icon
-              icon="ant-design:alipay-circle-filled"
-              :size="iconSize"
-              :color="iconColor"
-              class="cursor-pointer anticon"
-              @click="doSocialLogin('alipay')"
-            />
-            <Icon
-              icon="ant-design:dingtalk-circle-filled"
-              :size="iconSize"
-              :color="iconColor"
-              class="cursor-pointer anticon"
-              @click="doSocialLogin('dingtalk')"
-            />
-          </div>
-        </el-form-item>
-      </el-col>
-    </el-row>
-  </el-form>
-</template>
+
 <style lang="less" scoped>
 :deep(.anticon) {
   &:hover {

+ 5 - 5
yudao-ui-admin-vue3/src/views/Login/components/LoginFormTitle.vue

@@ -1,3 +1,8 @@
+<template>
+  <h2 class="mb-3 text-2xl font-bold text-center xl:text-3xl enter-x xl:text-center">
+    {{ getFormTitle }}
+  </h2>
+</template>
 <script setup lang="ts">
 import { computed, unref } from 'vue'
 import { useI18n } from '@/hooks/web/useI18n'
@@ -18,8 +23,3 @@ const getFormTitle = computed(() => {
   return titleObj[unref(getLoginState)]
 })
 </script>
-<template>
-  <h2 class="mb-3 text-2xl font-bold text-center xl:text-3xl enter-x xl:text-center">
-    {{ getFormTitle }}
-  </h2>
-</template>

+ 87 - 86
yudao-ui-admin-vue3/src/views/Login/components/MobileForm.vue

@@ -1,3 +1,89 @@
+<template>
+  <el-form
+    :model="loginData.loginForm"
+    :rules="rules"
+    label-position="top"
+    class="login-form"
+    label-width="120px"
+    size="large"
+    v-show="getShow"
+    ref="formSmsLogin"
+  >
+    <el-row style="margin-left: -10px; margin-right: -10px">
+      <!-- 租户名 -->
+      <el-col :span="24" style="padding-left: 10px; padding-right: 10px">
+        <el-form-item>
+          <LoginFormTitle style="width: 100%" />
+        </el-form-item>
+      </el-col>
+      <el-col :span="24" style="padding-left: 10px; padding-right: 10px">
+        <el-form-item prop="tenantName">
+          <el-input
+            type="text"
+            v-model="loginData.loginForm.tenantName"
+            :placeholder="t('login.tenantNamePlaceholder')"
+            :prefix-icon="iconHouse"
+          />
+        </el-form-item>
+      </el-col>
+      <!-- 手机号 -->
+      <el-col :span="24" style="padding-left: 10px; padding-right: 10px">
+        <el-form-item prop="mobileNumber">
+          <el-input
+            v-model="loginData.loginForm.mobileNumber"
+            :placeholder="t('login.mobileNumberPlaceholder')"
+            :prefix-icon="iconCellphone"
+          />
+        </el-form-item>
+      </el-col>
+      <!-- 验证码 -->
+      <el-col :span="24" style="padding-left: 10px; padding-right: 10px">
+        <el-form-item prop="code">
+          <el-row justify="space-between" style="width: 100%" :gutter="5">
+            <el-col :span="24">
+              <el-input
+                v-model="loginData.loginForm.code"
+                :placeholder="t('login.codePlaceholder')"
+                :prefix-icon="iconCircleCheck"
+              >
+                <!-- <el-button class="w-[100%]"> -->
+                <template #append>
+                  <span
+                    v-if="mobileCodeTimer <= 0"
+                    @click="getSmsCode"
+                    class="getMobileCode"
+                    style="cursor: pointer"
+                  >
+                    {{ t('login.getSmsCode') }}
+                  </span>
+                  <span v-if="mobileCodeTimer > 0" class="getMobileCode" style="cursor: pointer">
+                    {{ mobileCodeTimer }}秒后可重新获取
+                  </span>
+                </template>
+              </el-input>
+              <!-- </el-button> -->
+            </el-col>
+          </el-row>
+        </el-form-item>
+      </el-col>
+      <!-- 登录按钮 / 返回按钮 -->
+      <el-col :span="24" style="padding-left: 10px; padding-right: 10px">
+        <el-form-item>
+          <el-button :loading="loginLoading" type="primary" class="w-[100%]" @click="signIn">
+            {{ t('login.login') }}
+          </el-button>
+        </el-form-item>
+      </el-col>
+      <el-col :span="24" style="padding-left: 10px; padding-right: 10px">
+        <el-form-item>
+          <el-button :loading="loginLoading" class="w-[100%]" @click="handleBackLogin">
+            {{ t('login.backLogin') }}
+          </el-button>
+        </el-form-item>
+      </el-col>
+    </el-row>
+  </el-form>
+</template>
 <script setup lang="ts">
 import { useIcon } from '@/hooks/web/useIcon'
 import { reactive, ref, unref, watch, computed } from 'vue'
@@ -111,92 +197,7 @@ const signIn = async () => {
     })
 }
 </script>
-<template>
-  <el-form
-    :model="loginData.loginForm"
-    :rules="rules"
-    label-position="top"
-    class="login-form"
-    label-width="120px"
-    size="large"
-    v-show="getShow"
-    ref="formSmsLogin"
-  >
-    <el-row style="margin-left: -10px; margin-right: -10px">
-      <!-- 租户名 -->
-      <el-col :span="24" style="padding-left: 10px; padding-right: 10px">
-        <el-form-item>
-          <LoginFormTitle style="width: 100%" />
-        </el-form-item>
-      </el-col>
-      <el-col :span="24" style="padding-left: 10px; padding-right: 10px">
-        <el-form-item prop="tenantName">
-          <el-input
-            type="text"
-            v-model="loginData.loginForm.tenantName"
-            :placeholder="t('login.tenantNamePlaceholder')"
-            :prefix-icon="iconHouse"
-          />
-        </el-form-item>
-      </el-col>
-      <!-- 手机号 -->
-      <el-col :span="24" style="padding-left: 10px; padding-right: 10px">
-        <el-form-item prop="mobileNumber">
-          <el-input
-            v-model="loginData.loginForm.mobileNumber"
-            :placeholder="t('login.mobileNumberPlaceholder')"
-            :prefix-icon="iconCellphone"
-          />
-        </el-form-item>
-      </el-col>
-      <!-- 验证码 -->
-      <el-col :span="24" style="padding-left: 10px; padding-right: 10px">
-        <el-form-item prop="code">
-          <el-row justify="space-between" style="width: 100%" :gutter="5">
-            <el-col :span="24">
-              <el-input
-                v-model="loginData.loginForm.code"
-                :placeholder="t('login.codePlaceholder')"
-                :prefix-icon="iconCircleCheck"
-              >
-                <!-- <el-button class="w-[100%]"> -->
-                <template #append>
-                  <span
-                    v-if="mobileCodeTimer <= 0"
-                    @click="getSmsCode"
-                    class="getMobileCode"
-                    style="cursor: pointer"
-                  >
-                    {{ t('login.getSmsCode') }}
-                  </span>
-                  <span v-if="mobileCodeTimer > 0" class="getMobileCode" style="cursor: pointer">
-                    {{ mobileCodeTimer }}秒后可重新获取
-                  </span>
-                </template>
-              </el-input>
-              <!-- </el-button> -->
-            </el-col>
-          </el-row>
-        </el-form-item>
-      </el-col>
-      <!-- 登录按钮 / 返回按钮 -->
-      <el-col :span="24" style="padding-left: 10px; padding-right: 10px">
-        <el-form-item>
-          <el-button :loading="loginLoading" type="primary" class="w-[100%]" @click="signIn">
-            {{ t('login.login') }}
-          </el-button>
-        </el-form-item>
-      </el-col>
-      <el-col :span="24" style="padding-left: 10px; padding-right: 10px">
-        <el-form-item>
-          <el-button :loading="loginLoading" class="w-[100%]" @click="handleBackLogin">
-            {{ t('login.backLogin') }}
-          </el-button>
-        </el-form-item>
-      </el-col>
-    </el-row>
-  </el-form>
-</template>
+
 <style lang="less" scoped>
 :deep(.anticon) {
   &:hover {

+ 13 - 14
yudao-ui-admin-vue3/src/views/Login/components/QrCodeForm.vue

@@ -1,17 +1,3 @@
-<script setup lang="ts">
-import { computed, unref } from 'vue'
-import { ElRow, ElCol, ElCard, ElDivider } from 'element-plus'
-import { useI18n } from '@/hooks/web/useI18n'
-import { useLoginState, LoginStateEnum } from './useLogin'
-import LoginFormTitle from './LoginFormTitle.vue'
-import { Qrcode } from '@/components/Qrcode'
-import logoImg from '@/assets/imgs/logo.png'
-
-const { t } = useI18n()
-const { handleBackLogin, getLoginState } = useLoginState()
-const getShow = computed(() => unref(getLoginState) === LoginStateEnum.QR_CODE)
-</script>
-
 <template>
   <el-row v-show="getShow" style="maring-left: -10px; maring-right: -10px">
     <el-col :span="24" style="padding-left: 10px; padding-right: 10px">
@@ -32,3 +18,16 @@ const getShow = computed(() => unref(getLoginState) === LoginStateEnum.QR_CODE)
     </el-col>
   </el-row>
 </template>
+<script setup lang="ts">
+import { computed, unref } from 'vue'
+import { ElRow, ElCol, ElCard, ElDivider } from 'element-plus'
+import { useI18n } from '@/hooks/web/useI18n'
+import { useLoginState, LoginStateEnum } from './useLogin'
+import LoginFormTitle from './LoginFormTitle.vue'
+import { Qrcode } from '@/components/Qrcode'
+import logoImg from '@/assets/imgs/logo.png'
+
+const { t } = useI18n()
+const { handleBackLogin, getLoginState } = useLoginState()
+const getShow = computed(() => unref(getLoginState) === LoginStateEnum.QR_CODE)
+</script>

+ 36 - 36
yudao-ui-admin-vue3/src/views/Login/components/RegisterForm.vue

@@ -1,3 +1,39 @@
+<template>
+  <Form
+    :schema="schema"
+    :rules="rules"
+    label-position="top"
+    hide-required-asterisk
+    size="large"
+    v-show="getShow"
+    class="dark:(border-1 border-[var(--el-border-color)] border-solid)"
+    @register="register"
+  >
+    <template #title>
+      <LoginFormTitle style="width: 100%" />
+    </template>
+
+    <template #code="form">
+      <div class="w-[100%] flex">
+        <el-input v-model="form['code']" :placeholder="t('login.codePlaceholder')" />
+      </div>
+    </template>
+
+    <template #register>
+      <div class="w-[100%]">
+        <el-button type="primary" class="w-[100%]" :loading="loading" @click="loginRegister">
+          {{ t('login.register') }}
+        </el-button>
+      </div>
+      <div class="w-[100%] mt-15px">
+        <el-button class="w-[100%]" @click="handleBackLogin">
+          {{ t('login.hasUser') }}
+        </el-button>
+      </div>
+    </template>
+  </Form>
+</template>
+
 <script setup lang="ts">
 import { Form } from '@/components/Form'
 import { computed, reactive, ref, unref } from 'vue'
@@ -104,39 +140,3 @@ const loginRegister = async () => {
   })
 }
 </script>
-
-<template>
-  <Form
-    :schema="schema"
-    :rules="rules"
-    label-position="top"
-    hide-required-asterisk
-    size="large"
-    v-show="getShow"
-    class="dark:(border-1 border-[var(--el-border-color)] border-solid)"
-    @register="register"
-  >
-    <template #title>
-      <LoginFormTitle style="width: 100%" />
-    </template>
-
-    <template #code="form">
-      <div class="w-[100%] flex">
-        <el-input v-model="form['code']" :placeholder="t('login.codePlaceholder')" />
-      </div>
-    </template>
-
-    <template #register>
-      <div class="w-[100%]">
-        <el-button type="primary" class="w-[100%]" :loading="loading" @click="loginRegister">
-          {{ t('login.register') }}
-        </el-button>
-      </div>
-      <div class="w-[100%] mt-15px">
-        <el-button class="w-[100%]" @click="handleBackLogin">
-          {{ t('login.hasUser') }}
-        </el-button>
-      </div>
-    </template>
-  </Form>
-</template>

+ 2 - 1
yudao-ui-admin-vue3/src/views/Profile/components/BasicInfo.vue

@@ -62,7 +62,8 @@ const schema = reactive<FormSchema[]>([
   {
     field: 'sex',
     label: t('profile.user.sex'),
-    component: 'InputNumber'
+    component: 'InputNumber',
+    value: 0
   }
 ])
 const sexVlue = ref<number>()

+ 10 - 28
yudao-ui-admin-vue3/src/views/infra/codegen/codegen.data.ts

@@ -17,40 +17,28 @@ const crudSchemas = reactive<CrudSchema[]>([
     label: t('common.index'),
     field: 'id',
     type: 'index',
-    form: {
-      show: false
-    },
-    detail: {
-      show: false
-    }
+    isForm: false,
+    isDetail: false
   },
   {
     label: '表名称',
     field: 'tableName',
-    search: {
-      show: true
-    }
+    isSearch: true
   },
   {
     label: '表描述',
     field: 'tableComment',
-    search: {
-      show: true
-    }
+    isSearch: true
   },
   {
     label: '实体',
     field: 'className',
-    search: {
-      show: true
-    }
+    isSearch: true
   },
   {
     label: t('common.createTime'),
     field: 'createTime',
-    form: {
-      show: false
-    },
+    isForm: false,
     search: {
       show: true,
       component: 'DatePicker',
@@ -64,20 +52,14 @@ const crudSchemas = reactive<CrudSchema[]>([
   {
     label: t('common.updateTime'),
     field: 'updateTime',
-    form: {
-      show: false
-    }
+    isForm: false
   },
   {
     label: t('table.action'),
     field: 'action',
-    width: '500px',
-    form: {
-      show: false
-    },
-    detail: {
-      show: false
-    }
+    width: '350px',
+    isForm: false,
+    isDetail: false
   }
 ])
 export const { allSchemas } = useCrudSchemas(crudSchemas)

+ 1 - 1
yudao-ui-admin-vue3/src/views/infra/codegen/components/ImportTable.vue

@@ -33,7 +33,7 @@
       :data="dbTableList"
       v-loading="dbLoading"
       :checkbox-config="{ highlight: true, range: true }"
-      height="350px"
+      height="260px"
       class="xtable-scrollbar"
     >
       <vxe-column type="checkbox" width="60" />

+ 1 - 2
yudao-ui-admin-vue3/src/views/system/dept/dept.data.ts

@@ -49,8 +49,7 @@ export const modelSchema = reactive<FormSchema[]>([
   {
     label: '显示排序',
     field: 'sort',
-    component: 'InputNumber',
-    value: 0
+    component: 'Input'
   },
   {
     label: '状态',

+ 235 - 176
yudao-ui-admin-vue3/src/views/system/dept/index.vue

@@ -1,229 +1,288 @@
 <template>
-  <div class="flex">
-    <el-card class="w-1/3 dept" :gutter="12" shadow="always">
-      <template #header>
-        <div class="card-header">
-          <span>部门列表</span>
-          <XButton
-            type="primary"
-            preIcon="ep:zoom-in"
-            title="新增根节点"
-            v-hasPermi="['system:dept:create']"
-            @click="handleCreate"
+  <ContentWrap>
+    <!-- 搜索工作栏 -->
+    <el-form :model="queryParams" ref="queryForm" :inline="true">
+      <el-form-item label="部门名称" prop="name">
+        <el-input v-model="queryParams.name" placeholder="请输入部门名称" />
+      </el-form-item>
+      <el-form-item label="状态" prop="status">
+        <el-select v-model="queryParams.status" placeholder="请选择部门状态">
+          <el-option
+            v-for="dict in getIntDictOptions(DICT_TYPE.COMMON_STATUS)"
+            :key="dict.value"
+            :label="dict.label"
+            :value="dict.value"
           />
-        </div>
+        </el-select>
+      </el-form-item>
+      <el-form-item>
+        <!-- 操作:搜索 -->
+        <XButton
+          type="primary"
+          preIcon="ep:search"
+          :title="t('common.query')"
+          @click="handleQuery()"
+        />
+        <!-- 操作:重置 -->
+        <XButton preIcon="ep:refresh-right" :title="t('common.reset')" @click="resetQuery()" />
+      </el-form-item>
+    </el-form>
+    <vxe-toolbar>
+      <template #buttons>
+        <!-- 操作:新增 -->
+        <XButton
+          type="primary"
+          preIcon="ep:zoom-in"
+          :title="t('action.add')"
+          v-hasPermi="['system:dept:create']"
+          @click="handleCreate()"
+        />
+        <XButton title="展开所有" @click="xTable?.setAllTreeExpand(true)" />
+        <XButton title="关闭所有" @click="xTable?.clearTreeExpand()" />
       </template>
-      <div class="custom-tree-container">
-        <!-- <p>部门列表</p> -->
-        <!-- 操作工具栏 -->
-        <el-input v-model="filterText" placeholder="搜索部门" />
-        <el-tree
-          ref="treeRef"
+    </vxe-toolbar>
+    <!-- 列表 -->
+    <vxe-table
+      show-overflow
+      keep-source
+      ref="xTable"
+      :loading="tableLoading"
+      :row-config="{ keyField: 'id' }"
+      :column-config="{ resizable: true }"
+      :tree-config="{ transform: true, rowField: 'id', parentField: 'parentId' }"
+      :print-config="{}"
+      :export-config="{}"
+      :data="tableData"
+      class="xtable"
+    >
+      <vxe-column title="部门名称" field="name" width="200" tree-node />
+      <vxe-column title="负责人" field="leaderUserId" :formatter="userNicknameFormat" />
+      <vxe-column title="排序" field="sort" />
+      <vxe-column title="状态" field="status">
+        <template #default="{ row }">
+          <DictTag :type="DICT_TYPE.COMMON_STATUS" :value="row.status" />
+        </template>
+      </vxe-column>
+      <vxe-column title="创建时间" field="createTime" formatter="formatDate" />
+      <vxe-column title="操作" width="200">
+        <template #default="{ row }">
+          <!-- 操作:修改 -->
+          <XTextButton
+            preIcon="ep:edit"
+            :title="t('action.edit')"
+            v-hasPermi="['system:dept:update']"
+            @click="handleUpdate(row.id)"
+          />
+          <!-- 操作:删除 -->
+          <XTextButton
+            preIcon="ep:delete"
+            :title="t('action.del')"
+            v-hasPermi="['system:dept:delete']"
+            @click="handleDelete(row.id)"
+          />
+        </template>
+      </vxe-column>
+    </vxe-table>
+  </ContentWrap>
+  <!-- 添加或修改菜单对话框 -->
+  <XModal id="deptModel" v-model="dialogVisible" :title="dialogTitle">
+    <!-- 对话框(添加 / 修改) -->
+    <!-- 操作工具栏 -->
+    <Form ref="formRef" :schema="modelSchema" :rules="rules">
+      <template #parentId>
+        <el-tree-select
           node-key="id"
-          :data="deptOptions"
+          v-model="deptParentId"
           :props="defaultProps"
-          :highlight-current="true"
-          default-expand-all
-          :filter-node-method="filterNode"
-          :expand-on-click-node="false"
-        >
-          <template #default="{ node, data }">
-            <span class="custom-tree-node">
-              <span>{{ node.label }}</span>
-              <span>
-                <XTextButton
-                  preIcon="ep:zoom-in"
-                  :title="t('action.add')"
-                  v-hasPermi="['system:dept:create']"
-                  @click="handleCreate(data)"
-                />
-                <XTextButton
-                  preIcon="ep:edit"
-                  :title="t('action.edit')"
-                  v-hasPermi="['system:dept:update']"
-                  @click="handleUpdate(data)"
-                />
-                <XTextButton
-                  preIcon="ep:delete"
-                  :title="t('action.del')"
-                  v-hasPermi="['system:dept:delete']"
-                  @click="handleDelete(data)"
-                />
-              </span>
-            </span>
-          </template>
-        </el-tree>
-      </div>
-    </el-card>
-    <el-card class="w-2/3 dept" style="margin-left: 10px" :gutter="12" shadow="hover">
-      <template #header>
-        <div class="card-header">
-          <span>{{ formTitle }}</span>
-        </div>
-      </template>
-      <div v-if="!showForm">
-        <span><p>请从左侧选择部门</p></span>
-      </div>
-      <div v-if="showForm">
-        <!-- 操作工具栏 -->
-        <Form ref="formRef" :schema="modelSchema" :rules="rules">
-          <template #parentId>
-            <el-tree-select
-              node-key="id"
-              v-model="deptParentId"
-              :props="defaultProps"
-              :data="deptOptions"
-              check-strictly
-            />
-          </template>
-          <template #leaderUserId>
-            <el-select v-model="leaderUserId">
-              <el-option
-                v-for="item in userOption"
-                :key="parseInt(item.id)"
-                :label="item.nickname"
-                :value="parseInt(item.id)"
-              />
-            </el-select>
-          </template>
-        </Form>
-        <!-- 按钮:保存 -->
-        <XButton
-          type="primary"
-          :title="t('action.save')"
-          v-hasPermi="['system:dept:update']"
-          :loading="loading"
-          @click="submitForm()"
+          :data="deptOptions"
+          :default-expanded-keys="[100]"
+          check-strictly
         />
-        <!-- 按钮:关闭 -->
-        <XButton :loading="loading" :title="t('dialog.close')" @click="showForm = false" />
-      </div>
-    </el-card>
-  </div>
+      </template>
+      <template #leaderUserId>
+        <el-select v-model="leaderUserId">
+          <el-option
+            v-for="item in userOption"
+            :key="parseInt(item.id)"
+            :label="item.nickname"
+            :value="parseInt(item.id)"
+          />
+        </el-select>
+      </template>
+    </Form>
+    <template #footer>
+      <!-- 按钮:保存 -->
+      <XButton
+        v-if="['create', 'update'].includes(actionType)"
+        type="primary"
+        :loading="actionLoading"
+        @click="submitForm()"
+        :title="t('action.save')"
+      />
+      <!-- 按钮:关闭 -->
+      <XButton :loading="actionLoading" @click="dialogVisible = false" :title="t('dialog.close')" />
+    </template>
+  </XModal>
 </template>
 <script setup lang="ts">
+import { nextTick, onMounted, reactive, ref, unref } from 'vue'
 import { useI18n } from '@/hooks/web/useI18n'
-import { ElInput, ElCard, ElTree, ElTreeSelect, ElSelect, ElOption } from 'element-plus'
-import { handleTree } from '@/utils/tree'
-import { onMounted, ref, unref, watch } from 'vue'
-import * as DeptApi from '@/api/system/dept'
-import { Form, FormExpose } from '@/components/Form'
-import { modelSchema, rules } from './dept.data'
-import { DeptVO } from '@/api/system/dept/types'
 import { useMessage } from '@/hooks/web/useMessage'
+import { ElForm, ElFormItem, ElInput, ElSelect, ElTreeSelect, ElOption } from 'element-plus'
+import { VxeColumn, VxeTable, VxeTableInstance, VxeToolbar } from 'vxe-table'
+import { modelSchema } from './dept.data'
+import * as DeptApi from '@/api/system/dept'
 import { getListSimpleUsersApi } from '@/api/system/user'
-const message = useMessage()
+import { required } from '@/utils/formRules.js'
+import { DICT_TYPE, getIntDictOptions } from '@/utils/dict'
+import { handleTree } from '@/utils/tree'
+import { FormExpose } from '@/components/Form'
 
+const { t } = useI18n() // 国际化
+const message = useMessage() // 消息弹窗
+// 列表相关的变量
+const xTable = ref<VxeTableInstance>()
+const tableLoading = ref(false)
+const tableData = ref()
+// 弹窗相关的变量
+const dialogVisible = ref(false) // 是否显示弹出层
+const dialogTitle = ref('edit') // 弹出层标题
+const actionType = ref('') // 操作按钮的类型
+const actionLoading = ref(false) // 遮罩层
+const deptParentId = ref(0) // 上级ID
+const leaderUserId = ref()
+const formRef = ref<FormExpose>() // 表单 Ref
+const deptOptions = ref() // 树形结构
+const userOption = ref()
+// 新增和修改的表单校验
+const rules = reactive({
+  name: [required],
+  sort: [required],
+  path: [required],
+  status: [required]
+})
+
+// 下拉框[上级]的配置项目
 const defaultProps = {
+  checkStrictly: true,
   children: 'children',
   label: 'name',
   value: 'id'
 }
-const { t } = useI18n() // 国际化
-const loading = ref(false) // 遮罩层
-const dialogVisible = ref(false) // 是否显示弹出层
-const showForm = ref(false) // 显示form表单
-const formTitle = ref('部门信息') // 显示form标题
-const deptParentId = ref(0) // 上级ID
-// 创建form表单
-const formRef = ref<FormExpose>()
-
-// ========== 创建部门树结构 ==========
-const filterText = ref('')
-const deptOptions = ref() // 树形结构
-const treeRef = ref<InstanceType<typeof ElTree>>()
+// 获取下拉框[上级]的数据
 const getTree = async () => {
   const res = await DeptApi.listSimpleDeptApi()
   deptOptions.value = handleTree(res)
+  console.info(deptOptions.value)
 }
-const filterNode = (value: string, data: Tree) => {
-  if (!value) return true
-  return data.name.includes(value)
-}
-watch(filterText, (val) => {
-  treeRef.value!.filter(val)
-})
-// 用户列表
-const userOption = ref()
-const leaderUserId = ref()
 const getUserList = async () => {
   const res = await getListSimpleUsersApi()
   userOption.value = res
 }
-// 新增
-const handleCreate = (data: { id: number }) => {
-  // 重置表单
-  deptParentId.value = data.id
-  formTitle.value = '新增部门'
-  showForm.value = true
+// ========== 查询 ==========
+const queryParams = reactive<DeptApi.DeptPageReqVO>({
+  name: undefined,
+  status: undefined
+})
+// 执行查询
+const getList = async () => {
+  tableLoading.value = true
+  const res = await DeptApi.getDeptPageApi(queryParams)
+  tableData.value = res
+  tableLoading.value = false
+}
+
+// 查询操作
+const handleQuery = async () => {
+  await getList()
+}
+
+// 重置操作
+const resetQuery = async () => {
+  queryParams.name = undefined
+  queryParams.status = undefined
+  await getList()
+}
+
+// ========== 新增/修改 ==========
+
+// 设置标题
+const setDialogTile = (type: string) => {
+  dialogTitle.value = t('action.' + type)
+  actionType.value = type
+  dialogVisible.value = true
+}
+
+// 新增操作
+const handleCreate = async () => {
+  deptParentId.value = 0
+  leaderUserId.value = null
+  setDialogTile('create')
 }
-// 编辑
-const handleUpdate = async (data: { id: number }) => {
-  const res = await DeptApi.getDeptApi(data.id)
-  formTitle.value = '修改- ' + res?.name
-  deptParentId.value = res.parentId
+
+// 修改操作
+const handleUpdate = async (rowId: number) => {
+  setDialogTile('update')
+  // 设置数据
+  const res = await DeptApi.getDeptApi(rowId)
+  console.info(res)
+  deptParentId.value = res.deptParentId
   leaderUserId.value = res.leaderUserId
+  await nextTick()
   unref(formRef)?.setValues(res)
-  showForm.value = true
-}
-// 删除
-const handleDelete = async (data: { id: number }) => {
-  message
-    .confirm(t('common.delDataMessage'), t('common.confirmTitle'))
-    .then(async () => {
-      await DeptApi.deleteDeptApi(data.id)
-      message.success(t('common.delSuccess'))
-    })
-    .catch(() => {})
-  await getTree()
 }
-// 提交按钮
+
+// 提交新增/修改的表单
 const submitForm = async () => {
   const elForm = unref(formRef)?.getElFormRef()
   if (!elForm) return
   elForm.validate(async (valid) => {
     if (valid) {
-      loading.value = true
+      actionLoading.value = true
       // 提交请求
       try {
-        const data = unref(formRef)?.formModel as DeptVO
+        const data = unref(formRef)?.formModel as DeptApi.DeptVO
         data.parentId = deptParentId.value
         data.leaderUserId = leaderUserId.value
-        if (formTitle.value.startsWith('新增')) {
+        if (dialogTitle.value.startsWith('新增')) {
           await DeptApi.createDeptApi(data)
-        } else if (formTitle.value.startsWith('修改')) {
+        } else if (dialogTitle.value.startsWith('修改')) {
           await DeptApi.updateDeptApi(data)
         }
         // 操作成功,重新加载列表
         dialogVisible.value = false
       } finally {
-        loading.value = false
+        actionLoading.value = false
       }
     }
   })
 }
+
+// 删除操作
+const handleDelete = async (rowId: number) => {
+  message.delConfirm().then(async () => {
+    await DeptApi.deleteDeptApi(rowId)
+    message.success(t('common.delSuccess'))
+    await getList()
+  })
+}
+
+const userNicknameFormat = (row) => {
+  if (!row && !row.row && !row.row.leaderUserId) {
+    return '未设置'
+  }
+  for (const user of userOption.value) {
+    if (row.row.leaderUserId === user.id) {
+      return user.nickname
+    }
+  }
+  return '未知【' + row.row.leaderUserId + '】'
+}
+
+// ========== 初始化 ==========
 onMounted(async () => {
   await getTree()
   await getUserList()
+  await getList()
 })
 </script>
-
-<style scoped>
-.dept {
-  height: 600px;
-  max-height: 1800px;
-}
-.card-header {
-  display: flex;
-  justify-content: space-between;
-  align-items: center;
-}
-.custom-tree-node {
-  flex: 1;
-  display: flex;
-  align-items: center;
-  justify-content: space-between;
-  font-size: 14px;
-  padding-right: 8px;
-}
-</style>

+ 14 - 2
yudao-ui-admin-vue3/src/views/system/dict/index.vue

@@ -119,7 +119,14 @@
         :schema="DictTypeSchemas.allSchemas.formSchema"
         :rules="DictTypeSchemas.dictTypeRules"
         ref="typeFormRef"
-      />
+      >
+        <template #type>
+          <template v-if="dictTypeValue">
+            <el-tag>{{ dictTypeValue }}</el-tag>
+          </template>
+          <template v-else><el-input v-model="dictTypeValue" /> </template>
+        </template>
+      </Form>
       <Form
         v-if="['dataCreate', 'dataUpdate'].includes(actionType)"
         :schema="DictDataSchemas.allSchemas.formSchema"
@@ -152,6 +159,7 @@ import { ref, unref, onMounted } from 'vue'
 import { DICT_TYPE } from '@/utils/dict'
 import { useI18n } from '@/hooks/web/useI18n'
 import { FormExpose } from '@/components/Form'
+import { ElInput, ElTag } from 'element-plus'
 import * as DictTypeSchemas from './dict.type'
 import * as DictDataSchemas from './dict.data'
 import { useTable } from '@/hooks/web/useTable'
@@ -174,15 +182,17 @@ const {
   setSearchParams: setTypeSearchParams,
   delList: delTypeList
 } = typeMethods
-
+const dictTypeValue = ref('')
 // 字典分类修改操作
 const handleTypeCreate = () => {
+  dictTypeValue.value = ''
   setDialogTile('typeCreate')
 }
 const handleTypeUpdate = async (row: DictTypeVO) => {
   setDialogTile('typeUpdate')
   // 设置数据
   const res = await DictTypeApi.getDictTypeApi(row.id)
+  dictTypeValue.value = res.type
   unref(typeFormRef)?.setValues(res)
 }
 
@@ -229,6 +239,7 @@ const actionLoading = ref(false) // 遮罩层
 const typeFormRef = ref<FormExpose>() // 分类表单 Ref
 const dataFormRef = ref<FormExpose>() // 数据表单 Ref
 const actionType = ref('') // 操作按钮的类型
+
 // 设置标题
 const setDialogTile = (type: string) => {
   dialogTitle.value = t('action.' + type)
@@ -246,6 +257,7 @@ const submitTypeForm = async () => {
       try {
         const data = unref(typeFormRef)?.formModel as DictTypeVO
         if (actionType.value === 'typeCreate') {
+          data.type = dictTypeValue.value
           await DictTypeApi.createDictTypeApi(data)
           ElMessage.success(t('common.createSuccess'))
         } else if (actionType.value === 'typeUpdate') {

+ 1 - 2
yudao-ui-admin-vue3/src/views/system/tenant/tenant.data.ts

@@ -82,8 +82,7 @@ const crudSchemas = reactive<CrudSchema[]>([
     label: '账号额度',
     field: 'accountCount',
     form: {
-      component: 'InputNumber',
-      value: 0
+      component: 'InputNumber'
     }
   },
   {

+ 1 - 0
yudao-ui-admin-vue3/src/views/system/user/user.data.ts

@@ -74,6 +74,7 @@ const crudSchemas = reactive<VxeCrudSchema>({
     {
       title: '最后登录时间',
       field: 'loginDate',
+      formatter: 'formatDate',
       isForm: false
     },
     {

+ 3 - 1
yudao-ui-admin-vue3/vite.config.ts

@@ -13,7 +13,7 @@ import { createHtmlPlugin } from 'vite-plugin-html'
 import viteCompression from 'vite-plugin-compression'
 import VueMarcos from 'unplugin-vue-macros/vite'
 
-// 当前执行node命令时文件夹的地址(工作目录)
+// 当前执行node命令时文件夹的地址(工作目录)
 const root = process.cwd()
 
 // 路径查找
@@ -144,6 +144,8 @@ export default ({ command, mode }: ConfigEnv): UserConfig => {
         'vue-router',
         'vue-types',
         'vue-i18n',
+        'vxe-table',
+        'xe-utils',
         'element-plus/es',
         'element-plus/es/locale/lang/zh-cn',
         'element-plus/es/locale/lang/en',

+ 18 - 0
yudao-ui-admin/src/api/login.js

@@ -126,5 +126,23 @@ export function authorize(responseType, clientId, redirectUri, state,
   })
 }
 
+// 获取验证图片  以及token
+export function reqGet(data) {
+  return request({
+    url: 'system/captcha/get',
+    method: 'post',
+    data
+  })
+}
+
+// 滑动或者点选验证
+export function reqCheck(data) {
+  return request({
+    url: '/system/captcha/check',
+    method: 'post',
+    data
+  })
+}
+
 export class socialBindLogin {
 }

+ 2 - 2
yudao-ui-admin/src/components/RightToolbar/index.vue

@@ -92,13 +92,13 @@ export default {
 };
 </script>
 <style lang="scss" scoped>
-::v-deep .el-transfer__button {
+:deep(.el-transfer__button) {
   border-radius: 50%;
   padding: 12px;
   display: block;
   margin-left: 0px;
 }
-::v-deep .el-transfer__button:first-child {
+:deep(.el-transfer__button:first-child) {
   margin-bottom: 10px;
 }
 </style>

+ 1 - 1
yudao-ui-admin/src/components/Verifition/Verify/VerifyPoints.vue

@@ -60,7 +60,7 @@
  * */
 import { resetSize } from './../utils/util'
 import { aesEncrypt } from '@/utils/ase'
-import { reqGet, reqCheck } from './../api/index'
+import { reqGet, reqCheck } from '@/api/login'
 
 export default {
   name: 'VerifyPoints',

+ 1 - 1
yudao-ui-admin/src/components/Verifition/Verify/VerifySlide.vue

@@ -64,7 +64,7 @@
  * */
 import { aesEncrypt } from '@/utils/ase'
 import { resetSize } from './../utils/util'
-import { reqGet, reqCheck } from './../api/index'
+import { reqGet, reqCheck } from '@/api/login'
 
 //  "captchaType":"blockPuzzle",
 export default {

+ 0 - 27
yudao-ui-admin/src/components/Verifition/api/index.js

@@ -1,27 +0,0 @@
-/**
- * 此处可直接引用自己项目封装好的 axios 配合后端联调
- */
-
-import request from './../utils/axios' // 组件内部封装的axios
-// import request from "@/api/axios.js"       //调用项目封装的axios
-
-// 获取验证图片  以及token
-export function reqGet(data) {
-  return request({
-    // url: '/captcha/get',
-    url: '/admin-api/system/captcha/get', // 使用项目自定义的 /admin-api/ 前缀
-    method: 'post',
-    data
-  })
-}
-
-// 滑动或者点选验证
-export function reqCheck(data) {
-  return request({
-    // url: '/captcha/check',
-    url: '/admin-api/system/captcha/check', // 使用项目自定义的 /admin-api/ 前缀
-    method: 'post',
-    data
-  })
-}
-

+ 0 - 29
yudao-ui-admin/src/components/Verifition/utils/axios.js

@@ -1,29 +0,0 @@
-import axios from 'axios'
-
-axios.defaults.baseURL = process.env.VUE_APP_BASE_API
-
-const service = axios.create({
-  timeout: 40000,
-  headers: {
-    'X-Requested-With': 'XMLHttpRequest',
-    'Content-Type': 'application/json; charset=UTF-8'
-  },
-})
-service.interceptors.request.use(
-  config => {
-    return config
-  },
-  error => {
-    Promise.reject(error)
-  }
-)
-
-// response interceptor
-service.interceptors.response.use(
-  response => {
-    return response.data
-  },
-  error => {
-  }
-)
-export default service

+ 1 - 1
yudao-ui-admin/src/views/mall/trade/order/detail.vue

@@ -244,7 +244,7 @@ export default {
 </script>
 
 <style lang="scss" scoped>
-  ::v-deep .el-descriptions{
+  :deep(.el-descriptions){
     &:not(:nth-child(1)) {
       margin-top: 20px;
     }

+ 1 - 1
yudao-ui-admin/src/views/mall/trade/order/index.vue

@@ -332,7 +332,7 @@
 </script>
 
 <style lang="scss" scoped>
-  ::v-deep .order-table{
+  :deep(.order-table){
     margin-top: 20px;
     border-bottom: none;
     &::before{