Rmengdi 8 mēneši atpakaļ
revīzija
ea979bf033
100 mainītis faili ar 4149 papildinājumiem un 0 dzēšanām
  1. 15 0
      .editorconfig
  2. 11 0
      .env
  3. 37 0
      .env.development
  4. 45 0
      .env.production
  5. 25 0
      .env.test
  6. 15 0
      .eslintignore
  7. 305 0
      .eslintrc-auto-import.json
  8. 74 0
      .eslintrc.cjs
  9. 26 0
      .gitignore
  10. 4 0
      .husky/commit-msg
  11. 4 0
      .husky/pre-commit
  12. 9 0
      .prettierignore
  13. 41 0
      .prettierrc.cjs
  14. 4 0
      .stylelintignore
  15. 40 0
      .stylelintrc.cjs
  16. 14 0
      .vscode/extensions.json
  17. 96 0
      .vscode/settings.json
  18. 0 0
      CHANGELOG.md
  19. 8 0
      LICENSE
  20. 18 0
      README.md
  21. 46 0
      build/getEnv.ts
  22. 84 0
      build/plugins.ts
  23. 30 0
      build/proxy.ts
  24. 162 0
      commitlint.config.cjs
  25. 105 0
      index.html
  26. 8 0
      lint-staged.config.cjs
  27. 142 0
      package.json
  28. 5 0
      postcss.config.cjs
  29. BIN
      public/eco-1.png
  30. 43 0
      src/App.vue
  31. 3 0
      src/api/config/servicePort.ts
  32. 46 0
      src/api/helper/axiosCancel.ts
  33. 43 0
      src/api/helper/checkStatus.ts
  34. 223 0
      src/api/index.ts
  35. 108 0
      src/api/interface/index.ts
  36. 59 0
      src/api/interface/login.ts
  37. 29 0
      src/api/interface/menu.ts
  38. 176 0
      src/api/interface/monitor/logininfor.ts
  39. 266 0
      src/api/interface/monitor/operlog.ts
  40. 25 0
      src/api/interface/system/config.ts
  41. 28 0
      src/api/interface/system/data.ts
  42. 47 0
      src/api/interface/system/dept.ts
  43. 96 0
      src/api/interface/system/importExport.ts
  44. 71 0
      src/api/interface/system/menu.ts
  45. 24 0
      src/api/interface/system/oss.ts
  46. 41 0
      src/api/interface/system/ossConfig.ts
  47. 25 0
      src/api/interface/system/post.ts
  48. 54 0
      src/api/interface/system/role.ts
  49. 20 0
      src/api/interface/system/type.ts
  50. 87 0
      src/api/interface/system/user.ts
  51. 175 0
      src/api/interface/tool/gen.ts
  52. 26 0
      src/api/modules/login.ts
  53. 34 0
      src/api/modules/monitor/logininfor.ts
  54. 43 0
      src/api/modules/monitor/operlog.ts
  55. 78 0
      src/api/modules/system/config.ts
  56. 46 0
      src/api/modules/system/dept.ts
  57. 69 0
      src/api/modules/system/dict.ts
  58. 63 0
      src/api/modules/system/dictData.ts
  59. 19 0
      src/api/modules/system/importExport.ts
  60. 69 0
      src/api/modules/system/menu.ts
  61. 28 0
      src/api/modules/system/oss.ts
  62. 62 0
      src/api/modules/system/ossConfig.ts
  63. 71 0
      src/api/modules/system/post.ts
  64. 153 0
      src/api/modules/system/role.ts
  65. 138 0
      src/api/modules/system/user.ts
  66. 91 0
      src/api/modules/tool/gen.ts
  67. 16 0
      src/api/modules/upload.ts
  68. BIN
      src/assets/fonts/DIN.otf
  69. BIN
      src/assets/fonts/MetroDF.ttf
  70. BIN
      src/assets/fonts/YouSheBiaoTiHei.ttf
  71. 14 0
      src/assets/fonts/font.scss
  72. 48 0
      src/assets/iconfont/iconfont.scss
  73. BIN
      src/assets/iconfont/iconfont.ttf
  74. 1 0
      src/assets/icons/svg/404.svg
  75. 1 0
      src/assets/icons/svg/avatar-user.svg
  76. 1 0
      src/assets/icons/svg/bug.svg
  77. 1 0
      src/assets/icons/svg/build.svg
  78. 0 0
      src/assets/icons/svg/button.svg
  79. 0 0
      src/assets/icons/svg/cascader.svg
  80. 1 0
      src/assets/icons/svg/chart.svg
  81. 1 0
      src/assets/icons/svg/checkbox.svg
  82. 1 0
      src/assets/icons/svg/clipboard.svg
  83. 1 0
      src/assets/icons/svg/code.svg
  84. 0 0
      src/assets/icons/svg/color.svg
  85. 0 0
      src/assets/icons/svg/component.svg
  86. 0 0
      src/assets/icons/svg/dashboard.svg
  87. 0 0
      src/assets/icons/svg/date-range.svg
  88. 0 0
      src/assets/icons/svg/date.svg
  89. 0 0
      src/assets/icons/svg/dict.svg
  90. 1 0
      src/assets/icons/svg/documentation.svg
  91. 1 0
      src/assets/icons/svg/download.svg
  92. 1 0
      src/assets/icons/svg/drag.svg
  93. 1 0
      src/assets/icons/svg/druid.svg
  94. 1 0
      src/assets/icons/svg/edit.svg
  95. 1 0
      src/assets/icons/svg/education.svg
  96. 1 0
      src/assets/icons/svg/email.svg
  97. 1 0
      src/assets/icons/svg/example.svg
  98. 1 0
      src/assets/icons/svg/excel.svg
  99. 1 0
      src/assets/icons/svg/exit-fullscreen.svg
  100. 1 0
      src/assets/icons/svg/eye-open.svg

+ 15 - 0
.editorconfig

@@ -0,0 +1,15 @@
+# @see: http://editorconfig.org
+
+root = true
+
+[*] # 表示所有文件适用
+charset = utf-8 # 设置文件字符集为 utf-8
+end_of_line = lf # 控制换行类型(lf | cr | crlf)
+insert_final_newline = true # 始终在文件末尾插入一个新行
+indent_style = space # 缩进风格(tab | space)
+indent_size = 2 # 缩进大小
+max_line_length = 130 # 最大行长度
+
+[*.md] # 表示仅对 md 文件适用以下规则
+max_line_length = off # 关闭最大行长度限制
+trim_trailing_whitespace = false # 关闭末尾空格修剪

+ 11 - 0
.env

@@ -0,0 +1,11 @@
+# title
+VITE_GLOB_APP_TITLE = eco
+
+# 本地运行端口号
+VITE_PORT = 8848
+
+# 启动时自动打开浏览器
+VITE_OPEN = true
+
+# 打包后是否生成包分析文件
+VITE_REPORT = false

+ 37 - 0
.env.development

@@ -0,0 +1,37 @@
+# 本地环境
+VITE_USER_NODE_ENV = development
+
+# 公共基础路径
+VITE_PUBLIC_PATH = /
+
+# 路由模式
+# Optional: hash | history
+VITE_ROUTER_MODE = hash
+
+# 打包时是否删除 console
+VITE_DROP_CONSOLE = true
+
+# 是否开启 VitePWA
+VITE_PWA = false
+
+# 开发环境接口地址
+VITE_API_URL = /api
+# 接口加密传输 RSA 公钥与后端解密私钥对应 如更换需前后端一同更换
+VITE_APP_RSA_PUBLIC_KEY = 'MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAKoR8mX0rGKLqzcWmOzbfj64K8ZIgOdHnzkXSOVOZbFu/TJhZ7rFAN+eaGkl3C4buccQd/EjEsj9ir7ijT7h96MCAwEAAQ=='
+# 接口响应解密 RSA 私钥与后端加密公钥对应 如更换需前后端一同更换
+VITE_APP_RSA_PRIVATE_KEY = 'MIIBVAIBADANBgkqhkiG9w0BAQEFAASCAT4wggE6AgEAAkEAmc3CuPiGL/LcIIm7zryCEIbl1SPzBkr75E2VMtxegyZ1lYRD+7TZGAPkvIsBcaMs6Nsy0L78n2qh+lIZMpLH8wIDAQABAkEAk82Mhz0tlv6IVCyIcw/s3f0E+WLmtPFyR9/WtV3Y5aaejUkU60JpX4m5xNR2VaqOLTZAYjW8Wy0aXr3zYIhhQQIhAMfqR9oFdYw1J9SsNc+CrhugAvKTi0+BF6VoL6psWhvbAiEAxPPNTmrkmrXwdm/pQQu3UOQmc2vCZ5tiKpW10CgJi8kCIFGkL6utxw93Ncj4exE/gPLvKcT+1Emnoox+O9kRXss5AiAMtYLJDaLEzPrAWcZeeSgSIzbL+ecokmFKSDDcRske6QIgSMkHedwND1olF8vlKsJUGK3BcdtM8w4Xq7BpSBwsloE='
+
+# 客户端id
+VITE_APP_CLIENT_ID = 'e5cd7e4891bf95d1d19206ce24a7b32e'
+
+# 开发环境跨域代理,支持配置多个
+VITE_PROXY = [["/api","http://localhost:9090"]]
+
+# websocket 开关
+VITE_APP_WEBSOCKET = true
+
+# 监控地址
+VITE_APP_MONITOR_ADMIN = 'http://localhost:9099/admin/applications'
+
+# powerjob 控制台地址
+VITE_APP_POWERJOB_ADMIN = 'http://localhost:7700/'

+ 45 - 0
.env.production

@@ -0,0 +1,45 @@
+# 线上环境
+VITE_USER_NODE_ENV = production
+
+# 公共基础路径
+VITE_PUBLIC_PATH = /
+
+# 路由模式
+# Optional: hash | history
+VITE_ROUTER_MODE = hash
+
+# 是否启用 gzip 或 brotli 压缩打包,如果需要多个压缩规则,可以使用 “,” 分隔
+# Optional: gzip | brotli | none
+VITE_BUILD_COMPRESS = none
+
+# 打包压缩后是否删除源文件
+VITE_BUILD_COMPRESS_DELETE_ORIGIN_FILE = false
+
+# 打包时是否删除 console
+VITE_DROP_CONSOLE = true
+
+# 是否开启 VitePWA
+VITE_PWA = true
+
+# 接口加密传输 RSA 公钥与后端解密私钥对应 如更换需前后端一同更换
+VITE_APP_RSA_PUBLIC_KEY = 'MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAKoR8mX0rGKLqzcWmOzbfj64K8ZIgOdHnzkXSOVOZbFu/TJhZ7rFAN+eaGkl3C4buccQd/EjEsj9ir7ijT7h96MCAwEAAQ=='
+# 接口响应解密 RSA 私钥与后端加密公钥对应 如更换需前后端一同更换
+VITE_APP_RSA_PRIVATE_KEY = 'MIIBVAIBADANBgkqhkiG9w0BAQEFAASCAT4wggE6AgEAAkEAmc3CuPiGL/LcIIm7zryCEIbl1SPzBkr75E2VMtxegyZ1lYRD+7TZGAPkvIsBcaMs6Nsy0L78n2qh+lIZMpLH8wIDAQABAkEAk82Mhz0tlv6IVCyIcw/s3f0E+WLmtPFyR9/WtV3Y5aaejUkU60JpX4m5xNR2VaqOLTZAYjW8Wy0aXr3zYIhhQQIhAMfqR9oFdYw1J9SsNc+CrhugAvKTi0+BF6VoL6psWhvbAiEAxPPNTmrkmrXwdm/pQQu3UOQmc2vCZ5tiKpW10CgJi8kCIFGkL6utxw93Ncj4exE/gPLvKcT+1Emnoox+O9kRXss5AiAMtYLJDaLEzPrAWcZeeSgSIzbL+ecokmFKSDDcRske6QIgSMkHedwND1olF8vlKsJUGK3BcdtM8w4Xq7BpSBwsloE='
+
+# 客户端id
+VITE_APP_CLIENT_ID = 'e5cd7e4891bf95d1d19206ce24a7b32e'
+
+# 线上环境接口地址
+VITE_API_URL = /api-pro
+
+# 开发环境跨域代理,支持配置多个
+VITE_PROXY = [["/api-pro","http://localhost:9090"]]
+
+# websocket 开关
+VITE_APP_WEBSOCKET = true
+
+# 监控地址
+VITE_APP_MONITOR_ADMIN = '/admin/applications'
+
+# powerjob 控制台地址
+VITE_APP_POWERJOB_ADMIN = '/powerjob'

+ 25 - 0
.env.test

@@ -0,0 +1,25 @@
+# 测试环境
+VITE_USER_NODE_ENV = test
+
+# 公共基础路径
+VITE_PUBLIC_PATH = /
+
+# 路由模式
+# Optional: hash | history
+VITE_ROUTER_MODE = hash
+
+# 是否启用 gzip 或 brotli 压缩打包,如果需要多个压缩规则,可以使用 “,” 分隔
+# Optional: gzip | brotli | none
+VITE_BUILD_COMPRESS = none
+
+# 打包压缩后是否删除源文件
+VITE_BUILD_COMPRESS_DELETE_ORIGIN_FILE = false
+
+# 打包时是否删除 console
+VITE_DROP_CONSOLE = true
+
+# 是否开启 VitePWA
+VITE_PWA = false
+
+# 测试环境接口地址
+VITE_API_URL = "https://mock.mengxuegu.com/mock/629d727e6163854a32e8307e"

+ 15 - 0
.eslintignore

