wanggaokun 1 年之前
父節點
當前提交
e18490ce84
共有 100 個文件被更改,包括 2420 次插入2 次删除
  1. 15 0
      .editorconfig
  2. 11 0
      .env
  3. 31 0
      .env.development
  4. 33 0
      .env.production
  5. 25 0
      .env.test
  6. 15 0
      .eslintignore
  7. 67 0
      .eslintrc.cjs
  8. 24 2
      .gitignore
  9. 4 0
      .husky/commit-msg
  10. 4 0
      .husky/pre-commit
  11. 9 0
      .prettierignore
  12. 41 0
      .prettierrc.cjs
  13. 4 0
      .stylelintignore
  14. 40 0
      .stylelintrc.cjs
  15. 14 0
      .vscode/extensions.json
  16. 96 0
      .vscode/settings.json
  17. 0 0
      CHANGELOG.md
  18. 46 0
      build/getEnv.ts
  19. 117 0
      build/plugins.ts
  20. 31 0
      build/proxy.ts
  21. 162 0
      commitlint.config.cjs
  22. 105 0
      index.html
  23. 8 0
      lint-staged.config.cjs
  24. 133 0
      package.json
  25. 5 0
      postcss.config.cjs
  26. 二進制
      public/logo.png
  27. 1 0
      public/vue.svg
  28. 44 0
      src/App.vue
  29. 3 0
      src/api/config/servicePort.ts
  30. 46 0
      src/api/helper/axiosCancel.ts
  31. 43 0
      src/api/helper/checkStatus.ts
  32. 217 0
      src/api/index.ts
  33. 97 0
      src/api/interface/index.ts
  34. 29 0
      src/api/interface/menu.ts
  35. 24 0
      src/api/modules/login.ts
  36. 70 0
      src/api/modules/monitor/logininfor.ts
  37. 70 0
      src/api/modules/monitor/operlog.ts
  38. 70 0
      src/api/modules/system/dept.ts
  39. 78 0
      src/api/modules/system/dict.ts
  40. 63 0
      src/api/modules/system/dictData.ts
  41. 92 0
      src/api/modules/system/menu.ts
  42. 70 0
      src/api/modules/system/post.ts
  43. 70 0
      src/api/modules/system/role.ts
  44. 86 0
      src/api/modules/system/user.ts
  45. 91 0
      src/api/modules/tool/gen.ts
  46. 16 0
      src/api/modules/upload.ts
  47. 二進制
      src/assets/fonts/DIN.otf
  48. 二進制
      src/assets/fonts/MetroDF.ttf
  49. 二進制
      src/assets/fonts/YouSheBiaoTiHei.ttf
  50. 14 0
      src/assets/fonts/font.scss
  51. 48 0
      src/assets/iconfont/iconfont.scss
  52. 二進制
      src/assets/iconfont/iconfont.ttf
  53. 1 0
      src/assets/icons/404.svg
  54. 1 0
      src/assets/icons/bug.svg
  55. 1 0
      src/assets/icons/build.svg
  56. 0 0
      src/assets/icons/button.svg
  57. 0 0
      src/assets/icons/cascader.svg
  58. 1 0
      src/assets/icons/chart.svg
  59. 1 0
      src/assets/icons/checkbox.svg
  60. 1 0
      src/assets/icons/clipboard.svg
  61. 1 0
      src/assets/icons/code.svg
  62. 0 0
      src/assets/icons/color.svg
  63. 0 0
      src/assets/icons/component.svg
  64. 0 0
      src/assets/icons/dashboard.svg
  65. 0 0
      src/assets/icons/date-range.svg
  66. 0 0
      src/assets/icons/date.svg
  67. 0 0
      src/assets/icons/dict.svg
  68. 1 0
      src/assets/icons/documentation.svg
  69. 1 0
      src/assets/icons/download.svg
  70. 1 0
      src/assets/icons/drag.svg
  71. 1 0
      src/assets/icons/druid.svg
  72. 1 0
      src/assets/icons/edit.svg
  73. 1 0
      src/assets/icons/education.svg
  74. 1 0
      src/assets/icons/email.svg
  75. 1 0
      src/assets/icons/example.svg
  76. 1 0
      src/assets/icons/excel.svg
  77. 1 0
      src/assets/icons/exit-fullscreen.svg
  78. 1 0
      src/assets/icons/eye-open.svg
  79. 1 0
      src/assets/icons/eye.svg
  80. 0 0
      src/assets/icons/form.svg
  81. 1 0
      src/assets/icons/fullscreen.svg
  82. 1 0
      src/assets/icons/github.svg
  83. 1 0
      src/assets/icons/guide.svg
  84. 1 0
      src/assets/icons/icon.svg
  85. 1 0
      src/assets/icons/input.svg
  86. 1 0
      src/assets/icons/international.svg
  87. 1 0
      src/assets/icons/job.svg
  88. 1 0
      src/assets/icons/language.svg
  89. 1 0
      src/assets/icons/link.svg
  90. 1 0
      src/assets/icons/list.svg
  91. 1 0
      src/assets/icons/lock.svg
  92. 1 0
      src/assets/icons/log.svg
  93. 1 0
      src/assets/icons/logininfor.svg
  94. 1 0
      src/assets/icons/message.svg
  95. 1 0
      src/assets/icons/money.svg
  96. 2 0
      src/assets/icons/monitor.svg
  97. 1 0
      src/assets/icons/nested.svg
  98. 0 0
      src/assets/icons/number.svg
  99. 0 0
      src/assets/icons/online.svg
  100. 1 0
      src/assets/icons/password.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 = Admin
+
+# 本地运行端口号
+VITE_PORT = 8848
+
+# 启动时自动打开浏览器
+VITE_OPEN = true
+
+# 打包后是否生成包分析文件
+VITE_REPORT = false

+ 31 - 0
.env.development

@@ -0,0 +1,31 @@
+# 本地环境
+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"]]
+# VITE_PROXY = [["/api","https://mock.mengxuegu.com/mock/629d727e6163854a32e8307e"]]
+# VITE_PROXY = [["/api","https://www.fastmock.site/mock/f81e8333c1a9276214bcdbc170d9e0a0"]]
+# VITE_PROXY = [["/api-easymock","https://mock.mengxuegu.com"],["/api-fastmock","https://www.fastmock.site"]]

+ 33 - 0
.env.production

@@ -0,0 +1,33 @@
+# 线上环境
+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 = "http://localhost:8080"

+ 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

+ 67 - 0
.eslintrc.cjs

