chaooo 2 éve
szülő
commit
1f6b933864
100 módosított fájl, 2600 hozzáadás és 0 törlés
  1. 14 0
      .editorconfig
  2. 8 0
      .env.development
  3. 5 0
      .env.production
  4. 6 0
      .env.staging
  5. 14 0
      .eslintignore
  6. 269 0
      .eslintrc-auto-import.json
  7. 32 0
      .eslintrc.cjs
  8. 17 0
      .gitignore
  9. 4 0
      .husky/commit-msg
  10. 4 0
      .husky/pre-commit
  11. 10 0
      .prettierignore
  12. 36 0
      .prettierrc.cjs
  13. 10 0
      .stylelintignore
  14. 43 0
      .stylelintrc.cjs
  15. 93 0
      commitlint.config.cjs
  16. 18 0
      index.html
  17. 105 0
      package.json
  18. BIN
      public/favicon.ico
  19. 11 0
      src/App.vue
  20. 39 0
      src/api/auth/index.ts
  21. 60 0
      src/api/auth/types.ts
  22. 154 0
      src/api/user/index.ts
  23. 112 0
      src/api/user/types.ts
  24. BIN
      src/assets/401_images/401.gif
  25. BIN
      src/assets/404_images/404.png
  26. BIN
      src/assets/404_images/404_cloud.png
  27. 1 0
      src/assets/icons/advert.svg
  28. 0 0
      src/assets/icons/api.svg
  29. 0 0
      src/assets/icons/brand.svg
  30. 1 0
      src/assets/icons/bug.svg
  31. 0 0
      src/assets/icons/cascader.svg
  32. 1 0
      src/assets/icons/chart.svg
  33. 1 0
      src/assets/icons/client.svg
  34. 1 0
      src/assets/icons/close.svg
  35. 1 0
      src/assets/icons/close_all.svg
  36. 1 0
      src/assets/icons/close_left.svg
  37. 1 0
      src/assets/icons/close_other.svg
  38. 1 0
      src/assets/icons/close_right.svg
  39. 0 0
      src/assets/icons/coupon.svg
  40. 0 0
      src/assets/icons/dashboard.svg
  41. 18 0
      src/assets/icons/dict.svg
  42. 12 0
      src/assets/icons/dict_item.svg
  43. 1 0
      src/assets/icons/document.svg
  44. 1 0
      src/assets/icons/download.svg
  45. 1 0
      src/assets/icons/drag.svg
  46. 1 0
      src/assets/icons/edit.svg
  47. 1 0
      src/assets/icons/exit-fullscreen.svg
  48. 1 0
      src/assets/icons/eye-open.svg
  49. 1 0
      src/assets/icons/eye.svg
  50. 1 0
      src/assets/icons/fullscreen.svg
  51. 1 0
      src/assets/icons/github.svg
  52. 1 0
      src/assets/icons/goods-list.svg
  53. 1 0
      src/assets/icons/goods.svg
  54. 1 0
      src/assets/icons/guide.svg
  55. 0 0
      src/assets/icons/homepage.svg
  56. 0 0
      src/assets/icons/lab.svg
  57. 1 0
      src/assets/icons/language.svg
  58. 1 0
      src/assets/icons/link.svg
  59. 1 0
      src/assets/icons/menu.svg
  60. 1 0
      src/assets/icons/message.svg
  61. 1 0
      src/assets/icons/money.svg
  62. 2 0
      src/assets/icons/monitor.svg
  63. 1 0
      src/assets/icons/multi_level.svg
  64. 1 0
      src/assets/icons/nested.svg
  65. 0 0
      src/assets/icons/number.svg
  66. 1 0
      src/assets/icons/order.svg
  67. 1 0
      src/assets/icons/password.svg
  68. 0 0
      src/assets/icons/peoples.svg
  69. 1 0
      src/assets/icons/perm.svg
  70. 1 0
      src/assets/icons/publish.svg
  71. 1 0
      src/assets/icons/rabbitmq.svg
  72. 1 0
      src/assets/icons/rate.svg
  73. 0 0
      src/assets/icons/redis.svg
  74. 1 0
      src/assets/icons/refresh.svg
  75. 1 0
      src/assets/icons/role.svg
  76. 0 0
      src/assets/icons/security.svg
  77. 1 0
      src/assets/icons/shopping.svg
  78. 1 0
      src/assets/icons/size.svg
  79. 1 0
      src/assets/icons/skill.svg
  80. 1 0
      src/assets/icons/system.svg
  81. 1 0
      src/assets/icons/theme.svg
  82. 1 0
      src/assets/icons/tree.svg
  83. 1 0
      src/assets/icons/user.svg
  84. 1 0
      src/assets/icons/uv.svg
  85. 3 0
      src/assets/icons/valid_code.svg
  86. 3 0
      src/assets/icons/verify_code.svg
  87. BIN
      src/assets/index/indicator.png
  88. BIN
      src/assets/logo.png
  89. 102 0
      src/components/Breadcrumb/index.vue
  90. 46 0
      src/components/Hamburger/index.vue
  91. 165 0
      src/components/IconSelect/index.vue
  92. 88 0
      src/components/Pagination/index.vue
  93. 136 0
      src/components/RightPanel/index.vue
  94. 36 0
      src/components/SizeSelect/index.vue
  95. 45 0
      src/components/SvgIcon/index.vue
  96. 492 0
      src/components/TagInput/index.vue
  97. 34 0
      src/components/TagInput/util.ts
  98. 139 0
      src/components/Upload/MultiUpload.vue
  99. 81 0
      src/components/Upload/SingleUpload.vue
  100. 90 0
      src/components/WangEditor/index.vue

+ 14 - 0
.editorconfig

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

+ 8 - 0
.env.development

@@ -0,0 +1,8 @@
+## 开发环境
+
+# 变量必须以 VITE_ 为前缀才能暴露给外部读取
+NODE_ENV='development'
+
+VITE_APP_TITLE = 'vue3-element-admin'
+VITE_APP_PORT = 3000
+VITE_APP_BASE_API = '/dev-api'

+ 5 - 0
.env.production

@@ -0,0 +1,5 @@
+## 生产环境
+
+VITE_APP_TITLE = 'vue3-element-admin'
+VITE_APP_PORT = 3000
+VITE_APP_BASE_API = '/prod-api'

+ 6 - 0
.env.staging

@@ -0,0 +1,6 @@
+## 模拟环境
+NODE_ENV='staging'
+
+VITE_APP_TITLE = 'vue3-element-admin'
+VITE_APP_PORT = 3000
+VITE_APP_BASE_API = '/prod--api'

+ 14 - 0
.eslintignore

@@ -0,0 +1,14 @@
+dist
+node_modules
+public
+.husky
+.vscode
+.idea
+*.sh
+*.md
+
+src/assets
+
+.eslintrc.cjs
+.prettierrc.cjs
+.stylelintrc.cjs

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

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

+ 32 - 0
.eslintrc.cjs

@@ -0,0 +1,32 @@
+module.exports = {
+  env: {
+    browser: true,
+    es2021: true,
+    node: true,
+  },
+  parser: "vue-eslint-parser",
+  extends: [
+    // 参考vuejs官方的eslint配置: https://eslint.vuejs.org/user-guide/#usage
+    "plugin:vue/vue3-recommended",
+    "./.eslintrc-auto-import.json",
+    "prettier",
+  ],
+  parserOptions: {
+    ecmaVersion: "latest",
+    sourceType: "module",
+    parser: "@typescript-eslint/parser",
+  },
+  plugins: ["vue", "@typescript-eslint"],
+  rules: {
+    "vue/multi-word-component-names": "off", // 关闭组件名必须多字: https://eslint.vuejs.org/rules/multi-word-component-names.html
+    "@typescript-eslint/no-empty-function": "off", // 关闭空方法检查
+    "@typescript-eslint/no-explicit-any": "off", // 关闭any类型的警告
+    "vue/no-v-model-argument": "off",
+    "@typescript-eslint/no-non-null-assertion": "off",
+  },
+  // https://eslint.org/docs/latest/use/configure/language-options#specifying-globals
+  globals: {
+    DialogOption: "readonly",
+    OptionType: "readonly",
+  },
+};

+ 17 - 0
.gitignore

@@ -0,0 +1,17 @@
+node_modules
+.DS_Store
+dist
+dist-ssr
+*.local
+
+# Editor directories and files
+.idea
+.vscode
+*.suo
+*.ntvs*
+*.njsproj
+*.sln
+*.local
+
+package-lock.json
+pnpm-lock.yaml

+ 4 - 0
.husky/commit-msg

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

+ 4 - 0
.husky/pre-commit

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

+ 10 - 0
.prettierignore

@@ -0,0 +1,10 @@
+dist
+node_modules
+public
+.husky
+.vscode
+.idea
+*.sh
+*.md
+
+src/assets

+ 36 - 0
.prettierrc.cjs

@@ -0,0 +1,36 @@
+module.exports = {
+  // (x)=>{},单个参数箭头函数是否显示小括号。(always:始终显示;avoid:省略括号。默认:always)
+  arrowParens: "always",
+  // 开始标签的右尖括号是否跟随在最后一行属性末尾,默认false
+  bracketSameLine: false,
+  // 对象字面量的括号之间打印空格 (true - Example: { foo: bar } ; false - Example: {foo:bar})
+  bracketSpacing: true,
+  // 是否格式化一些文件中被嵌入的代码片段的风格(auto|off;默认auto)
+  embeddedLanguageFormatting: "auto",
+  // 指定 HTML 文件的空格敏感度 (css|strict|ignore;默认css)
+  htmlWhitespaceSensitivity: "css",
+  // 当文件已经被 Prettier 格式化之后,是否会在文件顶部插入一个特殊的 @format 标记,默认false
+  insertPragma: false,
+  // 在 JSX 中使用单引号替代双引号,默认false
+  jsxSingleQuote: false,
+  // 每行最多字符数量,超出换行(默认80)
+  printWidth: 80,
+  // 超出打印宽度 (always | never | preserve )
+  proseWrap: "preserve",
+  // 对象属性是否使用引号(as-needed | consistent | preserve;默认as-needed:对象的属性需要加引号才添加;)
+  quoteProps: "as-needed",
+  // 是否只格式化在文件顶部包含特定注释(@prettier| @format)的文件,默认false
+  requirePragma: false,
+  // 结尾添加分号
+  semi: true,
+  // 使用单引号 (true:单引号;false:双引号)
+  singleQuote: false,
+  // 缩进空格数,默认2个空格
+  tabWidth: 2,
+  // 元素末尾是否加逗号,默认es5: ES5中的 objects, arrays 等会添加逗号,TypeScript 中的 type 后不加逗号
+  trailingComma: "es5",
+  // 指定缩进方式,空格或tab,默认false,即使用空格
+  useTabs: false,
+  // vue 文件中是否缩进 <style> 和 <script> 标签,默认 false
+  vueIndentScriptAndStyle: false,
+};

+ 10 - 0
.stylelintignore

@@ -0,0 +1,10 @@
+dist
+node_modules
+public
+.husky
+.vscode
+.idea
+*.sh
+*.md
+
+src/assets

+ 43 - 0
.stylelintrc.cjs

@@ -0,0 +1,43 @@
+module.exports = {
+  // 继承推荐规范配置
+  extends: [
+    "stylelint-config-standard",
+    "stylelint-config-recommended-scss",
+    "stylelint-config-recommended-vue/scss",
+    "stylelint-config-html/vue",
+    "stylelint-config-recess-order",
+  ],
+  // 指定不同文件对应的解析器
+  overrides: [
+    {
+      files: ["**/*.{vue,html}"],
+      customSyntax: "postcss-html",
+    },
+    {
+      files: ["**/*.{css,scss}"],
+      customSyntax: "postcss-scss",
+    },
+  ],
+  // 自定义规则
+  rules: {
+    "import-notation": "string", // 指定导入CSS文件的方式("string"|"url")
+    "selector-class-pattern": null, // 选择器类名命名规则
+    "custom-property-pattern": null, // 自定义属性命名规则
+    "keyframes-name-pattern": null, // 动画帧节点样式命名规则
+    "no-descending-specificity": null, // 允许无降序特异性
+    // 允许 global 、export 、deep伪类
+    "selector-pseudo-class-no-unknown": [
+      true,
+      {
+        ignorePseudoClasses: ["global", "export", "deep"],
+      },
+    ],
+    // 允许未知属性
+    "property-no-unknown": [
+      true,
+      {
+        ignoreProperties: ["menuBg", "menuText", "menuActiveText"],
+      },
+    ],
+  },
+};

+ 93 - 0
commitlint.config.cjs

@@ -0,0 +1,93 @@
+module.exports = {
+  // 继承的规则
+  extends: ["@commitlint/config-conventional"],
+  // 自定义规则
+  rules: {
+    // @see https://commitlint.js.org/#/reference-rules
+
+    // 提交类型枚举,git提交type必须是以下类型
+    "type-enum": [
+      2,
+      "always",
+      [
+        "feat", // 新增功能
+        "fix", // 修复缺陷
+        "docs", // 文档变更
+        "style", // 代码格式(不影响功能,例如空格、分号等格式修正)
+        "refactor", // 代码重构(不包括 bug 修复、功能新增)
+        "perf", // 性能优化
+        "test", // 添加疏漏测试或已有测试改动
+        "build", // 构建流程、外部依赖变更(如升级 npm 包、修改 webpack 配置等)
+        "ci", // 修改 CI 配置、脚本
+        "revert", // 回滚 commit
+        "chore", // 对构建过程或辅助工具和库的更改(不影响源文件、测试用例)
+      ],
+    ],
+    "subject-case": [0], // subject大小写不做校验
+  },
+
+  prompt: {
+    messages: {
+      type: "选择你要提交的类型 :",
+      scope: "选择一个提交范围(可选):",
+      customScope: "请输入自定义的提交范围 :",
+      subject: "填写简短精炼的变更描述 :\n",
+      body: '填写更加详细的变更描述(可选)。使用 "|" 换行 :\n',
+      breaking: '列举非兼容性重大的变更(可选)。使用 "|" 换行 :\n',
+      footerPrefixesSelect: "选择关联issue前缀(可选):",
+      customFooterPrefix: "输入自定义issue前缀 :",
+      footer: "列举关联issue (可选) 例如: #31, #I3244 :\n",
+      generatingByAI: "正在通过 AI 生成你的提交简短描述...",
+      generatedSelectByAI: "选择一个 AI 生成的简短描述:",
+      confirmCommit: "是否提交或修改commit ?",
+    },
+    // prettier-ignore
+    types: [
+      { value: "feat",     name: "特性:     ✨  新增功能", emoji: ":sparkles:" },
+      { value: "fix",      name: "修复:     🐛  修复缺陷", emoji: ":bug:" },
+      { value: "docs",     name: "文档:     📝  文档变更", emoji: ":memo:" },
+      { value: "style",    name: "格式:     🌈  代码格式(不影响功能,例如空格、分号等格式修正)", emoji: ":lipstick:" },
+      { value: "refactor", name: "重构:     🔄  代码重构(不包括 bug 修复、功能新增)", emoji: ":recycle:" },
+      { value: "perf",     name: "性能:     🚀  性能优化", emoji: ":zap:" },
+      { value: "test",     name: "测试:     🧪  添加疏漏测试或已有测试改动", emoji: ":white_check_mark:"},
+      { value: "build",    name: "构建:     📦️  构建流程、外部依赖变更(如升级 npm 包、修改 vite 配置等)", emoji: ":package:"},
+      { value: "ci",       name: "集成:     ⚙️  修改 CI 配置、脚本",  emoji: ":ferris_wheel:"},
+      { value: "revert",   name: "回退:     ↩️  回滚 commit",emoji: ":rewind:"},
+      { value: "chore",    name: "其他:     🛠️  对构建过程或辅助工具和库的更改(不影响源文件、测试用例)", emoji: ":hammer:"},
+    ],
+    useEmoji: true,
+    emojiAlign: "center",
+    useAI: false,
+    aiNumber: 1,
+    themeColorCode: "",
+    scopes: [],
+    allowCustomScopes: true,
+    allowEmptyScopes: true,
+    customScopesAlign: "bottom",
+    customScopesAlias: "custom",
+    emptyScopesAlias: "empty",
+    upperCaseSubject: false,
+    markBreakingChangeMode: false,
+    allowBreakingChanges: ["feat", "fix"],
+    breaklineNumber: 100,
+    breaklineChar: "|",
+    skipQuestions: [],
+    issuePrefixes: [
+      { value: "closed", name: "closed:   ISSUES has been processed" },
+    ],
+    customIssuePrefixAlign: "top",
+    emptyIssuePrefixAlias: "skip",
+    customIssuePrefixAlias: "custom",
+    allowCustomIssuePrefix: true,
+    allowEmptyIssuePrefix: true,
+    confirmColorize: true,
+    maxHeaderLength: Infinity,
+    maxSubjectLength: Infinity,
+    minSubjectLength: 0,
+    scopeOverrides: undefined,
+    defaultBody: "",
+    defaultIssues: "",
+    defaultScope: "",
+    defaultSubject: "",
+  },
+};