@@ -0,0 +1,15 @@
+*.sh
+node_modules
+*.md
+*.woff
+*.ttf
+.vscode
+.idea
+dist
+/public
+/docs
+.husky
+.local
+/bin
+/src/mock/*
+stats.html

+ 305 - 0
.eslintrc-auto-import.json

@@ -0,0 +1,305 @@
+{
+  "globals": {
+    "Component": true,
+    "ComponentPublicInstance": true,
+    "ComputedRef": true,
+    "EffectScope": true,
+    "ExtractDefaultPropTypes": true,
+    "ExtractPropTypes": true,
+    "ExtractPublicPropTypes": true,
+    "InjectionKey": true,
+    "PropType": true,
+    "Ref": true,
+    "VNode": true,
+    "WritableComputedRef": true,
+    "acceptHMRUpdate": true,
+    "asyncComputed": true,
+    "autoResetRef": true,
+    "computed": true,
+    "computedAsync": true,
+    "computedEager": true,
+    "computedInject": true,
+    "computedWithControl": true,
+    "controlledComputed": true,
+    "controlledRef": true,
+    "createApp": true,
+    "createEventHook": true,
+    "createGlobalState": true,
+    "createInjectionState": true,
+    "createPinia": true,
+    "createReactiveFn": true,
+    "createReusableTemplate": true,
+    "createSharedComposable": true,
+    "createTemplatePromise": true,
+    "createUnrefFn": true,
+    "customRef": true,
+    "debouncedRef": true,
+    "debouncedWatch": true,
+    "defineAsyncComponent": true,
+    "defineComponent": true,
+    "defineStore": true,
+    "eagerComputed": true,
+    "effectScope": true,
+    "extendRef": true,
+    "getActivePinia": true,
+    "getCurrentInstance": true,
+    "getCurrentScope": true,
+    "h": true,
+    "ignorableWatch": true,
+    "inject": true,
+    "injectLocal": true,
+    "isDefined": true,
+    "isProxy": true,
+    "isReactive": true,
+    "isReadonly": true,
+    "isRef": true,
+    "makeDestructurable": true,
+    "mapActions": true,
+    "mapGetters": true,
+    "mapState": true,
+    "mapStores": true,
+    "mapWritableState": true,
+    "markRaw": true,
+    "nextTick": true,
+    "onActivated": true,
+    "onBeforeMount": true,
+    "onBeforeRouteLeave": true,
+    "onBeforeRouteUpdate": true,
+    "onBeforeUnmount": true,
+    "onBeforeUpdate": true,
+    "onClickOutside": true,
+    "onDeactivated": true,
+    "onErrorCaptured": true,
+    "onKeyStroke": true,
+    "onLongPress": true,
+    "onMounted": true,
+    "onRenderTracked": true,
+    "onRenderTriggered": true,
+    "onScopeDispose": true,
+    "onServerPrefetch": true,
+    "onStartTyping": true,
+    "onUnmounted": true,
+    "onUpdated": true,
+    "pausableWatch": true,
+    "provide": true,
+    "provideLocal": true,
+    "reactify": true,
+    "reactifyObject": true,
+    "reactive": true,
+    "reactiveComputed": true,
+    "reactiveOmit": true,
+    "reactivePick": true,
+    "readonly": true,
+    "ref": true,
+    "refAutoReset": true,
+    "refDebounced": true,
+    "refDefault": true,
+    "refThrottled": true,
+    "refWithControl": true,
+    "resolveComponent": true,
+    "resolveRef": true,
+    "resolveUnref": true,
+    "setActivePinia": true,
+    "setMapStoreSuffix": true,
+    "shallowReactive": true,
+    "shallowReadonly": true,
+    "shallowRef": true,
+    "storeToRefs": true,
+    "syncRef": true,
+    "syncRefs": true,
+    "templateRef": true,
+    "throttledRef": true,
+    "throttledWatch": true,
+    "toRaw": true,
+    "toReactive": true,
+    "toRef": true,
+    "toRefs": true,
+    "toValue": true,
+    "triggerRef": true,
+    "tryOnBeforeMount": true,
+    "tryOnBeforeUnmount": true,
+    "tryOnMounted": true,
+    "tryOnScopeDispose": true,
+    "tryOnUnmounted": true,
+    "unref": true,
+    "unrefElement": true,
+    "until": true,
+    "useActiveElement": true,
+    "useAnimate": true,
+    "useArrayDifference": true,
+    "useArrayEvery": true,
+    "useArrayFilter": true,
+    "useArrayFind": true,
+    "useArrayFindIndex": true,
+    "useArrayFindLast": true,
+    "useArrayIncludes": true,
+    "useArrayJoin": true,
+    "useArrayMap": true,
+    "useArrayReduce": true,
+    "useArraySome": true,
+    "useArrayUnique": true,
+    "useAsyncQueue": true,
+    "useAsyncState": true,
+    "useAttrs": true,
+    "useBase64": true,
+    "useBattery": true,
+    "useBluetooth": true,
+    "useBreakpoints": true,
+    "useBroadcastChannel": true,
+    "useBrowserLocation": true,
+    "useCached": true,
+    "useClipboard": true,
+    "useClipboardItems": true,
+    "useCloned": true,
+    "useColorMode": true,
+    "useConfirmDialog": true,
+    "useCounter": true,
+    "useCssModule": true,
+    "useCssVar": true,
+    "useCssVars": true,
+    "useCurrentElement": true,
+    "useCycleList": true,
+    "useDark": true,
+    "useDateFormat": true,
+    "useDebounce": true,
+    "useDebounceFn": true,
+    "useDebouncedRefHistory": true,
+    "useDeviceMotion": true,
+    "useDeviceOrientation": true,
+    "useDevicePixelRatio": true,
+    "useDevicesList": true,
+    "useDisplayMedia": true,
+    "useDocumentVisibility": true,
+    "useDraggable": true,
+    "useDropZone": true,
+    "useElementBounding": true,
+    "useElementByPoint": true,
+    "useElementHover": true,
+    "useElementSize": true,
+    "useElementVisibility": true,
+    "useEventBus": true,
+    "useEventListener": true,
+    "useEventSource": true,
+    "useEyeDropper": true,
+    "useFavicon": true,
+    "useFetch": true,
+    "useFileDialog": true,
+    "useFileSystemAccess": true,
+    "useFocus": true,
+    "useFocusWithin": true,
+    "useFps": true,
+    "useFullscreen": true,
+    "useGamepad": true,
+    "useGeolocation": true,
+    "useIdle": true,
+    "useImage": true,
+    "useInfiniteScroll": true,
+    "useIntersectionObserver": true,
+    "useInterval": true,
+    "useIntervalFn": true,
+    "useKeyModifier": true,
+    "useLastChanged": true,
+    "useLink": true,
+    "useLocalStorage": true,
+    "useMagicKeys": true,
+    "useManualRefHistory": true,
+    "useMediaControls": true,
+    "useMediaQuery": true,
+    "useMemoize": true,
+    "useMemory": true,
+    "useMounted": true,
+    "useMouse": true,
+    "useMouseInElement": true,
+    "useMousePressed": true,
+    "useMutationObserver": true,
+    "useNavigatorLanguage": true,
+    "useNetwork": true,
+    "useNow": true,
+    "useObjectUrl": true,
+    "useOffsetPagination": true,
+    "useOnline": true,
+    "usePageLeave": true,
+    "useParallax": true,
+    "useParentElement": true,
+    "usePerformanceObserver": true,
+    "usePermission": true,
+    "usePointer": true,
+    "usePointerLock": true,
+    "usePointerSwipe": true,
+    "usePreferredColorScheme": true,
+    "usePreferredContrast": true,
+    "usePreferredDark": true,
+    "usePreferredLanguages": true,
+    "usePreferredReducedMotion": true,
+    "usePrevious": true,
+    "useRafFn": true,
+    "useRefHistory": true,
+    "useResizeObserver": true,
+    "useRoute": true,
+    "useRouter": true,
+    "useScreenOrientation": true,
+    "useScreenSafeArea": true,
+    "useScriptTag": true,
+    "useScroll": true,
+    "useScrollLock": true,
+    "useSessionStorage": true,
+    "useShare": true,
+    "useSlots": true,
+    "useSorted": true,
+    "useSpeechRecognition": true,
+    "useSpeechSynthesis": true,
+    "useStepper": true,
+    "useStorage": true,
+    "useStorageAsync": true,
+    "useStyleTag": true,
+    "useSupported": true,
+    "useSwipe": true,
+    "useTemplateRefsList": true,
+    "useTextDirection": true,
+    "useTextSelection": true,
+    "useTextareaAutosize": true,
+    "useThrottle": true,
+    "useThrottleFn": true,
+    "useThrottledRefHistory": true,
+    "useTimeAgo": true,
+    "useTimeout": true,
+    "useTimeoutFn": true,
+    "useTimeoutPoll": true,
+    "useTimestamp": true,
+    "useTitle": true,
+    "useToNumber": true,
+    "useToString": true,
+    "useToggle": true,
+    "useTransition": true,
+    "useUrlSearchParams": true,
+    "useUserMedia": true,
+    "useVModel": true,
+    "useVModels": true,
+    "useVibrate": true,
+    "useVirtualList": true,
+    "useWakeLock": true,
+    "useWebNotification": true,
+    "useWebSocket": true,
+    "useWebWorker": true,
+    "useWebWorkerFn": true,
+    "useWindowFocus": true,
+    "useWindowScroll": true,
+    "useWindowSize": true,
+    "watch": true,
+    "watchArray": true,
+    "watchAtMost": true,
+    "watchDebounced": true,
+    "watchDeep": true,
+    "watchEffect": true,
+    "watchIgnorable": true,
+    "watchImmediate": true,
+    "watchOnce": true,
+    "watchPausable": true,
+    "watchPostEffect": true,
+    "watchSyncEffect": true,
+    "watchThrottled": true,
+    "watchTriggerable": true,
+    "watchWithFilter": true,
+    "whenever": true
+  }
+}

+ 74 - 0
.eslintrc.cjs

@@ -0,0 +1,74 @@
+// @see: http://eslint.cn
+
+module.exports = {
+  root: true,
+  env: {
+    browser: true,
+    node: true,
+    es6: true
+  },
+  plugins: ['vue', '@typescript-eslint', 'import', 'promise', 'node', 'prettier'],
+  // 指定如何解析语法
+  parser: 'vue-eslint-parser',
+  // 优先级低于 parse 的语法解析配置
+  parserOptions: {
+    parser: '@typescript-eslint/parser',
+    ecmaVersion: 2020,
+    sourceType: 'module',
+    jsxPragma: 'React',
+    ecmaFeatures: {
+      jsx: true
+    }
+  },
+  // 继承某些已有的规则
+  extends: [
+    'plugin:vue/vue3-recommended',
+    'plugin:@typescript-eslint/recommended',
+    'plugin:prettier/recommended',
+    './.eslintrc-auto-import.json',
+    'prettier'
+  ],
+  /**
+   * "off" 或 0    ==>  关闭规则
+   * "warn" 或 1   ==>  打开的规则作为警告(不影响代码执行)
+   * "error" 或 2  ==>  规则作为一个错误(代码不能执行,界面报错)
+   */
+  rules: {
+    // eslint (http://eslint.cn/docs/rules)
+    'no-var': 'error', // 要求使用 let 或 const 而不是 var
+    'no-multiple-empty-lines': ['error', { max: 1 }], // 不允许多个空行
+    'prefer-const': 'off', // 使用 let 关键字声明但在初始分配后从未重新分配的变量,要求使用 const
+    'no-use-before-define': 'off', // 禁止在 函数/类/变量 定义之前使用它们
+    'prettier/prettier': [
+      'warn',
+      {
+        singleQuote: true,
+        semi: false
+      }
+    ],
+    // typeScript (https://typescript-eslint.io/rules)
+    '@typescript-eslint/no-unused-vars': 'error', // 禁止定义未使用的变量
+    '@typescript-eslint/no-empty-function': 'error', // 禁止空函数
+    '@typescript-eslint/prefer-ts-expect-error': 'error', // 禁止使用 @ts-ignore
+    '@typescript-eslint/ban-ts-comment': 'error', // 禁止 @ts-<directive> 使用注释或要求在指令后进行描述
+    '@typescript-eslint/no-inferrable-types': 'off', // 可以轻松推断的显式类型可能会增加不必要的冗长
+    '@typescript-eslint/no-namespace': 'off', // 禁止使用自定义 TypeScript 模块和命名空间
+    '@typescript-eslint/no-explicit-any': 'off', // 禁止使用 any 类型
+    '@typescript-eslint/ban-types': 'off', // 禁止使用特定类型
+    '@typescript-eslint/no-var-requires': 'off', // 允许使用 require() 函数导入模块
+    '@typescript-eslint/no-non-null-assertion': 'off', // 不允许使用后缀运算符的非空断言(!)
+
+    // vue (https://eslint.vuejs.org/rules)
+    'vue/script-setup-uses-vars': 'error', // 防止<script setup>使用的变量<template>被标记为未使用,此规则仅在启用该 no-unused-vars 规则时有效
+    'vue/v-slot-style': 'error', // 强制执行 v-slot 指令样式
+    'vue/no-mutating-props': 'error', // 不允许改变组件 prop
+    'vue/custom-event-name-casing': 'error', // 为自定义事件名称强制使用特定大小写
+    'vue/html-closing-bracket-newline': 'error', // 在标签的右括号之前要求或禁止换行
+    'vue/attribute-hyphenation': 'error', // 对模板中的自定义组件强制执行属性命名样式:my-prop="prop"
+    'vue/attributes-order': 'off', // vue api使用顺序,强制执行属性顺序
+    'vue/no-v-html': 'off', // 禁止使用 v-html
+    'vue/require-default-prop': 'off', // 此规则要求为每个 prop 为必填时,必须提供默认值
+    'vue/multi-word-component-names': 'off', // 要求组件名称始终为 “-” 链接的单词
+    'vue/no-setup-props-destructure': 'off' // 禁止解构 props 传递给 setup
+  }
+}

+ 26 - 0
.gitignore

@@ -0,0 +1,26 @@
+# Logs
+logs
+*.log
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+pnpm-debug.log*
+lerna-debug.log*
+
+node_modules
+dist
+dist-ssr
+stats.html
+*.local
+
+# Editor directories and files
+.vscode/*
+!.vscode/extensions.json
+!.vscode/settings.json
+.idea
+.DS_Store
+*.suo
+*.ntvs*
+*.njsproj
+*.sln
+*.sw?

+ 4 - 0
.husky/commit-msg

@@ -0,0 +1,4 @@
+#!/usr/bin/env sh
+. "$(dirname -- "$0")/_/husky.sh"
+
+npx --no-install commitlint --edit $1

+ 4 - 0
.husky/pre-commit

@@ -0,0 +1,4 @@
+#!/usr/bin/env sh
+. "$(dirname -- "$0")/_/husky.sh"
+
+npm run lint:lint-staged

+ 9 - 0
.prettierignore

@@ -0,0 +1,9 @@
+/dist/*
+.local
+/node_modules/**
+
+**/*.svg
+**/*.sh
+
+/public/*
+stats.html

+ 41 - 0
.prettierrc.cjs

@@ -0,0 +1,41 @@
+// @see: https://www.prettier.cn
+
+module.exports = {
+  // 指定最大换行长度
+  printWidth: 150,
+  // 缩进制表符宽度 | 空格数
+  tabWidth: 2,
+  // 使用制表符而不是空格缩进行 (true:制表符,false:空格)
+  useTabs: false,
+  // 结尾不用分号 (true:有,false:没有)
+  semi: false,
+  // 使用单引号 (true:单引号,false:双引号)
+  singleQuote: true,
+  // 在对象字面量中决定是否将属性名用引号括起来 可选值 "<as-needed|consistent|preserve>"
+  quoteProps: 'as-needed',
+  // 在JSX中使用单引号而不是双引号 (true:单引号,false:双引号)
+  jsxSingleQuote: false,
+  // 多行时尽可能打印尾随逗号 可选值"<none|es5|all>"
+  trailingComma: 'none',
+  // 在对象,数组括号与文字之间加空格 "{ foo: bar }" (true:有,false:没有)
+  bracketSpacing: true,
+  // 将 > 多行元素放在最后一行的末尾,而不是单独放在下一行 (true:放末尾,false:单独一行)
+  bracketSameLine: false,
+  // (x) => {} 箭头函数参数只有一个时是否要有小括号 (avoid:省略括号,always:不省略括号)
+  arrowParens: 'avoid',
+  // 指定要使用的解析器,不需要写文件开头的 @prettier
+  requirePragma: false,
+  // 可以在文件顶部插入一个特殊标记,指定该文件已使用 Prettier 格式化
+  insertPragma: false,
+  // 用于控制文本是否应该被换行以及如何进行换行
+  proseWrap: 'preserve',
+  // 在html中空格是否是敏感的 "css" - 遵守 CSS 显示属性的默认值, "strict" - 空格被认为是敏感的 ,"ignore" - 空格被认为是不敏感的
+  htmlWhitespaceSensitivity: 'css',
+  // 控制在 Vue 单文件组件中 <script> 和 <style> 标签内的代码缩进方式
+  vueIndentScriptAndStyle: false,
+  // 换行符使用 lf 结尾是 可选值 "<auto|lf|crlf|cr>"
+  endOfLine: 'auto',
+  // 这两个选项可用于格式化以给定字符偏移量(分别包括和不包括)开始和结束的代码 (rangeStart:开始,rangeEnd:结束)
+  rangeStart: 0,
+  rangeEnd: Infinity
+}

+ 4 - 0
.stylelintignore

@@ -0,0 +1,4 @@
+/dist/*
+/public/*
+public/*
+stats.html

+ 40 - 0
.stylelintrc.cjs

@@ -0,0 +1,40 @@
+// @see: https://stylelint.io
+
+module.exports = {
+  root: true,
+  // 继承某些已有的规则
+  extends: [
+    'stylelint-config-standard', // 配置 stylelint 拓展插件
+    'stylelint-config-html/vue', // 配置 vue 中 template 样式格式化
+    'stylelint-config-standard-scss', // 配置 stylelint scss 插件
+    'stylelint-config-recommended-vue/scss', // 配置 vue 中 scss 样式格式化
+    'stylelint-config-recess-order' // 配置 stylelint css 属性书写顺序插件,
+  ],
+  overrides: [
+    // 扫描 .vue/html 文件中的 <style> 标签内的样式
+    {
+      files: ['**/*.{vue,html}'],
+      customSyntax: 'postcss-html'
+    }
+  ],
+  rules: {
+    'function-url-quotes': 'always', // URL 的引号 "always(必须加上引号)"|"never(没有引号)"
+    'color-hex-length': 'long', // 指定 16 进制颜色的简写或扩写 "short(16进制简写)"|"long(16进制扩写)"
+    'rule-empty-line-before': 'never', // 要求或禁止在规则之前的空行 "always(规则之前必须始终有一个空行)"|"never(规则前绝不能有空行)"|"always-multi-line(多行规则之前必须始终有一个空行)"|"never-multi-line(多行规则之前绝不能有空行)"
+    'font-family-no-missing-generic-family-keyword': null, // 禁止在字体族名称列表中缺少通用字体族关键字
+    'scss/at-import-partial-extension': null, // 解决不能使用 @import 引入 scss 文件
+    'property-no-unknown': null, // 禁止未知的属性
+    'no-empty-source': null, // 禁止空源码
+    'selector-class-pattern': null, // 强制选择器类名的格式
+    'value-no-vendor-prefix': null, // 关闭 vendor-prefix (为了解决多行省略 -webkit-box)
+    'no-descending-specificity': null, // 不允许较低特异性的选择器出现在覆盖较高特异性的选择器
+    'value-keyword-case': null, // 解决在 scss 中使用 v-bind 大写单词报错
+    'selector-pseudo-class-no-unknown': [
+      true,
+      {
+        ignorePseudoClasses: ['global', 'v-deep', 'deep']
+      }
+    ]
+  },
+  ignoreFiles: ['**/*.js', '**/*.jsx', '**/*.tsx', '**/*.ts']
+}

+ 14 - 0
.vscode/extensions.json

@@ -0,0 +1,14 @@
+{
+  "recommendations": [
+    "vue.volar",
+    "vue.vscode-typescript-vue-plugin",
+    "hollowtree.vue-snippets",
+    "dbaeumer.vscode-eslint",
+    "stylelint.vscode-stylelint",
+    "esbenp.prettier-vscode",
+    "editorconfig.editorconfig",
+    "streetsidesoftware.code-spell-checker",
+    "syler.sass-indented",
+    "mikestead.dotenv"
+  ]
+}

+ 96 - 0
.vscode/settings.json

@@ -0,0 +1,96 @@
+{
+  "editor.formatOnSave": true,
+  "editor.codeActionsOnSave": {
+    "source.fixAll.stylelint": "explicit"
+  },
+  "stylelint.enable": true,
+  "stylelint.validate": ["css", "less", "postcss", "scss", "vue", "sass", "html"],
+  "files.eol": "\n",
+  "typescript.tsdk": "node_modules/typescript/lib",
+  "[vue]": {
+    "editor.defaultFormatter": "esbenp.prettier-vscode"
+  },
+  "[typescript]": {
+    "editor.defaultFormatter": "esbenp.prettier-vscode"
+  },
+  "[json]": {
+    "editor.defaultFormatter": "esbenp.prettier-vscode"
+  },
+  "[jsonc]": {
+    "editor.defaultFormatter": "esbenp.prettier-vscode"
+  },
+  "[javascript]": {
+    "editor.defaultFormatter": "esbenp.prettier-vscode"
+  },
+  "[typescriptreact]": {
+    "editor.defaultFormatter": "esbenp.prettier-vscode"
+  },
+  "[scss]": {
+    "editor.defaultFormatter": "esbenp.prettier-vscode"
+  },
+  "[html]": {
+    "editor.defaultFormatter": "esbenp.prettier-vscode"
+  },
+  "[markdown]": {
+    "editor.defaultFormatter": "esbenp.prettier-vscode"
+  },
+  "[less]": {
+    "editor.defaultFormatter": "esbenp.prettier-vscode"
+  },
+  "cSpell.words": [
+    "AMAP",
+    "apng",
+    "axios",
+    "Biao",
+    "brotli",
+    "cascader",
+    "commitlint",
+    "contentleft",
+    "contentright",
+    "CSDN",
+    "daterange",
+    "datetimerange",
+    "echarts",
+    "fangda",
+    "geeker",
+    "Gitee",
+    "hexs",
+    "iconfont",
+    "juejin",
+    "liquidfill",
+    "longpress",
+    "monthrange",
+    "nprogress",
+    "officedocument",
+    "openxmlformats",
+    "Pageable",
+    "persistedstate",
+    "pinia",
+    "pjpeg",
+    "Prefixs",
+    "screenfull",
+    "sortablejs",
+    "sousuo",
+    "spreadsheetml",
+    "styl",
+    "stylelint",
+    "stylelintignore",
+    "stylelintrc",
+    "suoxiao",
+    "truetype",
+    "tuichu",
+    "unplugin",
+    "unref",
+    "VITE",
+    "vuedraggable",
+    "vueuse",
+    "Vuex",
+    "wangeditor",
+    "xiala",
+    "xiaoxi",
+    "Yahei",
+    "yiwen",
+    "zhongyingwen",
+    "zhuti"
+  ]
+}

+ 0 - 0
CHANGELOG.md


+ 8 - 0
LICENSE

@@ -0,0 +1,8 @@
+MIT License
+Copyright (c) <year> <copyright holders>
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

+ 18 - 0
README.md

@@ -0,0 +1,18 @@
+# eco-web
+
+<h4 align="center">基于Vue3+vite+ts+pinia+Element-Plus后台管理</h4>
+
+# 项目功能
+
+- TablePro组件
+- FormPro组件
+- 代码自动生成
+
+```
+yarn install
+
+## 启动
+yarn serve
+```
+
+前端脚手架

+ 46 - 0
build/getEnv.ts

@@ -0,0 +1,46 @@
+import path from 'path'
+
+export function isDevFn(mode: string): boolean {
+  return mode === 'development'
+}
+
+export function isProdFn(mode: string): boolean {
+  return mode === 'production'
+}
+
+export function isTestFn(mode: string): boolean {
+  return mode === 'test'
+}
+
+/**
+ * Whether to generate package preview
+ */
+export function isReportMode(): boolean {
+  return process.env.VITE_REPORT === 'true'
+}
+
+// Read all environment variable configuration files to process.env
+export function wrapperEnv(envConf: Recordable): ViteEnv {
+  const ret: any = {}
+
+  for (const envName of Object.keys(envConf)) {
+    let realName = envConf[envName].replace(/\\n/g, '\n')
+    realName = realName === 'true' ? true : realName === 'false' ? false : realName
+    if (envName === 'VITE_PORT') realName = Number(realName)
+    if (envName === 'VITE_PROXY') {
+      try {
+        realName = JSON.parse(realName)
+      } catch (error) {}
+    }
+    ret[envName] = realName
+  }
+  return ret
+}
+
+/**
+ * Get user root directory
+ * @param dir file path
+ */
+export function getRootPath(...dir: string[]) {
+  return path.resolve(process.cwd(), ...dir)
+}

+ 84 - 0
build/plugins.ts

