Browse Source

!195 发布 5.3.1-BETA_2.3.0-BETA 公测版本
Merge pull request !195 from 疯狂的狮子Li/dev

疯狂的狮子Li 3 months ago
parent
commit
b23b123613
98 changed files with 575 additions and 483 deletions
  1. 55 47
      .eslintrc-auto-import.json
  2. 0 86
      eslint.config.js
  3. 44 0
      eslint.config.ts
  4. 35 28
      package.json
  5. 2 2
      src/App.vue
  6. 1 0
      src/api/system/user/types.ts
  7. 0 5
      src/api/workflow/category/types.ts
  8. 13 0
      src/api/workflow/task/index.ts
  9. 6 0
      src/api/workflow/task/types.ts
  10. 0 0
      src/assets/icons/svg/button.svg
  11. 1 1
      src/assets/styles/btn.scss
  12. 9 13
      src/assets/styles/index.scss
  13. 5 11
      src/assets/styles/ruoyi.scss
  14. 2 0
      src/assets/styles/sidebar.scss
  15. 1 1
      src/components/Breadcrumb/index.vue
  16. 1 1
      src/components/DictTag/index.vue
  17. 12 5
      src/components/FileUpload/index.vue
  18. 2 2
      src/components/HeaderSearch/index.vue
  19. 1 1
      src/components/IconSelect/index.vue
  20. 6 2
      src/components/ImageUpload/index.vue
  21. 2 12
      src/components/Pagination/index.vue
  22. 1 1
      src/components/Process/approvalRecord.vue
  23. 1 1
      src/components/Process/processMeddle.vue
  24. 131 23
      src/components/Process/submitVerify.vue
  25. 1 1
      src/components/RightToolbar/index.vue
  26. 1 1
      src/components/RuoYiDoc/index.vue
  27. 1 1
      src/components/RuoYiGit/index.vue
  28. 1 1
      src/components/SizeSelect/index.vue
  29. 1 1
      src/components/SvgIcon/index.vue
  30. 3 3
      src/components/TopNav/index.vue
  31. 2 2
      src/components/TreeSelect/index.vue
  32. 8 6
      src/components/UserSelect/index.vue
  33. 1 1
      src/directive/permission/index.ts
  34. 7 7
      src/layout/components/AppMain.vue
  35. 1 1
      src/layout/components/IframeToggle/index.vue
  36. 10 9
      src/layout/components/Navbar.vue
  37. 3 3
      src/layout/components/Settings/index.vue
  38. 1 1
      src/layout/components/Sidebar/Logo.vue
  39. 3 3
      src/layout/components/Sidebar/index.vue
  40. 1 1
      src/layout/components/TagsView/ScrollPane.vue
  41. 3 3
      src/layout/components/TagsView/index.vue
  42. 2 2
      src/layout/components/TopBar/search.vue
  43. 2 2
      src/layout/components/notice/index.vue
  44. 6 6
      src/layout/index.vue
  45. 5 4
      src/permission.ts
  46. 1 1
      src/plugins/auth.ts
  47. 1 1
      src/plugins/tab.ts
  48. 16 0
      src/settings.ts
  49. 2 0
      src/store/index.ts
  50. 3 2
      src/store/modules/app.ts
  51. 2 2
      src/store/modules/dict.ts
  52. 1 2
      src/store/modules/notice.ts
  53. 12 26
      src/store/modules/permission.ts
  54. 3 2
      src/store/modules/settings.ts
  55. 2 1
      src/store/modules/tagsView.ts
  56. 2 7
      src/store/modules/user.ts
  57. 1 1
      src/utils/permission.ts
  58. 6 24
      src/utils/ruoyi.ts
  59. 1 1
      src/utils/sse.ts
  60. 1 1
      src/utils/websocket.ts
  61. 1 1
      src/views/demo/tree/index.vue
  62. 2 2
      src/views/index.vue
  63. 1 1
      src/views/login.vue
  64. 1 1
      src/views/monitor/cache/index.vue
  65. 1 1
      src/views/monitor/operlog/oper-info-dialog.vue
  66. 1 1
      src/views/redirect/index.vue
  67. 1 1
      src/views/register.vue
  68. 1 1
      src/views/system/client/index.vue
  69. 1 1
      src/views/system/dept/index.vue
  70. 1 1
      src/views/system/dict/data.vue
  71. 1 1
      src/views/system/dict/index.vue
  72. 1 1
      src/views/system/menu/index.vue
  73. 3 3
      src/views/system/post/index.vue
  74. 0 2
      src/views/system/role/authUser.vue
  75. 2 2
      src/views/system/role/index.vue
  76. 0 2
      src/views/system/role/selectUser.vue
  77. 1 1
      src/views/system/tenant/index.vue
  78. 1 1
      src/views/system/tenantPackage/index.vue
  79. 9 8
      src/views/system/user/index.vue
  80. 1 1
      src/views/system/user/profile/onlineDevice.vue
  81. 6 5
      src/views/system/user/profile/thirdParty.vue
  82. 1 1
      src/views/system/user/profile/userAvatar.vue
  83. 1 1
      src/views/tool/gen/editTable.vue
  84. 1 1
      src/views/tool/gen/genInfoForm.vue
  85. 1 1
      src/views/workflow/category/index.vue
  86. 4 0
      src/views/workflow/leave/leaveEdit.vue
  87. 23 20
      src/views/workflow/processDefinition/index.vue
  88. 2 2
      src/views/workflow/processInstance/index.vue
  89. 2 2
      src/views/workflow/task/allTaskWaiting.vue
  90. 2 2
      src/views/workflow/task/myDocument.vue
  91. 1 1
      src/views/workflow/task/taskCopyList.vue
  92. 1 1
      src/views/workflow/task/taskFinish.vue
  93. 1 1
      src/views/workflow/task/taskWaiting.vue
  94. 31 20
      tsconfig.json
  95. 10 9
      vite.config.ts
  96. 2 6
      vite/plugins/auto-import.ts
  97. 4 1
      vite/plugins/index.ts
  98. 4 4
      vite/plugins/svg-icon.ts

+ 55 - 47
.eslintrc-auto-import.json

@@ -1,46 +1,25 @@
 {
 {
   "globals": {
   "globals": {
-    "ComponentInternalInstance": true,
-    "TransferKey": true,
-    "ElFormRules": true,
-    "CheckboxValueType": true,
-    "PropType": true,
-    "DateModelType": true,
-    "UploadFile": true,
-    "ElFormInstance": true,
-    "ElTableInstance": true,
-    "ElTreeInstance": true,
-    "ElTreeSelectInstance": true,
-    "ElSelectInstance": true,
-    "ElUploadInstance": true,
-    "ElCardInstance": true,
-    "ElDialogInstance": true,
-    "ElInputInstance": true,
-    "ElInputNumberInstance": true,
-    "ElRadioInstance": true,
-    "ElRadioGroupInstance": true,
-    "ElRadioButtonInstance": true,
-    "ElCheckboxInstance": true,
-    "ElCheckboxGroupInstance": true,
-    "ElSwitchInstance": true,
-    "ElDatePickerInstance": true,
-    "ElTimePickerInstance": true,
-    "ElTimeSelectInstance": true,
-    "ElScrollbarInstance": true,
-    "ElCascaderInstance": true,
-    "ElColorPickerInstance": true,
-    "ElRateInstance": true,
-    "ElSliderInstance": true,
-    "useRouter": true,
-    "useRoute": true,
+    "Component": true,
+    "ComponentPublicInstance": true,
+    "ComputedRef": true,
+    "DirectiveBinding": true,
     "EffectScope": true,
     "EffectScope": true,
-    "ElTable": true,
-    "ElSelect": true,
-    "ElUpload": true,
-    "ElForm": true,
-    "ElTree": true,
+    "ElLoading": true,
     "ElMessage": true,
     "ElMessage": true,
     "ElMessageBox": true,
     "ElMessageBox": true,
+    "ElNotification": true,
+    "ExtractDefaultPropTypes": true,
+    "ExtractPropTypes": true,
+    "ExtractPublicPropTypes": true,
+    "InjectionKey": true,
+    "MaybeRef": true,
+    "MaybeRefOrGetter": true,
+    "PropType": true,
+    "Ref": true,
+    "VNode": true,
+    "WritableComputedRef": true,
+    "acceptHMRUpdate": true,
     "asyncComputed": true,
     "asyncComputed": true,
     "autoResetRef": true,
     "autoResetRef": true,
     "computed": true,
     "computed": true,
@@ -54,36 +33,50 @@
     "createEventHook": true,
     "createEventHook": true,
     "createGlobalState": true,
     "createGlobalState": true,
     "createInjectionState": true,
     "createInjectionState": true,
+    "createPinia": true,
     "createReactiveFn": true,
     "createReactiveFn": true,
+    "createReusableTemplate": true,
     "createSharedComposable": true,
     "createSharedComposable": true,
+    "createTemplatePromise": true,
     "createUnrefFn": true,
     "createUnrefFn": true,
     "customRef": true,
     "customRef": true,
     "debouncedRef": true,
     "debouncedRef": true,
     "debouncedWatch": true,
     "debouncedWatch": true,
     "defineAsyncComponent": true,
     "defineAsyncComponent": true,
     "defineComponent": true,
     "defineComponent": true,
+    "defineStore": true,
     "eagerComputed": true,
     "eagerComputed": true,
     "effectScope": true,
     "effectScope": true,
     "extendRef": true,
     "extendRef": true,
+    "getActivePinia": true,
     "getCurrentInstance": true,
     "getCurrentInstance": true,
     "getCurrentScope": true,
     "getCurrentScope": true,
     "h": true,
     "h": true,
     "ignorableWatch": true,
     "ignorableWatch": true,
     "inject": true,
     "inject": true,
+    "injectLocal": true,
     "isDefined": true,
     "isDefined": true,
     "isProxy": true,
     "isProxy": true,
     "isReactive": true,
     "isReactive": true,
     "isReadonly": true,
     "isReadonly": true,
     "isRef": true,
     "isRef": true,
     "makeDestructurable": true,
     "makeDestructurable": true,
+    "mapActions": true,
+    "mapGetters": true,
+    "mapState": true,
+    "mapStores": true,
+    "mapWritableState": true,
     "markRaw": true,
     "markRaw": true,
     "nextTick": true,
     "nextTick": true,
     "onActivated": true,
     "onActivated": true,
     "onBeforeMount": true,
     "onBeforeMount": true,
+    "onBeforeRouteLeave": true,
+    "onBeforeRouteUpdate": true,
     "onBeforeUnmount": true,
     "onBeforeUnmount": true,
     "onBeforeUpdate": true,
     "onBeforeUpdate": true,
     "onClickOutside": true,
     "onClickOutside": true,
     "onDeactivated": true,
     "onDeactivated": true,
+    "onElementRemoval": true,
     "onErrorCaptured": true,
     "onErrorCaptured": true,
     "onKeyStroke": true,
     "onKeyStroke": true,
     "onLongPress": true,
     "onLongPress": true,
@@ -95,8 +88,10 @@
     "onStartTyping": true,
     "onStartTyping": true,
     "onUnmounted": true,
     "onUnmounted": true,
     "onUpdated": true,
     "onUpdated": true,
+    "onWatcherCleanup": true,
     "pausableWatch": true,
     "pausableWatch": true,
     "provide": true,
     "provide": true,
+    "provideLocal": true,
     "reactify": true,
     "reactify": true,
     "reactifyObject": true,
     "reactifyObject": true,
     "reactive": true,
     "reactive": true,
@@ -111,12 +106,14 @@
     "refThrottled": true,
     "refThrottled": true,
     "refWithControl": true,
     "refWithControl": true,
     "resolveComponent": true,
     "resolveComponent": true,
-    "resolveDirective": true,
     "resolveRef": true,
     "resolveRef": true,
     "resolveUnref": true,
     "resolveUnref": true,
+    "setActivePinia": true,
+    "setMapStoreSuffix": true,
     "shallowReactive": true,
     "shallowReactive": true,
     "shallowReadonly": true,
     "shallowReadonly": true,
     "shallowRef": true,
     "shallowRef": true,
+    "storeToRefs": true,
     "syncRef": true,
     "syncRef": true,
     "syncRefs": true,
     "syncRefs": true,
     "templateRef": true,
     "templateRef": true,
@@ -126,6 +123,7 @@
     "toReactive": true,
     "toReactive": true,
     "toRef": true,
     "toRef": true,
     "toRefs": true,
     "toRefs": true,
+    "toValue": true,
     "triggerRef": true,
     "triggerRef": true,
     "tryOnBeforeMount": true,
     "tryOnBeforeMount": true,
     "tryOnBeforeUnmount": true,
     "tryOnBeforeUnmount": true,
@@ -136,11 +134,14 @@
     "unrefElement": true,
     "unrefElement": true,
     "until": true,
     "until": true,
     "useActiveElement": true,
     "useActiveElement": true,
+    "useAnimate": true,
+    "useArrayDifference": true,
     "useArrayEvery": true,
     "useArrayEvery": true,
     "useArrayFilter": true,
     "useArrayFilter": true,
     "useArrayFind": true,
     "useArrayFind": true,
     "useArrayFindIndex": true,
     "useArrayFindIndex": true,
     "useArrayFindLast": true,
     "useArrayFindLast": true,
+    "useArrayIncludes": true,
     "useArrayJoin": true,
     "useArrayJoin": true,
     "useArrayMap": true,
     "useArrayMap": true,
     "useArrayReduce": true,
     "useArrayReduce": true,
@@ -157,9 +158,11 @@
     "useBrowserLocation": true,
     "useBrowserLocation": true,
     "useCached": true,
     "useCached": true,
     "useClipboard": true,
     "useClipboard": true,
+    "useClipboardItems": true,
     "useCloned": true,
     "useCloned": true,
     "useColorMode": true,
     "useColorMode": true,
     "useConfirmDialog": true,
     "useConfirmDialog": true,
+    "useCountdown": true,
     "useCounter": true,
     "useCounter": true,
     "useCssModule": true,
     "useCssModule": true,
     "useCssVar": true,
     "useCssVar": true,
@@ -198,6 +201,7 @@
     "useFullscreen": true,
     "useFullscreen": true,
     "useGamepad": true,
     "useGamepad": true,
     "useGeolocation": true,
     "useGeolocation": true,
+    "useId": true,
     "useIdle": true,
     "useIdle": true,
     "useImage": true,
     "useImage": true,
     "useInfiniteScroll": true,
     "useInfiniteScroll": true,
@@ -206,6 +210,7 @@
     "useIntervalFn": true,
     "useIntervalFn": true,
     "useKeyModifier": true,
     "useKeyModifier": true,
     "useLastChanged": true,
     "useLastChanged": true,
+    "useLink": true,
     "useLocalStorage": true,
     "useLocalStorage": true,
     "useMagicKeys": true,
     "useMagicKeys": true,
     "useManualRefHistory": true,
     "useManualRefHistory": true,
@@ -213,6 +218,7 @@
     "useMediaQuery": true,
     "useMediaQuery": true,
     "useMemoize": true,
     "useMemoize": true,
     "useMemory": true,
     "useMemory": true,
+    "useModel": true,
     "useMounted": true,
     "useMounted": true,
     "useMouse": true,
     "useMouse": true,
     "useMouseInElement": true,
     "useMouseInElement": true,
@@ -226,6 +232,8 @@
     "useOnline": true,
     "useOnline": true,
     "usePageLeave": true,
     "usePageLeave": true,
     "useParallax": true,
     "useParallax": true,
+    "useParentElement": true,
+    "usePerformanceObserver": true,
     "usePermission": true,
     "usePermission": true,
     "usePointer": true,
     "usePointer": true,
     "usePointerLock": true,
     "usePointerLock": true,
@@ -235,10 +243,14 @@
     "usePreferredDark": true,
     "usePreferredDark": true,
     "usePreferredLanguages": true,
     "usePreferredLanguages": true,
     "usePreferredReducedMotion": true,
     "usePreferredReducedMotion": true,
+    "usePreferredReducedTransparency": true,
     "usePrevious": true,
     "usePrevious": true,
     "useRafFn": true,
     "useRafFn": true,
     "useRefHistory": true,
     "useRefHistory": true,
     "useResizeObserver": true,
     "useResizeObserver": true,
+    "useRoute": true,
+    "useRouter": true,
+    "useSSRWidth": true,
     "useScreenOrientation": true,
     "useScreenOrientation": true,
     "useScreenSafeArea": true,
     "useScreenSafeArea": true,
     "useScriptTag": true,
     "useScriptTag": true,
@@ -256,6 +268,7 @@
     "useStyleTag": true,
     "useStyleTag": true,
     "useSupported": true,
     "useSupported": true,
     "useSwipe": true,
     "useSwipe": true,
+    "useTemplateRef": true,
     "useTemplateRefsList": true,
     "useTemplateRefsList": true,
     "useTextDirection": true,
     "useTextDirection": true,
     "useTextSelection": true,
     "useTextSelection": true,
@@ -291,8 +304,10 @@
     "watchArray": true,
     "watchArray": true,
     "watchAtMost": true,
     "watchAtMost": true,
     "watchDebounced": true,
     "watchDebounced": true,
+    "watchDeep": true,
     "watchEffect": true,
     "watchEffect": true,
     "watchIgnorable": true,
     "watchIgnorable": true,
+    "watchImmediate": true,
     "watchOnce": true,
     "watchOnce": true,
     "watchPausable": true,
     "watchPausable": true,
     "watchPostEffect": true,
     "watchPostEffect": true,
@@ -300,13 +315,6 @@
     "watchThrottled": true,
     "watchThrottled": true,
     "watchTriggerable": true,
     "watchTriggerable": true,
     "watchWithFilter": true,
     "watchWithFilter": true,
-    "whenever": true,
-    "ImportOption": true,
-    "TreeType": true,
-    "FieldOption": true,
-    "PageData": true,
-    "storeToRefs": true,
-    "DictDataOption": true,
-    "UploadOption": true
+    "whenever": true
   }
   }
 }
 }