+ 18 - 0
index.html

@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<html lang="en">
+
+<head>
+  <meta charset="UTF-8" />
+  <link rel="icon" href="/favicon.ico" />
+  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
+  <meta name="description" content="vue-element-admin的vue3版本" />
+  <meta name="keywords" content="vue-element-admin,vue3-element-admin" />
+  <title>vue3-element-admin</title>
+</head>
+
+<body>
+  <div id="app"></div>
+  <script type="module" src="/src/main.ts"></script>
+</body>
+
+</html>

+ 105 - 0
package.json

@@ -0,0 +1,105 @@
+{
+  "name": "vue3-element-admin",
+  "private": true,
+  "version": "2.3.1",
+  "type": "module",
+  "scripts": {
+    "dev": "vite serve --mode development",
+    "build:prod": "vite build --mode production &&vue-tsc --noEmit",
+    "prepare": "husky install",
+    "lint:eslint": "eslint  --fix --ext .ts,.js,.vue ./src ",
+    "lint:prettier": "prettier --write \"**/*.{js,cjs,ts,json,tsx,css,less,scss,vue,html,md}\"",
+    "lint:stylelint": "stylelint  \"**/*.{css,scss,vue}\" --fix",
+    "lint:lint-staged": "lint-staged",
+    "commit": "git-cz"
+  },
+  "config": {
+    "commitizen": {
+      "path": "node_modules/cz-git"
+    }
+  },
+  "lint-staged": {
+    "*.{js,ts}": [
+      "eslint --fix",
+      "prettier --write"
+    ],
+    "*.{cjs,json}": [
+      "prettier --write"
+    ],
+    "*.{vue,html}": [
+      "eslint --fix",
+      "prettier --write",
+      "stylelint --fix"
+    ],
+    "*.{scss,css}": [
+      "stylelint --fix",
+      "prettier --write"
+    ],
+    "*.md": [
+      "prettier --write"
+    ]
+  },
+  "dependencies": {
+    "@types/lodash": "^4.14.195",
+    "@vitejs/plugin-vue": "^4.2.3",
+    "@vueuse/core": "^10.1.2",
+    "@wangeditor/editor": "^5.1.23",
+    "@wangeditor/editor-for-vue": "5.1.10",
+    "axios": "^1.4.0",
+    "codemirror": "^5.65.13",
+    "echarts": "^5.2.2",
+    "element-plus": "^2.3.6",
+    "lodash-es": "^4.17.21",
+    "nprogress": "^0.2.0",
+    "path-browserify": "^1.0.1",
+    "path-to-regexp": "^6.2.0",
+    "pinia": "^2.0.33",
+    "screenfull": "^6.0.0",
+    "vue": "^3.3.1",
+    "vue-i18n": "9.2.2",
+    "vue-router": "^4.2.0"
+  },
+  "devDependencies": {
+    "@commitlint/cli": "^17.6.3",
+    "@commitlint/config-conventional": "^17.6.3",
+    "@iconify-json/ep": "^1.1.10",
+    "@types/codemirror": "^5.60.7",
+    "@types/nprogress": "^0.2.0",
+    "@types/path-browserify": "^1.0.0",
+    "@typescript-eslint/eslint-plugin": "^5.59.6",
+    "@typescript-eslint/parser": "^5.59.6",
+    "autoprefixer": "^10.4.14",
+    "commitizen": "^4.3.0",
+    "cz-git": "^1.6.1",
+    "eslint": "^8.40.0",
+    "eslint-config-prettier": "^8.8.0",
+    "eslint-plugin-prettier": "^4.2.1",
+    "eslint-plugin-vue": "^9.13.0",
+    "fast-glob": "^3.2.11",
+    "husky": "^8.0.3",
+    "lint-staged": "^13.2.2",
+    "postcss": "^8.4.23",
+    "postcss-html": "^1.5.0",
+    "postcss-scss": "^4.0.6",
+    "prettier": "^2.8.8",
+    "sass": "^1.58.3",
+    "stylelint": "^15.5.0",
+    "stylelint-config-html": "^1.1.0",
+    "stylelint-config-recess-order": "^4.0.0",
+    "stylelint-config-recommended-scss": "11.0.0 ",
+    "stylelint-config-recommended-vue": "^1.4.0",
+    "stylelint-config-standard": "^33.0.0",
+    "stylelint-config-standard-scss": "^9.0.0",
+    "typescript": "^5.0.4",
+    "unocss": "^0.51.13",
+    "unplugin-auto-import": "^0.15.3",
+    "unplugin-icons": "^0.16.1",
+    "unplugin-vue-components": "^0.24.1",
+    "vite": "^4.3.5",
+    "vite-plugin-svg-icons": "^2.0.1",
+    "vue-tsc": "^1.6.5 "
+  },
+  "repository": "https://gitee.com/youlaiorg/vue3-element-admin.git",
+  "author": "有来开源组织",
+  "license": "MIT"
+}

BIN
public/favicon.ico


+ 11 - 0
src/App.vue

@@ -0,0 +1,11 @@
+<script setup lang="ts">
+import { ElConfigProvider } from 'element-plus';
+import { useAppStore } from '@/store/modules/app';
+const appStore = useAppStore();
+</script>
+
+<template>
+  <el-config-provider :locale="appStore.locale" :size="appStore.size">
+    <router-view />
+  </el-config-provider>
+</template>

+ 39 - 0
src/api/auth/index.ts

@@ -0,0 +1,39 @@
+import request from '@/utils/request';
+import { AxiosPromise } from 'axios';
+import { CaptchaResult, LoginData, LoginResult } from './types';
+
+/**
+ * 登录API
+ *
+ * @param data {LoginData}
+ * @returns
+ */
+export function loginApi(data: LoginData): AxiosPromise<LoginResult> {
+  return request({
+    url: '/api/v1/auth/login',
+    method: 'post',
+    params: data
+  });
+}
+
+/**
+ * 注销API
+ */
+export function logoutApi() {
+  return request({
+    url: '/api/v1/auth/logout',
+    method: 'delete'
+  });
+}
+
+
+
+/**
+ * 获取验证码
+ */
+export function getCaptchaApi(): AxiosPromise<CaptchaResult> {
+  return request({
+    url: '/api/v1/auth/captcha',
+    method: 'get'
+  });
+}

+ 60 - 0
src/api/auth/types.ts

@@ -0,0 +1,60 @@
+/**
+ * 登录请求参数
+ */
+export interface LoginData {
+  /**
+   * 用户名
+   */
+  username?: string;
+  /**
+   * 密码
+   */
+  password?: string;
+
+  /**
+   * 验证码缓存key
+   */
+  verifyCodeKey?: string;
+
+  /**
+   * 验证码
+   */
+  verifyCode?: string;
+}
+
+/**
+ * 登录响应
+ */
+export interface LoginResult {
+  /**
+   * 访问token
+   */
+  accessToken?: string;
+  /**
+   * 过期时间(单位:毫秒)
+   */
+  expires?: number;
+  /**
+   * 刷新token
+   */
+  refreshToken?: string;
+  /**
+   * token 类型
+   */
+  tokenType?: string;
+}
+
+/**
+ * 验证码响应
+ */
+export interface CaptchaResult {
+  /**
+   * 验证码缓存key
+   */
+  verifyCodeKey: string;
+  /**
+   * 验证码图片Base64字符串
+   */
+  verifyCodeBase64: string;
+}
+

+ 154 - 0
src/api/user/index.ts

@@ -0,0 +1,154 @@
+import request from '@/utils/request';
+import { AxiosPromise } from 'axios';
+import { UserForm, UserInfo, UserPageVO, UserQuery } from './types';
+
+/**
+ * 登录成功后获取用户信息(昵称、头像、权限集合和角色集合)
+ */
+export function getUserInfo(): AxiosPromise<UserInfo> {
+  return request({
+    url: '/api/v1/users/me',
+    method: 'get'
+  });
+}
+
+/**
+ * 获取用户分页列表
+ *
+ * @param queryParams
+ */
+export function getUserPage(
+  queryParams: UserQuery
+): AxiosPromise<PageResult<UserPageVO[]>> {
+  return request({
+    url: '/api/v1/users/page',
+    method: 'get',
+    params: queryParams
+  });
+}
+
+/**
+ * 获取用户表单详情
+ *
+ * @param userId
+ */
+export function getUserForm(userId: number): AxiosPromise<UserForm> {
+  return request({
+    url: '/api/v1/users/' + userId + '/form',
+    method: 'get'
+  });
+}
+
+/**
+ * 添加用户
+ *
+ * @param data
+ */
+export function addUser(data: any) {
+  return request({
+    url: '/api/v1/users',
+    method: 'post',
+    data: data
+  });
+}
+
+/**
+ * 修改用户
+ *
+ * @param id
+ * @param data
+ */
+export function updateUser(id: number, data: UserForm) {
+  return request({
+    url: '/api/v1/users/' + id,
+    method: 'put',
+    data: data
+  });
+}
+
+/**
+ * 修改用户状态
+ *
+ * @param id
+ * @param status
+ */
+export function updateUserStatus(id: number, status: number) {
+  return request({
+    url: '/api/v1/users/' + id + '/status',
+    method: 'patch',
+    params: { status: status }
+  });
+}
+
+/**
+ * 修改用户密码
+ *
+ * @param id
+ * @param password
+ */
+export function updateUserPassword(id: number, password: string) {
+  return request({
+    url: '/api/v1/users/' + id + '/password',
+    method: 'patch',
+    params: { password: password }
+  });
+}
+
+/**
+ * 删除用户
+ *
+ * @param ids
+ */
+export function deleteUsers(ids: string) {
+  return request({
+    url: '/api/v1/users/' + ids,
+    method: 'delete'
+  });
+}
+
+/**
+ * 下载用户导入模板
+ *
+ * @returns
+ */
+export function downloadTemplateApi() {
+  return request({
+    url: '/api/v1/users/template',
+    method: 'get',
+    responseType: 'arraybuffer'
+  });
+}
+
+/**
+ * 导出用户
+ *
+ * @param queryParams
+ * @returns
+ */
+export function exportUser(queryParams: UserQuery) {
+  return request({
+    url: '/api/v1/users/_export',
+    method: 'get',
+    params: queryParams,
+    responseType: 'arraybuffer'
+  });
+}
+
+/**
+ * 导入用户
+ *
+ * @param file
+ */
+export function importUser(deptId: number, file: File) {
+  const formData = new FormData();
+  formData.append('file', file);
+  return request({
+    url: '/api/v1/users/_import',
+    method: 'post',
+    params: { deptId: deptId },
+    data: formData,
+    headers: {
+      'Content-Type': 'multipart/form-data'
+    }
+  });
+}

+ 112 - 0
src/api/user/types.ts

@@ -0,0 +1,112 @@
+/**
+ * 登录用户信息
+ */
+export interface UserInfo {
+  userId: number;
+  nickname: string;
+  avatar: string;
+  roles: string[];
+  perms: string[];
+}
+
+/**
+ * 用户查询对象类型
+ */
+export interface UserQuery extends PageQuery {
+  keywords?: string;
+  status?: number;
+  deptId?: number;
+}
+
+/**
+ * 用户分页对象
+ */
+export interface UserPageVO {
+  /**
+   * 用户头像地址
+   */
+  avatar?: string;
+  /**
+   * 创建时间
+   */
+  createTime?: Date;
+  /**
+   * 部门名称
+   */
+  deptName?: string;
+  /**
+   * 用户邮箱
+   */
+  email?: string;
+  /**
+   * 性别
+   */
+  genderLabel?: string;
+  /**
+   * 用户ID
+   */
+  id?: number;
+  /**
+   * 手机号
+   */
+  mobile?: string;
+  /**
+   * 用户昵称
+   */
+  nickname?: string;
+  /**
+   * 角色名称,多个使用英文逗号(,)分割
+   */
+  roleNames?: string;
+  /**
+   * 用户状态(1:启用;0:禁用)
+   */
+  status?: number;
+  /**
+   * 用户名
+   */
+  username?: string;
+}
+
+/**
+ * 用户表单类型
+ */
+export interface UserForm {
+  /**
+   * 用户头像
+   */
+  avatar?: string;
+  /**
+   * 部门ID
+   */
+  deptId?: number;
+  /**
+   * 邮箱
+   */
+  email?: string;
+  /**
+   * 性别
+   */
+  gender?: number;
+  /**
+   * 用户ID
+   */
+  id?: number;
+  mobile?: string;
+  /**
+   * 昵称
+   */
+  nickname?: string;
+  /**
+   * 角色ID集合
+   */
+  roleIds?: number[];
+  /**
+   * 用户状态(1:正常;0:禁用)
+   */
+  status?: number;
+  /**
+   * 用户名
+   */
+  username?: string;
+}

BIN
src/assets/401_images/401.gif


BIN
src/assets/404_images/404.png


BIN
src/assets/404_images/404_cloud.png


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