@@ -0,0 +1,84 @@
+import { PluginOption } from 'vite'
+import { VitePWA } from 'vite-plugin-pwa'
+import { visualizer } from 'rollup-plugin-visualizer'
+import vue from '@vitejs/plugin-vue'
+import vueJsx from '@vitejs/plugin-vue-jsx'
+import eslintPlugin from 'vite-plugin-eslint'
+import simpleHtmlPlugin from 'vite-plugin-simple-html'
+import vueSetupExtend from 'unplugin-vue-setup-extend-plus/vite'
+import createAutoImport from '../vite/plugins/auto-import'
+import createComponents from '../vite/plugins/components'
+import prismjsPlugin from '../vite/plugins/prismjs-plugin'
+import createCompression from '../vite/plugins/compression'
+import createIcons from '../vite/plugins/icons'
+import createSvgIconsPlugin from '../vite/plugins/svg-icon'
+/**
+ * 创建 vite 插件
+ * @param viteEnv
+ */
+export const createVitePlugins = (viteEnv: ViteEnv, isBuild = false): (PluginOption | PluginOption[])[] => {
+  const { VITE_GLOB_APP_TITLE, VITE_REPORT, VITE_PWA } = viteEnv
+  return [
+    vue(),
+    // vue 可以使用 jsx/tsx 语法
+    vueJsx(),
+    // esLint 报错信息显示在浏览器界面上
+    eslintPlugin(),
+    // name 可以写在 script 标签上
+    vueSetupExtend({}),
+    // vue api
+    createAutoImport(),
+    createComponents(),
+    createIcons(),
+    createSvgIconsPlugin(isBuild),
+    // 创建打包压缩配置
+    createCompression(viteEnv),
+    // 注入变量到 html 文件
+    simpleHtmlPlugin({
+      minify: true,
+      inject: {
+        data: { title: VITE_GLOB_APP_TITLE }
+      }
+    }),
+    // 代码高亮
+    prismjsPlugin(),
+    // vitePWA
+    VITE_PWA && createVitePwa(viteEnv),
+    // 是否生成包预览,分析依赖包大小做优化处理
+    VITE_REPORT && (visualizer({ filename: 'stats.html', gzipSize: true, brotliSize: true }) as PluginOption)
+  ]
+}
+
+/**
+ * @description VitePwa
+ * @param viteEnv
+ */
+const createVitePwa = (viteEnv: ViteEnv): PluginOption | PluginOption[] => {
+  const { VITE_GLOB_APP_TITLE } = viteEnv
+  return VitePWA({
+    registerType: 'autoUpdate',
+    manifest: {
+      name: VITE_GLOB_APP_TITLE,
+      short_name: VITE_GLOB_APP_TITLE,
+      theme_color: '#ffffff',
+      icons: [
+        {
+          src: '/logo.png',
+          sizes: '192x192',
+          type: 'image/png'
+        },
+        {
+          src: '/logo.png',
+          sizes: '512x512',
+          type: 'image/png'
+        },
+        {
+          src: '/logo.png',
+          sizes: '512x512',
+          type: 'image/png',
+          purpose: 'any maskable'
+        }
+      ]
+    }
+  })
+}

+ 30 - 0
build/proxy.ts

@@ -0,0 +1,30 @@
+import type { ProxyOptions } from 'vite'
+
+type ProxyItem = [string, string]
+
+type ProxyList = ProxyItem[]
+
+type ProxyTargetList = Record<string, ProxyOptions>
+
+/**
+ * 创建代理,用于解析 .env.development 代理配置
+ * @param list
+ */
+export function createProxy(list: ProxyList = []) {
+  const ret: ProxyTargetList = {}
+  for (const [prefix, target] of list) {
+    const httpsRE = /^https:\/\//
+    const isHttps = httpsRE.test(target)
+    console.log('list', list)
+    // https://github.com/http-party/node-http-proxy#options
+    ret[prefix] = {
+      target: target,
+      changeOrigin: true,
+      ws: true,
+      rewrite: path => path.replace(new RegExp(`^${prefix}`), ''),
+      // https is require secure=false
+      ...(isHttps ? { secure: false } : {})
+    }
+  }
+  return ret
+}

+ 162 - 0
commitlint.config.cjs

@@ -0,0 +1,162 @@
+// @see: https://cz-git.qbenben.com/zh/guide
+const fs = require('fs')
+const path = require('path')
+
+const scopes = fs
+  .readdirSync(path.resolve(__dirname, 'src'), { withFileTypes: true })
+  .filter(dirent => dirent.isDirectory())
+  .map(dirent => dirent.name.replace(/s$/, ''))
+
+/** @type {import('cz-git').UserConfig} */
+module.exports = {
+  ignores: [commit => commit.includes('init')],
+  extends: ['@commitlint/config-conventional'],
+  rules: {
+    // @see: https://commitlint.js.org/#/reference-rules
+    'body-leading-blank': [2, 'always'],
+    'footer-leading-blank': [1, 'always'],
+    'header-max-length': [2, 'always', 108],
+    'subject-empty': [2, 'never'],
+    'type-empty': [2, 'never'],
+    'subject-case': [0],
+    'type-enum': [
+      2,
+      'always',
+      [
+        'feat',
+        'fix',
+        'docs',
+        'style',
+        'refactor',
+        'perf',
+        'test',
+        'build',
+        'ci',
+        'chore',
+        'revert',
+        'wip',
+        'workflow',
+        'types',
+        'release'
+      ]
+    ]
+  },
+  prompt: {
+    messages: {
+      // type: "Select the type of change that you're committing:",
+      // scope: 'Denote the SCOPE of this change (optional):',
+      // customScope: 'Denote the SCOPE of this change:',
+      // subject: 'Write a SHORT, IMPERATIVE tense description of the change:\n',
+      // body: 'Provide a LONGER description of the change (optional). Use "|" to break new line:\n',
+      // breaking: 'List any BREAKING CHANGES (optional). Use "|" to break new line:\n',
+      // footerPrefixsSelect: 'Select the ISSUES type of changeList by this change (optional):',
+      // customFooterPrefixs: 'Input ISSUES prefix:',
+      // footer: 'List any ISSUES by this change. E.g.: #31, #34:\n',
+      // confirmCommit: 'Are you sure you want to proceed with the commit above?'
+      // 中文版
+      type: '选择你要提交的类型 :',
+      scope: '选择一个提交范围(可选):',
+      customScope: '请输入自定义的提交范围 :',
+      subject: '填写简短精炼的变更描述 :\n',
+      body: '填写更加详细的变更描述(可选)。使用 "|" 换行 :\n',
+      breaking: '列举非兼容性重大的变更(可选)。使用 "|" 换行 :\n',
+      footerPrefixsSelect: '选择关联issue前缀(可选):',
+      customFooterPrefixs: '输入自定义issue前缀 :',
+      footer: '列举关联issue (可选) 例如: #31, #I3244 :\n',
+      confirmCommit: '是否提交或修改commit ?'
+    },
+    types: [
+      // {
+      //   value: 'feat',
+      //   name: 'feat:     🚀  A new feature',
+      //   emoji: '🚀'
+      // },
+      // {
+      //   value: 'fix',
+      //   name: 'fix:      🧩  A bug fix',
+      //   emoji: '🧩'
+      // },
+      // {
+      //   value: 'docs',
+      //   name: 'docs:     📚  Documentation only changes',
+      //   emoji: '📚'
+      // },
+      // {
+      //   value: 'style',
+      //   name: 'style:    🎨  Changes that do not affect the meaning of the code',
+      //   emoji: '🎨'
+      // },
+      // {
+      //   value: 'refactor',
+      //   name: 'refactor: ♻️   A code change that neither fixes a bug nor adds a feature',
+      //   emoji: '♻️'
+      // },
+      // {
+      //   value: 'perf',
+      //   name: 'perf:     ⚡️  A code change that improves performance',
+      //   emoji: '⚡️'
+      // },
+      // {
+      //   value: 'test',
+      //   name: 'test:     ✅  Adding missing tests or correcting existing tests',
+      //   emoji: '✅'
+      // },
+      // {
+      //   value: 'build',
+      //   name: 'build:    📦️   Changes that affect the build system or external dependencies',
+      //   emoji: '📦️'
+      // },
+      // {
+      //   value: 'ci',
+      //   name: 'ci:       🎡  Changes to our CI configuration files and scripts',
+      //   emoji: '🎡'
+      // },
+      // {
+      //   value: 'chore',
+      //   name: "chore:    🔨  Other changes that don't modify src or test files",
+      //   emoji: '🔨'
+      // },
+      // {
+      //   value: 'revert',
+      //   name: 'revert:   ⏪️  Reverts a previous commit',
+      //   emoji: '⏪️'
+      // },
+      // {
+      //   value: 'wip',
+      //   name: 'wip:      🕔  work in process',
+      //   emoji: '🕔'
+      // },
+      // {
+      //   value: 'workflow',
+      //   name: 'workflow: 📋  workflow improvements',
+      //   emoji: '📋'
+      // },
+      // {
+      //   value: 'type',
+      //   name: 'type:     🔰  type definition file changes',
+      //   emoji: '🔰'
+      // }
+      // 中文版
+      { value: 'feat', name: '特性:   🚀  新增功能', emoji: '🚀' },
+      { value: 'fix', name: '修复:   🧩  修复缺陷', emoji: '🧩' },
+      { value: 'docs', name: '文档:   📚  文档变更', emoji: '📚' },
+      { value: 'style', name: '格式:   🎨  代码格式(不影响功能,例如空格、分号等格式修正)', emoji: '🎨' },
+      { value: 'refactor', name: '重构:   ♻️  代码重构(不包括 bug 修复、功能新增)', emoji: '♻️' },
+      { value: 'perf', name: '性能:    ⚡️  性能优化', emoji: '⚡️' },
+      { value: 'test', name: '测试:   ✅  添加疏漏测试或已有测试改动', emoji: '✅' },
+      { value: 'build', name: '构建:   📦️  构建流程、外部依赖变更(如升级 npm 包、修改 webpack 配置等)', emoji: '📦️' },
+      { value: 'ci', name: '集成:   🎡  修改 CI 配置、脚本', emoji: '🎡' },
+      { value: 'revert', name: '回退:   ⏪️  回滚 commit', emoji: '⏪️' },
+      { value: 'chore', name: '其他:   🔨  对构建过程或辅助工具和库的更改(不影响源文件、测试用例)', emoji: '🔨' },
+      { value: 'wip', name: '开发:   🕔  正在开发中', emoji: '🕔' },
+      { value: 'workflow', name: '工作流:   📋  工作流程改进', emoji: '📋' },
+      { value: 'types', name: '类型:   🔰  类型定义文件修改', emoji: '🔰' }
+    ],
+    useEmoji: true,
+    scopes: [...scopes],
+    customScopesAlign: 'bottom',
+    emptyScopesAlias: 'empty',
+    customScopesAlias: 'custom',
+    allowBreakingChanges: ['feat', 'fix']
+  }
+}

+ 105 - 0
index.html

@@ -0,0 +1,105 @@
+<!doctype html>
+<html lang="en">
+  <head>
+    <meta charset="UTF-8" />
+    <link rel="icon" type="image/svg+xml" href="/eco-1.png" />
+    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
+    <title><%= title %></title>
+  </head>
+  <body>
+    <div id="app">
+      <style>
+        html,
+        body,
+        #app {
+          width: 100%;
+          height: 100%;
+          padding: 0;
+          margin: 0;
+        }
+        .loading-box {
+          display: flex;
+          flex-direction: column;
+          align-items: center;
+          justify-content: center;
+          width: 100%;
+          height: 100%;
+        }
+        .loading-box .loading-wrap {
+          display: flex;
+          align-items: center;
+          justify-content: center;
+          padding: 98px;
+        }
+        .dot {
+          position: relative;
+          box-sizing: border-box;
+          display: inline-block;
+          width: 32px;
+          height: 32px;
+          font-size: 32px;
+          transform: rotate(45deg);
+          animation: ant-rotate 1.2s infinite linear;
+        }
+        .dot i {
+          position: absolute;
+          display: block;
+          width: 14px;
+          height: 14px;
+          background-color: #409eff;
+          border-radius: 100%;
+          opacity: 0.3;
+          transform: scale(0.75);
+          transform-origin: 50% 50%;
+          animation: ant-spin-move 1s infinite linear alternate;
+        }
+        .dot i:nth-child(1) {
+          top: 0;
+          left: 0;
+        }
+        .dot i:nth-child(2) {
+          top: 0;
+          right: 0;
+          animation-delay: 0.4s;
+        }
+        .dot i:nth-child(3) {
+          right: 0;
+          bottom: 0;
+          animation-delay: 0.8s;
+        }
+        .dot i:nth-child(4) {
+          bottom: 0;
+          left: 0;
+          animation-delay: 1.2s;
+        }
+
+        @keyframes ant-rotate {
+          to {
+            transform: rotate(405deg);
+          }
+        }
+
+        @keyframes ant-spin-move {
+          to {
+            opacity: 1;
+          }
+        }
+      </style>
+      <div class="loading-box">
+        <div class="loading-wrap">
+          <span class="dot dot-spin"><i></i><i></i><i></i><i></i></span>
+        </div>
+      </div>
+    </div>
+    <script>
+      const globalState = JSON.parse(window.localStorage.getItem('admin-global'))
+      if (globalState) {
+        const dot = document.querySelectorAll('.dot i')
+        const html = document.querySelector('html')
+        dot.forEach(item => (item.style.background = globalState.primary))
+        if (globalState.isDark) html.style.background = '#141414'
+      }
+    </script>
+    <script type="module" src="/src/main.ts"></script>
+  </body>
+</html>

+ 8 - 0
lint-staged.config.cjs

@@ -0,0 +1,8 @@
+module.exports = {
+  '*.{js,jsx,ts,tsx}': ['eslint --fix', 'prettier --write'],
+  '{!(package)*.json,*.code-snippets,.!(browserslist)*rc}': ['prettier --write--parser json'],
+  'package.json': ['prettier --write'],
+  '*.vue': ['eslint --fix', 'prettier --write', 'stylelint --fix'],
+  '*.{scss,less,styl,html}': ['stylelint --fix', 'prettier --write'],
+  '*.md': ['prettier --write']
+}

+ 142 - 0
package.json

@@ -0,0 +1,142 @@
+{
+  "name": "eco",
+  "private": true,
+  "version": "1.2.0",
+  "type": "module",
+  "description": "eco open source management system",
+  "author": {
+    "name": "gaokunw",
+    "email": "wanggaokun@wo.cn"
+  },
+  "license": "MIT",
+  "homepage": "https://gitee.com/gaokunw/eco-web",
+  "repository": {
+    "type": "git",
+    "url": "git@gitee.com:gaokunw/eco-web.git"
+  },
+  "bugs": {
+    "url": "https://gitee.com/gaokunw/eco-web/issues"
+  },
+  "scripts": {
+    "dev": "vite",
+    "serve": "vite",
+    "build:dev": "vue-tsc && vite build --mode development",
+    "build:test": "vue-tsc && vite build --mode test",
+    "build:pro": "vue-tsc && vite build --mode production",
+    "type:check": "vue-tsc --noEmit --skipLibCheck",
+    "preview": "npm run build:dev && vite preview",
+    "lint:eslint": "eslint --fix --ext .js,.ts,.vue ./src",
+    "lint:prettier": "prettier --write \"src/**/*.{js,ts,json,tsx,css,less,scss,vue,html,md}\"",
+    "lint:stylelint": "stylelint --cache --fix \"**/*.{vue,less,postcss,css,scss}\" --cache --cache-location node_modules/.cache/stylelint/",
+    "lint:lint-staged": "lint-staged",
+    "prepare": "husky install",
+    "release": "standard-version",
+    "commit": "git add -A && czg && git push"
+  },
+  "dependencies": {
+    "@element-plus/icons-vue": "^2.3.1",
+    "@types/file-saver": "^2.0.7",
+    "@types/js-cookie": "^3.0.6",
+    "@vueuse/core": "^10.11.0",
+    "@wangeditor/editor": "^5.1.23",
+    "@wangeditor/editor-for-vue": "^5.1.12",
+    "axios": "^1.7.2",
+    "crypto-js": "^4.2.0",
+    "dayjs": "^1.11.11",
+    "driver.js": "^1.3.1",
+    "echarts": "^5.5.0",
+    "echarts-liquidfill": "^3.1.0",
+    "element-plus": "^2.7.6",
+    "file-saver": "^2.0.5",
+    "image-conversion": "^2.1.1",
+    "js-cookie": "^3.0.5",
+    "jsencrypt": "^3.3.2",
+    "md5": "^2.3.0",
+    "mitt": "^3.0.1",
+    "nanoid": "^5.0.4",
+    "nprogress": "^0.2.0",
+    "pinia": "^2.1.7",
+    "pinia-plugin-persistedstate": "^3.2.1",
+    "prismjs": "^1.29.0",
+    "qs": "^6.12.1",
+    "screenfull": "^6.0.2",
+    "sortablejs": "^1.15.1",
+    "vue": "^3.4.30",
+    "vue-cropper": "^1.1.2",
+    "vue-i18n": "^9.13.1",
+    "vue-router": "^4.4.0",
+    "vue-types": "^5.1.1",
+    "vuedraggable": "^4.1.0"
+  },
+  "devDependencies": {
+    "@commitlint/cli": "^18.4.3",
+    "@commitlint/config-conventional": "^18.4.3",
+    "@types/md5": "^2.3.5",
+    "@types/nprogress": "^0.2.3",
+    "@types/prismjs": "^1.26.3",
+    "@types/qs": "^6.9.15",
+    "@types/sortablejs": "^1.15.8",
+    "@typescript-eslint/eslint-plugin": "^7.9.0",
+    "@typescript-eslint/parser": "^7.9.0",
+    "@vitejs/plugin-vue": "^5.0.4",
+    "@vitejs/plugin-vue-jsx": "^3.1.0",
+    "autoprefixer": "^10.4.19",
+    "cz-git": "1.9.2",
+    "czg": "^1.9.2",
+    "eslint": "^8.57.0",
+    "eslint-config-prettier": "^9.1.0",
+    "eslint-plugin-import": "^2.29.1",
+    "eslint-plugin-node": "^11.1.0",
+    "eslint-plugin-prettier": "^5.1.3",
+    "eslint-plugin-promise": "^6.2.0",
+    "eslint-plugin-vue": "^9.26.0",
+    "husky": "^9.0.11",
+    "lint-staged": "^15.2.5",
+    "postcss": "^8.4.38",
+    "postcss-html": "^1.7.0",
+    "prettier": "^3.2.5",
+    "rollup-plugin-visualizer": "^5.12.0",
+    "sass": "^1.77.3",
+    "standard-version": "^9.5.0",
+    "stylelint": "^16.6.1",
+    "stylelint-config-html": "^1.1.0",
+    "stylelint-config-recess-order": "^5.0.1",
+    "stylelint-config-recommended-scss": "^14.0.0",
+    "stylelint-config-recommended-vue": "^1.5.0",
+    "stylelint-config-standard": "^36.0.0",
+    "stylelint-config-standard-scss": "^13.1.0",
+    "typescript": "^5.5.2",
+    "unplugin-auto-import": "^0.17.6",
+    "unplugin-icons": "^0.19.0",
+    "unplugin-vue-components": "^0.27.0",
+    "unplugin-vue-setup-extend-plus": "^1.0.1",
+    "vite": "^5.3.1",
+    "vite-plugin-compression": "^0.5.1",
+    "vite-plugin-eslint": "^1.8.1",
+    "vite-plugin-prismjs": "^0.0.8",
+    "vite-plugin-pwa": "^0.20.0",
+    "vite-plugin-simple-html": "^0.1.0",
+    "vite-plugin-svg-icons": "^2.0.1",
+    "vue-tsc": "^2.0.22"
+  },
+  "engines": {
+    "node": ">=16.0.0"
+  },
+  "browserslist": {
+    "production": [
+      "> 1%",
+      "not dead",
+      "not op_mini all"
+    ],
+    "development": [
+      "last 1 chrome version",
+      "last 1 firefox version",
+      "last 1 safari version"
+    ]
+  },
+  "config": {
+    "commitizen": {
+      "path": "node_modules/cz-git"
+    }
+  }
+}

