Explorar o código

init: 项目初始搭建

wanggaokun hai 1 ano
achega
9468541f7c
Modificáronse 100 ficheiros con 2991 adicións e 0 borrados
  1. 15 0
      .editorconfig
  2. 11 0
      .env
  3. 31 0
      .env.development
  4. 36 0
      .env.production
  5. 25 0
      .env.test
  6. 15 0
      .eslintignore
  7. 67 0
      .eslintrc.cjs
  8. 26 0
      .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. 8 0
      LICENSE
  19. 9 0
      README.md
  20. 46 0
      build/getEnv.ts
  21. 117 0
      build/plugins.ts
  22. 31 0
      build/proxy.ts
  23. 162 0
      commitlint.config.cjs
  24. 105 0
      index.html
  25. 8 0
      lint-staged.config.cjs
  26. 126 0
      package.json
  27. 5 0
      postcss.config.cjs
  28. BIN=BIN
      public/logo.png
  29. 1 0
      public/vue.svg
  30. 44 0
      src/App.vue
  31. 3 0
      src/api/config/servicePort.ts
  32. 46 0
      src/api/helper/axiosCancel.ts
  33. 43 0
      src/api/helper/checkStatus.ts
  34. 210 0
      src/api/index.ts
  35. 108 0
      src/api/interface/index.ts
  36. 29 0
      src/api/interface/menu.ts
  37. 28 0
      src/api/interface/system/data.ts
  38. 47 0
      src/api/interface/system/dept.ts
  39. 25 0
      src/api/interface/system/post.ts
  40. 54 0
      src/api/interface/system/role.ts
  41. 20 0
      src/api/interface/system/type.ts
  42. 87 0
      src/api/interface/system/user.ts
  43. 175 0
      src/api/interface/tool/gen.ts
  44. 24 0
      src/api/modules/login.ts
  45. 70 0
      src/api/modules/monitor/logininfor.ts
  46. 70 0
      src/api/modules/monitor/operlog.ts
  47. 70 0
      src/api/modules/system/dept.ts
  48. 78 0
      src/api/modules/system/dict.ts
  49. 63 0
      src/api/modules/system/dictData.ts
  50. 92 0
      src/api/modules/system/menu.ts
  51. 70 0
      src/api/modules/system/post.ts
  52. 151 0
      src/api/modules/system/role.ts
  53. 129 0
      src/api/modules/system/user.ts
  54. 91 0
      src/api/modules/tool/gen.ts
  55. 16 0
      src/api/modules/upload.ts
  56. BIN=BIN
      src/assets/fonts/DIN.otf
  57. BIN=BIN
      src/assets/fonts/MetroDF.ttf
  58. BIN=BIN
      src/assets/fonts/YouSheBiaoTiHei.ttf
  59. 14 0
      src/assets/fonts/font.scss
  60. 48 0
      src/assets/iconfont/iconfont.scss
  61. BIN=BIN
      src/assets/iconfont/iconfont.ttf
  62. 1 0
      src/assets/icons/404.svg
  63. 1 0
      src/assets/icons/avatar-user.svg
  64. 1 0
      src/assets/icons/bug.svg
  65. 1 0
      src/assets/icons/build.svg
  66. 0 0
      src/assets/icons/button.svg
  67. 0 0
      src/assets/icons/cascader.svg
  68. 1 0
      src/assets/icons/chart.svg
  69. 1 0
      src/assets/icons/checkbox.svg
  70. 1 0
      src/assets/icons/clipboard.svg
  71. 1 0
      src/assets/icons/code.svg
  72. 0 0
      src/assets/icons/color.svg
  73. 0 0
      src/assets/icons/component.svg
  74. 0 0
      src/assets/icons/dashboard.svg
  75. 0 0
      src/assets/icons/date-range.svg
  76. 0 0
      src/assets/icons/date.svg
  77. 0 0
      src/assets/icons/dict.svg
  78. 1 0
      src/assets/icons/documentation.svg
  79. 1 0
      src/assets/icons/download.svg
  80. 1 0
      src/assets/icons/drag.svg
  81. 1 0
      src/assets/icons/druid.svg
  82. 1 0
      src/assets/icons/edit.svg
  83. 1 0
      src/assets/icons/education.svg
  84. 1 0
      src/assets/icons/email.svg
  85. 1 0
      src/assets/icons/example.svg
  86. 1 0
      src/assets/icons/excel.svg
  87. 1 0
      src/assets/icons/exit-fullscreen.svg
  88. 1 0
      src/assets/icons/eye-open.svg
  89. 1 0
      src/assets/icons/eye.svg
  90. 0 0
      src/assets/icons/form.svg
  91. 1 0
      src/assets/icons/fullscreen.svg
  92. 1 0
      src/assets/icons/github.svg
  93. 1 0
      src/assets/icons/guide.svg
  94. 1 0
      src/assets/icons/icon.svg
  95. 1 0
      src/assets/icons/input.svg
  96. 1 0
      src/assets/icons/international.svg
  97. 1 0
      src/assets/icons/job.svg
  98. 1 0
      src/assets/icons/language.svg
  99. 1 0
      src/assets/icons/link.svg
  100. 1 0
      src/assets/icons/list.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 = als-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:8849"]]