@@ -0,0 +1,67 @@
+// @see: http://eslint.cn
+
+module.exports = {
+  root: true,
+  env: {
+    browser: true,
+    node: true,
+    es6: true
+  },
+  // 指定如何解析语法
+  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'],
+  /**
+   * "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
+  }
+}

+ 24 - 2
.gitignore

@@ -1,4 +1,26 @@
-# ---> VisualStudioCode
-.settings
+# 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: 130,
+  // 缩进制表符宽度 | 空格数
+  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


+ 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)
+}

+ 117 - 0
build/plugins.ts

@@ -0,0 +1,117 @@
+import { resolve } from 'path'
+import { PluginOption } from 'vite'
+import { VitePWA } from 'vite-plugin-pwa'
+import { visualizer } from 'rollup-plugin-visualizer'
+import { createSvgIconsPlugin } from 'vite-plugin-svg-icons'
+import vue from '@vitejs/plugin-vue'
+import vueJsx from '@vitejs/plugin-vue-jsx'
+import eslintPlugin from 'vite-plugin-eslint'
+import viteCompression from 'vite-plugin-compression'
+import simpleHtmlPlugin from 'vite-plugin-simple-html'
+import vueSetupExtend from 'unplugin-vue-setup-extend-plus/vite'
+import { prismjsPlugin } from 'vite-plugin-prismjs'
+
+/**
+ * 创建 vite 插件
+ * @param viteEnv
+ */
+export const createVitePlugins = (viteEnv: ViteEnv): (PluginOption | PluginOption[])[] => {
+  const { VITE_GLOB_APP_TITLE, VITE_REPORT, VITE_PWA } = viteEnv
+  return [
+    vue(),
+    // vue 可以使用 jsx/tsx 语法
+    vueJsx(),
+    // esLint 报错信息显示在浏览器界面上
+    eslintPlugin(),
+    // name 可以写在 script 标签上
+    vueSetupExtend({}),
+    // 创建打包压缩配置
+    createCompression(viteEnv),
+    // 注入变量到 html 文件
+    simpleHtmlPlugin({
+      minify: true,
+      inject: {
+        data: { title: VITE_GLOB_APP_TITLE }
+      }
+    }),
+    // 使用 svg 图标
+    createSvgIconsPlugin({
+      iconDirs: [resolve(process.cwd(), 'src/assets/icons')],
+      symbolId: 'icon-[dir]-[name]'
+    }),
+    // 代码高亮
+    prismjsPlugin({
+      languages: ['json', 'js', 'xml', 'java', 'sql', 'ts'], //  languages: 'all',
+      plugins: ['line-numbers', 'copy-to-clipboard', 'inline-color'], //配置显示行号插件
+      theme: 'tomorrow', //主题名称
+      css: true
+    }),
+    // vitePWA
+    VITE_PWA && createVitePwa(viteEnv),
+    // 是否生成包预览,分析依赖包大小做优化处理
+    VITE_REPORT && (visualizer({ filename: 'stats.html', gzipSize: true, brotliSize: true }) as PluginOption)
+  ]
+}
+
+/**
+ * @description 根据 compress 配置,生成不同的压缩规则
+ * @param viteEnv
+ */
+const createCompression = (viteEnv: ViteEnv): PluginOption | PluginOption[] => {
+  const { VITE_BUILD_COMPRESS = 'none', VITE_BUILD_COMPRESS_DELETE_ORIGIN_FILE } = viteEnv
+  const compressList = VITE_BUILD_COMPRESS.split(',')
+  const plugins: PluginOption[] = []
+  if (compressList.includes('gzip')) {
+    plugins.push(
+      viteCompression({
+        ext: '.gz',
+        algorithm: 'gzip',
+        deleteOriginFile: VITE_BUILD_COMPRESS_DELETE_ORIGIN_FILE
+      })
+    )
+  }
+  if (compressList.includes('brotli')) {
+    plugins.push(
+      viteCompression({
+        ext: '.br',
+        algorithm: 'brotliCompress',
+        deleteOriginFile: VITE_BUILD_COMPRESS_DELETE_ORIGIN_FILE
+      })
+    )
+  }
+  return plugins
+}
+
+/**
+ * @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'
+        }
+      ]
+    }
+  })
+}

+ 31 - 0
build/proxy.ts

@@ -0,0 +1,31 @@
+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="/vue.svg" />
+    <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']
+}

+ 133 - 0
package.json

@@ -0,0 +1,133 @@
+{
+  "name": "km-admin",
+  "private": true,
+  "version": "1.2.0",
+  "type": "module",
+  "description": "km-admin open source management system",
+  "author": {
+    "name": "gaokunw",
+    "email": "wanggaokun@wo.cn"
+  },
+  "license": "MIT",
+  "homepage": "https://gitee.com/gaokunw/kimi-web",
+  "repository": {
+    "type": "git",
+    "url": "git@gitee.com:gaokunw/kimi-web.git"
+  },
+  "bugs": {
+    "url": "https://gitee.com/gaokunw/kimi-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.6.1",
+    "@wangeditor/editor": "^5.1.23",
+    "@wangeditor/editor-for-vue": "^5.1.12",
+    "axios": "^1.6.2",
+    "crypto-js": "^4.2.0",
+    "dayjs": "^1.11.10",
+    "driver.js": "^1.3.1",
+    "echarts": "^5.4.3",
+    "echarts-liquidfill": "^3.1.0",
+    "element-plus": "^2.4.3",
+    "file-saver": "^2.0.5",
+    "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.0",
+    "prismjs": "^1.29.0",
+    "qs": "^6.11.2",
+    "screenfull": "^6.0.2",
+    "sortablejs": "^1.15.1",
+    "vue": "^3.3.11",
+    "vue-i18n": "^9.6.4",
+    "vue-router": "^4.2.5",
+    "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.10",
+    "@types/sortablejs": "^1.15.7",
+    "@typescript-eslint/eslint-plugin": "^6.14.0",
+    "@typescript-eslint/parser": "^6.14.0",
+    "@vitejs/plugin-vue": "^4.5.2",
+    "@vitejs/plugin-vue-jsx": "^3.1.0",
+    "autoprefixer": "^10.4.16",
+    "cz-git": "^1.7.1",
+    "czg": "^1.7.1",
+    "eslint": "^8.55.0",
+    "eslint-config-prettier": "^9.1.0",
+    "eslint-plugin-prettier": "^5.0.1",
+    "eslint-plugin-vue": "^9.19.2",
+    "husky": "^8.0.3",
+    "lint-staged": "^15.1.0",
+    "postcss": "^8.4.32",
+    "postcss-html": "^1.5.0",
+    "prettier": "^3.1.0",
+    "rollup-plugin-visualizer": "^5.9.3",
+    "sass": "^1.69.5",
+    "standard-version": "^9.5.0",
+    "stylelint": "^16.0.2",
+    "stylelint-config-html": "^1.1.0",
+    "stylelint-config-recess-order": "^4.4.0",
+    "stylelint-config-recommended-scss": "^14.0.0",
+    "stylelint-config-recommended-vue": "^1.5.0",
+    "stylelint-config-standard": "^35.0.0",
+    "stylelint-config-standard-scss": "^12.0.0",
+    "typescript": "4.9.5",
+    "unplugin-vue-setup-extend-plus": "^1.0.0",
+    "vite": "^5.0.8",
+    "vite-plugin-compression": "^0.5.1",
+    "vite-plugin-eslint": "^1.8.1",
+    "vite-plugin-prismjs": "^0.0.8",
+    "vite-plugin-pwa": "^0.17.2",
+    "vite-plugin-simple-html": "^0.1.0",
+    "vite-plugin-svg-icons": "^2.0.1",
+    "vue-tsc": "^1.8.25"
+  },
+  "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: {}
+  }
+}

二進制
public/logo.png


+ 1 - 0
public/vue.svg

@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="37.07" height="36" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 198"><path fill="#41B883" d="M204.8 0H256L128 220.8L0 0h97.92L128 51.2L157.44 0h47.36Z"></path><path fill="#41B883" d="m0 0l128 220.8L256 0h-51.2L128 132.48L50.56 0H0Z"></path><path fill="#35495E" d="M50.56 0L128 133.12L204.8 0h-47.36L128 51.2L97.92 0H50.56Z"></path></svg>

+ 44 - 0
src/App.vue

@@ -0,0 +1,44 @@
+<template>
+  <el-config-provider :locale="locale" :size="assemblySize" :button="buttonConfig">
+    <router-view></router-view>
+  </el-config-provider>
+</template>
+
+<script setup lang="ts">
+import { onMounted, reactive, computed } from 'vue'
+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()
+
+// init theme
+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('请求失败!')
+  }
+}

+ 217 - 0
src/api/index.ts

@@ -0,0 +1,217 @@
+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)
+        }
+        return config
+      },
+      (error: AxiosError) => {
+        console.log(error)
+        return Promise.reject(error)
+      }
+    )
+
+    /**
+     * @description 响应拦截器
+     *  服务器换返回信息 -> [拦截统一处理] -> 客户端JS获取到信息
+     */
+    this.service.interceptors.response.use(
+      (response: AxiosResponse) => {
+        // 加密后的 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, config, request } = response
+        axiosCanceler.removePending(config)
+        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(data)
+        }
+        // 成功请求(在页面上除非特殊情况,否则不用处理失败逻辑)
+        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 })
+  }
+  download(url: string, params?: object, _object = {}): Promise<BlobPart> {
+    return this.service.post(url, params, { ..._object, responseType: 'blob' })
+  }
+}
+
+export default new RequestHttp(config)

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

