From 607b73a7b3f323c17af92757cee1928fdd47dea2 Mon Sep 17 00:00:00 2001 From: kailong321200875 <321200875@qq.com> Date: Tue, 19 Dec 2023 09:46:22 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=9B=B4=E6=96=B0mini=E5=88=86?= =?UTF-8?q?=E6=94=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .env.base | 2 +- .env.dev | 2 +- .env.gitee | 2 +- .env.pro | 2 +- mock/_createProductionServer.ts | 2 +- mock/role/index.mock.ts | 91 +++ mock/role/index.ts | 544 ------------------ mock/user/{index.ts => index.mock.ts} | 19 +- package.json | 93 +-- src/api/common/index.ts | 11 - src/api/dashboard/analysis/index.ts | 23 - src/api/dashboard/analysis/types.ts | 22 - src/api/dashboard/workplace/index.ts | 22 - src/api/dashboard/workplace/types.ts | 30 - src/api/department/index.ts | 30 - src/api/department/types.ts | 32 -- src/api/login/index.ts | 20 +- src/api/menu/index.ts | 5 - src/api/table/index.ts | 22 - src/api/table/types.ts | 9 - src/axios/config.ts | 45 ++ src/{config => }/axios/index.ts | 13 +- src/{config => }/axios/service.ts | 15 +- src/{config => }/axios/types/index.ts | 13 - src/components/Button/index.ts | 3 + src/components/Button/src/Button.vue | 121 ++++ src/components/Menu/src/Menu.vue | 5 +- .../Menu/src/components/useRenderMenuItem.tsx | 15 +- src/components/Search/src/Search.vue | 8 +- src/components/Setting/src/Setting.vue | 19 +- .../src/components/InterfaceDisplay.vue | 15 +- .../src/components/LayoutRadioPicker.vue | 16 +- src/components/Table/src/Table.vue | 180 +++--- src/components/UserInfo/src/UserInfo.vue | 36 +- src/components/VideoPlayer/index.ts | 27 + .../VideoPlayer/src/VideoPlayer.vue | 59 ++ src/components/VideoPlayerViewer/index.ts | 3 + .../src/VideoPlayerViewer.vue | 49 ++ src/components/index.ts | 2 + src/config/axios/config.ts | 99 ---- src/constants/index.ts | 24 + src/locales/en.ts | 3 +- src/locales/zh-CN.ts | 3 +- src/permission.ts | 29 +- src/store/index.ts | 4 +- src/store/modules/app.ts | 38 +- src/store/modules/dict.ts | 34 -- src/store/modules/lock.ts | 5 +- src/store/modules/permission.ts | 19 +- src/store/modules/tagsView.ts | 31 +- src/store/modules/user.ts | 102 ++++ src/utils/routerHelper.ts | 19 +- src/views/Login/components/LoginForm.vue | 83 +-- stylelint.config.js | 2 + tsconfig.json | 4 +- types/components.d.ts | 3 +- types/global.d.ts | 7 +- vite.config.ts | 19 +- 58 files changed, 930 insertions(+), 1225 deletions(-) create mode 100644 mock/role/index.mock.ts delete mode 100644 mock/role/index.ts rename mock/user/{index.ts => index.mock.ts} (85%) delete mode 100644 src/api/common/index.ts delete mode 100644 src/api/dashboard/analysis/index.ts delete mode 100644 src/api/dashboard/analysis/types.ts delete mode 100644 src/api/dashboard/workplace/index.ts delete mode 100644 src/api/dashboard/workplace/types.ts delete mode 100644 src/api/department/index.ts delete mode 100644 src/api/department/types.ts delete mode 100644 src/api/menu/index.ts delete mode 100644 src/api/table/index.ts delete mode 100644 src/api/table/types.ts create mode 100644 src/axios/config.ts rename src/{config => }/axios/index.ts (72%) rename src/{config => }/axios/service.ts (78%) rename src/{config => }/axios/types/index.ts (74%) create mode 100644 src/components/Button/index.ts create mode 100644 src/components/Button/src/Button.vue create mode 100644 src/components/VideoPlayer/index.ts create mode 100644 src/components/VideoPlayer/src/VideoPlayer.vue create mode 100644 src/components/VideoPlayerViewer/index.ts create mode 100644 src/components/VideoPlayerViewer/src/VideoPlayerViewer.vue delete mode 100644 src/config/axios/config.ts create mode 100644 src/constants/index.ts delete mode 100644 src/store/modules/dict.ts create mode 100644 src/store/modules/user.ts diff --git a/.env.base b/.env.base index 799b9e1..7e2fb8f 100644 --- a/.env.base +++ b/.env.base @@ -2,7 +2,7 @@ NODE_ENV=development # 接口前缀 -VITE_API_BASE_PATH=base +VITE_API_BASE_PATH= # 打包路径 VITE_BASE_PATH=/ diff --git a/.env.dev b/.env.dev index b5b794e..afc3cee 100644 --- a/.env.dev +++ b/.env.dev @@ -2,7 +2,7 @@ NODE_ENV=production # 接口前缀 -VITE_API_BASE_PATH=dev +VITE_API_BASE_PATH= # 打包路径 VITE_BASE_PATH=/dist-dev/ diff --git a/.env.gitee b/.env.gitee index 412f1c4..9ac2a52 100644 --- a/.env.gitee +++ b/.env.gitee @@ -2,7 +2,7 @@ NODE_ENV=production # 接口前缀 -VITE_API_BASE_PATH=pro +VITE_API_BASE_PATH= # 打包路径 VITE_BASE_PATH=/vue-element-plus-admin/ diff --git a/.env.pro b/.env.pro index d21f25c..432fc46 100644 --- a/.env.pro +++ b/.env.pro @@ -2,7 +2,7 @@ NODE_ENV=production # 接口前缀 -VITE_API_BASE_PATH=pro +VITE_API_BASE_PATH= # 打包路径 VITE_BASE_PATH=/ diff --git a/mock/_createProductionServer.ts b/mock/_createProductionServer.ts index caa26bf..598ac64 100644 --- a/mock/_createProductionServer.ts +++ b/mock/_createProductionServer.ts @@ -1,6 +1,6 @@ import { createProdMockServer } from 'vite-plugin-mock/es/createProdMockServer' -const modules = import.meta.glob('./**/*.ts', { +const modules = import.meta.glob('./**/*.mock.ts', { import: 'default', eager: true }) diff --git a/mock/role/index.mock.ts b/mock/role/index.mock.ts new file mode 100644 index 0000000..6d7e458 --- /dev/null +++ b/mock/role/index.mock.ts @@ -0,0 +1,91 @@ +import { MockMethod } from 'vite-plugin-mock' +import { SUCCESS_CODE } from '@/constants' + +const timeout = 1000 + +const adminList = [ + { + path: '/level', + component: '#', + redirect: '/level/menu1/menu1-1/menu1-1-1', + name: 'Level', + meta: { + title: 'router.level', + icon: 'carbon:skill-level-advanced' + }, + children: [ + { + path: 'menu1', + name: 'Menu1', + component: '##', + redirect: '/level/menu1/menu1-1/menu1-1-1', + meta: { + title: 'router.menu1' + }, + children: [ + { + path: 'menu1-1', + name: 'Menu11', + component: '##', + redirect: '/level/menu1/menu1-1/menu1-1-1', + meta: { + title: 'router.menu11', + alwaysShow: true + }, + children: [ + { + path: 'menu1-1-1', + name: 'Menu111', + component: 'views/Level/Menu111', + meta: { + title: 'router.menu111' + } + } + ] + }, + { + path: 'menu1-2', + name: 'Menu12', + component: 'views/Level/Menu12', + meta: { + title: 'router.menu12' + } + } + ] + }, + { + path: 'menu2', + name: 'Menu2Demo', + component: 'views/Level/Menu2', + meta: { + title: 'router.menu2' + } + } + ] + } +] + +const testList: string[] = [ + '/level', + '/level/menu1', + '/level/menu1/menu1-1', + '/level/menu1/menu1-1/menu1-1-1', + '/level/menu1/menu1-2', + '/level/menu2' +] + +export default [ + // 列表接口 + { + url: '/mock/role/list', + method: 'get', + timeout, + response: ({ query }) => { + const { roleName } = query + return { + code: SUCCESS_CODE, + data: roleName === 'admin' ? adminList : testList + } + } + } +] as MockMethod[] diff --git a/mock/role/index.ts b/mock/role/index.ts deleted file mode 100644 index d19fd3b..0000000 --- a/mock/role/index.ts +++ /dev/null @@ -1,544 +0,0 @@ -import config from '@/config/axios/config' -import { MockMethod } from 'vite-plugin-mock' - -const { code } = config - -const timeout = 1000 - -const adminList = [ - { - path: '/dashboard', - component: '#', - redirect: '/dashboard/analysis', - name: 'Dashboard', - meta: { - title: 'router.dashboard', - icon: 'ant-design:dashboard-filled', - alwaysShow: true - }, - children: [ - { - path: 'analysis', - component: 'views/Dashboard/Analysis', - name: 'Analysis', - meta: { - title: 'router.analysis', - noCache: true - } - }, - { - path: 'workplace', - component: 'views/Dashboard/Workplace', - name: 'Workplace', - meta: { - title: 'router.workplace', - noCache: true - } - } - ] - }, - { - path: '/external-link', - component: '#', - meta: {}, - name: 'ExternalLink', - children: [ - { - path: 'https://element-plus-admin-doc.cn/', - name: 'DocumentLink', - meta: { - title: 'router.document', - icon: 'clarity:document-solid' - } - } - ] - }, - { - path: '/guide', - component: '#', - name: 'Guide', - meta: {}, - children: [ - { - path: 'index', - component: 'views/Guide/Guide', - name: 'GuideDemo', - meta: { - title: 'router.guide', - icon: 'cib:telegram-plane' - } - } - ] - }, - { - path: '/components', - component: '#', - redirect: '/components/form/default-form', - name: 'ComponentsDemo', - meta: { - title: 'router.component', - icon: 'bx:bxs-component', - alwaysShow: true - }, - children: [ - { - path: 'form', - component: '##', - name: 'Form', - meta: { - title: 'router.form', - alwaysShow: true - }, - children: [ - { - path: 'default-form', - component: 'views/Components/Form/DefaultForm', - name: 'DefaultForm', - meta: { - title: 'router.defaultForm' - } - }, - { - path: 'use-form', - component: 'views/Components/Form/UseFormDemo', - name: 'UseForm', - meta: { - title: 'UseForm' - } - } - ] - }, - { - path: 'table', - component: '##', - redirect: '/components/table/default-table', - name: 'TableDemo', - meta: { - title: 'router.table', - alwaysShow: true - }, - children: [ - { - path: 'default-table', - component: 'views/Components/Table/DefaultTable', - name: 'DefaultTable', - meta: { - title: 'router.defaultTable' - } - }, - { - path: 'use-table', - component: 'views/Components/Table/UseTableDemo', - name: 'UseTable', - meta: { - title: 'UseTable' - } - }, - { - path: 'tree-table', - component: 'views/Components/Table/TreeTable', - name: 'TreeTable', - meta: { - title: 'router.TreeTable' - } - }, - { - path: 'table-image-preview', - component: 'views/Components/Table/TableImagePreview', - name: 'TableImagePreview', - meta: { - title: 'router.PicturePreview' - } - }, - { - path: 'ref-table', - component: 'views/Components/Table/RefTable', - name: 'RefTable', - meta: { - title: 'RefTable' - } - } - ] - }, - { - path: 'editor-demo', - component: '##', - redirect: '/components/editor-demo/editor', - name: 'EditorDemo', - meta: { - title: 'router.editor', - alwaysShow: true - }, - children: [ - { - path: 'editor', - component: 'views/Components/Editor/Editor', - name: 'Editor', - meta: { - title: 'router.richText' - } - } - ] - }, - { - path: 'search', - component: 'views/Components/Search', - name: 'Search', - meta: { - title: 'router.search' - } - }, - { - path: 'descriptions', - component: 'views/Components/Descriptions', - name: 'Descriptions', - meta: { - title: 'router.descriptions' - } - }, - { - path: 'image-viewer', - component: 'views/Components/ImageViewer', - name: 'ImageViewer', - meta: { - title: 'router.imageViewer' - } - }, - { - path: 'dialog', - component: 'views/Components/Dialog', - name: 'Dialog', - meta: { - title: 'router.dialog' - } - }, - { - path: 'icon', - component: 'views/Components/Icon', - name: 'Icon', - meta: { - title: 'router.icon' - } - }, - { - path: 'echart', - component: 'views/Components/Echart', - name: 'Echart', - meta: { - title: 'router.echart' - } - }, - { - path: 'count-to', - component: 'views/Components/CountTo', - name: 'CountTo', - meta: { - title: 'router.countTo' - } - }, - { - path: 'qrcode', - component: 'views/Components/Qrcode', - name: 'Qrcode', - meta: { - title: 'router.qrcode' - } - }, - { - path: 'highlight', - component: 'views/Components/Highlight', - name: 'Highlight', - meta: { - title: 'router.highlight' - } - }, - { - path: 'infotip', - component: 'views/Components/Infotip', - name: 'Infotip', - meta: { - title: 'router.infotip' - } - }, - { - path: 'input-password', - component: 'views/Components/InputPassword', - name: 'InputPassword', - meta: { - title: 'router.inputPassword' - } - }, - { - path: 'sticky', - component: 'views/Components/Sticky', - name: 'Sticky', - meta: { - title: 'router.sticky' - } - } - ] - }, - { - path: '/hooks', - component: '#', - redirect: '/hooks/useWatermark', - name: 'Hooks', - meta: { - title: 'hooks', - icon: 'ic:outline-webhook', - alwaysShow: true - }, - children: [ - { - path: 'useWatermark', - component: 'views/hooks/useWatermark', - name: 'UseWatermark', - meta: { - title: 'useWatermark' - } - }, - { - path: 'useCrudSchemas', - component: 'views/hooks/useCrudSchemas', - name: 'UseCrudSchemas', - meta: { - title: 'useCrudSchemas' - } - } - ] - }, - { - path: '/level', - component: '#', - redirect: '/level/menu1/menu1-1/menu1-1-1', - name: 'Level', - meta: { - title: 'router.level', - icon: 'carbon:skill-level-advanced' - }, - children: [ - { - path: 'menu1', - name: 'Menu1', - component: '##', - redirect: '/level/menu1/menu1-1/menu1-1-1', - meta: { - title: 'router.menu1' - }, - children: [ - { - path: 'menu1-1', - name: 'Menu11', - component: '##', - redirect: '/level/menu1/menu1-1/menu1-1-1', - meta: { - title: 'router.menu11', - alwaysShow: true - }, - children: [ - { - path: 'menu1-1-1', - name: 'Menu111', - component: 'views/Level/Menu111', - meta: { - title: 'router.menu111' - } - } - ] - }, - { - path: 'menu1-2', - name: 'Menu12', - component: 'views/Level/Menu12', - meta: { - title: 'router.menu12' - } - } - ] - }, - { - path: 'menu2', - name: 'Menu2Demo', - component: 'views/Level/Menu2', - meta: { - title: 'router.menu2' - } - } - ] - }, - { - path: '/example', - component: '#', - redirect: '/example/example-dialog', - name: 'Example', - meta: { - title: 'router.example', - icon: 'ep:management', - alwaysShow: true - }, - children: [ - { - path: 'example-dialog', - component: 'views/Example/Dialog/ExampleDialog', - name: 'ExampleDialog', - meta: { - title: 'router.exampleDialog' - } - }, - { - path: 'example-page', - component: 'views/Example/Page/ExamplePage', - name: 'ExamplePage', - meta: { - title: 'router.examplePage' - } - }, - { - path: 'example-add', - component: 'views/Example/Page/ExampleAdd', - name: 'ExampleAdd', - meta: { - title: 'router.exampleAdd', - noTagsView: true, - noCache: true, - hidden: true, - showMainRoute: true, - activeMenu: '/example/example-page' - } - }, - { - path: 'example-edit', - component: 'views/Example/Page/ExampleEdit', - name: 'ExampleEdit', - meta: { - title: 'router.exampleEdit', - noTagsView: true, - noCache: true, - hidden: true, - showMainRoute: true, - activeMenu: '/example/example-page' - } - }, - { - path: 'example-detail', - component: 'views/Example/Page/ExampleDetail', - name: 'ExampleDetail', - meta: { - title: 'router.exampleDetail', - noTagsView: true, - noCache: true, - hidden: true, - showMainRoute: true, - activeMenu: '/example/example-page' - } - } - ] - }, - { - path: '/error', - component: '#', - redirect: '/error/404', - name: 'Error', - meta: { - title: 'router.errorPage', - icon: 'ci:error', - alwaysShow: true - }, - children: [ - { - path: '404-demo', - component: 'views/Error/404', - name: '404Demo', - meta: { - title: '404' - } - }, - { - path: '403-demo', - component: 'views/Error/403', - name: '403Demo', - meta: { - title: '403' - } - }, - { - path: '500-demo', - component: 'views/Error/500', - name: '500Demo', - meta: { - title: '500' - } - } - ] - } -] - -const testList: string[] = [ - '/dashboard', - '/dashboard/analysis', - '/dashboard/workplace', - 'external-link', - 'https://element-plus-admin-doc.cn/', - '/guide', - '/guide/index', - '/components', - '/components/form', - '/components/form/default-form', - '/components/form/use-form', - '/components/form/ref-form', - '/components/table', - '/components/table/default-table', - '/components/table/use-table', - '/components/table/tree-table', - '/components/table/table-image-preview', - '/components/table/ref-table', - '/components/editor-demo', - '/components/editor-demo/editor', - '/components/search', - '/components/descriptions', - '/components/image-viewer', - '/components/dialog', - '/components/icon', - '/components/echart', - '/components/count-to', - '/components/qrcode', - '/components/highlight', - '/components/infotip', - '/Components/InputPassword', - '/Components/Sticky', - '/hooks', - '/hooks/useWatermark', - '/hooks/useCrudSchemas', - '/level', - '/level/menu1', - '/level/menu1/menu1-1', - '/level/menu1/menu1-1/menu1-1-1', - '/level/menu1/menu1-2', - '/level/menu2', - '/example', - '/example/example-dialog', - '/example/example-page', - '/example/example-add', - '/example/example-edit', - '/example/example-detail', - '/error', - '/error/404-demo', - '/error/403-demo', - '/error/500-demo' -] - -export default [ - // 列表接口 - { - url: '/role/list', - method: 'get', - timeout, - response: ({ query }) => { - const { roleName } = query - return { - code: code, - data: roleName === 'admin' ? adminList : testList - } - } - } -] as MockMethod[] diff --git a/mock/user/index.ts b/mock/user/index.mock.ts similarity index 85% rename from mock/user/index.ts rename to mock/user/index.mock.ts index 887caf0..4e5918c 100644 --- a/mock/user/index.ts +++ b/mock/user/index.mock.ts @@ -1,7 +1,4 @@ -import config from '@/config/axios/config' -import { MockMethod } from 'vite-plugin-mock' - -const { code } = config +import { SUCCESS_CODE } from '@/constants' const timeout = 1000 @@ -31,7 +28,7 @@ const List: { export default [ // 列表接口 { - url: '/user/list', + url: '/mock/user/list', method: 'get', response: ({ query }) => { const { username, pageIndex, pageSize } = query @@ -45,8 +42,8 @@ export default [ ) return { + code: SUCCESS_CODE, data: { - code: code, total: mockList.length, list: pageList } @@ -55,7 +52,7 @@ export default [ }, // 登录接口 { - url: '/user/login', + url: '/mock/user/login', method: 'post', timeout, response: ({ body }) => { @@ -65,7 +62,7 @@ export default [ if (user.username === data.username && user.password === data.password) { hasUser = true return { - code: code, + code: SUCCESS_CODE, data: user } } @@ -80,14 +77,14 @@ export default [ }, // 退出接口 { - url: '/user/loginOut', + url: '/mock/user/loginOut', method: 'get', timeout, response: () => { return { - code: code, + code: SUCCESS_CODE, data: null } } } -] as MockMethod[] +] diff --git a/package.json b/package.json index 934b100..e2bb6b4 100644 --- a/package.json +++ b/package.json @@ -6,18 +6,18 @@ "private": false, "scripts": { "i": "pnpm install", - "dev": "vite --mode base", - "ts:check": "vue-tsc --noEmit --skipLibCheck", - "build:pro": "vite build --mode pro", - "build:gitee": "vite build --mode gitee", - "build:dev": "vite build --mode dev", - "build:test": "npm run ts:check && vite build --mode test", - "serve:pro": "vite preview --mode pro", - "serve:dev": "vite preview --mode dev", - "serve:test": "vite preview --mode test", - "npm:check": "npx npm-check-updates", - "clean": "npx rimraf node_modules", - "clean:cache": "npx rimraf node_modules/.cache", + "dev": "pnpm vite --mode base", + "ts:check": "pnpm vue-tsc --noEmit --skipLibCheck", + "build:pro": "pnpm vite build --mode pro", + "build:gitee": "pnpm vite build --mode gitee", + "build:dev": "pnpm vite build --mode dev", + "build:test": "pnpm run ts:check && vite build --mode test", + "serve:pro": "pnpm vite preview --mode pro", + "serve:dev": "pnpm vite preview --mode dev", + "serve:test": "pnpm vite preview --mode test", + "npm:check": "pnpx npm-check-updates -u", + "clean": "pnpx rimraf node_modules", + "clean:cache": "pnpx 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,vue,html,md}\"", "lint:style": "stylelint --fix \"**/*.{vue,less,postcss,css,scss}\" --cache --cache-location node_modules/.cache/stylelint/", @@ -26,90 +26,99 @@ "p": "plop" }, "dependencies": { + "@faker-js/faker": "^8.3.1", "@iconify/iconify": "^3.1.1", "@iconify/vue": "^4.1.1", - "@vueuse/core": "^10.6.1", + "@vueuse/core": "^10.7.0", "@wangeditor/editor": "^5.1.23", "@wangeditor/editor-for-vue": "^5.1.10", "@zxcvbn-ts/core": "^3.0.4", "animate.css": "^4.1.1", "axios": "^1.6.2", + "cropperjs": "^1.6.1", "dayjs": "^1.11.10", + "driver.js": "^1.3.1", "echarts": "^5.4.3", "echarts-wordcloud": "^2.1.0", - "element-plus": "^2.4.2", + "element-plus": "^2.4.3", "lodash-es": "^4.17.21", "mitt": "^3.0.1", - "mockjs": "^1.1.0", "nprogress": "^0.2.0", "pinia": "^2.1.7", - "pinia-plugin-persist": "^1.0.0", + "pinia-plugin-persistedstate": "^3.2.0", "qrcode": "^1.5.3", "qs": "^6.11.2", - "sortablejs": "^1.15.0", "url": "^0.11.3", - "vue": "3.3.8", - "vue-i18n": "9.7.0", + "vue": "3.3.10", + "vue-i18n": "9.8.0", + "vue-json-pretty": "^2.2.4", "vue-router": "^4.2.5", - "vue-types": "^5.1.1" + "vue-types": "^5.1.1", + "xgplayer": "^3.0.10" }, "devDependencies": { "@commitlint/cli": "^18.4.3", "@commitlint/config-conventional": "^18.4.3", - "@iconify/json": "^2.2.144", + "@iconify/json": "^2.2.153", "@intlify/unplugin-vue-i18n": "^1.5.0", "@purge-icons/generated": "^0.10.0", + "@types/fs-extra": "^11.0.4", + "@types/inquirer": "^9.0.7", "@types/lodash-es": "^4.17.12", - "@types/node": "^20.9.4", + "@types/node": "^20.10.3", "@types/nprogress": "^0.2.3", "@types/qrcode": "^1.5.5", "@types/qs": "^6.9.10", "@types/sortablejs": "^1.15.7", - "@typescript-eslint/eslint-plugin": "^6.12.0", - "@typescript-eslint/parser": "^6.12.0", - "@unocss/transformer-variant-group": "^0.57.7", - "@vitejs/plugin-legacy": "^5.1.0", - "@vitejs/plugin-vue": "^4.5.0", + "@typescript-eslint/eslint-plugin": "^6.13.2", + "@typescript-eslint/parser": "^6.13.2", + "@unocss/transformer-variant-group": "^0.58.0", + "@vitejs/plugin-legacy": "^5.2.0", + "@vitejs/plugin-vue": "^4.5.1", "@vitejs/plugin-vue-jsx": "^3.1.0", - "@vue-macros/volar": "^0.17.3", "autoprefixer": "^10.4.16", + "chalk": "^5.3.0", "consola": "^3.2.3", - "eslint": "^8.54.0", - "eslint-config-prettier": "^9.0.0", + "eslint": "^8.55.0", + "eslint-config-prettier": "^9.1.0", "eslint-define-config": "^2.0.0", "eslint-plugin-prettier": "^5.0.1", - "eslint-plugin-vue": "^9.18.1", + "eslint-plugin-vue": "^9.19.2", + "esno": "^4.0.0", + "fs-extra": "^11.2.0", "husky": "^8.0.3", + "inquirer": "^9.2.12", "less": "^4.2.0", - "lint-staged": "^15.1.0", + "lint-staged": "^15.2.0", "plop": "^4.0.0", - "postcss": "^8.4.31", + "postcss": "^8.4.32", "postcss-html": "^1.5.0", "postcss-less": "^6.0.0", "prettier": "^3.1.0", "rimraf": "^5.0.5", - "rollup": "^4.5.1", + "rollup": "^4.6.1", "stylelint": "^15.11.0", "stylelint-config-html": "^1.1.0", "stylelint-config-recommended": "^13.0.0", "stylelint-config-standard": "^34.0.0", "stylelint-order": "^6.0.3", - "terser": "^5.24.0", - "typescript": "5.3.2", - "unocss": "^0.57.7", - "unplugin-vue-define-options": "^1.4.0", - "vite": "5.0.2", + "terser": "^5.25.0", + "typescript": "5.3.3", + "unocss": "^0.58.0", + "vite": "5.0.6", "vite-plugin-ejs": "^1.7.0", "vite-plugin-eslint": "^1.8.1", - "vite-plugin-mock": "2.9.6", + "vite-plugin-mock": "^2.9.6", "vite-plugin-progress": "^0.0.7", "vite-plugin-purge-icons": "^0.10.0", "vite-plugin-style-import": "2.0.0", "vite-plugin-svg-icons": "^2.0.1", - "vue-tsc": "^1.8.22" + "vue-tsc": "^1.8.25" }, + "packageManager": "pnpm@8.1.0", "engines": { - "node": ">= 18.0.0 || >= 20.0.0" + "node": ">=18.0.0", + "pnpm": ">=8.1.0" }, "license": "MIT", "repository": { diff --git a/src/api/common/index.ts b/src/api/common/index.ts deleted file mode 100644 index 07c0f13..0000000 --- a/src/api/common/index.ts +++ /dev/null @@ -1,11 +0,0 @@ -import request from '@/config/axios' - -// 获取所有字典 -export const getDictApi = () => { - return request.get({ url: '/dict/list' }) -} - -// 模拟获取某个字典 -export const getDictOneApi = async () => { - return request.get({ url: '/dict/one' }) -} diff --git a/src/api/dashboard/analysis/index.ts b/src/api/dashboard/analysis/index.ts deleted file mode 100644 index 1f00ed0..0000000 --- a/src/api/dashboard/analysis/index.ts +++ /dev/null @@ -1,23 +0,0 @@ -import request from '@/config/axios' -import type { - AnalysisTotalTypes, - UserAccessSource, - WeeklyUserActivity, - MonthlySales -} from './types' - -export const getCountApi = (): Promise> => { - return request.get({ url: '/analysis/total' }) -} - -export const getUserAccessSourceApi = (): Promise> => { - return request.get({ url: '/analysis/userAccessSource' }) -} - -export const getWeeklyUserActivityApi = (): Promise> => { - return request.get({ url: '/analysis/weeklyUserActivity' }) -} - -export const getMonthlySalesApi = (): Promise> => { - return request.get({ url: '/analysis/monthlySales' }) -} diff --git a/src/api/dashboard/analysis/types.ts b/src/api/dashboard/analysis/types.ts deleted file mode 100644 index 4a239f5..0000000 --- a/src/api/dashboard/analysis/types.ts +++ /dev/null @@ -1,22 +0,0 @@ -export type AnalysisTotalTypes = { - users: number - messages: number - moneys: number - shoppings: number -} - -export type UserAccessSource = { - value: number - name: string -} - -export type WeeklyUserActivity = { - value: number - name: string -} - -export type MonthlySales = { - name: string - estimate: number - actual: number -} diff --git a/src/api/dashboard/workplace/index.ts b/src/api/dashboard/workplace/index.ts deleted file mode 100644 index 0880640..0000000 --- a/src/api/dashboard/workplace/index.ts +++ /dev/null @@ -1,22 +0,0 @@ -import request from '@/config/axios' -import type { WorkplaceTotal, Project, Dynamic, Team, RadarData } from './types' - -export const getCountApi = (): Promise> => { - return request.get({ url: '/workplace/total' }) -} - -export const getProjectApi = (): Promise> => { - return request.get({ url: '/workplace/project' }) -} - -export const getDynamicApi = (): Promise> => { - return request.get({ url: '/workplace/dynamic' }) -} - -export const getTeamApi = (): Promise> => { - return request.get({ url: '/workplace/team' }) -} - -export const getRadarApi = (): Promise> => { - return request.get({ url: '/workplace/radar' }) -} diff --git a/src/api/dashboard/workplace/types.ts b/src/api/dashboard/workplace/types.ts deleted file mode 100644 index da23e74..0000000 --- a/src/api/dashboard/workplace/types.ts +++ /dev/null @@ -1,30 +0,0 @@ -export type WorkplaceTotal = { - project: number - access: number - todo: number -} - -export type Project = { - name: string - icon: string - message: string - personal: string - time: Date | number | string -} - -export type Dynamic = { - keys: string[] - time: Date | number | string -} - -export type Team = { - name: string - icon: string -} - -export type RadarData = { - personal: number - team: number - max: number - name: string -} diff --git a/src/api/department/index.ts b/src/api/department/index.ts deleted file mode 100644 index b6ece1e..0000000 --- a/src/api/department/index.ts +++ /dev/null @@ -1,30 +0,0 @@ -import request from '@/config/axios' -import { DepartmentListResponse, DepartmentUserParams, DepartmentUserResponse } from './types' - -export const getDepartmentApi = () => { - return request.get({ url: '/department/list' }) -} - -export const getUserByIdApi = (params: DepartmentUserParams) => { - return request.get({ url: '/department/users', params }) -} - -export const deleteUserByIdApi = (ids: string[] | number[]) => { - return request.post({ url: '/department/user/delete', data: { ids } }) -} - -export const saveUserApi = (data: any) => { - return request.post({ url: '/department/user/save', data }) -} - -export const saveDepartmentApi = (data: any) => { - return request.post({ url: '/department/save', data }) -} - -export const deleteDepartmentApi = (ids: string[] | number[]) => { - return request.post({ url: '/department/delete', data: { ids } }) -} - -export const getDepartmentTableApi = (params: any) => { - return request.get({ url: '/department/table/list', params }) -} diff --git a/src/api/department/types.ts b/src/api/department/types.ts deleted file mode 100644 index 027a628..0000000 --- a/src/api/department/types.ts +++ /dev/null @@ -1,32 +0,0 @@ -export interface DepartmentItem { - id: string - departmentName: string - children?: DepartmentItem[] -} - -export interface DepartmentListResponse { - list: DepartmentItem[] -} - -export interface DepartmentUserParams { - pageSize: number - pageIndex: number - id: string - username?: string - account?: string -} - -export interface DepartmentUserItem { - id: string - username: string - account: string - email: string - createTime: string - role: string - department: DepartmentItem -} - -export interface DepartmentUserResponse { - list: DepartmentUserItem[] - total: number -} diff --git a/src/api/login/index.ts b/src/api/login/index.ts index ccddc37..dff73a0 100644 --- a/src/api/login/index.ts +++ b/src/api/login/index.ts @@ -1,4 +1,4 @@ -import request from '@/config/axios' +import request from '@/axios' import type { UserType } from './types' interface RoleParams { @@ -6,29 +6,19 @@ interface RoleParams { } export const loginApi = (data: UserType): Promise> => { - return request.post({ url: '/user/login', data }) + return request.post({ url: '/mock/user/login', data }) } export const loginOutApi = (): Promise => { - return request.get({ url: '/user/loginOut' }) -} - -export const getUserListApi = ({ params }: AxiosConfig) => { - return request.get<{ - code: string - data: { - list: UserType[] - total: number - } - }>({ url: '/user/list', params }) + return request.get({ url: '/mock/user/loginOut' }) } export const getAdminRoleApi = ( params: RoleParams ): Promise> => { - return request.get({ url: '/role/list', params }) + return request.get({ url: '/mock/role/list', params }) } export const getTestRoleApi = (params: RoleParams): Promise> => { - return request.get({ url: '/role/list', params }) + return request.get({ url: '/mock/role/list2', params }) } diff --git a/src/api/menu/index.ts b/src/api/menu/index.ts deleted file mode 100644 index a7c55a7..0000000 --- a/src/api/menu/index.ts +++ /dev/null @@ -1,5 +0,0 @@ -import request from '@/config/axios' - -export const getMenuListApi = () => { - return request.get({ url: '/menu/list' }) -} diff --git a/src/api/table/index.ts b/src/api/table/index.ts deleted file mode 100644 index c3b6d06..0000000 --- a/src/api/table/index.ts +++ /dev/null @@ -1,22 +0,0 @@ -import request from '@/config/axios' -import type { TableData } from './types' - -export const getTableListApi = (params: any) => { - return request.get({ url: '/example/list', params }) -} - -export const getTreeTableListApi = (params: any) => { - return request.get({ url: '/example/treeList', params }) -} - -export const saveTableApi = (data: Partial): Promise => { - return request.post({ url: '/example/save', data }) -} - -export const getTableDetApi = (id: string): Promise> => { - return request.get({ url: '/example/detail', params: { id } }) -} - -export const delTableListApi = (ids: string[] | number[]): Promise => { - return request.post({ url: '/example/delete', data: { ids } }) -} diff --git a/src/api/table/types.ts b/src/api/table/types.ts deleted file mode 100644 index 876c111..0000000 --- a/src/api/table/types.ts +++ /dev/null @@ -1,9 +0,0 @@ -export type TableData = { - id: string - author: string - title: string - content: string - importance: number - display_time: string - pageviews: number -} diff --git a/src/axios/config.ts b/src/axios/config.ts new file mode 100644 index 0000000..efdae3d --- /dev/null +++ b/src/axios/config.ts @@ -0,0 +1,45 @@ +import { AxiosResponse, InternalAxiosRequestConfig } from './types' +import { ElMessage } from 'element-plus' +import qs from 'qs' +import { SUCCESS_CODE } from '@/constants' +import { useUserStoreWithOut } from '@/store/modules/user' + +const defaultRequestInterceptors = (config: InternalAxiosRequestConfig) => { + if ( + config.method === 'post' && + config.headers['Content-Type'] === 'application/x-www-form-urlencoded' + ) { + config.data = qs.stringify(config.data) + } + if (config.method === 'get' && config.params) { + let url = config.url as string + url += '?' + const keys = Object.keys(config.params) + for (const key of keys) { + if (config.params[key] !== void 0 && config.params[key] !== null) { + url += `${key}=${encodeURIComponent(config.params[key])}&` + } + } + url = url.substring(0, url.length - 1) + config.params = {} + config.url = url + } + return config +} + +const defaultResponseInterceptors = (response: AxiosResponse) => { + if (response?.config?.responseType === 'blob') { + // 如果是文件流,直接过 + return response + } else if (response.data.code === SUCCESS_CODE) { + return response.data + } else { + ElMessage.error(response?.data?.message) + if (response?.data?.code === 401) { + const userStore = useUserStoreWithOut() + userStore.logout() + } + } +} + +export { defaultResponseInterceptors, defaultRequestInterceptors } diff --git a/src/config/axios/index.ts b/src/axios/index.ts similarity index 72% rename from src/config/axios/index.ts rename to src/axios/index.ts index 40ff667..94cbfc3 100644 --- a/src/config/axios/index.ts +++ b/src/axios/index.ts @@ -1,11 +1,10 @@ import service from './service' - -import config from './config' - -const { defaultHeaders } = config +import { CONTENT_TYPE } from '@/constants' +import { useUserStoreWithOut } from '@/store/modules/user' const request = (option: AxiosConfig) => { - const { url, method, params, data, headersType, responseType } = option + const { url, method, params, data, headers, responseType } = option + const userStore = useUserStoreWithOut() return service.request({ url: url, method, @@ -13,7 +12,9 @@ const request = (option: AxiosConfig) => { data, responseType: responseType, headers: { - 'Content-Type': headersType || defaultHeaders + 'Content-Type': CONTENT_TYPE, + [userStore.getTokenKey ?? 'Authorization']: userStore.getToken ?? '', + ...headers } }) } diff --git a/src/config/axios/service.ts b/src/axios/service.ts similarity index 78% rename from src/config/axios/service.ts rename to src/axios/service.ts index dd66ddd..9933bda 100644 --- a/src/config/axios/service.ts +++ b/src/axios/service.ts @@ -1,18 +1,16 @@ import axios, { AxiosError } from 'axios' -import config, { defaultRequestInterceptors, defaultResponseInterceptors } from './config' +import { defaultRequestInterceptors, defaultResponseInterceptors } from './config' import { AxiosInstance, InternalAxiosRequestConfig, RequestConfig, AxiosResponse } from './types' import { ElMessage } from 'element-plus' +import { REQUEST_TIMEOUT } from '@/constants' -const { interceptors, baseUrl } = config -export const PATH_URL = baseUrl[import.meta.env.VITE_API_BASE_PATH] - -const { requestInterceptors, responseInterceptors } = interceptors +export const PATH_URL = import.meta.env.VITE_API_BASE_PATH const abortControllerMap: Map = new Map() const axiosInstance: AxiosInstance = axios.create({ - ...config, + timeout: REQUEST_TIMEOUT, baseURL: PATH_URL }) @@ -28,6 +26,7 @@ axiosInstance.interceptors.response.use( (res: AxiosResponse) => { const url = res.config.url || '' abortControllerMap.delete(url) + // 这里不能做任何处理,否则后面的 interceptors 拿不到完整的上下文了 return res }, (error: AxiosError) => { @@ -37,8 +36,8 @@ axiosInstance.interceptors.response.use( } ) -axiosInstance.interceptors.request.use(requestInterceptors || defaultRequestInterceptors) -axiosInstance.interceptors.response.use(responseInterceptors || defaultResponseInterceptors) +axiosInstance.interceptors.request.use(defaultRequestInterceptors) +axiosInstance.interceptors.response.use(defaultResponseInterceptors) const service = { request: (config: RequestConfig) => { diff --git a/src/config/axios/types/index.ts b/src/axios/types/index.ts similarity index 74% rename from src/config/axios/types/index.ts rename to src/axios/types/index.ts index b900c17..b70eb26 100644 --- a/src/config/axios/types/index.ts +++ b/src/axios/types/index.ts @@ -15,18 +15,6 @@ interface RequestInterceptors { responseInterceptors?: (config: T) => T responseInterceptorsCatch?: (err: any) => any } -interface AxiosConfig { - baseUrl: { - base: string - dev: string - pro: string - test: string - } - code: number - defaultHeaders: AxiosHeaders - timeout: number - interceptors: RequestInterceptors -} interface RequestConfig extends AxiosRequestConfig { interceptors?: RequestInterceptors @@ -36,7 +24,6 @@ export { AxiosResponse, RequestInterceptors, RequestConfig, - AxiosConfig, AxiosInstance, InternalAxiosRequestConfig, AxiosRequestHeaders, diff --git a/src/components/Button/index.ts b/src/components/Button/index.ts new file mode 100644 index 0000000..6ae43b1 --- /dev/null +++ b/src/components/Button/index.ts @@ -0,0 +1,3 @@ +import BaseButton from './src/Button.vue' + +export { BaseButton } diff --git a/src/components/Button/src/Button.vue b/src/components/Button/src/Button.vue new file mode 100644 index 0000000..e5af71b --- /dev/null +++ b/src/components/Button/src/Button.vue @@ -0,0 +1,121 @@ + + + diff --git a/src/components/Menu/src/Menu.vue b/src/components/Menu/src/Menu.vue index 74e2d7d..e3448d6 100644 --- a/src/components/Menu/src/Menu.vue +++ b/src/components/Menu/src/Menu.vue @@ -155,6 +155,7 @@ export default defineComponent({ .is-active { & > .@{elNamespace}-sub-menu__title { color: var(--left-menu-text-active-color) !important; + // background-color: var(--left-menu-bg-color) !important; } } @@ -168,7 +169,6 @@ export default defineComponent({ } // 设置选中时的高亮背景和高亮颜色 - .@{elNamespace}-sub-menu.is-active, .@{elNamespace}-menu-item.is-active { color: var(--left-menu-text-active-color) !important; background-color: var(--left-menu-bg-active-color) !important; @@ -235,7 +235,7 @@ export default defineComponent({ .@{elNamespace}-menu-item.is-active { position: relative; - &:after { + &::after { display: none !important; } } @@ -270,6 +270,7 @@ export default defineComponent({ .is-active { & > .el-sub-menu__title { color: var(--left-menu-text-active-color) !important; + // background-color: var(--left-menu-bg-color) !important; } } diff --git a/src/components/Menu/src/components/useRenderMenuItem.tsx b/src/components/Menu/src/components/useRenderMenuItem.tsx index 17a520a..3a33922 100644 --- a/src/components/Menu/src/components/useRenderMenuItem.tsx +++ b/src/components/Menu/src/components/useRenderMenuItem.tsx @@ -1,24 +1,24 @@ import { ElSubMenu, ElMenuItem } from 'element-plus' -import type { RouteMeta } from 'vue-router' import { hasOneShowingChild } from '../helper' import { isUrl } from '@/utils/is' import { useRenderMenuTitle } from './useRenderMenuTitle' import { useDesign } from '@/hooks/web/useDesign' import { pathResolve } from '@/utils/routerHelper' +const { renderMenuTitle } = useRenderMenuTitle() + export const useRenderMenuItem = ( // allRouters: AppRouteRecordRaw[] = [], menuMode: 'vertical' | 'horizontal' ) => { const renderMenuItem = (routers: AppRouteRecordRaw[], parentPath = '/') => { - return routers.map((v) => { - const meta = (v.meta ?? {}) as RouteMeta - if (!meta.hidden) { + return routers + .filter((v) => !v.meta?.hidden) + .map((v) => { + const meta = v.meta ?? {} const { oneShowingChild, onlyOneChild } = hasOneShowingChild(v.children, v) const fullPath = isUrl(v.path) ? v.path : pathResolve(parentPath, v.path) // getAllParentPath(allRouters, v.path).join('/') - const { renderMenuTitle } = useRenderMenuTitle() - if ( oneShowingChild && (!onlyOneChild?.children || onlyOneChild?.noShowingChildren) && @@ -49,8 +49,7 @@ export const useRenderMenuItem = ( ) } - } - }) + }) } return { diff --git a/src/components/Search/src/Search.vue b/src/components/Search/src/Search.vue index 2fe42ec..5a15b4f 100644 --- a/src/components/Search/src/Search.vue +++ b/src/components/Search/src/Search.vue @@ -88,6 +88,9 @@ const newSchema = computed(() => { /> ) + }, + label: () => { + return   } } } @@ -117,11 +120,14 @@ const setProps = (props: SearchProps = {}) => { outsideProps.value = props } +const schemaRef = ref([]) + // 监听表单结构化数组,重新生成formModel watch( () => unref(newSchema), async (schema = []) => { formModel.value = initModel(schema, unref(formModel)) + schemaRef.value = schema }, { immediate: true, @@ -241,7 +247,7 @@ const onFormValidate = (prop: FormItemProp, isValid: boolean, message: string) = hide-required-asterisk :inline="getProps.inline" :is-col="getProps.isCol" - :schema="newSchema" + :schema="schemaRef" @register="formRegister" @validate="onFormValidate" /> diff --git a/src/components/Setting/src/Setting.vue b/src/components/Setting/src/Setting.vue index 7f6e4a4..3581761 100644 --- a/src/components/Setting/src/Setting.vue +++ b/src/components/Setting/src/Setting.vue @@ -1,5 +1,5 @@ @@ -278,12 +277,14 @@ const clear = () => {
- {{ t('setting.copy') }} + {{ + t('setting.copy') + }}
- + {{ t('setting.clearAndReset') }} - +
diff --git a/src/components/Setting/src/components/InterfaceDisplay.vue b/src/components/Setting/src/components/InterfaceDisplay.vue index 8e7d779..466dc65 100644 --- a/src/components/Setting/src/components/InterfaceDisplay.vue +++ b/src/components/Setting/src/components/InterfaceDisplay.vue @@ -108,13 +108,21 @@ const greyModeChange = (show: boolean) => { } // 动态路由 -const dynamicRouter = ref(appStore.getDynamicRouter) +const dynamicRouter = ref(!!appStore.getDynamicRouter) const dynamicRouterChange = (show: boolean) => { ElMessage.info(t('setting.reExperienced')) appStore.setDynamicRouter(show) } +// 服务端动态路由 +const serverDynamicRouter = ref(appStore.getServerDynamicRouter) + +const serverDynamicRouterChange = (show: boolean) => { + ElMessage.info(t('setting.reExperienced')) + appStore.setServerDynamicRouter(show) +} + // 固定菜单 const fixedMenu = ref(appStore.getFixedMenu) @@ -206,6 +214,11 @@ watch( +
+ {{ t('setting.serverDynamicRouter') }} + +
+
{{ t('setting.fixedMenu') }} diff --git a/src/components/Setting/src/components/LayoutRadioPicker.vue b/src/components/Setting/src/components/LayoutRadioPicker.vue index 96b1dbe..de6e80f 100644 --- a/src/components/Setting/src/components/LayoutRadioPicker.vue +++ b/src/components/Setting/src/components/LayoutRadioPicker.vue @@ -67,7 +67,7 @@ const layout = computed(() => appStore.getLayout) border: 2px solid #e5e7eb; border-radius: 4px; - &:before { + &::before { position: absolute; top: 0; left: 0; @@ -79,14 +79,14 @@ const layout = computed(() => appStore.getLayout) content: ''; } - &:after { + &::after { position: absolute; top: 0; left: 0; width: 100%; height: 25%; background-color: #fff; - border-radius: 4px 4px 0 4px; + border-radius: 4px 4px 0; content: ''; } } @@ -95,7 +95,7 @@ const layout = computed(() => appStore.getLayout) border: 2px solid #e5e7eb; border-radius: 4px; - &:before { + &::before { position: absolute; top: 0; left: 0; @@ -107,7 +107,7 @@ const layout = computed(() => appStore.getLayout) content: ''; } - &:after { + &::after { position: absolute; top: 0; left: 0; @@ -123,7 +123,7 @@ const layout = computed(() => appStore.getLayout) border: 2px solid #e5e7eb; border-radius: 4px; - &:before { + &::before { position: absolute; top: 0; left: 0; @@ -140,7 +140,7 @@ const layout = computed(() => appStore.getLayout) border: 2px solid #e5e7eb; border-radius: 4px; - &:before { + &::before { position: absolute; top: 0; left: 0; @@ -152,7 +152,7 @@ const layout = computed(() => appStore.getLayout) content: ''; } - &:after { + &::after { position: absolute; top: 0; left: 0; diff --git a/src/components/Table/src/Table.vue b/src/components/Table/src/Table.vue index 6fc3ff9..4eec3fc 100644 --- a/src/components/Table/src/Table.vue +++ b/src/components/Table/src/Table.vue @@ -5,7 +5,9 @@ import { ElPagination, ComponentSize, ElTooltipProps, - ElImage + ElImage, + ElEmpty, + ElCard } from 'element-plus' import { defineComponent, PropType, ref, computed, unref, watch, onMounted } from 'vue' import { propTypes } from '@/utils/propTypes' @@ -15,8 +17,10 @@ import { set, get } from 'lodash-es' import { CSSProperties } from 'vue' import { getSlot } from '@/utils/tsxHelper' import TableActions from './components/TableActions.vue' -// import Sortable from 'sortablejs' -// import { Icon } from '@/components/Icon' +import { isImgPath } from '@/utils/is' +import { createVideoViewer } from '@/components/VideoPlayer' +import { Icon } from '@/components/Icon' +import { BaseButton } from '@/components/Button' export default defineComponent({ name: 'Table', @@ -32,8 +36,6 @@ export default defineComponent({ type: Array as PropType, default: () => [] }, - // 展开行 - // expand: propTypes.bool.def(false), // 是否展示分页 pagination: { type: Object as PropType, @@ -62,7 +64,6 @@ export default defineComponent({ type: Array as PropType, default: () => [] }, - // sortable: propTypes.bool.def(false), height: propTypes.oneOfType([Number, String]), maxHeight: propTypes.oneOfType([Number, String]), stripe: propTypes.bool.def(false), @@ -186,9 +187,27 @@ export default defineComponent({ default: 'fixed' }, scrollbarAlwaysOn: propTypes.bool.def(false), - flexible: propTypes.bool.def(false) + flexible: propTypes.bool.def(false), + // 自定义内容 + customContent: propTypes.bool.def(false), + cardBodyStyle: { + type: Object as PropType, + default: () => ({}) + }, + cardBodyClass: { + type: String as PropType, + default: '' + }, + cardWrapStyle: { + type: Object as PropType, + default: () => ({}) + }, + cardWrapClass: { + type: String as PropType, + default: '' + } }, - emits: ['update:pageSize', 'update:currentPage', 'register', 'refresh', 'sortable-change'], + emits: ['update:pageSize', 'update:currentPage', 'register', 'refresh'], setup(props, { attrs, emit, slots, expose }) { const elTableRef = ref>() @@ -213,33 +232,6 @@ export default defineComponent({ return propsObj }) - // const sortableEl = ref() - // 初始化拖拽 - // const initDropTable = () => { - // const el = unref(elTableRef)?.$el.querySelector('.el-table__body tbody') - // if (!el) return - // if (unref(sortableEl)) unref(sortableEl).destroy() - - // sortableEl.value = Sortable.create(el, { - // handle: '.table-move', - // animation: 180, - // onEnd(e: any) { - // emit('sortable-change', e) - // } - // }) - // } - - // watch( - // () => getProps.value.sortable, - // async (v) => { - // await nextTick() - // v && initDropTable() - // }, - // { - // immediate: true - // } - // ) - const setProps = (props: TableProps = {}) => { mergeProps.value = Object.assign(unref(mergeProps), props) outsideProps.value = { ...props } as any @@ -260,7 +252,7 @@ export default defineComponent({ const addColumn = (column: TableColumn, index?: number) => { const { columns } = unref(getProps) - if (index) { + if (index !== void 0) { columns.splice(index, 0, column) } else { columns.push(column) @@ -391,14 +383,28 @@ export default defineComponent({ const renderPreview = (url: string) => { return (
- + {isImgPath(url) ? ( + + ) : ( + } + onClick={() => { + createVideoViewer({ + url + }) + }} + > + 预览 + + )}
) } @@ -438,6 +444,7 @@ export default defineComponent({ reserveSelection={reserveSelection} align={align} headerAlign={headerAlign} + selectable={v.selectable} width="50" > ) @@ -489,41 +496,68 @@ export default defineComponent({ return () => { const tableSlots = {} if (getSlot(slots, 'empty')) { - tableSlots['empty'] = (...args: any[]) => getSlot(slots, 'empty', ...args) + tableSlots['empty'] = (...args: any[]) => getSlot(slots, 'empty', args) } if (getSlot(slots, 'append')) { - tableSlots['append'] = (...args: any[]) => getSlot(slots, 'append', ...args) + tableSlots['append'] = (...args: any[]) => getSlot(slots, 'append', args) } - // const { sortable } = unref(getProps) - - // const sortableEl = sortable ? ( - // - // - // - // ) : null - return (
- {unref(getProps).showAction ? ( - - ) : null} - - {{ - default: () => renderTableColumn(), - ...tableSlots - }} - + {unref(getProps).customContent ? ( +
+ {unref(getProps)?.data?.length ? ( + unref(getProps)?.data.map((item) => { + const cardSlots = { + default: () => { + return getSlot(slots, 'content', item) + } + } + if (getSlot(slots, 'content-header')) { + cardSlots['header'] = () => { + return getSlot(slots, 'content-header', item) + } + } + if (getSlot(slots, 'content-footer')) { + cardSlots['footer'] = () => { + return getSlot(slots, 'content-footer', item) + } + } + return ( + + {cardSlots} + + ) + }) + ) : ( +
+ +
+ )} +
+ ) : ( + <> + {unref(getProps).showAction ? ( + + ) : null} + + {{ + default: () => renderTableColumn(), + ...tableSlots + }} + + + )} {unref(getProps).pagination ? ( -import { ElDropdown, ElDropdownMenu, ElDropdownItem, ElMessageBox } from 'element-plus' +import { ElDropdown, ElDropdownMenu, ElDropdownItem } from 'element-plus' import { useI18n } from '@/hooks/web/useI18n' -import { useStorage } from '@/hooks/web/useStorage' -import { resetRouter } from '@/router' -import { useRouter } from 'vue-router' -import { loginOutApi } from '@/api/login' import { useDesign } from '@/hooks/web/useDesign' -import { useTagsViewStore } from '@/store/modules/tagsView' import LockDialog from './components/LockDialog.vue' import { ref, computed } from 'vue' import LockPage from './components/LockPage.vue' import { useLockStore } from '@/store/modules/lock' +import { useUserStore } from '@/store/modules/user' + +const userStore = useUserStore() const lockStore = useLockStore() const getIsLock = computed(() => lockStore.getLockInfo?.isLock ?? false) -const tagsViewStore = useTagsViewStore() - const { getPrefixCls } = useDesign() const prefixCls = getPrefixCls('user-info') const { t } = useI18n() -const { clear } = useStorage() - -const { replace } = useRouter() - const loginOut = () => { - ElMessageBox.confirm(t('common.loginOutMessage'), t('common.reminder'), { - confirmButtonText: t('common.ok'), - cancelButtonText: t('common.cancel'), - type: 'warning' - }) - .then(async () => { - const res = await loginOutApi().catch(() => {}) - if (res) { - clear() - tagsViewStore.delAllViews() - resetRouter() // 重置静态路由表 - replace('/login') - } - }) - .catch(() => {}) + userStore.logoutConfirm() } const dialogVisible = ref(false) @@ -66,7 +44,9 @@ const toDocument = () => { alt="" class="w-[calc(var(--logo-height)-25px)] rounded-[50%]" /> - Archer + {{ + userStore.getUserInfo?.username + }}