+# 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"]]

+ 36 - 0
.env.production

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

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

+ 26 - 0
.gitignore

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

+ 4 - 0
.husky/commit-msg

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

+ 4 - 0
.husky/pre-commit

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

+ 9 - 0
.prettierignore

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

+ 41 - 0
.prettierrc.cjs

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

+ 4 - 0
.stylelintignore

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

+ 40 - 0
.stylelintrc.cjs

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

+ 14 - 0
.vscode/extensions.json

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

+ 96 - 0
.vscode/settings.json

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

+ 0 - 0
CHANGELOG.md


+ 8 - 0
LICENSE

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

+ 9 - 0
README.md

@@ -0,0 +1,9 @@
+# als-web
+
+```
+yarn install
+
+yarn serve
+```
+
+前端脚手架

+ 46 - 0
build/getEnv.ts

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

+ 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']
+}

+ 126 - 0
package.json

@@ -0,0 +1,126 @@
+{
+  "name": "als-admin",
+  "private": true,
+  "version": "1.2.0",
+  "type": "module",
+  "description": "als-admin open source management system",
+  "author": {
+    "name": "gaokunw",
+    "email": "wanggaokun@wo.cn"
+  },
+  "license": "MIT",
+  "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-cropper": "^1.1.2",
+    "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: {}
+  }
+}

BIN=BIN
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()
+
+// 初始化主题
+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('请求失败!')
+  }
+}

+ 210 - 0
src/api/index.ts

@@ -0,0 +1,210 @@
+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 }
+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 })
+  }
+  downloadGet(url: string, params?: object, _object = {}): Promise<BlobPart> {
+    return this.service.get(url, { ..._object, responseType: 'blob' })
+  }
+  downloadPost(url: string, params?: object, _object = {}): Promise<BlobPart> {
+    return this.service.post(url, params, { ..._object, responseType: 'blob' })
+  }
+}
+
+export default new RequestHttp(config)

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