@@ -0,0 +1,97 @@
+// 请求响应参数(不包含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 ReqPage {
+  pageNum: number
+  pageSize: number
+}
+
+// 文件上传模块
+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 ReqPage {
+    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[]
+  }
+}

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

@@ -0,0 +1,29 @@
+import { ReqPage } from '@/api/interface/index'
+// 用户管理模块
+export namespace Menu {
+  export interface ReqMenuParams extends ReqPage {
+    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[]
+  }
+}

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

@@ -0,0 +1,24 @@
+import { Login } from '@/api/interface/index'
+import http from '@/api'
+
+/**
+ * @name 登录模块
+ */
+// 用户登录
+export const loginApi = (params: Login.ReqLoginForm) => {
+  return http.post<Login.ResLogin>('/auth/login', params, { loading: true, isEncrypt: true }) // 正常 post json 请求  ==>  application/json
+}
+
+// 用户退出登录
+export const logoutApi = () => {
+  return http.post('/auth/logout', {}, { loading: false })
+}
+
+// 用户退出登录
+export const getInfoApi = () => {
+  return http.get('/system/user/getInfo', {}, { loading: false })
+}
+// 用户退出登录
+export const getCodeImg = () => {
+  return http.get('/captchaImage', {}, { loading: false })
+}

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

@@ -0,0 +1,70 @@
+import http from '@/api'
+
+/**
+ * @name 查询系统访问记录列表
+ * @param query 参数
+ * @returns 返回列表
+ */
+export const listLogininforApi = (query: any) => {
+  return http.get<any>('/monitor/logininfor/list', query, { loading: true })
+}
+
+/**
+ * @name 查询系统访问记录详细
+ * @param infoId infoId
+ * @returns returns
+ */
+export const getLogininforApi = (infoId: any) => {
+  return http.get<any>(`/monitor/logininfor/${infoId}`)
+}
+
+/**
+ * @name 新增系统访问记录
+ * @param data data
+ * @returns returns
+ */
+export const addLogininforApi = (data: any) => {
+  return http.post<any>('/monitor/logininfor', data, { loading: false })
+}
+
+/**
+ * @name 修改系统访问记录
+ * @param data data
+ * @returns returns
+ */
+export const updateLogininforApi = (data: any) => {
+  return http.put<any>('/monitor/logininfor', data, { loading: false })
+}
+
+/**
+ * @name 删除系统访问记录
+ * @param infoId infoId
+ * @returns returns
+ */
+export const delLogininforApi = ({ infoId }: { infoId: any }) => {
+  return http.delete<any>(`/monitor/logininfor/${infoId}`)
+}
+
+/**
+ * @name 下载模板
+ * @returns returns
+ */
+export const importTemplateApi = () => {
+  return http.download('/monitor/logininfor/importTemplate', {})
+}
+
+/**
+ * @name 导入数据
+ * @returns returns
+ */
+export const importDataApi = (data: any) => {
+  return http.post('/monitor/logininfor/importData', data)
+}
+
+/**
+ * @name 导出数据
+ * @returns returns
+ */
+export const exportApi = (data: any) => {
+  return http.download('/monitor/logininfor/export', data)
+}

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

@@ -0,0 +1,70 @@
+import http from '@/api'
+
+/**
+ * @name 查询操作日志记录列表
+ * @param query 参数
+ * @returns 返回列表
+ */
+export const listOperlogApi = (query: any) => {
+  return http.get<any>('/monitor/operlog/list', query, { loading: true })
+}
+
+/**
+ * @name 查询操作日志记录详细
+ * @param operId operId
+ * @returns returns
+ */
+export const getOperlogApi = (operId: any) => {
+  return http.get<any>(`/monitor/operlog/${operId}`)
+}
+
+/**
+ * @name 新增操作日志记录
+ * @param data data
+ * @returns returns
+ */
+export const addOperlogApi = (data: any) => {
+  return http.post<any>('/monitor/operlog', data, { loading: false })
+}
+
+/**
+ * @name 修改操作日志记录
+ * @param data data
+ * @returns returns
+ */
+export const updateOperlogApi = (data: any) => {
+  return http.put<any>('/monitor/operlog', data, { loading: false })
+}
+
+/**
+ * @name 删除操作日志记录
+ * @param operId operId
+ * @returns returns
+ */
+export const delOperlogApi = ({ operId }: { operId: any }) => {
+  return http.delete<any>(`/monitor/operlog/${operId}`)
+}
+
+/**
+ * @name 下载模板
+ * @returns returns
+ */
+export const importTemplateApi = () => {
+  return http.download('/monitor/operlog/importTemplate', {})
+}
+
+/**
+ * @name 导入数据
+ * @returns returns
+ */
+export const importDataApi = (data: any) => {
+  return http.post('/monitor/operlog/importData', data)
+}
+
+/**
+ * @name 导出数据
+ * @returns returns
+ */
+export const exportApi = (data: any) => {
+  return http.download('/monitor/operlog/export', data)
+}

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

@@ -0,0 +1,70 @@
+import http from '@/api'
+
+/**
+ * @name 查询部门列表
+ * @param query 参数
+ * @returns 返回列表
+ */
+export const listDeptApi = (query: any) => {
+  return http.get<any>('/system/dept/list', query, { loading: true })
+}
+
+/**
+ * @name 查询部门详细
+ * @param deptId deptId
+ * @returns returns
+ */
+export const getDeptApi = (deptId: any) => {
+  return http.get<any>(`/system/dept/${deptId}`)
+}
+
+/**
+ * @name 新增部门
+ * @param data data
+ * @returns returns
+ */
+export const addDeptApi = (data: any) => {
+  return http.post<any>('/system/dept', data, { loading: false })
+}
+
+/**
+ * @name 修改部门
+ * @param data data
+ * @returns returns
+ */
+export const updateDeptApi = (data: any) => {
+  return http.put<any>('/system/dept', data, { loading: false })
+}
+
+/**
+ * @name 删除部门
+ * @param deptId deptId
+ * @returns returns
+ */
+export const delDeptApi = (deptId: any) => {
+  return http.delete<any>(`/system/dept/${deptId}`)
+}
+
+/**
+ * @name 下载模板
+ * @returns returns
+ */
+export const importTemplateApi = () => {
+  return http.download('/system/dept/importTemplate', {})
+}
+
+/**
+ * @name 导入数据
+ * @returns returns
+ */
+export const importDataApi = (data: any) => {
+  return http.post('/system/dept/importData', data)
+}
+
+/**
+ * @name 导出数据
+ * @returns returns
+ */
+export const exportApi = (data: any) => {
+  return http.download('/system/dept/export', data)
+}

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