@@ -0,0 +1 @@
+<svg t="1650329991210" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="13818" width="200" height="200"><path d="M992 160v576H32V160h960m0-32H32c-17.6 0-32 14.4-32 32v576c0 17.6 14.4 32 32 32h960c17.6 0 32-14.4 32-32V160c0-17.6-14.4-32-32-32z" fill="" p-id="13819"></path><path d="M112 880h800c9.6 0 16 6.4 16 16s-6.4 16-16 16H112c-9.6 0-16-6.4-16-16s6.4-16 16-16z" fill="" p-id="13820"></path><path d="M334.4 275.2l171.2 382.4h-40l-57.6-124.8h-158.4L192 657.6H152l172.8-382.4h9.6z m-4.8 81.6l-62.4 137.6h124.8l-62.4-137.6zM563.2 657.6v-368H640c52.8 0 91.2 3.2 115.2 11.2 24 8 44.8 19.2 64 36.8 17.6 16 32 36.8 41.6 60.8 9.6 24 14.4 51.2 14.4 83.2s-8 62.4-22.4 89.6-35.2 49.6-60.8 64c-25.6 14.4-62.4 20.8-110.4 20.8h-118.4z m35.2-35.2H640c44.8 0 76.8-1.6 96-6.4s36.8-12.8 52.8-25.6c14.4-12.8 27.2-28.8 33.6-48 8-19.2 11.2-40 11.2-64s-4.8-46.4-12.8-67.2c-9.6-20.8-22.4-36.8-38.4-51.2s-36.8-22.4-59.2-27.2c-22.4-4.8-56-6.4-100.8-6.4h-25.6l1.6 296z" fill="" p-id="13821"></path></svg>

A különbségek nem kerülnek megjelenítésre, a fájl túl nagy
+ 0 - 0
src/assets/icons/api.svg


A különbségek nem kerülnek megjelenítésre, a fájl túl nagy
+ 0 - 0
src/assets/icons/brand.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>

A különbségek nem kerülnek megjelenítésre, a fájl túl nagy
+ 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/client.svg

@@ -0,0 +1 @@
+<svg t="1650328614187" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="5090" width="200" height="200"><path d="M962.184 55.874H61.818C27.732 55.874 0 83.606 0 117.692v621.64c0 34.086 27.732 61.818 61.818 61.818h308.52v44.98c0 41.234-33.547 74.782-74.781 74.782h-67.995c-13.036 0-23.606 10.568-23.606 23.606 0 13.038 10.57 23.606 23.606 23.606h568.874c13.036 0 23.606-10.568 23.606-23.606 0-13.038-10.57-23.606-23.606-23.606h-67.997c-41.234 0-74.782-33.548-74.782-74.782v-44.978h308.52c34.087 0 61.821-27.732 61.821-61.819v-621.64c0.004-34.087-27.728-61.819-61.814-61.819zM391.84 920.916c16.092-20.672 25.714-46.616 25.714-74.782v-44.98h188.894v44.98c0 28.166 9.622 54.112 25.714 74.782H391.841zM976.79 739.333c0 8.054-6.552 14.608-14.608 14.608H61.818c-8.054 0-14.608-6.552-14.608-14.608V615.267h929.58v124.066z m0-171.28H47.212v-450.36c0-8.055 6.552-14.609 14.608-14.609h900.362c8.054 0 14.61 6.552 14.61 14.608v450.361z" fill="" p-id="5091"></path><path d="M486.531 684.611a25.476 25.476 0 1 0 50.952 0 25.476 25.476 0 1 0-50.952 0zM552.477 218.508c-9.22-9.218-24.162-9.218-33.386 0L352.263 385.337c-9.218 9.218-9.218 24.166 0 33.386a23.534 23.534 0 0 0 16.694 6.914 23.526 23.526 0 0 0 16.692-6.914l166.828-166.829c9.218-9.218 9.218-24.166 0-33.386z m98.88 96.679c-9.216-9.218-24.158-9.218-33.384-0.002l-66.46 66.456c-9.218 9.22-9.218 24.168 0 33.386a23.53 23.53 0 0 0 16.692 6.914c6.04 0 12.082-2.304 16.692-6.914l66.46-66.456c9.218-9.218 9.218-24.166 0-33.384z" fill="" p-id="5092"></path></svg>

+ 1 - 0
src/assets/icons/close.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" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 36 36"><path d="M19.41 18l8.29-8.29a1 1 0 0 0-1.41-1.41L18 16.59l-8.29-8.3a1 1 0 0 0-1.42 1.42l8.3 8.29l-8.3 8.29A1 1 0 1 0 9.7 27.7l8.3-8.29l8.29 8.29a1 1 0 0 0 1.41-1.41z" fill="currentColor"></path></svg>

+ 1 - 0
src/assets/icons/close_all.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" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 36 36"><path d="M26 17H10a1 1 0 0 0 0 2h16a1 1 0 0 0 0-2z" fill="currentColor"></path></svg>

+ 1 - 0
src/assets/icons/close_left.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" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 24 24"><g fill="none"><path d="M7 12l7 7" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"></path><path d="M7 12l7-7" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"></path><path d="M21 12H7.5" stroke="currentColor" stroke-width="2" stroke-linecap="round" ></path><path d="M3 3v18" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"></path></g></svg>

+ 1 - 0
src/assets/icons/close_other.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" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 20 20"><path d="M3 5h14V3H3v2zm12 8V7H5v6h10zM3 17h14v-2H3v2z" fill="currentColor"></path></svg>

+ 1 - 0
src/assets/icons/close_right.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" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 24 24"><g transform="translate(24 0) scale(-1 1)"><g fill="none"><path d="M7 12l7 7" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"></path><path d="M7 12l7-7" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"></path><path d="M21 12H7.5" stroke="currentColor" stroke-width="2" stroke-linecap="round"></path><path d="M3 3v18" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"></path></g></g></svg>

A különbségek nem kerülnek megjelenítésre, a fájl túl nagy
+ 0 - 0
src/assets/icons/coupon.svg


A különbségek nem kerülnek megjelenítésre, a fájl túl nagy
+ 0 - 0
src/assets/icons/dashboard.svg


+ 18 - 0
src/assets/icons/dict.svg

@@ -0,0 +1,18 @@
+<svg t="1655030231175" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="3473"
+  width="200" height="200">
+  <path
+    d="M449.6 116.2H303.8c-14.2 0-25.7-11.5-25.7-25.7s11.5-25.7 25.7-25.7h145.8c14.2 0 25.7 11.5 25.7 25.7s-11.5 25.7-25.7 25.7z m0 0"
+    p-id="3474"></path>
+  <path
+    d="M160.1 859.3c-14.2 0-25.7-11.5-25.7-25.7V167.4c0-56.6 46-102.6 102.6-102.6h66.8c14.2 0 25.7 11.5 25.7 25.7s-11.5 25.7-25.7 25.7H237c-28.2 0-51.1 22.9-51.1 51.1v666.2c-0.1 14.3-11.6 25.8-25.8 25.8z m0 0M533.6 346.7c-6.3 0-12.4-1.3-17.6-3.5-13.5-5.8-21.9-17.9-21.9-31.6v-221c0-14.2 11.5-25.7 25.7-25.7s25.7 11.5 25.7 25.7v189l27.7-26.6c14.1-13.5 36.1-13.5 50.1 0l22.1 21.3V90.5c0-14.2 11.5-25.7 25.7-25.7s25.7 11.5 25.7 25.7v219.6c0 14.5-8.6 27.5-22 33.2-13.3 5.7-28.7 2.9-39.2-7.2l-37.5-36-37.5 36c-7.6 7.6-17.5 10.6-27 10.6z m0 0"
+    p-id="3475"></path>
+  <path
+    d="M846.1 958.9H236.9c-56.6 0-102.6-46-102.6-102.6v-22.8c0-14.2 11.5-25.7 25.7-25.7s25.7 11.5 25.7 25.7v22.8c0 28.2 22.9 51.1 51.1 51.1H846c14.2 0 25.7 11.5 25.7 25.7 0.1 14.3-11.4 25.8-25.6 25.8z m0 0"
+    p-id="3476"></path>
+  <path
+    d="M160.1 876h-0.9c-14.2-0.5-25.3-12.4-24.8-26.6 1-28.2 6.3-48.5 16.7-63.6 13.8-20.1 35.4-30.3 64.3-30.3h615c3.2-2.7 6.4-6.1 8.6-8.6V133.1c-1.8-5.1-11.7-15-16.8-16.8H449.6c-14.2 0-25.7-11.5-25.7-25.7s11.5-25.7 25.7-25.7h373.6c19.8 0 36.7 13.9 45 22.2 8.3 8.3 22.2 25.2 22.2 45v621.6c0 10.8-6.2 19.6-12.3 26.7-4.6 5.4-10.3 11-15.6 15.4-1 0.9-2.1 1.7-3.2 2.5-5.4 4.1-12.9 8.8-22.3 8.8H215.3c-15 0-28 0-29.5 44.2-0.5 13.8-11.9 24.7-25.7 24.7z m0 0"
+    p-id="3477"></path>
+  <path
+    d="M284.4 806.4c-14.2 0-25.7-11.5-25.7-25.7V90.5c0-14.2 11.5-25.7 25.7-25.7s25.7 11.5 25.7 25.7v690.1c0 14.3-11.5 25.8-25.7 25.8z m0 0M844.9 959h-1.6c-6.6-0.3-30-2.3-52.2-16.9-19.5-12.7-42.6-38-42.6-86.3 0-62.3 35.7-101 93.1-101 14.2 0 25.7 11.5 25.7 25.7s-11.5 25.7-25.7 25.7c-12.5 0-41.7 0-41.7 49.6 0 21 6.6 35.3 20.1 43.8 10.6 6.6 22.1 7.8 25 8 1.4-0.1 2.9 0 4.4 0.2 13.7 1.7 23.6 14 22.5 27.7-0.9 9.5-8.8 23.5-27 23.5z m-1.8-51.3c-1.1 0.1-2.3 0.3-3.4 0.6 1.1-0.3 2.2-0.5 3.4-0.6z m0 0"
+    p-id="3478"></path>
+</svg>

+ 12 - 0
src/assets/icons/dict_item.svg

@@ -0,0 +1,12 @@
+<svg t="1655022848495" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2190"
+  width="200" height="200">
+  <path d="M239.9 492.6m-42 0a42 42 0 1 0 84 0 42 42 0 1 0-84 0Z" p-id="2191"></path>
+  <path d="M826 513.5H378.5c-11.6 0-21-9.4-21-21s9.4-21 21-21H826c11.6 0 21 9.4 21 21s-9.4 21-21 21z" p-id="2192">
+  </path>
+  <path d="M239.9 632.4m-42 0a42 42 0 1 0 84 0 42 42 0 1 0-84 0Z" p-id="2193"></path>
+  <path d="M826 653.4H378.5c-11.6 0-21-9.4-21-21s9.4-21 21-21H826c11.6 0 21 9.4 21 21s-9.4 21-21 21z" p-id="2194">
+  </path>
+  <path
+    d="M882.6 234.9H531.2l-29-46.3c-6.9-11.7-35-54.7-77.8-54.7h-304c-30.9 0-55.9 25-55.9 55.9v623.3c0 42.4 34.5 76.9 76.9 76.9h741.2c42.4 0 76.9-34.5 76.9-76.9V311.8c0-42.4-34.5-76.9-76.9-76.9z m34.9 578.2c0 19.3-15.7 35-35 35H141.4c-19.3 0-35-15.7-35-35V311.8c0-19.3 15.7-35 35-35h741.2c19.3 0 35 15.7 35 35v501.3z"
+    p-id="2195"></path>
+</svg>

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

@@ -0,0 +1 @@
+<svg t="1675604765384" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="21161" width="200" height="200"><path d="M832.1 185.1H609.4l-17.1-62c-9.6-34.6-40.5-58.8-75.3-58.8H196c-43.2 0-78.3 36.4-78.3 81.1V897c0 35.3 28.7 64 64 64H832c35.3 0 64-28.7 64-64V249c0.1-35.2-28.6-63.9-63.9-63.9z m-644.4-39.7c0-6.6 4.4-11.1 8.3-11.1h321c3.4 0 6.6 3.1 7.8 7.4l12 43.4H187.7v-39.7z m638.4 745.8H187.7V255.1h638.4v636.1z" p-id="21162"></path><path d="M346.1 415.1m-35 0a35 35 0 1 0 70 0 35 35 0 1 0-70 0Z" p-id="21163"></path><path d="M462.3 380.1h257.8v70H462.3z" p-id="21164"></path><path d="M346.1 582.3m-35 0a35 35 0 1 0 70 0 35 35 0 1 0-70 0Z" p-id="21165"></path><path d="M462.3 547.3h257.8v70H462.3z" p-id="21166"></path><path d="M346.1 749.5m-35 0a35 35 0 1 0 70 0 35 35 0 1 0-70 0Z" p-id="21167"></path><path d="M462.3 714.5h257.8v70H462.3z" p-id="21168"></path></svg>

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

@@ -0,0 +1 @@
+<svg t="1675606213335" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="17495" width="200" height="200"><path d="M624 706.3h-74.1V464c0-4.4-3.6-8-8-8h-60c-4.4 0-8 3.6-8 8v242.3H400c-6.7 0-10.4 7.7-6.3 12.9l112 141.7c3.2 4.1 9.4 4.1 12.6 0l112-141.7c4.1-5.2 0.4-12.9-6.3-12.9z" p-id="17496"></path><path d="M811.4 366.7C765.6 245.9 648.9 160 512.2 160S258.8 245.8 213 366.6C127.3 389.1 64 467.2 64 560c0 110.5 89.5 200 199.9 200H304c4.4 0 8-3.6 8-8v-60c0-4.4-3.6-8-8-8h-40.1c-33.7 0-65.4-13.4-89-37.7-23.5-24.2-36-56.8-34.9-90.6 0.9-26.4 9.9-51.2 26.2-72.1 16.7-21.3 40.1-36.8 66.1-43.7l37.9-9.9 13.9-36.6c8.6-22.8 20.6-44.1 35.7-63.4 14.9-19.2 32.6-35.9 52.4-49.9 41.1-28.9 89.5-44.2 140-44.2s98.9 15.3 140 44.2c19.9 14 37.5 30.8 52.4 49.9 15.1 19.3 27.1 40.7 35.7 63.4l13.8 36.5 37.8 10C846.1 454.5 884 503.8 884 560c0 33.1-12.9 64.3-36.3 87.7-23.4 23.4-54.5 36.3-87.6 36.3H720c-4.4 0-8 3.6-8 8v60c0 4.4 3.6 8 8 8h40.1C870.5 760 960 670.5 960 560c0-92.7-63.1-170.7-148.6-193.3z" p-id="17497"></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/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/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>

+ 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/goods-list.svg