+ 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: any) => {
+  return http.delete<any>(`/monitor/logininfor/${infoId}`)
+}
+
+/**
+ * @name 下载模板
+ * @returns returns
+ */
+export const importTemplateApi = () => {
+  return http.downloadPost('/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.downloadPost('/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: any) => {
+  return http.delete<any>(`/monitor/operlog/${operId}`)
+}
+
+/**
+ * @name 下载模板
+ * @returns returns
+ */
+export const importTemplateApi = () => {
+  return http.downloadPost('/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.downloadPost('/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.downloadPost('/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.downloadPost('/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: any) => {
+  return http.delete<any>(`/system/dict/type/${id}`)
+}
+
+/**
+ * @name 下载模板
+ * @returns returns
+ */
+export const importTemplateApi = () => {
+  return http.downloadPost('/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.downloadPost('/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: any) => {
+  return http.delete<any>(`/system/dict/data/${id}`)
+}
+
+/**
+ * @name 导出数据
+ * @returns returns
+ */
+export const exportApi = (data: any) => {
+  return http.downloadPost('/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.downloadPost('/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.downloadPost('/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: any) => {
+  return http.delete<any>(`/system/post/${postId}`)
+}
+
+/**
+ * @name 下载模板
+ * @returns returns
+ */
+export const importTemplateApi = () => {
+  return http.downloadPost('/system/post/importTemplate', {})
+}
+
+/**
+ * @name 导入数据
+ * @returns returns
+ */
+export const importDataApi = (data: any) => {
+  return http.post('/system/post/importData', data)
+}
+
+/**
+ * @name 导出数据
+ * @returns returns
+ */
+export const exportApi = (data: any) => {
+  return http.downloadPost('/system/post/export', data)
+}

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

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

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

@@ -0,0 +1,129 @@
+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 用户密码重置
+ * @param data data
+ * @returns returns
+ */
+export const resetUserPwdApi = (data: any) => {
+  return http.put<any>('/system/user/resetPwd', data, { loading: false })
+}
+
+/**
+ * @name 下载模板
+ * @returns returns
+ */
+export const importTemplateApi = () => {
+  return http.downloadPost('/system/user/importTemplate', {})
+}
+
+/**
+ * @name 导入数据
+ * @returns returns
+ */
+export const importDataApi = (params: FormData) => {
+  return http.post('/system/user/importData', params)
+}
+
+/**
+ * @name 导出数据
+ * @returns returns
+ */
+export const exportApi = (data: any) => {
+  return http.downloadPost('/system/user/export', data)
+}
+
+/**
+ * @name 用户头像上传
+ * @param params params
+ * @returns returns
+ */
+export const uploadAvatarApi = (params: FormData) => {
+  return http.post<any>('/system/user/profile/avatar', params)
+}
+
+/**
+ * @name 查询用户个人信息
+ * @returns returns
+ */
+export const getUserProfileApi = () => {
+  return http.get<any>(`/system/user/profile`)
+}
+
+/**
+ * @name 修改用户个人信息
+ * @param data data
+ * @returns returns
+ */
+export const updateUserProfileApi = (data: any) => {
+  return http.put<any>('/system/user/profile', data, { loading: false })
+}
+/**
+ * @name 修改用户密码
+ * @param data data
+ * @returns returns
+ */
+export const updateUserPwdApi = (data: any) => {
+  return http.put<any>('system/user/profile/updatePwd', data, { loading: false })
+}

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

@@ -0,0 +1,91 @@
+import http from '@/api'
+
+/**
+ * @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 tableId tableName
+ * @returns returns
+ */
+export const synchDbApi = (tableId: any) => {
+  return http.get<any>(`/tool/gen/syncDb/${tableId}`)
+}
+
+/**
+ * @name 生成代码操作
+ * @param tableId tableId
+ * @returns returns
+ */
+export const batchGenCodeApi = (tableId: any) => {
+  return http.downloadGet(`/tool/gen/batchGenCode?tables=${tableId}`)
+}

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

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

BIN=BIN
src/assets/fonts/DIN.otf


BIN=BIN
src/assets/fonts/MetroDF.ttf


BIN=BIN
src/assets/fonts/YouSheBiaoTiHei.ttf


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

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

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

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

BIN=BIN
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/avatar-user.svg

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

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

A diferenza do arquivo foi suprimida porque é demasiado grande
+ 0 - 0
src/assets/icons/button.svg


A diferenza do arquivo foi suprimida porque é demasiado grande
+ 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>

A diferenza do arquivo foi suprimida porque é demasiado grande
+ 0 - 0
src/assets/icons/color.svg


A diferenza do arquivo foi suprimida porque é demasiado grande
+ 0 - 0
src/assets/icons/component.svg


A diferenza do arquivo foi suprimida porque é demasiado grande
+ 0 - 0
src/assets/icons/dashboard.svg


A diferenza do arquivo foi suprimida porque é demasiado grande
+ 0 - 0
src/assets/icons/date-range.svg


A diferenza do arquivo foi suprimida porque é demasiado grande
+ 0 - 0
src/assets/icons/date.svg


A diferenza do arquivo foi suprimida porque é demasiado grande
+ 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>

A diferenza do arquivo foi suprimida porque é demasiado grande
+ 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>

Algúns arquivos non se mostraron porque demasiados arquivos cambiaron neste cambio