+ 5 - 0
postcss.config.cjs

@@ -0,0 +1,5 @@
+module.exports = {
+  plugins: {
+    autoprefixer: {}
+  }
+}

BIN
public/eco-1.png


+ 43 - 0
src/App.vue

@@ -0,0 +1,43 @@
+<template>
+  <el-config-provider :locale="locale" :size="assemblySize" :button="buttonConfig">
+    <router-view></router-view>
+  </el-config-provider>
+</template>
+
+<script setup lang="ts">
+import { useI18n } from 'vue-i18n'
+import { getBrowserLang } from '@/utils'
+import { useTheme } from '@/hooks/useTheme'
+import { ElConfigProvider } from 'element-plus'
+import { LanguageType } from './stores/interface'
+import { useGlobalStore } from '@/stores/modules/global'
+import en from 'element-plus/es/locale/lang/en'
+import zhCn from 'element-plus/es/locale/lang/zh-cn'
+
+const globalStore = useGlobalStore()
+
+// 初始化主题
+const { initTheme } = useTheme()
+initTheme()
+
+// init language
+const i18n = useI18n()
+onMounted(() => {
+  const language = globalStore.language ?? getBrowserLang()
+  i18n.locale.value = language
+  globalStore.setGlobalState('language', language as LanguageType)
+})
+
+// element language
+const locale = computed(() => {
+  if (globalStore.language == 'zh') return zhCn
+  if (globalStore.language == 'en') return en
+  return getBrowserLang() == 'zh' ? zhCn : en
+})
+
+// element assemblySize
+const assemblySize = computed(() => globalStore.assemblySize)
+
+// element button config
+const buttonConfig = reactive({ autoInsertSpace: false })
+</script>

+ 3 - 0
src/api/config/servicePort.ts

@@ -0,0 +1,3 @@
+// 后端微服务模块前缀
+export const PORT1 = '/dev-api'
+export const PORT2 = '/hooks'

+ 46 - 0
src/api/helper/axiosCancel.ts

@@ -0,0 +1,46 @@
+import { CustomAxiosRequestConfig } from '../index'
+import qs from 'qs'
+
+// 声明一个 Map 用于存储每个请求的标识 和 取消函数
+let pendingMap = new Map<string, AbortController>()
+
+// 序列化参数
+export const getPendingUrl = (config: CustomAxiosRequestConfig) =>
+  [config.method, config.url, qs.stringify(config.data), qs.stringify(config.params)].join('&')
+
+export class AxiosCanceler {
+  /**
+   * @description: 添加请求
+   * @param {Object} config
+   * @return void
+   */
+  addPending(config: CustomAxiosRequestConfig) {
+    // 在请求开始前,对之前的请求做检查取消操作
+    this.removePending(config)
+    const url = getPendingUrl(config)
+    const controller = new AbortController()
+    config.signal = controller.signal
+    pendingMap.set(url, controller)
+  }
+
+  /**
+   * @description: 移除请求
+   * @param {Object} config
+   */
+  removePending(config: CustomAxiosRequestConfig) {
+    const url = getPendingUrl(config)
+    // 如果在 pending 中存在当前请求标识,需要取消当前请求
+    const controller = pendingMap.get(url)
+    controller && controller.abort()
+  }
+
+  /**
+   * @description: 清空所有pending
+   */
+  removeAllPending() {
+    pendingMap.forEach(controller => {
+      controller && controller.abort()
+    })
+    pendingMap.clear()
+  }
+}

+ 43 - 0
src/api/helper/checkStatus.ts

@@ -0,0 +1,43 @@
+import { ElMessage } from 'element-plus'
+
+/**
+ * @description: 校验网络请求状态码
+ * @param {Number} status
+ * @return void
+ */
+export const checkStatus = (status: number) => {
+  switch (status) {
+    case 400:
+      ElMessage.error('请求失败!请您稍后重试')
+      break
+    case 401:
+      ElMessage.error('登录失效!请您重新登录')
+      break
+    case 403:
+      ElMessage.error('当前账号无权限访问!')
+      break
+    case 404:
+      ElMessage.error('你所访问的资源不存在!')
+      break
+    case 405:
+      ElMessage.error('请求方式错误!请您稍后重试')
+      break
+    case 408:
+      ElMessage.error('请求超时!请您稍后重试')
+      break
+    case 500:
+      ElMessage.error('服务异常!')
+      break
+    case 502:
+      ElMessage.error('网关错误!')
+      break
+    case 503:
+      ElMessage.error('服务不可用!')
+      break
+    case 504:
+      ElMessage.error('网关超时!')
+      break
+    default:
+      ElMessage.error('请求失败!')
+  }
+}

+ 223 - 0
src/api/index.ts

@@ -0,0 +1,223 @@
+import axios, { AxiosInstance, AxiosError, AxiosRequestConfig, InternalAxiosRequestConfig, AxiosResponse } from 'axios'
+import { showFullScreenLoading, tryHideFullScreenLoading } from '@/components/Loading/fullScreen'
+import { LOGIN_URL } from '@/config'
+import { ElMessage, ElMessageBox } from 'element-plus'
+import { ResultData } from '@/api/interface'
+import { ResultEnum } from '@/enums/httpEnum'
+import { checkStatus } from './helper/checkStatus'
+import { AxiosCanceler } from './helper/axiosCancel'
+import { useUserStore } from '@/stores/modules/user'
+import router from '@/routers'
+import { getToken } from '@/utils/token'
+import { tansParams } from '@/utils/common'
+import { nanoid } from 'nanoid'
+import cache from '@/plugins/cache'
+import { encryptBase64, encryptWithAes, generateAesKey, decryptWithAes, decryptBase64 } from '@/utils/crypto'
+import { encrypt, decrypt } from '@/utils/jsEncrypt'
+export interface CustomAxiosRequestConfig extends InternalAxiosRequestConfig {
+  loading?: boolean
+  cancel?: boolean
+  isEncrypt?: boolean
+}
+
+const config = {
+  // 默认地址请求地址,可在 .env.** 文件中修改
+  baseURL: import.meta.env.VITE_API_URL as string,
+  // 设置超时时间
+  timeout: ResultEnum.TIMEOUT as number,
+  // 跨域时候允许携带凭证
+  withCredentials: true
+}
+const encryptHeader = 'encrypt-key'
+// 是否显示重新登录
+export let isReLogin = { show: false }
+
+export const globalHeaders = () => {
+  return {
+    Authorization: 'Bearer ' + getToken(),
+    clientId: import.meta.env.VITE_APP_CLIENT_ID
+  }
+}
+axios.defaults.headers['Content-Type'] = 'application/json;charset=utf-8'
+axios.defaults.headers['clientId'] = import.meta.env.VITE_APP_CLIENT_ID
+const axiosCanceler = new AxiosCanceler()
+
+class RequestHttp {
+  service: AxiosInstance
+  public constructor(config: AxiosRequestConfig) {
+    // instantiation
+    this.service = axios.create(config)
+
+    /**
+     * @description 请求拦截器
+     * 客户端发送请求 -> [请求拦截器] -> 服务器
+     * token校验(JWT) : 接受服务器返回的 token,存储到 vuex/pinia/本地储存当中
+     */
+    this.service.interceptors.request.use(
+      (config: CustomAxiosRequestConfig) => {
+        // 是否需要加密
+        const isEncrypt = config.isEncrypt ?? (config.isEncrypt = false)
+        // 重复请求不需要取消,在 api 服务中通过指定的第三个参数: { cancel: false } 来控制
+        config.cancel ?? (config.cancel = true)
+        config.cancel && axiosCanceler.addPending(config)
+        // 当前请求不需要显示 loading,在 api 服务中通过指定的第三个参数: { loading: false } 来控制
+        config.loading ?? (config.loading = true)
+        config.loading && showFullScreenLoading()
+        // 是否需要设置 token
+        const isToken = (config.headers || {}).isToken === false
+        // 是否需要防止数据重复提交
+        const isRepeatSubmit = (config.headers || {}).repeatSubmit === false
+        const requestId = nanoid()
+        const userStore = useUserStore()
+        if (getToken() && !isToken) {
+          // 请求加上随机ID
+          config.headers.set('RequestId', requestId)
+          if (config.headers && typeof config.headers.set === 'function') {
+            config.headers.set('Authorization', 'Bearer ' + userStore.token)
+          }
+        }
+        // get请求映射params参数
+        if (config.method === 'get' && config.params) {
+          let url = config.url + '?' + tansParams(config.params)
+          url = url.slice(0, -1)
+          config.params = {}
+          config.url = url
+        }
+        if (!isRepeatSubmit && (config.method === 'post' || config.method === 'put')) {
+          const requestObj = {
+            url: config.url,
+            data: typeof config.data === 'object' ? JSON.stringify(config.data) : config.data,
+            time: new Date().getTime()
+          }
+          const sessionObj = cache.session.getJSON('sessionObj')
+          if (sessionObj === undefined || sessionObj === null || sessionObj === '') {
+            cache.session.setJSON('sessionObj', requestObj)
+          } else {
+            const s_url = sessionObj.url // 请求地址
+            const s_data = sessionObj.data // 请求数据
+            const s_time = sessionObj.time // 请求时间
+            const interval = 1000 // 间隔时间(ms),小于此时间视为重复提交
+            if (s_data === requestObj.data && requestObj.time - s_time < interval && s_url === requestObj.url) {
+              const message = '数据正在处理,请勿重复提交'
+              console.warn(`[${s_url}]: ` + message)
+              return Promise.reject(new Error(message))
+            } else {
+              cache.session.setJSON('sessionObj', requestObj)
+            }
+          }
+        }
+        // 当开启参数加密
+        if (isEncrypt && (config.method === 'post' || config.method === 'put')) {
+          // 生成一个 AES 密钥
+          const aesKey = generateAesKey()
+          config.headers[encryptHeader] = encrypt(encryptBase64(aesKey))
+          config.data = typeof config.data === 'object' ? encryptWithAes(JSON.stringify(config.data), aesKey) : encryptWithAes(config.data, aesKey)
+        }
+        // FormData数据去请求头Content-Type
+        if (config.data instanceof FormData) {
+          delete config.headers['Content-Type']
+        }
+        return config
+      },
+      (error: AxiosError) => {
+        console.log(error)
+        return Promise.reject(error)
+      }
+    )
+
+    /**
+     * @description 响应拦截器
+     *  服务器换返回信息 -> [拦截统一处理] -> 客户端JS获取到信息
+     */
+    this.service.interceptors.response.use(
+      (response: AxiosResponse & { config: CustomAxiosRequestConfig }) => {
+        const { config } = response
+        axiosCanceler.removePending(config)
+        // 加密后的 AES 秘钥
+        const keyStr = response.headers[encryptHeader]
+        // 加密
+        if (keyStr != null && keyStr != '') {
+          const data = response.data
+          // 请求体 AES 解密
+          const base64Str = decrypt(keyStr)
+          // base64 解码 得到请求头的 AES 秘钥
+          const aesKey = decryptBase64(base64Str.toString())
+          // aesKey 解码 data
+          const decryptData = decryptWithAes(data, aesKey)
+          // 将结果 (得到的是 JSON 字符串) 转为 JSON
+          response.data = JSON.parse(decryptData)
+        }
+        const { data, request } = response
+        tryHideFullScreenLoading()
+        if (request.responseType === 'blob' || request.responseType === 'arraybuffer') {
+          return data
+        }
+        // 登录失效
+        if (data.code == ResultEnum.OVERDUE) {
+          const userStore = useUserStore()
+          if (!isReLogin.show) {
+            isReLogin.show = true
+            ElMessageBox.confirm('登录状态已过期,您可以继续留在该页面,或者重新登录', '系统提示', {
+              confirmButtonText: '重新登录',
+              cancelButtonText: '取消',
+              type: 'warning'
+            })
+              .then(() => {
+                isReLogin.show = false
+                userStore.logOut().then(() => {
+                  router.replace(LOGIN_URL)
+                })
+              })
+              .catch(() => {
+                isReLogin.show = false
+              })
+          }
+          return Promise.reject('无效的会话,或者会话已过期,请重新登录。')
+        }
+        // 全局错误信息拦截(防止下载文件的时候返回数据流,没有 code 直接报错)
+        if (data.code && data.code == ResultEnum.ERROR) {
+          ElMessage.error(data.msg)
+          return Promise.reject(new Error(data.msg))
+        }
+        // 成功请求(在页面上除非特殊情况,否则不用处理失败逻辑)
+        return data
+      },
+      async (error: AxiosError) => {
+        const { response } = error
+        tryHideFullScreenLoading()
+        // 请求超时 && 网络错误单独判断,没有 response
+        if (error.message.indexOf('timeout') !== -1) ElMessage.error('请求超时!请您稍后重试')
+        if (error.message.indexOf('Network Error') !== -1) ElMessage.error('网络错误!请您稍后重试')
+        // 根据服务器响应的错误状态码,做不同的处理
+        if (response) checkStatus(response.status)
+        // 服务器结果都没有返回(可能服务器错误可能客户端断网),断网处理:可以跳转到断网页面
+        if (!window.navigator.onLine) router.replace('/500')
+        return Promise.reject(error)
+      }
+    )
+  }
+
+  /**
+   * @description 常用请求方法封装
+   */
+  get<T>(url: string, params?: object, _object = {}): Promise<ResultData<T>> {
+    return this.service.get(url, { params, ..._object })
+  }
+  post<T>(url: string, params?: object | string, _object = {}): Promise<ResultData<T>> {
+    return this.service.post(url, params, _object)
+  }
+  put<T>(url: string, params?: object, _object = {}): Promise<ResultData<T>> {
+    return this.service.put(url, params, _object)
+  }
+  delete<T>(url: string, params?: any, _object = {}): Promise<ResultData<T>> {
+    return this.service.delete(url, { params, ..._object })
+  }
+  downloadGet(url: string, params?: object, _object = {}): Promise<BlobPart> {
+    return this.service.get(url, { ..._object, responseType: 'blob' })
+  }
+  downloadPost(url: string, params?: object, _object = {}): Promise<BlobPart> {
+    return this.service.post(url, params, { ..._object, responseType: 'blob' })
+  }
+}
+
+export default new RequestHttp(config)

+ 108 - 0
src/api/interface/index.ts

@@ -0,0 +1,108 @@
+// 请求响应参数(不包含data)
+export interface Result {
+  code: string | number
+  msg: string
+}
+
+// 请求响应参数(包含data)
+export interface ResultData<T = any> extends Result {
+  data: T
+}
+
+// 分页响应参数
+export interface ResPage<T> {
+  list: T[]
+  pageNum: number
+  pageSize: number
+  total: number
+}
+
+// 分页请求参数
+export interface PageQuery {
+  pageNum: number
+  pageSize: number
+}
+
+// 分页请求参数
+export interface BaseEntity {
+  /** 乐观锁 */
+  version?: number
+  createBy?: any
+  createDept?: any
+  createTime?: string
+  updateBy?: any
+  updateTime?: any
+}
+
+// 文件上传模块
+export namespace Upload {
+  export interface ResFileUrl {
+    fileUrl: string
+  }
+}
+
+// 登录模块
+export namespace Login {
+  export interface ReqLoginForm {
+    username: string
+    password: string
+    rememberMe: boolean
+    code: string
+    uuid: string
+    clientId: string
+    grantType: string
+    tenantId: string
+  }
+  export interface ResLogin {
+    access_token: string
+  }
+  export interface ResAuthButtons {
+    [key: string]: string[]
+  }
+}
+
+// 用户管理模块
+export namespace User {
+  export interface ReqUserParams extends PageQuery {
+    username: string
+    gender: number
+    idCard: string
+    email: string
+    address: string
+    createTime: string[]
+    status: string
+  }
+  export interface ResUserList {
+    userId: number
+    id: string
+    userName: string
+    gender: number
+    user: { detail: { age: number } }
+    idCard: string
+    email: string
+    address: string
+    createTime: string
+    status: string
+    avatar: string
+    photo: any[]
+    children?: ResUserList[]
+  }
+  export interface ResStatus {
+    userLabel: string
+    userValue: number
+  }
+  export interface ResGender {
+    genderLabel: string
+    genderValue: number
+  }
+  export interface ResDepartment {
+    id: string
+    name: string
+    children?: ResDepartment[]
+  }
+  export interface ResRole {
+    id: string
+    name: string
+    children?: ResDepartment[]
+  }
+}

+ 59 - 0
src/api/interface/login.ts

@@ -0,0 +1,59 @@
+/**
+ * 注册
+ */
+export type RegisterForm = {
+  tenantId: number
+  username: string
+  password: string
+  confirmPassword?: string
+  code?: string
+  uuid?: string
+  userType?: string
+}
+
+/**
+ * 登录请求
+ */
+export interface LoginData {
+  tenantId?: number | string
+  username: string
+  password: string
+  rememberMe?: boolean
+  socialCode?: string
+  socialState?: string
+  source?: string
+  code?: string
+  uuid?: string
+  clientId: string
+  grantType: string
+}
+
+/**
+ * 登录响应
+ */
+export interface LoginResult {
+  access_token: string
+}
+
+/**
+ * 验证码返回
+ */
+export interface VerifyCodeResult {
+  captchaEnabled: boolean
+  uuid?: string
+  img?: string
+}
+
+/**
+ * 租户
+ */
+export interface TenantVO {
+  companyName: string
+  domain: any
+  tenantId: string
+}
+
+export interface TenantInfo {
+  tenantEnabled: boolean
+  voList: TenantVO[]
+}

+ 29 - 0
src/api/interface/menu.ts

@@ -0,0 +1,29 @@
+import { PageQuery } from '@/api/interface/index'
+// 用户管理模块
+export namespace Menu {
+  export interface ReqMenuParams extends PageQuery {
+    username: string
+    gender: number
+    idCard: string
+    email: string
+    address: string
+    createTime: string[]
+    status: number
+  }
+  export interface ResMenuList {
+    menuId: string
+    menuName: string
+    parentName: string
+    parentId: number
+    orderNum: number
+    path: string
+    component: string
+    query: string
+    isFrame: string
+    isCache: string
+    menuType: string
+    visible: string
+    status: string
+    children?: ResMenuList[]
+  }
+}

+ 176 - 0
src/api/interface/monitor/logininfor.ts