+ 0 - 86
eslint.config.js

@@ -1,86 +0,0 @@
-import globals from 'globals';
-import pluginJs from '@eslint/js';
-import tseslint from 'typescript-eslint';
-import pluginVue from 'eslint-plugin-vue';
-import { readFile } from 'node:fs/promises';
-import prettier from 'eslint-plugin-prettier';
-
-/**
- * https://blog.csdn.net/sayUonly/article/details/123482912
- * 自动导入的配置
- */
-const autoImportFile = new URL('./.eslintrc-auto-import.json', import.meta.url);
-const autoImportGlobals = JSON.parse(await readFile(autoImportFile, 'utf8'));
-
-/** @type {import('eslint').Linter.Config[]} */
-export default [
-  {
-    /**
-     * 不需要.eslintignore文件 而是在这里配置
-     */
-    ignores: [
-      '*.sh',
-      'node_modules',
-      '*.md',
-      '*.woff',
-      '*.ttf',
-      '.vscode',
-      '.idea',
-      'dist',
-      '/public',
-      '/docs',
-      '.husky',
-      '.local',
-      '/bin',
-      '.eslintrc.cjs',
-      'prettier.config.js',
-      'src/assets',
-      'tailwind.config.js'
-    ]
-  },
-  { files: ['**/*.{js,mjs,cjs,ts,vue}'] },
-  {
-    languageOptions: {
-      globals: globals.browser
-    }
-  },
-  pluginJs.configs.recommended,
-  ...tseslint.configs.recommended,
-  ...pluginVue.configs['flat/essential'],
-  {
-    files: ['**/*.vue'],
-    languageOptions: {
-      parserOptions: {
-        parser: tseslint.parser
-      }
-    }
-  },
-  {
-    languageOptions: {
-      globals: {
-        // 自动导入的配置 undef
-        ...autoImportGlobals.globals,
-        DialogOption: 'readonly',
-        LayoutSetting: 'readonly'
-      }
-    },
-    plugins: { prettier },
-    rules: {
-      '@typescript-eslint/no-empty-function': 'off',
-      '@typescript-eslint/no-explicit-any': 'off',
-      '@typescript-eslint/no-unused-vars': 'off',
-      '@typescript-eslint/no-this-alias': 'off',
-
-      // vue
-      'vue/multi-word-component-names': 'off',
-      'vue/valid-define-props': 'off',
-      'vue/no-v-model-argument': 'off',
-      'prefer-rest-params': 'off',
-      // prettier
-      'prettier/prettier': 'error',
-      // 允许使用空Object类型 {}
-      '@typescript-eslint/no-empty-object-type': 'off',
-      '@typescript-eslint/no-unused-expressions': 'off'
-    }
-  }
-];

+ 44 - 0
eslint.config.ts

@@ -0,0 +1,44 @@
+import pluginVue from 'eslint-plugin-vue';
+import globals from 'globals';
+import prettier from 'eslint-plugin-prettier';
+import { defineConfigWithVueTs, vueTsConfigs } from '@vue/eslint-config-typescript';
+import skipFormatting from '@vue/eslint-config-prettier/skip-formatting';
+
+export default defineConfigWithVueTs(
+  {
+    name: 'app/files-to-lint',
+    files: ['**/*.{js,cjs,ts,mts,tsx,vue}']
+  },
+
+  {
+    name: 'app/files-to-ignore',
+    ignores: ['**/dist/**', '**/dist-ssr/**', '**/coverage/**']
+  },
+  {
+    languageOptions: {
+      globals: globals.browser
+    }
+  },
+  pluginVue.configs['flat/essential'],
+  vueTsConfigs.recommended,
+  skipFormatting,
+  {
+    plugins: { prettier },
+    rules: {
+      '@typescript-eslint/no-empty-function': 'off',
+      '@typescript-eslint/no-explicit-any': 'off',
+      '@typescript-eslint/no-unused-vars': 'off',
+      '@typescript-eslint/no-this-alias': 'off',
+      // vue
+      'vue/multi-word-component-names': 'off',
+      'vue/valid-define-props': 'off',
+      'vue/no-v-model-argument': 'off',
+      'prefer-rest-params': 'off',
+      // prettier
+      'prettier/prettier': 'error',
+      // 允许使用空Object类型 {}
+      '@typescript-eslint/no-empty-object-type': 'off',
+      '@typescript-eslint/no-unused-expressions': 'off'
+    }
+  }
+);

+ 35 - 28
package.json

@@ -1,7 +1,7 @@
 {
 {
-  "$schema": "https://json.schemastore.org/tsconfig",
+  "$schema": "https://json.schemastore.org/package",
   "name": "ruoyi-vue-plus",
   "name": "ruoyi-vue-plus",
-  "version": "5.3.0",
+  "version": "5.3.1-BETA_2.3.0-BETA",
   "description": "RuoYi-Vue-Plus多租户管理系统",
   "description": "RuoYi-Vue-Plus多租户管理系统",
   "author": "LionLi",
   "author": "LionLi",
   "license": "MIT",
   "license": "MIT",
@@ -23,13 +23,11 @@
     "@element-plus/icons-vue": "2.3.1",
     "@element-plus/icons-vue": "2.3.1",
     "@highlightjs/vue-plugin": "2.1.0",
     "@highlightjs/vue-plugin": "2.1.0",
     "@vueup/vue-quill": "1.2.0",
     "@vueup/vue-quill": "1.2.0",
-    "@vueuse/core": "11.3.0",
+    "@vueuse/core": "12.7.0",
     "animate.css": "4.1.1",
     "animate.css": "4.1.1",
     "await-to-js": "3.0.0",
     "await-to-js": "3.0.0",
     "axios": "1.7.8",
     "axios": "1.7.8",
     "crypto-js": "4.2.0",
     "crypto-js": "4.2.0",
-    "diagram-js": "12.3.0",
-    "didi": "9.0.2",
     "echarts": "5.5.0",
     "echarts": "5.5.0",
     "element-plus": "2.8.8",
     "element-plus": "2.8.8",
     "file-saver": "2.0.5",
     "file-saver": "2.0.5",
@@ -50,38 +48,47 @@
     "vxe-table": "4.5.22"
     "vxe-table": "4.5.22"
   },
   },
   "devDependencies": {
   "devDependencies": {
-    "@eslint/js": "9.15.0",
     "@iconify/json": "2.2.276",
     "@iconify/json": "2.2.276",
     "@types/crypto-js": "4.2.2",
     "@types/crypto-js": "4.2.2",
     "@types/file-saver": "2.0.7",
     "@types/file-saver": "2.0.7",
     "@types/js-cookie": "3.0.6",
     "@types/js-cookie": "3.0.6",
-    "@types/node": "18.18.2",
+    "@types/node": "^22.13.4",
     "@types/nprogress": "0.2.3",
     "@types/nprogress": "0.2.3",
-    "@unocss/preset-attributify": "0.64.1",
-    "@unocss/preset-icons": "0.64.1",
-    "@unocss/preset-uno": "0.64.1",
-    "@vitejs/plugin-vue": "5.0.4",
+    "@unocss/preset-attributify": "66.0.0",
+    "@unocss/preset-icons": "66.0.0",
+    "@unocss/preset-uno": "66.0.0",
+    "@vitejs/plugin-vue": "5.2.1",
     "@vue/compiler-sfc": "3.4.23",
     "@vue/compiler-sfc": "3.4.23",
-    "autoprefixer": "10.4.18",
-    "eslint": "9.15.0",
-    "eslint-plugin-prettier": "^5.2.1",
-    "eslint-plugin-vue": "9.31.0",
-    "fast-glob": "3.3.2",
-    "globals": "15.12.0",
-    "postcss": "8.4.36",
-    "prettier": "3.2.5",
-    "sass": "1.72.0",
-    "typescript": "5.7.2",
-    "typescript-eslint": "8.16.0",
-    "unocss": "0.64.1",
+    "@vue/eslint-config-prettier": "10.2.0",
+    "@vue/eslint-config-typescript": "14.4.0",
+    "autoprefixer": "10.4.20",
+    "eslint": "9.21.0",
+    "eslint-plugin-prettier": "5.2.3",
+    "eslint-plugin-vue": "9.32.0",
+    "globals": "16.0.0",
+    "prettier": "3.5.2",
+    "sass": "1.84.0",
+    "typescript": "~5.7.3",
+    "unocss": "66.0.0",
     "unplugin-auto-import": "0.17.5",
     "unplugin-auto-import": "0.17.5",
     "unplugin-icons": "0.18.5",
     "unplugin-icons": "0.18.5",
-    "unplugin-vue-components": "0.26.0",
+    "unplugin-vue-components": "28.0.0",
     "unplugin-vue-setup-extend-plus": "1.0.1",
     "unplugin-vue-setup-extend-plus": "1.0.1",
     "vite": "5.4.11",
     "vite": "5.4.11",
     "vite-plugin-compression": "0.5.1",
     "vite-plugin-compression": "0.5.1",
-    "vite-plugin-svg-icons": "2.0.1",
-    "vitest": "1.5.0",
-    "vue-tsc": "2.0.13"
-  }
+    "vite-plugin-svg-icons-ng": "^1.2.2",
+    "vite-plugin-vue-devtools": "7.7.1",
+    "vitest": "3.0.5",
+    "vue-tsc": "^2.2.2"
+  },
+  "engines": {
+    "node": ">=18.18.0",
+    "npm": ">=8.9.0"
+  },
+  "browserslist": [
+    "Chrome >= 87",
+    "Edge >= 88",
+    "Safari >= 14",
+    "Firefox >= 78"
+  ]
 }
 }

+ 2 - 2
src/App.vue

@@ -5,9 +5,9 @@
 </template>
 </template>
 
 
 <script setup lang="ts">
 <script setup lang="ts">
-import useSettingsStore from '@/store/modules/settings';
+import { useSettingsStore } from '@/store/modules/settings';
 import { handleThemeStyle } from '@/utils/theme';
 import { handleThemeStyle } from '@/utils/theme';
-import useAppStore from '@/store/modules/app';
+import { useAppStore } from '@/store/modules/app';
 
 
 const appStore = useAppStore();
 const appStore = useAppStore();
 
 

+ 1 - 0
src/api/system/user/types.ts

@@ -19,6 +19,7 @@ export interface UserQuery extends PageQuery {
   status?: string;
   status?: string;
   deptId?: string | number;
   deptId?: string | number;
   roleId?: string | number;
   roleId?: string | number;
+  userIds?: string;
 }
 }
 
 
 /**
 /**

+ 0 - 5
src/api/workflow/category/types.ts

@@ -6,7 +6,6 @@ export interface CategoryTreeVO {
   children: CategoryTreeVO[];
   children: CategoryTreeVO[];
 }
 }
 export interface CategoryVO {
 export interface CategoryVO {
-
   /**
   /**
    * 流程分类ID
    * 流程分类ID
    */
    */
@@ -39,7 +38,6 @@ export interface CategoryVO {
 }
 }
 
 
 export interface CategoryForm extends BaseEntity {
 export interface CategoryForm extends BaseEntity {
-
   /**
   /**
    * 流程分类ID
    * 流程分类ID
    */
    */
@@ -59,14 +57,11 @@ export interface CategoryForm extends BaseEntity {
    * 显示顺序
    * 显示顺序
    */
    */
   orderNum?: number;
   orderNum?: number;
-
 }
 }
 
 
 export interface CategoryQuery {
 export interface CategoryQuery {
-
   /**
   /**
    * 流程分类名称
    * 流程分类名称
    */
    */
   categoryName?: string;
   categoryName?: string;
-
 }
 }

+ 13 - 0
src/api/workflow/task/index.ts

@@ -178,3 +178,16 @@ export const currentTaskAllUser = (taskId: string | number) => {
     method: 'get'
     method: 'get'
   });
   });
 };
 };
+
+/**
+ * 获取下一节点写
+ * @param data参数
+ * @returns
+ */
+export const getNextNodeList = (data: any): any => {
+  return request({
+    url: '/workflow/task/getNextNodeList',
+    method: 'post',
+    data: data
+  });
+};

+ 6 - 0
src/api/workflow/task/types.ts

@@ -29,8 +29,14 @@ export interface FlowTaskVO {
   nodeType: number;
   nodeType: number;
   nodeRatio: string | number;
   nodeRatio: string | number;
   version?: string;
   version?: string;
+  applyNode?: boolean;
+  buttonList?: buttonList[];
 }
 }
 
 
