瀏覽代碼

!245 合并master上1.8.1的修改到master-vxe
Merge pull request !245 from clockdotnet/master-vxe

芋道源码 1 年之前
父節點
當前提交
6ec2ee8af4
共有 100 個文件被更改,包括 1366 次插入1108 次删除
  1. 1 1
      .env.dev
  2. 0 31
      .env.test
  3. 16 18
      .eslintrc.js
  4. 7 3
      .vscode/extensions.json
  5. 25 50
      .vscode/settings.json
  6. 16 16
      README.md
  7. 2 2
      build/vite/index.ts
  8. 3 1
      build/vite/optimize.ts
  9. 55 56
      package.json
  10. 0 0
      public/home.png
  11. 0 5
      src/api/login/index.ts
  12. 49 0
      src/api/mall/product/comment.ts
  13. 6 5
      src/api/mall/product/spu.ts
  14. 64 0
      src/api/mall/promotion/bargain/bargainActivity.ts
  15. 3 5
      src/api/mall/promotion/combination/combinationActivity.ts
  16. 8 0
      src/api/mall/promotion/coupon/coupon.ts
  17. 1 1
      src/api/mall/promotion/coupon/couponTemplate.ts
  18. 1 1
      src/api/mall/promotion/seckill/seckillConfig.ts
  19. 75 0
      src/api/mall/trade/afterSale/index.ts
  20. 5 0
      src/api/mall/trade/delivery/express/index.ts
  21. 6 6
      src/api/mall/trade/delivery/pickUpStore/index.ts
  22. 133 12
      src/api/mall/trade/order/index.ts
  23. 0 228
      src/api/mall/trade/order/type/orderType.ts
  24. 15 0
      src/api/member/address/index.ts
  25. 38 0
      src/api/member/group/index.ts
  26. 42 0
      src/api/member/level/index.ts
  27. 2 2
      src/api/member/point/config/index.ts
  28. 18 0
      src/api/member/point/record/index.ts
  29. 33 0
      src/api/member/signin/config/index.ts
  30. 13 0
      src/api/member/signin/record/index.ts
  31. 36 0
      src/api/member/tag/index.ts
  32. 43 0
      src/api/member/user/index.ts
  33. 11 24
      src/api/pay/app/index.ts
  34. 7 31
      src/api/pay/channel/index.ts
  35. 36 0
      src/api/pay/demo/index.ts
  36. 0 78
      src/api/pay/merchant/index.ts
  37. 16 0
      src/api/pay/notify/index.ts
  38. 7 17
      src/api/pay/order/index.ts
  39. 6 6
      src/api/pay/refund/index.ts
  40. 0 47
      src/api/point/record/index.ts
  41. 0 37
      src/api/point/signInConfig/index.ts
  42. 0 38
      src/api/point/signInRecord/index.ts
  43. 1 1
      src/api/system/permission/index.ts
  44. 1 0
      src/assets/svgs/member_balance.svg
  45. 0 0
      src/assets/svgs/member_expenditure_balance.svg
  46. 1 0
      src/assets/svgs/member_level.svg
  47. 0 0
      src/assets/svgs/member_point.svg
  48. 0 0
      src/assets/svgs/member_recharge_balance.svg
  49. 1 0
      src/assets/svgs/pay/icon/alipay_app.svg
  50. 1 0
      src/assets/svgs/pay/icon/alipay_bar.svg
  51. 1 0
      src/assets/svgs/pay/icon/alipay_pc.svg
  52. 2 0
      src/assets/svgs/pay/icon/alipay_qr.svg
  53. 1 0
      src/assets/svgs/pay/icon/alipay_wap.svg
  54. 1 0
      src/assets/svgs/pay/icon/mock.svg
  55. 2 0
      src/assets/svgs/pay/icon/wx_app.svg
  56. 0 0
      src/assets/svgs/pay/icon/wx_bar.svg
  57. 1 0
      src/assets/svgs/pay/icon/wx_lite.svg
  58. 1 0
      src/assets/svgs/pay/icon/wx_native.svg
  59. 2 0
      src/assets/svgs/pay/icon/wx_pub.svg
  60. 3 0
      src/components/Card/index.ts
  61. 37 0
      src/components/Card/src/CardTitle.vue
  62. 1 1
      src/components/ContentDetailWrap/src/ContentDetailWrap.vue
  63. 3 1
      src/components/Cropper/src/CopperModal.vue
  64. 2 2
      src/components/Cropper/src/CropperAvatar.vue
  65. 2 1
      src/components/Descriptions/index.ts
  66. 2 2
      src/components/Descriptions/src/Descriptions.vue
  67. 29 0
      src/components/Descriptions/src/DescriptionsItemLabel.vue
  68. 50 34
      src/components/Dialog/src/Dialog.vue
  69. 2 3
      src/components/Editor/src/Editor.vue
  70. 3 1
      src/components/InputPassword/src/InputPassword.vue
  71. 14 2
      src/components/Pagination/index.vue
  72. 2 1
      src/config/axios/index.ts
  73. 35 17
      src/hooks/web/useCrudSchemas.ts
  74. 17 10
      src/layout/components/AppView.vue
  75. 1 1
      src/layout/components/Footer/src/Footer.vue
  76. 1 1
      src/layout/components/LocaleDropdown/src/LocaleDropdown.vue
  77. 1 2
      src/layout/components/Logo/src/Logo.vue
  78. 4 13
      src/layout/components/Menu/src/Menu.vue
  79. 6 3
      src/layout/components/Message/src/Message.vue
  80. 0 1
      src/layout/components/Setting/src/Setting.vue
  81. 2 13
      src/layout/components/TabMenu/src/TabMenu.vue
  82. 54 58
      src/layout/components/TagsView/src/TagsView.vue
  83. 7 7
      src/layout/components/ToolHeader.vue
  84. 2 2
      src/layout/components/UserInfo/src/UserInfo.vue
  85. 54 26
      src/layout/components/useRenderLayout.tsx
  86. 2 2
      src/main.ts
  87. 1 0
      src/plugins/unocss/index.ts
  88. 0 3
      src/plugins/windi.css/index.ts
  89. 90 51
      src/router/modules/remaining.ts
  90. 4 7
      src/store/modules/permission.ts
  91. 1 0
      src/store/modules/user.ts
  92. 3 1
      src/styles/index.scss
  93. 6 13
      src/styles/var.css
  94. 55 77
      src/utils/constants.ts
  95. 6 11
      src/utils/dict.ts
  96. 1 1
      src/utils/formatTime.ts
  97. 25 1
      src/utils/index.ts
  98. 2 2
      src/views/Home/Index.vue
  99. 16 12
      src/views/Login/Login.vue
  100. 5 3
      src/views/Profile/components/BasicInfo.vue

+ 1 - 1
.env.dev

@@ -28,4 +28,4 @@ VITE_DROP_CONSOLE=false
 VITE_SOURCEMAP=true
 
 # 输出路径
-VITE_OUT_DIR=dist-dev
+VITE_OUT_DIR=dist

+ 0 - 31
.env.test

@@ -1,31 +0,0 @@
-# 测试环境
-NODE_ENV=production
-
-VITE_DEV=false
-
-# 请求路径
-VITE_BASE_URL='http://localhost:48080'
-
-# 上传路径
-VITE_UPLOAD_URL='http://localhost:48080/admin-api/infra/file/upload'
-
-# 接口前缀
-VITE_API_BASEPATH=
-
-# 接口地址
-VITE_API_URL=/admin-api
-
-# 是否删除debugger
-VITE_DROP_DEBUGGER=false
-
-# 是否删除console.log
-VITE_DROP_CONSOLE=false
-
-# 是否sourcemap
-VITE_SOURCEMAP=true
-
-# 打包路径
-VITE_BASE_PATH=/
-
-# 输出路径
-VITE_OUT_DIR=dist-test

+ 16 - 18
.eslintrc.js

@@ -1,4 +1,6 @@
-module.exports = {
+// @ts-check
+const { defineConfig } = require('eslint-define-config')
+module.exports = defineConfig({
   root: true,
   env: {
     browser: true,
@@ -16,9 +18,16 @@ module.exports = {
       jsx: true
     }
   },
-  extends: ['plugin:vue/vue3-recommended', 'prettier', 'plugin:@typescript-eslint/recommended', 'plugin:prettier/recommended'],
+  extends: [
+    'plugin:vue/vue3-recommended',
+    'plugin:@typescript-eslint/recommended',
+    'prettier',
+    'plugin:prettier/recommended'
+  ],
   rules: {
     'vue/script-setup-uses-vars': 'error',
+    'vue/no-reserved-component-names': 'off',
+    'vue/no-setup-props-destructure': 'off',
     '@typescript-eslint/ban-ts-ignore': 'off',
     '@typescript-eslint/explicit-function-return-type': 'off',
     '@typescript-eslint/no-explicit-any': 'off',
@@ -31,20 +40,8 @@ module.exports = {
     '@typescript-eslint/ban-types': 'off',
     '@typescript-eslint/no-non-null-assertion': 'off',
     '@typescript-eslint/explicit-module-boundary-types': 'off',
-    '@typescript-eslint/no-unused-vars': [
-      'error',
-      {
-        argsIgnorePattern: '^_',
-        varsIgnorePattern: '^_'
-      }
-    ],
-    'no-unused-vars': [
-      'error',
-      {
-        argsIgnorePattern: '^_',
-        varsIgnorePattern: '^_'
-      }
-    ],
+    '@typescript-eslint/no-unused-vars': 'off',
+    'no-unused-vars': 'off',
     'space-before-function-paren': 'off',
 
     'vue/attributes-order': 'off',
@@ -68,6 +65,7 @@ module.exports = {
         math: 'always'
       }
     ],
-    'vue/multi-word-component-names': 'off'
+    'vue/multi-word-component-names': 'off',
+    'vue/no-v-html': 'off'
   }
-}
+})

+ 7 - 3
.vscode/extensions.json

@@ -1,15 +1,19 @@
 {
   "recommendations": [
-    "voorjaar.windicss-intellisense",
+    "christian-kohler.path-intellisense",
     "vscode-icons-team.vscode-icons",
     "davidanson.vscode-markdownlint",
     "stylelint.vscode-stylelint",
     "dbaeumer.vscode-eslint",
     "esbenp.prettier-vscode",
-    "vue.volar",
+    "mrmlnc.vscode-less",
     "lokalise.i18n-ally",
+    "redhat.vscode-yaml",
+    "csstools.postcss",
     "mikestead.dotenv",
     "eamodio.gitlens",
-    "antfu.iconify"
+    "antfu.iconify",
+    "antfu.unocss",
+    "Vue.volar"
   ]
 }

+ 25 - 50
.vscode/settings.json

@@ -1,7 +1,5 @@
 {
   "typescript.tsdk": "./node_modules/typescript/lib",
-  "volar.tsPlugin": true,
-  "volar.tsPluginStatus": false,
   "npm.packageManager": "pnpm",
   "editor.tabSize": 2,
   "prettier.printWidth": 100, // 超过最大值换行
@@ -102,59 +100,35 @@
   "i18n-ally.displayLanguage": "zh-CN",
   "i18n-ally.enabledFrameworks": ["vue", "react"],
   "cSpell.words": [
-    "vben",
-    "windicss",
-    "tailwind",
+    "brotli",
     "browserslist",
-    "tailwindcss",
+    "codemirror",
+    "commitlint",
+    "cropperjs",
+    "echarts",
     "esnext",
-    "antv",
-    "tinymce",
-    "qrcode",
-    "sider",
+    "esno",
+    "iconify",
+    "INTLIFY",
+    "lintstagedrc",
+    "logicflow",
+    "nprogress",
     "pinia",
+    "pnpm",
+    "qrcode",
     "sider",
-    "nprogress",
-    "INTLIFY",
+    "sortablejs",
     "stylelint",
-    "esno",
+    "unocss",
+    "unplugin",
+    "unref",
+    "videojs",
     "vitejs",
-    "sortablejs",
-    "codemirror",
-    "iconify",
-    "commitlint",
-    "vditor",
-    "echarts",
-    "cropperjs",
-    "logicflow",
     "vueuse",
-    "zxcvbn",
-    "lintstagedrc",
-    "brotli",
-    "sider",
-    "pnpm",
-    "antd"
-  ],
-  "vetur.format.scriptInitialIndent": true,
-  "vetur.format.styleInitialIndent": true,
-  "vetur.validation.script": false,
-  "MicroPython.executeButton": [
-    {
-      "text": "▶",
-      "tooltip": "运行",
-      "alignment": "left",
-      "command": "extension.executeFile",
-      "priority": 3.5
-    }
-  ],
-  "MicroPython.syncButton": [
-    {
-      "text": "$(sync)",
-      "tooltip": "同步",
-      "alignment": "left",
-      "command": "extension.execute",
-      "priority": 4
-    }
+    "wangeditor",
+    "xingyu",
+    "yudao",
+    "zxcvbn"
   ],
   // 控制相关文件嵌套展示
   "explorer.fileNesting.enabled": true,
@@ -163,7 +137,8 @@
     "*.ts": "$(capture).test.ts, $(capture).test.tsx",
     "*.tsx": "$(capture).test.ts, $(capture).test.tsx",
     "*.env": "$(capture).env.*",
-    "package.json": "pnpm-lock.yaml,yarn.lock,LICENSE,README*,CHANGELOG*,CNAME,.gitattributes,.gitignore,prettier.config.js,stylelint.config.js,commitlint.config.js,.stylelintignore,.prettierignore,.gitpod.yml,.eslintrc.js,.eslintignore"
+    "package.json": "pnpm-lock.yaml,yarn.lock,LICENSE,README*,CHANGELOG*,CNAME,.gitattributes,.eslintrc-auto-import.json,.gitignore,prettier.config.js,stylelint.config.js,commitlint.config.js,.stylelintignore,.prettierignore,.gitpod.yml,.eslintrc.js,.eslintignore"
   },
-  "terminal.integrated.scrollback": 10000
+  "terminal.integrated.scrollback": 10000,
+  "nuxt.isNuxtApp": false
 }

+ 16 - 16
README.md

@@ -9,7 +9,7 @@
 
 ## 🐶 新手必读
 
-* nodejs > 16.0.0 && pnpm > 8.6.0 (强制使用pnpm)
+* nodejs > 16.18.0 && pnpm > 8.6.0 (强制使用pnpm)
 * 演示地址【Vue3 + element-plus】:<http://dashboard-vue3.yudao.iocoder.cn>
 * 演示地址【Vue3 + vben(ant-design-vue)】:<http://dashboard-vben.yudao.iocoder.cn>
 * 演示地址【Vue2 + element-ui】:<http://dashboard.yudao.iocoder.cn>
@@ -24,7 +24,7 @@
 * 改换 saas,自动引入等功能
 * 使用 Element Plus 免费开源的中后台模版,具备如下特性:
 
-![首页](preview/home.png)
+![首页](public/home.png)
 
 * **最新技术栈**:使用 Vue3、Vite4 等前端前沿技术开发
 * **TypeScript**: 应用程序级 JavaScript 的语言