@@ -0,0 +1,176 @@
+import { PageQuery, BaseEntity } from '@/api/interface/index'
+export interface LogininforVO extends BaseEntity {
+  /**
+   * 访问ID
+   */
+  infoId: string | number
+
+  /**
+   * 用户账号
+   */
+  userName: string
+
+  /**
+   * 客户端
+   */
+  clientKey: string
+
+  /**
+   * 设备类型
+   */
+  deviceType: string
+
+  /**
+   * 登录IP地址
+   */
+  ipaddr: string
+
+  /**
+   * 登录地点
+   */
+  loginLocation: string
+
+  /**
+   * 浏览器类型
+   */
+  browser: string
+
+  /**
+   * 操作系统
+   */
+  os: string
+
+  /**
+   * 登录状态(1成功 0失败)
+   */
+  status: string
+
+  /**
+   * 提示消息
+   */
+  msg: string
+
+  /**
+   * 访问时间
+   */
+  loginTime: string
+}
+
+export interface LogininforForm {
+  /**
+   * 访问ID
+   */
+  infoId?: string | number
+
+  /**
+   * 用户账号
+   */
+  userName?: string
+
+  /**
+   * 客户端
+   */
+  clientKey?: string
+
+  /**
+   * 设备类型
+   */
+  deviceType?: string
+
+  /**
+   * 登录IP地址
+   */
+  ipaddr?: string
+
+  /**
+   * 登录地点
+   */
+  loginLocation?: string
+
+  /**
+   * 浏览器类型
+   */
+  browser?: string
+
+  /**
+   * 操作系统
+   */
+  os?: string
+
+  /**
+   * 登录状态(1成功 0失败)
+   */
+  status?: string
+
+  /**
+   * 提示消息
+   */
+  msg?: string
+
+  /**
+   * 访问时间
+   */
+  loginTime?: string
+}
+
+export interface LogininforQuery extends PageQuery {
+  /**
+   * 访问ID
+   */
+  infoId?: string | number
+
+  /**
+   * 用户账号
+   */
+  userName?: string
+
+  /**
+   * 客户端
+   */
+  clientKey?: string
+
+  /**
+   * 设备类型
+   */
+  deviceType?: string
+
+  /**
+   * 登录IP地址
+   */
+  ipaddr?: string
+
+  /**
+   * 登录地点
+   */
+  loginLocation?: string
+
+  /**
+   * 浏览器类型
+   */
+  browser?: string
+
+  /**
+   * 操作系统
+   */
+  os?: string
+
+  /**
+   * 登录状态(1成功 0失败)
+   */
+  status?: string
+
+  /**
+   * 提示消息
+   */
+  msg?: string
+
+  /**
+   * 访问时间
+   */
+  loginTime?: string
+
+  /**
+   * 日期范围参数
+   */
+  params?: any
+}

+ 266 - 0
src/api/interface/monitor/operlog.ts

@@ -0,0 +1,266 @@
+import { PageQuery, BaseEntity } from '@/api/interface/index'
+export interface OperLogVO extends BaseEntity {
+  /**
+   * 日志主键
+   */
+  operId: string | number
+
+  /**
+   * 模块标题
+   */
+  title: string
+
+  /**
+   * 业务类型(0其它 1新增 2修改 3删除)
+   */
+  businessType: number
+
+  /**
+   * 方法名称
+   */
+  method: string
+
+  /**
+   * 请求方式
+   */
+  requestMethod: string
+
+  /**
+   * 操作类别(0其它 1后台用户 2手机端用户)
+   */
+  operatorType: number
+
+  /**
+   * 操作人员
+   */
+  operName: string
+
+  /**
+   * 部门名称
+   */
+  deptName: string
+
+  /**
+   * 请求URL
+   */
+  operUrl: string
+
+  /**
+   * 主机地址
+   */
+  operIp: string
+
+  /**
+   * 操作地点
+   */
+  operLocation: string
+
+  /**
+   * 请求参数
+   */
+  operParam: string
+
+  /**
+   * 返回参数
+   */
+  jsonResult: string
+
+  /**
+   * 操作状态(1正常 0异常)
+   */
+  status: number
+
+  /**
+   * 错误消息
+   */
+  errorMsg: string
+
+  /**
+   * 操作时间
+   */
+  operTime: string
+
+  /**
+   * 消耗时间
+   */
+  costTime: number
+}
+
+export interface OperLogForm {
+  /**
+   * 日志主键
+   */
+  operId?: string | number
+
+  /**
+   * 模块标题
+   */
+  title?: string
+
+  /**
+   * 业务类型(0其它 1新增 2修改 3删除)
+   */
+  businessType?: number
+
+  /**
+   * 方法名称
+   */
+  method?: string
+
+  /**
+   * 请求方式
+   */
+  requestMethod?: string
+
+  /**
+   * 操作类别(0其它 1后台用户 2手机端用户)
+   */
+  operatorType?: number
+
+  /**
+   * 操作人员
+   */
+  operName?: string
+
+  /**
+   * 部门名称
+   */
+  deptName?: string
+
+  /**
+   * 请求URL
+   */
+  operUrl?: string
+
+  /**
+   * 主机地址
+   */
+  operIp?: string
+
+  /**
+   * 操作地点
+   */
+  operLocation?: string
+
+  /**
+   * 请求参数
+   */
+  operParam?: string
+
+  /**
+   * 返回参数
+   */
+  jsonResult?: string
+
+  /**
+   * 操作状态(1正常 0异常)
+   */
+  status?: number
+
+  /**
+   * 错误消息
+   */
+  errorMsg?: string
+
+  /**
+   * 操作时间
+   */
+  operTime?: string
+
+  /**
+   * 消耗时间
+   */
+  costTime?: number
+}
+
+export interface OperLogQuery extends PageQuery {
+  /**
+   * 日志主键
+   */
+  operId?: string | number
+
+  /**
+   * 模块标题
+   */
+  title?: string
+
+  /**
+   * 业务类型(0其它 1新增 2修改 3删除)
+   */
+  businessType?: number
+
+  /**
+   * 方法名称
+   */
+  method?: string
+
+  /**
+   * 请求方式
+   */
+  requestMethod?: string
+
+  /**
+   * 操作类别(0其它 1后台用户 2手机端用户)
+   */
+  operatorType?: number
+
+  /**
+   * 操作人员
+   */
+  operName?: string
+
+  /**
+   * 部门名称
+   */
+  deptName?: string
+
+  /**
+   * 请求URL
+   */
+  operUrl?: string
+
+  /**
+   * 主机地址
+   */
+  operIp?: string
+
+  /**
+   * 操作地点
+   */
+  operLocation?: string
+
+  /**
+   * 请求参数
+   */
+  operParam?: string
+
+  /**
+   * 返回参数
+   */
+  jsonResult?: string
+
+  /**
+   * 操作状态(1正常 0异常)
+   */
+  status?: number
+
+  /**
+   * 错误消息
+   */
+  errorMsg?: string
+
+  /**
+   * 操作时间
+   */
+  operTime?: string
+
+  /**
+   * 消耗时间
+   */
+  costTime?: number
+
+  /**
+   * 日期范围参数
+   */
+  params?: any
+}

+ 25 - 0
src/api/interface/system/config.ts

@@ -0,0 +1,25 @@
+import { PageQuery, BaseEntity } from '@/api/interface/index'
+export interface ConfigVO extends BaseEntity {
+  configId: number | string
+  configName: string
+  configKey: string
+  configValue: string
+  configType: string
+  remark: string
+}
+
+export interface ConfigForm {
+  configId: number | string | undefined
+  configName: string
+  configKey: string
+  configValue: string
+  configType: string
+  version: number
+  remark: string
+}
+
+export interface ConfigQuery extends PageQuery {
+  configName: string
+  configKey: string
+  configType: string
+}

+ 28 - 0
src/api/interface/system/data.ts

@@ -0,0 +1,28 @@
+import { PageQuery, BaseEntity } from '@/api/interface/index'
+export interface DictDataQuery extends PageQuery {
+  dictName: string
+  dictType: string
+  dictLabel: string
+}
+
+export interface DictDataVO extends BaseEntity {
+  dictCode: string
+  dictLabel: string
+  dictValue: string
+  cssClass: string
+  listClass: ElTagType
+  dictSort: number
+  remark: string
+}
+
+export interface DictDataForm {
+  dictType?: string
+  dictCode: string | undefined
+  dictLabel: string
+  dictValue: string
+  cssClass: string
+  listClass: ElTagType
+  dictSort: number
+  version: number
+  remark: string
+}

+ 47 - 0
src/api/interface/system/dept.ts

@@ -0,0 +1,47 @@
+import { PageQuery, BaseEntity } from '@/api/interface/index'
+/**
+ * 部门查询参数
+ */
+export interface DeptQuery extends PageQuery {
+  deptName?: string
+  status?: number
+}
+
+/**
+ * 部门类型
+ */
+export interface DeptVO extends BaseEntity {
+  id: number | string
+  parentName: string
+  parentId: number | string
+  children: DeptVO[]
+  deptId: number | string
+  deptName: string
+  orderNum: number
+  leader: string
+  phone: string
+  email: string
+  status: string
+  delFlag: string
+  ancestors: string
+  menuId: string | number
+}
+
+/**
+ * 部门表单类型
+ */
+export interface DeptForm {
+  parentName?: string
+  parentId?: number | string
+  children?: DeptForm[]
+  deptId?: number | string
+  deptName?: string
+  orderNum?: number
+  leader?: string
+  phone?: string
+  email?: string
+  status?: string
+  version?: number
+  delFlag?: string
+  ancestors?: string
+}

+ 96 - 0
src/api/interface/system/importExport.ts

@@ -0,0 +1,96 @@
+import { PageQuery, BaseEntity } from '@/api/interface/index'
+export interface ImportExportVO extends BaseEntity {
+  /**
+   * 唯一编码
+   */
+  id: string | number
+
+  /**
+   * 文件名称
+   */
+  name: string
+
+  /**
+   * 文件地址
+   */
+  url: string
+
+  /**
+   * 日志信息
+   */
+  logInfo: string
+
+  /**
+   * 状态(1正常  0异常)
+   */
+  status: string
+
+  /**
+   * 文件Id
+   */
+  ossId: number
+}
+
+export interface ImportExportForm {
+  /**
+   * 唯一编码
+   */
+  id?: string | number
+
+  /**
+   * 文件名称
+   */
+  name?: string
+
+  /**
+   * 文件地址
+   */
+  url?: string
+
+  /**
+   * 文件地址
+   */
+  ossId?: number
+
+  /**
+   * 日志信息
+   */
+  logInfo?: string
+
+  /**
+   * 状态(1正常  0异常)
+   */
+  status?: number
+
+  /**
+   * 乐观锁
+   */
+  version?: number
+}
+
+export interface ImportExportQuery extends PageQuery {
+  /**
+   * 文件名称
+   */
+  name?: string
+
+  /**
+   * 文件地址
+   */
+  url?: string
+
+  /**
+   * 日志信息
+   */
+  logInfo?: string
+
+  /**
+   * 状态(1正常  0异常)
+   */
+  status?: number
+
+  /**
+   * 日期范围参数
+   */
+  params?: any
+}

+ 71 - 0
src/api/interface/system/menu.ts

@@ -0,0 +1,71 @@
+import { MenuTypeEnum } from '@/enums/MenuTypeEnum'
+import { BaseEntity } from '@/api/interface/index'
+
+/**
+ * 菜单树形结构类型
+ */
+export interface MenuTreeOption {
+  id: string | number
+  label: string
+  parentId: string | number
+  weight: number
+  children?: MenuTreeOption[]
+}
+
+export interface RoleMenuTree {
+  menus: MenuTreeOption[]
+  checkedKeys: string[]
+}
+
+/**
+ * 菜单查询参数类型
+ */
+export interface MenuQuery {
+  keywords?: string
+  menuName?: string
+  status?: string
+}
+
+/**
+ * 菜单视图对象类型
+ */
+export interface MenuVO extends BaseEntity {
+  parentName: string
+  parentId: string | number
+  children: MenuVO[]
+  menuId: string | number
+  menuName: string
+  orderNum: number
+  path: string
+  component: string
+  queryParam: string
+  isFrame: string
+  isCache: string
+  menuType: MenuTypeEnum
+  visible: string
+  status: string
+  icon: string
+  remark: string
+}
+
+export interface MenuForm {
+  parentName?: string
+  parentId?: string | number
+  children?: MenuForm[]
+  menuId?: string | number
+  menuName: string
+  orderNum: number
+  path: string
+  component?: string
+  queryParam?: string
+  isFrame?: string
+  isCache?: string
+  menuType?: MenuTypeEnum
+  visible?: string
+  status?: string
+  icon?: string
+  remark?: string
+  query?: string
+  perms?: string
+  version?: number
+}

+ 24 - 0
src/api/interface/system/oss.ts

@@ -0,0 +1,24 @@
+import { PageQuery, BaseEntity } from '@/api/interface/index'
+
+export interface OssVO extends BaseEntity {
+  ossId: string | number
+  fileName: string
+  originalName: string
+  fileSuffix: string
+  url: string
+  createByName: string
+  service: string
+}
+
+export interface OssQuery extends PageQuery {
+  fileName: string
+  originalName: string
+  fileSuffix: string
+  createTime: string
+  service: string
+  orderByColumn: string
+  isAsc: string
+}
+export interface OssForm {
+  file: undefined | string
+}

+ 41 - 0
src/api/interface/system/ossConfig.ts

@@ -0,0 +1,41 @@
+import { PageQuery, BaseEntity } from '@/api/interface/index'
+
+export interface OssConfigVO extends BaseEntity {
+  ossConfigId: number | string
+  configKey: string
+  accessKey: string
+  secretKey: string
+  bucketName: string
+  prefix: string
+  endpoint: string
+  domain: string
+  isHttps: string
+  region: string
+  status: string
+  ext1: string
+  remark: string
+  accessPolicy: string
+}
+
+export interface OssConfigQuery extends PageQuery {
+  configKey: string
+  bucketName: string
+  status: string
+}
+
+export interface OssConfigForm {
+  ossConfigId: string | number | undefined
+  configKey: string
+  accessKey: string
+  secretKey: string
+  bucketName: string
+  prefix: string
+  endpoint: string
+  domain: string
+  isHttps: string
+  accessPolicy: string
+  region: string
+  status: string
+  version: number
+  remark: string
+}

+ 25 - 0
src/api/interface/system/post.ts

@@ -0,0 +1,25 @@
+import { PageQuery, BaseEntity } from '@/api/interface/index'
+export interface PostVO extends BaseEntity {
+  postId: number | string
+  postCode: string
+  postName: string
+  postSort: number
+  status: string
+  remark: string
+}
+
+export interface PostForm {
+  postId: number | string | undefined
+  postCode: string
+  postName: string
+  postSort: number
+  status: string
+  version: number
+  remark: string
+}
+
+export interface PostQuery extends PageQuery {
+  postCode: string
+  postName: string
+  status: string
+}

+ 54 - 0
src/api/interface/system/role.ts

@@ -0,0 +1,54 @@
+import { PageQuery, BaseEntity } from '@/api/interface/index'
+/**
+ * 菜单树形结构类型
+ */
+export interface DeptTreeOption {
+  id: string
+  label: string
+  parentId: string
+  weight: number
+  children?: DeptTreeOption[]
+}
+
+export interface RoleDeptTree {
+  checkedKeys: string[]
+  depts: DeptTreeOption[]
+}
+
+export interface RoleVO extends BaseEntity {
+  roleId: string | number
+  roleName: string
+  roleKey: string
+  roleSort: number
+  dataScope: string
+  menuCheckStrictly: boolean
+  deptCheckStrictly: boolean
+  status: string
+  delFlag: string
+  remark?: any
+  flag: boolean
+  menuIds?: Array<string | number>
+  deptIds?: Array<string | number>
+  admin: boolean
+}
+
+export interface RoleQuery extends PageQuery {
+  roleName: string
+  roleKey: string
+  status: string
+}
+
+export interface RoleForm {
+  roleName: string
+  roleKey: string
+  roleSort: number
+  status: string
+  menuCheckStrictly: boolean
+  deptCheckStrictly: boolean
+  remark: string
+  dataScope?: string
+  roleId: string | undefined
+  menuIds: Array<string | number>
+  deptIds: Array<string | number>
+  version?: number
+}

+ 20 - 0
src/api/interface/system/type.ts

@@ -0,0 +1,20 @@
+import { PageQuery, BaseEntity } from '@/api/interface/index'
+export interface DictTypeVO extends BaseEntity {
+  dictId: number | string
+  dictName: string
+  dictType: string
+  remark: string
+}
+
+export interface DictTypeForm {
+  dictId: number | string | undefined
+  dictName: string
+  dictType: string
+  version: number
+  remark: string
+}
+
+export interface DictTypeQuery extends PageQuery {
+  dictName: string
+  dictType: string
+}

+ 87 - 0
src/api/interface/system/user.ts

@@ -0,0 +1,87 @@
+import { RoleVO } from '@/api/interface/system/role'
+import { PostVO } from '@/api/interface/system/post'
+import { DeptVO } from '@/api/interface/system/dept'
+import { PageQuery, BaseEntity } from '@/api/interface/index'
+/**
+ * 用户信息
+ */
+export interface UserInfo {
+  user: UserVO
+  roles: string[]
+  permissions: string[]
+}
+
+/**
+ * 用户查询对象类型
+ */
+export interface UserQuery extends PageQuery {
+  userName?: string
+  phonenumber?: string
+  status?: string
+  deptId?: string | number
+  roleId?: string | number
+}
+
+/**
+ * 用户返回对象
+ */
+export interface UserVO extends BaseEntity {
+  userId: string | number
+  deptId: number
+  userName: string
+  nickName: string
+  userType: string
+  email: string
+  phonenumber: string
+  dept: DeptVO
+  gender: string
+  avatar: string
+  url: string
+  status: string
+  delFlag: string
+  loginIp: string
+  loginDate: string
+  remark: string
+  deptName: string
+  roles: RoleVO[]
+  roleIds: any
+  postIds: any
+  roleId: any
+  admin: boolean
+}
+
+/**
+ * 用户表单类型
+ */
+export interface UserForm {
+  id?: string
+  userId?: string
+  deptId?: number
+  userName: string
+  nickName?: string
+  password: string
+  phonenumber?: string
+  email?: string
+  gender?: string
+  status: string
+  remark?: string
+  postIds: string[]
+  roleIds: string[]
+  version?: number
+}
+
+export interface UserInfoVO {
+  user: UserVO
+  roles: RoleVO[]
+  roleIds: string[]
+  posts: PostVO[]
+  postIds: string[]
+  roleGroup: string
+  postGroup: string
+}
+
+export interface ResetPwdForm {
+  oldPassword: string
+  newPassword: string
+  confirmPassword: string
+}

+ 175 - 0
src/api/interface/tool/gen.ts