@@ -0,0 +1,78 @@
+import http from '@/api'
+
+/**
+ * @name 查询字典类型列表
+ * @param query 参数
+ * @returns 返回列表
+ */
+export const listDictApi = (query: any) => {
+  return http.get<any>('/system/dict/type/list', query, { loading: false })
+}
+
+/**
+ * @name 查询字典类型详细
+ * @param dictId dictId
+ * @returns returns
+ */
+export const getDictApi = (dictId: any) => {
+  return http.get<any>(`/system/dict/type/${dictId}`)
+}
+
+/**
+ * @name 新增字典类型
+ * @param data data
+ * @returns returns
+ */
+export const addDictApi = (data: any) => {
+  return http.post<any>('/system/dict/type', data, { loading: false })
+}
+
+/**
+ * @name 修改字典类型
+ * @param data data
+ * @returns returns
+ */
+export const updateDictApi = (data: any) => {
+  return http.put<any>('/system/dict/type', data, { loading: false })
+}
+
+/**
+ * @name 删除字典类型
+ * @param dictId dictId
+ * @returns returns
+ */
+export const delDictApi = ({ id }: { id: any }) => {
+  return http.delete<any>(`/system/dict/type/${id}`)
+}
+
+/**
+ * @name 下载模板
+ * @returns returns
+ */
+export const importTemplateApi = () => {
+  return http.download('/system/dict/type/importTemplate', {})
+}
+
+/**
+ * @name 导入数据
+ * @returns returns
+ */
+export const importDataApi = (data: any) => {
+  return http.post('/system/dict/type/importData', data)
+}
+
+/**
+ * @name 导出数据
+ * @returns returns
+ */
+export const exportApi = (data: any) => {
+  return http.download('/system/dict/type/export', data)
+}
+
+/**
+ * @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'
+
+/**
+ * @name 查询字典数据列表
+ * @param query 参数
+ * @returns 返回列表
+ */
+export const listDataApi = (query: any) => {
+  return http.get<any>('/system/dict/data/list', query, { loading: true })
+}
+
+/**
+ * @name 查询字典数据详细
+ * @param dictCode dictCode
+ * @returns returns
+ */
+export const getDataApi = (dictCode: any) => {
+  return http.get<any>(`/system/dict/data/${dictCode}`)
+}
+
+/**
+ * @name 根据字典类型查询字典数据信息
+ * @param dictType dictType
+ * @returns returns
+ */
+export const getDictsApi = (dictType: string) => {
+  return http.get<any>(`/system/dict/data/type/${dictType}`)
+}
+
+/**
+ * @name 新增字典数据
+ * @param data data
+ * @returns returns
+ */
+export const addDataApi = (data: any) => {
+  return http.post<any>('/system/dict/data', data, { loading: false })
+}
+
+/**
+ * @name 修改字典数据
+ * @param data data
+ * @returns returns
+ */
+export const updateDataApi = (data: any) => {
+  return http.put<any>('/system/dict/data', data, { loading: false })
+}
+
+/**
+ * @name 删除字典数据
+ * @param dictCode dictCode
+ * @returns returns
+ */
+export const delDataApi = ({ id }: { id: any }) => {
+  return http.delete<any>(`/system/dict/data/${id}`)
+}
+
+/**
+ * @name 导出数据
+ * @returns returns
+ */
+export const exportApi = (data: any) => {
+  return http.download('/system/dict/data/export', data)
+}

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

@@ -0,0 +1,92 @@
+import http from '@/api'
+
+// 获取路由
+export const getRoutersApi = () => {
+  return http.get<Menu.MenuOptions[]>('/system/menu/getRouters', {}, { loading: false })
+}
+
+/**
+ * @name 查询菜单列表
+ * @param query 参数
+ * @returns 返回列表
+ */
+export const listMenuApi = (query?: any) => {
+  return http.get<any>('/system/menu/list', query, { loading: true })
+}
+
+/**
+ * @name 查询菜单详细
+ * @param menuId menuId
+ * @returns returns
+ */
+export const getMenuApi = (menuId: any) => {
+  return http.get<any>(`/system/menu/${menuId}`)
+}
+
+/**
+ * @name 新增菜单
+ * @param data data
+ * @returns returns
+ */
+export const addMenuApi = (data: any) => {
+  return http.post<any>('/system/menu', data, { loading: false })
+}
+
+/**
+ * @name 修改菜单
+ * @param data data
+ * @returns returns
+ */
+export const updateMenuApi = (data: any) => {
+  return http.put<any>('/system/menu', data, { loading: false })
+}
+
+/**
+ * @name 删除菜单
+ * @param menuId menuId
+ * @returns returns
+ */
+export const delMenuApi = (menuId: any) => {
+  return http.delete<any>(`/system/menu/${menuId}`)
+}
+
+/**
+ * @name 下载模板
+ * @returns returns
+ */
+export const importTemplateApi = () => {
+  return http.download('/system/menu/importTemplate', {})
+}
+
+/**
+ * @name 导入数据
+ * @returns returns
+ */
+export const importDataApi = (data: any) => {
+  return http.post('/system/menu/importData', data)
+}
+
+/**
+ * @name 导出数据
+ * @returns returns
+ */
+export const exportApi = (data: any) => {
+  return http.download('/system/menu/export', data)
+}
+
+/**
+ * @name 查询菜单下拉树结构
+ * @returns returns
+ */
+export const treeselectApi = () => {
+  return http.get<any>(`/system/menu/treeselect`)
+}
+
+/**
+ * @name 根据角色ID查询菜单下拉树结构
+ * @param roleId roleId
+ * @returns returns
+ */
+export const roleMenuTreeselectApi = (roleId: any) => {
+  return http.get<any>(`/system/menu/roleMenuTreeselect/${roleId}`)
+}

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