@@ -0,0 +1 @@
+<svg t="1650624175386" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="12087" width="200" height="200"><path d="M879.2064 234.7008l-89.8048 0L789.4016 197.632c0-6.2464-0.6144-12.3904-1.6384-18.3296-2.1504-11.776-6.3488-22.8352-12.1856-32.5632-11.6736-19.3536-29.696-33.4848-50.7904-38.4-5.2224-1.2288-10.6496-1.8432-16.2816-1.8432L144.7936 106.496c-5.5296 0-10.9568 0.6144-16.2816 1.8432-20.992 4.9152-39.1168 18.944-50.7904 38.4-5.8368 9.728-10.0352 20.6848-12.1856 32.5632-1.1264 5.9392-1.6384 11.9808-1.6384 18.3296l0 457.9328c0 6.2464 0.6144 12.3904 1.6384 18.3296 2.1504 11.776 6.3488 22.8352 12.1856 32.4608 11.6736 19.3536 29.696 33.4848 50.7904 38.4 5.2224 1.2288 10.6496 1.8432 16.2816 1.8432l47.2064 0L192 826.368c0 50.0736 36.352 91.0336 80.7936 91.0336l606.3104 0c44.4416 0 80.7936-40.96 80.7936-91.0336L959.8976 426.7008l0 0c0 0 0 0 0 0l0-100.9664C960 275.6608 923.648 234.7008 879.2064 234.7008zM192 325.7344l0 378.2656-47.2064 0c-20.6848 0-38.1952-22.1184-38.1952-48.3328L106.5984 197.632c0-26.2144 17.5104-48.3328 38.1952-48.3328l563.6096 0c20.6848 0 38.1952 22.1184 38.1952 48.3328l0 36.9664-85.2992 0L490.7008 234.5984 272.896 234.5984C228.352 234.7008 192 275.6608 192 325.7344zM661.2992 277.2992l0 378.9824-66.2528-33.0752-19.0464-9.5232-19.0464 9.5232-66.2528 33.0752L490.7008 426.7008l0 0c0 0 0 0 0 0L490.7008 277.2992 661.2992 277.2992zM448 277.2992l0 128L234.7008 405.2992l0-79.6672c0-26.2144 17.5104-48.3328 38.1952-48.3328L448 277.2992zM917.2992 826.368c0 26.2144-17.5104 48.3328-38.1952 48.3328L272.896 874.7008c-20.6848 0-38.1952-22.1184-38.1952-48.3328L234.7008 448l213.2992 0 0 213.2992c0 23.4496 19.2512 42.7008 42.7008 42.7008l85.2992-42.7008 85.2992 42.7008c23.4496 0 42.7008-19.1488 42.7008-42.7008L704 448l213.2992 0L917.2992 826.368zM917.2992 405.2992 704 405.2992l0-128 175.2064 0c20.6848 0 38.1952 22.1184 38.1952 48.3328L917.4016 405.2992z" p-id="12088"></path></svg>

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

@@ -0,0 +1 @@
+<svg t="1650329871849" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="10813" width="200" height="200"><path d="M909.7 219.4l-6.1-3.2V87.5c0-4.6-1.8-8.7-4.2-12.2-0.3-0.4-0.5-0.8-0.8-1.2-1.1-1.3-2.2-2.5-3.6-3.5-0.7-0.6-1.5-1.1-2.3-1.5-1.2-0.7-2.4-1.4-3.8-1.9-1.8-0.7-3.8-1-5.8-1.2-0.5 0-0.9-0.3-1.4-0.3H139.9c-9.7 0-18.2 6.3-20.9 15.6-1.4 4.6-1.2 9.4 0.4 13.7-0.7 2.1-1.3 4.2-1.3 6.5v114.7l-6.4 3.2c-9 1.2-15.7 5.3-15.7 15.1v690.2l2 1.9c2.4 18.1 16.9 32 35.3 33.1l0.5 0.4h752.4c20.4 0 36.6-15.9 38-35.9l1-0.9V234.6c0.1-9.9-6.5-13.9-15.5-15.2z m-88.3-110.1l-58.6 37.5c-5.6 4.3-8.8 11.1-8.5 18.1 0.3 7.1 3.9 13.6 9.8 17.4l66.3 36.5H194.8l73-37.8c6.3-3.9 10.2-10.8 10.4-18.3 0.1-7.5-3.6-14.5-9.9-18.5l-64.7-34.9h617.8z m38.6 17.3v66.7l-57.9-30.5 57.9-36.2z m-698.2-1.3l63.4 36.7-63.4 32.1v-68.8z m719.9 791.3h-742V262.5h741.9v654.1zM340.1 423.2c15.9 86.5 78.5 143.9 163.2 143.9 84.6 0 147.2-57.2 163.2-143.6 13.3-7 22.5-20.8 22.5-36.8 0-23-18.7-41.8-41.8-41.8-23 0-41.8 18.7-41.8 41.8 0 13.6 6.6 25.6 16.7 33.2C610 476 572.2 523.5 503.2 523.5c-68.9 0-106.6-47.3-118.8-103.3 10.3-7.6 17.1-19.7 17.1-33.5 0-23-18.8-41.8-41.8-41.8-23 0-41.7 18.7-41.7 41.8 0.1 15.8 9.1 29.5 22.1 36.5z" p-id="10814"></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>

A különbségek nem kerülnek megjelenítésre, a fájl túl nagy
+ 0 - 0
src/assets/icons/homepage.svg


A különbségek nem kerülnek megjelenítésre, a fájl túl nagy
+ 0 - 0
src/assets/icons/lab.svg


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

@@ -0,0 +1 @@
+<svg t="1675576810577" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1553" width="200" height="200"><path d="M379.392 460.8l114.688 114.688-42.496 102.4L307.2 532.48l-168.96 168.96-71.68-72.704L234.496 460.8l-45.056-45.056c-27.136-27.136-51.2-66.56-66.56-108.544h112.64c7.68 14.336 16.896 27.136 26.112 35.84l45.568 46.08 45.056-45.056C382.976 312.32 409.6 247.808 409.6 204.8H0V102.4h256V0h102.4v102.4h256v102.4h-102.4c0 70.144-37.888 161.28-87.04 210.944L378.88 460.8z m196.608 409.6L512 1024H409.6l256-614.4h102.4l256 614.4h-102.4l-64-153.6h-281.6z m42.496-102.4h196.608L716.8 532.48 618.496 768z" p-id="1554" data-spm-anchor-id="a313x.7781069.0.i0" class="selected"></path></svg>

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

@@ -0,0 +1 @@
+<svg t="1675604734873" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="20095" width="200" height="200"><path d="M611.2 368l-294.4 294.4c-6.4 6.4-9.6 16-9.6 22.4s3.2 16 9.6 22.4 16 9.6 22.4 9.6 16-3.2 22.4-9.6l294.4-294.4c6.4-6.4 9.6-16 9.6-22.4s-3.2-16-9.6-22.4c-12.8-12.8-32-12.8-44.8 0z" p-id="20096"></path><path d="M608 755.2l-99.2 99.2c-96 96-249.6 96-342.4 3.2-92.8-92.8-92.8-246.4 3.2-342.4L268.8 416c12.8-12.8 12.8-32 0-44.8s-32-12.8-44.8 0l-99.2 99.2C3.2 592 3.2 784 121.6 902.4 179.2 960 259.2 992 336 992c80 0 156.8-28.8 217.6-89.6l99.2-99.2c12.8-12.8 12.8-32 0-44.8s-32-16-44.8-3.2zM902.4 121.6c-57.6-57.6-131.2-86.4-214.4-86.4h-3.2c-83.2 0-160 35.2-217.6 92.8l-96 96c-12.8 12.8-12.8 32 0 44.8s32 12.8 44.8 0l96-96c48-48 108.8-73.6 172.8-73.6h3.2c64 0 121.6 25.6 166.4 70.4 92.8 92.8 92.8 246.4-3.2 345.6l-96 96c-12.8 12.8-12.8 32 0 44.8 6.4 6.4 16 9.6 22.4 9.6s16-3.2 22.4-9.6l96-96c121.6-124.8 124.8-320 6.4-438.4z" p-id="20097"></path></svg>

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

@@ -0,0 +1 @@
+<svg t="1650624092030" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="11056" width="200" height="200"><path d="M374.272 440.832H127.488c-33.792 0-61.44-27.648-61.44-61.44V132.608c0-33.792 27.648-61.44 61.44-61.44h247.296c33.792 0 61.44 27.648 61.44 61.44v247.296c-0.512 33.792-27.648 60.928-61.952 60.928zM127.488 132.608v247.296h247.296V132.608H127.488zM762.88 492.032c-16.384 0-31.744-6.144-43.52-17.92l-174.592-174.592c-11.776-11.776-17.92-27.136-17.92-43.52s6.144-31.744 17.92-43.52l174.592-174.592c11.776-11.776 27.136-17.92 43.52-17.92s31.744 6.144 43.52 17.92l174.592 174.592c11.776 11.776 17.92 27.136 17.92 43.52s-6.144 31.744-17.92 43.52l-174.592 174.592c-11.776 11.776-27.136 17.92-43.52 17.92z m0-410.624L588.288 256 762.88 430.592 937.472 256 762.88 81.408zM374.272 952.832H127.488c-33.792 0-61.44-27.648-61.44-61.44v-247.296c0-33.792 27.648-61.44 61.44-61.44h247.296c33.792 0 61.44 27.648 61.44 61.44v247.296c-0.512 34.304-27.648 61.44-61.952 61.44z m-246.784-308.224v247.296h247.296v-247.296H127.488zM886.272 952.832h-247.296c-33.792 0-61.44-27.648-61.44-61.44v-247.296c0-33.792 27.648-61.44 61.44-61.44h247.296c33.792 0 61.44 27.648 61.44 61.44v247.296c0 34.304-27.136 61.44-61.44 61.44z m-246.784-308.224v247.296h247.296v-247.296h-247.296z" p-id="11057"></path></svg>

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

@@ -0,0 +1 @@
+<svg t="1651250049265" class="icon" viewBox="0 0 1146 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="12503" width="200" height="200"><path d="M1091.555481 293.125035l-0.029028-0.152398-0.123369-0.123369C999.485831 119.76239 802.044436 0 573.238256 0c-316.53614 0-573.223741 229.292399-573.223741 512.039914 0 90.22637 47.947047 182.143624 93.869388 255.736933l-21.771021 172.861911c0 8.352815 3.461592 16.458892 10.471861 22.808774 6.451479 5.682237 14.862351 8.686638 23.382077 9.100287v0.166911h2.148074l215.083179-21.132405c75.545445 32.816187 160.372602 72.345105 250.04744 72.345105 316.53614 0 573.223741-229.205315 573.223741-511.974601 0.021771-78.295851-19.731803-152.462464-54.913773-218.827794z m-773.306687 270.265461a51.423153 51.423153 0 1 1 0-102.853563 51.43041 51.43041 0 0 1 0 102.853563z m252.630935 0a51.437667 51.437667 0 0 1 0-102.853563 51.43041 51.43041 0 1 1 0 102.853563z m252.638191 0a51.43041 51.43041 0 1 1-0.014514-102.846306 51.43041 51.43041 0 0 1 0.014514 102.846306z" fill="" p-id="12504"></path></svg>

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

@@ -0,0 +1 @@
+<svg t="1651249944904" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="8089" width="200" height="200"><path d="M688 316.8C726.4 278.4 768 220.8 768 160c0-35.2-9.6-64-32-86.4C694.4 32 620.8 32 537.6 32l-22.4 0c-12.8 0-25.6 0-38.4 0C396.8 32 332.8 32 291.2 70.4c-22.4 22.4-32 51.2-32 89.6 0 64 41.6 118.4 76.8 156.8-140.8 73.6-236.8 220.8-236.8 371.2 0 278.4 281.6 278.4 416 278.4s416 0 416-278.4C931.2 534.4 832 390.4 688 316.8zM611.2 579.2c19.2 0 32 12.8 32 32s-12.8 32-32 32l-64 0 0 32 64 0c19.2 0 32 12.8 32 32s-12.8 32-32 32l-64 0 0 67.2c0 19.2-12.8 32-32 32s-32-12.8-32-32l0-67.2-64 0c-19.2 0-32-12.8-32-32s12.8-32 32-32l64 0 0-32-64 0c-19.2 0-32-12.8-32-32s12.8-32 32-32l64 0 0-19.2-89.6-86.4c-12.8-12.8-12.8-32 0-44.8 12.8-12.8 32-12.8 44.8 0l80 76.8 80-76.8c12.8-12.8 32-12.8 44.8 0 12.8 12.8 12.8 32 0 44.8l-96 92.8 0 12.8L611.2 579.2z" p-id="8090"></path></svg>

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

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

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

@@ -0,0 +1 @@
+<svg t="1675604603623" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1216" width="200" height="200"><path d="M832.128 768c33.194667 0 60.501333 25.173333 63.573333 57.813333L896 832a64 64 0 0 1-63.872 64h-298.922667A63.786667 63.786667 0 0 1 469.333333 832a64 64 0 0 1 63.872-64h298.922667zM213.333333 874.666667c-23.722667 0-42.666667-19.072-42.666666-42.624V362.666667A42.666667 42.666667 0 0 1 213.333333 320l4.992 0.298667c21.333333 2.432 37.674667 20.48 37.674667 42.325333L255.957333 490.666667h128.298667c21.248 0 39.594667 16.469333 42.112 37.674666L426.666667 533.333333l-0.298667 4.992a42.368 42.368 0 0 1-42.112 37.674667H256l0.042667 213.333333h128.256c22.869333 0 42.410667 19.114667 42.410666 42.666667l-0.298666 4.992a42.368 42.368 0 0 1-42.112 37.674667zM832.128 469.333333c33.194667 0 60.501333 25.173333 63.573333 57.813334L896 533.333333a64 64 0 0 1-63.872 64h-298.922667A63.786667 63.786667 0 0 1 469.333333 533.333333a64 64 0 0 1 63.872-64h298.922667z m-255.957333-341.333333c33.194667 0 60.458667 25.173333 63.573333 57.813333L640 192c0 35.328-29.013333 64-63.829333 64H191.829333A63.744 63.744 0 0 1 128 192C128 156.672 157.013333 128 191.829333 128h384.341334z" fill="#000000" p-id="1217"></path></svg>

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

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

A különbségek nem kerülnek megjelenítésre, a fájl túl nagy
+ 0 - 0
src/assets/icons/number.svg


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

@@ -0,0 +1 @@
+<svg t="1650329913223" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="11785" width="200" height="200"><path d="M875.4 101.1H155c-37.9 0-73.4 30.8-73.4 68.7 0 37.9 35.5 68.7 73.4 68.7h5v689.7l25.5-25.5h2.8l74.5-74.5 81.2 81.2 1.4-1.4 2.5 2.5 81.1-81.1 81.1 81.1 2.5-2.5 2.5 2.5 81.1-81.1 81.1 81.1 2.5-2.5 1.4 1.4 81.2-81.2 74.5 74.5h2.8l25.5 25.5V238.5h10.3c37.9 0 68.7-30.8 68.7-68.7 0-37.9-30.9-68.7-68.8-68.7z m5.9 97.6h-16.2v-57.6h-39v63.6h-0.1v629l-62.2-62.2-1.4 1.4-1.4-1.4-81.2 81.2-81.1-81.2-2.5 2.5-2.5-2.5-81.1 81.1-81.1-81.1-2.5 2.5-2.5-2.5-81.1 81.2-81.2-81.2-1.4 1.4-1.4-1.4-62.2 62.2 0.2-692.6H160v57.6h-14.7c-15.9 0-28.8-12.9-28.8-28.9 0-15.9 12.9-28.8 28.8-28.8h736c15.9 0 28.9 12.9 28.9 28.8-0.1 16-13 28.9-28.9 28.9zM288.6 451.2h209.3c10.3 0 18.6-8.3 18.6-18.6s-8.3-18.6-18.6-18.6H288.6c-10.3 0-18.6 8.3-18.6 18.6s8.4 18.6 18.6 18.6z m0-117.5h326.8c10.3 0 18.6-8.3 18.6-18.6s-8.3-18.6-18.6-18.6H288.6c-10.3 0-18.6 8.3-18.6 18.6s8.4 18.6 18.6 18.6zM635 531.5H288.6c-10.3 0-18.6 8.3-18.6 18.6s8.3 18.6 18.6 18.6H635c10.3 0 18.6-8.3 18.6-18.6s-8.3-18.6-18.6-18.6zM595.9 649H288.6c-10.3 0-18.6 8.3-18.6 18.6s8.3 18.6 18.6 18.6h307.2c10.3 0 18.6-8.3 18.6-18.6 0.1-10.3-8.3-18.6-18.5-18.6z" p-id="11786"></path></svg>

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

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