@@ -0,0 +1,175 @@
+import { PageQuery, BaseEntity } from '@/api/interface/index'
+export interface TableVO extends BaseEntity {
+  tableId: string | number
+  tableName: string
+  tableComment: string
+  subTableName?: any
+  subTableFkName?: any
+  className: string
+  tplCategory: string
+  packageName: string
+  moduleName: string
+  businessName: string
+  functionName: string
+  functionAuthor: string
+  genType: string
+  genPath: string
+  pkColumn?: any
+  columns?: any
+  options?: any
+  remark?: any
+  treeCode?: any
+  treeParentCode?: any
+  treeName?: any
+  menuIds?: any
+  parentMenuId?: any
+  parentMenuName?: any
+  tree: boolean
+  crud: boolean
+  editColumns: number
+}
+
+export interface TableQuery extends PageQuery {
+  tableName: string
+  tableComment: string
+}
+
+export interface DbColumnVO extends BaseEntity {
+  columnId?: any
+  tableId?: any
+  columnName?: any
+  columnComment?: any
+  columnType?: any
+  javaType?: any
+  javaField?: any
+  isPk?: any
+  isIncrement?: any
+  isRequired?: any
+  isInsert?: any
+  isEdit?: any
+  isList?: any
+  isQuery?: any
+  queryType?: any
+  htmlType?: any
+  dictType?: any
+  sort?: any
+  increment: boolean
+  capJavaField?: any
+  usableColumn: boolean
+  superColumn: boolean
+  list: boolean
+  pk: boolean
+  insert: boolean
+  edit: boolean
+  query: boolean
+  required: boolean
+}
+
+export interface DbTableVO {
+  tableId?: any
+  tableName: string
+  tableComment: string
+  subTableName?: any
+  subTableFkName?: any
+  className?: any
+  tplCategory?: any
+  packageName?: any
+  moduleName?: any
+  businessName?: any
+  functionName?: any
+  functionAuthor?: any
+  genType?: any
+  genPath?: any
+  pkColumn?: any
+  columns: DbColumnVO[]
+  options?: any
+  remark?: any
+  treeCode?: any
+  treeParentCode?: any
+  treeName?: any
+  menuIds?: any
+  parentMenuId?: any
+  parentMenuName?: any
+  tree: boolean
+  crud: boolean
+  version?: number
+}
+
+export interface DbTableQuery extends PageQuery {
+  tableName: string
+  tableComment: string
+}
+
+export interface GenTableVO {
+  info: DbTableVO
+  rows: DbColumnVO[]
+  tables: DbTableVO[]
+}
+
+export interface DbColumnForm extends BaseEntity {
+  columnId: string
+  tableId: string
+  columnName: string
+  columnComment: string
+  columnType: string
+  javaType: string
+  javaField: string
+  isPk: string
+  isIncrement: string
+  isRequired: string
+  isInsert?: any
+  isEdit: string
+  isList: string
+  isQuery?: any
+  queryType: string
+  htmlType: string
+  dictType: string
+  sort: number
+  increment: boolean
+  capJavaField: string
+  usableColumn: boolean
+  superColumn: boolean
+  list: boolean
+  pk: boolean
+  insert: boolean
+  edit: boolean
+  query: boolean
+  required: boolean
+}
+
+export interface DbParamForm {
+  treeCode?: any
+  treeName?: any
+  treeParentCode?: any
+  parentMenuId: string
+}
+
+export interface DbTableForm extends BaseEntity {
+  tableId: string | string
+  tableName: string
+  tableComment: string
+  subTableName?: any
+  subTableFkName?: any
+  className: string
+  tplCategory: string
+  packageName: string
+  moduleName: string
+  businessName: string
+  functionName: string
+  functionAuthor: string
+  genType: string
+  genPath: string
+  pkColumn?: any
+  columns: DbColumnForm[]
+  options: string
+  remark?: any
+  treeCode?: any
+  treeParentCode?: any
+  treeName?: any
+  menuIds?: any
+  parentMenuId: string
+  parentMenuName?: any
+  tree: boolean
+  crud: boolean
+  params: DbParamForm
+}

+ 26 - 0
src/api/modules/login.ts

@@ -0,0 +1,26 @@
+import { UserInfo } from '@/api/interface/system/user'
+import { LoginData, LoginResult, VerifyCodeResult } from '@/api/interface/login'
+import http from '@/api'
+
+/**
+ *
+ * 用户登录
+ * @param data {LoginData}
+ */
+export const loginApi = (data: LoginData) => {
+  return http.post<LoginResult>('/auth/login', data, { loading: true, isEncrypt: true }) // 正常 post json 请求  ==>  application/json
+}
+
+// 用户退出登录
+export const logoutApi = () => {
+  return http.post('/auth/logout', {}, { loading: false })
+}
+
+// 获取用户详细信息
+export const getInfoApi = () => {
+  return http.get<UserInfo>('/system/user/getInfo', {}, { loading: false })
+}
+// 获取验证码
+export const getCodeImg = () => {
+  return http.get<VerifyCodeResult>('/captchaImage', {}, { loading: false })
+}

+ 34 - 0
src/api/modules/monitor/logininfor.ts

@@ -0,0 +1,34 @@
+import http from '@/api'
+import { LogininforVO, LogininforQuery } from '@/api/interface/monitor/logininfor'
+/**
+ * @name 查询系统访问记录列表
+ * @param query 参数
+ * @returns 返回列表
+ */
+export const listLogininforApi = (query: LogininforQuery) => {
+  return http.get<LogininforVO[]>('/monitor/logininfor/list', query, { loading: true })
+}
+
+/**
+ * @name 删除系统访问记录
+ * @param infoId infoId
+ * @returns returns
+ */
+export const delLogininforApi = (infoId: string | number | Array<string | number>) => {
+  return http.delete<any>(`/monitor/logininfor/${infoId}`)
+}
+
+/**
+ * @name 导出数据
+ * @returns returns
+ */
+export const exportLogininforApi = (data: any) => {
+  return http.downloadPost('/monitor/logininfor/export', data)
+}
+
+/**
+ * @name 清空日志
+ */
+export const cleanLoginInfoApi = () => {
+  return http.delete<any>(`/monitor/logininfor/clean`)
+}

+ 43 - 0
src/api/modules/monitor/operlog.ts

@@ -0,0 +1,43 @@
+import http from '@/api'
+import { OperLogVO, OperLogQuery } from '@/api/interface/monitor/operlog'
+/**
+ * @name 查询操作日志记录列表
+ * @param query 参数
+ * @returns 返回列表
+ */
+export const listOperLogApi = (query: OperLogQuery) => {
+  return http.get<OperLogVO[]>('/monitor/operlog/list', query, { loading: true })
+}
+
+/**
+ * @name 查询操作日志记录详细
+ * @param operId operId
+ * @returns returns
+ */
+export const getOperLogApi = (operId: string | number) => {
+  return http.get<OperLogVO>(`/monitor/operlog/${operId}`)
+}
+
+/**
+ * @name 删除操作日志记录
+ * @param operId operId
+ * @returns returns
+ */
+export const delOperLogApi = (operId: string | number | Array<string | number>) => {
+  return http.delete<any>(`/monitor/operlog/${operId}`)
+}
+
+/**
+ * @name 导出数据
+ * @returns returns
+ */
+export const exportOperLogApi = (data: any) => {
+  return http.downloadPost('/monitor/operlog/export', data)
+}
+
+/**
+ * @name 清空操作日志
+ */
+export const cleanOperlogApi = () => {
+  return http.delete<any>(`/monitor/operlog/clean`)
+}

+ 78 - 0
src/api/modules/system/config.ts

@@ -0,0 +1,78 @@
+import { ConfigVO } from '@/api/interface/system/config'
+import http from '@/api'
+/**
+ * @name 根据参数键名查询参数值
+ * @param ossConfigId ossConfigId
+ * @returns returns
+ */
+export const getConfigKeyApi = (configKey: string) => {
+  return http.get<ConfigVO>(`/system/config/configKey/${configKey}`)
+}
+/**
+ * @name 查询参数配置列表
+ * @param query 参数
+ * @returns 返回列表
+ */
+export const listConfigApi = (query: any) => {
+  return http.get<any>('/system/config/list', query, { loading: true })
+}
+
+/**
+ * @name 查询参数配置详细
+ * @param configId configId
+ * @returns returns
+ */
+export const getConfigApi = (configId: any) => {
+  return http.get<any>(`/system/config/${configId}`)
+}
+
+/**
+ * @name 新增参数配置
+ * @param data data
+ * @returns returns
+ */
+export const addConfigApi = (data: any) => {
+  return http.post<any>('/system/config', data, { loading: false })
+}
+
+/**
+ * @name 修改参数配置
+ * @param data data
+ * @returns returns
+ */
+export const updateConfigApi = (data: any) => {
+  return http.put<any>('/system/config', data, { loading: false })
+}
+/**
+ * @name 修改参数配置
+ * @param data data
+ * @returns returns
+ */
+export const updateConfigByKeyApi = (data: any) => {
+  return http.put<any>('/system/config/updateByKey', data, { loading: false })
+}
+
+/**
+ * @name 删除参数配置
+ * @param configId configId
+ * @returns returns
+ */
+export const delConfigApi = (configId: any) => {
+  return http.delete<any>(`/system/config/${configId}`)
+}
+
+/**
+ * @name 刷新参数缓存
+ * @returns returns
+ */
+export const refreshCacheApi = () => {
+  return http.delete<any>(`/system/config/refreshCache`)
+}
+
+/**
+ * @name 导出数据
+ * @returns returns
+ */
+export const exportConfigApi = (data: any) => {
+  return http.downloadPost('/system/config/export', data)
+}

+ 46 - 0
src/api/modules/system/dept.ts

@@ -0,0 +1,46 @@
+import http from '@/api'
+import { DeptForm, DeptQuery, DeptVO } from '@/api/interface/system/dept'
+/**
+ * @name 查询部门列表
+ * @param query 参数
+ * @returns 返回列表
+ */
+export const listDeptApi = (query: DeptQuery) => {
+  return http.get<any>('/system/dept/list', query, { loading: true })
+}
+
+/**
+ * @name 查询部门详细
+ * @param deptId deptId
+ * @returns returns
+ */
+export const getDeptApi = (deptId: string | number) => {
+  return http.get<DeptVO>(`/system/dept/${deptId}`)
+}
+
+/**
+ * @name 新增部门
+ * @param data data
+ * @returns returns
+ */
+export const addDeptApi = (data: DeptForm) => {
+  return http.post<any>('/system/dept', data, { loading: false })
+}
+
+/**
+ * @name 修改部门
+ * @param data data
+ * @returns returns
+ */
+export const updateDeptApi = (data: DeptForm) => {
+  return http.put<any>('/system/dept', data, { loading: false })
+}
+
+/**
+ * @name 删除部门
+ * @param deptId deptId
+ * @returns returns
+ */
+export const delDeptApi = (deptId: number | string) => {
+  return http.delete<any>(`/system/dept/${deptId}`)
+}

+ 69 - 0
src/api/modules/system/dict.ts

@@ -0,0 +1,69 @@
+import http from '@/api'
+import { DictTypeForm, DictTypeVO, DictTypeQuery } from '@/api/interface/system/type'
+/**
+ * @name 查询字典类型列表
+ * @param query 参数
+ * @returns 返回列表
+ */
+export const listDictApi = (query: DictTypeQuery) => {
+  return http.get<DictTypeVO[]>('/system/dict/type/list', query, { loading: false })
+}
+
+/**
+ * @name 查询字典类型详细
+ * @param dictId dictId
+ * @returns returns
+ */
+export const getDictApi = (dictId: string | number) => {
+  return http.get<any>(`/system/dict/type/${dictId}`)
+}
+
+/**
+ * @name 新增字典类型
+ * @param data data
+ * @returns returns
+ */
+export const addDictApi = (data: DictTypeForm) => {
+  return http.post<any>('/system/dict/type', data, { loading: false })
+}
+
+/**
+ * @name 修改字典类型
+ * @param data data
+ * @returns returns
+ */
+export const updateDictApi = (data: DictTypeForm) => {
+  return http.put<any>('/system/dict/type', data, { loading: false })
+}
+
+/**
+ * @name 删除字典类型
+ * @param dictId dictId
+ * @returns returns
+ */
+export const delDictApi = (id: string | number | Array<string | number>) => {
+  return http.delete<any>(`/system/dict/type/${id}`)
+}
+
+/**
+ * @name 导出数据
+ * @returns returns
+ */
+export const exportApi = (data: any) => {
+  return http.downloadPost('/system/dict/type/export', data)
+}
+/**
+ * @name 刷新字典缓存
+ * @returns returns
+ */
+export const refreshCacheApi = () => {
+  return http.delete<any>(`system/dict/type/refreshCache`)
+}
+
+/**
+ * @name 获取字典选择框列表
+ * @returns returns
+ */
+export const optionSelectApi = () => {
+  return http.get<any>(`/system/dict/type/option/select`)
+}

+ 63 - 0
src/api/modules/system/dictData.ts

@@ -0,0 +1,63 @@
+import http from '@/api'
+import { DictDataForm, DictDataQuery, DictDataVO } from '@/api/interface/system/data'
+/**
+ * @name 查询字典数据列表
+ * @param query 参数
+ * @returns 返回列表
+ */
+export const listDataApi = (query: DictDataQuery) => {
+  return http.get<DictDataVO[]>('/system/dict/data/list', query, { loading: true })
+}
+
+/**
+ * @name 查询字典数据详细
+ * @param dictCode dictCode
+ * @returns returns
+ */
+export const getDataApi = (dictCode: string | number) => {
+  return http.get<DictDataVO>(`/system/dict/data/${dictCode}`)
+}
+
+/**
+ * @name 根据字典类型查询字典数据信息
+ * @param dictType dictType
+ * @returns returns
+ */
+export const getDictsApi = (dictType: string) => {
+  return http.get<DictDataVO[]>(`/system/dict/data/type/${dictType}`)
+}
+
+/**
+ * @name 新增字典数据
+ * @param data data
+ * @returns returns
+ */
+export const addDataApi = (data: DictDataForm) => {
+  return http.post<any>('/system/dict/data', data, { loading: false })
+}
+
+/**
+ * @name 修改字典数据
+ * @param data data
+ * @returns returns
+ */
+export const updateDataApi = (data: DictDataForm) => {
+  return http.put<any>('/system/dict/data', data, { loading: false })
+}
+
+/**
+ * @name 删除字典数据
+ * @param dictCode dictCode
+ * @returns returns
+ */
+export const delDataApi = (id: string | number | Array<string | number>) => {
+  return http.delete<any>(`/system/dict/data/${id}`)
+}
+
+/**
+ * @name 导出数据
+ * @returns returns
+ */
+export const exportApi = (data: any) => {
+  return http.downloadPost('/system/dict/data/export', data)
+}

+ 19 - 0
src/api/modules/system/importExport.ts

@@ -0,0 +1,19 @@
+import http from '@/api'
+import { ImportExportVO, ImportExportQuery } from '@/api/interface/system/importExport'
+/**
+ * @name 查询导入导出日志列表
+ * @param query 参数
+ * @returns 返回列表
+ */
+export const listImportExportApi = (query: ImportExportQuery) => {
+  return http.get<ImportExportVO[]>('/system/importExport/list', query, { loading: true })
+}
+
+/**
+ * @name 查询导入导出日志详细
+ * @param id id
+ * @returns returns
+ */
+export const getImportExportApi = (id: string | number) => {
+  return http.get<ImportExportVO>(`/system/importExport/${id}`)
+}

+ 69 - 0
src/api/modules/system/menu.ts

@@ -0,0 +1,69 @@
+import http from '@/api'
+import { MenuQuery, MenuVO, MenuForm, MenuTreeOption, RoleMenuTree } from '@/api/interface/system/menu'
+import { RouteRecordRaw } from 'vue-router'
+// 获取路由
+export const getRoutersApi = () => {
+  return http.get<RouteRecordRaw[]>('/system/menu/getRouters', {}, { loading: false })
+}
+
+/**
+ * @name 查询菜单列表
+ * @param query 参数
+ * @returns 返回列表
+ */
+export const listMenuApi = (query?: MenuQuery) => {
+  return http.get<MenuVO[]>('/system/menu/list', query, { loading: true })
+}
+
+/**
+ * @name 查询菜单详细
+ * @param menuId menuId
+ * @returns returns
+ */
+export const getMenuApi = (menuId: string | number) => {
+  return http.get<MenuVO>(`/system/menu/${menuId}`)
+}
+
+/**
+ * @name 新增菜单
+ * @param data data
+ * @returns returns
+ */
+export const addMenuApi = (data: MenuForm) => {
+  return http.post<any>('/system/menu', data, { loading: false })
+}
+
+/**
+ * @name 修改菜单
+ * @param data data
+ * @returns returns
+ */
+export const updateMenuApi = (data: MenuForm) => {
+  return http.put<any>('/system/menu', data, { loading: false })
+}
+
+/**
+ * @name 删除菜单
+ * @param menuId menuId
+ * @returns returns
+ */
+export const delMenuApi = (menuId: string | number) => {
+  return http.delete<any>(`/system/menu/${menuId}`)
+}
+
+/**
+ * @name 查询菜单下拉树结构
+ * @returns returns
+ */
+export const treeSelectApi = () => {
+  return http.get<MenuTreeOption[]>(`/system/menu/treeselect`)
+}
+
+/**
+ * @name 根据角色ID查询菜单下拉树结构
+ * @param roleId roleId
+ * @returns returns
+ */
+export const roleMenuTreeselectApi = (roleId: string | number) => {
+  return http.get<RoleMenuTree>(`/system/menu/roleMenuTreeselect/${roleId}`)
+}

+ 28 - 0
src/api/modules/system/oss.ts

@@ -0,0 +1,28 @@
+import http from '@/api'
+import { OssQuery, OssVO } from '@/api/interface/system/oss'
+/**
+ * @name 查询OSS对象存储列表
+ * @param query 参数
+ * @returns 返回列表
+ */
+export const listOssApi = (query: OssQuery) => {
+  return http.get<OssVO[]>('/resource/oss/list', query, { loading: true })
+}
+
+/**
+ * @name 查询OSS对象基于id串
+ * @param ossId ossId
+ * @returns returns
+ */
+export const getListByIdsApi = (ossIds: string | number) => {
+  return http.get<OssVO[]>(`/resource/oss/listByIds/${ossIds}`)
+}
+
+/**
+ * @name 删除OSS对象存储
+ * @param ossId ossId
+ * @returns returns
+ */
+export const delOssApi = (ossId: string | number | Array<string | number>) => {
+  return http.delete<any>(`/resource/oss/${ossId}`)
+}

+ 62 - 0
src/api/modules/system/ossConfig.ts

@@ -0,0 +1,62 @@
+import http from '@/api'
+import { OssConfigForm, OssConfigQuery, OssConfigVO } from '@/api/interface/system/ossConfig'
+/**
+ * @name 查询对象存储配置列表
+ * @param query 参数
+ * @returns 返回列表
+ */
+export const listOssConfigApi = (query: OssConfigQuery) => {
+  return http.get<OssConfigVO[]>('/resource/oss/config/list', query, { loading: true })
+}
+
+/**
+ * @name 查询对象存储配置详细
+ * @param ossConfigId ossConfigId
+ * @returns returns
+ */
+export const getOssConfigApi = (ossConfigId: string | number) => {
+  return http.get<OssConfigVO>(`/resource/oss/config/${ossConfigId}`)
+}
+
+/**
+ * @name 新增对象存储配置
+ * @param data data
+ * @returns returns
+ */
+export const addOssConfigApi = (data: OssConfigForm) => {
+  return http.post<any>('/resource/oss/config', data, { loading: false })
+}
+
+/**
+ * @name 修改对象存储配置
+ * @param data data
+ * @returns returns
+ */
+export const updateOssConfigApi = (data: OssConfigForm) => {
+  return http.put<any>('/resource/oss/config', data, { loading: false })
+}
+/**
+ * @name 对象存储状态修改
+ * @param data data
+ * @returns returns
+ */
+export const changeOssConfigStatusApi = (data: { ossConfigId: string | number; version: number; status: string; configKey: string }) => {
+  return http.put<any>('/resource/oss/config/changeStatus', data, { loading: false })
+}
+
+/**
+ * @name 删除对象存储配置
+ * @param ossConfigId ossConfigId
+ * @returns returns
+ */
+export const delOssConfigApi = (ossConfigId: string | number | Array<string | number>) => {
+  return http.delete<any>(`/resource/oss/config/${ossConfigId}`)
+}
+
+/**
+ * @name 下载模板
+ * @returns returns
+ */
+export const importTemplateApi = () => {
+  return http.downloadPost('/resource/oss/config/importTemplate', {})
+}