@@ -0,0 +1,70 @@
+import http from '@/api'
+
+/**
+ * @name 查询岗位信息列表
+ * @param query 参数
+ * @returns 返回列表
+ */
+export const listPostApi = (query: any) => {
+  return http.get<any>('/system/post/list', query, { loading: true })
+}
+
+/**
+ * @name 查询岗位信息详细
+ * @param postId postId
+ * @returns returns
+ */
+export const getPostApi = (postId: any) => {
+  return http.get<any>(`/system/post/${postId}`)
+}
+
+/**
+ * @name 新增岗位信息
+ * @param data data
+ * @returns returns
+ */
+export const addPostApi = (data: any) => {
+  return http.post<any>('/system/post', data, { loading: false })
+}
+
+/**
+ * @name 修改岗位信息
+ * @param data data
+ * @returns returns
+ */
+export const updatePostApi = (data: any) => {
+  return http.put<any>('/system/post', data, { loading: false })
+}
+
+/**
+ * @name 删除岗位信息
+ * @param postId postId
+ * @returns returns
+ */
+export const delPostApi = ({ postId }: { postId: any }) => {
+  return http.delete<any>(`/system/post/${postId}`)
+}
+
+/**
+ * @name 下载模板
+ * @returns returns
+ */
+export const importTemplateApi = () => {
+  return http.download('/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.download('/system/post/export', data)
+}

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

@@ -0,0 +1,70 @@
+import http from '@/api'
+
+/**
+ * @name 查询角色信息列表
+ * @param query 参数
+ * @returns 返回列表
+ */
+export const listRoleApi = (query: any) => {
+  return http.get<any>('/system/role/list', query, { loading: true })
+}
+
+/**
+ * @name 查询角色信息详细
+ * @param roleId roleId
+ * @returns returns
+ */
+export const getRoleApi = (roleId: any) => {
+  return http.get<any>(`/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 roleId roleId
+ * @returns returns
+ */
+export const delRoleApi = ({ roleId }: { roleId: any }) => {
+  return http.delete<any>(`/system/role/${roleId}`)
+}
+
+/**
+ * @name 下载模板
+ * @returns returns
+ */
+export const importTemplateApi = () => {
+  return http.download('/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.download('/system/role/export', data)
+}

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

@@ -0,0 +1,86 @@
+import http from '@/api'
+import { parseStrEmpty } from '@/utils/common'
+
+/**
+ * @name 查询用户列表
+ * @param query 参数
+ * @returns 返回列表
+ */
+export const listUserApi = (query: any) => {
+  return http.get<any>('/system/user/list', query, { loading: true })
+}
+
+/**
+ * @name 查询用户详细
+ * @param userId userId
+ * @returns returns
+ */
+export const getUserApi = (userId?: string) => {
+  return http.get<any>(`/system/user/` + parseStrEmpty(userId))
+}
+
+/**
+ * @name 查询部门下拉树结构
+ * @returns returns
+ */
+export const deptTreeSelectApi = () => {
+  return http.get<any>(`/system/user/deptTree`)
+}
+
+/**
+ * @name 新增用户
+ * @returns returns
+ */
+export const addUserApi = (data: any) => {
+  return http.post<any>('/system/user', data, { loading: false })
+}
+
+/**
+ * @name 修改用户
+ * @returns returns
+ */
+export const updateUserApi = (data: any) => {
+  return http.put<any>('/system/user', data, { loading: false })
+}
+
+/**
+ * @name 删除用户
+ * @returns returns
+ */
+export const delUserApi = (userId: any) => {
+  return http.delete<any>(`/system/user/${userId}`)
+}
+
+/**
+ * @name 用户状态修改
+ * @param userId userId
+ * @param status status
+ * @returns returns
+ */
+export const changeUserStatus = (data: any) => {
+  return http.put<any>('/system/user/changeStatus', data, { loading: false })
+}
+
+/**
+ * @name 下载模板
+ * @returns returns
+ */
+export const importTemplateApi = () => {
+  return http.download('/system/user/importTemplate', {})
+}
+
+/**
+ * @name 导入数据
+ * @returns returns
+ */
+export const importDataApi = (params: FormData) => {
+  return http.post('/system/user/importData', params)
+}
+
+/**
+ * @name 导出数据
+ * @returns returns
+ */
+export const exportApi = (data: any) => {
+  return http.download('/system/user/export', data)
+}

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

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

二進制
src/assets/fonts/DIN.otf


二進制
src/assets/fonts/MetroDF.ttf


二進制
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';
+}

二進制
src/assets/iconfont/iconfont.ttf


+ 1 - 0
src/assets/icons/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/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/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>

文件差異過大導致無法顯示
+ 0 - 0
src/assets/icons/button.svg


文件差異過大導致無法顯示
+ 0 - 0
src/assets/icons/cascader.svg


+ 1 - 0
src/assets/icons/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/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/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/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>

文件差異過大導致無法顯示
+ 0 - 0
src/assets/icons/color.svg


文件差異過大導致無法顯示
+ 0 - 0
src/assets/icons/component.svg


文件差異過大導致無法顯示
+ 0 - 0
src/assets/icons/dashboard.svg


文件差異過大導致無法顯示
+ 0 - 0
src/assets/icons/date-range.svg


文件差異過大導致無法顯示
+ 0 - 0
src/assets/icons/date.svg


文件差異過大導致無法顯示
+ 0 - 0
src/assets/icons/dict.svg


+ 1 - 0
src/assets/icons/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/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/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/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/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/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/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/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/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/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/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>

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

@@ -0,0 +1 @@
+<svg width="128" height="64" xmlns="http://www.w3.org/2000/svg"><path d="M127.072 7.994c1.37-2.208.914-5.152-.914-6.87-2.056-1.717-4.797-1.226-6.396.982-.229.245-25.586 32.382-55.74 32.382-29.24 0-55.74-32.382-55.968-32.627-1.6-1.963-4.57-2.208-6.397-.49C-.17 3.086-.399 6.275 1.2 8.238c.457.736 5.94 7.36 14.62 14.72L4.17 35.96c-1.828 1.963-1.6 5.152.228 6.87.457.98 1.6 1.471 2.742 1.471s2.284-.49 3.198-1.472l12.564-13.983c5.94 4.416 13.021 8.587 20.788 11.53l-4.797 17.418c-.685 2.699.686 5.397 3.198 6.133h1.37c2.057 0 3.884-1.472 4.341-3.68L52.6 42.83c3.655.736 7.538 1.227 11.422 1.227 3.883 0 7.767-.49 11.422-1.227l4.797 17.173c.457 2.208 2.513 3.68 4.34 3.68.457 0 .914 0 1.143-.246 2.513-.736 3.883-3.434 3.198-6.133l-4.797-17.172c7.767-2.944 14.848-7.114 20.788-11.53l12.336 13.738c.913.981 2.056 1.472 3.198 1.472s2.284-.49 3.198-1.472c1.828-1.963 1.828-4.906.228-6.87l-11.65-13.001c9.366-7.36 14.849-14.474 14.849-14.474z"/></svg>

文件差異過大導致無法顯示
+ 0 - 0
src/assets/icons/form.svg


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

@@ -0,0 +1 @@
+<svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M38.47 52L52 38.462l-23.648-23.67L43.209 0H.035L0 43.137l14.757-14.865L38.47 52zm74.773 47.726L89.526 76 76 89.536l23.648 23.672L84.795 128h43.174L128 84.863l-14.757 14.863zM89.538 52l23.668-23.648L128 43.207V.038L84.866 0 99.73 14.76 76 38.472 89.538 52zM38.46 76L14.792 99.651 0 84.794v43.173l43.137.033-14.865-14.757L52 89.53 38.46 76z"/></svg>

+ 1 - 0
src/assets/icons/github.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="1581238998885" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4187" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css"></style></defs><path d="M511.542857 14.057143C228.914286 13.942857 0 242.742857 0 525.142857 0 748.457143 143.2 938.285714 342.628571 1008c26.857143 6.742857 22.742857-12.342857 22.742858-25.371429v-88.571428c-155.085714 18.171429-161.371429-84.457143-171.771429-101.6C172.571429 756.571429 122.857143 747.428571 137.714286 730.285714c35.314286-18.171429 71.314286 4.571429 113.028571 66.171429 30.171429 44.685714 89.028571 37.142857 118.857143 29.714286 6.514286-26.857143 20.457143-50.857143 39.657143-69.485715-160.685714-28.8-227.657143-126.857143-227.657143-243.428571 0-56.571429 18.628571-108.571429 55.2-150.514286-23.314286-69.142857 2.171429-128.342857 5.6-137.142857 66.4-5.942857 135.428571 47.542857 140.8 51.771429 37.714286-10.171429 80.8-15.542857 129.028571-15.542858 48.457143 0 91.657143 5.6 129.714286 15.885715 12.914286-9.828571 76.914286-55.771429 138.628572-50.171429 3.314286 8.8 28.228571 66.628571 6.285714 134.857143 37.028571 42.057143 55.885714 94.514286 55.885714 151.2 0 116.8-67.428571 214.971429-228.571428 243.314286a145.714286 145.714286 0 0 1 43.542857 104v128.571428c0.914286 10.285714 0 20.457143 17.142857 20.457143 202.4-68.228571 348.114286-259.428571 348.114286-484.685714 0-282.514286-229.028571-511.2-511.428572-511.2z" p-id="4188"></path></svg>

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

@@ -0,0 +1 @@
+<svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M1.482 70.131l36.204 16.18 69.932-65.485-61.38 70.594 46.435 18.735c1.119.425 2.397-.17 2.797-1.363v-.085L127.998.047 1.322 65.874c-1.12.597-1.519 1.959-1.04 3.151.32.511.72.937 1.2 1.107zm44.676 57.821L64.22 107.26l-18.062-7.834v28.527z"/></svg>

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

@@ -0,0 +1 @@
+<svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M115.147.062a13 13 0 0 1 4.94.945c1.55.63 2.907 1.526 4.069 2.688a13.148 13.148 0 0 1 2.761 4.069c.678 1.55 1.017 3.245 1.017 5.086v102.3c0 3.681-1.187 6.733-3.56 9.155-2.373 2.422-5.352 3.633-8.937 3.633H12.992c-3.875 0-7-1.26-9.373-3.779-2.373-2.518-3.56-5.667-3.56-9.445V12.704c0-3.39 1.163-6.345 3.488-8.863C5.872 1.32 8.972.062 12.847.062h102.3zM81.434 109.047c1.744 0 3.003-.412 3.778-1.235.775-.824 1.163-1.914 1.163-3.27 0-1.26-.388-2.325-1.163-3.197-.775-.872-2.034-1.307-3.778-1.307H72.57c.097-.194.145-.485.145-.872V27.09h9.01c1.743 0 2.954-.436 3.633-1.308.678-.872 1.017-1.938 1.017-3.197 0-1.26-.34-2.325-1.017-3.197-.679-.872-1.89-1.308-3.633-1.308H46.268c-1.743 0-2.954.436-3.632 1.308-.678.872-1.018 1.938-1.018 3.197 0 1.26.34 2.325 1.018 3.197.678.872 1.889 1.308 3.632 1.308h8.138v72.075c0 .193.024.339.073.436.048.096.072.242.072.436H46.56c-1.744 0-3.003.435-3.778 1.307-.775.872-1.163 1.938-1.163 3.197 0 1.356.388 2.446 1.163 3.27.775.823 2.034 1.235 3.778 1.235h34.875z"/></svg>

+ 1 - 0
src/assets/icons/input.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="1575802859706" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="3102" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css"></style></defs><path d="M896 224H128c-35.2 0-64 28.8-64 64v448c0 35.2 28.8 64 64 64h768c35.2 0 64-28.8 64-64V288c0-35.2-28.8-64-64-64z m0 480c0 19.2-12.8 32-32 32H160c-19.2 0-32-12.8-32-32V320c0-19.2 12.8-32 32-32h704c19.2 0 32 12.8 32 32v384z" p-id="3103"></path><path d="M224 352c-19.2 0-32 12.8-32 32v256c0 16 12.8 32 32 32s32-12.8 32-32V384c0-16-12.8-32-32-32z" p-id="3104"></path></svg>

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

@@ -0,0 +1 @@
+<svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M83.287 103.01c-1.57-3.84-6.778-10.414-15.447-19.548-2.327-2.444-2.182-4.306-1.338-9.862v-.64c.553-3.81 1.513-6.05 14.313-8.087 6.516-1.018 8.203 1.57 10.589 5.178l.785 1.193a12.625 12.625 0 0 0 6.43 5.207c1.134.524 2.53 1.164 4.421 2.24 4.596 2.53 4.596 5.41 4.596 11.753v.727a26.91 26.91 0 0 1-5.178 17.454 59.055 59.055 0 0 1-19.025 11.026c3.49-6.546.814-14.313 0-16.553l-.146-.087zM64 5.12a58.502 58.502 0 0 1 25.484 5.818 54.313 54.313 0 0 0-12.859 10.327c-.93 1.28-1.716 2.473-2.472 3.579-2.444 3.694-3.637 5.352-5.818 5.614a25.105 25.105 0 0 1-4.219 0c-4.276-.29-10.094-.64-11.956 4.422-1.193 3.23-1.396 11.956 2.444 16.495.66 1.077.778 2.4.32 3.578a7.01 7.01 0 0 1-2.066 3.229 18.938 18.938 0 0 1-2.909-2.91 18.91 18.91 0 0 0-8.32-6.603c-1.25-.349-2.647-.64-3.985-.93-3.782-.786-8.03-1.688-9.019-3.812a14.895 14.895 0 0 1-.727-5.818 21.935 21.935 0 0 0-1.396-9.25 8.873 8.873 0 0 0-5.557-4.946A58.705 58.705 0 0 1 64 5.12zM0 64c0 35.346 28.654 64 64 64 35.346 0 64-28.654 64-64 0-35.346-28.654-64-64-64C28.654 0 0 28.654 0 64z"/></svg>

+ 1 - 0
src/assets/icons/job.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="1566036191400" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="5472" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css"></style></defs><path d="M934.912 1016.832H192c-14.336 0-25.6-11.264-25.6-25.6v-189.44c0-14.336 11.264-25.6 25.6-25.6s25.6 11.264 25.6 25.6v163.84h691.712V64H217.6v148.48c0 14.336-11.264 25.6-25.6 25.6s-25.6-11.264-25.6-25.6v-174.08c0-14.336 11.264-25.6 25.6-25.6h742.912c14.336 0 25.6 11.264 25.6 25.6v952.832c0 14.336-11.264 25.6-25.6 25.6z" p-id="5473"></path><path d="M232.96 371.2h-117.76c-14.336 0-25.6-11.264-25.6-25.6s11.264-25.6 25.6-25.6h117.76c14.336 0 25.6 11.264 25.6 25.6s-11.264 25.6-25.6 25.6zM232.96 540.16h-117.76c-14.336 0-25.6-11.264-25.6-25.6s11.264-25.6 25.6-25.6h117.76c14.336 0 25.6 11.264 25.6 25.6s-11.264 25.6-25.6 25.6zM232.96 698.88h-117.76c-14.336 0-25.6-11.264-25.6-25.6s11.264-25.6 25.6-25.6h117.76c14.336 0 25.6 11.264 25.6 25.6s-11.264 25.6-25.6 25.6zM574.464 762.88c-134.144 0-243.2-109.056-243.2-243.2S440.32 276.48 574.464 276.48s243.2 109.056 243.2 243.2-109.056 243.2-243.2 243.2z m0-435.2c-105.984 0-192 86.016-192 192S468.48 711.68 574.464 711.68s192-86.016 192-192S680.448 327.68 574.464 327.68z" p-id="5474"></path><path d="M663.04 545.28h-87.04c-14.336 0-25.6-11.264-25.6-25.6s11.264-25.6 25.6-25.6h87.04c14.336 0 25.6 11.264 25.6 25.6s-11.264 25.6-25.6 25.6z" p-id="5475"></path><path d="M576 545.28c-14.336 0-25.6-11.264-25.6-25.6v-87.04c0-14.336 11.264-25.6 25.6-25.6s25.6 11.264 25.6 25.6v87.04c0 14.336-11.264 25.6-25.6 25.6z" p-id="5476"></path></svg>

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

@@ -0,0 +1 @@
+<svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M84.742 36.8c2.398 7.2 5.595 12.8 11.19 18.4 4.795-4.8 7.992-11.2 10.39-18.4h-21.58zm-52.748 40h20.78l-10.39-28-10.39 28z"/><path d="M111.916 0H16.009C7.218 0 .025 7.2.025 16v96c0 8.8 7.193 16 15.984 16h95.907c8.791 0 15.984-7.2 15.984-16V16c0-8.8-6.394-16-15.984-16zM72.754 103.2c-1.598 1.6-3.197 1.6-4.795 1.6-.8 0-2.398 0-3.197-.8-.8-.8-1.599 0-1.599-.8s-.799-1.6-1.598-3.2c-.8-1.6-.8-2.4-1.599-4l-3.196-8.8H28.797L25.6 96c-1.598 3.2-2.398 5.6-3.197 7.2-.8 1.6-2.398 1.6-4.795 1.6-1.599 0-3.197-.8-4.796-1.6-1.598-1.6-2.397-2.4-2.397-4 0-.8 0-1.6.799-3.2.8-1.6.8-2.4 1.598-4l17.583-44.8c.8-1.6.8-3.2 1.599-4.8.799-1.6 1.598-3.2 2.397-4 .8-.8 1.599-2.4 3.197-3.2 1.599-.8 3.197-.8 4.796-.8 1.598 0 3.196 0 4.795.8 1.598.8 2.398 1.6 3.197 3.2.799.8 1.598 2.4 2.397 4 .8 1.6 1.599 3.2 2.398 5.6l17.583 44c1.598 3.2 2.398 5.6 2.398 7.2-.8.8-1.599 2.4-2.398 4zM116.711 72c-8.791-3.2-15.185-7.2-20.78-12-5.594 5.6-12.787 9.6-21.579 12l-2.397-4c8.791-2.4 15.984-5.6 21.579-11.2C87.939 51.2 83.144 44 81.545 36h-7.992v-3.2h21.58c-1.6-2.4-3.198-5.6-4.796-8l2.397-.8c1.599 2.4 3.997 5.6 5.595 8.8h19.98v4h-7.992c-2.397 8-6.393 15.2-11.189 20 5.595 4.8 11.988 8.8 20.78 11.2l-3.197 4z"/></svg>

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

@@ -0,0 +1 @@
+<svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M115.625 127.937H.063V12.375h57.781v12.374H12.438v90.813h90.813V70.156h12.374z"/><path d="M116.426 2.821l8.753 8.753-56.734 56.734-8.753-8.745z"/><path d="M127.893 37.982h-12.375V12.375H88.706V0h39.187z"/></svg>

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

@@ -0,0 +1 @@
+<svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M1.585 12.087c0 6.616 3.974 11.98 8.877 11.98 4.902 0 8.877-5.364 8.877-11.98 0-6.616-3.975-11.98-8.877-11.98-4.903 0-8.877 5.364-8.877 11.98zM125.86.107H35.613c-1.268 0-2.114 1.426-2.114 2.852v18.255c0 1.712 1.057 2.853 2.114 2.853h90.247c1.268 0 2.114-1.426 2.114-2.853V2.96c0-1.711-1.057-2.852-2.114-2.852zM.106 62.86c0 6.615 3.974 11.979 8.876 11.979 4.903 0 8.877-5.364 8.877-11.98 0-6.616-3.974-11.98-8.877-11.98-4.902 0-8.876 5.364-8.876 11.98zM124.17 50.88H33.921c-1.268 0-2.114 1.425-2.114 2.851v18.256c0 1.711 1.057 2.852 2.114 2.852h90.247c1.268 0 2.114-1.426 2.114-2.852V53.73c0-1.426-.846-2.852-2.114-2.852zM.106 115.913c0 6.616 3.974 11.98 8.876 11.98 4.903 0 8.877-5.364 8.877-11.98 0-6.616-3.974-11.98-8.877-11.98-4.902 0-8.876 5.364-8.876 11.98zm124.064-11.98H33.921c-1.268 0-2.114 1.426-2.114 2.853v18.255c0 1.711 1.057 2.852 2.114 2.852h90.247c1.268 0 2.114-1.426 2.114-2.852v-18.255c0-1.427-.846-2.853-2.114-2.853z"/></svg>

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

@@ -0,0 +1 @@
+<svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M119.88 49.674h-7.987V39.52C111.893 17.738 90.45.08 63.996.08 37.543.08 16.1 17.738 16.1 39.52v10.154H8.113c-4.408 0-7.987 2.94-7.987 6.577v65.13c0 3.637 3.57 6.577 7.987 6.577H119.88c4.407 0 7.987-2.94 7.987-6.577v-65.13c-.008-3.636-3.58-6.577-7.987-6.577zm-23.953 0H32.065V39.52c0-14.524 14.301-26.295 31.931-26.295 17.63 0 31.932 11.777 31.932 26.295v10.153z"/></svg>

+ 1 - 0
src/assets/icons/log.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="1566035943711" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4805" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css"></style></defs><path d="M208.736 566.336H64.384v59.328h144.352v-59.328z m0-336.096H165.44V74.592c0-7.968 4.896-14.848 10.464-14.848h502.016V0.448H175.936c-38.72 1.248-69.248 34.368-68.192 74.144v155.648H64.384V289.6h144.352V230.24z m0 168.096H64.384v59.328h144.352v-59.328z m714.656 76.576h-57.76v474.496c0 7.936-4.896 14.848-10.464 14.848H175.936c-5.568 0-10.464-6.912-10.464-14.848v-155.68h43.296v-59.296H64.384v59.296h43.328v155.68c-1.024 39.776 29.472 72.896 68.192 74.144h679.232c38.72-1.184 69.248-34.368 68.256-74.144V474.912z m14.944-290.336l-83.072-85.312a71.264 71.264 0 0 0-52.544-21.728 71.52 71.52 0 0 0-51.616 23.872L386.528 507.264a30.496 30.496 0 0 0-6.176 10.72L308.16 740.512a30.016 30.016 0 0 0 6.976 30.24c7.712 7.968 19.2 10.752 29.568 7.2l216.544-74.112a28.736 28.736 0 0 0 12.128-7.936L940.448 287.456a75.552 75.552 0 0 0-2.112-102.88z m-557.12 518.272l39.104-120.64 78.336 80.416-117.44 40.224z m170.048-70.016l-103.552-106.016 200.16-222.4 103.52 106.304-200.128 222.112zM897.952 247.072l-0.256 0.224-107.136 119.168-103.52-106.528 106.432-118.624a14.144 14.144 0 0 1 10.304-4.736 13.44 13.44 0 0 1 10.464 4.288l83.264 85.696c5.472 5.6 5.664 14.72 0.448 20.512z" p-id="4806"></path></svg>

+ 1 - 0
src/assets/icons/logininfor.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="1566036016814" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="5261" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css"></style></defs><path d="M896 128h-85.333333a42.666667 42.666667 0 0 0 0 85.333333h42.666666v640H170.666667V213.333333h42.666666a42.666667 42.666667 0 0 0 0-85.333333H128a42.666667 42.666667 0 0 0-42.666667 42.666667v725.333333a42.666667 42.666667 0 0 0 42.666667 42.666667h768a42.666667 42.666667 0 0 0 42.666667-42.666667V170.666667a42.666667 42.666667 0 0 0-42.666667-42.666667z" p-id="5262"></path><path d="M341.333333 298.666667a42.666667 42.666667 0 0 0 42.666667-42.666667V128a42.666667 42.666667 0 0 0-85.333333 0v128a42.666667 42.666667 0 0 0 42.666666 42.666667zM512 298.666667a42.666667 42.666667 0 0 0 42.666667-42.666667V128a42.666667 42.666667 0 0 0-85.333334 0v128a42.666667 42.666667 0 0 0 42.666667 42.666667zM682.666667 298.666667a42.666667 42.666667 0 0 0 42.666666-42.666667V128a42.666667 42.666667 0 0 0-85.333333 0v128a42.666667 42.666667 0 0 0 42.666667 42.666667zM341.333333 768a42.666667 42.666667 0 0 0 42.666667-42.666667 128 128 0 0 1 256 0 42.666667 42.666667 0 0 0 85.333333 0 213.333333 213.333333 0 0 0-107.52-184.32A128 128 0 0 0 640 469.333333a128 128 0 0 0-256 0 128 128 0 0 0 22.186667 71.68A213.333333 213.333333 0 0 0 298.666667 725.333333a42.666667 42.666667 0 0 0 42.666666 42.666667z m128-298.666667a42.666667 42.666667 0 1 1 42.666667 42.666667 42.666667 42.666667 0 0 1-42.666667-42.666667z" p-id="5263"></path></svg>

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

@@ -0,0 +1 @@
+<svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M0 20.967v59.59c0 11.59 8.537 20.966 19.075 20.966h28.613l1 26.477L76.8 101.523h32.125c10.538 0 19.075-9.377 19.075-20.966v-59.59C128 9.377 119.463 0 108.925 0h-89.85C8.538 0 0 9.377 0 20.967zm82.325 33.1c0-5.524 4.013-9.935 9.037-9.935 5.026 0 9.038 4.41 9.038 9.934 0 5.524-4.025 9.934-9.038 9.934-5.024 0-9.037-4.41-9.037-9.934zm-27.613 0c0-5.524 4.013-9.935 9.038-9.935s9.037 4.41 9.037 9.934c0 5.524-4.025 9.934-9.037 9.934-5.025 0-9.038-4.41-9.038-9.934zm-27.1 0c0-5.524 4.013-9.935 9.038-9.935s9.038 4.41 9.038 9.934c0 5.524-4.026 9.934-9.05 9.934-5.013 0-9.025-4.41-9.025-9.934z"/></svg>

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

@@ -0,0 +1 @@
+<svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M54.122 127.892v-28.68H7.513V87.274h46.609v-12.4H7.513v-12.86h38.003L.099 0h22.6l32.556 45.07c3.617 5.144 6.44 9.611 8.487 13.385 1.788-3.05 4.89-7.779 9.301-14.186L103.93 0h24.01L82.385 62.013h38.34v12.862h-46.41v12.4h46.41v11.937h-46.41v28.68H54.123z"/></svg>

+ 2 - 0
src/assets/icons/monitor.svg

@@ -0,0 +1,2 @@
+<?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="1543827393750" class="icon" style="" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4695" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css">@font-face { font-family: rbicon; src: url("chrome-extension://dipiagiiohfljcicegpgffpbnjmgjcnf/fonts/rbicon.woff2") format("woff2"); font-weight: normal; font-style: normal; }
+</style></defs><path d="M64 64V640H896V64H64zM0 0h960v704H0V0z" p-id="4696"></path><path d="M192 896H768v64H192zM448 640H512v256h-64z" p-id="4697"></path><path d="M479.232 561.604267l309.9904-348.330667-47.803733-42.5472-259.566934 291.669333L303.957333 240.008533 163.208533 438.6048l52.224 37.009067 91.6224-129.28z" p-id="4698"></path></svg>

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

@@ -0,0 +1 @@
+<svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M.002 9.2c0 5.044 3.58 9.133 7.998 9.133 4.417 0 7.997-4.089 7.997-9.133 0-5.043-3.58-9.132-7.997-9.132S.002 4.157.002 9.2zM31.997.066h95.981V18.33H31.997V.066zm0 45.669c0 5.044 3.58 9.132 7.998 9.132 4.417 0 7.997-4.088 7.997-9.132 0-3.263-1.524-6.278-3.998-7.91-2.475-1.63-5.524-1.63-7.998 0-2.475 1.632-4 4.647-4 7.91zM63.992 36.6h63.986v18.265H63.992V36.6zm-31.995 82.2c0 5.043 3.58 9.132 7.998 9.132 4.417 0 7.997-4.089 7.997-9.132 0-5.044-3.58-9.133-7.997-9.133s-7.998 4.089-7.998 9.133zm31.995-9.131h63.986v18.265H63.992V109.67zm0-27.404c0 5.044 3.58 9.133 7.998 9.133 4.417 0 7.997-4.089 7.997-9.133 0-3.263-1.524-6.277-3.998-7.909-2.475-1.631-5.524-1.631-7.998 0-2.475 1.632-4 4.646-4 7.91zm31.995-9.13h31.991V91.4H95.987V73.135z"/></svg>

文件差異過大導致無法顯示
+ 0 - 0
src/assets/icons/number.svg


文件差異過大導致無法顯示
+ 0 - 0
src/assets/icons/online.svg


+ 1 - 0
src/assets/icons/password.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="1575802846045" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2750" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css"></style></defs><path d="M868.593046 403.832442c-30.081109-28.844955-70.037123-44.753273-112.624057-44.753273L265.949606 359.079168c-42.554188 0-82.510202 15.908318-112.469538 44.690852-30.236652 28.782533-46.857191 67.222007-46.857191 108.198258l0 294.079782c0 40.977273 16.619516 79.414701 46.702672 108.136859 29.959336 28.844955 70.069869 44.814672 112.624057 44.814672l490.019383 0c42.585911 0 82.696444-15.969717 112.624057-44.814672 30.082132-28.844955 46.579875-67.222007 46.579875-108.136859L915.172921 511.968278C915.171897 471.053426 898.675178 432.677397 868.593046 403.832442zM841.821309 806.049083c0 22.098297-8.882298 42.772152-25.099654 58.306964-16.154935 15.661701-37.81935 24.203238-60.752666 24.203238L265.949606 888.559285c-22.934339 0-44.567032-8.54256-60.877509-24.264637-16.186657-15.474436-25.067932-36.148291-25.067932-58.246589L180.004165 511.968278c0-22.035876 8.881274-42.772152 25.192775-58.307987 16.186657-15.536858 37.81935-24.139793 60.753689-24.139793l490.019383 0c22.933315 0 44.597731 8.602935 60.752666 24.139793 16.21838 15.535835 25.099654 36.272112 25.099654 58.307987L841.822332 806.049083zM510.974136 135.440715c114.914216 0 208.318536 89.75214 208.318536 200.055338l73.350588 0c0-149.113109-126.366036-270.496667-281.669124-270.496667-155.333788 0-281.699824 121.383558-281.699824 270.496667l73.350588 0C302.623877 225.193879 396.059919 135.440715 510.974136 135.440715zM474.299865 747.244792l73.350588 0L547.650453 629.576859l-73.350588 0L474.299865 747.244792z" p-id="2751"></path></svg>

部分文件因文件數量過多而無法顯示