A különbségek nem kerülnek megjelenítésre, a fájl túl nagy
+ 0 - 0
src/assets/icons/peoples.svg


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

@@ -0,0 +1 @@
+<svg t="1653975130734" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2343" width="200" height="200"><path d="M768 416.914c43.886-43.885 43.886-109.714 0-153.6C724.114 219.43 650.971 219.43 607.086 256s-43.886 109.714 0 153.6S724.114 460.8 768 416.914z m-109.714-51.2c-14.629-14.628-14.629-36.571 0-51.2 14.628-14.628 36.571-14.628 51.2 0 14.628 14.629 14.628 36.572 0 51.2s-36.572 14.629-51.2 0z m-512 563.2c-14.629 14.629-36.572 14.629-51.2 0s-14.629-36.571 0-51.2l387.657-387.657-14.629-21.943C409.6 365.714 424.23 241.371 504.686 153.6c102.4-102.4 263.314-102.4 358.4 0s102.4 263.314 0 358.4c-80.457 87.771-204.8 102.4-307.2 43.886l-21.943-14.629-160.914 160.914 80.457 80.458c14.628 14.628 36.571 14.628 51.2 0 14.628-14.629 14.628-36.572 0-51.2l-21.943-29.258 65.828-65.828c124.343 58.514 277.943 36.571 373.029-65.829 131.657-131.657 131.657-336.457 0-468.114s-336.457-124.343-468.114 0C358.4 204.8 329.143 351.086 387.657 475.429L36.571 826.514c-43.885 43.886-43.885 109.715 0 153.6 43.886 43.886 109.715 43.886 153.6 0l80.458-80.457-51.2-43.886-73.143 73.143z m307.2-51.2L321.829 746.057l-51.2 58.514L402.286 936.23c14.628 14.628 36.571 14.628 51.2 0 14.628-21.943 14.628-43.886 0-58.515z" p-id="2344"></path></svg>

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

@@ -0,0 +1 @@
+<svg t="1650624655184" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="22328" width="200" height="200"><path d="M924.145781 233.089709l0-3.215228-0.642636-0.642636 0-2.571568-0.642636-0.642636 0-0.642636-0.642636-0.642636-0.642636 0-0.642636-0.642636 0-0.642636-1.928932-1.928932 0-0.642636-0.642636-0.642636 0-1.286296-1.928932 0-0.642636-0.642636-1.286296 0-0.642636-0.642636 0-0.642636-0.642636 0 0-0.642636-0.642636 0-0.642636-0.642636-0.642636 0 0-0.642636-2.571568 0 0-0.642636-5.14416 0-0.642636 0.642636-0.642636 0 0 0.642636-1.286296 0-0.642636 0.642636-1.286296 0L112.707968 515.999081c-10.287297 3.857864-15.431457 14.788821-11.573593 25.718755 2.571568 5.786797 7.073092 9.644661 12.216229 11.573593l235.972363 94.517677 24.433482 135.667889c1.928932 10.930957 12.216229 17.36039 22.50455 16.074094 4.500501-0.642636 8.358365-3.215228 10.930957-6.429433l87.444585-87.444585 178.104397 71.370491c10.287297 3.857864 21.218254-0.642636 25.718755-10.287297l223.756133-523.383258 0.642636-0.642636 0-0.642636 0-1.286296 0-5.14416L924.145781 233.089709 924.145781 233.089709zM364.112812 610.516758 364.112812 610.516758l-190.32165-75.870991 604.39841-230.829226L364.112812 610.516758 364.112812 610.516758zM405.263024 738.468918 405.263024 738.468918l-12.859889-74.585719 62.368466 25.076118L405.263024 738.468918 405.263024 738.468918zM670.169369 733.325781 670.169369 733.325781 406.54932 627.877147l452.012767-334.347904L670.169369 733.325781 670.169369 733.325781z" p-id="22329"></path></svg>

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

@@ -0,0 +1 @@
+<svg t="1650625601015" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="38305" width="200" height="200"><path d="M192 128h-128v768h896V384h-384V128h-128v256h-256V128zM384 320v-256h256v256h384v640H0V64h256v256h128z" p-id="38306"></path><path d="M640 576v128h128v-128H640zM576 512h256v256h-256V512z" p-id="38307"></path></svg>

+ 1 - 0
src/assets/icons/rate.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="1577246781606" class="icon" viewBox="0 0 1069 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1098" xmlns:xlink="http://www.w3.org/1999/xlink" width="84.5595703125" height="81"><defs><style type="text/css"></style></defs><path d="M633.72929961 378.02038203l9.49872568 18.68789795 20.78025469 2.79745225 206.61592412 27.33248408a11.46496817 11.46496817 0 0 1 6.6095543 19.47324902l-147.2675168 147.35350284-14.89299345 14.89299345 3.8006376 20.68280244 37.84585956 204.89044571a11.46496817 11.46496817 0 0 1-16.4808914 12.2961788L554.68980898 751.84713388l-18.68789794-9.49299345-18.48726123 9.99171915-183.23885392 99.34968163a11.46496817 11.46496817 0 0 1-16.78471347-11.8662416l32.5433127-205.79617881 3.29617793-20.78598692-15.19108243-14.49172002-151.03375839-143.48407587a11.46496817 11.46496817 0 0 1 6.09936328-19.63949062l205.79617881-32.63503185 20.78598691-3.2961788L428.87898125 380.72038203 518.59235674 192.64331182a11.46496817 11.46496817 0 0 1 20.56815264-0.26369385l94.56879023 185.63503183zM496.64840732 85.52038203l-121.75796162 254.98089229L95.76433145 384.76178369A34.3949045 34.3949045 0 0 0 77.46050938 443.66879023l204.87324901 194.66369385-44.16879023 279.1146498a34.3949045 34.3949045 0 0 0 50.36560489 35.61592325l248.4-134.67898038 251.84522285 128.27579591a34.3949045 34.3949045 0 0 0 49.43694287-36.89426777l-51.30573223-277.85350284 199.73120977-199.90891758a34.3949045 34.3949045 0 0 0-19.82866201-58.40827998l-280.11783428-37.03184736L558.32993633 84.71210205a34.3949045 34.3949045 0 0 0-61.68152901 0.80254775z" p-id="1099"></path></svg>

A különbségek nem kerülnek megjelenítésre, a fájl túl nagy
+ 0 - 0
src/assets/icons/redis.svg


+ 1 - 0
src/assets/icons/refresh.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" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 512 512"><path d="M400 148l-21.12-24.57A191.43 191.43 0 0 0 240 64C134 64 48 150 48 256s86 192 192 192a192.09 192.09 0 0 0 181.07-128" fill="none" stroke="currentColor" stroke-linecap="square" stroke-miterlimit="10" stroke-width="32"></path><path d="M464 68.45V220a4 4 0 0 1-4 4H308.45a4 4 0 0 1-2.83-6.83L457.17 65.62a4 4 0 0 1 6.83 2.83z" fill="currentColor"></path></svg>

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

@@ -0,0 +1 @@
+<svg t="1640017511829" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="10964" width="256" height="256"><path d="M79.23846992 961.89615371v-25.44230742c0-109.28076943 28.83461573-214.89230742 81.13846113-297.41538515 48.42692315-76.39615372 115.30384629-131.57307685 195.50769258-161.89615372A240.78461573 240.78461573 0 0 1 279.48846992 300.5c0-131.53846114 104.33076943-238.53461572 232.54615372-238.53461572s232.51153887 106.99615372 232.51153798 238.53461572a240.85384629 240.85384629 0 0 1-76.74230742 176.98846114c190.86923057 73.00384629 276.99230742 277.13076943 276.99230742 458.96538514v25.44230743H79.23846992zM694.90770049 300.5c0-103.43076943-82.03846114-187.61538427-182.87307686-187.61538427-100.83461573 0-182.87307685 84.18461573-182.87307685 187.61538427 0 103.46538427 82.03846114 187.65 182.87307685 187.65 100.83461573 0 182.87307685-84.18461573 182.87307686-187.65z m-79.16538516 213.50769258a226.45384629 226.45384629 0 0 1-103.7076917 25.0961537 225.93461572 225.93461572 0 0 1-104.12307686-25.30384628c-195.02307685 51.12692315-271.10769258 239.05384629-278.41153886 397.17692315h765.03461573c-7.99615372-167.4-95.22692315-347.74615372-278.79230831-396.96923057z m-143.41153799 37.2461537h79.40769258l39.73846114-8.48076943-45.24230742 65.66538429 30.6 227.52692313-64.8 56.90769258-69.19615372-56.90769258 40.53461485-227.52692313-50.78076944-65.66538429 39.73846201 8.48076944z" p-id="10965"></path></svg>

A különbségek nem kerülnek megjelenítésre, a fájl túl nagy
+ 0 - 0
src/assets/icons/security.svg


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

@@ -0,0 +1 @@
+<svg t="1650814514935" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="42619" width="200" height="200"><path d="M346.112 806.912q19.456 0 36.864 7.168t30.208 19.968 20.48 30.208 7.68 36.864-7.68 36.864-20.48 30.208-30.208 20.48-36.864 7.68q-20.48 0-37.888-7.68t-30.208-20.48-20.48-30.208-7.68-36.864 7.68-36.864 20.48-30.208 30.208-19.968 37.888-7.168zM772.096 808.96q19.456 0 37.376 7.168t30.72 19.968 20.48 30.208 7.68 36.864-7.68 36.864-20.48 30.208-30.72 20.48-37.376 7.68-36.864-7.68-30.208-20.48-20.48-30.208-7.68-36.864 7.68-36.864 20.48-30.208 30.208-19.968 36.864-7.168zM944.128 227.328q28.672 0 44.544 7.68t22.528 18.944 6.144 24.064-3.584 22.016-13.312 37.888-22.016 62.976-23.552 68.096-18.944 53.248q-13.312 40.96-33.28 56.832t-49.664 15.872l-35.84 0-65.536 0-86.016 0-96.256 0-253.952 0 14.336 92.16 517.12 0q49.152 0 49.152 41.984 0 20.48-9.728 35.328t-38.4 14.848l-49.152 0-94.208 0-118.784 0-119.808 0-99.328 0-55.296 0q-20.48 0-34.304-9.216t-23.04-24.064-14.848-32.256-8.704-32.768q-1.024-6.144-5.632-29.696t-11.264-58.88-14.848-78.848-16.384-87.552q-19.456-103.424-44.032-230.4l-76.8 0q-15.36 0-25.6-7.68t-16.896-18.432-9.216-23.04-2.56-22.528q0-20.48 13.824-33.792t37.376-13.312l21.504 0 21.504 0 25.6 0 34.816 0q20.48 0 32.768 6.144t19.456 15.36 10.24 19.456 5.12 17.408q2.048 8.192 4.096 23.04t4.096 30.208q3.072 18.432 6.144 38.912l700.416 0zM867.328 194.56l-374.784 0 135.168-135.168q23.552-23.552 51.712-24.064t51.712 23.04z" p-id="42620"></path></svg>

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

@@ -0,0 +1 @@
+<svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M0 54.857h54.796v18.286H36.531V128H18.265V73.143H0V54.857zm127.857-36.571H91.935V128H72.456V18.286H36.534V0h91.326l-.003 18.286z"/></svg>

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

@@ -0,0 +1 @@
+<svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M31.652 93.206h33.401c1.44 2.418 3.077 4.663 4.93 6.692h-38.33v-6.692zm0-10.586h28.914a44.8 44.8 0 0 1-1.264-6.688h-27.65v6.688zm0-17.27H59.39c.288-2.286.714-4.532 1.34-6.687H31.65v6.687h.003zm53.913 44.84v5.85c0 2.798-2.095 5.075-4.667 5.075h-70.07c-2.576 0-4.663-2.277-4.663-5.075V31.26l23.22-20.96v22.25H17.16v6.688h18.39V6.688h45.348c2.576 0 4.667 2.277 4.667 5.066v20.009c1.987-.675 4.053-1.128 6.17-1.445v-18.56C91.738 5.28 86.874 0 80.902 0H31.15L0 28.118v87.917c0 6.48 4.859 11.759 10.832 11.759h70.07c5.974 0 10.837-5.27 10.837-11.759v-4.41c-2.117-.312-4.183-.765-6.17-1.435h-.004zM23.279 58.667h-7.96v6.688h7.96v-6.688zm-7.956 41.23h7.96v-6.691h-7.96v6.692zm7.956-23.96h-7.96v6.687h7.96v-6.688zm89.718-15.042l-4.896-4.07-12.447 17.613-11.19-9.305-3.762 5.311 16.091 13.38 16.204-22.929zM128 70.978c0-18.632-13.97-33.782-31.147-33.782-17.168 0-31.135 15.155-31.135 33.782 0 18.628 13.97 33.783 31.135 33.783 17.172 0 31.143-15.15 31.143-33.783H128zm-6.17 0c0 14.933-11.203 27.1-24.981 27.1-13.77 0-24.987-12.158-24.987-27.1 0-14.941 11.195-27.099 24.987-27.099 13.778 0 24.982 12.158 24.982 27.1z"/></svg>

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

@@ -0,0 +1 @@
+<svg t="1675605231338" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="12660" width="200" height="200"><path d="M139 669.6V164.3c0-12.7 10.3-23.1 23.1-23.1h694.4c12.7 0 23.1 10.4 23.1 23.1v248.5h70V164.3c0-51.3-41.8-93.1-93.1-93.1H162c-51.3 0.1-93 41.8-93 93.1v505.3c0 51.3 41.8 93.1 93.1 93.1h224.7v-70H162c-12.7 0-23-10.4-23-23.1zM104.7 800.6h282v70h-282z" p-id="12661"></path><path d="M954.9 599.4l-5.1-15c-11.5-33.9-29.4-64.9-53.2-91.9l-10.5-11.9h-83.2l-41.7-72.2-15.6-3.1c-34.8-6.9-71.3-6.9-106.1 0l-15.6 3.1-41.7 72.2H499l-10.5 11.9c-23.8 27.1-41.7 58-53.2 91.9l-5.1 15 41.7 72.2-41.7 72.2 5.1 15c11.5 33.9 29.4 64.9 53.2 91.9l10.5 11.9h83.2l41.7 72.2 15.6 3.1c17.4 3.5 35.3 5.2 53.1 5.2s35.6-1.8 53.1-5.2l15.6-3.1 41.7-72.2h83.2l10.5-11.9c23.8-27.1 41.7-58 53.2-91.9l5.1-15-41.7-72.2 41.6-72.2z m-76.8 151.2c-6.4 14.9-14.5 29-24.3 42h-91.2l-45.6 79c-16.1 1.9-32.4 1.9-48.5 0l-45.6-79h-91.2c-9.8-13-17.9-27-24.3-42l45.6-79.1-45.6-79.1c6.4-14.9 14.5-29 24.3-42h91.2l45.6-79c16.1-1.9 32.4-1.9 48.5 0l45.6 79h91.2c9.8 13 17.9 27 24.3 42l-45.6 79.1 45.6 79.1z" p-id="12662"></path><path d="M692.7 560.2c-61.4 0-111.3 49.9-111.3 111.3s49.9 111.3 111.3 111.3S804 732.9 804 671.5c0-61.3-49.9-111.3-111.3-111.3z m0 152.7c-22.8 0-41.3-18.5-41.3-41.3s18.5-41.3 41.3-41.3 41.3 18.5 41.3 41.3-18.5 41.3-41.3 41.3z" p-id="12663"></path></svg>

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