+ 71 - 0
src/api/modules/system/post.ts

@@ -0,0 +1,71 @@
+import http from '@/api'
+import { PostForm, PostQuery, PostVO } from '@/api/interface/system/post'
+
+/**
+ * @name 查询岗位信息列表
+ * @param query 参数
+ * @returns 返回列表
+ */
+export const listPostApi = (query: PostQuery) => {
+  return http.get<PostVO[]>('/system/post/list', query, { loading: true })
+}
+
+/**
+ * @name 查询岗位信息详细
+ * @param postId postId
+ * @returns returns
+ */
+export const getPostApi = (postId: string | number) => {
+  return http.get<any>(`/system/post/${postId}`)
+}
+
+/**
+ * @name 新增岗位信息
+ * @param data data
+ * @returns returns
+ */
+export const addPostApi = (data: PostForm) => {
+  return http.post<any>('/system/post', data, { loading: false })
+}
+
+/**
+ * @name 修改岗位信息
+ * @param data data
+ * @returns returns
+ */
+export const updatePostApi = (data: PostForm) => {
+  return http.put<any>('/system/post', data, { loading: false })
+}
+
+/**
+ * @name 删除岗位信息
+ * @param postId postId
+ * @returns returns
+ */
+export const delPostApi = (postId: string | number | (string | number)[]) => {
+  return http.delete<any>(`/system/post/${postId}`)
+}
+
+/**
+ * @name 下载模板
+ * @returns returns
+ */
+export const importTemplateApi = () => {
+  return http.downloadPost('/system/post/importTemplate', {})
+}
+
+/**
+ * @name 导入数据
+ * @returns returns
+ */
+export const importDataApi = (data: any) => {
+  return http.post('/system/post/importData', data)
+}
+
+/**
+ * @name 导出数据
+ * @returns returns
+ */
+export const exportApi = (data: any) => {
+  return http.downloadPost('/system/post/export', data)
+}

+ 153 - 0
src/api/modules/system/role.ts

@@ -0,0 +1,153 @@
+import http from '@/api'
+import { RoleQuery, RoleVO, RoleDeptTree } from '@/api/interface/system/role'
+import { UserVO, UserQuery } from '@/api/interface/system/user'
+import { RoleMenuTree } from '@/api/interface/system/menu'
+/**
+ * @name 查询角色信息列表
+ * @param query 参数
+ * @returns 返回列表
+ */
+export const listRoleApi = (query: RoleQuery) => {
+  return http.get<RoleVO[]>('/system/role/list', query, { loading: true })
+}
+
+/**
+ * @name 根据角色ID查询部门树结构
+ * @param roleId 角色Id
+ * @returns 返回列表
+ */
+export const deptTreeSelectApi = (roleId: string | number) => {
+  return http.get<RoleDeptTree>(`/system/role/deptTree/${roleId}`)
+}
+
+/**
+ * @name 根据角色ID查询菜单下拉树结构
+ * @param roleId 角色Id
+ * @returns 返回列表
+ */
+export const roleMenuTreeSelectApi = (roleId: any) => {
+  return http.get<RoleMenuTree>(`/system/menu/roleMenuTreeselect/${roleId}`)
+}
+
+/**
+ * @name 查询角色信息详细
+ * @param roleId roleId
+ * @returns returns
+ */
+export const getRoleApi = (roleId: string | number) => {
+  return http.get<RoleVO>(`/system/role/${roleId}`)
+}
+
+/**
+ * @name 新增角色信息
+ * @param data data
+ * @returns returns
+ */
+export const addRoleApi = (data: any) => {
+  return http.post<any>('/system/role', data, { loading: false })
+}
+
+/**
+ * @name 修改角色信息
+ * @param data data
+ * @returns returns
+ */
+export const updateRoleApi = (data: any) => {
+  return http.put<any>('/system/role', data, { loading: false })
+}
+
+/**
+ * @name 角色数据权限
+ * @param data data
+ * @returns returns
+ */
+export const dataScopeApi = (data: any) => {
+  return http.put<any>('/system/role/dataScope', data, { loading: false })
+}
+
+/**
+ * @name 修改角色状态
+ * @param data data
+ * @returns returns
+ */
+export const changeStatusApi = (data: { roleId: string | number; version: number; status: string }) => {
+  return http.put<any>('/system/role/changeStatus', data, { loading: false })
+}
+
+/**
+ * @name 删除角色信息
+ * @param roleId roleId
+ * @returns returns
+ */
+export const delRoleApi = (roleId: Array<string | number> | string | number) => {
+  return http.delete<any>(`/system/role/${roleId}`)
+}
+
+/**
+ * @name 下载模板
+ * @returns returns
+ */
+export const importTemplateApi = () => {
+  return http.downloadPost('/system/role/importTemplate', {})
+}
+
+/**
+ * @name 导入数据
+ * @returns returns
+ */
+export const importDataApi = (data: any) => {
+  return http.post('/system/role/importData', data)
+}
+
+/**
+ * @name 导出数据
+ * @returns returns
+ */
+export const exportApi = (data: any) => {
+  return http.downloadPost('/system/role/export', data)
+}
+
+/**
+ * @name 查询角色已授权用户列表
+ * @param query 参数
+ * @returns 返回列表
+ */
+export const allocatedUserListApi = (query: UserQuery) => {
+  return http.get<UserVO[]>(`/system/role/authUser/allocatedList`, query, { loading: true })
+}
+
+/**
+ * @name 查询角色未授权用户列表
+ * @param query 参数
+ * @returns 返回列表
+ */
+export const unallocatedUserListApi = (query: UserQuery) => {
+  return http.get<UserVO[]>(`/system/role/authUser/unallocatedList`, query, { loading: true })
+}
+
+/**
+ * @name 取消用户授权角色
+ * @param data data
+ * @returns returns
+ */
+export const authUserCancelApi = (data: any) => {
+  return http.put<any>('/system/role/authUser/cancel', data, { loading: false })
+}
+
+/**
+ * @name 批量取消用户授权角色
+ * @param data data
+ * @returns returns
+ */
+export const authUserCancelAllApi = (data: any) => {
+  return http.put<any>('/system/role/authUser/cancelAll', data, { loading: false })
+}
+
+/**
+ * @name 授权用户选择
+ * @param data data
+ * @returns returns
+ */
+export const authUserSelectAllApi = (data: any) => {
+  return http.put<any>('/system/role/authUser/selectAll', data, { loading: false })
+}

+ 138 - 0
src/api/modules/system/user.ts

@@ -0,0 +1,138 @@
+import http from '@/api'
+import { parseStrEmpty } from '@/utils/common'
+import { UserForm, UserQuery, UserVO, UserInfoVO } from '@/api/interface/system/user'
+import { DeptVO } from '@/api/interface/system/dept'
+/**
+ * @name 查询用户列表
+ * @param query 参数
+ * @returns 返回列表
+ */
+export const listUserApi = (query: UserQuery) => {
+  return http.get<UserVO[]>('/system/user/list', query, { loading: true })
+}
+
+/**
+ * @name 查询用户详细
+ * @param userId userId
+ * @returns returns
+ */
+export const getUserApi = (userId?: string | number) => {
+  return http.get<UserInfoVO>(`/system/user/` + parseStrEmpty(userId))
+}
+
+/**
+ * @name 查询部门下拉树结构
+ * @returns returns
+ */
+export const deptTreeSelectApi = () => {
+  return http.get<DeptVO[]>(`/system/user/deptTree`)
+}
+
+/**
+ * @name 新增用户
+ * @returns returns
+ */
+export const addUserApi = (data: UserForm) => {
+  return http.post<any>('/system/user', data, { loading: false })
+}
+
+/**
+ * @name 修改用户
+ * @returns returns
+ */
+export const updateUserApi = (data: UserForm) => {
+  return http.put<any>('/system/user', data, { loading: false })
+}
+
+/**
+ * @name 删除用户
+ * @returns returns
+ */
+export const delUserApi = (userId: Array<string | number> | string | number) => {
+  return http.delete<any>(`/system/user/${userId}`)
+}
+
+/**
+ * @name 用户状态修改
+ * @param userId userId
+ * @param status status
+ * @returns returns
+ */
+export const changeUserStatus = (data: { userId: number | string; version: number; status: string }) => {
+  return http.put<any>('/system/user/changeStatus', data, { loading: false })
+}
+
+/**
+ * @name 用户密码重置
+ * @param data data
+ * @returns returns
+ */
+export const resetUserPwdApi = (data: any) => {
+  return http.put<any>('/system/user/resetPwd', data, { loading: false })
+}
+
+/**
+ * @name 下载模板
+ * @returns returns
+ */
+export const importTemplateApi = () => {
+  return http.downloadPost('/system/user/importTemplate', {})
+}
+
+/**
+ * @name 导入数据
+ * @returns returns
+ */
+export const importDataApi = (params: FormData) => {
+  return http.post('/system/user/importData', params)
+}
+
+/**
+ * @name 导出下载数据
+ * @returns returns
+ */
+export const exportDownApi = (data: any) => {
+  return http.downloadPost('/system/user/export', data, { loading: false })
+}
+
+/**
+ * @name 导出数据
+ * @returns returns
+ */
+export const exportApi = (data: any) => {
+  return http.post('/system/user/export', data)
+}
+
+/**
+ * @name 用户头像上传
+ * @param params params
+ * @returns returns
+ */
+export const uploadAvatarApi = (params: FormData) => {
+  return http.post<any>('/system/user/profile/avatar', params)
+}
+
+/**
+ * @name 查询用户个人信息
+ * @returns returns
+ */
+export const getUserProfileApi = () => {
+  return http.get<UserInfoVO>(`/system/user/profile`)
+}
+
+/**
+ * @name 修改用户个人信息
+ * @param data data
+ * @returns returns
+ */
+export const updateUserProfileApi = (data: UserForm) => {
+  return http.put<any>('/system/user/profile', data, { loading: false })
+}
+/**
+ * @name 修改用户密码
+ * @param data data
+ * @returns returns
+ */
+export const updateUserPwdApi = (data: { oldPassword: string; newPassword: string }) => {
+  return http.put<any>('system/user/profile/updatePwd', data, { loading: false })
+}

+ 91 - 0
src/api/modules/tool/gen.ts

@@ -0,0 +1,91 @@
+import http from '@/api'
+import { DbTableQuery, DbTableVO, TableQuery, TableVO, GenTableVO, DbTableForm } from '@/api/interface/tool/gen'
+/**
+ * @name 查询生成表数据
+ * @param query {TableQuery} 参数
+ * @returns 返回列表
+ */
+export const listTableApi = (query: TableQuery) => {
+  return http.get<TableVO[]>('/tool/gen/list', query, { loading: true })
+}
+
+/**
+ * @name 查询db数据库列表
+ * @param query 参数
+ * @returns 返回列表
+ */
+export const listDbTableApi = (query: DbTableQuery) => {
+  return http.get<DbTableVO[]>('/tool/gen/db/list', query, { loading: true })
+}
+
+/**
+ * @name 查询表详细信息
+ * @param tableId tableId
+ * @returns returns
+ */
+export const getTableApi = (tableId: string | number) => {
+  return http.get<GenTableVO>(`/tool/gen/${tableId}`)
+}
+
+/**
+ * @name 修改代码生成信息
+ * @param data data
+ * @returns returns
+ */
+export const updateGenTableApi = (data: DbTableForm) => {
+  return http.put<GenTableVO>('/tool/gen', data, { loading: false })
+}
+
+/**
+ * @name 导入表
+ * @param data data
+ * @returns returns
+ */
+export const importTableApi = (data: { tables: string }) => {
+  return http.post<GenTableVO>('/tool/gen/importTable', data, { loading: false })
+}
+
+/**
+ * @name 预览生成代码
+ * @param tableId tableId
+ * @returns returns
+ */
+export const previewTableApi = (tableId: string | number) => {
+  return http.get<any>(`/tool/gen/preview/${tableId}`)
+}
+
+/**
+ * @name 删除表数据
+ * @param tableId tableId
+ * @returns returns
+ */
+export const delTableApi = (tableId: string | number | Array<string | number>) => {
+  return http.delete<any>(`/tool/gen/${tableId}`)
+}
+
+/**
+ * @name 生成代码(自定义路径)
+ * @param tableId tableId
+ * @returns returns
+ */
+export const genCodeApi = (tableId: string | number) => {
+  return http.get<any>(`/tool/gen/genCode/${tableId}`)
+}
+
+/**
+ * @name 同步数据库
+ * @param tableId tableName
+ * @returns returns
+ */
+export const synchDbApi = (tableId: string | number) => {
+  return http.get<any>(`/tool/gen/syncDb/${tableId}`)
+}
+
+/**
+ * @name 生成代码操作
+ * @param tableId tableId
+ * @returns returns
+ */
+export const batchGenCodeApi = (tableId: string | number) => {
+  return http.downloadGet(`/tool/gen/batchGenCode?tables=${tableId}`)
+}

+ 16 - 0
src/api/modules/upload.ts

@@ -0,0 +1,16 @@
+import { Upload } from '@/api/interface/index'
+import { PORT1 } from '@/api/config/servicePort'
+import http from '@/api'
+
+/**
+ * @name 文件上传模块
+ */
+// 图片上传
+export const uploadImg = (params: FormData) => {
+  return http.post<Upload.ResFileUrl>(PORT1 + `/file/upload/img`, params, { cancel: false })
+}
+
+// 视频上传
+export const uploadVideo = (params: FormData) => {
+  return http.post<Upload.ResFileUrl>(PORT1 + `/file/upload/video`, params, { cancel: false })
+}

BIN
src/assets/fonts/DIN.otf


BIN
src/assets/fonts/MetroDF.ttf


BIN
src/assets/fonts/YouSheBiaoTiHei.ttf


+ 14 - 0
src/assets/fonts/font.scss

@@ -0,0 +1,14 @@
+@font-face {
+  font-family: YouSheBiaoTiHei;
+  src: url('./YouSheBiaoTiHei.ttf');
+}
+
+@font-face {
+  font-family: MetroDF;
+  src: url('./MetroDF.ttf');
+}
+
+@font-face {
+  font-family: DIN;
+  src: url('./DIN.otf');
+}

+ 48 - 0
src/assets/iconfont/iconfont.scss

@@ -0,0 +1,48 @@
+@font-face {
+  font-family: iconfont; /* Project id 2667653 */
+  src: url('iconfont.ttf?t=1694681005434') format('truetype');
+}
+.iconfont {
+  font-family: iconfont !important;
+  font-size: 20px;
+  font-style: normal;
+  -webkit-font-smoothing: antialiased;
+  -moz-osx-font-smoothing: grayscale;
+  cursor: pointer;
+}
+.icon-yiwen::before {
+  font-size: 15px;
+  content: '\e693';
+}
+.icon-xiala::before {
+  content: '\e62b';
+}
+.icon-tuichu::before {
+  content: '\e645';
+}
+.icon-xiaoxi::before {
+  font-size: 21.2px;
+  content: '\e61f';
+}
+.icon-zhuti::before {
+  font-size: 22.4px;
+  content: '\e638';
+}
+.icon-sousuo::before {
+  content: '\e611';
+}
+.icon-contentright::before {
+  content: '\e8c9';
+}
+.icon-contentleft::before {
+  content: '\e8ca';
+}
+.icon-fangda::before {
+  content: '\e826';
+}
+.icon-suoxiao::before {
+  content: '\e641';
+}
+.icon-zhongyingwen::before {
+  content: '\e8cb';
+}

BIN
src/assets/iconfont/iconfont.ttf


+ 1 - 0
src/assets/icons/svg/404.svg

@@ -0,0 +1 @@
+<svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M121.718 73.272v9.953c3.957-7.584 6.199-16.05 6.199-24.995C127.917 26.079 99.273 0 63.958 0 28.644 0 0 26.079 0 58.23c0 .403.028.806.028 1.21l22.97-25.953h13.34l-19.76 27.187h6.42V53.77l13.728-19.477v49.361H22.998V73.272H2.158c5.951 20.284 23.608 36.208 45.998 41.399-1.44 3.3-5.618 11.263-12.565 12.674-8.607 1.764 23.358.428 46.163-13.178 17.519-4.611 31.938-15.849 39.77-30.513h-13.506V73.272H85.02V59.464l22.998-25.977h13.008l-19.429 27.187h6.421v-7.433l13.727-19.402v39.433h-.027zm-78.24 2.822a10.516 10.516 0 0 1-.996-4.535V44.548c0-1.613.332-3.124.996-4.535a11.66 11.66 0 0 1 2.713-3.68c1.134-1.032 2.49-1.864 4.04-2.468 1.55-.605 3.21-.908 4.982-.908h11.292c1.77 0 3.431.303 4.981.908 1.522.604 2.85 1.41 3.986 2.418l-12.26 16.303v-2.898a1.96 1.96 0 0 0-.665-1.512c-.443-.403-.996-.604-1.66-.604-.665 0-1.218.201-1.661.604a1.96 1.96 0 0 0-.664 1.512v9.071L44.364 77.606a10.556 10.556 0 0 1-.886-1.512zm35.73-4.535c0 1.613-.332 3.124-.997 4.535a11.66 11.66 0 0 1-2.712 3.68c-1.134 1.032-2.49 1.864-4.04 2.469-1.55.604-3.21.907-4.982.907H55.185c-1.77 0-3.431-.303-4.981-.907-1.55-.605-2.906-1.437-4.041-2.47a12.49 12.49 0 0 1-1.384-1.512l13.727-18.217v6.375c0 .605.222 1.109.665 1.512.442.403.996.604 1.66.604.664 0 1.218-.201 1.66-.604a1.96 1.96 0 0 0 .665-1.512V53.87L75.97 36.838c.913.932 1.66 1.99 2.214 3.175.664 1.41.996 2.922.996 4.535v27.011h.028z"/></svg>

+ 1 - 0
src/assets/icons/svg/avatar-user.svg

@@ -0,0 +1 @@
+<?xml version="1.0" ?><svg height="512" viewBox="0 0 512 512" width="512" xmlns="http://www.w3.org/2000/svg"><title/><path d="M256,48C141.31,48,48,141.31,48,256s93.31,208,208,208,208-93.31,208-208S370.69,48,256,48Zm2,96a72,72,0,1,1-72,72A72,72,0,0,1,258,144Zm-2,288a175.55,175.55,0,0,1-129.18-56.6C135.66,329.62,215.06,320,256,320s120.34,9.62,129.18,55.39A175.52,175.52,0,0,1,256,432Z"/></svg>

+ 1 - 0
src/assets/icons/svg/bug.svg