@@ -39,15 +39,15 @@
 | 框架                                                                   | 说明               | 版本     |
 |----------------------------------------------------------------------|------------------|--------|
 | [Vue](https://staging-cn.vuejs.org/)                                 | Vue 框架           | 3.3.4 |
-| [Vite](https://cn.vitejs.dev//)                                      | 开发与构建工具          | 4.3.9  |
-| [Element Plus](https://element-plus.org/zh-CN/)                      | Element Plus     | 2.3.7 |
-| [TypeScript](https://www.typescriptlang.org/docs/)                   | JavaScript 的超集   | 5.0.4  |
-| [pinia](https://pinia.vuejs.org/)                                    | Vue 存储库 替代 vuex5 | 2.1.4 |
-| [vueuse](https://vueuse.org/)                                        | 常用工具集            | 10.2.0 |
+| [Vite](https://cn.vitejs.dev//)                                      | 开发与构建工具          | 4.4.9  |
+| [Element Plus](https://element-plus.org/zh-CN/)                      | Element Plus     | 2.3.12 |
+| [TypeScript](https://www.typescriptlang.org/docs/)                   | JavaScript 的超集   | 5.1.6  |
+| [pinia](https://pinia.vuejs.org/)                                    | Vue 存储库 替代 vuex5 | 2.1.6 |
+| [vueuse](https://vueuse.org/)                                        | 常用工具集            | 10.4.1 |
 | [vue-i18n](https://kazupon.github.io/vue-i18n/zh/introduction.html/) | 国际化              | 9.2.2  |
-| [vue-router](https://router.vuejs.org/)                              | Vue 路由           | 4.2.1  |
-| [windicss](https://cn.windicss.org/)                                 | 下一代工具优先的 CSS 框架  | 3.5.6  |
-| [iconify](https://icon-sets.iconify.design/)                         | 在线图标库            | 3.1.0  |
+| [vue-router](https://router.vuejs.org/)                              | Vue 路由           | 4.2.4  |
+| [unocss](https://uno.antfu.me/)                                      | 原子 css          | 0.55.7  |
+| [iconify](https://icon-sets.iconify.design/)                         | 在线图标库            | 3.1.1  |
 | [wangeditor](https://www.wangeditor.com/)                            | 富文本编辑器           | 5.1.23 |
 
 ## 开发工具
@@ -56,14 +56,14 @@
 
 | 插件名                           | 功能                       |
 |-------------------------------|--------------------------|
-| TypeScript Vue Plugin (Volar) | 用于 TypeScript 的 Vue 插件   |
+| TypeScript Vue Plugin (Volar) | 用于 TypeScript 的 Vue 插件  |
 | Vue Language Features (Volar) | Vue3.0 语法支持              |
-| WindiCSS IntelliSense         | 自动完成、语法突出显示、代码折叠和构建等高级功能 |
-| Iconify IntelliSense          | Iconify 预览和搜索            |
-| i18n Ally                     | 国际化智能提示                  |
+| unocss                        | unocss for vscode           |
+| Iconify IntelliSense          | Iconify 预览和搜索           |
+| i18n Ally                     | 国际化智能提示               |
 | Stylelint                     | Css    格式化               |
-| Prettier                      | 代码格式化                    |
-| ESLint                        | 脚本代码检查                   |
+| Prettier                      | 代码格式化                   |
+| ESLint                        | 脚本代码检查                  |
 | DotENV                        | env 文件高亮                 |
 
 ## 内置功能

+ 2 - 2
build/vite/index.ts

@@ -1,7 +1,6 @@
 import { resolve } from 'path'
 import Vue from '@vitejs/plugin-vue'
 import VueJsx from '@vitejs/plugin-vue-jsx'
-import WindiCSS from 'vite-plugin-windicss'
 import progress from 'vite-plugin-progress'
 import EslintPlugin from 'vite-plugin-eslint'
 import PurgeIcons from 'vite-plugin-purge-icons'
@@ -14,6 +13,7 @@ import viteCompression from 'vite-plugin-compression'
 import topLevelAwait from 'vite-plugin-top-level-await'
 import VueI18nPlugin from '@intlify/unplugin-vue-i18n/vite'
 import { createSvgIconsPlugin } from 'vite-plugin-svg-icons'
+import UnoCSS from 'unocss/vite'
 
 export function createVitePlugins() {
   const root = process.cwd()
@@ -24,7 +24,7 @@ export function createVitePlugins() {
   return [
     Vue(),
     VueJsx(),
-    WindiCSS(),
+    UnoCSS(),
     progress(),
     PurgeIcons(),
     ElementPlus({}),

+ 3 - 1
build/vite/optimize.ts

@@ -8,7 +8,7 @@ const include = [
   'pinia',
   'dayjs',
   'qrcode',
-  'windicss',
+  'unocss',
   'vue-router',
   'vue-types',
   'vue-i18n',
@@ -37,6 +37,8 @@ const include = [
   'element-plus/es',
   'element-plus/es/locale/lang/zh-cn',
   'element-plus/es/locale/lang/en',
+  'element-plus/es/components/avatar/style/css',
+  'element-plus/es/components/space/style/css',
   'element-plus/es/components/backtop/style/css',
   'element-plus/es/components/form/style/css',
   'element-plus/es/components/radio-group/style/css',

+ 55 - 56
package.json

@@ -1,6 +1,6 @@
 {
   "name": "yudao-ui-admin-vue3",
-  "version": "1.8.0-snapshot",
+  "version": "1.8.1-snapshot",
   "description": "基于vue3、vite4、element-plus、typesScript",
   "author": "xingyu",
   "private": false,
@@ -11,64 +11,61 @@
     "ts:check": "vue-tsc --noEmit",
     "build:pro": "node --max_old_space_size=8192 ./node_modules/vite/bin/vite.js build --mode pro",
     "build:dev": "node --max_old_space_size=8192 ./node_modules/vite/bin/vite.js build --mode dev",
+    "build:base": "node --max_old_space_size=8192 ./node_modules/vite/bin/vite.js build --mode base",
     "build:stage": "node --max_old_space_size=8192 ./node_modules/vite/bin/vite.js build --mode stage",
-    "build:test": "node --max_old_space_size=8192 ./node_modules/vite/bin/vite.js build --mode test",
     "build:static": "node --max_old_space_size=8192 ./node_modules/vite/bin/vite.js build --mode static",
     "build:front": "node --max_old_space_size=8192 ./node_modules/vite/bin/vite.js build --mode front",
     "serve:pro": "vite preview --mode pro",
     "serve:dev": "vite preview --mode dev",
-    "serve:test": "vite preview --mode test",
-    "preview": "pnpm build && vite preview",
-    "npm:check": "npx npm-check-updates",
+    "preview": "pnpm build:base && vite preview",
     "clean": "npx rimraf node_modules",
     "clean:cache": "npx rimraf node_modules/.cache",
     "lint:eslint": "eslint --fix --ext .js,.ts,.vue ./src",
     "lint:format": "prettier --write --loglevel warn \"src/**/*.{js,ts,json,tsx,css,less,scss,vue,html,md}\"",
-    "lint:style": "stylelint --fix \"**/*.{vue,less,postcss,css,scss}\" --cache --cache-location node_modules/.cache/stylelint/",
-    "lint:lint-staged": "lint-staged -c ",
-    "lint:pretty": "pretty-quick --staged"
+    "lint:style": "stylelint --fix \"./src/**/*.{vue,less,postcss,css,scss}\" --cache --cache-location node_modules/.cache/stylelint/",
+    "lint:lint-staged": "lint-staged -c "
   },
   "dependencies": {
     "@element-plus/icons-vue": "^2.1.0",
     "@form-create/designer": "^3.1.3",
-    "@form-create/element-ui": "^3.1.18",
+    "@form-create/element-ui": "^3.1.24",
     "@iconify/iconify": "^3.1.1",
     "@videojs-player/vue": "^1.0.0",
-    "@vueuse/core": "^10.2.1",
+    "@vueuse/core": "^10.4.1",
     "@wangeditor/editor": "^5.1.23",
     "@wangeditor/editor-for-vue": "^5.1.10",
-    "@zxcvbn-ts/core": "^3.0.2",
+    "@zxcvbn-ts/core": "^3.0.3",
     "animate.css": "^4.1.1",
-    "axios": "^1.4.0",
+    "axios": "^1.5.0",
     "benz-amr-recorder": "^1.1.5",
     "bpmn-js-token-simulation": "^0.10.0",
     "camunda-bpmn-moddle": "^7.0.1",
-    "cropperjs": "^1.5.13",
+    "cropperjs": "^1.6.0",
     "crypto-js": "^4.1.1",
     "dayjs": "^1.11.9",
-    "diagram-js": "^11.6.0",
-    "echarts": "^5.4.2",
+    "diagram-js": "^12.3.0",
+    "echarts": "^5.4.3",
     "echarts-wordcloud": "^2.1.0",
-    "element-plus": "2.3.7",
-    "fast-xml-parser": "^4.2.5",
+    "element-plus": "2.3.12",
+    "fast-xml-parser": "^4.2.7",
     "highlight.js": "^11.8.0",
-    "intro.js": "^7.0.1",
+    "intro.js": "^7.2.0",
     "jsencrypt": "^3.3.2",
     "lodash-es": "^4.17.21",
     "min-dash": "^4.1.1",
     "mitt": "^3.0.1",
     "nprogress": "^0.2.0",
-    "pinia": "^2.1.4",
+    "pinia": "^2.1.6",
     "qrcode": "^1.5.3",
     "qs": "^6.11.2",
     "steady-xml": "^0.1.0",
-    "url": "^0.11.1",
-    "video.js": "^8.3.0",
+    "url": "^0.11.2",
+    "video.js": "^7.21.5",
     "vue": "3.3.4",
     "vue-dompurify-html": "^4.1.4",
     "vue-i18n": "9.2.2",
     "vue-router": "^4.2.4",
-    "vue-types": "^5.1.0",
+    "vue-types": "^5.1.1",
     "vuedraggable": "^4.1.0",
     "vxe-table": "^4.3.11",
     "web-storage-cache": "^1.1.1",
@@ -76,50 +73,53 @@
     "xml-js": "^1.6.11"
   },
   "devDependencies": {
-    "@commitlint/cli": "^17.6.6",
-    "@commitlint/config-conventional": "^17.6.6",
-    "@iconify/json": "^2.2.87",
-    "@intlify/unplugin-vue-i18n": "^0.12.1",
+    "@commitlint/cli": "^17.7.1",
+    "@commitlint/config-conventional": "^17.7.0",
+    "@iconify/json": "^2.2.114",
+    "@intlify/unplugin-vue-i18n": "^1.0.1",
     "@purge-icons/generated": "^0.9.0",
     "@types/intro.js": "^5.1.1",
-    "@types/lodash-es": "^4.17.7",
-    "@types/node": "^20.4.1",
+    "@types/lodash-es": "^4.17.9",
+    "@types/node": "^20.6.0",
     "@types/nprogress": "^0.2.0",
-    "@types/qrcode": "^1.5.1",
-    "@types/qs": "^6.9.7",
-    "@typescript-eslint/eslint-plugin": "^5.61.0",
-    "@typescript-eslint/parser": "^5.61.0",
-    "@vitejs/plugin-legacy": "^4.1.0",
-    "@vitejs/plugin-vue": "^4.2.3",
-    "@vitejs/plugin-vue-jsx": "^3.0.1",
-    "autoprefixer": "^10.4.14",
+    "@types/qrcode": "^1.5.2",
+    "@types/qs": "^6.9.8",
+    "@typescript-eslint/eslint-plugin": "^6.6.0",
+    "@typescript-eslint/parser": "^6.6.0",
+    "@unocss/transformer-variant-group": "^0.55.7",
+    "@vitejs/plugin-legacy": "^4.1.1",
+    "@vitejs/plugin-vue": "^4.3.4",
+    "@vitejs/plugin-vue-jsx": "^3.0.2",
+    "@vue-macros/volar": "^0.14.3",
+    "autoprefixer": "^10.4.15",
     "bpmn-js": "^8.9.0",
     "bpmn-js-properties-panel": "^0.46.0",
     "consola": "^3.2.3",
-    "eslint": "^8.44.0",
-    "eslint-config-prettier": "^8.8.0",
-    "eslint-define-config": "^1.21.0",
-    "eslint-plugin-prettier": "^4.2.1",
-    "eslint-plugin-vue": "^9.15.1",
-    "lint-staged": "^13.2.3",
-    "postcss": "^8.4.25",
+    "eslint": "^8.49.0",
+    "eslint-config-prettier": "^9.0.0",
+    "eslint-define-config": "^1.23.0",
+    "eslint-plugin-prettier": "^5.0.0",
+    "eslint-plugin-vue": "^9.17.0",
+    "lint-staged": "^14.0.1",
+    "postcss": "^8.4.29",
     "postcss-html": "^1.5.0",
-    "postcss-scss": "^4.0.6",
-    "prettier": "^2.8.8",
+    "postcss-scss": "^4.0.8",
+    "prettier": "^3.0.3",
     "rimraf": "^5.0.1",
-    "rollup": "^3.26.2",
-    "sass": "^1.63.6",
-    "stylelint": "^15.10.1",
+    "rollup": "^3.29.1",
+    "sass": "^1.66.1",
+    "stylelint": "^15.10.3",
+    "stylelint-config-html": "^1.1.0",
     "stylelint-config-recommended": "^13.0.0",
-    "stylelint-config-recommended-vue": "^1.4.0",
     "stylelint-config-standard": "^34.0.0",
     "stylelint-order": "^6.0.3",
-    "terser": "^5.18.2",
+    "terser": "^5.19.4",
     "typescript": "5.1.6",
+    "unocss": "^0.55.7",
     "unplugin-auto-import": "^0.16.6",
-    "unplugin-element-plus": "^0.7.2",
-    "unplugin-vue-components": "^0.25.1",
-    "vite": "4.4.2",
+    "unplugin-element-plus": "^0.8.0",
+    "unplugin-vue-components": "^0.25.2",
+    "vite": "4.4.9",
     "vite-plugin-compression": "^0.5.1",
     "vite-plugin-ejs": "^1.6.4",
     "vite-plugin-eslint": "^1.8.1",
@@ -127,9 +127,8 @@
     "vite-plugin-purge-icons": "^0.9.2",
     "vite-plugin-svg-icons": "^2.0.1",
     "vite-plugin-top-level-await": "^1.3.1",
-    "vite-plugin-windicss": "^1.9.0",
-    "vue-tsc": "^1.8.4",
-    "windicss": "^3.5.6"
+    "vue-eslint-parser": "^9.3.1",
+    "vue-tsc": "^1.8.10"
   },
   "license": "MIT",
   "repository": {

+ 0 - 0
preview/home.png → public/home.png


+ 0 - 5
src/api/login/index.ts

@@ -37,11 +37,6 @@ export const getInfoApi = () => {
   return request.get({ url: '/system/auth/get-permission-info' })
 }
 
-// 路由
-export const getAsyncRoutesApi = () => {
-  return request.get({ url: '/system/auth/list-menus' })
-}
-
 //获取登录验证码
 export const sendSmsCodeApi = (data: SmsCodeVO) => {
   return request.post({ url: '/system/auth/send-sms-code', data })

+ 49 - 0
src/api/mall/product/comment.ts

@@ -0,0 +1,49 @@
+import request from '@/config/axios'
+
+export interface CommentVO {
+  id: number
+  userId: number
+  userNickname: string
+  userAvatar: string
+  anonymous: boolean
+  orderId: number
+  orderItemId: number
+  spuId: number
+  spuName: string
+  skuId: number
+  visible: boolean
+  scores: number
+  descriptionScores: number
+  benefitScores: number
+  content: string
+  picUrls: string
+  replyStatus: boolean
+  replyUserId: number
+  replyContent: string
+  replyTime: Date
+}
+
+// 查询商品评论列表
+export const getCommentPage = async (params) => {
+  return await request.get({ url: `/product/comment/page`, params })
+}
+
+// 查询商品评论详情
+export const getComment = async (id: number) => {
+  return await request.get({ url: `/product/comment/get?id=` + id })
+}
+
+// 添加自评
+export const createComment = async (data: CommentVO) => {
+  return await request.post({ url: `/product/comment/create`, data })
+}
+
+// 显示 / 隐藏评论
+export const updateCommentVisible = async (data: any) => {
+  return await request.put({ url: `/product/comment/update-visible`, data })
+}
+
+// 商家回复
+export const replyComment = async (data: any) => {
+  return await request.put({ url: `/product/comment/reply`, data })
+}

+ 6 - 5
src/api/mall/product/spu.ts

@@ -9,18 +9,19 @@ export interface Property {
 
 export interface Sku {
   id?: number // 商品 SKU 编号
+  name?: string // 商品 SKU 名称
   spuId?: number // SPU 编号
   properties?: Property[] // 属性数组
-  price?: number // 商品价格
-  marketPrice?: number // 市场价
-  costPrice?: number // 成本价
+  price?: number | string // 商品价格
+  marketPrice?: number | string // 市场价
+  costPrice?: number | string // 成本价
   barCode?: string // 商品条码
   picUrl?: string // 图片地址
   stock?: number // 库存
   weight?: number // 商品重量,单位:kg 千克
   volume?: number // 商品体积,单位:m^3 平米
-  subCommissionFirstPrice?: number // 一级分销的佣金
-  subCommissionSecondPrice?: number // 二级分销的佣金
+  subCommissionFirstPrice?: number | string // 一级分销的佣金
+  subCommissionSecondPrice?: number | string // 二级分销的佣金
   salesCount?: number // 商品销量
 }
 

+ 64 - 0
src/api/mall/promotion/bargain/bargainActivity.ts

@@ -0,0 +1,64 @@
+import request from '@/config/axios'
+import { Sku, Spu } from '@/api/mall/product/spu'
+
+export interface BargainActivityVO {
+  id?: number
+  name?: string
+  startTime?: Date
+  endTime?: Date
+  status?: number
+  userSize?: number // 达到该人数,才能砍到低价
+  bargainCount?: number // 最大帮砍次数
+  totalLimitCount?: number // 最大购买次数
+  spuId: number
+  skuId: number
+  bargainFirstPrice: number // 砍价起始价格,单位分
+  bargainPrice: number // 砍价底价
+  stock: number // 活动库存
+  randomMinPrice?: number // 用户每次砍价的最小金额,单位:分
+  randomMaxPrice?: number // 用户每次砍价的最大金额,单位:分
+  successCount?: number // 砍价成功数量
+}
+
+// 砍价活动所需属性。选择的商品和属性的时候使用方便使用活动的通用封装
+export interface BargainProductVO {
+  spuId: number
+  skuId: number
+  bargainFirstPrice: number // 砍价起始价格,单位分
+  bargainPrice: number // 砍价底价
+  stock: number // 活动库存
+}
+
+// 扩展 Sku 配置
+export type SkuExtension = Sku & {
+  productConfig: BargainProductVO
+}
+
+export interface SpuExtension extends Spu {
+  skus: SkuExtension[] // 重写类型
+}
+
+// 查询砍价活动列表
+export const getBargainActivityPage = async (params: any) => {
+  return await request.get({ url: '/promotion/bargain-activity/page', params })
+}
+
+// 查询砍价活动详情
+export const getBargainActivity = async (id: number) => {
+  return await request.get({ url: '/promotion/bargain-activity/get?id=' + id })
+}
+
+// 新增砍价活动
+export const createBargainActivity = async (data: BargainActivityVO) => {
+  return await request.post({ url: '/promotion/bargain-activity/create', data })
+}
+
+// 修改砍价活动
+export const updateBargainActivity = async (data: BargainActivityVO) => {
+  return await request.put({ url: '/promotion/bargain-activity/update', data })
+}
+
+// 删除砍价活动
+export const deleteBargainActivity = async (id: number) => {
+  return await request.delete({ url: '/promotion/bargain-activity/delete?id=' + id })
+}

+ 3 - 5
src/api/mall/promotion/combination/combinationactivity.ts → src/api/mall/promotion/combination/combinationActivity.ts

@@ -1,8 +1,6 @@
 import request from '@/config/axios'
 import { Sku, Spu } from '@/api/mall/product/spu'
 
-// TODO @puhui999: combinationActivity.ts
-
 export interface CombinationActivityVO {
   id?: number
   name?: string
@@ -12,8 +10,8 @@ export interface CombinationActivityVO {
   startTime?: Date
   endTime?: Date
   userSize?: number
-  totalNum?: number
-  successNum?: number
+  totalCount?: number
+  successCount?: number
   orderUserCount?: number
   virtualGroup?: number
   status?: number
@@ -25,7 +23,7 @@ export interface CombinationActivityVO {
 export interface CombinationProductVO {
   spuId: number
   skuId: number
-  activePrice: number // 拼团价格
+  combinationPrice: number // 拼团价格
 }
 
 // 扩展 Sku 配置

+ 8 - 0
src/api/mall/promotion/coupon.ts → src/api/mall/promotion/coupon/coupon.ts

@@ -16,3 +16,11 @@ export const getCouponPage = async (params: PageParam) => {
     params: params
   })
 }
+
+// 发送优惠券
+export const sendCoupon = async (data: any) => {
+  return request.post({
+    url: '/promotion/coupon/send',
+    data: data
+  })
+}

+ 1 - 1
src/api/mall/promotion/couponTemplate.ts → src/api/mall/promotion/coupon/couponTemplate.ts

@@ -9,7 +9,7 @@ export interface CouponTemplateVO {
   takeType: number
   usePrice: number
   productScope: number
-  productSpuIds: string
+  productScopeValues: number[]
   validityType: number
   validStartTime: Date
   validEndTime: Date

+ 1 - 1
src/api/mall/promotion/seckill/seckillConfig.ts

@@ -20,7 +20,7 @@ export const getSeckillConfig = async (id: number) => {
 }
 
 // 获得所有开启状态的秒杀时段精简列表
-export const getListAllSimple = async () => {
+export const getSimpleSeckillConfigList = async () => {
   return await request.get({ url: '/promotion/seckill-config/list-all-simple' })
 }
 

+ 75 - 0
src/api/mall/trade/afterSale/index.ts

@@ -0,0 +1,75 @@
+import request from '@/config/axios'
+
+export interface TradeAfterSaleVO {
+  id?: number | null // 售后编号,主键自增
+  no?: string // 售后单号
+  status?: number | null // 退款状态
+  way?: number | null // 售后方式
+  type?: number | null // 售后类型
+  userId?: number | null // 用户编号
+  applyReason?: string // 申请原因
+  applyDescription?: string // 补充描述
+  applyPicUrls?: string[] // 补充凭证图片
+  orderId?: number | null // 交易订单编号
+  orderNo?: string // 订单流水号
+  orderItemId?: number | null // 交易订单项编号
+  spuId?: number | null // 商品 SPU 编号
+  spuName?: string // 商品 SPU 名称
+  skuId?: number | null // 商品 SKU 编号
+  properties?: ProductPropertiesVO[] // 属性数组
+  picUrl?: string // 商品图片
+  count?: number | null // 退货商品数量
+  auditTime?: Date // 审批时间
+  auditUserId?: number | null // 审批人
+  auditReason?: string // 审批备注
+  refundPrice?: number | null // 退款金额,单位:分。
+  payRefundId?: number | null // 支付退款编号
+  refundTime?: Date // 退款时间
+  logisticsId?: number | null // 退货物流公司编号
+  logisticsNo?: string // 退货物流单号
+  deliveryTime?: Date // 退货时间
+  receiveTime?: Date // 收货时间
+  receiveReason?: string // 收货备注
+}
+
+export interface ProductPropertiesVO {
+  propertyId?: number | null // 属性的编号
+  propertyName?: string // 属性的名称
+  valueId?: number | null //属性值的编号
+  valueName?: string // 属性值的名称
+}
+
+// 获得交易售后分页
+export const getAfterSalePage = async (params) => {
+  return await request.get({ url: `/trade/after-sale/page`, params })
+}
+
+// 获得交易售后详情
+export const getAfterSale = async (id: any) => {
+  return await request.get({ url: `/trade/after-sale/get-detail?id=${id}` })
+}
+
+// 同意售后
+export const agree = async (id: any) => {
+  return await request.put({ url: `/trade/after-sale/agree?id=${id}` })
+}
+
+// 拒绝售后
+export const disagree = async (data: any) => {
+  return await request.put({ url: `/trade/after-sale/disagree`, data })
+}
+
+// 确认收货
+export const receive = async (id: any) => {
+  return await request.put({ url: `/trade/after-sale/receive?id=${id}` })
+}
+
+// 拒绝收货
+export const refuse = async (id: any) => {
+  return await request.put({ url: `/trade/after-sale/refuse?id=${id}` })
+}
+
+// 确认退款
+export const refund = async (id: any) => {
+  return await request.put({ url: `/trade/after-sale/refund?id=${id}` })
+}

+ 5 - 0
src/api/mall/trade/delivery/express/index.ts

@@ -19,6 +19,11 @@ export const getDeliveryExpress = async (id: number) => {
   return await request.get({ url: '/trade/delivery/express/get?id=' + id })
 }
 
+// 获得快递公司精简信息列表
+export const getSimpleDeliveryExpressList = () => {
+  return request.get({ url: '/trade/delivery/express/list-all-simple' })
+}
+
 // 新增快递公司
 export const createDeliveryExpress = async (data: DeliveryExpressVO) => {
   return await request.post({ url: '/trade/delivery/express/create', data })

+ 6 - 6
src/api/mall/trade/delivery/pickUpStore/index.ts

@@ -16,7 +16,7 @@ export interface DeliveryPickUpStoreVO {
 }
 
 // 查询自提门店列表
-export const getDeliveryPickUpStorePage = async (params: DeliveryPickUpStorePageReqVO) => {
+export const getDeliveryPickUpStorePage = async (params) => {
   return await request.get({ url: '/trade/delivery/pick-up-store/page', params })
 }
 
@@ -25,6 +25,11 @@ export const getDeliveryPickUpStore = async (id: number) => {
   return await request.get({ url: '/trade/delivery/pick-up-store/get?id=' + id })
 }
 
+// 查询自提门店精简列表
+export const getListAllSimple = async () => {
+  return await request.get({ url: '/trade/delivery/pick-up-store/list-all-simple' })
+}
+
 // 新增自提门店
 export const createDeliveryPickUpStore = async (data: DeliveryPickUpStoreVO) => {
   return await request.post({ url: '/trade/delivery/pick-up-store/create', data })
@@ -39,8 +44,3 @@ export const updateDeliveryPickUpStore = async (data: DeliveryPickUpStoreVO) =>
 export const deleteDeliveryPickUpStore = async (id: number) => {
   return await request.delete({ url: '/trade/delivery/pick-up-store/delete?id=' + id })
 }
-
-// 导出自提门店 Excel
-export const exportDeliveryPickUpStoreApi = async (params) => {
-  return await request.download({ url: '/trade/delivery/pick-up-store/export-excel', params })
-}

+ 133 - 12
src/api/mall/trade/order/index.ts

@@ -1,12 +1,133 @@
-import request from '@/config/axios'
-
-// 获得交易订单分页
-// TODO @xiaobai:改成 getOrderPage
-export const getOrderList = (params: PageParam) => {
-  return request.get({ url: '/trade/order/page', params })
-}
-
-// 获得交易订单详情
-export const getOrderDetail = (id: number) => {
-  return request.get({ url: '/trade/order/get-detail?id=' + id })
-}
+import request from '@/config/axios'
+
+export interface OrderVO {
+  id?: number | null // 订单编号
+  no?: string // 订单流水号
+  createTime?: Date | null // 下单时间
+  type?: number | null // 订单类型
+  terminal?: number | null // 订单来源
+  userId?: number | null // 用户编号
+  userIp?: string // 用户 IP
+  userRemark?: string // 用户备注
+  status?: number | null // 订单状态
+  productCount?: number | null // 购买的商品数量
+  finishTime?: Date | null // 订单完成时间
+  cancelTime?: Date | null // 订单取消时间
+  cancelType?: number | null // 取消类型
+  remark?: string // 商家备注
+  payOrderId?: number | null // 支付订单编号
+  payed?: boolean // 是否已支付
+  payTime?: Date | null // 付款时间
+  payChannelCode?: string // 支付渠道
+  totalPrice?: number | null // 商品原价(总)
+  orderPrice?: number | null // 订单原价(总)
+  discountPrice?: number | null // 订单优惠(总)
+  deliveryPrice?: number | null // 运费金额
+  adjustPrice?: number | null // 订单调价(总)
+  payPrice?: number | null // 应付金额(总)
+  deliveryType?: number | null // 发货方式
+  deliveryTemplateId?: number | null // 配送模板编号
+  logisticsId?: number | null | null // 发货物流公司编号
+  logisticsNo?: string // 发货物流单号
+  deliveryStatus?: number | null // 发货状态
+  deliveryTime?: Date | null // 发货时间
+  receiveTime?: Date | null // 收货时间
+  receiverName?: string // 收件人名称
+  receiverMobile?: string // 收件人手机
+  receiverAreaId?: number | null // 收件人地区编号
+  receiverPostCode?: number | null // 收件人邮编
+  receiverDetailAddress?: string // 收件人详细地址
+  afterSaleStatus?: number | null // 售后状态
+  refundPrice?: number | null // 退款金额
+  couponId?: number | null // 优惠劵编号
+  couponPrice?: number | null // 优惠劵减免金额
+  pointPrice?: number | null // 积分抵扣的金额
+  receiverAreaName?: string //收件人地区名字
+  items?: OrderItemRespVO[] // 订单项列表
+  // 用户信息
+  user?: {
+    id?: number | null
+    nickname?: string
+    avatar?: string
+  }
+  // 订单操作日志
+  orderLog: orderLog[]
+}
+
+export interface orderLog {
+  content?: string
+  createTime?: Date
+}
+
+export interface OrderItemRespVO {
+  // ========== 订单项基本信息 ==========
+  id?: number | null // 编号
+  userId?: number | null // 用户编号
+  orderId?: number | null // 订单编号
+  // ========== 商品基本信息 ==========
+  spuId?: number | null // 商品 SPU 编号
+  spuName?: string //商品 SPU 名称
+  skuId?: number | null // 商品 SKU 编号
+  picUrl?: string //商品图片
+  count?: number | null //购买数量
+  // ========== 价格 + 支付基本信息 ==========
+  originalPrice?: number | null //商品原价(总)
+  originalUnitPrice?: number | null //商品原价(单)
+  discountPrice?: number | null //商品优惠(总)
+  payPrice?: number | null //商品实付金额(总)
+  orderPartPrice?: number | null //子订单分摊金额(总)
+  orderDividePrice?: number | null //分摊后子订单实付金额(总)
+  // ========== 营销基本信息 ==========
+  // TODO 芋艿:在捉摸一下
+  // ========== 售后基本信息 ==========
+  afterSaleStatus?: number | null // 售后状态
+  properties?: ProductPropertiesVO[] //属性数组
+}
+
+export interface ProductPropertiesVO {
+  propertyId?: number | null // 属性的编号
+  propertyName?: string // 属性的名称
+  valueId?: number | null //属性值的编号
+  valueName?: string // 属性值的名称
+}
+
+// 查询交易订单列表
+export const getOrderPage = async (params) => {
+  return await request.get({ url: `/trade/order/page`, params })
+}
+
+// 查询交易订单详情
+export const getOrder = async (id: number | null) => {
+  return await request.get({ url: `/trade/order/get-detail?id=` + id })
+}
+
+// 查询交易订单物流详情
+export const getExpressTrackList = async (id: number | null) => {
+  return await request.get({ url: `/trade/order/get-express-track-list?id=` + id })
+}
+
+export interface DeliveryVO {
+  id: number // 订单编号
+  logisticsId: number | null // 物流公司编号
+  logisticsNo: string // 物流编号
+}
+
+// 订单发货
+export const delivery = async (data: DeliveryVO) => {
+  return await request.put({ url: `/trade/order/delivery`, data })
+}
+
+// 订单备注
+export const updateRemark = async (data: any) => {
+  return await request.put({ url: `/trade/order/update-remark`, data })
+}
+
+// 订单调价
+export const updatePrice = async (data: any) => {
+  return await request.put({ url: `/trade/order/update-price`, data })
+}
+
+// 修改订单地址
+export const updateAddress = async (data: any) => {
+  return await request.put({ url: `/trade/order/update-address`, data })
+}

+ 0 - 228
src/api/mall/trade/order/type/orderType.ts

@@ -1,228 +0,0 @@
-// TODO @xiaobai:这个放到 order/index.ts  里哈
-// TODO @xiaobai:注释放到变量后面,这样简洁一点
-// TODO @xiaobai:这个改成 TradeOrderRespVO
-export interface TradeOrderPageItemRespVO {
-  // 订单编号
-  id?: number
-  // 订单流水号
-  no?: string
-  // 下单时间
-  createTime?: Date
-  // 订单类型
-  type?: number
-  // 订单来源
-  terminal?: number
-  // 用户编号
-  userId?: number
-  // 用户 IP
-  userIp?: string
-  // 用户备注
-  userRemark?: string
-  // 订单状态
-  status?: number
-  // 购买的商品数量
-  productCount?: number
-  // 订单完成时间
-  finishTime?: Date
-  // 订单取消时间
-  cancelTime?: Date
-  // 取消类型
-  cancelType?: number
-  // 商家备注
-  remark?: string
-  // 支付订单编号
-  payOrderId: number
-  // 是否已支付
-  payed?: boolean
-  // 付款时间
-  payTime?: Date
-  // 支付渠道
-  payChannelCode?: string
-  // 商品原价(总)
-  originalPrice?: number
-  // 订单原价(总)
-  orderPrice?: number
-  // 订单优惠(总)
-  discountPrice?: number
-  // 运费金额
-  deliveryPrice?: number
-  // 订单调价(总)
-  adjustPrice?: number
-  // 应付金额(总)
-  payPrice?: number
-  // 配送模板编号
-  deliveryTemplateId?: number
-  // 发货物流公司编号
-  logisticsId?: number
-  // 发货物流单号
-  logisticsNo?: string
-  // 发货状态
-  deliveryStatus?: number
-  // 发货时间
-  deliveryTime?: Date
-  // 收货时间
-  receiveTime?: Date
-  // 收件人名称
-  receiverName?: string
-  // 收件人手机
-  receiverMobile?: string
-  // 收件人地区编号
-  receiverAreaId?: number
-  // 收件人邮编
-  receiverPostCode?: number
-  // 收件人详细地址
-  receiverDetailAddress?: string
-  // 售后状态
-  afterSaleStatus?: number
-  // 退款金额
-  refundPrice?: number
-  // 优惠劵编号
-  couponId?: number
-  // 优惠劵减免金额
-  couponPrice?: number
-  // 积分抵扣的金额
-  pointPrice?: number
-  //收件人地区名字
-  receiverAreaName?: string
-  // 订单项列表
-  items?: TradeOrderItemBaseVO[]
-  //用户信息
-  user?: MemberUserRespDTO
-}
-
-// TODO @xiaobai:这个改成 TradeOrderItemRespVO
-/**
- * 交易订单项 Base VO,提供给添加、修改、详细的子 VO 使用
- * 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成
- */
-export interface TradeOrderItemBaseVO {
-  // ========== 订单项基本信息 ==========
-  /**
-   * 编号
-   */
-  id?: number
-  /**
-   * 用户编号
-   */
-  userId?: number
-  /**
-   * 订单编号
-   */
-  orderId?: number
-  // ========== 商品基本信息 ==========
-  /**
-   * 商品 SPU 编号
-   */
-  spuId?: number
-  /**
-   * 商品 SPU 名称
-   */
-  spuName?: string
-  /**
-   * 商品 SKU 编号
-   */
-  skuId?: number
-  /**
-   * 商品图片
-   */
-  picUrl?: string
-  /**
-   * 购买数量
-   */
-  count?: number
-  // ========== 价格 + 支付基本信息 ==========
-  /**
-   * 商品原价(总)
-   */
-  originalPrice?: number
-  /**
-   * 商品原价(单)
-   */
-  originalUnitPrice?: number
-  /**
-   * 商品优惠(总)
-   */
-  discountPrice?: number
-  /**
-   * 商品实付金额(总)
-   */
-  payPrice?: number
-  /**
-   * 子订单分摊金额(总)
-   */
-  orderPartPrice?: number
-  /**
-   * 分摊后子订单实付金额(总)
-   */
-  orderDividePrice?: number
-  // ========== 营销基本信息 ==========
-  // TODO 芋艿:在捉摸一下
-  // ========== 售后基本信息 ==========
-  /**
-   * 售后状态
-   */
-  afterSaleStatus?: number
-  //属性数组
-  properties?: ProductPropertyValueDetailRespVO[]
-}
-
-/**
- * 管理后台 - 商品属性值的明细 Response VO
- */
-export interface ProductPropertyValueDetailRespVO {
-  /**
-   * 属性的编号
-   */
-  propertyId?: number
-  /**
-   * 属性的名称
-   */
-  propertyName?: string
-  /**
-   * 属性值的编号
-   */
-  valueId?: number
-  /**
-   * 属性值的名称
-   */
-  valueName?: string
-}
-
-/**
- * 订单详情查询 请求
- */
-export interface TradeOrderPageReqVO {
-  pageNo: number
-  pageSize: number
-  no?: string
-  userId?: string
-  userNickname?: string
-  userMobile?: string
-  receiverName?: string
-  receiverMobile?: string
-  terminal?: string
-  type?: number
-  status?: number
-  payChannelCode?: string
-  createTime?: [Date, Date]
-  spuName?: string
-  itemCount?: string
-  all?: string
-}
-
-//用户信息
-export interface MemberUserRespDTO {
-  id?: number
-  nickname?: string
-  status?: number
-  avatar?: string
-  mobile?: string
-}
-//订单详情选中type
-export interface SelectType {
-  queryParams: TradeOrderPageReqVO
-  selectTotal: number //选中的数量
-  selectAllFlag: boolean //全选标识
-  selectData: Map<number, Set<string>> //存放涉及选中得页面以及每页选中得数据订单号  全选时根据条件查询 排除取消的list订单
-  unSelectList: Set<string> //登记取消的list 全选标识为true 时登记单独取消的list,再次选中时排除, 全选标识为false 时清空list
-}

+ 15 - 0
src/api/member/address/index.ts

@@ -0,0 +1,15 @@
+import request from '@/config/axios'
+
+export interface AddressVO {
+  id: number
+  name: string
+  mobile: string
+  areaId: number
+  detailAddress: string
+  defaultStatus: boolean
+}
+
+// 查询用户收件地址列表
+export const getAddressList = async (params) => {
+  return await request.get({ url: `/member/address/list`, params })
+}

+ 38 - 0
src/api/member/group/index.ts

@@ -0,0 +1,38 @@
+import request from '@/config/axios'
+
+export interface GroupVO {
+  id: number
+  name: string
+  remark: string
+  status: number
+}
+
+// 查询用户分组列表
+export const getGroupPage = async (params: any) => {
+  return await request.get({ url: `/member/group/page`, params })
+}
+
+// 查询用户分组详情
+export const getGroup = async (id: number) => {
+  return await request.get({ url: `/member/group/get?id=` + id })
+}
+
+// 新增用户分组
+export const createGroup = async (data: GroupVO) => {
+  return await request.post({ url: `/member/group/create`, data })
+}
+
+// 查询用户分组 - 精简信息列表
+export const getSimpleGroupList = async () => {
+  return await request.get({ url: `/member/group/list-all-simple` })
+}
+
+// 修改用户分组
+export const updateGroup = async (data: GroupVO) => {
+  return await request.put({ url: `/member/group/update`, data })
+}
+
+// 删除用户分组
+export const deleteGroup = async (id: number) => {
+  return await request.delete({ url: `/member/group/delete?id=` + id })
+}

+ 42 - 0
src/api/member/level/index.ts

@@ -0,0 +1,42 @@
+import request from '@/config/axios'
+
+export interface LevelVO {
+  id: number
+  name: string
+  experience: number
+  value: number
+  discountPercent: number
+  icon: string
+  bgUrl: string
+  status: number
+}
+
+// 查询会员等级列表
+export const getLevelList = async (params) => {
+  return await request.get({ url: `/member/level/list`, params })
+}
+
+// 查询会员等级详情
+export const getLevel = async (id: number) => {
+  return await request.get({ url: `/member/level/get?id=` + id })
+}
+
+// 查询会员等级 - 精简信息列表
+export const getSimpleLevelList = async () => {
+  return await request.get({ url: `/member/level/list-all-simple` })
+}
+
+// 新增会员等级
+export const createLevel = async (data: LevelVO) => {
+  return await request.post({ url: `/member/level/create`, data })
+}
+
+// 修改会员等级
+export const updateLevel = async (data: LevelVO) => {
+  return await request.put({ url: `/member/level/update`, data })
+}
+
+// 删除会员等级
+export const deleteLevel = async (id: number) => {
+  return await request.delete({ url: `/member/level/delete?id=` + id })
+}

+ 2 - 2
src/api/point/config/index.ts → src/api/member/point/config/index.ts

@@ -10,10 +10,10 @@ export interface ConfigVO {
 
 // 查询积分设置详情
 export const getConfig = async () => {
-  return await request.get({ url: `/point/config/get` })
+  return await request.get({ url: `/member/point/config/get` })
 }
 
 // 新增修改积分设置
 export const saveConfig = async (data: ConfigVO) => {
-  return await request.put({ url: `/point/config/save`, data })
+  return await request.put({ url: `/member/point/config/save`, data })
 }

+ 18 - 0
src/api/member/point/record/index.ts

@@ -0,0 +1,18 @@
+import request from '@/config/axios'
+
+export interface RecordVO {
+  id: number
+  bizId: string
+  bizType: string
+  title: string
+  description: string
+  point: number
+  totalPoint: number
+  userId: number
+  createDate: Date
+}
+
+// 查询用户积分记录列表
+export const getRecordPage = async (params) => {
+  return await request.get({ url: `/member/point/record/page`, params })
+}

+ 33 - 0
src/api/member/signin/config/index.ts

@@ -0,0 +1,33 @@
+import request from '@/config/axios'
+
+export interface SignInConfigVO {
+  id: number
+  day: number | null
+  point: number | null
+  enable: boolean | null
+}
+
+// 查询积分签到规则列表
+export const getSignInConfigList = async () => {
+  return await request.get({ url: `/member/sign-in/config/list` })
+}
+
+// 查询积分签到规则详情
+export const getSignInConfig = async (id: number) => {
+  return await request.get({ url: `/member/sign-in/config/get?id=` + id })
+}
+
+// 新增积分签到规则
+export const createSignInConfig = async (data: SignInConfigVO) => {
+  return await request.post({ url: `/member/sign-in/config/create`, data })
+}
+
+// 修改积分签到规则
+export const updateSignInConfig = async (data: SignInConfigVO) => {
+  return await request.put({ url: `/member/sign-in/config/update`, data })
+}
+
+// 删除积分签到规则
+export const deleteSignInConfig = async (id: number) => {
+  return await request.delete({ url: `/member/sign-in/config/delete?id=` + id })
+}

+ 13 - 0
src/api/member/signin/record/index.ts

@@ -0,0 +1,13 @@
+import request from '@/config/axios'
+
+export interface SignInRecordVO {
+  id: number
+  userId: number
+  day: number
+  point: number
+}
+
+// 查询用户签到积分列表
+export const getSignInRecordPage = async (params) => {
+  return await request.get({ url: `/member/sign-in/record/page`, params })
+}

+ 36 - 0
src/api/member/tag/index.ts

@@ -0,0 +1,36 @@
+import request from '@/config/axios'
+
+export interface TagVO {
+  id: number
+  name: string
+}
+
+// 查询会员标签列表
+export const getMemberTagPage = async (params: any) => {
+  return await request.get({ url: `/member/tag/page`, params })
+}
+
+// 查询会员标签详情
+export const getMemberTag = async (id: number) => {
+  return await request.get({ url: `/member/tag/get?id=` + id })
+}
+
+// 查询会员标签 - 精简信息列表
+export const getSimpleTagList = async () => {
+  return await request.get({ url: `/member/tag/list-all-simple` })
+}
+
+// 新增会员标签
+export const createMemberTag = async (data: TagVO) => {
+  return await request.post({ url: `/member/tag/create`, data })
+}
+
+// 修改会员标签
+export const updateMemberTag = async (data: TagVO) => {
+  return await request.put({ url: `/member/tag/update`, data })
+}
+
+// 删除会员标签
+export const deleteMemberTag = async (id: number) => {
+  return await request.delete({ url: `/member/tag/delete?id=` + id })
+}

+ 43 - 0
src/api/member/user/index.ts

@@ -0,0 +1,43 @@
+import request from '@/config/axios'
+
+export interface UserVO {
+  id: number
+  avatar: string | undefined
+  birthday: number | undefined
+  createTime: number | undefined
+  loginDate: number | undefined
+  loginIp: string
+  mark: string
+  mobile: string
+  name: string | undefined
+  nickname: string | undefined
+  registerIp: string
+  sex: number
+  status: number
+  areaId: number | undefined
+  areaName: string | undefined
+  levelName: string | null
+  point: number | undefined | null
+  totalPoint: number | undefined | null
+  experience: number | null | undefined
+}
+
+// 查询会员用户列表
+export const getUserPage = async (params) => {
+  return await request.get({ url: `/member/user/page`, params })
+}
+
+// 查询会员用户详情
+export const getUser = async (id: number) => {
+  return await request.get({ url: `/member/user/get?id=` + id })
+}
+
+// 修改会员用户
+export const updateUser = async (data: UserVO) => {
+  return await request.put({ url: `/member/user/update`, data })
+}
+
+// 修改会员用户等级
+export const updateUserLevel = async (data: any) => {
+  return await request.put({ url: `/member/user/update-level`, data })
+}

+ 11 - 24
src/api/pay/app/index.ts

@@ -22,57 +22,44 @@ export interface AppPageReqVO extends PageParam {
   createTime?: Date[]
 }
 
-export interface AppExportReqVO {
-  name?: string
-  status?: number
-  remark?: string
-  payNotifyUrl?: string
-  refundNotifyUrl?: string
-  merchantName?: string
-  createTime?: Date[]
-}
-
 export interface AppUpdateStatusReqVO {
   id: number
   status: number
 }
 
 // 查询列表支付应用
-export const getAppPageApi = (params: AppPageReqVO) => {
+export const getAppPage = (params: AppPageReqVO) => {
   return request.get({ url: '/pay/app/page', params })
 }
 
 // 查询详情支付应用
-export const getAppApi = (id: number) => {
+export const getApp = (id: number) => {
   return request.get({ url: '/pay/app/get?id=' + id })
 }
 
 // 新增支付应用
-export const createAppApi = (data: AppVO) => {
+export const createApp = (data: AppVO) => {
   return request.post({ url: '/pay/app/create', data })
 }
 
 // 修改支付应用
-export const updateAppApi = (data: AppVO) => {
+export const updateApp = (data: AppVO) => {
   return request.put({ url: '/pay/app/update', data })
 }
 
 // 支付应用信息状态修改
-export const changeAppStatusApi = (data: AppUpdateStatusReqVO) => {
+export const changeAppStatus = (data: AppUpdateStatusReqVO) => {
   return request.put({ url: '/pay/app/update-status', data: data })
 }
 
 // 删除支付应用
-export const deleteAppApi = (id: number) => {
+export const deleteApp = (id: number) => {
   return request.delete({ url: '/pay/app/delete?id=' + id })
 }
 
-// 导出支付应用
-export const exportAppApi = (params: AppExportReqVO) => {
-  return request.download({ url: '/pay/app/export-excel', params })
-}
-
-// 根据商ID称搜索应用列表
-export const getAppListByMerchantIdApi = (merchantId: number) => {
-  return request.get({ url: '/pay/app/list-merchant-id', params: { merchantId: merchantId } })
+// 获得支付应用列表
+export const getAppList = () => {
+  return request.get({
+    url: '/pay/app/list'
+  })
 }

+ 7 - 31
src/api/pay/channel/index.ts

@@ -7,64 +7,40 @@ export interface ChannelVO {
   status: number
   remark: string
   feeRate: number
-  merchantId: number
   appId: number
   createTime: Date
 }
 
-export interface ChannelPageReqVO extends PageParam {
-  code?: string
-  status?: number
-  remark?: string
-  feeRate?: number
-  merchantId?: number
-  appId?: number
-  config?: string
-  createTime?: Date[]
-}
-
-export interface ChannelExportReqVO {
-  code?: string
-  status?: number
-  remark?: string
-  feeRate?: number
-  merchantId?: number
-  appId?: number
-  config?: string
-  createTime?: Date[]
-}
-
 // 查询列表支付渠道
-export const getChannelPageApi = (params: ChannelPageReqVO) => {
+export const getChannelPage = (params: PageParam) => {
   return request.get({ url: '/pay/channel/page', params })
 }
 
 // 查询详情支付渠道
-export const getChannelApi = (merchantId: number, appId: string, code: string) => {
+export const getChannel = (appId: string, code: string) => {
   const params = {
-    merchantId: merchantId,
     appId: appId,
     code: code
   }
-  return request.get({ url: '/pay/channel/get-channel', params: params })
+  return request.get({ url: '/pay/channel/get', params: params })
 }
 
 // 新增支付渠道
-export const createChannelApi = (data: ChannelVO) => {
+export const createChannel = (data: ChannelVO) => {
   return request.post({ url: '/pay/channel/create', data })
 }
 
 // 修改支付渠道
-export const updateChannelApi = (data: ChannelVO) => {
+export const updateChannel = (data: ChannelVO) => {
   return request.put({ url: '/pay/channel/update', data })
 }
 
 // 删除支付渠道
-export const deleteChannelApi = (id: number) => {
+export const deleteChannel = (id: number) => {
   return request.delete({ url: '/pay/channel/delete?id=' + id })
 }
 
 // 导出支付渠道
-export const exportChannelApi = (params: ChannelExportReqVO) => {
+export const exportChannel = (params) => {
   return request.download({ url: '/pay/channel/export-excel', params })
 }

+ 36 - 0
src/api/pay/demo/index.ts

@@ -0,0 +1,36 @@
+import request from '@/config/axios'
+
+export interface DemoOrderVO {
+  spuId: number
+  createTime: Date
+}
+
+// 创建示例订单
+export function createDemoOrder(data: DemoOrderVO) {
+  return request.post({
+    url: '/pay/demo-order/create',
+    data: data
+  })
+}
+
+// 获得示例订单
+export function getDemoOrder(id: number) {
+  return request.get({
+    url: '/pay/demo-order/get?id=' + id
+  })
+}
+
+// 获得示例订单分页
+export function getDemoOrderPage(query: PageParam) {
+  return request.get({
+    url: '/pay/demo-order/page',
+    params: query
+  })
+}
+
+// 退款示例订单
+export function refundDemoOrder(id) {
+  return request.put({
+    url: '/pay/demo-order/refund?id=' + id
+  })
+}

+ 0 - 78
src/api/pay/merchant/index.ts

@@ -1,78 +0,0 @@
-import request from '@/config/axios'
-
-export interface MerchantVO {
-  id: number
-  no: string
-  name: string
-  shortName: string
-  status: number
-  remark: string
-  createTime: Date
-}
-
-export interface MerchantPageReqVO extends PageParam {
-  no?: string
-  name?: string
-  shortName?: string
-  status?: number
-  remark?: string
-  createTime?: Date[]
-}
-
-export interface MerchantExportReqVO {
-  no?: string
-  name?: string
-  shortName?: string
-  status?: number
-  remark?: string
-  createTime?: Date[]
-}
-
-// 查询列表支付商户
-export const getMerchantPageApi = (params: MerchantPageReqVO) => {
-  return request.get({ url: '/pay/merchant/page', params })
-}
-
-// 查询详情支付商户
-export const getMerchantApi = (id: number) => {
-  return request.get({ url: '/pay/merchant/get?id=' + id })
-}
-
-// 根据商户名称搜索商户列表
-export const getMerchantListByNameApi = (name?: string) => {
-  return request.get({
-    url: '/pay/merchant/list-by-name',
-    params: {
-      name: name
-    }
-  })
-}
-
-// 新增支付商户
-export const createMerchantApi = (data: MerchantVO) => {
-  return request.post({ url: '/pay/merchant/create', data })
-}
-
-// 修改支付商户
-export const updateMerchantApi = (data: MerchantVO) => {
-  return request.put({ url: '/pay/merchant/update', data })
-}
-
-// 删除支付商户
-export const deleteMerchantApi = (id: number) => {
-  return request.delete({ url: '/pay/merchant/delete?id=' + id })
-}
-
-// 导出支付商户
-export const exportMerchantApi = (params: MerchantExportReqVO) => {
-  return request.download({ url: '/pay/merchant/export-excel', params })
-}
-
-// 支付商户状态修改
-export const changeMerchantStatusApi = (id: number, status: number) => {
-  const data = {
-    id,
-    status
-  }
-  return request.put({ url: '/pay/merchant/update-status', data: data })
-}

+ 16 - 0
src/api/pay/notify/index.ts

@@ -0,0 +1,16 @@
+import request from '@/config/axios'
+
+// 获得支付通知明细
+export const getNotifyTaskDetail = (id) => {
+  return request.get({
+    url: '/pay/notify/get-detail?id=' + id
+  })
+}
+
+// 获得支付通知分页
+export const getNotifyTaskPage = (query) => {
+  return request.get({
+    url: '/pay/notify/page',
+    params: query
+  })
+}

+ 7 - 17
src/api/pay/order/index.ts

@@ -79,36 +79,26 @@ export interface OrderExportReqVO {
 }
 
 // 查询列表支付订单
-export const getOrderPageApi = async (params: OrderPageReqVO) => {
+export const getOrderPage = async (params: OrderPageReqVO) => {
   return await request.get({ url: '/pay/order/page', params })
 }
 
 // 查询详情支付订单
-export const getOrderApi = async (id: number) => {
+export const getOrder = async (id: number) => {
   return await request.get({ url: '/pay/order/get?id=' + id })
 }
 
 // 获得支付订单的明细
-export const getOrderDetailApi = async (id: number) => {
+export const getOrderDetail = async (id: number) => {
   return await request.get({ url: '/pay/order/get-detail?id=' + id })
 }
 
-// 新增支付订单
-export const createOrderApi = async (data: OrderVO) => {
-  return await request.post({ url: '/pay/order/create', data })
-}
-
-// 修改支付订单
-export const updateOrderApi = async (data: OrderVO) => {
-  return await request.put({ url: '/pay/order/update', data })
-}
-
-// 删除支付订单
-export const deleteOrderApi = async (id: number) => {
-  return await request.delete({ url: '/pay/order/delete?id=' + id })
+// 提交支付订单
+export const submitOrder = async (data: any) => {
+  return await request.post({ url: '/pay/order/submit', data })
 }
 
 // 导出支付订单
-export const exportOrderApi = async (params: OrderExportReqVO) => {
+export const exportOrder = async (params: OrderExportReqVO) => {
   return await request.download({ url: '/pay/order/export-excel', params })
 }

+ 6 - 6
src/api/pay/refund/index.ts

@@ -86,31 +86,31 @@ export interface PayRefundExportReqVO {
 }
 
 // 查询列表退款订单
-export const getRefundPageApi = (params: RefundPageReqVO) => {
+export const getRefundPage = (params: RefundPageReqVO) => {
   return request.get({ url: '/pay/refund/page', params })
 }
 
 // 查询详情退款订单
-export const getRefundApi = (id: number) => {
+export const getRefund = (id: number) => {
   return request.get({ url: '/pay/refund/get?id=' + id })
 }
 
 // 新增退款订单
-export const createRefundApi = (data: RefundVO) => {
+export const createRefund = (data: RefundVO) => {
   return request.post({ url: '/pay/refund/create', data })
 }
 
 // 修改退款订单
-export const updateRefundApi = (data: RefundVO) => {
+export const updateRefund = (data: RefundVO) => {
   return request.put({ url: '/pay/refund/update', data })
 }
 
 // 删除退款订单
-export const deleteRefundApi = (id: number) => {
+export const deleteRefund = (id: number) => {
   return request.delete({ url: '/pay/refund/delete?id=' + id })
 }
 
 // 导出退款订单
-export const exportRefundApi = (params: PayRefundExportReqVO) => {
+export const exportRefund = (params: PayRefundExportReqVO) => {
   return request.download({ url: '/pay/refund/export-excel', params })
 }

+ 0 - 47
src/api/point/record/index.ts

@@ -1,47 +0,0 @@
-import request from '@/config/axios'
-
-export interface RecordVO {
-  id: number
-  bizId: string
-  bizType: string
-  type: string
-  title: string
-  description: string
-  point: number
-  totalPoint: number
-  status: number
-  userId: number
-  freezingTime: Date
-  thawingTime: Date
-  createDate: Date
-}
-
-// 查询用户积分记录列表
-export const getRecordPage = async (params) => {
-  return await request.get({ url: `/point/record/page`, params })
-}
-
-// 查询用户积分记录详情
-export const getRecord = async (id: number) => {
-  return await request.get({ url: `/point/record/get?id=` + id })
-}
-
-// 新增用户积分记录
-export const createRecord = async (data: RecordVO) => {
-  return await request.post({ url: `/point/record/create`, data })
-}
-
-// 修改用户积分记录
-export const updateRecord = async (data: RecordVO) => {
-  return await request.put({ url: `/point/record/update`, data })
-}
-
-// 删除用户积分记录
-export const deleteRecord = async (id: number) => {
-  return await request.delete({ url: `/point/record/delete?id=` + id })
-}
-
-// 导出用户积分记录 Excel
-export const exportRecord = async (params) => {
-  return await request.download({ url: `/point/record/export-excel`, params })
-}

+ 0 - 37
src/api/point/signInConfig/index.ts

@@ -1,37 +0,0 @@
-import request from '@/config/axios'
-
-export interface SignInConfigVO {
-  id: number
-  day: number
-  point: number
-}
-
-// 查询积分签到规则列表
-export const getSignInConfigPage = async (params) => {
-  return await request.get({ url: `/point/sign-in-config/page`, params })
-}
-
-// 查询积分签到规则详情
-export const getSignInConfig = async (id: number) => {
-  return await request.get({ url: `/point/sign-in-config/get?id=` + id })
-}
-
-// 新增积分签到规则
-export const createSignInConfig = async (data: SignInConfigVO) => {
-  return await request.post({ url: `/point/sign-in-config/create`, data })
-}
-
-// 修改积分签到规则
-export const updateSignInConfig = async (data: SignInConfigVO) => {
-  return await request.put({ url: `/point/sign-in-config/update`, data })
-}
-
-// 删除积分签到规则
-export const deleteSignInConfig = async (id: number) => {
-  return await request.delete({ url: `/point/sign-in-config/delete?id=` + id })
-}
-
-// 导出积分签到规则 Excel
-export const exportSignInConfig = async (params) => {
-  return await request.download({ url: `/point/sign-in-config/export-excel`, params })
-}

+ 0 - 38
src/api/point/signInRecord/index.ts

@@ -1,38 +0,0 @@
-import request from '@/config/axios'
-
-export interface SignInRecordVO {
-  id: number
-  userId: number
-  day: number
-  point: number
-}
-
-// 查询用户签到积分列表
-export const getSignInRecordPage = async (params) => {
-  return await request.get({ url: `/point/sign-in-record/page`, params })
-}
-
-// 查询用户签到积分详情
-export const getSignInRecord = async (id: number) => {
-  return await request.get({ url: `/point/sign-in-record/get?id=` + id })
-}
-
-// 新增用户签到积分
-export const createSignInRecord = async (data: SignInRecordVO) => {
-  return await request.post({ url: `/point/sign-in-record/create`, data })
-}
-
-// 修改用户签到积分
-export const updateSignInRecord = async (data: SignInRecordVO) => {
-  return await request.put({ url: `/point/sign-in-record/update`, data })
-}
-
-// 删除用户签到积分
-export const deleteSignInRecord = async (id: number) => {
-  return await request.delete({ url: `/point/sign-in-record/delete?id=` + id })
-}
-
-// 导出用户签到积分 Excel
-export const exportSignInRecord = async (params) => {
-  return await request.download({ url: `/point/sign-in-record/export-excel`, params })
-}

+ 1 - 1
src/api/system/permission/index.ts

@@ -18,7 +18,7 @@ export interface PermissionAssignRoleDataScopeReqVO {
 
 // 查询角色拥有的菜单权限
 export const listRoleMenusApi = async (roleId: number) => {
-  return await request.get({ url: '/system/permission/list-role-resources?roleId=' + roleId })
+  return await request.get({ url: '/system/permission/list-role-menus?roleId=' + roleId })
 }
 
 // 赋予角色菜单权限

+ 1 - 0
src/assets/svgs/member_balance.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="1693028338187" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="22985" width="128" height="128" xmlns:xlink="http://www.w3.org/1999/xlink"><path d="M983.8 312.7C958 251.7 921 197 874 150c-47-47-101.8-83.9-162.7-109.7C648.2 13.5 581.1 0 512 0S375.8 13.5 312.7 40.2C251.7 66 197 102.9 150 150c-47 47-83.9 101.8-109.7 162.7C13.5 375.8 0 442.9 0 512s13.5 136.2 40.2 199.3C66 772.3 102.9 827 150 874c47 47 101.8 83.9 162.7 109.7 63.1 26.7 130.2 40.2 199.3 40.2s136.2-13.5 199.3-40.2C772.3 958 827 921 874 874c47-47 83.9-101.8 109.7-162.7 26.7-63.1 40.2-130.2 40.2-199.3s-13.4-136.2-40.1-199.3z m-55.3 375.2c-22.8 53.8-55.4 102.2-96.9 143.7s-89.9 74.1-143.7 96.9C632.2 952.1 573 964 512 964s-120.2-11.9-175.9-35.5c-53.8-22.8-102.2-55.4-143.7-96.9s-74.1-89.9-96.9-143.7C71.9 632.2 60 573 60 512s11.9-120.2 35.5-175.9c22.8-53.8 55.4-102.2 96.9-143.7s89.9-74.1 143.7-96.9C391.8 71.9 451 60 512 60s120.2 11.9 175.9 35.5c53.8 22.8 102.2 55.4 143.7 96.9s74.1 89.9 96.9 143.7C952.1 391.8 964 451 964 512s-11.9 120.2-35.5 175.9z" fill="#000000" p-id="22986"></path><path d="M706 469.1H574.7l84.2-180.6c7-15 0.4-32.9-14.5-39.9-15-7-32.9-0.4-39.9 14.5L512 461.5l-92.5-198.3c-7-15-24.9-21.5-39.9-14.5s-21.5 24.9-14.5 39.9l84.2 180.6H318c-16.5 0-30 13.5-30 30s13.5 30 30 30h164v64h-92.5c-20.6 0-37.5 13.5-37.5 30s16.9 30 37.5 30H482v95c0 16.5 13.5 30 30 30s30-13.5 30-30v-95h92.5c20.6 0 37.5-13.5 37.5-30s-16.9-30-37.5-30H542v-64h164c16.5 0 30-13.5 30-30 0-16.6-13.5-30.1-30-30.1z" fill="#000000" p-id="22987"></path></svg>

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


+ 1 - 0
src/assets/svgs/member_level.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="1693027700643" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="8876" width="128" height="128" xmlns:xlink="http://www.w3.org/1999/xlink"><path d="M936.96 385.877333l-203.434667-204.8-18.090667-7.68L308.565333 173.397333l-18.090667 7.68L87.04 385.877333c-9.728 9.898667-9.898667 25.941333-0.170667 35.84l406.869333 421.034667c4.778667 4.949333 11.434667 7.850667 18.432 7.850667 6.997333 0 13.653333-2.901333 18.432-7.850667l406.869333-421.034667C946.858667 411.648 946.688 395.776 936.96 385.877333zM868.522667 389.632l-141.994667 0-163.84-165.034667 141.994667 0L868.522667 389.632zM319.317333 224.768l143.018667 0-163.84 165.034667L155.477333 389.802667 319.317333 224.768zM176.469333 440.832l132.608 0 18.090667-7.509333 185.173333-186.538667 185.173333 186.538667 18.090667 7.509333 131.584 0L512 787.968 176.469333 440.832z" p-id="8877" fill="#000000"></path></svg>

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


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


+ 1 - 0
src/assets/svgs/pay/icon/alipay_app.svg

@@ -0,0 +1 @@
+<svg t="1627279997305" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="11904" width="40" height="40"><path d="M938.7008 669.525333L938.7008 249.412267c0-90.555733-73.5232-164.078933-164.1472-164.078933L249.378133 85.333333c-90.555733 0-164.078933 73.48906699-164.078933 164.078933l0 525.2096c0 90.555733 73.454933 164.078933 164.07893301 164.078933l525.20959999 0c80.725333 0 147.8656-58.368 161.553067-135.099733-43.52-18.8416-232.106667-100.283733-330.376533-147.182933-74.786133 90.589867-153.088 144.930133-271.121067 144.930133s-196.81279999-72.704-187.357867-161.655467c6.2464-58.402133 46.2848-153.9072 220.296533-137.5232 91.682133 8.6016 133.666133 25.736533 208.418133 50.414933 19.3536-35.4304 35.4304-74.513067 47.616-116.0192L292.0448 436.565333l0-32.8704 164.0448 0 0-58.9824L256 344.712533l1e-8-36.181333 200.12373299 0L456.123733 223.3344c0 0 1.809067-13.312 16.520533-13.31200001l82.056533 1e-8 0 98.474667 213.333333 0 0 36.181333-213.333333 1e-8 0 58.98239999 174.045867 0c-16.00853301 65.1264-40.277333 124.962133-70.690133 177.220267C708.608 599.176533 938.7008 669.525333 938.7008 669.525333L938.7008 669.525333 938.7008 669.525333 938.7008 669.525333zM321.57013299 744.994133c-124.7232 0-144.452267-78.7456-137.83039999-111.65013299 6.5536-32.733867 42.666667-75.502933 112.0256-75.50293301 79.6672 0 151.04 20.445867 236.714667 62.088533C472.302933 698.333867 398.370133 744.994133 321.57013299 744.994133L321.57013299 744.994133 321.57013299 744.994133zM321.57013299 744.994133" fill="#1296db" p-id="11905"></path></svg>

文件差異過大導致無法顯示
+ 1 - 0
src/assets/svgs/pay/icon/alipay_bar.svg


+ 1 - 0
src/assets/svgs/pay/icon/alipay_pc.svg

@@ -0,0 +1 @@
+<svg t="1627279878333" class="icon" viewBox="0 0 1285 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="8535" width="40" height="40"><path d="M1141.76 855.04h-286.72c0 40.96 30.72 71.68 71.68 71.68h107.52c20.48 0 35.84 15.36 35.84 35.84s-15.36 35.84-35.84 35.84h-783.36c-20.48 0-35.84-15.36-35.84-35.84s15.36-35.84 35.84-35.84h107.52c40.96 0 71.68-30.72 71.68-71.68h-286.72c-76.8 0-143.36-61.44-143.36-143.36v-568.32c0-76.8 61.44-143.36 143.36-143.36h993.28c76.8 0 143.36 61.44 143.36 143.36v568.32c5.12 76.8-56.32 143.36-138.24 143.36z m71.68-711.68c0-40.96-30.72-71.68-71.68-71.68h-993.28c-40.96 0-71.68 30.72-71.68 71.68v568.32c0 40.96 30.72 71.68 71.68 71.68h993.28c40.96 0 71.68-30.72 71.68-71.68v-568.32z m-143.36 568.32h-855.04c-40.96 0-71.68-30.72-71.68-71.68v-424.96c0-40.96 30.72-71.68 71.68-71.68h855.04c40.96 0 71.68 30.72 71.68 71.68v424.96c0 40.96-30.72 71.68-71.68 71.68z" p-id="8536" fill="#1977FD"></path></svg>

+ 2 - 0
src/assets/svgs/pay/icon/alipay_qr.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="1627279238245" class="icon" viewBox="0 0 1115 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4112" width="43.5546875" height="40" xmlns:xlink="http://www.w3.org/1999/xlink"><defs><style type="text/css">@font-face { font-family: feedback-iconfont; src: url("//at.alicdn.com/t/font_1031158_1uhr8ri0pk5.eot?#iefix") format("embedded-opentype"), url("//at.alicdn.com/t/font_1031158_1uhr8ri0pk5.woff2") format("woff2"), url("//at.alicdn.com/t/font_1031158_1uhr8ri0pk5.woff") format("woff"), url("//at.alicdn.com/t/font_1031158_1uhr8ri0pk5.ttf") format("truetype"), url("//at.alicdn.com/t/font_1031158_1uhr8ri0pk5.svg#iconfont") format("svg"); }
+</style></defs><path d="M751.388 68.267a34.133 34.133 0 0 1 0-68.267h227.556a91.022 91.022 0 0 1 91.022 91.022v227.556a34.133 34.133 0 1 1-68.266 0V91.022a22.756 22.756 0 0 0-22.756-22.755H751.388M1001.7 705.422a34.133 34.133 0 0 1 68.266 0v227.556A91.022 91.022 0 0 1 978.944 1024H748.885a34.133 34.133 0 0 1 0-68.267H978.49a22.756 22.756 0 0 0 22.755-22.755V705.422M364.09 955.733a34.133 34.133 0 1 1 0 68.267H136.533a91.022 91.022 0 0 1-91.022-91.022V705.422a34.133 34.133 0 0 1 68.267 0v227.556a22.756 22.756 0 0 0 22.755 22.755H364.09M113.778 318.578a34.133 34.133 0 1 1-68.267 0V91.022A91.022 91.022 0 0 1 136.533 0H364.09a34.133 34.133 0 0 1 0 68.267H136.533a22.756 22.756 0 0 0-22.755 22.755v227.556M34.133 477.867a34.133 34.133 0 0 0 0 68.266h168.619v-68.266z m1046.756 0H912.27v68.266h168.619a34.133 34.133 0 0 0 0-68.266zM202.752 157.24h709.746v320.627H202.752z m0 388.893h709.746V866.76H202.752z" fill="#1977FD" p-id="4113"></path></svg>

+ 1 - 0
src/assets/svgs/pay/icon/alipay_wap.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="1645964864184" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="8460" xmlns:xlink="http://www.w3.org/1999/xlink" width="40" height="40"><defs><style type="text/css"></style></defs><path d="M768.3 0 255.7 0c-70.8 0-128.1 57.4-128.1 128.1l0 767.8c0 70.8 57.4 128.1 128.1 128.1L512 1024l256.3 0c70.8 0 128.1-57.4 128.1-128.1L896.4 128.1C896.4 57.3 839 0 768.3 0zM383.9 96.1c0-17.7 14.3-32 32-32l192.2 0c17.7 0 32 14.3 32 32l0 0c0 17.7-14.3 32-32 32L415.9 128.1C398.2 128.1 383.9 113.8 383.9 96.1L383.9 96.1zM512 959.9 512 959.9 512 959.9c-35.4 0-64.1-28.8-64.1-64.1 0-35.4 28.7-64.1 64.1-64.1l0 0 0 0c35.4 0 64.1 28.7 64.1 64.1C576.1 931.1 547.4 959.9 512 959.9zM832.3 755.6c0 6.7-5.4 12.2-12.2 12.2L203.9 767.8c-6.7 0-12.2-5.4-12.2-12.2L191.7 204.3c0-6.7 5.4-12.2 12.2-12.2l616.3 0c6.7 0 12.2 5.4 12.2 12.2L832.4 755.6z" p-id="8461" fill="#1977FD"></path></svg>

+ 1 - 0
src/assets/svgs/pay/icon/mock.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="1676209854312" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="3033" xmlns:xlink="http://www.w3.org/1999/xlink" width="128" height="128"><path d="M173.077333 362.666667l91.114667-214.677334a65.6 65.6 0 0 1 86.016-34.773333c11.584 4.906667 24.96 10.282667 40.896 16.448 8.277333 3.2 16.789333 6.464 27.904 10.666667 28.202667 10.709333 39.296 14.933333 46.144 17.642666l51.477333-51.669333c28.181333-28.16 74.112-27.946667 102.570667 0.533333l195.925333 195.925334c16.426667 16.426667 23.445333 38.634667 21.056 59.904H896a42.666667 42.666667 0 0 1 42.666667 42.666666v490.666667a42.666667 42.666667 0 0 1-42.666667 42.666667H128a42.666667 42.666667 0 0 1-42.666667-42.666667V405.333333a42.666667 42.666667 0 0 1 42.666667-42.666666h45.077333z m48.96 0h39.104l169.194667-169.770667-27.328-10.389333c-11.2-4.245333-19.818667-7.530667-28.224-10.794667a1459.2 1459.2 0 0 1-42.197333-17.002667 20.522667 20.522667 0 0 0-26.901334 10.88L222.037333 362.666667z m108.842667 0h454.954667a23.509333 23.509333 0 0 0-5.290667-25.322667l-195.925333-195.925333a23.36 23.36 0 0 0-33.024-0.213334L330.88 362.666667zM128 405.333333v490.666667h768V405.333333H128z m597.333333 320a85.333333 85.333333 0 1 1 0-170.666666 85.333333 85.333333 0 0 1 0 170.666666z m0-42.666666a42.666667 42.666667 0 1 0 0-85.333334 42.666667 42.666667 0 0 0 0 85.333334z" fill="#4296d5" p-id="3034"></path></svg>

+ 2 - 0
src/assets/svgs/pay/icon/wx_app.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="1627279375144" class="icon" viewBox="0 0 1115 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4399" width="43.5546875" height="40" xmlns:xlink="http://www.w3.org/1999/xlink"><defs><style type="text/css">@font-face { font-family: feedback-iconfont; src: url("//at.alicdn.com/t/font_1031158_1uhr8ri0pk5.eot?#iefix") format("embedded-opentype"), url("//at.alicdn.com/t/font_1031158_1uhr8ri0pk5.woff2") format("woff2"), url("//at.alicdn.com/t/font_1031158_1uhr8ri0pk5.woff") format("woff"), url("//at.alicdn.com/t/font_1031158_1uhr8ri0pk5.ttf") format("truetype"), url("//at.alicdn.com/t/font_1031158_1uhr8ri0pk5.svg#iconfont") format("svg"); }
+</style></defs><path d="M751.388 68.267a34.133 34.133 0 0 1 0-68.267h227.556a91.022 91.022 0 0 1 91.022 91.022v227.556a34.133 34.133 0 1 1-68.266 0V91.022a22.756 22.756 0 0 0-22.756-22.755H751.388M1001.7 705.422a34.133 34.133 0 0 1 68.266 0v227.556A91.022 91.022 0 0 1 978.944 1024H748.885a34.133 34.133 0 0 1 0-68.267H978.49a22.756 22.756 0 0 0 22.755-22.755V705.422M364.09 955.733a34.133 34.133 0 1 1 0 68.267H136.533a91.022 91.022 0 0 1-91.022-91.022V705.422a34.133 34.133 0 0 1 68.267 0v227.556a22.756 22.756 0 0 0 22.755 22.755H364.09M113.778 318.578a34.133 34.133 0 1 1-68.267 0V91.022A91.022 91.022 0 0 1 136.533 0H364.09a34.133 34.133 0 0 1 0 68.267H136.533a22.756 22.756 0 0 0-22.755 22.755v227.556M34.133 477.867a34.133 34.133 0 0 0 0 68.266h168.619v-68.266z m1046.756 0H912.27v68.266h168.619a34.133 34.133 0 0 0 0-68.266zM202.752 157.24h709.746v320.627H202.752z m0 388.893h709.746V866.76H202.752z" fill="#04C361" p-id="4400"></path></svg>

文件差異過大導致無法顯示
+ 0 - 0
src/assets/svgs/pay/icon/wx_bar.svg


+ 1 - 0
src/assets/svgs/pay/icon/wx_lite.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="1676209433089" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2990" xmlns:xlink="http://www.w3.org/1999/xlink" width="128" height="128"><path d="M608.6 290.3c67.1 0 121.7 50.5 121.7 112.9 0 19.4-5.6 38.4-15.7 55.5-15.3 25-39.8 43.5-69.4 52.3-7.9 2.3-13.9 3.2-19.4 3.2-13 0-23.1-10.2-23.1-23.1 0-13 10.2-23.1 23.1-23.1 0.9 0 2.8 0 5.1-0.9 19.9-5.6 35.6-17.1 44.4-32.4 6-9.7 8.8-20.4 8.8-31.5 0-36.6-33.8-66.6-75-66.6-14.4 0-28.2 3.7-40.7 10.6-21.8 12.5-34.7 33.3-34.7 56v193.9c0 39.3-21.8 75.4-57.9 95.8-19.4 11.1-41.2 16.7-63.4 16.7-67.1 0-121.7-50.5-121.7-112.9 0-19.4 5.6-38.4 15.7-55.5 15.3-25 39.8-43.5 69.4-52.3 8.3-2.3 13.9-3.2 19.4-3.2 13 0 23.1 10.2 23.1 23.1 0 13-10.2 23.1-23.1 23.1-0.9 0-2.8 0-5.1 0.9-19.9 6-35.6 17.6-44.4 32.4-6 9.7-8.8 20.4-8.8 31.5 0 36.6 33.8 66.6 75.4 66.6 14.4 0 28.2-3.7 40.7-10.6 21.8-12.5 34.7-33.3 34.7-56V403.3c0-39.3 21.8-75.4 57.9-95.8 19-11.6 40.7-17.2 63-17.2zM510.8 929c231.1 0 418.4-187.3 418.4-418.4S741.9 92.1 510.8 92.1 92.4 279.5 92.4 510.6 279.7 929 510.8 929z m0 22C267.5 951 70.3 753.8 70.3 510.6S267.5 70.1 510.8 70.1s440.5 197.2 440.5 440.5S754.1 951 510.8 951z" p-id="2991" fill="#58bf6b"></path></svg>

+ 1 - 0
src/assets/svgs/pay/icon/wx_native.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="1627279375144" class="icon" viewBox="0 0 1115 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4399" width="43.5546875" height="40" xmlns:xlink="http://www.w3.org/1999/xlink"><defs><style type="text/css">@font-face { font-family: feedback-iconfont; src: url(&quot;//at.alicdn.com/t/font_1031158_1uhr8ri0pk5.eot?#iefix&quot;) format(&quot;embedded-opentype&quot;), url(&quot;//at.alicdn.com/t/font_1031158_1uhr8ri0pk5.woff2&quot;) format(&quot;woff2&quot;), url(&quot;//at.alicdn.com/t/font_1031158_1uhr8ri0pk5.woff&quot;) format(&quot;woff&quot;), url(&quot;//at.alicdn.com/t/font_1031158_1uhr8ri0pk5.ttf&quot;) format(&quot;truetype&quot;), url(&quot;//at.alicdn.com/t/font_1031158_1uhr8ri0pk5.svg#iconfont&quot;) format(&quot;svg&quot;); }</style></defs><path d="M751.388 68.267a34.133 34.133 0 0 1 0-68.267h227.556a91.022 91.022 0 0 1 91.022 91.022v227.556a34.133 34.133 0 1 1-68.266 0V91.022a22.756 22.756 0 0 0-22.756-22.755H751.388M1001.7 705.422a34.133 34.133 0 0 1 68.266 0v227.556A91.022 91.022 0 0 1 978.944 1024H748.885a34.133 34.133 0 0 1 0-68.267H978.49a22.756 22.756 0 0 0 22.755-22.755V705.422M364.09 955.733a34.133 34.133 0 1 1 0 68.267H136.533a91.022 91.022 0 0 1-91.022-91.022V705.422a34.133 34.133 0 0 1 68.267 0v227.556a22.756 22.756 0 0 0 22.755 22.755H364.09M113.778 318.578a34.133 34.133 0 1 1-68.267 0V91.022A91.022 91.022 0 0 1 136.533 0H364.09a34.133 34.133 0 0 1 0 68.267H136.533a22.756 22.756 0 0 0-22.755 22.755v227.556M34.133 477.867a34.133 34.133 0 0 0 0 68.266h168.619v-68.266z m1046.756 0H912.27v68.266h168.619a34.133 34.133 0 0 0 0-68.266zM202.752 157.24h709.746v320.627H202.752z m0 388.893h709.746V866.76H202.752z" fill="#04C361" p-id="4400"/></svg>

+ 2 - 0
src/assets/svgs/pay/icon/wx_pub.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="1627279797174" class="icon" viewBox="0 0 1260 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="7665" xmlns:xlink="http://www.w3.org/1999/xlink" width="49.21875" height="40"><defs><style type="text/css">@font-face { font-family: feedback-iconfont; src: url("//at.alicdn.com/t/font_1031158_1uhr8ri0pk5.eot?#iefix") format("embedded-opentype"), url("//at.alicdn.com/t/font_1031158_1uhr8ri0pk5.woff2") format("woff2"), url("//at.alicdn.com/t/font_1031158_1uhr8ri0pk5.woff") format("woff"), url("//at.alicdn.com/t/font_1031158_1uhr8ri0pk5.ttf") format("truetype"), url("//at.alicdn.com/t/font_1031158_1uhr8ri0pk5.svg#iconfont") format("svg"); }
+</style></defs><path d="M797.14798 481.753a269.194 269.194 0 0 0 102.892-211.929C900.03998 120.99 779.02998 0 630.15698 0 481.28298 0 360.27398 120.99 360.27398 269.824c0 85.878 40.33 162.462 102.912 211.929A450.974 450.974 0 0 0 309.84198 582.774c-85.543 85.524-132.608 199.208-132.608 320.236 0 25.01 0 51.712 0.197 76.367a44.898 44.898 0 0 0 44.82 44.623h816.01a44.8 44.8 0 0 0 44.82-44.623V903.01c0-121.009-47.066-234.732-132.609-320.236a451.072 451.072 0 0 0-153.344-101.021z" p-id="7666" fill="#04C361"></path><path d="M1186.18898 580.391A378.644 378.644 0 0 0 1061.81198 473.03a223.783 223.783 0 0 0 64.237-157.657c0-49.742-15.872-96.67-45.746-136.074A225.34 225.34 0 0 0 964.70998 99.9a37.297 37.297 0 0 0-46.14 25.718c-5.592 19.89 5.79 40.724 25.6 46.356 63.114 18.196 107.363 77.135 107.363 143.4a148.913 148.913 0 0 1-81.23 133.06 38.065 38.065 0 0 0-20.363 36.608c1.32 15.203 11.58 28.16 25.975 32.65 125.479 39.601 209.703 155.038 209.703 287.173v63.074c0 20.638 16.62 37.534 37.16 37.711h0.196a37.396 37.396 0 0 0 37.337-37.336V805.06c-0.197-81.644-25.777-159.35-74.142-224.69z m-901.77-62.503a36.982 36.982 0 0 0 25.955-32.65 37.455 37.455 0 0 0-20.362-36.628 148.913 148.913 0 0 1-81.231-133.06c0-66.245 44.071-125.184 107.382-143.4a37.612 37.612 0 0 0 25.58-46.356 37.376 37.376 0 0 0-46.139-25.718 225.32 225.32 0 0 0-115.593 79.4 223.252 223.252 0 0 0-45.746 136.074c0 60.258 23.533 116.381 64.237 157.676A380.475 380.475 0 0 0 74.14498 580.569 373.839 373.839 0 0 0 0.00198 805.258v63.232c0 20.657 16.798 37.356 37.356 37.356h0.197a37.317 37.317 0 0 0 37.14-37.73V805.06c0-132.332 84.401-247.769 209.723-287.173z" p-id="7667" fill="#04C361"></path></svg>

+ 3 - 0
src/components/Card/index.ts

@@ -0,0 +1,3 @@
+import CardTitle from './src/CardTitle.vue'
+
+export { CardTitle }

+ 37 - 0
src/components/Card/src/CardTitle.vue

@@ -0,0 +1,37 @@
+<script lang="ts" setup>
+defineComponent({
+  name: 'CardTitle'
+})
+
+const { title } = defineProps({
+  title: {
+    type: String,
+    required: true
+  }
+})
+</script>
+
+<template>
+  <span class="card-title">{{ title }}</span>
+</template>
+
+<style scoped lang="scss">
+.card-title {
+  font-size: 14px;
+  font-weight: 600;
+
+  &::before {
+    position: relative;
+    top: 8px;
+    left: -5px;
+    display: inline-block;
+    width: 3px;
+    height: 14px;
+    //background-color: #105cfb;
+    background: var(--el-color-primary);
+    border-radius: 5px;
+    content: '';
+    transform: translateY(-50%);
+  }
+}
+</style>

+ 1 - 1
src/components/ContentDetailWrap/src/ContentDetailWrap.vue

@@ -26,7 +26,7 @@ onMounted(() => {
       <div
         :class="[
           `${prefixCls}-header`,
-          'flex border-bottom-1 h-50px items-center text-center pr-10px'
+          'flex b-b-1 h-50px items-center text-center bg-white pr-10px'
         ]"
       >
         <div :class="[`${prefixCls}-header__back`, 'flex pl-10px pr-10px ']">

+ 3 - 1
src/components/Cropper/src/CopperModal.vue

@@ -220,7 +220,9 @@ $prefix-cls: #{$namespace}-cropper-am;
         transparent 75%,
         rgb(0 0 0 / 25%) 0
       );
-    background-position: 0 0, 12px 12px;
+    background-position:
+      0 0,
+      12px 12px;
     background-size: 24px 24px;
   }
 

+ 2 - 2
src/components/Cropper/src/CropperAvatar.vue

@@ -1,7 +1,7 @@
 <template>
   <div class="user-info-head" @click="open()">
-    <img v-if="sourceValue" :src="sourceValue" alt="avatar" class="img-circle img-lg" />
-    <img v-if="!sourceValue" :src="avatar" alt="avatar" class="img-circle img-lg" />
+    <el-avatar v-if="sourceValue" :src="sourceValue" alt="avatar" class="img-circle img-lg" />
+    <el-avatar v-if="!sourceValue" :src="avatar" alt="avatar" class="img-circle img-lg" />
     <el-button v-if="showBtn" :class="`${prefixCls}-upload-btn`" @click="open()">
       {{ btnText ? btnText : t('cropper.selectImage') }}
     </el-button>

+ 2 - 1
src/components/Descriptions/index.ts

@@ -1,3 +1,4 @@
 import Descriptions from './src/Descriptions.vue'
+import DescriptionsItemLabel from './src/DescriptionsItemLabel.vue'
 
-export { Descriptions }
+export { Descriptions, DescriptionsItemLabel }

+ 2 - 2
src/components/Descriptions/src/Descriptions.vue

@@ -69,14 +69,14 @@ const toggleClick = () => {
   <div
     :class="[
       prefixCls,
-      'bg-[var(--el-color-white)] dark:(bg-[var(--el-bg-color)] border-[var(--el-border-color)] border-1px)'
+      'bg-[var(--el-color-white)] dark:bg-[var(--el-bg-color)] dark:border-[var(--el-border-color)] dark:border-1px'
     ]"
   >
     <div
       v-if="title"
       :class="[
         `${prefixCls}-header`,
-        'h-50px flex justify-between items-center border-bottom-1 border-solid border-[var(--tags-view-border-color)] px-10px cursor-pointer dark:border-[var(--el-border-color)]'
+        'h-50px flex justify-between items-center b-b-1 border-solid border-[var(--el-border-color)] px-10px cursor-pointer dark:border-[var(--el-border-color)]'
       ]"
       @click="toggleClick"
     >

+ 29 - 0
src/components/Descriptions/src/DescriptionsItemLabel.vue

@@ -0,0 +1,29 @@
+<script setup lang="ts">
+const { label } = defineProps({
+  label: {
+    type: String,
+    required: true
+  },
+  icon: {
+    type: String,
+    required: false
+  }
+})
+</script>
+
+<template>
+  <div class="cell-item">
+    <Icon :icon="icon" v-if="icon" style="vertical-align: middle" :size="18" />
+    {{ label }}
+  </div>
+</template>
+
+<style scoped lang="scss">
+.cell-item {
+  display: inline;
+}
+
+.cell-item::after {
+  content: ':';
+}
+</style>

+ 50 - 34
src/components/Dialog/src/Dialog.vue

@@ -10,7 +10,7 @@ const props = defineProps({
   fullscreen: propTypes.bool.def(true),
   width: propTypes.oneOfType([String, Number]).def('40%'),
   scroll: propTypes.bool.def(false), // 是否开启滚动条。如果是的话,按照 maxHeight 设置最大高度
-  maxHeight: propTypes.oneOfType([String, Number]).def('300px')
+  maxHeight: propTypes.oneOfType([String, Number]).def('400px')
 })
 
 const getBindValue = computed(() => {
@@ -36,7 +36,6 @@ const dialogHeight = ref(isNumber(props.maxHeight) ? `${props.maxHeight}px` : pr
 watch(
   () => isFullscreen.value,
   async (val: boolean) => {
-    // 计算最大高度
     await nextTick()
     if (val) {
       const windowHeight = document.documentElement.offsetHeight
@@ -59,36 +58,47 @@ const dialogStyle = computed(() => {
 
 <template>
   <ElDialog
+    v-bind="getBindValue"
     :close-on-click-modal="true"
     :fullscreen="isFullscreen"
     :width="width"
     destroy-on-close
-    draggable
     lock-scroll
-    v-bind="getBindValue"
+    draggable
+    class="com-dialog"
+    :show-close="false"
   >
-    <template #header>
-      <div class="flex justify-between">
+    <template #header="{ close }">
+      <div class="flex justify-between items-center h-54px pl-15px pr-15px relative">
         <slot name="title">
           {{ title }}
         </slot>
-        <Icon
-          v-if="fullscreen"
-          :icon="isFullscreen ? 'zmdi:fullscreen-exit' : 'zmdi:fullscreen'"
-          class="mr-22px cursor-pointer is-hover mt-2px z-10"
-          color="var(--el-color-info)"
-          @click="toggleFull"
-        />
+        <div
+          class="h-54px flex justify-between items-center absolute top-[50%] right-15px translate-y-[-50%]"
+        >
+          <Icon
+            v-if="fullscreen"
+            class="cursor-pointer is-hover mr-10px"
+            :icon="isFullscreen ? 'radix-icons:exit-full-screen' : 'radix-icons:enter-full-screen'"
+            color="var(--el-color-info)"
+            hover-color="var(--el-color-primary)"
+            @click="toggleFull"
+          />
+          <Icon
+            class="cursor-pointer is-hover"
+            icon="ep:close"
+            hover-color="var(--el-color-primary)"
+            color="var(--el-color-info)"
+            @click="close"
+          />
+        </div>
       </div>
     </template>
 
-    <!-- 情况一:如果 scroll 为 true,说明开启滚动条 -->
     <ElScrollbar v-if="scroll" :style="dialogStyle">
       <slot></slot>
     </ElScrollbar>
-    <!-- 情况二:如果 scroll 为 false,说明关闭滚动条滚动条 -->
     <slot v-else></slot>
-
     <template v-if="slots.footer" #footer>
       <slot name="footer"></slot>
     </template>
@@ -96,28 +106,34 @@ const dialogStyle = computed(() => {
 </template>
 
 <style lang="scss">
-.#{$elNamespace}-dialog__header {
-  margin-right: 0 !important;
-  border-bottom: 1px solid var(--tags-view-border-color);
-}
+.com-dialog {
+  .#{$elNamespace}-overlay-dialog {
+    display: flex;
+    justify-content: center;
+    align-items: center;
+  }
 
-.#{$elNamespace}-dialog__footer {
-  border-top: 1px solid var(--tags-view-border-color);
-}
+  .#{$elNamespace}-dialog {
+    margin: 0 !important;
 
-.is-hover {
-  &:hover {
-    color: var(--el-color-primary) !important;
-  }
-}
+    &__header {
+      height: 54px;
+      padding: 0;
+      margin-right: 0 !important;
+      border-bottom: 1px solid var(--el-border-color);
+    }
 
-.dark {
-  .#{$elNamespace}-dialog__header {
-    border-bottom: 1px solid var(--el-border-color);
-  }
+    &__body {
+      padding: 15px !important;
+    }
+
+    &__footer {
+      border-top: 1px solid var(--el-border-color);
+    }
 
-  .#{$elNamespace}-dialog__footer {
-    border-top: 1px solid var(--el-border-color);
+    &__headerbtn {
+      top: 0;
+    }
   }
 }
 </style>

+ 2 - 3
src/components/Editor/src/Editor.vue

@@ -162,7 +162,6 @@ const handleChange = (editor: IDomEditor) => {
 // 组件销毁时,及时销毁编辑器
 onBeforeUnmount(() => {
   const editor = unref(editorRef.value)
-  if (editor === null) return
 
   // 销毁,并移除 editor
   editor?.destroy()
@@ -179,12 +178,12 @@ defineExpose({
 </script>
 
 <template>
-  <div class="border-1 border-solid border-[var(--tags-view-border-color)] z-99">
+  <div class="border-1 border-solid border-[var(--el-border-color)] z-99">
     <!-- 工具栏 -->
     <Toolbar
       :editor="editorRef"
       :editorId="editorId"
-      class="border-bottom-1 border-solid border-[var(--tags-view-border-color)]"
+      class="border-0 b-b-1 border-solid border-[var(--el-border-color)]"
     />
     <!-- 编辑器 -->
     <Editor

+ 3 - 1
src/components/InputPassword/src/InputPassword.vue

@@ -112,7 +112,9 @@ $prefix-cls: #{$namespace}-input-password;
       height: inherit;
       background-color: transparent;
       border-radius: inherit;
-      transition: width 0.5s ease-in-out, background 0.25s;
+      transition:
+        width 0.5s ease-in-out,
+        background 0.25s;
 
       &[data-score='0'] {
         width: 20%;

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

@@ -8,14 +8,26 @@
     :page-sizes="[10, 20, 30, 50, 100]"
     :pager-count="pagerCount"
     :total="total"
+    :small="isSmall"
     class="float-right mt-15px mb-15px"
     layout="total, sizes, prev, pager, next, jumper"
     @size-change="handleSizeChange"
     @current-change="handleCurrentChange"
   />
 </template>
-<script name="Pagination" setup>
-import { computed } from 'vue'
+<script lang="ts" setup>
+import { computed, watchEffect } from 'vue'
+import { useAppStore } from '@/store/modules/app'
+
+defineOptions({ name: 'Pagination' })
+
+// 此处解决了当全局size为small的时候分页组件样式太大的问题
+const appStore = useAppStore()
+const layoutCurrentSize = computed(() => appStore.currentSize)
+const isSmall = ref<boolean>(layoutCurrentSize.value === 'small')
+watchEffect(() => {
+  isSmall.value = layoutCurrentSize.value === 'small'
+})
 
 const props = defineProps({
   // 总条目数

+ 2 - 1
src/config/axios/index.ts

@@ -5,12 +5,13 @@ import { config } from './config'
 const { default_headers } = config
 
 const request = (option: any) => {
-  const { url, method, params, data, headersType, responseType } = option
+  const { url, method, params, data, headersType, responseType, ...config } = option
   return service({
     url: url,
     method,
     params,
     data,
+    ...config,
     responseType: responseType,
     headers: {
       'Content-Type': headersType || default_headers

+ 35 - 17
src/hooks/web/useCrudSchemas.ts

@@ -9,6 +9,7 @@ import { TableColumn } from '@/types/table'
 import { DescriptionsSchema } from '@/types/descriptions'
 import { ComponentOptions, ComponentProps } from '@/types/components'
 import { DictTag } from '@/components/DictTag'
+import { cloneDeep, merge } from 'lodash-es'
 
 export type CrudSchema = Omit<TableColumn, 'children'> & {
   isSearch?: boolean // 是否在查询显示
@@ -116,14 +117,18 @@ const filterSearchSchema = (crudSchema: CrudSchema[], allSchemas: AllSchemas): F
         }
         if (!schemaItem.search?.component) component = 'Select'
       }
-      const searchSchemaItem = {
-        // 默认为 input
-        component: component,
-        componentProps: comonentProps,
-        ...schemaItem.search,
-        field: schemaItem.field,
-        label: schemaItem.search?.label || schemaItem.label
-      }
+
+      // updated by AKing: 解决了当使用默认的dict选项时,form中事件不能触发的问题
+      const searchSchemaItem = merge(
+        {
+          // 默认为 input
+          component,
+          ...schemaItem.search,
+          field: schemaItem.field,
+          label: schemaItem.search?.label || schemaItem.label
+        },
+        { componentProps: comonentProps }
+      )
       if (searchSchemaItem.api) {
         searchRequestTask.push(async () => {
           const res = await (searchSchemaItem.api as () => AxiosPromise)()
@@ -223,15 +228,19 @@ const filterFormSchema = (crudSchema: CrudSchema[], allSchemas: AllSchemas): For
         }
         if (!(schemaItem.form && schemaItem.form.component)) component = 'Select'
       }
-      const formSchemaItem = {
-        // 默认为 input
-        component: component,
-        componentProps: comonentProps,
-        value: defaultValue,
-        ...schemaItem.form,
-        field: schemaItem.field,
-        label: schemaItem.form?.label || schemaItem.label
-      }
+
+      // updated by AKing: 解决了当使用默认的dict选项时,form中事件不能触发的问题
+      const formSchemaItem = merge(
+        {
+          // 默认为 input
+          component,
+          value: defaultValue,
+          ...schemaItem.form,
+          field: schemaItem.field,
+          label: schemaItem.form?.label || schemaItem.label
+        },
+        { componentProps: comonentProps }
+      )
 
       if (formSchemaItem.api) {
         formRequestTask.push(async () => {
@@ -306,3 +315,12 @@ const filterOptions = (options: Recordable, labelField?: string) => {
     return v
   })
 }
+
+// 将 tableColumns 指定 fields 放到最前面
+export const sortTableColumns = (tableColumns: TableColumn[], field: string) => {
+  const fieldIndex = tableColumns.findIndex((item) => item.field === field)
+  const fieldColumn = cloneDeep(tableColumns[fieldIndex])
+  tableColumns.splice(fieldIndex, 1)
+  // 添加到开头
+  tableColumns.unshift(fieldColumn)
+}

+ 17 - 10
src/layout/components/AppView.vue

@@ -16,26 +16,33 @@ const tagsViewStore = useTagsViewStore()
 const getCaches = computed((): string[] => {
   return tagsViewStore.getCachedViews
 })
+
+const tagsView = computed(() => appStore.getTagsView)
 </script>
 
 <template>
   <section
     :class="[
-      'p-[var(--app-content-padding)] w-[100%] bg-[var(--app-content-bg-color)] dark:bg-[var(--el-bg-color)]',
+      'p-[var(--app-content-padding)] w-[calc(100%-var(--app-content-padding)-var(--app-content-padding))] bg-[var(--app-content-bg-color)] dark:bg-[var(--el-bg-color)]',
       {
-        '!min-h-[calc(100%-var(--app-footer-height))]':
-          ((fixedHeader && (layout === 'classic' || layout === 'topLeft')) || layout === 'top') &&
-          footer,
-
-        '!min-h-[calc(100%-var(--tags-view-height)-var(--top-tool-height)-var(--app-footer-height))]':
+        '!min-h-[calc(100%-var(--app-content-padding)-var(--app-content-padding)-var(--app-footer-height))]':
+          (fixedHeader &&
+            (layout === 'classic' || layout === 'topLeft' || layout === 'top') &&
+            footer) ||
+          (!tagsView && layout === 'top' && footer),
+        '!min-h-[calc(100%-var(--app-content-padding)-var(--app-content-padding)-var(--app-footer-height)-var(--tags-view-height))]':
+          tagsView && layout === 'top' && footer,
+
+        '!min-h-[calc(100%-var(--tags-view-height)-var(--app-content-padding)-var(--app-content-padding)-var(--top-tool-height)-var(--app-footer-height))]':
           !fixedHeader && layout === 'classic' && footer,
 
-        '!min-h-[calc(100%-var(--tags-view-height)-var(--app-footer-height))]':
-          !fixedHeader && (layout === 'topLeft' || layout === 'top') && footer,
+        '!min-h-[calc(100%-var(--tags-view-height)-var(--app-content-padding)-var(--app-content-padding)-var(--app-footer-height))]':
+          !fixedHeader && layout === 'topLeft' && footer,
 
-        '!min-h-[calc(100%-var(--top-tool-height))]': fixedHeader && layout === 'cutMenu' && footer,
+        '!min-h-[calc(100%-var(--top-tool-height)-var(--app-content-padding)-var(--app-content-padding))]':
+          fixedHeader && layout === 'cutMenu' && footer,
 
-        '!min-h-[calc(100%-var(--top-tool-height)-var(--tags-view-height))]':
+        '!min-h-[calc(100%-var(--top-tool-height)-var(--app-content-padding)-var(--app-content-padding)-var(--tags-view-height))]':
           !fixedHeader && layout === 'cutMenu' && footer
       }
     ]"

+ 1 - 1
src/layout/components/Footer/src/Footer.vue

@@ -17,7 +17,7 @@ const title = computed(() => appStore.getTitle)
 <template>
   <div
     :class="prefixCls"
-    class="text-center text-[var(--el-text-color-placeholder)] bg-[var(--app-contnet-bg-color)] h-[var(--app-footer-height)] leading-[var(--app-footer-height)] dark:bg-[var(--el-bg-color)]"
+    class="text-center text-[var(--el-text-color-placeholder)] bg-[var(--app-content-bg-color)] h-[var(--app-footer-height)] leading-[var(--app-footer-height)] dark:bg-[var(--el-bg-color)]"
   >
     <p style="font-size: 14px">Copyright ©2022-{{ title }}</p>
   </div>

+ 1 - 1
src/layout/components/LocaleDropdown/src/LocaleDropdown.vue

@@ -36,7 +36,7 @@ const setLang = (lang: LocaleType) => {
       :class="$attrs.class"
       :color="color"
       :size="18"
-      class="cursor-pointer"
+      class="cursor-pointer !p-0"
       icon="ion:language-sharp"
     />
     <template #dropdown>

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

@@ -60,8 +60,7 @@ watch(
       :class="[
         prefixCls,
         layout !== 'classic' ? `${prefixCls}__Top` : '',
-        'flex !h-[var(--logo-height)] items-center cursor-pointer justify-center relative',
-        'dark:bg-[var(--el-bg-color)]'
+        'flex !h-[var(--logo-height)] items-center cursor-pointer pl-8px relative decoration-none overflow-hidden'
       ]"
       to="/"
     >

+ 4 - 13
src/layout/components/Menu/src/Menu.vue

@@ -138,15 +138,6 @@ $prefix-cls: #{$namespace}-menu;
   position: relative;
   transition: width var(--transition-time-02);
 
-  &:after {
-    position: absolute;
-    top: 0;
-    right: 0;
-    height: 100%;
-    border-left: 1px solid var(--left-menu-border-color);
-    content: '';
-  }
-
   :deep(.#{$elNamespace}-menu) {
     width: 100% !important;
     border-right: none;
@@ -181,7 +172,7 @@ $prefix-cls: #{$namespace}-menu;
     .#{$elNamespace}-menu-item.is-active {
       position: relative;
 
-      &:after {
+      &::after {
         @extend .is-active--after;
       }
     }
@@ -204,7 +195,7 @@ $prefix-cls: #{$namespace}-menu;
       position: relative;
       background-color: var(--left-menu-collapse-bg-active-color) !important;
 
-      &:after {
+      &::after {
         @extend .is-active--after;
       }
     }
@@ -235,7 +226,7 @@ $prefix-cls: #{$namespace}-menu;
       .#{$elNamespace}-menu-item.is-active {
         position: relative;
 
-        &:after {
+        &::after {
           display: none !important;
         }
       }
@@ -291,7 +282,7 @@ $prefix-cls: #{$namespace}-menu-popper;
       background-color: var(--left-menu-bg-active-color) !important;
     }
 
-    &:after {
+    &::after {
       @extend .is-active--after;
     }
   }

+ 6 - 3
src/layout/components/Message/src/Message.vue

@@ -33,9 +33,12 @@ onMounted(() => {
   // 首次加载小红点
   getUnreadCount()
   // 轮询刷新小红点
-  timer = setInterval(() => {
-    getUnreadCount()
-  }, 1000 * 60 * 2)
+  timer = setInterval(
+    () => {
+      getUnreadCount()
+    },
+    1000 * 60 * 2
+  )
 })
 onUnmounted(() => {
   clearInterval(timer)

+ 0 - 1
src/layout/components/Setting/src/Setting.vue

@@ -42,7 +42,6 @@ const setHeaderTheme = (color: string) => {
   setCssVar('--top-header-bg-color', color)
   setCssVar('--top-header-text-color', textColor)
   setCssVar('--top-header-hover-color', textHoverColor)
-  setCssVar('--top-tool-border-color', topToolBorderColor)
   appStore.setTheme({
     topHeaderBgColor: color,
     topHeaderTextColor: textColor,

+ 2 - 13
src/layout/components/TabMenu/src/TabMenu.vue

@@ -139,7 +139,7 @@ export default defineComponent({
         id={`${variables.namespace}-menu`}
         class={[
           prefixCls,
-          'relative bg-[var(--left-menu-bg-color)] top-1px z-3000',
+          'relative bg-[var(--left-menu-bg-color)] top-1px z-3000 layout-border__right',
           {
             'w-[var(--tab-menu-max-width)]': !unref(collapse),
             'w-[var(--tab-menu-min-width)]': unref(collapse)
@@ -195,7 +195,7 @@ export default defineComponent({
         </div>
         <Menu
           class={[
-            '!absolute top-0 border-left-1 border-solid border-[var(--left-menu-bg-light-color)]',
+            '!absolute top-0',
             {
               '!left-[var(--tab-menu-min-width)]': unref(collapse),
               '!left-[var(--tab-menu-max-width)]': !unref(collapse),
@@ -217,16 +217,6 @@ $prefix-cls: #{$namespace}-tab-menu;
 .#{$prefix-cls} {
   transition: all var(--transition-time-02);
 
-  &::after {
-    position: absolute;
-    top: 0;
-    right: 0;
-    width: 1px;
-    height: 100%;
-    border-left: 1px solid var(--left-menu-border-color);
-    content: '';
-  }
-
   &__item {
     color: var(--left-menu-text-color);
     transition: all var(--transition-time-02);
@@ -240,7 +230,6 @@ $prefix-cls: #{$namespace}-tab-menu;
   &--collapse {
     color: var(--left-menu-text-color);
     background-color: var(--left-menu-bg-light-color);
-    border-top: 1px solid var(--left-menu-border-color);
   }
 
   .is-active {

+ 54 - 58
src/layout/components/TagsView/src/TagsView.vue

@@ -7,9 +7,9 @@ import { useAppStore } from '@/store/modules/app'
 import { filterAffixTags } from './helper'
 import { ContextMenu, ContextMenuExpose } from '@/layout/components/ContextMenu'
 import { useDesign } from '@/hooks/web/useDesign'
+import { useTemplateRefsList } from '@vueuse/core'
 import { ElScrollbar } from 'element-plus'
 import { useScrollTo } from '@/hooks/event/useScrollTo'
-import { useTemplateRefsList } from '@vueuse/core'
 
 const { getPrefixCls } = useDesign()
 
@@ -33,6 +33,8 @@ const appStore = useAppStore()
 
 const tagsViewIcon = computed(() => appStore.getTagsViewIcon)
 
+const isDark = computed(() => appStore.getIsDark)
+
 // 初始化tag
 const initTags = () => {
   affixTagArr.value = filterAffixTags(unref(routers))
@@ -71,7 +73,7 @@ const closeAllTags = () => {
   toLastView()
 }
 
-// 关闭其
+// 关闭其
 const closeOthersTags = () => {
   tagsViewStore.delOthersViews(unref(selectedTag) as RouteLocationNormalizedLoaded)
 }
@@ -126,6 +128,7 @@ const moveToCurrentTag = async () => {
       if (v.fullPath !== unref(currentRoute).fullPath) {
         tagsViewStore.updateVisitedView(unref(currentRoute))
       }
+
       break
     }
   }
@@ -261,29 +264,21 @@ watch(
     class="flex w-full relative bg-[#fff] dark:bg-[var(--el-bg-color)]"
   >
     <span
-      :class="`${prefixCls}__tool`"
-      class="w-[var(--tags-view-height)] h-[var(--tags-view-height)] cursor-pointer"
+      :class="`${prefixCls}__tool ${prefixCls}__tool--first`"
+      class="w-[var(--tags-view-height)] h-[var(--tags-view-height)] flex items-center justify-center cursor-pointer"
       @click="move(-200)"
     >
       <Icon
-        :color="appStore.getIsDark ? 'var(--el-text-color-regular)' : '#333'"
         icon="ep:d-arrow-left"
+        color="var(--el-text-color-placeholder)"
+        :hover-color="isDark ? '#fff' : 'var(--el-color-black)'"
       />
     </span>
     <div class="overflow-hidden flex-1">
       <ElScrollbar ref="scrollbarRef" class="h-full" @scroll="scroll">
         <div class="flex h-full">
           <ContextMenu
-            v-for="item in visitedViews"
-            :key="item.fullPath"
             :ref="itemRefs.set"
-            :class="[
-              `${prefixCls}__item`,
-              item?.meta?.affix ? `${prefixCls}__item--affix` : '',
-              {
-                'is-active': isActive(item)
-              }
-            ]"
             :schema="[
               {
                 icon: 'ep:refresh',
@@ -341,14 +336,23 @@ watch(
                 }
               }
             ]"
+            v-for="item in visitedViews"
+            :key="item.fullPath"
             :tag-item="item"
+            :class="[
+              `${prefixCls}__item`,
+              item?.meta?.affix ? `${prefixCls}__item--affix` : '',
+              {
+                'is-active': isActive(item)
+              }
+            ]"
             @visible-change="visibleChange"
           >
             <div>
-              <router-link :ref="tagLinksRefs.set" v-slot="{ navigate }" :to="{ ...item }" custom>
+              <router-link :ref="tagLinksRefs.set" :to="{ ...item }" custom v-slot="{ navigate }">
                 <div
-                  class="h-full flex justify-center items-center whitespace-nowrap pl-15px"
                   @click="navigate"
+                  class="h-full flex justify-center items-center whitespace-nowrap pl-15px"
                 >
                   <Icon
                     v-if="
@@ -364,9 +368,9 @@ watch(
                   {{ t(item?.meta?.title as string) }}
                   <Icon
                     :class="`${prefixCls}__item--close`"
-                    :size="12"
                     color="#333"
                     icon="ep:close"
+                    :size="12"
                     @click.prevent.stop="closeSelectedTag(item)"
                   />
                 </div>
@@ -378,25 +382,28 @@ watch(
     </div>
     <span
       :class="`${prefixCls}__tool`"
-      class="w-[var(--tags-view-height)] h-[var(--tags-view-height)] text-center leading-[var(--tags-view-height)] cursor-pointer"
+      class="w-[var(--tags-view-height)] h-[var(--tags-view-height)] flex items-center justify-center cursor-pointer"
       @click="move(200)"
     >
       <Icon
-        :color="appStore.getIsDark ? 'var(--el-text-color-regular)' : '#333'"
         icon="ep:d-arrow-right"
+        color="var(--el-text-color-placeholder)"
+        :hover-color="isDark ? '#fff' : 'var(--el-color-black)'"
       />
     </span>
     <span
       :class="`${prefixCls}__tool`"
-      class="w-[var(--tags-view-height)] h-[var(--tags-view-height)] text-center leading-[var(--tags-view-height)] cursor-pointer"
+      class="w-[var(--tags-view-height)] h-[var(--tags-view-height)] flex items-center justify-center cursor-pointer"
       @click="refreshSelectedTag(selectedTag)"
     >
       <Icon
-        :color="appStore.getIsDark ? 'var(--el-text-color-regular)' : '#333'"
         icon="ep:refresh-right"
+        color="var(--el-text-color-placeholder)"
+        :hover-color="isDark ? '#fff' : 'var(--el-color-black)'"
       />
     </span>
     <ContextMenu
+      trigger="click"
       :schema="[
         {
           icon: 'ep:refresh',
@@ -448,15 +455,15 @@ watch(
           }
         }
       ]"
-      trigger="click"
     >
       <span
         :class="`${prefixCls}__tool`"
-        class="w-[var(--tags-view-height)] h-[var(--tags-view-height)] text-center leading-[var(--tags-view-height)] cursor-pointer block"
+        class="w-[var(--tags-view-height)] h-[var(--tags-view-height)] flex items-center justify-center cursor-pointer block"
       >
         <Icon
-          :color="appStore.getIsDark ? 'var(--el-text-color-regular)' : '#333'"
           icon="ep:menu"
+          color="var(--el-text-color-placeholder)"
+          :hover-color="isDark ? '#fff' : 'var(--el-color-black)'"
         />
       </span>
     </ContextMenu>
@@ -473,47 +480,49 @@ $prefix-cls: #{$namespace}-tags-view;
 
   &__tool {
     position: relative;
-    display: inline-flex;
-    align-items: center;
-    justify-content: center;
 
-    &:hover {
-      :deep(span) {
-        color: var(--el-color-black) !important;
-      }
-    }
-
-    &:after {
+    &::before {
       position: absolute;
       top: 1px;
       left: 0;
       width: 100%;
       height: calc(100% - 1px);
-      border-right: 1px solid var(--tags-view-border-color);
-      border-left: 1px solid var(--tags-view-border-color);
+      border-left: 1px solid var(--el-border-color);
       content: '';
     }
+
+    &--first {
+      &::before {
+        position: absolute;
+        top: 1px;
+        left: 0;
+        width: 100%;
+        height: calc(100% - 1px);
+        border-right: 1px solid var(--el-border-color);
+        border-left: none;
+        content: '';
+      }
+    }
   }
 
   &__item {
     position: relative;
     top: 2px;
-    height: calc(100% - 4px);
-    padding-right: 16px;
+    height: calc(100% - 6px);
+    padding-right: 25px;
     margin-left: 4px;
     font-size: 12px;
-    border-radius: 3px 3px 3px 3px;
     cursor: pointer;
     border: 1px solid #d9d9d9;
+    border-radius: 2px;
 
     &--close {
       position: absolute;
       top: 50%;
-      right: 3px;
+      right: 5px;
       display: none;
       transform: translate(0, -50%);
     }
-
     &:not(.#{$prefix-cls}__item--affix):hover {
       .#{$prefix-cls}__item--close {
         display: block;
@@ -531,7 +540,6 @@ $prefix-cls: #{$namespace}-tags-view;
     color: var(--el-color-white);
     background-color: var(--el-color-primary);
     border: 1px solid var(--el-color-primary);
-
     .#{$prefix-cls}__item--close {
       :deep(span) {
         color: var(--el-color-white) !important;
@@ -543,26 +551,14 @@ $prefix-cls: #{$namespace}-tags-view;
 .dark {
   .#{$prefix-cls} {
     &__tool {
-      &:hover {
-        :deep(span) {
-          color: #fff !important;
+      &--first {
+        &::after {
+          display: none;
         }
       }
-
-      &:after {
-        border-right: 1px solid var(--el-border-color);
-        border-left: 1px solid var(--el-border-color);
-      }
     }
 
     &__item {
-      position: relative;
-      top: 2px;
-      height: calc(100% - 4px);
-      padding-right: 16px;
-      font-size: 12px;
-      border-radius: 3px 3px 3px 3px;
-      cursor: pointer;
       border: 1px solid var(--el-border-color);
     }
 
@@ -575,7 +571,7 @@ $prefix-cls: #{$namespace}-tags-view;
     &__item.is-active {
       color: var(--el-color-white);
       background-color: var(--el-color-primary);
-
+      border: 1px solid var(--el-color-primary);
       .#{$prefix-cls}__item--close {
         :deep(span) {
           color: var(--el-color-white) !important;

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

@@ -52,28 +52,28 @@ export default defineComponent({
         {layout.value !== 'top' ? (
           <div class="h-full flex items-center">
             {hamburger.value && layout.value !== 'cutMenu' ? (
-              <Collapse class="hover-trigger" color="var(--top-header-text-color)"></Collapse>
+              <Collapse class="custom-hover" color="var(--top-header-text-color)"></Collapse>
             ) : undefined}
-            {breadcrumb.value ? <Breadcrumb class="<md:hidden"></Breadcrumb> : undefined}
+            {breadcrumb.value ? <Breadcrumb class="lt-md:hidden"></Breadcrumb> : undefined}
           </div>
         ) : undefined}
         <div class="h-full flex items-center">
           {screenfull.value ? (
-            <Screenfull class="hover-trigger" color="var(--top-header-text-color)"></Screenfull>
+            <Screenfull class="custom-hover" color="var(--top-header-text-color)"></Screenfull>
           ) : undefined}
           {size.value ? (
-            <SizeDropdown class="hover-trigger" color="var(--top-header-text-color)"></SizeDropdown>
+            <SizeDropdown class="custom-hover" color="var(--top-header-text-color)"></SizeDropdown>
           ) : undefined}
           {locale.value ? (
             <LocaleDropdown
-              class="hover-trigger"
+              class="custom-hover"
               color="var(--top-header-text-color)"
             ></LocaleDropdown>
           ) : undefined}
           {message.value ? (
-            <Message class="hover-trigger" color="var(--top-header-text-color)"></Message>
+            <Message class="custom-hover" color="var(--top-header-text-color)"></Message>
           ) : undefined}
-          <UserInfo class="hover-trigger"></UserInfo>
+          <UserInfo></UserInfo>
         </div>
       </div>
     )

+ 2 - 2
src/layout/components/UserInfo/src/UserInfo.vue

@@ -49,9 +49,9 @@ const toDocument = () => {
 </script>
 
 <template>
-  <ElDropdown :class="prefixCls" trigger="click">
+  <ElDropdown class="custom-hover" :class="prefixCls" trigger="click">
     <div class="flex items-center">
-      <img :src="avatar" alt="" class="w-[calc(var(--logo-height)-25px)] rounded-[50%]" />
+      <ElAvatar :src="avatar" alt="" class="w-[calc(var(--logo-height)-25px)] rounded-[50%]" />
       <span class="<lg:hidden text-14px pl-[5px] text-[var(--top-header-text-color)]">
         {{ userName }}
       </span>

+ 54 - 26
src/layout/components/useRenderLayout.tsx

@@ -39,11 +39,16 @@ export const useRenderLayout = () => {
   const renderClassic = () => {
     return (
       <>
-        <div class={['absolute top-0 left-0 h-full', { '!fixed z-3000': mobile.value }]}>
+        <div
+          class={[
+            'absolute top-0 left-0 h-full layout-border__right',
+            { '!fixed z-3000': mobile.value }
+          ]}
+        >
           {logo.value ? (
             <Logo
               class={[
-                'bg-[var(--left-menu-bg-color)] border-bottom-1 border-solid border-[var(--logo-border-color)] dark:border-[var(--el-border-color)]',
+                'bg-[var(--left-menu-bg-color)] relative',
                 {
                   '!pl-0': mobile.value && collapse.value,
                   'w-[var(--left-menu-min-width)]': appStore.getCollapse,
@@ -83,19 +88,26 @@ export const useRenderLayout = () => {
               class={[
                 {
                   'fixed top-0 left-0 z-10': fixedHeader.value,
-                  'w-[calc(100%-var(--left-menu-min-width))] left-[var(--left-menu-min-width)]':
+                  'w-[calc(100%-var(--left-menu-min-width))] !left-[var(--left-menu-min-width)]':
                     collapse.value && fixedHeader.value && !mobile.value,
-                  'w-[calc(100%-var(--left-menu-max-width))] left-[var(--left-menu-max-width)]':
+                  'w-[calc(100%-var(--left-menu-max-width))] !left-[var(--left-menu-max-width)]':
                     !collapse.value && fixedHeader.value && !mobile.value,
                   '!w-full !left-0': mobile.value
                 }
               ]}
               style="transition: all var(--transition-time-02);"
             >
-              <ToolHeader class="border-bottom-1 border-solid border-[var(--top-tool-border-color)] bg-[var(--top-header-bg-color)] dark:border-[var(--el-border-color)]"></ToolHeader>
+              <ToolHeader
+                class={[
+                  'bg-[var(--top-header-bg-color)]',
+                  {
+                    'layout-border__bottom': !tagsView.value
+                  }
+                ]}
+              ></ToolHeader>
 
               {tagsView.value ? (
-                <TagsView class="border-bottom-1 border-top-1 border-solid border-[var(--tags-view-border-color)] dark:border-[var(--el-border-color)]"></TagsView>
+                <TagsView class="layout-border__bottom layout-border__top"></TagsView>
               ) : undefined}
             </div>
 
@@ -109,13 +121,13 @@ export const useRenderLayout = () => {
   const renderTopLeft = () => {
     return (
       <>
-        <div class="flex items-center bg-[var(--top-header-bg-color)] border-bottom-1 border-solid border-[var(--top-tool-border-color)] dark:border-[var(--el-border-color)]">
-          {logo.value ? <Logo class="hover-trigger !pr-15px"></Logo> : undefined}
+        <div class="flex items-center bg-[var(--top-header-bg-color)] relative layout-border__bottom dark:bg-[var(--el-bg-color)]">
+          {logo.value ? <Logo class="custom-hover"></Logo> : undefined}
 
           <ToolHeader class="flex-1"></ToolHeader>
         </div>
         <div class="absolute top-[var(--logo-height)+1px] left-0 w-full h-[calc(100%-1px-var(--logo-height))] flex">
-          <Menu class="!h-full"></Menu>
+          <Menu class="!h-full relative layout-border__right"></Menu>
           <div
             class={[
               `${prefixCls}-content`,
@@ -142,12 +154,12 @@ export const useRenderLayout = () => {
               {tagsView.value ? (
                 <TagsView
                   class={[
-                    'border-bottom-1 border-top-1 border-solid border-[var(--tags-view-border-color)] dark:border-[var(--el-border-color)]',
+                    'layout-border__bottom absolute',
                     {
                       '!fixed top-0 left-0 z-10': fixedHeader.value,
-                      'w-[calc(100%-var(--left-menu-min-width))] left-[var(--left-menu-min-width)] mt-[var(--logo-height)]':
+                      'w-[calc(100%-var(--left-menu-min-width))] !left-[var(--left-menu-min-width)] mt-[calc(var(--logo-height)+1px)]':
                         collapse.value && fixedHeader.value,
-                      'w-[calc(100%-var(--left-menu-max-width))] left-[var(--left-menu-max-width)] mt-[var(--logo-height)]':
+                      'w-[calc(100%-var(--left-menu-max-width))] !left-[var(--left-menu-max-width)] mt-[calc(var(--logo-height)+1px)]':
                         !collapse.value && fixedHeader.value
                     }
                   ]}
@@ -166,12 +178,28 @@ export const useRenderLayout = () => {
   const renderTop = () => {
     return (
       <>
-        <div class="flex items-center justify-between bg-[var(--top-header-bg-color)] border-bottom-1 border-solid border-[var(--top-tool-border-color)] dark:border-[var(--el-border-color)]">
-          {logo.value ? <Logo class="hover-trigger"></Logo> : undefined}
+        <div
+          class={[
+            'flex items-center justify-between bg-[var(--top-header-bg-color)] relative',
+            {
+              'layout-border__bottom': !tagsView.value
+            }
+          ]}
+        >
+          {logo.value ? <Logo class="custom-hover"></Logo> : undefined}
           <Menu class="flex-1 px-10px h-[var(--top-tool-height)]"></Menu>
           <ToolHeader></ToolHeader>
         </div>
-        <div class={[`${prefixCls}-content`, 'h-full w-full']}>
+        <div
+          class={[
+            `${prefixCls}-content`,
+            'w-full',
+            {
+              'h-[calc(100%-var(--app-footer-height))]': !fixedHeader.value,
+              'h-[calc(100%-var(--tags-view-height)-var(--app-footer-height))]': fixedHeader.value
+            }
+          ]}
+        >
           <ElScrollbar
             v-loading={pageLoading.value}
             class={[
@@ -186,9 +214,9 @@ export const useRenderLayout = () => {
             {tagsView.value ? (
               <TagsView
                 class={[
-                  'border-bottom-1 border-top-1 border-solid border-[var(--tags-view-border-color)] dark:border-[var(--el-border-color)]',
+                  'layout-border__bottom layout-border__top relative',
                   {
-                    '!fixed w-full top-[var(--top-tool-height)] left-0': fixedHeader.value
+                    '!fixed w-full top-[calc(var(--top-tool-height)+1px)] left-0': fixedHeader.value
                   }
                 ]}
                 style="transition: width var(--transition-time-02), left var(--transition-time-02);"
@@ -205,12 +233,12 @@ export const useRenderLayout = () => {
   const renderCutMenu = () => {
     return (
       <>
-        <div class="flex items-center bg-[var(--top-header-bg-color)] border-bottom-1 border-solid border-[var(--top-tool-border-color)] dark:border-[var(--el-border-color)]">
-          {logo.value ? <Logo class="hover-trigger !pr-15px"></Logo> : undefined}
+        <div class="flex items-center bg-[var(--top-header-bg-color)] relative layout-border__bottom">
+          {logo.value ? <Logo class="custom-hover !pr-15px"></Logo> : undefined}
 
           <ToolHeader class="flex-1"></ToolHeader>
         </div>
-        <div class="absolute top-[var(--logo-height)] left-0 w-full h-[calc(100%-var(--logo-height))] flex">
+        <div class="absolute top-[var(--logo-height)] left-0 w-[calc(100%-2px)] h-[calc(100%-var(--logo-height))] flex">
           <TabMenu></TabMenu>
           <div
             class={[
@@ -242,18 +270,18 @@ export const useRenderLayout = () => {
               {tagsView.value ? (
                 <TagsView
                   class={[
-                    'border-bottom-1 border-top-1 border-solid border-[var(--tags-view-border-color)] dark:border-[var(--el-border-color)]',
+                    'relative layout-border__bottom layout-border__top',
                     {
                       '!fixed top-0 left-0 z-10': fixedHeader.value,
-                      'w-[calc(100%-var(--tab-menu-min-width))] left-[var(--tab-menu-min-width)] mt-[var(--logo-height)]':
+                      'w-[calc(100%-var(--tab-menu-min-width))] !left-[var(--tab-menu-min-width)] mt-[var(--logo-height)]':
                         collapse.value && fixedHeader.value,
-                      'w-[calc(100%-var(--tab-menu-max-width))] left-[var(--tab-menu-max-width)] mt-[var(--logo-height)]':
+                      'w-[calc(100%-var(--tab-menu-max-width))] !left-[var(--tab-menu-max-width)] mt-[var(--logo-height)]':
                         !collapse.value && fixedHeader.value,
-                      '!fixed top-0 left-[var(--tab-menu-min-width)+var(--left-menu-max-width)] z-10':
+                      '!fixed top-0 !left-[var(--tab-menu-min-width)+var(--left-menu-max-width)] z-10':
                         fixedHeader.value && fixedMenu.value,
-                      'w-[calc(100%-var(--tab-menu-min-width)-var(--left-menu-max-width))] left-[var(--tab-menu-min-width)+var(--left-menu-max-width)] mt-[var(--logo-height)]':
+                      'w-[calc(100%-var(--tab-menu-min-width)-var(--left-menu-max-width))] !left-[var(--tab-menu-min-width)+var(--left-menu-max-width)] mt-[var(--logo-height)]':
                         collapse.value && fixedHeader.value && fixedMenu.value,
-                      'w-[calc(100%-var(--tab-menu-max-width)-var(--left-menu-max-width))] left-[var(--tab-menu-max-width)+var(--left-menu-max-width)] mt-[var(--logo-height)]':
+                      'w-[calc(100%-var(--tab-menu-max-width)-var(--left-menu-max-width))] !left-[var(--tab-menu-max-width)+var(--left-menu-max-width)] mt-[var(--logo-height)]':
                         !collapse.value && fixedHeader.value && fixedMenu.value
                     }
                   ]}

+ 2 - 2
src/main.ts

@@ -1,5 +1,5 @@
-// 引入windi css
-import '@/plugins/windi.css'
+// 引入unocss css
+import '@/plugins/unocss'
 
 // 导入全局的svg图标
 import '@/plugins/svgIcon'

+ 1 - 0
src/plugins/unocss/index.ts

@@ -0,0 +1 @@
+import 'virtual:uno.css'

+ 0 - 3
src/plugins/windi.css/index.ts

@@ -1,3 +0,0 @@
-import 'virtual:windi.css'
-
-import 'virtual:windi-devtools'

+ 90 - 51
src/router/modules/remaining.ts

@@ -5,32 +5,32 @@ const { t } = useI18n()
  * redirect: noredirect        当设置 noredirect 的时候该路由在面包屑导航中不可被点击
  * name:'router-name'          设定路由的名字,一定要填写不然使用<keep-alive>时会出现各种问题
  * meta : {
-    hidden: true              当设置 true 的时候该路由不会再侧边栏出现 如404,login等页面(默认 false)
+ hidden: true              当设置 true 的时候该路由不会再侧边栏出现 如404,login等页面(默认 false)
 
-    alwaysShow: true          当你一个路由下面的 children 声明的路由大于1个时,自动会变成嵌套的模式,
-                              只有一个时,会将那个子路由当做根路由显示在侧边栏,
-                              若你想不管路由下面的 children 声明的个数都显示你的根路由,
-                              你可以设置 alwaysShow: true,这样它就会忽略之前定义的规则,
-                              一直显示根路由(默认 false)
+ alwaysShow: true          当你一个路由下面的 children 声明的路由大于1个时,自动会变成嵌套的模式,
+ 只有一个时,会将那个子路由当做根路由显示在侧边栏,
+ 若你想不管路由下面的 children 声明的个数都显示你的根路由,
+ 你可以设置 alwaysShow: true,这样它就会忽略之前定义的规则,
+ 一直显示根路由(默认 false)
 
-    title: 'title'            设置该路由在侧边栏和面包屑中展示的名字
+ title: 'title'            设置该路由在侧边栏和面包屑中展示的名字
 
-    icon: 'svg-name'          设置该路由的图标
+ icon: 'svg-name'          设置该路由的图标
 
-    noCache: true             如果设置为true,则不会被 <keep-alive> 缓存(默认 false)
+ noCache: true             如果设置为true,则不会被 <keep-alive> 缓存(默认 false)
 
-    breadcrumb: false         如果设置为false,则不会在breadcrumb面包屑中显示(默认 true)
+ breadcrumb: false         如果设置为false,则不会在breadcrumb面包屑中显示(默认 true)
 
-    affix: true               如果设置为true,则会一直固定在tag项中(默认 false)
+ affix: true               如果设置为true,则会一直固定在tag项中(默认 false)
 
-    noTagsView: true          如果设置为true,则不会出现在tag中(默认 false)
+ noTagsView: true          如果设置为true,则不会出现在tag中(默认 false)
 
-    activeMenu: '/dashboard'  显示高亮的路由路径
+ activeMenu: '/dashboard'  显示高亮的路由路径
 
-    followAuth: '/dashboard'  跟随哪个路由进行权限过滤
+ followAuth: '/dashboard'  跟随哪个路由进行权限过滤
 
-    canTo: true               设置为true即使hidden为true,也依然可以进行路由跳转(默认 false)
-  }
+ canTo: true               设置为true即使hidden为true,也依然可以进行路由跳转(默认 false)
+ }
  **/
 const remainingRouter: AppRouteRecordRaw[] = [
   {
@@ -195,22 +195,6 @@ const remainingRouter: AppRouteRecordRaw[] = [
       noTagsView: true
     }
   },
-  {
-    path: '/trade/order',
-    component: Layout,
-    name: 'order',
-    meta: {
-      hidden: true
-    },
-    children: [
-      {
-        path: 'detail',
-        name: 'TradeOrderDetail',
-        component: () => import('@/views/mall/trade/order/tradeOrderDetail.vue'),
-        meta: { title: '订单详情', hidden: true }
-      }
-    ]
-  },
   {
     path: '/403',
     component: () => import('@/views/Error/403.vue'),
@@ -346,22 +330,6 @@ const remainingRouter: AppRouteRecordRaw[] = [
       }
     ]
   },
-  {
-    path: '/property',
-    component: Layout,
-    name: 'ProductProperty',
-    meta: {
-      hidden: true
-    },
-    children: [
-      {
-        path: 'value/:propertyId(\\d+)',
-        component: () => import('@/views/mall/product/property/value/index.vue'),
-        name: 'ProductPropertyValue',
-        meta: { title: '商品属性值', icon: '', activeMenu: '/product/property' }
-      }
-    ]
-  },
   {
     path: '/product',
     component: Layout,
@@ -372,7 +340,7 @@ const remainingRouter: AppRouteRecordRaw[] = [
     children: [
       {
         path: 'spu/add',
-        component: () => import('@/views/mall/product/spu/addForm.vue'),
+        component: () => import('@/views/mall/product/spu/form/index.vue'),
         name: 'ProductSpuAdd',
         meta: {
           noCache: true,
@@ -385,7 +353,7 @@ const remainingRouter: AppRouteRecordRaw[] = [
       },
       {
         path: 'spu/edit/:spuId(\\d+)',
-        component: () => import('@/views/mall/product/spu/addForm.vue'),
+        component: () => import('@/views/mall/product/spu/form/index.vue'),
         name: 'ProductSpuEdit',
         meta: {
           noCache: true,
@@ -398,7 +366,7 @@ const remainingRouter: AppRouteRecordRaw[] = [
       },
       {
         path: 'spu/detail/:spuId(\\d+)',
-        component: () => import('@/views/mall/product/spu/addForm.vue'),
+        component: () => import('@/views/mall/product/spu/form/index.vue'),
         name: 'ProductSpuDetail',
         meta: {
           noCache: true,
@@ -408,6 +376,77 @@ const remainingRouter: AppRouteRecordRaw[] = [
           title: '商品详情',
           activeMenu: '/product/product-spu'
         }
+      },
+      {
+        path: 'property/value/:propertyId(\\d+)',
+        component: () => import('@/views/mall/product/property/value/index.vue'),
+        name: 'ProductPropertyValue',
+        meta: {
+          noCache: true,
+          hidden: true,
+          canTo: true,
+          icon: 'ep:view',
+          title: '商品属性值',
+          activeMenu: '/product/property'
+        }
+      }
+    ]
+  },
+  {
+    path: '/trade',
+    component: Layout,
+    name: 'Order',
+    meta: {
+      hidden: true
+    },
+    children: [
+      {
+        path: 'order/detail/:orderId(\\d+)',
+        component: () => import('@/views/mall/trade/order/detail/index.vue'),
+        name: 'TradeOrderDetail',
+        meta: { title: '订单详情', icon: '', activeMenu: '/trade/trade/order' }
+      },
+      {
+        path: 'after-sale/detail/:orderId(\\d+)',
+        component: () => import('@/views/mall/trade/afterSale/detail/index.vue'),
+        name: 'TradeAfterSaleDetail',
+        meta: { title: '退款详情', icon: '', activeMenu: '/trade/trade/after-sale' }
+      }
+    ]
+  },
+  {
+    path: '/member',
+    component: Layout,
+    name: 'member',
+    meta: { hidden: true },
+    children: [
+      {
+        path: 'user/detail/:id',
+        name: 'MemberUserDetail',
+        meta: {
+          title: '会员详情',
+          noCache: true,
+          hidden: true
+        },
+        component: () => import('@/views/member/user/detail/index.vue')
+      }
+    ]
+  },
+  {
+    path: '/pay',
+    component: Layout,
+    name: 'pay',
+    meta: { hidden: true },
+    children: [
+      {
+        path: 'cashier',
+        name: 'PayCashier',
+        meta: {
+          title: '收银台',
+          noCache: true,
+          hidden: true
+        },
+        component: () => import('@/views/pay/cashier/index.vue')
       }
     ]
   }

+ 4 - 7
src/store/modules/permission.ts

@@ -2,8 +2,7 @@ import { defineStore } from 'pinia'
 import { store } from '../index'
 import { cloneDeep } from 'lodash-es'
 import remainingRouter from '@/router/modules/remaining'
-import { generateRoute, flatMultiLevelRoutes } from '@/utils/routerHelper'
-import { getAsyncRoutesApi } from '@/api/login'
+import { flatMultiLevelRoutes, generateRoute } from '@/utils/routerHelper'
 import { CACHE_KEY, useCache } from '@/hooks/web/useCache'
 
 const { wsCache } = useCache()
@@ -34,14 +33,12 @@ export const usePermissionStore = defineStore('permission', {
   actions: {
     async generateRoutes(): Promise<unknown> {
       return new Promise<void>(async (resolve) => {
-        let res: AppCustomRouteRecordRaw[]
+        // 获得菜单列表,它在登录的时候,setUserInfoAction 方法中已经进行获取
+        let res: AppCustomRouteRecordRaw[] = []
         if (wsCache.get(CACHE_KEY.ROLE_ROUTERS)) {
           res = wsCache.get(CACHE_KEY.ROLE_ROUTERS) as AppCustomRouteRecordRaw[]
-        } else {
-          res = await getAsyncRoutesApi()
-          wsCache.set(CACHE_KEY.ROLE_ROUTERS, res)
         }
-        const routerMap: AppRouteRecordRaw[] = generateRoute(res as AppCustomRouteRecordRaw[])
+        const routerMap: AppRouteRecordRaw[] = generateRoute(res)
         // 动态路由,404一定要放到最后面
         this.addRouters = routerMap.concat([
           {

+ 1 - 0
src/store/modules/user.ts

@@ -58,6 +58,7 @@ export const useUserStore = defineStore('admin-user', {
       this.user = userInfo.user
       this.isSetUser = true
       wsCache.set(CACHE_KEY.USER, userInfo)
+      wsCache.set(CACHE_KEY.ROLE_ROUTERS, userInfo.menus)
     },
     async loginOut() {
       await loginOutApi()

+ 3 - 1
src/styles/index.scss

@@ -24,7 +24,9 @@
   }
 
   & .peg {
-    box-shadow: 0 0 10px var(--el-color-primary), 0 0 5px var(--el-color-primary) !important;
+    box-shadow:
+      0 0 10px var(--el-color-primary),
+      0 0 5px var(--el-color-primary) !important;
   }
 
   & .spinner-icon {

+ 6 - 13
src/styles/var.css

@@ -1,8 +1,5 @@
 :root {
-  --dark-bg-color: #293146;
-
-  /* left menu start */
-  --left-menu-border-color: '#eee';
+  --login-bg-color: #293146;
 
   --left-menu-max-width: 200px;
 
@@ -25,8 +22,6 @@
   --logo-height: 50px;
 
   --logo-title-text-color: #fff;
-
-  --logo-border-color: 'inherit';
   /* logo end */
 
   /* header start */
@@ -40,11 +35,7 @@
 
   --top-tool-p-x: 0;
 
-  --top-tool-border-color: #eee;
-
   --tags-view-height: 35px;
-
-  --tags-view-border-color: #eee;
   /* header start */
 
   /* tab menu start */
@@ -53,19 +44,21 @@
   --tab-menu-min-width: 30px;
 
   --tab-menu-collapse-height: 36px;
-
-  --tab-menu-border-color: #eee;
   /* tab menu end */
 
   --app-content-padding: 20px;
 
-  --app-contnet-bg-color: #f5f7f9;
+  --app-content-bg-color: #f5f7f9;
 
   --app-footer-height: 50px;
 
   --transition-time-02: 0.2s;
 }
 
+.dark {
+  --app-content-bg-color: var(--el-bg-color);
+}
+
 html,
 body {
   -webkit-font-smoothing: antialiased;

+ 55 - 77
src/utils/constants.ts

@@ -99,6 +99,10 @@ export const PayChannelEnum = {
     code: 'wx_app',
     name: '微信 APP 支付'
   },
+  WX_BAR: {
+    code: 'wx_bar',
+    name: '微信条码支付'
+  },
   ALIPAY_PC: {
     code: 'alipay_pc',
     name: '支付宝 PC 网站支付'
@@ -118,6 +122,31 @@ export const PayChannelEnum = {
   ALIPAY_BAR: {
     code: 'alipay_bar',
     name: '支付宝条码支付'
+  },
+  MOCK: {
+    code: 'mock',
+    name: '模拟支付'
+  }
+}
+
+/**
+ * 支付的展示模式每局
+ */
+export const PayDisplayModeEnum = {
+  URL: {
+    mode: 'url'
+  },
+  IFRAME: {
+    mode: 'iframe'
+  },
+  FORM: {
+    mode: 'form'
+  },
+  QR_CODE: {
+    mode: 'qr_code'
+  },
+  APP: {
+    mode: 'app'
   }
 }
 
@@ -126,7 +155,8 @@ export const PayChannelEnum = {
  */
 export const PayType = {
   WECHAT: 'WECHAT',
-  ALIPAY: 'ALIPAY'
+  ALIPAY: 'ALIPAY',
+  MOCK: 'MOCK'
 }
 
 /**
@@ -147,80 +177,6 @@ export const PayOrderStatusEnum = {
   }
 }
 
-/**
- * 支付订单回调状态枚举
- */
-export const PayOrderNotifyStatusEnum = {
-  NO: {
-    status: 0,
-    name: '未通知'
-  },
-  SUCCESS: {
-    status: 10,
-    name: '通知成功'
-  },
-  FAILURE: {
-    status: 20,
-    name: '通知失败'
-  }
-}
-
-/**
- * 支付订单退款状态枚举
- */
-export const PayOrderRefundStatusEnum = {
-  NO: {
-    status: 0,
-    name: '未退款'
-  },
-  SOME: {
-    status: 10,
-    name: '部分退款'
-  },
-  ALL: {
-    status: 20,
-    name: '全部退款'
-  }
-}
-
-/**
- * 支付退款订单状态枚举
- */
-export const PayRefundStatusEnum = {
-  CREATE: {
-    status: 0,
-    name: '退款订单生成'
-  },
-  SUCCESS: {
-    status: 1,
-    name: '退款成功'
-  },
-  FAILURE: {
-    status: 2,
-    name: '退款失败'
-  },
-  PROCESSING_NOTIFY: {
-    status: 3,
-    name: '退款中,渠道通知结果'
-  },
-  PROCESSING_QUERY: {
-    status: 4,
-    name: '退款中,系统查询结果'
-  },
-  UNKNOWN_RETRY: {
-    status: 5,
-    name: '状态未知,请重试'
-  },
-  UNKNOWN_QUERY: {
-    status: 6,
-    name: '状态未知,系统查询结果'
-  },
-  CLOSE: {
-    status: 99,
-    name: '退款关闭'
-  }
-}
-
 /**
  * 商品 SPU 状态
  */
@@ -253,17 +209,39 @@ export const CouponTemplateValidityTypeEnum = {
   }
 }
 
+/**
+ * 优惠劵模板的领取方式的枚举
+ */
+export const CouponTemplateTakeTypeEnum = {
+  USER: {
+    type: 1,
+    name: '直接领取'
+  },
+  ADMIN: {
+    type: 2,
+    name: '指定发放'
+  },
+  REGISTER: {
+    type: 3,
+    name: '新人券'
+  }
+}
+
 /**
  * 营销的商品范围枚举
  */
 export const PromotionProductScopeEnum = {
   ALL: {
     scope: 1,
-    name: '全部商品参与'
+    name: '通用劵'
   },
   SPU: {
     scope: 2,
-    name: '指定商品参与'
+    name: '商品劵'
+  },
+  CATEGORY: {
+    scope: 3,
+    name: '品类劵'
   }
 }
 

+ 6 - 11
src/utils/dict.ts

@@ -90,6 +90,7 @@ export enum DICT_TYPE {
   USER_TYPE = 'user_type',
   COMMON_STATUS = 'common_status',
   SYSTEM_TENANT_PACKAGE_ID = 'system_tenant_package_id',
+  TERMINAL = 'terminal', // 终端
 
   // ========== SYSTEM 模块 ==========
   SYSTEM_USER_SEX = 'system_user_sex',
@@ -131,16 +132,11 @@ export enum DICT_TYPE {
   BPM_OA_LEAVE_TYPE = 'bpm_oa_leave_type',
 
   // ========== PAY 模块 ==========
-  PAY_CHANNEL_WECHAT_VERSION = 'pay_channel_wechat_version', // 微信渠道版本
-  PAY_CHANNEL_ALIPAY_SIGN_TYPE = 'pay_channel_alipay_sign_type', // 支付渠道支付宝算法类型
-  PAY_CHANNEL_ALIPAY_MODE = 'pay_channel_alipay_mode', // 支付宝公钥类型
-  PAY_CHANNEL_ALIPAY_SERVER_TYPE = 'pay_channel_alipay_server_type', // 支付宝网关地址
-  PAY_CHANNEL_CODE_TYPE = 'pay_channel_code_type', // 支付渠道编码类型
-  PAY_ORDER_NOTIFY_STATUS = 'pay_order_notify_status', // 商户支付订单回调状态
+  PAY_CHANNEL_CODE = 'pay_channel_code_type', // 支付渠道编码类型
   PAY_ORDER_STATUS = 'pay_order_status', // 商户支付订单状态
-  PAY_ORDER_REFUND_STATUS = 'pay_order_refund_status', // 商户支付订单退款状态
-  PAY_REFUND_ORDER_STATUS = 'pay_refund_order_status', // 退款订单状态
-  PAY_REFUND_ORDER_TYPE = 'pay_refund_order_type', // 退款订单类别
+  PAY_REFUND_STATUS = 'pay_refund_status', // 退款订单状态
+  PAY_NOTIFY_STATUS = 'pay_notify_status', // 商户支付回调状态
+  PAY_NOTIFY_TYPE = 'pay_notify_type', // 商户支付回调状态
 
   // ========== MP 模块 ==========
   MP_AUTO_REPLY_REQUEST_MATCH = 'mp_auto_reply_request_match', // 自动回复请求匹配类型
@@ -148,7 +144,6 @@ export enum DICT_TYPE {
 
   // ========== MALL - 会员模块 ==========
   MEMBER_POINT_BIZ_TYPE = 'member_point_biz_type', // 积分的业务类型
-  MEMBER_POINT_STATUS = 'member_point_status', // 积分的状态
 
   // ========== MALL - 商品模块 ==========
   PRODUCT_UNIT = 'product_unit', // 商品单位
@@ -162,7 +157,7 @@ export enum DICT_TYPE {
   TRADE_ORDER_TYPE = 'trade_order_type', // 订单 - 类型
   TRADE_ORDER_STATUS = 'trade_order_status', // 订单 - 状态
   TRADE_ORDER_ITEM_AFTER_SALE_STATUS = 'trade_order_item_after_sale_status', // 订单项 - 售后状态
-  TERMINAL = 'terminal', // 终端
+  TRADE_DELIVERY_TYPE = 'trade_delivery_type', // 配送方式
 
   // ========== MALL - 营销模块 ==========
   PROMOTION_DISCOUNT_TYPE = 'promotion_discount_type', // 优惠类型

+ 1 - 1
src/utils/formatTime.ts

@@ -11,7 +11,7 @@ import dayjs from 'dayjs'
  * @description format 季度 + 星期 + 几周:"YYYY-mm-dd HH:MM:SS WWW QQQQ ZZZ"
  * @returns 返回拼接后的时间字符串
  */
-export function formatDate(date: Date, format?: string): string {
+export function formatDate(date: Date | number, format?: string): string {
   // 日期不存在,则返回空
   if (!date) {
     return ''

+ 25 - 1
src/utils/index.ts

@@ -174,7 +174,6 @@ export const copyValueToTarget = (target, source) => {
   Object.assign(target, newObj)
 }
 
-// TODO @puhui999:返回要带上 .00 哈.例如说 1.00
 /**
  * 将一个整数转换为分数保留两位小数
  * @param num
@@ -185,6 +184,31 @@ export const formatToFraction = (num: number | string | undefined): number => {
   return parseFloat((parsedNumber / 100).toFixed(2))
 }
 
+/**
+ * 将一个数转换为 1.00 这样
+ * 数据呈现的时候使用
+ *
+ * @param num 整数
+ */
+export const floatToFixed2 = (num: number | string | undefined): string => {
+  let str = '0.00'
+  if (typeof num === 'undefined') {
+    return str
+  }
+  const f = formatToFraction(num)
+  const decimalPart = f.toString().split('.')[1]
+  const len = decimalPart ? decimalPart.length : 0
+  switch (len) {
+    case 0:
+      str = f.toString() + '.00'
+      break
+    case 1:
+      str = f.toString() + '0'
+      break
+  }
+  return str
+}
+
 /**
  * 将一个分数转换为整数
  * @param num

+ 2 - 2
src/views/Home/Index.vue

@@ -7,7 +7,7 @@
             <div class="flex items-center">
               <img :src="avatar" alt="" class="w-70px h-70px rounded-[50%] mr-20px" />
               <div>
-                <div class="text-20px text-700">
+                <div class="text-20px">
                   {{ t('workplace.welcome') }} {{ username }} {{ t('workplace.happyDay') }}
                 </div>
                 <div class="mt-10px text-14px text-gray-500">
@@ -17,7 +17,7 @@
             </div>
           </el-col>
           <el-col :xl="12" :lg="12" :md="12" :sm="24" :xs="24">
-            <div class="flex h-70px items-center justify-end <sm:mt-10px">
+            <div class="flex h-70px items-center justify-end lt-sm:mt-10px">
               <div class="px-8px text-right">
                 <div class="text-14px text-gray-400 mb-20px">{{ t('workplace.project') }}</div>
                 <CountTo

+ 16 - 12
src/views/Login/Login.vue

@@ -1,11 +1,11 @@
 <template>
   <div
     :class="prefixCls"
-    class="h-[100%] relative <xl:bg-v-dark <sm:px-10px <xl:px-10px <md:px-10px"
+    class="h-[100%] relative lt-xl:bg-[var(--login-bg-color)] lt-sm:px-10px lt-xl:px-10px lt-md:px-10px"
   >
     <div class="relative h-full flex mx-auto">
       <div
-        :class="`${prefixCls}__left flex-1 bg-gray-500 bg-opacity-20 relative p-30px <xl:hidden`"
+        :class="`${prefixCls}__left flex-1 bg-gray-500 bg-opacity-20 relative p-30px lt-xl:hidden`"
       >
         <!-- 左上角的 logo + 系统标题 -->
         <div class="flex items-center relative text-white">
@@ -27,33 +27,35 @@
           </TransitionGroup>
         </div>
       </div>
-      <div class="flex-1 p-30px <sm:p-10px dark:bg-v-dark relative">
+      <div class="flex-1 p-30px lt-sm:p-10px dark:bg-[var(--login-bg-color)] relative">
         <!-- 右上角的主题、语言选择 -->
-        <div class="flex justify-between items-center text-white @2xl:justify-end @xl:justify-end">
-          <div class="flex items-center @2xl:hidden @xl:hidden">
+        <div
+          class="flex justify-between items-center text-white at-2xl:justify-end at-xl:justify-end"
+        >
+          <div class="flex items-center at-2xl:hidden at-xl:hidden">
             <img alt="" class="w-48px h-48px mr-10px" src="@/assets/imgs/logo.png" />
             <span class="text-20px font-bold">{{ underlineToHump(appStore.getTitle) }}</span>
           </div>
           <div class="flex justify-end items-center space-x-10px">
             <ThemeSwitch />
-            <LocaleDropdown class="<xl:text-white dark:text-white" />
+            <LocaleDropdown class="lt-xl:text-white dark:text-white" />
           </div>
         </div>
         <!-- 右边的登录界面 -->
         <Transition appear enter-active-class="animate__animated animate__bounceInRight">
           <div
-            class="h-full flex items-center m-auto w-[100%] @2xl:max-w-500px @xl:max-w-500px @md:max-w-500px @lg:max-w-500px"
+            class="h-full flex items-center m-auto w-[100%] at-2xl:max-w-500px at-xl:max-w-500px at-md:max-w-500px at-lg:max-w-500px"
           >
             <!-- 账号登录 -->
-            <LoginForm class="p-20px h-auto m-auto <xl:(rounded-3xl light:bg-white)" />
+            <LoginForm class="p-20px h-auto m-auto lt-xl:(rounded-3xl light:bg-white)" />
             <!-- 手机登录 -->
-            <MobileForm class="p-20px h-auto m-auto <xl:(rounded-3xl light:bg-white)" />
+            <MobileForm class="p-20px h-auto m-auto lt-xl:(rounded-3xl light:bg-white)" />
             <!-- 二维码登录 -->
-            <QrCodeForm class="p-20px h-auto m-auto <xl:(rounded-3xl light:bg-white)" />
+            <QrCodeForm class="p-20px h-auto m-auto lt-xl:(rounded-3xl light:bg-white)" />
             <!-- 注册 -->
-            <RegisterForm class="p-20px h-auto m-auto <xl:(rounded-3xl light:bg-white)" />
+            <RegisterForm class="p-20px h-auto m-auto lt-xl:(rounded-3xl light:bg-white)" />
             <!-- 三方登录 -->
-            <SSOLoginVue class="p-20px h-auto m-auto <xl:(rounded-3xl light:bg-white)" />
+            <SSOLoginVue class="p-20px h-auto m-auto lt-xl:(rounded-3xl light:bg-white)" />
           </div>
         </Transition>
       </div>
@@ -80,6 +82,8 @@ const prefixCls = getPrefixCls('login')
 $prefix-cls: #{$namespace}-login;
 
 .#{$prefix-cls} {
+  overflow: auto;
+
   &__left {
     &::before {
       position: absolute;

+ 5 - 3
src/views/Profile/components/BasicInfo.vue

@@ -1,5 +1,5 @@
 <template>
-  <Form ref="formRef" :labelWidth="80" :rules="rules" :schema="schema">
+  <Form ref="formRef" :labelWidth="200" :rules="rules" :schema="schema">
     <template #sex="form">
       <el-radio-group v-model="form['sex']">
         <el-radio :label="1">{{ t('profile.user.man') }}</el-radio>
@@ -7,8 +7,10 @@
       </el-radio-group>
     </template>
   </Form>
-  <XButton :title="t('common.save')" @click="submit()" />
-  <XButton :title="t('common.reset')" type="danger" @click="init()" />
+  <div style="text-align: center">
+    <XButton :title="t('common.save')" type="primary" @click="submit()" />
+    <XButton :title="t('common.reset')" type="danger" @click="init()" />
+  </div>
 </template>
 <script lang="ts" name="BasicInfo" setup>
 import type { FormRules } from 'element-plus'

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