@@ -0,0 +1 @@
+<svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M125.5 36.984L95.336 2.83C93.735 1.018 91.565 0 89.3 0c-2.263 0-4.433 1.018-6.033 2.83l-3.786 4.286c-1.6 1.812-3.77 2.83-6.032 2.831H54.553c-2.263 0-4.434-1.018-6.033-2.83L44.734 2.83C43.134 1.018 40.964 0 38.701 0c-2.263 0-4.434 1.018-6.034 2.83L2.5 36.984C.9 38.796 0 41.254 0 43.815c0 2.562.899 5.02 2.5 6.831L14.565 64.31c2.178 2.468 5.367 3.403 8.33 2.444 1.35-.435 2.709.592 2.709 2.18v49.407c0 5.313 3.84 9.66 8.532 9.66h59.726c4.693 0 8.532-4.347 8.532-9.66V68.934c0-1.59 1.36-2.616 2.71-2.181 2.962.96 6.15.024 8.329-2.444L125.5 50.646c1.6-1.811 2.499-4.269 2.499-6.83 0-2.563-.899-5.02-2.5-6.832z"/></svg>

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

@@ -0,0 +1 @@
+<svg t="1650623941490" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="9166" width="200" height="200"><path d="M977.454545 558.545455h-34.90909v-104.727273c0-44.218182-37.236364-81.454545-81.454546-81.454546H546.909091v-93.090909H744.727273c25.6 0 46.545455-20.945455 46.545454-46.545454V93.090909c0-25.6-20.945455-46.545455-46.545454-46.545454H279.272727c-25.6 0-46.545455 20.945455-46.545454 46.545454v139.636364c0 25.6 20.945455 46.545455 46.545454 46.545454h197.818182v93.090909H162.909091c-44.218182 0-81.454545 37.236364-81.454546 81.454546V558.545455H46.545455c-25.6 0-46.545455 20.945455-46.545455 46.545454v325.818182c0 25.6 20.945455 46.545455 46.545455 46.545454h139.636363c25.6 0 46.545455-20.945455 46.545455-46.545454V605.090909c0-25.6-20.945455-46.545455-46.545455-46.545454H151.272727v-104.727273c0-6.981818 4.654545-11.636364 11.636364-11.636364h314.181818v116.363637H442.181818c-25.6 0-46.545455 20.945455-46.545454 46.545454v325.818182c0 25.6 20.945455 46.545455 46.545454 46.545454h139.636364c25.6 0 46.545455-20.945455 46.545454-46.545454V605.090909c0-25.6-20.945455-46.545455-46.545454-46.545454h-34.909091v-116.363637H861.090909c6.981818 0 11.636364 4.654545 11.636364 11.636364V558.545455H837.818182c-25.6 0-46.545455 20.945455-46.545455 46.545454v325.818182c0 25.6 20.945455 46.545455 46.545455 46.545454h139.636363c25.6 0 46.545455-20.945455 46.545455-46.545454V605.090909c0-25.6-20.945455-46.545455-46.545455-46.545454zM162.909091 628.363636v279.272728H69.818182V628.363636h93.090909z m395.636364 0v279.272728h-93.09091V628.363636h93.09091zM302.545455 209.454545V116.363636h418.90909v93.090909H302.545455z m651.636363 698.181819h-93.090909V628.363636h93.090909v279.272728z" p-id="9167"></path></svg>

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

@@ -0,0 +1 @@
+<svg t="1650622753800" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4947" width="200" height="200"><path d="M599.378 958.454H424.62c-165.805 0-296.769 0-296.769-86.024v-17.178c0-161.188 133.115-292.258 296.77-292.258h174.756c163.619 0 296.769 131.102 296.769 292.258v17.178c0 86.024-137.557 86.024-296.768 86.024z m-176.39-346.981c-137.625 0-249.608 109.935-249.608 245.098v17.491c0 35.046 144.255 35.046 249.608 35.046h177.985c87.207 0 249.645 0 249.645-35.046v-17.491c0-135.163-112.018-245.098-249.645-245.098H422.988z m80.266-83.526c-129.923 0-235.555-104.14-235.555-232.12 0-128.015 105.632-232.119 235.555-232.119s235.554 104.104 235.554 232.12c0 127.978-105.7 232.12-235.554 232.12zM316.246 295.098c0 101.224 83.91 183.572 187.008 183.572 103.133 0 187.042-82.348 187.042-183.572 0-101.19-83.909-183.502-187.042-183.502-103.134 0-187.008 82.311-187.008 183.502z m0 17.767" fill="" p-id="4948"></path></svg>

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

@@ -0,0 +1 @@
+<svg t="1650813729189" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="3256" width="200" height="200"><path d="M504.29 576.68c-150.17 0-272.35-122.93-272.35-274.03C231.95 153.42 354.12 32 504.29 32s272.33 121.42 272.33 270.65c0.01 151.1-122.16 274.03-272.33 274.03z m0-476.18c-112.4 0-203.84 90.69-203.84 202.15 0 113.33 91.45 205.53 203.84 205.53s203.83-92.19 203.83-205.53c0-111.46-91.43-202.15-203.83-202.15z" p-id="3257"></path><path d="M410.8 988.38H96.13c-18.92 0-34.25-15.33-34.25-34.25 0-245.82 198.46-445.81 442.4-445.81 18.92 0 34.25 15.33 34.25 34.25s-15.33 34.25-34.25 34.25c-194.72 0-355.16 151-372.37 343.05H410.8c18.92 0 34.25 15.33 34.25 34.25s-15.33 34.26-34.25 34.26z" p-id="3258"></path><path d="M756.99 637.76c-97.82 0-177.12 79.3-177.12 177.12S659.17 992 756.99 992s177.12-79.3 177.12-177.12H756.99V637.76z" p-id="3259"></path><path d="M785 609.76v177.12h177.12c0-97.82-79.3-177.12-177.12-177.12z" p-id="3260"></path></svg>

A különbségek nem kerülnek megjelenítésre, a fájl túl nagy
+ 3 - 0
src/assets/icons/valid_code.svg


A különbségek nem kerülnek megjelenítésre, a fájl túl nagy
+ 3 - 0
src/assets/icons/verify_code.svg


BIN
src/assets/index/indicator.png


BIN
src/assets/logo.png


+ 102 - 0
src/components/Breadcrumb/index.vue

@@ -0,0 +1,102 @@
+<template>
+  <el-breadcrumb class="h-[50px] flex items-center">
+    <transition-group name="breadcrumb">
+      <el-breadcrumb-item v-for="(item, index) in breadcrumbs" :key="item.path">
+        <span
+          v-if="
+            item.redirect === 'noredirect' || index === breadcrumbs.length - 1
+          "
+          class="text-[var(--el-disabled-text-color)]"
+          >{{ item.meta.title }}</span
+        >
+        <a v-else @click.prevent="handleLink(item)">
+          {{ item.meta.title }}
+        </a>
+      </el-breadcrumb-item>
+    </transition-group>
+  </el-breadcrumb>
+</template>
+
+<script setup lang="ts">
+import { onBeforeMount, ref, watch } from "vue";
+import { useRoute, RouteLocationMatched } from "vue-router";
+import { compile } from "path-to-regexp";
+import router from "@/router";
+
+const currentRoute = useRoute();
+const pathCompile = (path: string) => {
+  const { params } = currentRoute;
+  const toPath = compile(path);
+  return toPath(params);
+};
+
+const breadcrumbs = ref([] as Array<RouteLocationMatched>);
+
+function getBreadcrumb() {
+  let matched = currentRoute.matched.filter(
+    (item) => item.meta && item.meta.title
+  );
+  const first = matched[0];
+  if (!isDashboard(first)) {
+    matched = [
+      { path: "/dashboard", meta: { title: "dashboard" } } as any,
+    ].concat(matched);
+  }
+  breadcrumbs.value = matched.filter((item) => {
+    return item.meta && item.meta.title && item.meta.breadcrumb !== false;
+  });
+}
+
+function isDashboard(route: RouteLocationMatched) {
+  const name = route && route.name;
+  if (!name) {
+    return false;
+  }
+  return (
+    name.toString().trim().toLocaleLowerCase() ===
+    "Dashboard".toLocaleLowerCase()
+  );
+}
+
+function handleLink(item: any) {
+  const { redirect, path } = item;
+  if (redirect) {
+    router.push(redirect).catch((err) => {
+      console.warn(err);
+    });
+    return;
+  }
+  router.push(pathCompile(path)).catch((err) => {
+    console.warn(err);
+  });
+}
+
+watch(
+  () => currentRoute.path,
+  (path) => {
+    if (path.startsWith("/redirect/")) {
+      return;
+    }
+    getBreadcrumb();
+  }
+);
+
+onBeforeMount(() => {
+  getBreadcrumb();
+});
+</script>
+
+<style lang="scss" scoped>
+.app-breadcrumb.el-breadcrumb {
+  display: inline-block;
+  margin-left: 8px;
+  font-size: 14px;
+  line-height: 50px;
+}
+
+// 覆盖 element-plus 的样式
+.el-breadcrumb__inner,
+.el-breadcrumb__inner a {
+  font-weight: 400 !important;
+}
+</style>

+ 46 - 0
src/components/Hamburger/index.vue

@@ -0,0 +1,46 @@
+<template>
+  <div
+    class="px-[15px] hover:bg-gray-50 cursor-pointer h-[50px] leading-[50px] dark:hover:bg-[var(--el-fill-color-light)]"
+    @click="toggleClick"
+  >
+    <svg
+      :class="{ 'is-active': isActive }"
+      class="hamburger"
+      viewBox="0 0 1024 1024"
+      xmlns="http://www.w3.org/2000/svg"
+      style="color: #fff !important"
+    >
+      <path
+        d="M408 442h480c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8H408c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8zm-8 204c0 4.4 3.6 8 8 8h480c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8H408c-4.4 0-8 3.6-8 8v56zm504-486H120c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h784c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zm0 632H120c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h784c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zM142.4 642.1L298.7 519a8.84 8.84 0 0 0 0-13.9L142.4 381.9c-5.8-4.6-14.4-.5-14.4 6.9v246.3a8.9 8.9 0 0 0 14.4 7z"
+      />
+    </svg>
+  </div>
+</template>
+
+<script setup lang="ts">
+defineProps({
+  isActive: {
+    required: true,
+    type: Boolean,
+    default: false,
+  },
+});
+
+const emit = defineEmits(["toggleClick"]);
+
+function toggleClick() {
+  emit("toggleClick");
+}
+</script>
+
+<style lang="scss" scoped>
+.hamburger {
+  width: 20px;
+  height: 20px;
+  vertical-align: -4px;
+
+  &.is-active {
+    transform: rotate(180deg);
+  }
+}
+</style>

+ 165 - 0
src/components/IconSelect/index.vue

@@ -0,0 +1,165 @@
+<script setup lang="ts">
+const props = defineProps({
+  modelValue: {
+    type: String,
+    require: false,
+    default: "",
+  },
+});
+
+const emit = defineEmits(["update:modelValue"]);
+const inputValue = toRef(props, "modelValue");
+
+const visible = ref(false); // 弹窗显示状态
+
+const allIconNames: string[] = []; // 所有的图标名称集合
+
+const filterValue = ref(""); // 筛选的值
+const filterIconNames = ref<string[]>([]); // 过滤后的图标名称集合
+
+const iconSelectorRef = ref();
+const iconSelectorDialogRef = ref();
+/**
+ * icon 加载
+ */
+function loadIcons() {
+  const icons = import.meta.glob("../../assets/icons/*.svg");
+  for (const icon in icons) {
+    const iconName = icon.split("assets/icons/")[1].split(".svg")[0];
+    allIconNames.push(iconName);
+  }
+  filterIconNames.value = allIconNames;
+}
+
+/**
+ * icon 筛选
+ */
+function handleFilter() {
+  if (filterValue.value) {
+    filterIconNames.value = allIconNames.filter((iconName) =>
+      iconName.includes(filterValue.value)
+    );
+  } else {
+    filterIconNames.value = allIconNames;
+  }
+}
+
+/**
+ * icon 选择
+ */
+function handleSelect(iconName: string) {
+  emit("update:modelValue", iconName);
+  visible.value = false;
+}
+
+/**
+ * 点击容器外的区域关闭弹窗 VueUse onClickOutside
+ */
+onClickOutside(iconSelectorRef, () => (visible.value = false), {
+  ignore: [iconSelectorDialogRef],
+});
+
+onMounted(() => {
+  loadIcons();
+});
+</script>
+
+<template>
+  <div ref="iconSelectorRef" class="iconselect-container">
+    <el-input
+      v-model="inputValue"
+      readonly
+      placeholder="点击选择图标"
+      @click="visible = !visible"
+    >
+      <template #prepend>
+        <svg-icon :icon-class="inputValue" />
+      </template>
+    </el-input>
+
+    <el-popover
+      shadow="none"
+      :visible="visible"
+      placement="bottom-end"
+      trigger="click"
+      width="400"
+    >
+      <template #reference>
+        <div
+          class="cursor-pointer text-[#999] absolute right-[10px] top-0 height-[32px] leading-[32px]"
+          @click="visible = !visible"
+        >
+          <i-ep-caret-top v-show="visible"></i-ep-caret-top>
+          <i-ep-caret-bottom v-show="!visible"></i-ep-caret-bottom>
+        </div>
+      </template>
+
+      <!-- 下拉选择弹窗 -->
+      <div ref="iconSelectorDialogRef">
+        <el-input
+          v-model="filterValue"
+          class="p-2"
+          placeholder="搜索图标"
+          clearable
+          @input="handleFilter"
+        />
+        <el-divider border-style="dashed" />
+
+        <el-scrollbar height="300px">
+          <ul class="icon-list">
+            <li
+              v-for="(iconName, index) in filterIconNames"
+              :key="index"
+              class="icon-item"
+              @click="handleSelect(iconName)"
+            >
+              <el-tooltip :content="iconName" placement="bottom" effect="light">
+                <svg-icon
+                  color="var(--el-text-color-regular)"
+                  :icon-class="iconName"
+                />
+              </el-tooltip>
+            </li>
+          </ul>
+        </el-scrollbar>
+      </div>
+    </el-popover>
+  </div>
+</template>
+
+<style scoped lang="scss">
+.el-divider--horizontal {
+  margin: 10px auto !important;
+}
+
+.iconselect-container {
+  position: relative;
+  width: 400px;
+}
+
+.icon-list {
+  display: flex;
+  flex-wrap: wrap;
+  padding-left: 10px;
+  margin-top: 10px;
+
+  .icon-item {
+    display: flex;
+    flex-direction: column;
+    align-items: center;
+    justify-items: center;
+    width: 10%;
+    padding: 5px;
+    margin: 0 10px 10px 0;
+    cursor: pointer;
+    border: 1px solid #ccc;
+
+    &:hover {
+      color: var(--el-color-primary);
+      border-color: var(--el-color-primary);
+      transition: all 0.2s;
+      transform: scaleX(1.1);
+    }
+  }
+}
+</style>