@@ -0,0 +1 @@
+<svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M127.88 73.143c0 1.412-.506 2.635-1.518 3.669-1.011 1.033-2.209 1.55-3.592 1.55h-17.887c0 9.296-1.783 17.178-5.35 23.645l16.609 17.044c1.011 1.034 1.517 2.257 1.517 3.67 0 1.412-.506 2.635-1.517 3.668-.958 1.033-2.155 1.55-3.593 1.55-1.438 0-2.635-.517-3.593-1.55l-15.811-16.063a15.49 15.49 0 0 1-1.196 1.06c-.532.434-1.65 1.208-3.353 2.322a50.104 50.104 0 0 1-5.192 2.974c-1.758.87-3.94 1.658-6.546 2.364-2.607.706-5.189 1.06-7.748 1.06V47.044H58.89v73.062c-2.716 0-5.417-.367-8.106-1.102-2.688-.734-5.003-1.631-6.945-2.692a66.769 66.769 0 0 1-5.268-3.179c-1.571-1.057-2.73-1.94-3.476-2.65L33.9 109.34l-14.611 16.877c-1.066 1.14-2.344 1.711-3.833 1.711-1.277 0-2.422-.434-3.434-1.304-1.012-.978-1.557-2.187-1.635-3.627-.079-1.44.333-2.705 1.236-3.794l16.129-18.51c-3.087-6.197-4.63-13.644-4.63-22.342H5.235c-1.383 0-2.58-.517-3.592-1.55S.125 74.545.125 73.132c0-1.412.506-2.635 1.518-3.668 1.012-1.034 2.21-1.55 3.592-1.55h17.887V43.939L9.308 29.833c-1.012-1.033-1.517-2.256-1.517-3.669 0-1.412.505-2.635 1.517-3.668 1.012-1.034 2.21-1.55 3.593-1.55s2.58.516 3.593 1.55l13.813 14.106h67.396l13.814-14.106c1.012-1.034 2.21-1.55 3.592-1.55 1.384 0 2.581.516 3.593 1.55 1.012 1.033 1.518 2.256 1.518 3.668 0 1.413-.506 2.636-1.518 3.67l-13.814 14.105v23.975h17.887c1.383 0 2.58.516 3.593 1.55 1.011 1.033 1.517 2.256 1.517 3.668l-.005.01zM89.552 26.175H38.448c0-7.23 2.489-13.386 7.466-18.469C50.892 2.623 56.92.082 64 .082c7.08 0 13.108 2.541 18.086 7.624 4.977 5.083 7.466 11.24 7.466 18.469z"/></svg>

+ 1 - 0
src/assets/icons/svg/build.svg

@@ -0,0 +1 @@
+<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1568899741379" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2054" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css"></style></defs><path d="M960 591.424V368.96c0-0.288 0.16-0.512 0.16-0.768S960 367.68 960 367.424V192a32 32 0 0 0-32-32H96a32 32 0 0 0-32 32v175.424c0 0.288-0.16 0.512-0.16 0.768s0.16 0.48 0.16 0.768v222.464c0 0.288-0.16 0.512-0.16 0.768s0.16 0.48 0.16 0.768V864a32 32 0 0 0 32 32h832a32 32 0 0 0 32-32v-271.04c0-0.288 0.16-0.512 0.16-0.768S960 591.68 960 591.424z m-560-31.232v-160H608v160h-208z m208 64V832h-208v-207.808H608z m-480-224h208v160H128v-160z m544 0h224v160h-224v-160zM896 224v112.192H128V224h768zM128 624.192h208V832H128v-207.808zM672 832v-207.808h224V832h-224z" p-id="2055"></path></svg>

Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 0 - 0
src/assets/icons/svg/button.svg


Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 0 - 0
src/assets/icons/svg/cascader.svg


+ 1 - 0
src/assets/icons/svg/chart.svg

@@ -0,0 +1 @@
+<svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M0 54.857h36.571V128H0V54.857zM91.429 27.43H128V128H91.429V27.429zM45.714 0h36.572v128H45.714V0z"/></svg>

+ 1 - 0
src/assets/icons/svg/checkbox.svg

@@ -0,0 +1 @@
+<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1575982282951" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="902" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css"></style></defs><path d="M828.40625 90.125H195.59375C137.375 90.125 90.125 137.375 90.125 195.59375v632.8125c0 58.21875 47.25 105.46875 105.46875 105.46875h632.8125c58.21875 0 105.46875-47.25 105.46875-105.46875V195.59375c0-58.21875-47.25-105.46875-105.46875-105.46875z m52.734375 738.28125c0 29.16-23.57015625 52.734375-52.734375 52.734375H195.59375c-29.109375 0-52.734375-23.574375-52.734375-52.734375V195.59375c0-29.109375 23.625-52.734375 52.734375-52.734375h632.8125c29.16 0 52.734375 23.625 52.734375 52.734375v632.8125z" p-id="903"></path><path d="M421.52890625 709.55984375a36.28125 36.28125 0 0 1-27.55265625-12.66890625L205.17453125 476.613125a36.28546875 36.28546875 0 0 1 55.10109375-47.22890625l164.986875 192.4846875 342.16171875-298.48078125a36.2896875 36.2896875 0 0 1 47.70984375 54.68765625L445.3859375 700.6203125a36.3234375 36.3234375 0 0 1-23.85703125 8.93953125z" p-id="904"></path></svg>

+ 1 - 0
src/assets/icons/svg/clipboard.svg

@@ -0,0 +1 @@
+<svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M54.857 118.857h64V73.143H89.143c-1.902 0-3.52-.668-4.855-2.002-1.335-1.335-2.002-2.954-2.002-4.855V36.57H54.857v82.286zM73.143 16v-4.571a2.2 2.2 0 0 0-.677-1.61 2.198 2.198 0 0 0-1.609-.676H20.571c-.621 0-1.158.225-1.609.676a2.198 2.198 0 0 0-.676 1.61V16a2.2 2.2 0 0 0 .676 1.61c.451.45.988.676 1.61.676h50.285c.622 0 1.158-.226 1.61-.677.45-.45.676-.987.676-1.609zm18.286 48h21.357L91.43 42.642V64zM128 73.143v48c0 1.902-.667 3.52-2.002 4.855-1.335 1.335-2.953 2.002-4.855 2.002H52.57c-1.901 0-3.52-.667-4.854-2.002-1.335-1.335-2.003-2.953-2.003-4.855v-11.429H6.857c-1.902 0-3.52-.667-4.855-2.002C.667 106.377 0 104.759 0 102.857v-96c0-1.902.667-3.52 2.002-4.855C3.337.667 4.955 0 6.857 0h77.714c1.902 0 3.52.667 4.855 2.002 1.335 1.335 2.003 2.953 2.003 4.855V30.29c1 .622 1.856 1.29 2.569 2.003l29.147 29.147c1.335 1.335 2.478 3.145 3.429 5.43.95 2.287 1.426 4.383 1.426 6.291v-.018z"/></svg>

+ 1 - 0
src/assets/icons/svg/code.svg

@@ -0,0 +1 @@
+<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1546567861908" class="icon" style="" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2422" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css"></style></defs><path d="M318.577778 819.2L17.066667 512l301.511111-307.2 45.511111 45.511111L96.711111 512l267.377778 261.688889zM705.422222 819.2l-45.511111-45.511111L927.288889 512l-267.377778-261.688889 45.511111-45.511111L1006.933333 512zM540.785778 221.866667l55.751111 11.150222L483.157333 802.133333l-55.751111-11.093333z" fill="#bfbfbf" p-id="2423"></path></svg>

Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 0 - 0
src/assets/icons/svg/color.svg


Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 0 - 0
src/assets/icons/svg/component.svg


Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 0 - 0
src/assets/icons/svg/dashboard.svg


Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 0 - 0
src/assets/icons/svg/date-range.svg


Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 0 - 0
src/assets/icons/svg/date.svg


Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 0 - 0
src/assets/icons/svg/dict.svg


+ 1 - 0
src/assets/icons/svg/documentation.svg

@@ -0,0 +1 @@
+<svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M71.984 44.815H115.9L71.984 9.642v35.173zM16.094.05h63.875l47.906 38.37v76.74c0 3.392-1.682 6.645-4.677 9.044-2.995 2.399-7.056 3.746-11.292 3.746H16.094c-4.236 0-8.297-1.347-11.292-3.746-2.995-2.399-4.677-5.652-4.677-9.044V12.84C.125 5.742 7.23.05 16.094.05zm71.86 102.32V89.58h-71.86v12.79h71.86zm23.952-25.58V64H16.094v12.79h95.812z"/></svg>

+ 1 - 0
src/assets/icons/svg/download.svg

@@ -0,0 +1 @@
+<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1569915748289" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="3062" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css"></style></defs><path d="M768.35456 416a256 256 0 1 0-512 0 192 192 0 1 0 0 384v64a256 256 0 0 1-58.88-505.216 320.128 320.128 0 0 1 629.76 0A256.128 256.128 0 0 1 768.35456 864v-64a192 192 0 0 0 0-384z m-512 384h64v64H256.35456v-64z m448 0h64v64h-64v-64z" fill="#333333" p-id="3063"></path><path d="M539.04256 845.248V512.192a32.448 32.448 0 0 0-32-32.192c-17.664 0-32 14.912-32 32.192v333.056l-36.096-36.096a32.192 32.192 0 0 0-45.056 0.192 31.616 31.616 0 0 0-0.192 45.056l90.88 90.944a31.36 31.36 0 0 0 22.528 9.088 30.08 30.08 0 0 0 22.4-9.088l90.88-90.88a32.192 32.192 0 0 0-0.192-45.12 31.616 31.616 0 0 0-45.056-0.192l-36.096 36.096z" fill="#333333" p-id="3064"></path></svg>

+ 1 - 0
src/assets/icons/svg/drag.svg

@@ -0,0 +1 @@
+<svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M73.137 29.08h-9.209 29.7L63.886.093 34.373 29.08h20.49v27.035H27.238v17.948h27.625v27.133h18.274V74.063h27.41V56.115h-27.41V29.08zm-9.245 98.827l27.518-26.711H36.59l27.302 26.71zM.042 64.982l27.196 27.029V38.167L.042 64.982zm100.505-26.815V92.01l27.41-27.029-27.41-26.815z"/></svg>

+ 1 - 0
src/assets/icons/svg/druid.svg

@@ -0,0 +1 @@
+<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1566036347051" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="5853" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css"></style></defs><path d="M832 128H192a64.19 64.19 0 0 0-64 64v640a64.19 64.19 0 0 0 64 64h640a64.19 64.19 0 0 0 64-64V192a64.19 64.19 0 0 0-64-64z m0 703.89l-0.11 0.11H192.11l-0.11-0.11V768h640zM832 544H720L605.6 696.54 442.18 435.07 333.25 544H192v-64h114.75l147.07-147.07L610.4 583.46 688 480h144z m0-288H192v-63.89l0.11-0.11h639.78l0.11 0.11z" p-id="5854"></path></svg>

+ 1 - 0
src/assets/icons/svg/edit.svg

@@ -0,0 +1 @@
+<svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M106.133 67.2a4.797 4.797 0 0 0-4.8 4.8c0 .187.014.36.027.533h-.027V118.4H9.6V26.667h50.133c2.654 0 4.8-2.147 4.8-4.8 0-2.654-2.146-4.8-4.8-4.8H9.6a9.594 9.594 0 0 0-9.6 9.6V118.4c0 5.307 4.293 9.6 9.6 9.6h91.733c5.307 0 9.6-4.293 9.6-9.6V72.533h-.026c.013-.173.026-.346.026-.533 0-2.653-2.146-4.8-4.8-4.8z"/><path d="M125.16 13.373L114.587 2.8c-3.747-3.747-9.854-3.72-13.6.027l-52.96 52.96a4.264 4.264 0 0 0-.907 1.36L33.813 88.533c-.746 1.76-.226 3.534.907 4.68 1.133 1.147 2.92 1.667 4.693.92l31.4-13.293c.507-.213.96-.52 1.36-.907l52.96-52.96c3.747-3.746 3.774-9.853.027-13.6zM66.107 72.4l-18.32 7.76 7.76-18.32L92.72 24.667l10.56 10.56L66.107 72.4zm52.226-52.227l-8.266 8.267-10.56-10.56 8.266-8.267.027-.026 10.56 10.56-.027.026z"/></svg>

+ 1 - 0
src/assets/icons/svg/education.svg

@@ -0,0 +1 @@
+<svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M88.883 119.565c-7.284 0-19.434 2.495-21.333 8.25v.127c-4.232.13-5.222 0-7.108 0-1.895-5.76-14.045-8.256-21.333-8.256H0V0h42.523c9.179 0 17.109 5.47 21.47 13.551C68.352 5.475 76.295 0 85.478 0H128v119.57l-39.113-.005h-.004zM60.442 24.763c0-9.651-8.978-16.507-17.777-16.507H7.108V111.43H39.11c7.054-.14 18.177.082 21.333 6.12v-4.628c-.134-5.722-.004-13.522 0-13.832V27.413l.004-2.655-.004.005zm60.442-16.517h-35.55c-8.802 0-17.78 6.856-17.78 16.493v74.259c.004.32.138 8.115 0 13.813v4.627c3.155-6.022 14.279-6.26 21.333-6.114h32V8.25l-.003-.005z"/></svg>

+ 1 - 0
src/assets/icons/svg/email.svg

@@ -0,0 +1 @@
+<svg width="128" height="96" xmlns="http://www.w3.org/2000/svg"><path d="M64.125 56.975L120.188.912A12.476 12.476 0 0 0 115.5 0h-103c-1.588 0-3.113.3-4.513.838l56.138 56.137z"/><path d="M64.125 68.287l-62.3-62.3A12.42 12.42 0 0 0 0 12.5v71C0 90.4 5.6 96 12.5 96h103c6.9 0 12.5-5.6 12.5-12.5v-71a12.47 12.47 0 0 0-1.737-6.35L64.125 68.287z"/></svg>

+ 1 - 0
src/assets/icons/svg/example.svg

@@ -0,0 +1 @@
+<svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M96.258 57.462h31.421C124.794 27.323 100.426 2.956 70.287.07v31.422a32.856 32.856 0 0 1 25.971 25.97zm-38.796-25.97V.07C27.323 2.956 2.956 27.323.07 57.462h31.422a32.856 32.856 0 0 1 25.97-25.97zm12.825 64.766v31.421c30.46-2.885 54.507-27.253 57.713-57.712H96.579c-2.886 13.466-13.146 23.726-26.292 26.291zM31.492 70.287H.07c2.886 30.46 27.253 54.507 57.713 57.713V96.579c-13.466-2.886-23.726-13.146-26.291-26.292z"/></svg>

+ 1 - 0
src/assets/icons/svg/excel.svg

@@ -0,0 +1 @@
+<svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M78.208 16.576v8.384h38.72v5.376h-38.72v8.704h38.72v5.376h-38.72v8.576h38.72v5.376h-38.72v8.576h38.72v5.376h-38.72v8.576h38.72v5.376h-38.72v8.512h38.72v5.376h-38.72v11.136H128v-94.72H78.208zM0 114.368L72.128 128V0L0 13.632v100.736z"/><path d="M28.672 82.56h-11.2l14.784-23.488-14.08-22.592h11.52l8.192 14.976 8.448-14.976h11.136l-14.08 22.208L58.368 82.56H46.656l-8.768-15.68z"/></svg>

+ 1 - 0
src/assets/icons/svg/exit-fullscreen.svg

@@ -0,0 +1 @@
+<svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M49.217 41.329l-.136-35.24c-.06-2.715-2.302-4.345-5.022-4.405h-3.65c-2.712-.06-4.866 2.303-4.806 5.016l.152 19.164-24.151-23.79a6.698 6.698 0 0 0-9.499 0 6.76 6.76 0 0 0 0 9.526l23.93 23.713-18.345.074c-2.712-.069-5.228 1.813-5.64 5.02v3.462c.069 2.721 2.31 4.97 5.022 5.03l35.028-.207c.052.005.087.025.133.025l2.457.054a4.626 4.626 0 0 0 3.436-1.38c.88-.874 1.205-2.096 1.169-3.462l-.262-2.465c0-.048.182-.081.182-.136h.002zm52.523 51.212l18.32-.073c2.713.06 5.224-1.609 5.64-4.815v-3.462c-.068-2.722-2.317-4.97-5.021-5.04l-34.58.21c-.053 0-.086-.021-.138-.021l-2.451-.06a4.64 4.64 0 0 0-3.445 1.381c-.885.868-1.201 2.094-1.174 3.46l.27 2.46c.005.06-.177.095-.177.141l.141 34.697c.069 2.713 2.31 4.338 5.022 4.397l3.45.006c2.705.062 4.867-2.31 4.8-5.026l-.153-18.752 24.151 23.946a6.69 6.69 0 0 0 9.494 0 6.747 6.747 0 0 0 0-9.523L101.74 92.54v.001zM48.125 80.662a4.636 4.636 0 0 0-3.437-1.382l-2.457.06c-.05 0-.082.022-.137.022l-35.025-.21c-2.712.07-4.957 2.318-5.022 5.04v3.462c.409 3.206 2.925 4.874 5.633 4.814l18.554.06-24.132 23.928c-2.62 2.626-2.62 6.89 0 9.524a6.694 6.694 0 0 0 9.496 0l24.155-23.79-.155 18.866c-.06 2.722 2.094 5.093 4.801 5.025h3.65c2.72-.069 4.962-1.685 5.022-4.406l.141-34.956c0-.05-.182-.082-.182-.136l.262-2.46c.03-1.366-.286-2.592-1.166-3.46h-.001zM80.08 47.397a4.62 4.62 0 0 0 3.443 1.374l2.45-.054c.055 0 .088-.02.143-.028l35.08.21c2.712-.062 4.953-2.312 5.021-5.033l.009-3.463c-.417-3.211-2.937-5.084-5.64-5.025l-18.615-.073 23.917-23.715c2.63-2.623 2.63-6.879.008-9.513a6.691 6.691 0 0 0-9.494 0L92.251 26.016l.155-19.312c.065-2.713-2.097-5.085-4.802-5.025h-3.45c-2.713.069-4.954 1.693-5.022 4.406l-.139 35.247c0 .054.18.088.18.136l-.267 2.465c-.028 1.366.288 2.588 1.174 3.463v.001z"/></svg>

+ 1 - 0
src/assets/icons/svg/eye-open.svg

@@ -0,0 +1 @@
+<svg class="icon" viewBox="0 0 1024 1024" xmlns="http://www.w3.org/2000/svg" width="128" height="128"><defs><style/></defs><path d="M512 128q69.675 0 135.51 21.163t115.498 54.997 93.483 74.837 73.685 82.006 51.67 74.837 32.17 54.827L1024 512q-2.347 4.992-6.315 13.483T998.87 560.17t-31.658 51.669-44.331 59.99-56.832 64.34-69.504 60.16-82.347 51.5-94.848 34.687T512 896q-69.675 0-135.51-21.163t-115.498-54.826-93.483-74.326-73.685-81.493-51.67-74.496-32.17-54.997L0 513.707q2.347-4.992 6.315-13.483t18.816-34.816 31.658-51.84 44.331-60.33 56.832-64.683 69.504-60.331 82.347-51.84 94.848-34.816T512 128.085zm0 85.333q-46.677 0-91.648 12.331t-81.152 31.83-70.656 47.146-59.648 54.485-48.853 57.686-37.675 52.821-26.325 43.99q12.33 21.674 26.325 43.52t37.675 52.351 48.853 57.003 59.648 53.845T339.2 767.02t81.152 31.488T512 810.667t91.648-12.331 81.152-31.659 70.656-46.848 59.648-54.186 48.853-57.344 37.675-52.651T927.957 512q-12.33-21.675-26.325-43.648t-37.675-52.65-48.853-57.345-59.648-54.186-70.656-46.848-81.152-31.659T512 213.334zm0 128q70.656 0 120.661 50.006T682.667 512 632.66 632.661 512 682.667 391.339 632.66 341.333 512t50.006-120.661T512 341.333zm0 85.334q-35.328 0-60.33 25.002T426.666 512t25.002 60.33T512 597.334t60.33-25.002T597.334 512t-25.002-60.33T512 426.666z"/></svg>

Daži faili netika attēloti, jo izmaiņu fails ir pārāk liels