+export interface buttonList {
+  code: string;
+  show: boolean;
+}
 export interface VariableVo {
 export interface VariableVo {
   key: string;
   key: string;
   value: string;
   value: string;

File diff suppressed because it is too large
+ 0 - 0
src/assets/icons/svg/button.svg


+ 1 - 1
src/assets/styles/btn.scss

@@ -1,4 +1,4 @@
-@import './variables.module.scss';
+@use './variables.module.scss' as *;
 
 
 @mixin colorBtn($color) {
 @mixin colorBtn($color) {
   background: $color;
   background: $color;

+ 9 - 13
src/assets/styles/index.scss

@@ -1,12 +1,12 @@
-@import './variables.module.scss';
-@import './mixin.scss';
-@import './transition.scss';
-@import './element-ui.scss';
-@import './sidebar.scss';
-@import './btn.scss';
-@import './ruoyi.scss';
-@import 'animate.css';
-@import 'element-plus/dist/index.css';
+@use './variables.module.scss' as *;
+@use './mixin.scss';
+@use './transition.scss';
+@use './element-ui.scss';
+@use './sidebar.scss';
+@use './btn.scss';
+@use './ruoyi.scss';
+@use 'animate.css';
+@use 'element-plus/dist/index.css';
 
 
 body {
 body {
   height: 100%;
   height: 100%;
@@ -162,10 +162,6 @@ aside {
   position: relative;
   position: relative;
 }
 }
 
 
-.pagination-container {
-  margin-top: 30px;
-}
-
 .text-center {
 .text-center {
   text-align: center;
   text-align: center;
 }
 }

+ 5 - 11
src/assets/styles/ruoyi.scss

@@ -1,3 +1,5 @@
+@use './variables.module.scss' as *;
+
 /**
 /**
  * 通用css样式布局处理
  * 通用css样式布局处理
  * Copyright (c) 2019 ruoyi
  * Copyright (c) 2019 ruoyi
@@ -114,10 +116,9 @@ h6 {
 
 
 /** 表格布局 **/
 /** 表格布局 **/
 .pagination-container {
 .pagination-container {
-  // position: relative;
-  height: 25px;
-  margin-bottom: 10px;
-  margin-top: 15px;
+  display: flex;
+  justify-content: flex-end;
+  margin-top: 20px;
   padding: 10px 20px !important;
   padding: 10px 20px !important;
 }
 }
 
 
@@ -130,11 +131,6 @@ h6 {
   width: 100%;
   width: 100%;
 }
 }
 
 
-.pagination-container .el-pagination {
-  //right: 0;
-  //position: absolute;
-}
-
 @media (max-width: 768px) {
 @media (max-width: 768px) {
   .pagination-container .el-pagination > .el-pagination__jump {
   .pagination-container .el-pagination > .el-pagination__jump {
     display: none !important;
     display: none !important;
@@ -201,8 +197,6 @@ h6 {
 }
 }
 
 
 .card-box {
 .card-box {
-  padding-right: 15px;
-  padding-left: 15px;
   margin-bottom: 10px;
   margin-bottom: 10px;
 }
 }
 
 

+ 2 - 0
src/assets/styles/sidebar.scss

@@ -1,3 +1,5 @@
+@use './variables.module.scss' as *;
+
 #app {
 #app {
   .main-container {
   .main-container {
     height: 100%;
     height: 100%;

+ 1 - 1
src/components/Breadcrumb/index.vue

@@ -11,7 +11,7 @@
 
 
 <script setup lang="ts">
 <script setup lang="ts">
 import { RouteLocationMatched } from 'vue-router';
 import { RouteLocationMatched } from 'vue-router';
-import usePermissionStore from '@/store/modules/permission';
+import { usePermissionStore } from '@/store/modules/permission';
 
 
 const route = useRoute();
 const route = useRoute();
 const router = useRouter();
 const router = useRouter();

+ 1 - 1
src/components/DictTag/index.vue

@@ -87,7 +87,7 @@ const handleArray = (array: Array<string | number>) => {
 };
 };
 </script>
 </script>
 
 
-<style scoped>
+<style lang="scss" scoped>
 .el-tag + .el-tag {
 .el-tag + .el-tag {
   margin-left: 10px;
   margin-left: 10px;
 }
 }

+ 12 - 5
src/components/FileUpload/index.vue

@@ -7,18 +7,20 @@
       :before-upload="handleBeforeUpload"
       :before-upload="handleBeforeUpload"
       :file-list="fileList"
       :file-list="fileList"
       :limit="limit"
       :limit="limit"
+      :accept="fileAccept"
       :on-error="handleUploadError"
       :on-error="handleUploadError"
       :on-exceed="handleExceed"
       :on-exceed="handleExceed"
       :on-success="handleUploadSuccess"
       :on-success="handleUploadSuccess"
       :show-file-list="false"
       :show-file-list="false"
       :headers="headers"
       :headers="headers"
       class="upload-file-uploader"
       class="upload-file-uploader"
+      v-if="!disabled"
     >
     >
       <!-- 上传按钮 -->
       <!-- 上传按钮 -->
       <el-button type="primary">选取文件</el-button>
       <el-button type="primary">选取文件</el-button>
     </el-upload>
     </el-upload>
     <!-- 上传提示 -->
     <!-- 上传提示 -->
-    <div v-if="showTip" class="el-upload__tip">
+    <div v-if="showTip && !disabled" class="el-upload__tip">
       请上传
       请上传
       <template v-if="fileSize">
       <template v-if="fileSize">
         大小不超过 <b style="color: #f56c6c">{{ fileSize }}MB</b>
         大小不超过 <b style="color: #f56c6c">{{ fileSize }}MB</b>
@@ -35,7 +37,7 @@
           <span class="el-icon-document"> {{ getFileName(file.name) }} </span>
           <span class="el-icon-document"> {{ getFileName(file.name) }} </span>
         </el-link>
         </el-link>
         <div class="ele-upload-list__item-content-action">
         <div class="ele-upload-list__item-content-action">
-          <el-button type="danger" link @click="handleDelete(index)">删除</el-button>
+          <el-button type="danger" v-if="!disabled" link @click="handleDelete(index)">删除</el-button>
         </div>
         </div>
       </li>
       </li>
     </transition-group>
     </transition-group>
@@ -57,9 +59,11 @@ const props = defineProps({
   // 大小限制(MB)
   // 大小限制(MB)
   fileSize: propTypes.number.def(5),
   fileSize: propTypes.number.def(5),
   // 文件类型, 例如['png', 'jpg', 'jpeg']
   // 文件类型, 例如['png', 'jpg', 'jpeg']
-  fileType: propTypes.array.def(['doc', 'xls', 'ppt', 'txt', 'pdf']),
+  fileType: propTypes.array.def(['doc', 'docx', 'xls', 'xlsx', 'ppt', 'pptx', 'txt', 'pdf']),
   // 是否显示提示
   // 是否显示提示
-  isShowTip: propTypes.bool.def(true)
+  isShowTip: propTypes.bool.def(true),
+  // 禁用组件(仅查看文件)
+  disabled: propTypes.bool.def(false)
 });
 });
 
 
 const { proxy } = getCurrentInstance() as ComponentInternalInstance;
 const { proxy } = getCurrentInstance() as ComponentInternalInstance;
@@ -76,6 +80,9 @@ const showTip = computed(() => props.isShowTip && (props.fileType || props.fileS
 
 
 const fileUploadRef = ref<ElUploadInstance>();
 const fileUploadRef = ref<ElUploadInstance>();
 
 
+// 监听 fileType 变化,更新 fileAccept
+const fileAccept = computed(() => props.fileType.map((type) => `.${type}`).join(','));
+
 watch(
 watch(
   () => props.modelValue,
   () => props.modelValue,
   async (val) => {
   async (val) => {
@@ -209,7 +216,7 @@ const listToString = (list: any[], separator?: string) => {
 };
 };
 </script>
 </script>
 
 
-<style scoped lang="scss">
+<style lang="scss" scoped>
 .upload-file-uploader {
 .upload-file-uploader {
   margin-bottom: 5px;
   margin-bottom: 5px;
 }
 }

+ 2 - 2
src/components/HeaderSearch/index.vue

@@ -21,7 +21,7 @@
 import Fuse from 'fuse.js';
 import Fuse from 'fuse.js';
 import { getNormalPath } from '@/utils/ruoyi';
 import { getNormalPath } from '@/utils/ruoyi';
 import { isHttp } from '@/utils/validate';
 import { isHttp } from '@/utils/validate';
-import usePermissionStore from '@/store/modules/permission';
+import { usePermissionStore } from '@/store/modules/permission';
 import { RouteRecordRaw } from 'vue-router';
 import { RouteRecordRaw } from 'vue-router';
 
 
 type Router = Array<{
 type Router = Array<{
@@ -36,7 +36,7 @@ const show = ref(false);
 const fuse = ref();
 const fuse = ref();
 const headerSearchSelectRef = ref<ElSelectInstance>();
 const headerSearchSelectRef = ref<ElSelectInstance>();
 const router = useRouter();
 const router = useRouter();
-const routes = computed(() => usePermissionStore().getRoutes());
+const routes = computed(() => usePermissionStore().getDefaultRoutes());
 
 
 const click = () => {
 const click = () => {
   show.value = !show.value;
   show.value = !show.value;

+ 1 - 1
src/components/IconSelect/index.vue

@@ -65,7 +65,7 @@ const selectedIcon = (iconName: string) => {
 };
 };
 </script>
 </script>
 
 
-<style scoped lang="scss">
+<style lang="scss" scoped>
 .el-scrollbar {
 .el-scrollbar {
   max-height: calc(50vh - 100px) !important;
   max-height: calc(50vh - 100px) !important;
   overflow-y: auto;
   overflow-y: auto;

+ 6 - 2
src/components/ImageUpload/index.vue

@@ -1,13 +1,14 @@
 <template>
 <template>
   <div class="component-upload-image">
   <div class="component-upload-image">
     <el-upload
     <el-upload
-      ref="imageUpload"
+      ref="imageUploadRef"
       multiple
       multiple
       :action="uploadImgUrl"
       :action="uploadImgUrl"
       list-type="picture-card"
       list-type="picture-card"
       :on-success="handleUploadSuccess"
       :on-success="handleUploadSuccess"
       :before-upload="handleBeforeUpload"
       :before-upload="handleBeforeUpload"
       :limit="limit"
       :limit="limit"
+      :accept="fileAccept"
       :on-error="handleUploadError"
       :on-error="handleUploadError"
       :on-exceed="handleExceed"
       :on-exceed="handleExceed"
       :before-remove="handleDelete"
       :before-remove="handleDelete"
@@ -87,6 +88,9 @@ const showTip = computed(() => props.isShowTip && (props.fileType || props.fileS
 
 
 const imageUploadRef = ref<ElUploadInstance>();
 const imageUploadRef = ref<ElUploadInstance>();
 
 
+// 监听 fileType 变化,更新 fileAccept
+const fileAccept = computed(() => props.fileType.map((type) => `.${type}`).join(','));
+
 watch(
 watch(
   () => props.modelValue,
   () => props.modelValue,
   async (val: string) => {
   async (val: string) => {
@@ -230,7 +234,7 @@ const listToString = (list: any[], separator?: string) => {
 };
 };
 </script>
 </script>
 
 
-<style scoped lang="scss">
+<style lang="scss" scoped>
 // .el-upload--picture-card 控制加号部分
 // .el-upload--picture-card 控制加号部分
 :deep(.hide .el-upload--picture-card) {
 :deep(.hide .el-upload--picture-card) {
   display: none;
   display: none;

+ 2 - 12
src/components/Pagination/index.vue

@@ -14,13 +14,7 @@
   </div>
   </div>
 </template>
 </template>
 
 
-<script lang="ts">
-export default {
-  name: 'Pagination'
-};
-</script>
-
-<script setup lang="ts">
+<script setup name="Pagination" lang="ts">
 import { scrollTo } from '@/utils/scroll-to';
 import { scrollTo } from '@/utils/scroll-to';
 import { propTypes } from '@/utils/propTypes';
 import { propTypes } from '@/utils/propTypes';
 
 
@@ -28,10 +22,7 @@ const props = defineProps({
   total: propTypes.number,
   total: propTypes.number,
   page: propTypes.number.def(1),
   page: propTypes.number.def(1),
   limit: propTypes.number.def(20),
   limit: propTypes.number.def(20),
-  pageSizes: {
-    type: Array,
-    default: () => [10, 20, 30, 50]
-  },
+  pageSizes: { type: Array<number>, default: () => [10, 20, 30, 50] },
   // 移动端页码按钮的数量端默认值5
   // 移动端页码按钮的数量端默认值5
   pagerCount: propTypes.number.def(document.body.clientWidth < 992 ? 5 : 7),
   pagerCount: propTypes.number.def(document.body.clientWidth < 992 ? 5 : 7),
   layout: propTypes.string.def('total, sizes, prev, pager, next, jumper'),
   layout: propTypes.string.def('total, sizes, prev, pager, next, jumper'),
@@ -77,7 +68,6 @@ function handleCurrentChange(val: number) {
 
 
 <style lang="scss" scoped>
 <style lang="scss" scoped>
 .pagination-container {
 .pagination-container {
-  padding: 32px 16px;
   .el-pagination {
   .el-pagination {
     float: v-bind(float);
     float: v-bind(float);
   }
   }

+ 1 - 1
src/components/Process/approvalRecord.vue

@@ -72,7 +72,7 @@
     </el-dialog>
     </el-dialog>
   </div>
   </div>
 </template>
 </template>
-<script lang="ts" setup>
+<script setup lang="ts">
 import { flowImage } from '@/api/workflow/instance';
 import { flowImage } from '@/api/workflow/instance';
 import { propTypes } from '@/utils/propTypes';
 import { propTypes } from '@/utils/propTypes';
 import { listByIds } from '@/api/system/oss';
 import { listByIds } from '@/api/system/oss';

+ 1 - 1
src/components/Process/processMeddle.vue

@@ -49,7 +49,7 @@
     </el-dialog>
     </el-dialog>
   </el-dialog>
   </el-dialog>
 </template>
 </template>
-<script lang="ts" setup>
+<script setup lang="ts">
 import { propTypes } from '@/utils/propTypes';
 import { propTypes } from '@/utils/propTypes';
 import { FlowTaskVO, TaskOperationBo } from '@/api/workflow/task/types';
 import { FlowTaskVO, TaskOperationBo } from '@/api/workflow/task/types';
 import UserSelect from '@/components/UserSelect';
 import UserSelect from '@/components/UserSelect';

+ 131 - 23
src/components/Process/submitVerify.vue

@@ -11,12 +11,23 @@
       <el-form-item v-if="task.flowStatus === 'waiting'" label="附件">
       <el-form-item v-if="task.flowStatus === 'waiting'" label="附件">
         <fileUpload v-model="form.fileId" :file-type="['png', 'jpg', 'jpeg', 'doc', 'docx', 'xlsx', 'xls', 'ppt', 'txt', 'pdf']" :file-size="20" />
         <fileUpload v-model="form.fileId" :file-type="['png', 'jpg', 'jpeg', 'doc', 'docx', 'xlsx', 'xls', 'ppt', 'txt', 'pdf']" :file-size="20" />
       </el-form-item>
       </el-form-item>
-      <el-form-item label="抄送">
+      <el-form-item label="抄送" v-if="task.flowStatus === 'waiting' && buttonObj.copy">
         <el-button type="primary" icon="Plus" circle @click="openUserSelectCopy" />
         <el-button type="primary" icon="Plus" circle @click="openUserSelectCopy" />
         <el-tag v-for="user in selectCopyUserList" :key="user.userId" closable style="margin: 2px" @close="handleCopyCloseTag(user)">
         <el-tag v-for="user in selectCopyUserList" :key="user.userId" closable style="margin: 2px" @close="handleCopyCloseTag(user)">
           {{ user.nickName }}
           {{ user.nickName }}
         </el-tag>
         </el-tag>
       </el-form-item>
       </el-form-item>
+      <el-form-item v-if="buttonObj.pop && nestNodeList && nestNodeList.length > 0" label="下一步审批人" prop="assigneeMap">
+        <div v-for="(item, index) in nestNodeList" :key="index" style="margin-bottom: 5px; width: 500px">
+          <span>【{{ item.nodeName }}】:</span>
+          <el-input v-if="false" v-model="form.assigneeMap[item.nodeCode]" />
+          <el-input placeholder="请选择审批人" readonly v-model="nickName[item.nodeCode]">
+            <template v-slot:append>
+              <el-button @click="choosePeople(item)" icon="search">选择</el-button>
+            </template>
+          </el-input>
+        </div>
+      </el-form-item>
       <el-form-item v-if="task.flowStatus === 'waiting'" label="审批意见">
       <el-form-item v-if="task.flowStatus === 'waiting'" label="审批意见">
         <el-input v-model="form.message" type="textarea" resize="none" />
         <el-input v-model="form.message" type="textarea" resize="none" />
       </el-form-item>
       </el-form-item>
@@ -24,10 +35,14 @@
     <template #footer>
     <template #footer>
       <span class="dialog-footer">
       <span class="dialog-footer">
         <el-button :disabled="buttonDisabled" type="primary" @click="handleCompleteTask"> 提交 </el-button>
         <el-button :disabled="buttonDisabled" type="primary" @click="handleCompleteTask"> 提交 </el-button>
-        <el-button v-if="task.flowStatus === 'waiting'" :disabled="buttonDisabled" type="primary" @click="openDelegateTask"> 委托 </el-button>
-        <el-button v-if="task.flowStatus === 'waiting'" :disabled="buttonDisabled" type="primary" @click="openTransferTask"> 转办 </el-button>
+        <el-button v-if="task.flowStatus === 'waiting' && buttonObj.trust" :disabled="buttonDisabled" type="primary" @click="openDelegateTask">
+          委托
+        </el-button>
+        <el-button v-if="task.flowStatus === 'waiting' && buttonObj.transfer" :disabled="buttonDisabled" type="primary" @click="openTransferTask">
+          转办
+        </el-button>
         <el-button
         <el-button
-          v-if="task.flowStatus === 'waiting' && Number(task.nodeRatio) > 0"
+          v-if="task.flowStatus === 'waiting' && Number(task.nodeRatio) > 0 && buttonObj.addSign"
           :disabled="buttonDisabled"
           :disabled="buttonDisabled"
           type="primary"
           type="primary"
           @click="openMultiInstanceUser"
           @click="openMultiInstanceUser"
@@ -35,15 +50,24 @@
           加签
           加签
         </el-button>
         </el-button>
         <el-button
         <el-button
-          v-if="task.flowStatus === 'waiting' && Number(task.nodeRatio) > 0"
+          v-if="task.flowStatus === 'waiting' && Number(task.nodeRatio) > 0 && buttonObj.subSign"
           :disabled="buttonDisabled"
           :disabled="buttonDisabled"
           type="primary"
           type="primary"
           @click="handleTaskUser"
           @click="handleTaskUser"
         >
         >
           减签
           减签
         </el-button>
         </el-button>
-        <el-button v-if="task.flowStatus === 'waiting'" :disabled="buttonDisabled" type="danger" @click="handleTerminationTask"> 终止 </el-button>
-        <el-button v-if="task.flowStatus === 'waiting'" :disabled="buttonDisabled" type="danger" @click="handleBackProcessOpen"> 退回 </el-button>
+        <el-button
+          v-if="task.flowStatus === 'waiting' && buttonObj.termination"
+          :disabled="buttonDisabled"
+          type="danger"
+          @click="handleTerminationTask"
+        >
+          终止
+        </el-button>
+        <el-button v-if="task.flowStatus === 'waiting' && buttonObj.back" :disabled="buttonDisabled" type="danger" @click="handleBackProcessOpen">
+          退回
+        </el-button>
         <el-button :disabled="buttonDisabled" @click="cancel">取消</el-button>
         <el-button :disabled="buttonDisabled" @click="cancel">取消</el-button>
       </span>
       </span>
     </template>
     </template>
@@ -55,6 +79,8 @@
     <UserSelect ref="delegateTaskRef" :multiple="false" @confirm-call-back="handleDelegateTask"></UserSelect>
     <UserSelect ref="delegateTaskRef" :multiple="false" @confirm-call-back="handleDelegateTask"></UserSelect>
     <!-- 加签组件 -->
     <!-- 加签组件 -->
     <UserSelect ref="multiInstanceUserRef" :multiple="true" @confirm-call-back="addMultiInstanceUser"></UserSelect>
     <UserSelect ref="multiInstanceUserRef" :multiple="true" @confirm-call-back="addMultiInstanceUser"></UserSelect>
+    <!-- 弹窗选人 -->
+    <UserSelect ref="porUserRef" :multiple="true" :userIds="popUserIds" @confirm-call-back="handlePopUser"></UserSelect>
 
 
     <!-- 驳回开始 -->
     <!-- 驳回开始 -->
     <el-dialog v-model="backVisible" draggable title="驳回" width="40%" :close-on-click-modal="false">
     <el-dialog v-model="backVisible" draggable title="驳回" width="40%" :close-on-click-modal="false">
@@ -72,7 +98,11 @@
           </el-checkbox-group>
           </el-checkbox-group>
         </el-form-item>
         </el-form-item>
         <el-form-item v-if="task.flowStatus === 'waiting'" label="附件">
         <el-form-item v-if="task.flowStatus === 'waiting'" label="附件">
-          <fileUpload v-model="backForm.fileId" :file-type="['png', 'jpg', 'jpeg', 'doc', 'docx', 'xlsx', 'xls', 'ppt', 'txt', 'pdf']" :file-size="20" />
+          <fileUpload
+            v-model="backForm.fileId"
+            :file-type="['png', 'jpg', 'jpeg', 'doc', 'docx', 'xlsx', 'xls', 'ppt', 'txt', 'pdf']"
+            :file-size="20"
+          />
         </el-form-item>
         </el-form-item>
         <el-form-item label="审批意见">
         <el-form-item label="审批意见">
           <el-input v-model="backForm.message" type="textarea" resize="none" />
           <el-input v-model="backForm.message" type="textarea" resize="none" />
@@ -102,11 +132,20 @@
   </el-dialog>
   </el-dialog>
 </template>
 </template>
 
 
-<script lang="ts" setup>
+<script setup lang="ts">
 import { ref } from 'vue';
 import { ref } from 'vue';
 import { ComponentInternalInstance } from 'vue';
 import { ComponentInternalInstance } from 'vue';
 import { ElForm } from 'element-plus';
 import { ElForm } from 'element-plus';
-import { completeTask, backProcess, getTask, taskOperation, terminationTask, getBackTaskNode, currentTaskAllUser } from '@/api/workflow/task';
+import {
+  completeTask,
+  backProcess,
+  getTask,
+  taskOperation,
+  terminationTask,
+  getBackTaskNode,
+  currentTaskAllUser,
+  getNextNodeList
+} from '@/api/workflow/task';
 import UserSelect from '@/components/UserSelect';
 import UserSelect from '@/components/UserSelect';
 
 
 const { proxy } = getCurrentInstance() as ComponentInternalInstance;
 const { proxy } = getCurrentInstance() as ComponentInternalInstance;
@@ -117,6 +156,7 @@ const userSelectCopyRef = ref<InstanceType<typeof UserSelect>>();
 const transferTaskRef = ref<InstanceType<typeof UserSelect>>();
 const transferTaskRef = ref<InstanceType<typeof UserSelect>>();
 const delegateTaskRef = ref<InstanceType<typeof UserSelect>>();
 const delegateTaskRef = ref<InstanceType<typeof UserSelect>>();
 const multiInstanceUserRef = ref<InstanceType<typeof UserSelect>>();
 const multiInstanceUserRef = ref<InstanceType<typeof UserSelect>>();
+const porUserRef = ref<InstanceType<typeof UserSelect>>();
 
 
 const props = defineProps({
 const props = defineProps({
   taskVariables: {
   taskVariables: {
@@ -136,12 +176,28 @@ const selectCopyUserList = ref<UserVO[]>([]);
 const selectCopyUserIds = ref<string>(undefined);
 const selectCopyUserIds = ref<string>(undefined);
 //可减签的人员
 //可减签的人员
 const deleteUserList = ref<any>([]);
 const deleteUserList = ref<any>([]);
+//弹窗可选择的人员id
+const popUserIds = ref<any>([]);
 //驳回是否显示
 //驳回是否显示
 const backVisible = ref(false);
 const backVisible = ref(false);
 const backLoading = ref(true);
 const backLoading = ref(true);
 const backButtonDisabled = ref(true);
 const backButtonDisabled = ref(true);
 // 可驳回得任务节点
 // 可驳回得任务节点
 const taskNodeList = ref([]);
 const taskNodeList = ref([]);
+const nickName = ref({});
+//节点编码
+const nodeCode = ref<string>('');
+const buttonObj = ref<any>({
+  pop: false,
+  trust: false,
+  transfer: false,
+  addSign: false,
+  subSign: false,
+  termination: false,
+  back: false
+});
+//下一节点列表
+const nestNodeList = ref([]);
 //任务
 //任务
 const task = ref<FlowTaskVO>({
 const task = ref<FlowTaskVO>({
   id: undefined,
   id: undefined,
@@ -159,7 +215,9 @@ const task = ref<FlowTaskVO>({
   formCustom: undefined,
   formCustom: undefined,
   formPath: undefined,
   formPath: undefined,
   nodeType: undefined,
   nodeType: undefined,
-  nodeRatio: undefined
+  nodeRatio: undefined,
+  applyNode: false,
+  buttonList: []
 });
 });
 const dialog = reactive<DialogOption>({
 const dialog = reactive<DialogOption>({
   visible: false,
   visible: false,
@@ -170,6 +228,7 @@ const deleteSignatureVisible = ref(false);
 const form = ref<Record<string, any>>({
 const form = ref<Record<string, any>>({
   taskId: undefined,
   taskId: undefined,
   message: undefined,
   message: undefined,
+  assigneeMap: {},
   variables: {},
   variables: {},
   messageType: ['1'],
   messageType: ['1'],
   flowCopyList: []
   flowCopyList: []
@@ -181,8 +240,9 @@ const backForm = ref<Record<string, any>>({
   variables: {},
   variables: {},
   messageType: ['1']
   messageType: ['1']
 });
 });
+
 //打开弹窗
 //打开弹窗
-const openDialog = (id?: string) => {
+const openDialog = async (id?: string) => {
   selectCopyUserIds.value = undefined;
   selectCopyUserIds.value = undefined;
   selectCopyUserList.value = [];
   selectCopyUserList.value = [];
   form.value.fileId = undefined;
   form.value.fileId = undefined;
@@ -191,13 +251,20 @@ const openDialog = (id?: string) => {
   dialog.visible = true;
   dialog.visible = true;
   loading.value = true;
   loading.value = true;
   buttonDisabled.value = true;
   buttonDisabled.value = true;
-  nextTick(() => {
-    getTask(taskId.value).then((response) => {
-      task.value = response.data;
-      loading.value = false;
-      buttonDisabled.value = false;
-    });
+  const response = await getTask(taskId.value);
+  task.value = response.data;
+  buttonObj.value = {};
+  task.value.buttonList.forEach((e) => {
+    buttonObj.value[e.code] = e.show;
   });
   });
+  buttonDisabled.value = false;
+  const data = {
+    taskId: taskId.value,
+    variables: props.taskVariables
+  };
+  const nextData = await getNextNodeList(data);
+  nestNodeList.value = nextData.data;
+  loading.value = false;
 };
 };
 
 
 onMounted(() => {});
 onMounted(() => {});
@@ -207,10 +274,29 @@ const emits = defineEmits(['submitCallback', 'cancelCallback']);
 const handleCompleteTask = async () => {
 const handleCompleteTask = async () => {
   form.value.taskId = taskId.value;
   form.value.taskId = taskId.value;
   form.value.taskVariables = props.taskVariables;
   form.value.taskVariables = props.taskVariables;
+  let verify = false;
+  if (buttonObj.value.pop && nestNodeList.value && nestNodeList.value.length > 0) {
+    nestNodeList.value.forEach((e) => {
+      if (
+        Object.keys(form.value.assigneeMap).length === 0 ||
+        form.value.assigneeMap[e.nodeCode] === '' ||
+        form.value.assigneeMap[e.nodeCode] === null ||
+        form.value.assigneeMap[e.nodeCode] === undefined
+      ) {
+        verify = true;
+      }
+    });
+    if (verify) {
+      proxy?.$modal.msgWarning('请选择审批人!');
+      return false;
+    }
+  } else {
+    form.value.assigneeMap = {};
+  }
   if (selectCopyUserList.value && selectCopyUserList.value.length > 0) {
   if (selectCopyUserList.value && selectCopyUserList.value.length > 0) {
-    let flowCopyList = [];
+    const flowCopyList = [];
     selectCopyUserList.value.forEach((e) => {
     selectCopyUserList.value.forEach((e) => {
-      let copyUser = {
+      const copyUser = {
         userId: e.userId,
         userId: e.userId,
         userName: e.nickName
         userName: e.nickName
       };
       };
@@ -239,7 +325,7 @@ const handleBackProcessOpen = async () => {
   backVisible.value = true;
   backVisible.value = true;
   backLoading.value = true;
   backLoading.value = true;
   backButtonDisabled.value = true;
   backButtonDisabled.value = true;
-  let data = await getBackTaskNode(task.value.definitionId, task.value.nodeCode);
+  const data = await getBackTaskNode(task.value.definitionId, task.value.nodeCode);
   taskNodeList.value = data.data;
   taskNodeList.value = data.data;
   backLoading.value = false;
   backLoading.value = false;
   backButtonDisabled.value = false;
   backButtonDisabled.value = false;
@@ -266,6 +352,8 @@ const handleBackProcess = async () => {
 const cancel = async () => {
 const cancel = async () => {
   dialog.visible = false;
   dialog.visible = false;
   buttonDisabled.value = false;
   buttonDisabled.value = false;
+  nickName.value = {};
+  form.value.assigneeMap = {};
   emits('cancelCallback');
   emits('cancelCallback');
 };
 };
 //打开抄送人员
 //打开抄送人员
@@ -386,7 +474,7 @@ const handleDelegateTask = async (data) => {
 };
 };
 //终止任务
 //终止任务
 const handleTerminationTask = async () => {
 const handleTerminationTask = async () => {
-  let params = {
+  const params = {
     taskId: taskId.value,
     taskId: taskId.value,
     comment: form.value.message
     comment: form.value.message
   };
   };
@@ -402,7 +490,7 @@ const handleTerminationTask = async () => {
   proxy?.$modal.msgSuccess('操作成功');
   proxy?.$modal.msgSuccess('操作成功');
 };
 };
 const handleTaskUser = async () => {
 const handleTaskUser = async () => {
-  let data = await currentTaskAllUser(taskId.value);
+  const data = await currentTaskAllUser(taskId.value);
   deleteUserList.value = data.data;
   deleteUserList.value = data.data;
   if (deleteUserList.value && deleteUserList.value.length > 0) {
   if (deleteUserList.value && deleteUserList.value.length > 0) {
     deleteUserList.value.forEach((e) => {
     deleteUserList.value.forEach((e) => {
@@ -411,6 +499,26 @@ const handleTaskUser = async () => {
   }
   }
   deleteSignatureVisible.value = true;
   deleteSignatureVisible.value = true;
 };
 };
+// 选择人员
+const choosePeople = async (data) => {
+  if (!data.permissionFlag) {
+    proxy?.$modal.msgError('没有可选择的人员,请联系管理员!');
+  }
+  popUserIds.value = data.permissionFlag;
+  nodeCode.value = data.nodeCode;
+  porUserRef.value.open();
+};
+//确认选择
+const handlePopUser = async (userList) => {
+  const userIds = userList.map((item) => {
+    return item.userId;
+  });
+  const nickNames = userList.map((item) => {
+    return item.nickName;
+  });
+  form.value.assigneeMap[nodeCode.value] = userIds.join(',');
+  nickName.value[nodeCode.value] = nickNames.join(',');
+};
 
 
 /**
 /**
  * 对外暴露子组件方法
  * 对外暴露子组件方法

+ 1 - 1
src/components/RightToolbar/index.vue

@@ -16,7 +16,7 @@
               :data="columns"
               :data="columns"
               show-checkbox
               show-checkbox
               node-key="key"
               node-key="key"
-              :props="{ label: 'label', children: 'children' }"
+              :props="{ label: 'label', children: 'children' } as any"
               @check="columnChange"
               @check="columnChange"
             ></el-tree>
             ></el-tree>
             <template #reference>
             <template #reference>

+ 1 - 1
src/components/RuoYiDoc/index.vue

@@ -4,7 +4,7 @@
   </div>
   </div>
 </template>
 </template>
 
 
-<script setup>
+<script setup lang="ts">
 const url = ref('https://plus-doc.dromara.org/');
 const url = ref('https://plus-doc.dromara.org/');
 
 
 function goto() {
 function goto() {

+ 1 - 1
src/components/RuoYiGit/index.vue

@@ -4,7 +4,7 @@
   </div>
   </div>
 </template>
 </template>
 
 
-<script setup>
+<script setup lang="ts">
 const url = ref('https://gitee.com/dromara/RuoYi-Vue-Plus');
 const url = ref('https://gitee.com/dromara/RuoYi-Vue-Plus');
 
 
 function goto() {
 function goto() {

+ 1 - 1
src/components/SizeSelect/index.vue

@@ -16,7 +16,7 @@
 </template>
 </template>
 
 
 <script setup lang="ts">
 <script setup lang="ts">
-import useAppStore from '@/store/modules/app';
+import { useAppStore } from '@/store/modules/app';
 
 
 const appStore = useAppStore();
 const appStore = useAppStore();
 const size = computed(() => appStore.size);
 const size = computed(() => appStore.size);

+ 1 - 1
src/components/SvgIcon/index.vue

@@ -21,7 +21,7 @@ const svgClass = computed(() => {
 });
 });
 </script>
 </script>
 
 
-<style scope lang="scss">
+<style lang="scss" scoped>
 .sub-el-icon,
 .sub-el-icon,
 .nav-icon {
 .nav-icon {
   display: inline-block;
   display: inline-block;

+ 3 - 3
src/components/TopNav/index.vue

@@ -22,9 +22,9 @@
 <script setup lang="ts">
 <script setup lang="ts">
 import { constantRoutes } from '@/router';
 import { constantRoutes } from '@/router';
 import { isHttp } from '@/utils/validate';
 import { isHttp } from '@/utils/validate';
-import useAppStore from '@/store/modules/app';
-import useSettingsStore from '@/store/modules/settings';
-import usePermissionStore from '@/store/modules/permission';
+import { useAppStore } from '@/store/modules/app';
+import { useSettingsStore } from '@/store/modules/settings';
+import { usePermissionStore } from '@/store/modules/permission';
 import { RouteRecordRaw } from 'vue-router';
 import { RouteRecordRaw } from 'vue-router';
 
 
 // 顶部栏初始数
 // 顶部栏初始数

+ 2 - 2
src/components/TreeSelect/index.vue

@@ -6,7 +6,7 @@
       style="width: 100%"
       style="width: 100%"
       :filterable="true"
       :filterable="true"
       :clearable="true"
       :clearable="true"
-      :filter-method="selectFilterData"
+      :filter-method="selectFilterData as any"
       :placeholder="placeholder"
       :placeholder="placeholder"
       @clear="clearHandle"
       @clear="clearHandle"
     >
     >
@@ -16,7 +16,7 @@
           ref="selectTree"
           ref="selectTree"
           :accordion="accordion"
           :accordion="accordion"
           :data="options"
           :data="options"
-          :props="objMap"
+          :props="objMap as any"
           :node-key="objMap.value"
           :node-key="objMap.value"
           :expand-on-click-node="false"
           :expand-on-click-node="false"
           :default-expanded-keys="defaultExpandedKey"
           :default-expanded-keys="defaultExpandedKey"

+ 8 - 6
src/components/UserSelect/index.vue

@@ -11,7 +11,7 @@
               class="mt-2"
               class="mt-2"
               node-key="id"
               node-key="id"
               :data="deptOptions"
               :data="deptOptions"
-              :props="{ label: 'label', children: 'children' }"
+              :props="{ label: 'label', children: 'children' } as any"
               :expand-on-click-node="false"
               :expand-on-click-node="false"
               :filter-node-method="filterNode"
               :filter-node-method="filterNode"
               highlight-current
               highlight-current
@@ -108,11 +108,13 @@ interface PropType {
   modelValue?: UserVO[] | UserVO | undefined;
   modelValue?: UserVO[] | UserVO | undefined;
   multiple?: boolean;
   multiple?: boolean;
   data?: string | number | (string | number)[] | undefined;
   data?: string | number | (string | number)[] | undefined;
+  userIds?: string | number | (string | number)[] | undefined;
 }
 }
 const prop = withDefaults(defineProps<PropType>(), {
 const prop = withDefaults(defineProps<PropType>(), {
   multiple: true,
   multiple: true,
   modelValue: undefined,
   modelValue: undefined,
-  data: undefined
+  data: undefined,
+  userIds: undefined
 });
 });
 const emit = defineEmits(['update:modelValue', 'confirmCallBack']);
 const emit = defineEmits(['update:modelValue', 'confirmCallBack']);
 
 
@@ -143,7 +145,8 @@ const queryParams = ref<UserQuery>({
   phonenumber: '',
   phonenumber: '',
   status: '',
   status: '',
   deptId: '',
   deptId: '',
-  roleId: ''
+  roleId: '',
+  userIds: ''
 });
 });
 
 
 const defaultSelectUserIds = computed(() => computedIds(prop.data));
 const defaultSelectUserIds = computed(() => computedIds(prop.data));
@@ -166,7 +169,7 @@ const confirm = () => {
 
 
 const computedIds = (data) => {
 const computedIds = (data) => {
   if (data instanceof Array) {
   if (data instanceof Array) {
-    return data.map(item => String(item));
+    return data.map((item) => String(item));
   } else if (typeof data === 'string') {
   } else if (typeof data === 'string') {
     return data.split(',');
     return data.split(',');
   } else if (typeof data === 'number') {
   } else if (typeof data === 'number') {
@@ -192,6 +195,7 @@ const getTreeSelect = async () => {
 /** 查询用户列表 */
 /** 查询用户列表 */
 const getList = async () => {
 const getList = async () => {
   loading.value = true;
   loading.value = true;
+  queryParams.value.userIds = prop.userIds;
   const res = await api.listUser(proxy?.addDateRange(queryParams.value, dateRange.value));
   const res = await api.listUser(proxy?.addDateRange(queryParams.value, dateRange.value));
   loading.value = false;
   loading.value = false;
   userList.value = res.rows;
   userList.value = res.rows;
@@ -302,5 +306,3 @@ defineExpose({
   close: userDialog.closeDialog
   close: userDialog.closeDialog
 });
 });
 </script>
 </script>
-
-<style lang="scss" scoped></style>

+ 1 - 1
src/directive/permission/index.ts

@@ -1,5 +1,5 @@
 import { Directive, DirectiveBinding } from 'vue';
 import { Directive, DirectiveBinding } from 'vue';
-import useUserStore from '@/store/modules/user';
+import { useUserStore } from '@/store/modules/user';
 /**
 /**
  * 操作权限处理
  * 操作权限处理
  */
  */

+ 7 - 7
src/layout/components/AppMain.vue

@@ -1,12 +1,12 @@
 <template>
 <template>
   <section class="app-main">
   <section class="app-main">
     <router-view v-slot="{ Component, route }">
     <router-view v-slot="{ Component, route }">
-      <transition v-if="!route.meta.noCache" :enter-active-class="animante" mode="out-in">
+      <transition v-if="!route.meta.noCache" :enter-active-class="animate" mode="out-in">
         <keep-alive v-if="!route.meta.noCache" :include="tagsViewStore.cachedViews">
         <keep-alive v-if="!route.meta.noCache" :include="tagsViewStore.cachedViews">
           <component :is="Component" v-if="!route.meta.link" :key="route.path" />
           <component :is="Component" v-if="!route.meta.link" :key="route.path" />
         </keep-alive>
         </keep-alive>
       </transition>
       </transition>
-      <transition v-if="route.meta.noCache" :enter-active-class="animante" mode="out-in">
+      <transition v-if="route.meta.noCache" :enter-active-class="animate" mode="out-in">
         <component :is="Component" v-if="!route.meta.link && route.meta.noCache" :key="route.path" />
         <component :is="Component" v-if="!route.meta.link && route.meta.noCache" :key="route.path" />
       </transition>
       </transition>
     </router-view>
     </router-view>
@@ -15,8 +15,8 @@
 </template>
 </template>
 
 
 <script setup name="AppMain" lang="ts">
 <script setup name="AppMain" lang="ts">
-import useSettingsStore from '@/store/modules/settings';
-import useTagsViewStore from '@/store/modules/tagsView';
+import { useSettingsStore } from '@/store/modules/settings';
+import { useTagsViewStore } from '@/store/modules/tagsView';
 
 
 import IframeToggle from './IframeToggle/index.vue';
 import IframeToggle from './IframeToggle/index.vue';
 const { proxy } = getCurrentInstance() as ComponentInternalInstance;
 const { proxy } = getCurrentInstance() as ComponentInternalInstance;
@@ -24,16 +24,16 @@ const route = useRoute();
 const tagsViewStore = useTagsViewStore();
 const tagsViewStore = useTagsViewStore();
 
 
 // 随机动画集合
 // 随机动画集合
-const animante = ref<string>('');
+const animate = ref<string>('');
 const animationEnable = ref(useSettingsStore().animationEnable);
 const animationEnable = ref(useSettingsStore().animationEnable);
 watch(
 watch(
   () => useSettingsStore().animationEnable,
   () => useSettingsStore().animationEnable,
   (val: boolean) => {
   (val: boolean) => {
     animationEnable.value = val;
     animationEnable.value = val;
     if (val) {
     if (val) {
-      animante.value = proxy?.animate.animateList[Math.round(Math.random() * proxy?.animate.animateList.length)] as string;
+      animate.value = proxy?.animate.animateList[Math.round(Math.random() * proxy?.animate.animateList.length)] as string;
     } else {
     } else {
-      animante.value = proxy?.animate.defaultAnimate as string;
+      animate.value = proxy?.animate.defaultAnimate as string;
     }
     }
   },
   },
   { immediate: true }
   { immediate: true }

+ 1 - 1
src/layout/components/IframeToggle/index.vue

@@ -11,7 +11,7 @@
 <script setup lang="ts">
 <script setup lang="ts">
 import InnerLink from '../InnerLink/index.vue';
 import InnerLink from '../InnerLink/index.vue';
 
 
-import useTagsViewStore from '@/store/modules/tagsView';
+import { useTagsViewStore } from '@/store/modules/tagsView';
 
 
 const route = useRoute();
 const route = useRoute();
 const tagsViewStore = useTagsViewStore();
 const tagsViewStore = useTagsViewStore();

+ 10 - 9
src/layout/components/Navbar.vue

@@ -90,15 +90,16 @@
 
 
 <script setup lang="ts">
 <script setup lang="ts">
 import SearchMenu from './TopBar/search.vue';
 import SearchMenu from './TopBar/search.vue';
-import useAppStore from '@/store/modules/app';
-import useUserStore from '@/store/modules/user';
-import useSettingsStore from '@/store/modules/settings';
-import useNoticeStore from '@/store/modules/notice';
+import { useAppStore } from '@/store/modules/app';
+import { useUserStore } from '@/store/modules/user';
+import { useSettingsStore } from '@/store/modules/settings';
+import { useNoticeStore } from '@/store/modules/notice';
 import { getTenantList } from '@/api/login';
 import { getTenantList } from '@/api/login';
 import { dynamicClear, dynamicTenant } from '@/api/system/tenant';
 import { dynamicClear, dynamicTenant } from '@/api/system/tenant';
 import { TenantVO } from '@/api/types';
 import { TenantVO } from '@/api/types';
 import notice from './notice/index.vue';
 import notice from './notice/index.vue';
 import router from '@/router';
 import router from '@/router';
+import {ElMessageBoxOptions} from "element-plus/es/components/message-box/src/message-box.type";
 
 
 const appStore = useAppStore();
 const appStore = useAppStore();
 const userStore = useUserStore();
 const userStore = useUserStore();
@@ -128,8 +129,8 @@ const dynamicTenantEvent = async (tenantId: string) => {
     await dynamicTenant(tenantId);
     await dynamicTenant(tenantId);
     dynamic.value = true;
     dynamic.value = true;
     await proxy?.$router.push('/');
     await proxy?.$router.push('/');
-    await proxy?.proxy.$tab.closeAllPage();
-    await proxy?.proxy.$tab.refreshPage();
+    await proxy?.$tab.closeAllPage();
+    await proxy?.$tab.refreshPage();
   }
   }
 };
 };
 
 
@@ -137,8 +138,8 @@ const dynamicClearEvent = async () => {
   await dynamicClear();
   await dynamicClear();
   dynamic.value = false;
   dynamic.value = false;
   await proxy?.$router.push('/');
   await proxy?.$router.push('/');
-  await proxy?.proxy.$tab.closeAllPage();
-  await proxy?.proxy.$tab.refreshPage();
+  await proxy?.$tab.closeAllPage();
+  await proxy?.$tab.refreshPage();
 };
 };
 
 
 /** 租户列表 */
 /** 租户列表 */
@@ -163,7 +164,7 @@ const logout = async () => {
     confirmButtonText: '确定',
     confirmButtonText: '确定',
     cancelButtonText: '取消',
     cancelButtonText: '取消',
     type: 'warning'
     type: 'warning'
-  });
+  } as ElMessageBoxOptions);
   userStore.logout().then(() => {
   userStore.logout().then(() => {
     router.replace({
     router.replace({
       path: '/login',
       path: '/login',

+ 3 - 3
src/layout/components/Settings/index.vue

@@ -89,9 +89,9 @@
 
 
 <script setup lang="ts">
 <script setup lang="ts">
 import { useDynamicTitle } from '@/utils/dynamicTitle';
 import { useDynamicTitle } from '@/utils/dynamicTitle';
-import useAppStore from '@/store/modules/app';
-import useSettingsStore from '@/store/modules/settings';
-import usePermissionStore from '@/store/modules/permission';
+import { useAppStore } from '@/store/modules/app';
+import { useSettingsStore } from '@/store/modules/settings';
+import { usePermissionStore } from '@/store/modules/permission';
 import { handleThemeStyle } from '@/utils/theme';
 import { handleThemeStyle } from '@/utils/theme';
 import { SideThemeEnum } from '@/enums/SideThemeEnum';
 import { SideThemeEnum } from '@/enums/SideThemeEnum';
 import defaultSettings from '@/settings';
 import defaultSettings from '@/settings';

+ 1 - 1
src/layout/components/Sidebar/Logo.vue

@@ -24,7 +24,7 @@
 <script setup lang="ts">
 <script setup lang="ts">
 import variables from '@/assets/styles/variables.module.scss';
 import variables from '@/assets/styles/variables.module.scss';
 import logo from '@/assets/logo/logo.png';
 import logo from '@/assets/logo/logo.png';
-import useSettingsStore from '@/store/modules/settings';
+import { useSettingsStore } from '@/store/modules/settings';
 const { proxy } = getCurrentInstance() as ComponentInternalInstance;
 const { proxy } = getCurrentInstance() as ComponentInternalInstance;
 
 
 defineProps({
 defineProps({

+ 3 - 3
src/layout/components/Sidebar/index.vue

@@ -24,9 +24,9 @@
 import Logo from './Logo.vue';
 import Logo from './Logo.vue';
 import SidebarItem from './SidebarItem.vue';
 import SidebarItem from './SidebarItem.vue';
 import variables from '@/assets/styles/variables.module.scss';
 import variables from '@/assets/styles/variables.module.scss';
-import useAppStore from '@/store/modules/app';
-import useSettingsStore from '@/store/modules/settings';
-import usePermissionStore from '@/store/modules/permission';
+import { useAppStore } from '@/store/modules/app';
+import { useSettingsStore } from '@/store/modules/settings';
+import { usePermissionStore } from '@/store/modules/permission';
 import { RouteRecordRaw } from 'vue-router';
 import { RouteRecordRaw } from 'vue-router';
 
 
 const { proxy } = getCurrentInstance() as ComponentInternalInstance;
 const { proxy } = getCurrentInstance() as ComponentInternalInstance;

+ 1 - 1
src/layout/components/TagsView/ScrollPane.vue

@@ -6,7 +6,7 @@
 
 
 <script setup lang="ts">
 <script setup lang="ts">
 import { RouteLocationNormalized } from 'vue-router';
 import { RouteLocationNormalized } from 'vue-router';
-import useTagsViewStore from '@/store/modules/tagsView';
+import { useTagsViewStore } from '@/store/modules/tagsView';
 
 
 const tagAndTagSpacing = ref(4);
 const tagAndTagSpacing = ref(4);
 
 

+ 3 - 3
src/layout/components/TagsView/index.vue

@@ -32,9 +32,9 @@
 <script setup lang="ts">
 <script setup lang="ts">
 import ScrollPane from './ScrollPane.vue';
 import ScrollPane from './ScrollPane.vue';
 import { getNormalPath } from '@/utils/ruoyi';
 import { getNormalPath } from '@/utils/ruoyi';
-import useSettingsStore from '@/store/modules/settings';
-import usePermissionStore from '@/store/modules/permission';
-import useTagsViewStore from '@/store/modules/tagsView';
+import { useSettingsStore } from '@/store/modules/settings';
+import { usePermissionStore } from '@/store/modules/permission';
+import { useTagsViewStore } from '@/store/modules/tagsView';
 import { RouteRecordRaw, RouteLocationNormalized } from 'vue-router';
 import { RouteRecordRaw, RouteLocationNormalized } from 'vue-router';
 
 
 const visible = ref(false);
 const visible = ref(false);

+ 2 - 2
src/layout/components/TopBar/search.vue

@@ -28,7 +28,7 @@
 <script setup lang="ts" name="layoutBreadcrumbSearch">
 <script setup lang="ts" name="layoutBreadcrumbSearch">
 import { getNormalPath } from '@/utils/ruoyi';
 import { getNormalPath } from '@/utils/ruoyi';
 import { isHttp } from '@/utils/validate';
 import { isHttp } from '@/utils/validate';
-import usePermissionStore from '@/store/modules/permission';
+import { usePermissionStore } from '@/store/modules/permission';
 import { RouteRecordRaw } from 'vue-router';
 import { RouteRecordRaw } from 'vue-router';
 type Router = Array<{
 type Router = Array<{
   path: string;
   path: string;
@@ -130,7 +130,7 @@ defineExpose({
 });
 });
 </script>
 </script>
 
 
-<style scoped lang="scss">
+<style lang="scss" scoped>
 .layout-search-dialog {
 .layout-search-dialog {
   position: relative;
   position: relative;
   :deep(.el-dialog) {
   :deep(.el-dialog) {

+ 2 - 2
src/layout/components/notice/index.vue

@@ -25,7 +25,7 @@
 
 
 <script setup lang="ts" name="layoutBreadcrumbUserNews">
 <script setup lang="ts" name="layoutBreadcrumbUserNews">
 import { storeToRefs } from 'pinia';
 import { storeToRefs } from 'pinia';
-import useNoticeStore from '@/store/modules/notice';
+import { useNoticeStore } from '@/store/modules/notice';
 
 
 const noticeStore = storeToRefs(useNoticeStore());
 const noticeStore = storeToRefs(useNoticeStore());
 const { readAll } = useNoticeStore();
 const { readAll } = useNoticeStore();
@@ -65,7 +65,7 @@ onMounted(() => {
 });
 });
 </script>
 </script>
 
 
-<style scoped lang="scss">
+<style lang="scss" scoped>
 .layout-navbars-breadcrumb-user-news {
 .layout-navbars-breadcrumb-user-news {
   .head-box {
   .head-box {
     display: flex;
     display: flex;

+ 6 - 6
src/layout/index.vue

@@ -24,8 +24,8 @@
 <script setup lang="ts">
 <script setup lang="ts">
 import SideBar from './components/Sidebar/index.vue';
 import SideBar from './components/Sidebar/index.vue';
 import { AppMain, Navbar, Settings, TagsView } from './components';
 import { AppMain, Navbar, Settings, TagsView } from './components';
-import useAppStore from '@/store/modules/app';
-import useSettingsStore from '@/store/modules/settings';
+import { useAppStore } from '@/store/modules/app';
+import { useSettingsStore } from '@/store/modules/settings';
 import { initWebSocket } from '@/utils/websocket';
 import { initWebSocket } from '@/utils/websocket';
 import { initSSE } from '@/utils/sse';
 import { initSSE } from '@/utils/sse';
 
 
@@ -68,7 +68,7 @@ onMounted(() => {
 });
 });
 
 
 onMounted(() => {
 onMounted(() => {
-  let protocol = window.location.protocol === 'https:' ? 'wss://' : 'ws://';
+  const protocol = window.location.protocol === 'https:' ? 'wss://' : 'ws://';
   initWebSocket(protocol + window.location.host + import.meta.env.VITE_APP_BASE_API + '/resource/websocket');
   initWebSocket(protocol + window.location.host + import.meta.env.VITE_APP_BASE_API + '/resource/websocket');
 });
 });
 
 
@@ -86,11 +86,11 @@ const setLayout = () => {
 </script>
 </script>
 
 
 <style lang="scss" scoped>
 <style lang="scss" scoped>
-@import '@/assets/styles/mixin.scss';
-@import '@/assets/styles/variables.module.scss';
+@use '@/assets/styles/mixin.scss';
+@use '@/assets/styles/variables.module.scss' as *;
 
 
 .app-wrapper {
 .app-wrapper {
-  @include clearfix;
+  @include mixin.clearfix;
   position: relative;
   position: relative;
   height: 100%;
   height: 100%;
   width: 100%;
   width: 100%;

+ 5 - 4
src/permission.ts

@@ -5,9 +5,10 @@ import 'nprogress/nprogress.css';
 import { getToken } from '@/utils/auth';
 import { getToken } from '@/utils/auth';
 import { isHttp, isPathMatch } from '@/utils/validate';
 import { isHttp, isPathMatch } from '@/utils/validate';
 import { isRelogin } from '@/utils/request';
 import { isRelogin } from '@/utils/request';
-import useUserStore from '@/store/modules/user';
-import useSettingsStore from '@/store/modules/settings';
-import usePermissionStore from '@/store/modules/permission';
+import { useUserStore } from '@/store/modules/user';
+import { useSettingsStore } from '@/store/modules/settings';
+import { usePermissionStore } from '@/store/modules/permission';
+import { ElMessage } from 'element-plus/es';
 
 
 NProgress.configure({ showSpinner: false });
 NProgress.configure({ showSpinner: false });
 const whiteList = ['/login', '/register', '/social-callback', '/register*', '/register/*'];
 const whiteList = ['/login', '/register', '/social-callback', '/register*', '/register/*'];
@@ -19,7 +20,7 @@ const isWhiteList = (path: string) => {
 router.beforeEach(async (to, from, next) => {
 router.beforeEach(async (to, from, next) => {
   NProgress.start();
   NProgress.start();
   if (getToken()) {
   if (getToken()) {
-    to.meta.title && useSettingsStore().setTitle(to.meta.title);
+    to.meta.title && useSettingsStore().setTitle(to.meta.title as string);
     /* has token*/
     /* has token*/
     if (to.path === '/login') {
     if (to.path === '/login') {
       next({ path: '/' });
       next({ path: '/' });

+ 1 - 1
src/plugins/auth.ts

@@ -1,4 +1,4 @@
-import useUserStore from '@/store/modules/user';
+import { useUserStore } from '@/store/modules/user';
 
 
 const authPermission = (permission: string): boolean => {
 const authPermission = (permission: string): boolean => {
   const all_permission = '*:*:*';
   const all_permission = '*:*:*';

+ 1 - 1
src/plugins/tab.ts

@@ -1,6 +1,6 @@
 import router from '@/router';
 import router from '@/router';
 import { RouteLocationMatched, RouteLocationNormalized, RouteLocationRaw } from 'vue-router';
 import { RouteLocationMatched, RouteLocationNormalized, RouteLocationRaw } from 'vue-router';
-import useTagsViewStore from '@/store/modules/tagsView';
+import { useTagsViewStore } from '@/store/modules/tagsView';
 
 
 export default {
 export default {
   /**
   /**

+ 16 - 0
src/settings.ts

@@ -50,13 +50,29 @@ const setting: DefaultSettings = {
    */
    */
   errorLog: 'production',
   errorLog: 'production',
 
 
+  /**
+   * 是否开启动画 开启随机 关闭渐进渐出
+   */
   animationEnable: false,
   animationEnable: false,
 
 
+  /**
+   * 是否暗黑模式
+   */
   dark: false,
   dark: false,
+
+  /**
+   * 默认语言
+   */
   language: LanguageEnum.zh_CN,
   language: LanguageEnum.zh_CN,
 
 
+  /**
+   * 默认大小
+   */
   size: 'default',
   size: 'default',
 
 
+  /**
+   * 默认布局
+   */
   layout: ''
   layout: ''
 };
 };
 export default setting;
 export default setting;

+ 2 - 0
src/store/index.ts

@@ -1,3 +1,5 @@
+import { createPinia } from "pinia";
+
 const store = createPinia();
 const store = createPinia();
 
 
 export default store;
 export default store;

+ 3 - 2
src/store/modules/app.ts

@@ -1,5 +1,8 @@
 import zhCN from 'element-plus/es/locale/lang/zh-cn';
 import zhCN from 'element-plus/es/locale/lang/zh-cn';
 import enUS from 'element-plus/es/locale/lang/en';
 import enUS from 'element-plus/es/locale/lang/en';
+import { defineStore } from 'pinia';
+import { useStorage } from '@vueuse/core';
+import { ref, reactive, computed } from 'vue';
 
 
 export const useAppStore = defineStore('app', () => {
 export const useAppStore = defineStore('app', () => {
   const sidebarStatus = useStorage('sidebarStatus', '1');
   const sidebarStatus = useStorage('sidebarStatus', '1');
@@ -68,5 +71,3 @@ export const useAppStore = defineStore('app', () => {
     toggleSideBarHide
     toggleSideBarHide
   };
   };
 });
 });
-
-export default useAppStore;

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

@@ -1,3 +1,5 @@
+import { defineStore } from 'pinia';
+
 export const useDictStore = defineStore('dict', () => {
 export const useDictStore = defineStore('dict', () => {
   const dict = ref<Map<string, DictDataOption[]>>(new Map());
   const dict = ref<Map<string, DictDataOption[]>>(new Map());
 
 
@@ -61,5 +63,3 @@ export const useDictStore = defineStore('dict', () => {
     cleanDict
     cleanDict
   };
   };
 });
 });
-
-export default useDictStore;

+ 1 - 2
src/store/modules/notice.ts

@@ -1,4 +1,5 @@
 import { defineStore } from 'pinia';
 import { defineStore } from 'pinia';
+import { reactive } from 'vue';
 
 
 interface NoticeItem {
 interface NoticeItem {
   title?: string;
   title?: string;
@@ -38,5 +39,3 @@ export const useNoticeStore = defineStore('notice', () => {
     clearNotice
     clearNotice
   };
   };
 });
 });
-
-export default useNoticeStore;

+ 12 - 26
src/store/modules/permission.ts

@@ -4,11 +4,10 @@ import store from '@/store';
 import { getRouters } from '@/api/menu';
 import { getRouters } from '@/api/menu';
 import auth from '@/plugins/auth';
 import auth from '@/plugins/auth';
 import { RouteRecordRaw } from 'vue-router';
 import { RouteRecordRaw } from 'vue-router';
-
 import Layout from '@/layout/index.vue';
 import Layout from '@/layout/index.vue';
 import ParentView from '@/components/ParentView/index.vue';
 import ParentView from '@/components/ParentView/index.vue';
 import InnerLink from '@/layout/components/InnerLink/index.vue';
 import InnerLink from '@/layout/components/InnerLink/index.vue';
-
+import { ref } from 'vue';
 import { createCustomNameComponent } from '@/utils/createCustomNameComponent';
 import { createCustomNameComponent } from '@/utils/createCustomNameComponent';
 
 
 // 匹配views里面所有的.vue文件
 // 匹配views里面所有的.vue文件
@@ -23,6 +22,9 @@ export const usePermissionStore = defineStore('permission', () => {
   const getRoutes = (): RouteRecordRaw[] => {
   const getRoutes = (): RouteRecordRaw[] => {
     return routes.value as RouteRecordRaw[];
     return routes.value as RouteRecordRaw[];
   };
   };
+  const getDefaultRoutes = (): RouteRecordRaw[] => {
+    return defaultRoutes.value as RouteRecordRaw[];
+  };
   const getSidebarRoutes = (): RouteRecordRaw[] => {
   const getSidebarRoutes = (): RouteRecordRaw[] => {
     return sidebarRouters.value as RouteRecordRaw[];
     return sidebarRouters.value as RouteRecordRaw[];
   };
   };
@@ -97,29 +99,14 @@ export const usePermissionStore = defineStore('permission', () => {
   };
   };
   const filterChildren = (childrenMap: RouteRecordRaw[], lastRouter?: RouteRecordRaw): RouteRecordRaw[] => {
   const filterChildren = (childrenMap: RouteRecordRaw[], lastRouter?: RouteRecordRaw): RouteRecordRaw[] => {
     let children: RouteRecordRaw[] = [];
     let children: RouteRecordRaw[] = [];
-    childrenMap.forEach((el) => {
-      if (el.children && el.children.length) {
-        if (el.component?.toString() === 'ParentView' && !lastRouter) {
-          el.children.forEach((c) => {
-            c.path = el.path + '/' + c.path;
-            if (c.children && c.children.length) {
-              children = children.concat(filterChildren(c.children, c));
-              return;
-            }
-            children.push(c);
-          });
-          return;
-        }
-      }
-      if (lastRouter) {
-        el.path = lastRouter.path + '/' + el.path;
-        if (el.children && el.children.length) {
-          children = children.concat(filterChildren(el.children, el));
-          return;
-        }
+    childrenMap.forEach(el => {
+      el.path = lastRouter ? lastRouter.path + '/' + el.path : el.path;
+      if (el.children && el.children.length && el.component?.toString() === 'ParentView') {
+        children = children.concat(filterChildren(el.children, el));
+      } else {
+        children.push(el);
       }
       }
-      children = children.concat(el);
-    });
+    })
     return children;
     return children;
   };
   };
   return {
   return {
@@ -129,6 +116,7 @@ export const usePermissionStore = defineStore('permission', () => {
     defaultRoutes,
     defaultRoutes,
 
 
     getRoutes,
     getRoutes,
+    getDefaultRoutes,
     getSidebarRoutes,
     getSidebarRoutes,
     getTopbarRoutes,
     getTopbarRoutes,
 
 
@@ -217,5 +205,3 @@ function duplicateRouteChecker(localRoutes: Route[], routes: Route[]) {
     nameList.push(route.name.toString());
     nameList.push(route.name.toString());
   });
   });
 }
 }
-
-export default usePermissionStore;

+ 3 - 2
src/store/modules/settings.ts

@@ -1,8 +1,11 @@
 import { defineStore } from 'pinia';
 import { defineStore } from 'pinia';
 import defaultSettings from '@/settings';
 import defaultSettings from '@/settings';
 import { useDynamicTitle } from '@/utils/dynamicTitle';
 import { useDynamicTitle } from '@/utils/dynamicTitle';
+import { useStorage } from '@vueuse/core';
+import { ref } from 'vue';
 
 
 export const useSettingsStore = defineStore('setting', () => {
 export const useSettingsStore = defineStore('setting', () => {
+  // @ts-ignore
   const storageSetting = useStorage<LayoutSetting>('layout-setting', {
   const storageSetting = useStorage<LayoutSetting>('layout-setting', {
     topNav: defaultSettings.topNav,
     topNav: defaultSettings.topNav,
     tagsView: defaultSettings.tagsView,
     tagsView: defaultSettings.tagsView,
@@ -43,5 +46,3 @@ export const useSettingsStore = defineStore('setting', () => {
     setTitle
     setTitle
   };
   };
 });
 });
-
-export default useSettingsStore;

+ 2 - 1
src/store/modules/tagsView.ts

@@ -1,4 +1,6 @@
 import { RouteLocationNormalized } from 'vue-router';
 import { RouteLocationNormalized } from 'vue-router';
+import { defineStore } from 'pinia';
+import { ref } from 'vue';
 
 
 export const useTagsViewStore = defineStore('tagsView', () => {
 export const useTagsViewStore = defineStore('tagsView', () => {
   const visitedViews = ref<RouteLocationNormalized[]>([]);
   const visitedViews = ref<RouteLocationNormalized[]>([]);
@@ -230,4 +232,3 @@ export const useTagsViewStore = defineStore('tagsView', () => {
     delIframeView
     delIframeView
   };
   };
 });
 });
-export default useTagsViewStore;

+ 2 - 7
src/store/modules/user.ts

@@ -3,7 +3,8 @@ import { getToken, removeToken, setToken } from '@/utils/auth';
 import { login as loginApi, logout as logoutApi, getInfo as getUserInfo } from '@/api/login';
 import { login as loginApi, logout as logoutApi, getInfo as getUserInfo } from '@/api/login';
 import { LoginData } from '@/api/types';
 import { LoginData } from '@/api/types';
 import defAva from '@/assets/images/profile.jpg';
 import defAva from '@/assets/images/profile.jpg';
-import store from '@/store';
+import { defineStore } from 'pinia';
+import { ref } from 'vue';
 
 
 export const useUserStore = defineStore('user', () => {
 export const useUserStore = defineStore('user', () => {
   const token = ref(getToken());
   const token = ref(getToken());
@@ -83,9 +84,3 @@ export const useUserStore = defineStore('user', () => {
     setAvatar
     setAvatar
   };
   };
 });
 });
-
-export default useUserStore;
-// 非setup
-export function useUserStoreHook() {
-  return useUserStore(store);
-}

+ 1 - 1
src/utils/permission.ts

@@ -1,4 +1,4 @@
-import useUserStore from '@/store/modules/user';
+import { useUserStore } from '@/store/modules/user';
 
 
 /**
 /**
  * 字符权限校验
  * 字符权限校验

+ 6 - 24
src/utils/ruoyi.ts

@@ -167,39 +167,21 @@ export const handleTree = <T>(data: any[], id?: string, parentId?: string, child
   };
   };
 
 
   const childrenListMap: any = {};
   const childrenListMap: any = {};
-  const nodeIds: any = {};
   const tree: T[] = [];
   const tree: T[] = [];
-
   for (const d of data) {
   for (const d of data) {
-    const parentId = d[config.parentId];
-    if (childrenListMap[parentId] == null) {
-      childrenListMap[parentId] = [];
-    }
-    nodeIds[d[config.id]] = d;
-    childrenListMap[parentId].push(d);
+    const id = d[config.id];
+    childrenListMap[id] = d;
   }
   }
 
 
   for (const d of data) {
   for (const d of data) {
     const parentId = d[config.parentId];
     const parentId = d[config.parentId];
-    if (nodeIds[parentId] == null) {
+    const parentObj = childrenListMap[parentId]
+    if (!parentObj) {
       tree.push(d);
       tree.push(d);
+    } else {
+      parentObj[config.childrenList].push(d)
     }
     }
   }
   }
-  const adaptToChildrenList = (o: any) => {
-    if (childrenListMap[o[config.id]] !== null) {
-      o[config.childrenList] = childrenListMap[o[config.id]];
-    }
-    if (o[config.childrenList]) {
-      for (const c of o[config.childrenList]) {
-        adaptToChildrenList(c);
-      }
-    }
-  };
-
-  for (const t of tree) {
-    adaptToChildrenList(t);
-  }
-
   return tree;
   return tree;
 };
 };
 
 

+ 1 - 1
src/utils/sse.ts

@@ -1,6 +1,6 @@
 import { getToken } from '@/utils/auth';
 import { getToken } from '@/utils/auth';
 import { ElNotification } from 'element-plus';
 import { ElNotification } from 'element-plus';
-import useNoticeStore from '@/store/modules/notice';
+import { useNoticeStore } from '@/store/modules/notice';
 
 
 // 初始化
 // 初始化
 export const initSSE = (url: any) => {
 export const initSSE = (url: any) => {

+ 1 - 1
src/utils/websocket.ts

@@ -1,6 +1,6 @@
 import { getToken } from '@/utils/auth';
 import { getToken } from '@/utils/auth';
 import { ElNotification } from 'element-plus';
 import { ElNotification } from 'element-plus';
-import useNoticeStore from '@/store/modules/notice';
+import { useNoticeStore } from '@/store/modules/notice';
 
 
 // 初始化socket
 // 初始化socket
 export const initWebSocket = (url: any) => {
 export const initWebSocket = (url: any) => {

+ 1 - 1
src/views/demo/tree/index.vue

@@ -62,7 +62,7 @@
           <el-tree-select
           <el-tree-select
             v-model="form.parentId"
             v-model="form.parentId"
             :data="treeOptions"
             :data="treeOptions"
-            :props="{ value: 'id', label: 'treeName', children: 'children' }"
+            :props="{ value: 'id', label: 'treeName', children: 'children' } as any"
             value-key="id"
             value-key="id"
             placeholder="请选择父id"
             placeholder="请选择父id"
             check-strictly
             check-strictly

+ 2 - 2
src/views/index.vue

@@ -33,7 +33,7 @@
           * 部署方式 Docker 容器编排 一键部署业务集群<br />
           * 部署方式 Docker 容器编排 一键部署业务集群<br />
           * 国际化 SpringMessage Spring标准国际化方案<br />
           * 国际化 SpringMessage Spring标准国际化方案<br />
         </p>
         </p>
-        <p><b>当前版本:</b> <span>v5.3.0</span></p>
+        <p><b>当前版本:</b> <span>v5.3.1</span></p>
         <p>
         <p>
           <el-tag type="danger">&yen;免费开源</el-tag>
           <el-tag type="danger">&yen;免费开源</el-tag>
         </p>
         </p>
@@ -100,7 +100,7 @@ const goTarget = (url: string) => {
 };
 };
 </script>
 </script>
 
 
-<style scoped lang="scss">
+<style lang="scss" scoped>
 .home {
 .home {
   blockquote {
   blockquote {
     padding: 10px 20px;
     padding: 10px 20px;

+ 1 - 1
src/views/login.vue

@@ -73,7 +73,7 @@
     </el-form>
     </el-form>
     <!--  底部  -->
     <!--  底部  -->
     <div class="el-login-footer">
     <div class="el-login-footer">
-      <span>Copyright © 2018-2024 疯狂的狮子Li All Rights Reserved.</span>
+      <span>Copyright © 2018-2025 疯狂的狮子Li All Rights Reserved.</span>
     </div>
     </div>
   </div>
   </div>
 </template>
 </template>

+ 1 - 1
src/views/monitor/cache/index.vue

@@ -1,6 +1,6 @@
 <template>
 <template>
   <div class="p-2">
   <div class="p-2">
-    <el-row>
+    <el-row :gutter="10">
       <el-col :span="24" class="card-box">
       <el-col :span="24" class="card-box">
         <el-card shadow="hover">
         <el-card shadow="hover">
           <template #header>
           <template #header>

+ 1 - 1
src/views/monitor/operlog/oper-info-dialog.vue

@@ -95,7 +95,7 @@ const typeFormat = (row: OperLogForm) => {
 };
 };
 </script>
 </script>
 
 
-<style scoped>
+<style lang="scss" scoped>
 /**
 /**
 label宽度固定
 label宽度固定
 */
 */

+ 1 - 1
src/views/redirect/index.vue

@@ -2,7 +2,7 @@
   <div></div>
   <div></div>
 </template>
 </template>
 
 
-<script setup>
+<script setup lang="ts">
 import { useRoute, useRouter } from 'vue-router';
 import { useRoute, useRouter } from 'vue-router';
 
 
 const route = useRoute();
 const route = useRoute();

+ 1 - 1
src/views/register.vue

@@ -67,7 +67,7 @@
     </el-form>
     </el-form>
     <!--  底部  -->
     <!--  底部  -->
     <div class="el-register-footer">
     <div class="el-register-footer">
-      <span>Copyright © 2018-2024 疯狂的狮子Li All Rights Reserved.</span>
+      <span>Copyright © 2018-2025 疯狂的狮子Li All Rights Reserved.</span>
     </div>
     </div>
   </div>
   </div>
 </template>
 </template>

+ 1 - 1
src/views/system/client/index.vue

@@ -2,7 +2,7 @@
   <div class="p-2">
   <div class="p-2">
     <transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
     <transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
       <div v-show="showSearch" class="search">
       <div v-show="showSearch" class="search">
-        <el-form ref="queryFormRef" :model="queryParams" :inline="true">
+        <el-form ref="queryFormRef" :model="queryParams" :inline="true" label-width="85px">
           <el-form-item label="客户端key" prop="clientKey">
           <el-form-item label="客户端key" prop="clientKey">
             <el-input v-model="queryParams.clientKey" placeholder="请输入客户端key" clearable @keyup.enter="handleQuery" />
             <el-input v-model="queryParams.clientKey" placeholder="请输入客户端key" clearable @keyup.enter="handleQuery" />
           </el-form-item>
           </el-form-item>

+ 1 - 1
src/views/system/dept/index.vue

@@ -82,7 +82,7 @@
               <el-tree-select
               <el-tree-select
                 v-model="form.parentId"
                 v-model="form.parentId"
                 :data="deptOptions"
                 :data="deptOptions"
-                :props="{ value: 'deptId', label: 'deptName', children: 'children' }"
+                :props="{ value: 'deptId', label: 'deptName', children: 'children' } as any"
                 value-key="deptId"
                 value-key="deptId"
                 placeholder="选择上级部门"
                 placeholder="选择上级部门"
                 check-strictly
                 check-strictly

+ 1 - 1
src/views/system/dict/data.vue

@@ -126,7 +126,7 @@
 </template>
 </template>
 
 
 <script setup name="Data" lang="ts">
 <script setup name="Data" lang="ts">
-import useDictStore from '@/store/modules/dict';
+import { useDictStore } from '@/store/modules/dict';
 import { optionselect as getDictOptionselect, getType } from '@/api/system/dict/type';
 import { optionselect as getDictOptionselect, getType } from '@/api/system/dict/type';
 import { listData, getData, delData, addData, updateData } from '@/api/system/dict/data';
 import { listData, getData, delData, addData, updateData } from '@/api/system/dict/data';
 import { DictTypeVO } from '@/api/system/dict/type/types';
 import { DictTypeVO } from '@/api/system/dict/type/types';

+ 1 - 1
src/views/system/dict/index.vue

@@ -108,7 +108,7 @@
 </template>
 </template>
 
 
 <script setup name="Dict" lang="ts">
 <script setup name="Dict" lang="ts">
-import useDictStore from '@/store/modules/dict';
+import { useDictStore } from '@/store/modules/dict';
 import { listType, getType, delType, addType, updateType, refreshCache } from '@/api/system/dict/type';
 import { listType, getType, delType, addType, updateType, refreshCache } from '@/api/system/dict/type';
 import { DictTypeForm, DictTypeQuery, DictTypeVO } from '@/api/system/dict/type/types';
 import { DictTypeForm, DictTypeQuery, DictTypeVO } from '@/api/system/dict/type/types';
 
 

+ 1 - 1
src/views/system/menu/index.vue

@@ -85,7 +85,7 @@
               <el-tree-select
               <el-tree-select
                 v-model="form.parentId"
                 v-model="form.parentId"
                 :data="menuOptions"
                 :data="menuOptions"
-                :props="{ value: 'menuId', label: 'menuName', children: 'children' }"
+                :props="{ value: 'menuId', label: 'menuName', children: 'children' } as any"
                 value-key="menuId"
                 value-key="menuId"
                 placeholder="选择上级菜单"
                 placeholder="选择上级菜单"
                 check-strictly
                 check-strictly

+ 3 - 3
src/views/system/post/index.vue

@@ -10,7 +10,7 @@
             class="mt-2"
             class="mt-2"
             node-key="id"
             node-key="id"
             :data="deptOptions"
             :data="deptOptions"
-            :props="{ label: 'label', children: 'children' }"
+            :props="{ label: 'label', children: 'children' } as any"
             :expand-on-click-node="false"
             :expand-on-click-node="false"
             :filter-node-method="filterNode"
             :filter-node-method="filterNode"
             highlight-current
             highlight-current
@@ -43,7 +43,7 @@
                   <el-tree-select
                   <el-tree-select
                     v-model="queryParams.deptId"
                     v-model="queryParams.deptId"
                     :data="deptOptions"
                     :data="deptOptions"
-                    :props="{ value: 'id', label: 'label', children: 'children' }"
+                    :props="{ value: 'id', label: 'label', children: 'children' } as any"
                     value-key="id"
                     value-key="id"
                     placeholder="请选择部门"
                     placeholder="请选择部门"
                     check-strictly
                     check-strictly
@@ -133,7 +133,7 @@
               <el-tree-select
               <el-tree-select
                 v-model="form.deptId"
                 v-model="form.deptId"
                 :data="deptOptions"
                 :data="deptOptions"
-                :props="{ value: 'id', label: 'label', children: 'children' }"
+                :props="{ value: 'id', label: 'label', children: 'children' } as any"
                 value-key="id"
                 value-key="id"
                 placeholder="请选择部门"
                 placeholder="请选择部门"
                 check-strictly
                 check-strictly

+ 0 - 2
src/views/system/role/authUser.vue

@@ -156,5 +156,3 @@ onMounted(() => {
   getList();
   getList();
 });
 });
 </script>
 </script>
-
-<style lang="scss" scoped></style>

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

@@ -135,7 +135,7 @@
             node-key="id"
             node-key="id"
             :check-strictly="!form.menuCheckStrictly"
             :check-strictly="!form.menuCheckStrictly"
             empty-text="加载中,请稍候"
             empty-text="加载中,请稍候"
-            :props="{ label: 'label', children: 'children' }"
+            :props="{ label: 'label', children: 'children' } as any"
           ></el-tree>
           ></el-tree>
         </el-form-item>
         </el-form-item>
         <el-form-item label="备注">
         <el-form-item label="备注">
@@ -177,7 +177,7 @@
             node-key="id"
             node-key="id"
             :check-strictly="!form.deptCheckStrictly"
             :check-strictly="!form.deptCheckStrictly"
             empty-text="加载中,请稍候"
             empty-text="加载中,请稍候"
-            :props="{ label: 'label', children: 'children' }"
+            :props="{ label: 'label', children: 'children' } as any"
           ></el-tree>
           ></el-tree>
         </el-form-item>
         </el-form-item>
       </el-form>
       </el-form>

+ 0 - 2
src/views/system/role/selectUser.vue

@@ -128,5 +128,3 @@ defineExpose({
   show
   show
 });
 });
 </script>
 </script>
-
-<style scoped></style>

+ 1 - 1
src/views/system/tenant/index.vue

@@ -155,7 +155,7 @@ import {
   syncTenantDict
   syncTenantDict
 } from '@/api/system/tenant';
 } from '@/api/system/tenant';
 import { selectTenantPackage } from '@/api/system/tenantPackage';
 import { selectTenantPackage } from '@/api/system/tenantPackage';
-import useUserStore from '@/store/modules/user';
+import { useUserStore } from '@/store/modules/user';
 import { TenantForm, TenantQuery, TenantVO } from '@/api/system/tenant/types';
 import { TenantForm, TenantQuery, TenantVO } from '@/api/system/tenant/types';
 import { TenantPkgVO } from '@/api/system/tenantPackage/types';
 import { TenantPkgVO } from '@/api/system/tenantPackage/types';
 
 

+ 1 - 1
src/views/system/tenantPackage/index.vue

@@ -82,7 +82,7 @@
             node-key="id"
             node-key="id"
             :check-strictly="!form.menuCheckStrictly"
             :check-strictly="!form.menuCheckStrictly"
             empty-text="加载中,请稍候"
             empty-text="加载中,请稍候"
-            :props="{ label: 'label', children: 'children' }"
+            :props="{ label: 'label', children: 'children' } as any"
           ></el-tree>
           ></el-tree>
         </el-form-item>
         </el-form-item>
         <el-form-item label="备注" prop="remark">
         <el-form-item label="备注" prop="remark">

+ 9 - 8
src/views/system/user/index.vue

@@ -10,7 +10,7 @@
             class="mt-2"
             class="mt-2"
             node-key="id"
             node-key="id"
             :data="deptOptions"
             :data="deptOptions"
-            :props="{ label: 'label', children: 'children' }"
+            :props="{ label: 'label', children: 'children' } as any"
             :expand-on-click-node="false"
             :expand-on-click-node="false"
             :filter-node-method="filterNode"
             :filter-node-method="filterNode"
             highlight-current
             highlight-current
@@ -81,8 +81,9 @@
                   <template #dropdown>
                   <template #dropdown>
                     <el-dropdown-menu>
                     <el-dropdown-menu>
                       <el-dropdown-item icon="Download" @click="importTemplate">下载模板</el-dropdown-item>
                       <el-dropdown-item icon="Download" @click="importTemplate">下载模板</el-dropdown-item>
-                      <el-dropdown-item v-has-permi="['system:user:import']" icon="Top" @click="handleImport">导入数据</el-dropdown-item>
-                      <el-dropdown-item v-has-permi="['system:user:export']" icon="Download" @click="handleExport">导出数据</el-dropdown-item>
+                      <!-- 注意 由于el-dropdown-item标签是延迟加载的 所以v-has-permi自定义标签不生效 需要使用v-if调用方法执行 -->
+                      <el-dropdown-item v-if="checkPermi(['system:user:import'])" icon="Top" @click="handleImport">导入数据</el-dropdown-item>
+                      <el-dropdown-item v-if="checkPermi(['system:user:export'])" icon="Download" @click="handleExport">导出数据</el-dropdown-item>
                     </el-dropdown-menu>
                     </el-dropdown-menu>
                   </template>
                   </template>
                 </el-dropdown>
                 </el-dropdown>
@@ -155,7 +156,7 @@
               <el-tree-select
               <el-tree-select
                 v-model="form.deptId"
                 v-model="form.deptId"
                 :data="enabledDeptOptions"
                 :data="enabledDeptOptions"
-                :props="{ value: 'id', label: 'label', children: 'children' }"
+                :props="{ value: 'id', label: 'label', children: 'children' } as any"
                 value-key="id"
                 value-key="id"
                 placeholder="请选择归属部门"
                 placeholder="请选择归属部门"
                 check-strictly
                 check-strictly
@@ -287,13 +288,15 @@
 <script setup name="User" lang="ts">
 <script setup name="User" lang="ts">
 import api from '@/api/system/user';
 import api from '@/api/system/user';
 import { UserForm, UserQuery, UserVO } from '@/api/system/user/types';
 import { UserForm, UserQuery, UserVO } from '@/api/system/user/types';
-import {DeptTreeVO, DeptVO} from '@/api/system/dept/types';
+import { DeptTreeVO, DeptVO } from '@/api/system/dept/types';
 import { RoleVO } from '@/api/system/role/types';
 import { RoleVO } from '@/api/system/role/types';
 import { PostQuery, PostVO } from '@/api/system/post/types';
 import { PostQuery, PostVO } from '@/api/system/post/types';
 import { treeselect } from '@/api/system/dept';
 import { treeselect } from '@/api/system/dept';
 import { globalHeaders } from '@/utils/request';
 import { globalHeaders } from '@/utils/request';
 import { to } from 'await-to-js';
 import { to } from 'await-to-js';
 import { optionselect } from '@/api/system/post';
 import { optionselect } from '@/api/system/post';
+import { hasPermi } from '@/directive/permission';
+import { checkPermi } from '@/utils/permission';
 
 
 const router = useRouter();
 const router = useRouter();
 const { proxy } = getCurrentInstance() as ComponentInternalInstance;
 const { proxy } = getCurrentInstance() as ComponentInternalInstance;
@@ -450,7 +453,7 @@ const getDeptTree = async () => {
 
 
 /** 过滤禁用的部门 */
 /** 过滤禁用的部门 */
 const filterDisabledDept = (deptList: DeptTreeVO[]) => {
 const filterDisabledDept = (deptList: DeptTreeVO[]) => {
-  return deptList.filter(dept => {
+  return deptList.filter((dept) => {
     if (dept.disabled) {
     if (dept.disabled) {
       return false;
       return false;
     }
     }
@@ -660,5 +663,3 @@ async function handleDeptChange(value: number | string) {
   form.value.postIds = [];
   form.value.postIds = [];
 }
 }
 </script>
 </script>
-
-<style lang="scss" scoped></style>

+ 1 - 1
src/views/system/user/profile/onlineDevice.vue

@@ -26,7 +26,7 @@
   </div>
   </div>
 </template>
 </template>
 
 
-<script name="Online" lang="ts" setup>
+<script setup name="Online" lang="ts">
 import { delOnline } from '@/api/monitor/online';
 import { delOnline } from '@/api/monitor/online';
 import { propTypes } from '@/utils/propTypes';
 import { propTypes } from '@/utils/propTypes';
 
 

+ 6 - 5
src/views/system/user/profile/thirdParty.vue

@@ -55,10 +55,10 @@
   </div>
   </div>
 </template>
 </template>
 
 
-<script lang="ts" setup>
+<script setup lang="ts">
 import { authUnlock, authBinding } from '@/api/system/social/auth';
 import { authUnlock, authBinding } from '@/api/system/social/auth';
 import { propTypes } from '@/utils/propTypes';
 import { propTypes } from '@/utils/propTypes';
-import useUserStore from '@/store/modules/user';
+import { useUserStore } from '@/store/modules/user';
 
 
 const { proxy } = getCurrentInstance() as ComponentInternalInstance;
 const { proxy } = getCurrentInstance() as ComponentInternalInstance;
 
 
@@ -94,7 +94,7 @@ const authUrl = (source: string) => {
 };
 };
 </script>
 </script>
 
 
-<style type="text/css">
+<style lang="scss" scoped>
 .user-bind .third-app {
 .user-bind .third-app {
   display: -webkit-box;
   display: -webkit-box;
   display: -ms-flexbox;
   display: -ms-flexbox;
@@ -128,8 +128,9 @@ a {
 }
 }
 
 
 .provider-desc {
 .provider-desc {
-  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Helvetica, Arial, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol',
-    'Liberation Sans', 'PingFang SC', 'Microsoft YaHei', 'Hiragino Sans GB', 'Wenquanyi Micro Hei', 'WenQuanYi Zen Hei', 'ST Heiti', SimHei, SimSun,
+  font-family:
+    -apple-system, BlinkMacSystemFont, 'Segoe UI', Helvetica, Arial, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', 'Liberation Sans',
+    'PingFang SC', 'Microsoft YaHei', 'Hiragino Sans GB', 'Wenquanyi Micro Hei', 'WenQuanYi Zen Hei', 'ST Heiti', SimHei, SimSun,
     'WenQuanYi Zen Hei Sharp', sans-serif;
     'WenQuanYi Zen Hei Sharp', sans-serif;
   font-size: 1.071rem;
   font-size: 1.071rem;
 }
 }

+ 1 - 1
src/views/system/user/profile/userAvatar.vue

@@ -59,7 +59,7 @@
 import 'vue-cropper/dist/index.css';
 import 'vue-cropper/dist/index.css';
 import { VueCropper } from 'vue-cropper';
 import { VueCropper } from 'vue-cropper';
 import { uploadAvatar } from '@/api/system/user';
 import { uploadAvatar } from '@/api/system/user';
-import useUserStore from '@/store/modules/user';
+import { useUserStore } from '@/store/modules/user';
 import { UploadRawFile } from 'element-plus';
 import { UploadRawFile } from 'element-plus';
 
 
 interface Options {
 interface Options {

+ 1 - 1
src/views/tool/gen/editTable.vue

@@ -89,7 +89,7 @@
           </el-table-column>
           </el-table-column>
           <el-table-column label="字典类型" min-width="12%">
           <el-table-column label="字典类型" min-width="12%">
             <template #default="scope">
             <template #default="scope">
-              <el-select v-model="scope.row.dictType" clearable filterable placeholder="请选择">
+              <el-select v-model="scope.row.dictType" clearable filterable placeholder="请选择" value-on-clear="">
                 <el-option v-for="dict in dictOptions" :key="dict.dictType" :label="dict.dictName" :value="dict.dictType">
                 <el-option v-for="dict in dictOptions" :key="dict.dictType" :label="dict.dictName" :value="dict.dictType">
                   <span style="float: left">{{ dict.dictName }}</span>
                   <span style="float: left">{{ dict.dictName }}</span>
                   <span style="float: right; color: #8492a6; font-size: 13px">{{ dict.dictType }}</span>
                   <span style="float: right; color: #8492a6; font-size: 13px">{{ dict.dictType }}</span>

+ 1 - 1
src/views/tool/gen/genInfoForm.vue

@@ -70,7 +70,7 @@
           <el-tree-select
           <el-tree-select
             v-model="infoForm.parentMenuId"
             v-model="infoForm.parentMenuId"
             :data="menuOptions"
             :data="menuOptions"
-            :props="{ value: 'menuId', label: 'menuName', children: 'children' }"
+            :props="{ value: 'menuId', label: 'menuName', children: 'children' } as any"
             value-key="menuId"
             value-key="menuId"
             node-key="menuId"
             node-key="menuId"
             placeholder="选择上级菜单"
             placeholder="选择上级菜单"

+ 1 - 1
src/views/workflow/category/index.vue

@@ -58,7 +58,7 @@
           <el-tree-select
           <el-tree-select
             v-model="form.parentId"
             v-model="form.parentId"
             :data="categoryOptions"
             :data="categoryOptions"
-            :props="{ value: 'categoryId', label: 'categoryName', children: 'children' }"
+            :props="{ value: 'categoryId', label: 'categoryName', children: 'children' } as any"
             value-key="categoryId"
             value-key="categoryId"
             placeholder="请选择上级分类"
             placeholder="请选择上级分类"
             check-strictly
             check-strictly

+ 4 - 0
src/views/workflow/leave/leaveEdit.vue

@@ -111,6 +111,10 @@ const flowCodeOptions = [
   {
   {
     value: 'leave5',
     value: 'leave5',
     label: '请假申请-并行会签网关'
     label: '请假申请-并行会签网关'
+  },
+  {
+    value: 'leave6',
+    label: '请假申请-排他并行会签'
   }
   }
 ];
 ];
 
 

+ 23 - 20
src/views/workflow/processDefinition/index.vue

@@ -10,7 +10,7 @@
             class="mt-2"
             class="mt-2"
             node-key="id"
             node-key="id"
             :data="categoryOptions"
             :data="categoryOptions"
-            :props="{ label: 'label', children: 'children' }"
+            :props="{ label: 'label', children: 'children' } as any"
             :expand-on-click-node="false"
             :expand-on-click-node="false"
             :filter-node-method="filterNode"
             :filter-node-method="filterNode"
             highlight-current
             highlight-current
@@ -131,7 +131,7 @@
           <el-tree-select
           <el-tree-select
             v-model="selectCategory"
             v-model="selectCategory"
             :data="categoryOptions"
             :data="categoryOptions"
-            :props="{ value: 'id', label: 'label', children: 'children' }"
+            :props="{ value: 'id', label: 'label', children: 'children' } as any"
             filterable
             filterable
             value-key="id"
             value-key="id"
             :render-after-expand="false"
             :render-after-expand="false"
@@ -163,7 +163,7 @@
             <el-tree-select
             <el-tree-select
               v-model="form.category"
               v-model="form.category"
               :data="categoryOptions"
               :data="categoryOptions"
-              :props="{ value: 'id', label: 'label', children: 'children' }"
+              :props="{ value: 'id', label: 'label', children: 'children' } as any"
               filterable
               filterable
               value-key="id"
               value-key="id"
               :render-after-expand="false"
               :render-after-expand="false"
@@ -177,7 +177,7 @@
           <el-form-item label="流程名称" prop="flowName">
           <el-form-item label="流程名称" prop="flowName">
             <el-input v-model="form.flowName" placeholder="请输入流程名称" maxlength="100" show-word-limit />
             <el-input v-model="form.flowName" placeholder="请输入流程名称" maxlength="100" show-word-limit />
           </el-form-item>
           </el-form-item>
-          <el-form-item label="表单路径" prop="flowName">
+          <el-form-item label="表单路径" prop="formPath">
             <el-input v-model="form.formPath" placeholder="请输入表单路径" maxlength="100" show-word-limit />
             <el-input v-model="form.formPath" placeholder="请输入表单路径" maxlength="100" show-word-limit />
           </el-form-item>
           </el-form-item>
         </el-form>
         </el-form>
@@ -190,12 +190,13 @@
   </div>
   </div>
 </template>
 </template>
 
 
-<script lang="ts" setup name="processDefinition">
+<script setup name="processDefinition" lang="ts">
 import { listDefinition, deleteDefinition, active, importDef, unPublishList, publish, add, edit, getInfo, copy } from '@/api/workflow/definition';
 import { listDefinition, deleteDefinition, active, importDef, unPublishList, publish, add, edit, getInfo, copy } from '@/api/workflow/definition';
 import { categoryTree } from '@/api/workflow/category';
 import { categoryTree } from '@/api/workflow/category';
 import { CategoryTreeVO } from '@/api/workflow/category/types';
 import { CategoryTreeVO } from '@/api/workflow/category/types';
 import { FlowDefinitionQuery, FlowDefinitionVo, FlowDefinitionForm } from '@/api/workflow/definition/types';
 import { FlowDefinitionQuery, FlowDefinitionVo, FlowDefinitionForm } from '@/api/workflow/definition/types';
 import { UploadRequestOptions, TabsPaneContext } from 'element-plus';
 import { UploadRequestOptions, TabsPaneContext } from 'element-plus';
+import { ElMessageBoxOptions } from "element-plus/es/components/message-box/src/message-box.type";
 
 
 const { proxy } = getCurrentInstance() as ComponentInternalInstance;
 const { proxy } = getCurrentInstance() as ComponentInternalInstance;
 
 
@@ -324,9 +325,9 @@ const handleSelectionChange = (selection: any) => {
 };
 };
 //分页
 //分页
 const getPageList = async () => {
 const getPageList = async () => {
-  console.log(proxy.$route.query.activeName)
-  if (proxy.$route.query.activeName) {
-    activeName.value = proxy.$route.query.activeName;
+  let query = proxy.$route.query;
+  if (query.activeName) {
+    activeName.value = query.activeName;
   }
   }
   if (activeName.value === '0') {
   if (activeName.value === '0') {
     getList();
     getList();
@@ -370,7 +371,7 @@ const handlePublish = async (row?: FlowDefinitionVo) => {
   loading.value = true;
   loading.value = true;
   await publish(row.id).finally(() => (loading.value = false));
   await publish(row.id).finally(() => (loading.value = false));
   processDefinitionDialog.visible = false;
   processDefinitionDialog.visible = false;
-  activeName.value = "0"
+  activeName.value = '0';
   await handleQuery();
   await handleQuery();
   proxy?.$modal.msgSuccess('发布成功');
   proxy?.$modal.msgSuccess('发布成功');
 };
 };
@@ -417,7 +418,7 @@ const handlerImportDefinition = (data: UploadRequestOptions): XMLHttpRequest =>
     .then(() => {
     .then(() => {
       uploadDialog.visible = false;
       uploadDialog.visible = false;
       proxy?.$modal.msgSuccess('部署成功');
       proxy?.$modal.msgSuccess('部署成功');
-      activeName.value = "1"
+      activeName.value = '1';
       handleQuery();
       handleQuery();
     })
     })
     .finally(() => {
     .finally(() => {
@@ -482,9 +483,9 @@ const handleSubmit = async () => {
     if (valid) {
     if (valid) {
       loading.value = true;
       loading.value = true;
       if (form.value.id) {
       if (form.value.id) {
-        await edit(form.value).finally(() => loading.value = false);
+        await edit(form.value).finally(() => (loading.value = false));
       } else {
       } else {
-        await add(form.value).finally(() => loading.value = false);
+        await add(form.value).finally(() => (loading.value = false));
       }
       }
       proxy?.$modal.msgSuccess('操作成功');
       proxy?.$modal.msgSuccess('操作成功');
       modelDialog.visible = false;
       modelDialog.visible = false;
@@ -498,15 +499,17 @@ const handleCopyDef = async (row: FlowDefinitionVo) => {
     confirmButtonText: '确认',
     confirmButtonText: '确认',
     cancelButtonText: '取消',
     cancelButtonText: '取消',
     type: 'warning'
     type: 'warning'
-  }).then(() => {
+  } as ElMessageBoxOptions).then(() => {
     loading.value = true;
     loading.value = true;
-    copy(row.id).then((resp) => {
-      if (resp.code === 200) {
-        proxy?.$modal.msgSuccess('操作成功');
-        activeName.value = "1"
-        handleQuery();
-      }
-    }).finally(() => loading.value = false);
+    copy(row.id)
+      .then((resp) => {
+        if (resp.code === 200) {
+          proxy?.$modal.msgSuccess('操作成功');
+          activeName.value = '1';
+          handleQuery();
+        }
+      })
+      .finally(() => (loading.value = false));
   });
   });
 };
 };
 
 

+ 2 - 2
src/views/workflow/processInstance/index.vue

@@ -10,7 +10,7 @@
             class="mt-2"
             class="mt-2"
             node-key="id"
             node-key="id"
             :data="categoryOptions"
             :data="categoryOptions"
-            :props="{ label: 'label', children: 'children' }"
+            :props="{ label: 'label', children: 'children' } as any"
             :expand-on-click-node="false"
             :expand-on-click-node="false"
             :filter-node-method="filterNode"
             :filter-node-method="filterNode"
             highlight-current
             highlight-current
@@ -174,7 +174,7 @@
   </div>
   </div>
 </template>
 </template>
 
 
-<script lang="ts" setup>
+<script setup lang="ts">
 import { pageByRunning, pageByFinish, deleteByInstanceIds, instanceVariable, invalid } from '@/api/workflow/instance';
 import { pageByRunning, pageByFinish, deleteByInstanceIds, instanceVariable, invalid } from '@/api/workflow/instance';
 import { categoryTree } from '@/api/workflow/category';
 import { categoryTree } from '@/api/workflow/category';
 import { CategoryTreeVO } from '@/api/workflow/category/types';
 import { CategoryTreeVO } from '@/api/workflow/category/types';

+ 2 - 2
src/views/workflow/task/allTaskWaiting.vue

@@ -97,14 +97,14 @@
     </el-card>
     </el-card>
     <!-- 选人组件 -->
     <!-- 选人组件 -->
     <UserSelect ref="userSelectRef" :multiple="false" @confirm-call-back="submitCallback"></UserSelect>
     <UserSelect ref="userSelectRef" :multiple="false" @confirm-call-back="submitCallback"></UserSelect>
-    <!-- 选人组件 -->
+    <!-- 流程干预组件 -->
     <processMeddle ref="processMeddleRef" @submitCallback="getWaitingList"></processMeddle>
     <processMeddle ref="processMeddleRef" @submitCallback="getWaitingList"></processMeddle>
     <!-- 申请人 -->
     <!-- 申请人 -->
     <UserSelect ref="applyUserSelectRef" :multiple="true" :data="selectUserIds" @confirm-call-back="userSelectCallBack"></UserSelect>
     <UserSelect ref="applyUserSelectRef" :multiple="true" :data="selectUserIds" @confirm-call-back="userSelectCallBack"></UserSelect>
   </div>
   </div>
 </template>
 </template>
 
 
-<script lang="ts" setup>
+<script setup lang="ts">
 import { pageByAllTaskWait, pageByAllTaskFinish, updateAssignee } from '@/api/workflow/task';
 import { pageByAllTaskWait, pageByAllTaskFinish, updateAssignee } from '@/api/workflow/task';
 import UserSelect from '@/components/UserSelect';
 import UserSelect from '@/components/UserSelect';
 import { TaskQuery } from '@/api/workflow/task/types';
 import { TaskQuery } from '@/api/workflow/task/types';

+ 2 - 2
src/views/workflow/task/myDocument.vue

@@ -10,7 +10,7 @@
             class="mt-2"
             class="mt-2"
             node-key="id"
             node-key="id"
             :data="categoryOptions"
             :data="categoryOptions"
-            :props="{ label: 'label', children: 'children' }"
+            :props="{ label: 'label', children: 'children' } as any"
             :expand-on-click-node="false"
             :expand-on-click-node="false"
             :filter-node-method="filterNode"
             :filter-node-method="filterNode"
             highlight-current
             highlight-current
@@ -101,7 +101,7 @@
   </div>
   </div>
 </template>
 </template>
 
 
-<script lang="ts" setup>
+<script setup lang="ts">
 import { pageByCurrent, deleteByInstanceIds, cancelProcessApply } from '@/api/workflow/instance';
 import { pageByCurrent, deleteByInstanceIds, cancelProcessApply } from '@/api/workflow/instance';
 import { categoryTree } from '@/api/workflow/category';
 import { categoryTree } from '@/api/workflow/category';
 import { CategoryTreeVO } from '@/api/workflow/category/types';
 import { CategoryTreeVO } from '@/api/workflow/category/types';

+ 1 - 1
src/views/workflow/task/taskCopyList.vue

@@ -59,7 +59,7 @@
   </div>
   </div>
 </template>
 </template>
 
 
-<script lang="ts" setup>
+<script setup lang="ts">
 import { pageByTaskCopy } from '@/api/workflow/task';
 import { pageByTaskCopy } from '@/api/workflow/task';
 import { TaskQuery } from '@/api/workflow/task/types';
 import { TaskQuery } from '@/api/workflow/task/types';
 import workflowCommon from '@/api/workflow/workflowCommon';
 import workflowCommon from '@/api/workflow/workflowCommon';

+ 1 - 1
src/views/workflow/task/taskFinish.vue

@@ -80,7 +80,7 @@
   </div>
   </div>
 </template>
 </template>
 
 
-<script lang="ts" setup>
+<script setup lang="ts">
 import { pageByTaskFinish } from '@/api/workflow/task';
 import { pageByTaskFinish } from '@/api/workflow/task';
 import { TaskQuery, FlowTaskVO } from '@/api/workflow/task/types';
 import { TaskQuery, FlowTaskVO } from '@/api/workflow/task/types';
 import workflowCommon from '@/api/workflow/workflowCommon';
 import workflowCommon from '@/api/workflow/workflowCommon';

+ 1 - 1
src/views/workflow/task/taskWaiting.vue

@@ -77,7 +77,7 @@
   </div>
   </div>
 </template>
 </template>
 
 
-<script lang="ts" setup>
+<script setup lang="ts">
 import { pageByTaskWait } from '@/api/workflow/task';
 import { pageByTaskWait } from '@/api/workflow/task';
 import { TaskQuery, FlowTaskVO } from '@/api/workflow/task/types';
 import { TaskQuery, FlowTaskVO } from '@/api/workflow/task/types';
 import workflowCommon from '@/api/workflow/workflowCommon';
 import workflowCommon from '@/api/workflow/workflowCommon';

+ 31 - 20
tsconfig.json

@@ -1,31 +1,42 @@
 {
 {
+  "$schema": "https://json.schemastore.org/tsconfig",
   "compilerOptions": {
   "compilerOptions": {
-    "target": "esnext",
-    "module": "esnext",
-    //    "useDefineForClassFields": true,
-    "moduleResolution": "bundler",
+    "baseUrl": ".",
+    // https://vite.dev/config/build-options.html#build-target
+    "target": "ES2020",
+    "module": "ESNext",
+    "moduleResolution": "Bundler",
+    "lib": ["ESNext", "DOM", "DOM.Iterable"],
+    "skipLibCheck": true,
+    // This setting lets you specify a file for storing incremental compilation information as a part of composite projects which enables faster building of larger TypeScript codebases.
+    "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.tsbuildinfo",
     "strict": true,
     "strict": true,
+    "allowJs": true,
     "jsx": "preserve",
     "jsx": "preserve",
-    "strictNullChecks": false,
     "sourceMap": true,
     "sourceMap": true,
     "resolveJsonModule": true,
     "resolveJsonModule": true,
     "esModuleInterop": true,
     "esModuleInterop": true,
-    "strictFunctionTypes": false,
-    "lib": ["esnext", "dom"],
-    "noImplicitAny": false,
-    "baseUrl": ".",
-    "allowJs": true,
-    "experimentalDecorators": true,
+    "noEmit": true,
     "paths": {
     "paths": {
-      "@/*": ["src/*"]
+      "@/*": ["./src/*"]
     },
     },
-    "types": ["vite/client"],
-    "skipLibCheck": true,
-    "removeComments": true,
-    // 允许默认导入
-    "allowSyntheticDefaultImports": true,
-    "forceConsistentCasingInFileNames": true
+    "types": ["node", "vite/client"],
+    // 自定义配置
+    "noImplicitAny": false, // 禁用 隐式的any错误
+    "removeComments": true, // 移除 ts注释
+    "experimentalDecorators": true, // 启用实验性的装饰器支持
+    "strictFunctionTypes": false, // 禁用严格函数类型检查
+    "strictNullChecks": false, // 禁用严格的空值检查
+    "allowSyntheticDefaultImports": true, // 允许默认导入
+    "forceConsistentCasingInFileNames": true // 强制在文件名中使用一致的大小写
   },
   },
-  "include": ["src/**/*.ts", "src/**/*.vue", "src/types/**/*.d.ts", "vite.config.ts"],
-  "exclude": ["node_modules", "dist", "**/*.js", "**/*.md", "src/**/*.md"]
+  "include": [
+    "src/**/*.ts",
+    "src/**/*.vue",
+    "vite.config.ts",
+    "vitest.config.ts",
+    "eslint.config.ts",
+    "src/**/*.d.ts"
+  ],
+  "exclude": ["node_modules", "dist", "src/**/__tests__/*"]
 }
 }

+ 10 - 9
vite.config.ts

@@ -1,9 +1,9 @@
-import { UserConfig, ConfigEnv, loadEnv, defineConfig } from 'vite';
-
+import { defineConfig, loadEnv } from 'vite';
 import createPlugins from './vite/plugins';
 import createPlugins from './vite/plugins';
-
+import autoprefixer from 'autoprefixer'; // css自动添加兼容性前缀
 import path from 'path';
 import path from 'path';
-export default defineConfig(({ mode, command }: ConfigEnv): UserConfig => {
+
+export default defineConfig(({ mode, command }) => {
   const env = loadEnv(mode, process.cwd());
   const env = loadEnv(mode, process.cwd());
   return {
   return {
     // 部署生产环境和开发环境下的URL。
     // 部署生产环境和开发环境下的URL。
@@ -12,7 +12,6 @@ export default defineConfig(({ mode, command }: ConfigEnv): UserConfig => {
     base: env.VITE_APP_CONTEXT_PATH,
     base: env.VITE_APP_CONTEXT_PATH,
     resolve: {
     resolve: {
       alias: {
       alias: {
-        '~': path.resolve(__dirname, './'),
         '@': path.resolve(__dirname, './src')
         '@': path.resolve(__dirname, './src')
       },
       },
       extensions: ['.mjs', '.js', '.ts', '.jsx', '.tsx', '.json', '.vue']
       extensions: ['.mjs', '.js', '.ts', '.jsx', '.tsx', '.json', '.vue']
@@ -35,18 +34,20 @@ export default defineConfig(({ mode, command }: ConfigEnv): UserConfig => {
     css: {
     css: {
       preprocessorOptions: {
       preprocessorOptions: {
         scss: {
         scss: {
-          javascriptEnabled: true
+          // additionalData: '@use "@/assets/styles/variables.module.scss as *";'
+          // javascriptEnabled: true
+          api: 'modern-compiler'
         }
         }
       },
       },
       postcss: {
       postcss: {
         plugins: [
         plugins: [
+          // 浏览器兼容性
+          autoprefixer(),
           {
           {
             postcssPlugin: 'internal:charset-removal',
             postcssPlugin: 'internal:charset-removal',
             AtRule: {
             AtRule: {
               charset: (atRule) => {
               charset: (atRule) => {
-                if (atRule.name === 'charset') {
-                  atRule.remove();
-                }
+                atRule.remove();
               }
               }
             }
             }
           }
           }

+ 2 - 6
vite/plugins/auto-import.ts

@@ -1,22 +1,18 @@
 import AutoImport from 'unplugin-auto-import/vite';
 import AutoImport from 'unplugin-auto-import/vite';
 import { ElementPlusResolver } from 'unplugin-vue-components/resolvers';
 import { ElementPlusResolver } from 'unplugin-vue-components/resolvers';
-import IconsResolver from 'unplugin-icons/resolver';
 
 
 export default (path: any) => {
 export default (path: any) => {
   return AutoImport({
   return AutoImport({
     // 自动导入 Vue 相关函数
     // 自动导入 Vue 相关函数
     imports: ['vue', 'vue-router', '@vueuse/core', 'pinia'],
     imports: ['vue', 'vue-router', '@vueuse/core', 'pinia'],
     eslintrc: {
     eslintrc: {
-      enabled: false,
+      enabled: true,
       filepath: './.eslintrc-auto-import.json',
       filepath: './.eslintrc-auto-import.json',
       globalsPropValue: true
       globalsPropValue: true
     },
     },
     resolvers: [
     resolvers: [
       // 自动导入 Element Plus 相关函数ElMessage, ElMessageBox... (带样式)
       // 自动导入 Element Plus 相关函数ElMessage, ElMessageBox... (带样式)
-      ElementPlusResolver(),
-      IconsResolver({
-        prefix: 'Icon'
-      })
+      ElementPlusResolver()
     ],
     ],
     vueTemplate: true, // 是否在 vue 模板中自动导入
     vueTemplate: true, // 是否在 vue 模板中自动导入
     dts: path.resolve(path.resolve(__dirname, '../../src'), 'types', 'auto-imports.d.ts')
     dts: path.resolve(path.resolve(__dirname, '../../src'), 'types', 'auto-imports.d.ts')

+ 4 - 1
vite/plugins/index.ts

@@ -1,4 +1,6 @@
 import vue from '@vitejs/plugin-vue';
 import vue from '@vitejs/plugin-vue';
+import vueDevTools from 'vite-plugin-vue-devtools';
+
 import createUnoCss from './unocss';
 import createUnoCss from './unocss';
 import createAutoImport from './auto-import';
 import createAutoImport from './auto-import';
 import createComponents from './components';
 import createComponents from './components';
@@ -11,12 +13,13 @@ import path from 'path';
 export default (viteEnv: any, isBuild = false): [] => {
 export default (viteEnv: any, isBuild = false): [] => {
   const vitePlugins: any = [];
   const vitePlugins: any = [];
   vitePlugins.push(vue());
   vitePlugins.push(vue());
+  vitePlugins.push(vueDevTools());
   vitePlugins.push(createUnoCss());
   vitePlugins.push(createUnoCss());
   vitePlugins.push(createAutoImport(path));
   vitePlugins.push(createAutoImport(path));
   vitePlugins.push(createComponents(path));
   vitePlugins.push(createComponents(path));
   vitePlugins.push(createCompression(viteEnv));
   vitePlugins.push(createCompression(viteEnv));
   vitePlugins.push(createIcons());
   vitePlugins.push(createIcons());
-  vitePlugins.push(createSvgIconsPlugin(path, isBuild));
+  vitePlugins.push(createSvgIconsPlugin(path));
   vitePlugins.push(createSetupExtend());
   vitePlugins.push(createSetupExtend());
   return vitePlugins;
   return vitePlugins;
 };
 };

+ 4 - 4
vite/plugins/svg-icon.ts

@@ -1,10 +1,10 @@
-import { createSvgIconsPlugin } from 'vite-plugin-svg-icons';
-export default (path: any, isBuild: boolean) => {
+import { createSvgIconsPlugin } from 'vite-plugin-svg-icons-ng';
+
+export default (path: any) => {
   return createSvgIconsPlugin({
   return createSvgIconsPlugin({
     // 指定需要缓存的图标文件夹
     // 指定需要缓存的图标文件夹
     iconDirs: [path.resolve(path.resolve(__dirname, '../../src'), 'assets/icons/svg')],
     iconDirs: [path.resolve(path.resolve(__dirname, '../../src'), 'assets/icons/svg')],
     // 指定symbolId格式
     // 指定symbolId格式
-    symbolId: 'icon-[dir]-[name]',
-    svgoOptions: isBuild
+    symbolId: 'icon-[dir]-[name]'
   });
   });
 };
 };

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