+ 88 - 0
src/components/Pagination/index.vue

@@ -0,0 +1,88 @@
+<template>
+  <div :class="'pagination ' + { hidden: hidden }">
+    <el-pagination
+      v-model:current-page="currentPage"
+      v-model:page-size="pageSize"
+      :background="background"
+      :layout="layout"
+      :page-sizes="pageSizes"
+      :total="total"
+      @size-change="handleSizeChange"
+      @current-change="handleCurrentChange"
+    />
+  </div>
+</template>
+
+<script setup lang="ts">
+import { computed, PropType } from "vue";
+import { scrollTo } from "@/utils/scroll-to";
+
+const props = defineProps({
+  total: {
+    required: true,
+    type: Number as PropType<number>,
+    default: 0,
+  },
+  page: {
+    type: Number,
+    default: 1,
+  },
+  limit: {
+    type: Number,
+    default: 20,
+  },
+  pageSizes: {
+    type: Array as PropType<number[]>,
+    default() {
+      return [10, 20, 30, 50];
+    },
+  },
+  layout: {
+    type: String,
+    default: "total, sizes, prev, pager, next, jumper",
+  },
+  background: {
+    type: Boolean,
+    default: true,
+  },
+  autoScroll: {
+    type: Boolean,
+    default: true,
+  },
+  hidden: {
+    type: Boolean,
+    default: false,
+  },
+});
+
+const emit = defineEmits(["pagination", "update:page", "update:limit"]);
+
+const currentPage = useVModel(props, "page", emit);
+
+const pageSize = useVModel(props, "limit", emit);
+
+function handleSizeChange(val: number) {
+  emit("pagination", { page: currentPage, limit: val });
+  if (props.autoScroll) {
+    scrollTo(0, 800);
+  }
+}
+
+function handleCurrentChange(val: number) {
+  currentPage.value = val;
+  emit("pagination", { page: val, limit: props.limit });
+  if (props.autoScroll) {
+    scrollTo(0, 800);
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+.pagination {
+  padding: 12px;
+
+  &.hidden {
+    display: none;
+  }
+}
+</style>

+ 136 - 0
src/components/RightPanel/index.vue

@@ -0,0 +1,136 @@
+<script setup lang="ts">
+import { onBeforeUnmount, onMounted, ref, watch } from "vue";
+
+import { addClass, removeClass } from "@/utils/index";
+
+const show = ref(false);
+
+defineProps({
+  buttonTop: {
+    default: 250,
+    type: Number,
+  },
+});
+
+watch(show, (value) => {
+  if (value) {
+    addEventClick();
+  }
+  if (value) {
+    addClass(document.body, "showRightPanel");
+  } else {
+    removeClass(document.body, "showRightPanel");
+  }
+});
+
+function addEventClick() {
+  window.addEventListener("click", closeSidebar, { passive: true });
+}
+
+function closeSidebar(evt: any) {
+  // 主题选择点击不关闭
+  let parent = evt.target.closest(".right-panel-container");
+  if (!parent) {
+    show.value = false;
+    window.removeEventListener("click", closeSidebar);
+  }
+}
+
+const rightPanel = ref();
+
+function insertToBody() {
+  const body = document.querySelector("body") as any;
+  body.insertBefore(rightPanel.value, body.firstChild);
+}
+
+onMounted(() => {
+  insertToBody();
+});
+
+onBeforeUnmount(() => {
+  rightPanel.value.remove();
+});
+</script>
+
+<template>
+  <div ref="rightPanel" :class="{ show: show }">
+    <div class="right-panel-overlay" />
+    <div class="right-panel-container">
+      <div
+        class="right-panel-btn"
+        :style="{
+          top: buttonTop + 'px',
+        }"
+        @click="show = !show"
+      >
+        <i-ep-close v-show="show" />
+        <i-ep-setting v-show="!show" />
+      </div>
+      <div>
+        <slot />
+      </div>
+    </div>
+  </div>
+</template>
+
+<style lang="scss" scoped>
+.showRightPanel {
+  position: relative;
+  width: calc(100% - 15px);
+  overflow: hidden;
+}
+
+.right-panel-overlay {
+  position: fixed;
+  top: 0;
+  left: 0;
+  background: rgb(0 0 0 / 20%);
+}
+
+.right-panel-container {
+  position: fixed;
+  top: 0;
+  right: 0;
+  z-index: 999;
+  width: 100%;
+  max-width: 300px;
+  height: 100vh;
+  background-color: var(--el-bg-color-overlay);
+  box-shadow: 0 0 15px 0 rgb(0 0 0 / 5%);
+  transition: all 0.25s cubic-bezier(0.7, 0.3, 0.1, 1);
+  transform: translate(100%);
+}
+
+.show {
+  transition: all 0.3s cubic-bezier(0.7, 0.3, 0.1, 1);
+
+  .right-panel-overlay {
+    z-index: 99;
+    width: 100%;
+    height: 100%;
+    opacity: 1;
+  }
+
+  .right-panel-container {
+    transform: translate(0);
+  }
+}
+
+.right-panel-btn {
+  position: absolute;
+  left: -36px;
+  width: 36px;
+  height: 36px;
+  color: var(--el-color-white);
+  text-align: center;
+  cursor: pointer;
+  background-color: var(--el-color-primary);
+  border-radius: 6px 0 0 6px;
+
+  svg {
+    width: 20px;
+    height: 20px;
+    vertical-align: -10px;
+  }
+}
+</style>

+ 36 - 0
src/components/SizeSelect/index.vue

@@ -0,0 +1,36 @@
+<script setup lang="ts">
+import { useAppStore } from '@/store/modules/app';
+
+const appStore = useAppStore();
+
+const sizeOptions = ref([
+  { label: '默认', value: 'default' },
+  { label: '大型', value: 'large' },
+  { label: '小型', value: 'small' }
+]);
+
+function handleSizeChange(size: string) {
+  appStore.changeSize(size);
+  ElMessage.success('切换布局大小成功');
+}
+</script>
+
+<template>
+  <el-dropdown trigger="click" @command="handleSizeChange">
+    <div>
+      <svg-icon icon-class="size" />
+    </div>
+    <template #dropdown>
+      <el-dropdown-menu>
+        <el-dropdown-item
+          v-for="item of sizeOptions"
+          :key="item.value"
+          :disabled="appStore.size == item.value"
+          :command="item.value"
+        >
+          {{ item.label }}
+        </el-dropdown-item>
+      </el-dropdown-menu>
+    </template>
+  </el-dropdown>
+</template>

+ 45 - 0
src/components/SvgIcon/index.vue

@@ -0,0 +1,45 @@
+<template>
+  <svg
+    aria-hidden="true"
+    class="svg-icon"
+    :style="'width:' + size + ';height:' + size"
+  >
+    <use :xlink:href="symbolId" :fill="color" />
+  </svg>
+</template>
+
+<script setup lang="ts">
+const props = defineProps({
+  prefix: {
+    type: String,
+    default: "icon",
+  },
+  iconClass: {
+    type: String,
+    required: false,
+    default: "",
+  },
+  color: {
+    type: String,
+    default: "",
+  },
+  size: {
+    type: String,
+    default: "1em",
+  },
+});
+
+const symbolId = computed(() => `#${props.prefix}-${props.iconClass}`);
+</script>
+
+<style scoped>
+.svg-icon {
+  display: inline-block;
+  width: 1em;
+  height: 1em;
+  overflow: hidden;
+  vertical-align: -0.15em; /* 因icon大小被设置为和字体大小一致,而span等标签的下边缘会和字体的基线对齐,故需设置一个往下的偏移比例,来纠正视觉上的未对齐效果 */
+  outline: none;
+  fill: currentcolor; /* 定义元素的颜色,currentColor是一个变量,这个变量的值就表示当前元素的color值,如果当前元素未设置color值,则从父元素继承 */
+}
+</style>

+ 492 - 0
src/components/TagInput/index.vue

@@ -0,0 +1,492 @@
+<template>
+  <div :class="['tagInputarea', className]">
+    <div
+      ref="cmEle"
+      :class="[
+        'tagInputareaIuput',
+        'ThemeBorderColor3',
+        !!readonly ? 'readonlyBg' : '',
+      ]"
+    ></div>
+  </div>
+</template>
+<script lang="ts" setup>
+import CodeMirror from "codemirror";
+import "codemirror/lib/codemirror.css";
+import { getRePosFromStr, MODE } from "./util";
+
+const props = defineProps({
+  mode: {
+    type: Number,
+    default: MODE.TEXT,
+  },
+  className: {
+    type: String,
+    default: "",
+  },
+  defaultValue: {
+    type: String,
+    default: "",
+    required: true,
+  },
+  renderTag: {
+    type: Function,
+    required: true,
+  },
+  minHeight: {
+    type: Number,
+    default: 20,
+  },
+  readonly: {
+    type: Boolean,
+    default: false,
+  },
+  noCursor: {
+    type: Boolean,
+    default: false,
+  },
+  operatorsSetMargin: {
+    type: Boolean,
+    default: false,
+  },
+  autoComma: {
+    type: Boolean,
+    default: false,
+  },
+  // 是否禁用复制
+  disabledCopy: {
+    type: Boolean,
+    required: false,
+    default: false,
+  },
+});
+const emit = defineEmits(["onChange", "onBlur", "onFocus"]);
+//编辑器挂载dom节点
+const cmEle = ref();
+
+//编辑器实例
+let cmInstance: any = null;
+
+onMounted(() => {
+  if (cmEle.value) {
+    //编辑器初始化
+    cmInstance = CodeMirror(cmEle.value, {
+      value: props.defaultValue,
+      mode: "",
+      lineWrapping: true,
+      cursorHeight: props.noCursor || props.readonly ? 0 : 1,
+    });
+    //最小高度初始化
+    if (props.minHeight) {
+      let height =
+        typeof props.minHeight === "number"
+          ? `${props.minHeight}px`
+          : props.minHeight;
+      //编辑器高度
+      cmInstance.setSize("100%", height);
+      //编辑内容高度
+      let codeEle = cmEle.value.getElementsByClassName("CodeMirror-code")[0];
+      codeEle && codeEle.setAttribute("style", `min-height:${height}`);
+    }
+    //默认值初始化
+    if (props.defaultValue) {
+      updateTextareaView();
+      cmInstance.execCommand("goDocEnd");
+    }
+    //监听 value change
+    cmInstance.on("change", cmChange);
+    //监听 value beforeChange
+    cmInstance.on("beforeChange", cmBeforeChange);
+    //监听表单聚焦
+    cmInstance.on("focus", () => {
+      cmEle.value.classList.add("active");
+      cmFocus();
+    });
+
+    //监听表单失焦
+    cmInstance.on("blur", () => {
+      if (cmEle.value) {
+        cmEle.value.classList.remove("active");
+      }
+      cmBlur();
+    });
+    if (props.disabledCopy) {
+      // 禁止复制,防止tag复制的是id
+      cmInstance.on("copy", (cm: any, e: Event) => {
+        e.preventDefault();
+      });
+    }
+  }
+});
+
+//编辑器change
+const cmChange = (cm: any, obj: any): void => {
+  let value = cm.getValue();
+  if (obj.origin !== "setValue") {
+    emit("onChange", null, value, obj);
+  }
+
+  updateTextareaView();
+};
+
+//编辑器beforeChange
+const cmBeforeChange = (cm: any, obj: any): any => {
+  let { text } = obj;
+  // 如果是自定义公式,只能允许数字+、-、*、/、( \ ) , .,大写字符
+  if (
+    props.mode === MODE.FORMULA &&
+    (obj.origin === "paste" ||
+      obj.origin === "+input" ||
+      obj.origin === "*compose")
+  ) {
+    text = text.map((t: string) =>
+      t.replace(/[^+\-*\/0-9/a-z/A-Z\(\)\,\.]/gm, "").toUpperCase()
+    );
+    // 最大输入10000字符
+    if (text.map((t: string) => t).join("").length > 10000) {
+      text = text
+        .map((t: string) => t)
+        .join("")
+        .slice(0, 10000)
+        .split(",");
+      obj.update(obj.from, obj.to, text);
+      obj.cancel();
+    }
+  }
+
+  if (obj.origin === "undo" || obj.origin === "redo") {
+    return;
+  }
+  // 事件内,mode只能从每次props取,不然取不到最新
+  if (
+    props.readonly ||
+    (props.mode === MODE.ONLYTAG &&
+      obj.origin !== "+delete" &&
+      obj.origin !== "inserttag" &&
+      obj.origin !== "setValue")
+  ) {
+    obj.cancel();
+  }
+
+  // 事件内,mode只能从每次props取,不然取不到最新
+  if (
+    props.mode === MODE.FORMULA &&
+    obj.origin !== "+delete" &&
+    obj.origin !== "inserttag" &&
+    obj.origin !== "setValue"
+  ) {
+    text = text.map((t: any) =>
+      t
+        .toUpperCase()
+        .split("")
+        .filter((t: any) =>
+          (obj.origin === "paste"
+            ? /[0-9A-Z\+\-\*\/\(\)\,\.\$]/
+            : /[0-9A-Z\+\-\*\/\(\)\,\.]/
+          ).test(t)
+        )
+        .join("")
+    );
+  }
+  if (
+    props.mode === MODE.DATE &&
+    obj.origin !== "+delete" &&
+    obj.origin !== "inserttag" &&
+    obj.origin !== "setValue"
+  ) {
+    text = text.map((t: any) =>
+      t
+        .split("")
+        .filter((t: any) =>
+          (obj.origin === "paste" ? /[0-9YMdhm\+\-\$]/ : /[0-9YMdhm\+\-]/).test(
+            t
+          )
+        )
+        .join("")
+    );
+  }
+  obj.update(obj.from, obj.to, text);
+};
+
+//编辑器 foucus
+const cmFocus = (): void => {
+  emit("onFocus");
+};
+
+//编辑器 blur
+const cmBlur = (): void => {
+  emit("onBlur");
+};
+
+//设置 value
+const setValue = (value: string): void => {
+  // const position = cmInstance.getCursor()
+  cmInstance.setValue(value || "");
+  // const newPosition = {
+  //     line: position.line,
+  //     ch: position.ch + value.length - 2,
+  // }
+
+  // cmInstance.focus()
+  // cmInstance.setCursor(newPosition)
+  // cmInstance.execCommand('goDocEnd')
+};
+const getValue = () => {
+  return cmInstance.getValue();
+};
+//回显,更新渲染
+let markers: any = null;
+const updateTextareaView = () => {
+  const { mode, operatorsSetMargin } = props;
+  const value = cmInstance.getValue();
+  if (markers) {
+    markers.forEach((marker: any) => marker.clear());
+  }
+  markers = [];
+  markColumns(markers, value);
+  if (mode === MODE.FORMULA || operatorsSetMargin) {
+    markOperators(markers, value);
+  }
+};
+
+//光标行
+const markColumns = (markers: any, value: any) => {
+  const poss = getRePosFromStr(value);
+  poss.forEach((pos: any, i: number) => {
+    renderColumnTag(pos.tag, { isLast: i === poss.length - 1 }, (node: any) => {
+      markers.push(
+        cmInstance.markText(
+          { line: pos.line, ch: pos.start },
+          { line: pos.line, ch: pos.stop },
+          { replacedWith: node, handleMouseEvents: true }
+        )
+      );
+    });
+  });
+};
+
+//光标操作
+const markOperators = (markers: any, value: any) => {
+  const poss = getRePosFromStr(value, /\+|\-|\*|\/|\(|\)|,/g);
+  poss.forEach((pos: any, i: number) => {
+    const operatorEle = document.createElement("span");
+    operatorEle.classList.add("operator");
+    operatorEle.innerHTML = pos.tag;
+    markers.push(
+      cmInstance.markText(
+        { line: pos.line, ch: pos.start },
+        { line: pos.line, ch: pos.stop },
+        { replacedWith: operatorEle, handleMouseEvents: true }
+      )
+    );
+  });
+};
+
+//渲染 tag
+const renderColumnTag = (id: any, options: any, cb: any) => {
+  const node = document.createElement("div");
+  node.classList.add("columnTagCon");
+  //自定义渲染tag
+  if (props.renderTag) {
+    const tag = props.renderTag(id, options);
+    if (tag instanceof HTMLElement) {
+      node.appendChild(tag);
+      cb(node);
+      return;
+    }
+  }
+  node.append(id);
+  cb(node);
+  return;
+};
+
+//插入 tag
+const insertColumnTag = (id: string) => {
+  const { mode, autoComma } = props;
+  const position = cmInstance.getCursor();
+  const editorValue = cmInstance.getValue();
+
+  cmInstance.replaceRange(
+    `${
+      mode === MODE.FORMULA && autoComma && editorValue[position.ch - 1] === "$"
+        ? ","
+        : ""
+    }$${id}$`,
+    position,
+    undefined,
+    "inserttag"
+  );
+  cmInstance.focus();
+  cmInstance.execCommand("goDocEnd");
+  if (cmEle.value) {
+    cmEle.value.scrollTop = cmEle.value.scrollHeight - cmEle.value.clientHeight;
+  }
+};
+// 获取光标位置
+const getCursor = () => {
+  return cmInstance.getCursor();
+};
+// 设置光标位置
+const setCustomCursor = (position: { line: number; ch: number }) => {
+  cmInstance.setCursor(position);
+};
+// 插入公式
+const insertFormula = (value: string) => {
+  const { mode, autoComma } = props;
+  const position = cmInstance.getCursor();
+
+  cmInstance.replaceRange(value, position, undefined, "insertFormula");
+  setTimeout(() => {
+    const newPosition = {
+      line: position.line,
+      ch: position.ch + value.length - 2,
+    };
+
+    cmInstance.focus();
+    cmInstance.setCursor(newPosition);
+    // cmInstance.execCommand('goDocEnd')
+  }, 0);
+  if (cmEle.value) {
+    cmEle.value.scrollTop = cmEle.value.scrollHeight - cmEle.value.clientHeight;
+  }
+};
+defineExpose({
+  insertColumnTag,
+});
+</script>
+
+<style lang="scss" scoped>
+.tagInputarea {
+  min-width: 0;
+  :deep {
+    .tagInputareaIuput {
+      border-radius: 3px;
+      border: 1px solid #409eff;
+      overflow: auto;
+
+      &:not(.active) {
+        border-color: #ccc !important;
+      }
+      // &.hasRightIcon {
+      //   border-radius: 3px 0 0 3px;
+      // }
+      &.readonlyBg {
+        .CodeMirror {
+          background-color: #eee !important;
+        }
+      }
+    }
+    // .rightIcon {
+    //   background-color: #f5f5f5;
+    //   font-size: 20px;
+    //   color: #757575;
+    //   height: 34px;
+    //   line-height: 33px;
+    //   padding: 0 7px;
+    //   border: 1px solid #ccc;
+    //   border-left: none;
+    //   border-radius: 0 3px 3px 0;
+    // }
+    .CodeMirror {
+      font-family: inherit !important;
+      box-sizing: border-box;
+      height: auto !important;
+
+      .CodeMirror-vscrollbar {
+        display: none !important;
+      }
+
+      // .CodeMirror-scroll {
+      //     height: auto;
+      //     overflow-y: hidden;
+      //     overflow-x: auto;
+      // }
+
+      .CodeMirror-lines {
+        padding: 6px 0;
+        min-height: 35px;
+      }
+      .CodeMirror-line {
+        padding: 0 10px;
+      }
+      .columnTagCon {
+        position: relative;
+        display: inline-flex;
+        // box-sizing: border-box;
+        // padding: 2px 4px;
+        // max-width: 100%;
+        // background: #d8eeff;
+        // color: #174c76;
+        // border: 1px solid #bbd6ea;
+        // border-radius: 5px;
+      }
+      .columnTag {
+        position: relative;
+        display: inline-flex;
+        box-sizing: border-box;
+        cursor: pointer;
+        height: 24px;
+        font-size: 12px;
+        border: 1px solid #90caf9;
+        border-radius: 24px;
+        .columnName,
+        .columnValue {
+          display: inline-block;
+          height: 22px;
+          line-height: 22px;
+          padding: 0 10px;
+          overflow: hidden;
+        }
+        .columnName {
+          color: #2196f3;
+          background-color: rgba(33, 150, 243, 0.06);
+        }
+        .columnValue {
+          color: #fff;
+          border-radius: 0 22px 22px 0;
+          background-color: #249eff;
+          .ellipsis {
+            max-width: 9em;
+          }
+        }
+        &.onlytag {
+          margin-right: 6px;
+          &:after {
+            content: ",";
+            position: absolute;
+            right: -6px;
+            top: 6px;
+          }
+        }
+        &.deleted {
+          border-color: #f44336;
+          .columnName {
+            color: #f44336;
+            background-color: rgba(244, 67, 54, 0.06);
+          }
+          &:hover {
+            border-color: #f44336;
+            .columnName {
+              color: #f44336;
+              background-color: rgba(244, 67, 54, 0.12);
+            }
+          }
+        }
+        &:hover {
+          border-color: #ddd;
+          .columnName {
+            color: #9e9e9e;
+            background-color: rgba(158, 158, 158, 0.06);
+          }
+          .columnValue {
+            background-color: #bdbdbd;
+          }
+        }
+      }
+      .operator {
+        margin: 0 4px;
+      }
+    }
+  }
+}
+</style>

+ 34 - 0
src/components/TagInput/util.ts

@@ -0,0 +1,34 @@
+/**
+ * getRePosFromStr 正则匹配字段返回位置信息
+ * */
+export function getRePosFromStr(text: any = '', re: any = /\$.+?\$/g) {
+    const lines = text.split('\n')
+    const positions: any = []
+    let m
+    for (let i = 0; i < lines.length; i++) {
+        const l = lines[i]
+        while ((m = re.exec(l)) !== null) {
+            var tag = m[0].substring(1, m[0].length - 1)
+            positions.push({
+                line: i,
+                start: m.index,
+                stop: m.index + m[0].length,
+                tag,
+            })
+        }
+    }
+    return positions
+}
+/**
+ * 输入框模式
+ */
+export enum MODE {
+    // 文本
+    TEXT = 1,
+    // 公式
+    FORMULA,
+    // 只允许选择tag
+    ONLYTAG,
+    // 日期
+    DATE
+}

+ 139 - 0
src/components/Upload/MultiUpload.vue

@@ -0,0 +1,139 @@
+<!--
+  多图上传组件
+  @author: youlaitech
+  @date 2022/11/20
+-->
+
+<template>
+  <el-upload
+    v-model:file-list="fileList"
+    list-type="picture-card"
+    :before-upload="handleBeforeUpload"
+    :http-request="handleUpload"
+    :on-remove="handleRemove"
+    :on-preview="previewImg"
+    :limit="props.limit"
+  >
+    <i-ep-plus />
+  </el-upload>
+
+  <el-dialog v-model="dialogVisible">
+    <img w-full :src="previewImgUrl" alt="Preview Image" />
+  </el-dialog>
+</template>
+
+<script setup lang="ts">
+import {
+  UploadRawFile,
+  UploadRequestOptions,
+  UploadUserFile,
+  UploadFile,
+  UploadProps,
+} from "element-plus";
+import { uploadFileApi, deleteFileApi } from "@/api/file";
+
+const emit = defineEmits(["update:modelValue"]);
+
+const props = defineProps({
+  /**
+   * 文件路径集合
+   */
+  modelValue: {
+    type: Array<string>,
+    default: [] as Array<string>,
+  },
+  /**
+   * 文件上传数量限制
+   */
+  limit: {
+    type: Number,
+    default: 10,
+  },
+});
+
+const previewImgUrl = ref("");
+const dialogVisible = ref(false);
+
+const fileList = ref([] as UploadUserFile[]);
+watch(
+  () => props.modelValue,
+  (newVal: string[]) => {
+    const filePaths = fileList.value.map((file) => file.url);
+    // 监听modelValue文件集合值未变化时,跳过赋值
+    if (
+      filePaths.length > 0 &&
+      filePaths.length === newVal.length &&
+      filePaths.every((x) => newVal.some((y) => y === x)) &&
+      newVal.every((y) => filePaths.some((x) => x === y))
+    ) {
+      return;
+    }
+
+    fileList.value = newVal.map((filePath) => {
+      return { url: filePath } as UploadUserFile;
+    });
+  },
+  { immediate: true }
+);
+
+/**
+ * 自定义图片上传
+ *
+ * @param params
+ */
+async function handleUpload(options: UploadRequestOptions): Promise<any> {
+  // 上传API调用
+  const { data: fileInfo } = await uploadFileApi(options.file);
+
+  // 上传成功需手动替换文件路径为远程URL,否则图片地址为预览地址 blob:http://
+  const fileIndex = fileList.value.findIndex(
+    (file) => file.uid == (options.file as any).uid
+  );
+
+  fileList.value.splice(fileIndex, 1, {
+    name: fileInfo.name,
+    url: fileInfo.url,
+  } as UploadUserFile);
+
+  emit(
+    "update:modelValue",
+    fileList.value.map((file) => file.url)
+  );
+}
+
+/**
+ * 删除图片
+ */
+function handleRemove(removeFile: UploadFile) {
+  const filePath = removeFile.url;
+
+  if (filePath) {
+    deleteFileApi(filePath).then(() => {
+      // 删除成功回调
+      emit(
+        "update:modelValue",
+        fileList.value.map((file) => file.url)
+      );
+    });
+  }
+}
+
+/**
+ * 限制用户上传文件的格式和大小
+ */
+function handleBeforeUpload(file: UploadRawFile) {
+  if (file.size > 2 * 1048 * 1048) {
+    ElMessage.warning("上传图片不能大于2M");
+    return false;
+  }
+  return true;
+}
+
+/**
+ * 预览图片
+ */
+const previewImg: UploadProps["onPreview"] = (uploadFile) => {
+  previewImgUrl.value = uploadFile.url!;
+  dialogVisible.value = true;
+};
+</script>

+ 81 - 0
src/components/Upload/SingleUpload.vue

@@ -0,0 +1,81 @@
+<template>
+  <!-- 上传组件 -->
+  <el-upload
+    v-model="imgUrl"
+    class="single-uploader"
+    :show-file-list="false"
+    list-type="picture-card"
+    :before-upload="handleBeforeUpload"
+    :http-request="uploadFile"
+  >
+    <img v-if="imgUrl" :src="imgUrl" class="single" />
+    <el-icon v-else class="single-uploader-icon"><i-ep-plus /></el-icon>
+  </el-upload>
+</template>
+
+<script setup lang="ts">
+import { UploadRawFile, UploadRequestOptions } from "element-plus";
+import { uploadFileApi } from "@/api/file";
+
+const props = defineProps({
+  modelValue: {
+    type: String,
+    default: "",
+  },
+});
+
+const emit = defineEmits(["update:modelValue"]);
+const imgUrl = useVModel(props, "modelValue", emit);
+
+/**
+ * 自定义图片上传
+ *
+ * @param options
+ */
+async function uploadFile(options: UploadRequestOptions): Promise<any> {
+  const { data: fileInfo } = await uploadFileApi(options.file);
+  imgUrl.value = fileInfo.url;
+}
+
+/**
+ * 限制用户上传文件的格式和大小
+ */
+function handleBeforeUpload(file: UploadRawFile) {
+  if (file.size > 2 * 1048 * 1048) {
+    ElMessage.warning("上传图片不能大于2M");
+    return false;
+  }
+  return true;
+}
+</script>
+
+<style scoped>
+.single-uploader .single {
+  display: block;
+  width: 178px;
+  height: 178px;
+}
+</style>
+
+<style>
+.single-uploader .el-upload {
+  position: relative;
+  overflow: hidden;
+  cursor: pointer;
+  border: 1px dashed var(--el-border-color);
+  border-radius: 6px;
+  transition: var(--el-transition-duration-fast);
+}
+
+.single-uploader .el-upload:hover {
+  border-color: var(--el-color-primary);
+}
+
+.el-icon.single-uploader-icon {
+  width: 178px;
+  height: 178px;
+  font-size: 28px;
+  color: #8c939d;
+  text-align: center;
+}
+</style>

+ 90 - 0
src/components/WangEditor/index.vue

@@ -0,0 +1,90 @@
+<template>
+  <div class="editor-wrapper">
+    <!-- 工具栏 -->
+    <Toolbar
+      id="toolbar-container"
+      :editor="editorRef"
+      :default-config="toolbarConfig"
+      :mode="mode"
+    />
+    <!-- 编辑器 -->
+    <Editor
+      id="editor-container"
+      v-model="modelValue"
+      :default-config="editorConfig"
+      :mode="mode"
+      @on-change="handleChange"
+      @on-created="handleCreated"
+    />
+  </div>
+</template>
+
+<script setup lang="ts">
+import { Editor, Toolbar } from "@wangeditor/editor-for-vue";
+
+// API 引用
+import { uploadFileApi } from "@/api/file";
+
+const props = defineProps({
+  modelValue: {
+    type: [String],
+    default: "",
+  },
+});
+
+const emit = defineEmits(["update:modelValue"]);
+
+const modelValue = useVModel(props, "modelValue", emit);
+
+const editorRef = shallowRef(); // 编辑器实例,必须用 shallowRef
+const mode = ref("default"); // 编辑器模式
+const toolbarConfig = ref({}); // 工具条配置
+// 编辑器配置
+const editorConfig = ref({
+  placeholder: "请输入内容...",
+  MENU_CONF: {
+    uploadImage: {
+      // 自定义图片上传
+      async customUpload(file: any, insertFn: any) {
+        uploadFileApi(file).then((response) => {
+          const url = response.data.url;
+          insertFn(url);
+        });
+      },
+    },
+  },
+});
+
+const handleCreated = (editor: any) => {
+  editorRef.value = editor; // 记录 editor 实例,重要!
+};
+
+function handleChange(editor: any) {
+  modelValue.value = editor.getHtml();
+}
+
+// 组件销毁时,也及时销毁编辑器
+onBeforeUnmount(() => {
+  const editor = editorRef.value;
+  if (editor == null) return;
+  editor.destroy();
+});
+</script>
+
+<style src="@wangeditor/editor/dist/css/style.css"></style>
+
+<style lang="scss" scoped>
+.editor-wrapper {
+  display: flex;
+  flex-direction: column;
+  border: 1px solid #ccc;
+
+  #toolbar-container {
+    border-bottom: 1px solid #ccc;
+  }
+
+  #editor-container {
+    flex-grow: 1;
+  }
+}
+</style>

Nem az összes módosított fájl került megjelenítésre, mert túl sok fájl változott