From 8440b7cabe052142300aae010ae4b6becebbde81 Mon Sep 17 00:00:00 2001 From: Uyarn Date: Thu, 24 Mar 2022 01:37:51 +0800 Subject: [PATCH] feat: support tabs page --- .env | 4 +- .eslintrc | 23 +-- src/config/style.ts | 1 + src/interface.ts | 15 ++ src/layouts/components/Content.vue | 24 ++- src/layouts/index.tsx | 138 ++++++++++++++++-- src/layouts/setting.vue | 3 + src/pages/dashboard/base/index.vue | 9 ++ src/pages/dashboard/detail/index.vue | 8 + src/pages/detail/advanced/index.vue | 8 + src/pages/detail/base/index.vue | 8 + src/pages/detail/deploy/index.vue | 8 + src/pages/detail/secondary/index.vue | 8 + src/pages/form/base/index.vue | 8 + src/pages/form/step/index.vue | 8 + src/pages/list/base/index.vue | 8 + src/pages/list/card/index.vue | 8 + src/pages/list/filter/index.vue | 5 + src/pages/list/tree/index.vue | 8 + src/pages/login/index.vue | 6 + src/pages/result/403/index.vue | 6 +- src/pages/result/404/index.vue | 6 + src/pages/result/500/index.vue | 6 +- .../result/browser-incompatible/index.vue | 7 +- src/pages/result/fail/index.vue | 6 +- src/pages/result/network-error/index.vue | 5 + src/pages/result/success/index.vue | 6 +- src/pages/user/index.vue | 6 + src/router/modules/base.ts | 4 +- src/router/modules/components.ts | 34 ++--- src/router/modules/others.ts | 2 +- src/store/index.ts | 1 + src/store/modules/tabs-router.ts | 51 +++++++ src/style/layout.less | 23 ++- 34 files changed, 406 insertions(+), 65 deletions(-) create mode 100644 src/store/modules/tabs-router.ts diff --git a/.env b/.env index 4bf8a25..7e878e0 100644 --- a/.env +++ b/.env @@ -1,3 +1,3 @@ VITE_SOME_KEY=123 -# 打包路径 -VITE_BASE_URL = / \ No newline at end of file +# 打包路径 根据项目不同按需配置 +VITE_BASE_URL = ./ \ No newline at end of file diff --git a/.eslintrc b/.eslintrc index 7467fd5..0e482c7 100644 --- a/.eslintrc +++ b/.eslintrc @@ -15,10 +15,7 @@ "defineProps": "readonly", "defineEmits": "readonly" }, - "plugins": [ - "vue", - "@typescript-eslint" - ], + "plugins": ["vue", "@typescript-eslint"], "parserOptions": { "parser": "@typescript-eslint/parser", "sourceType": "module", @@ -28,27 +25,22 @@ } }, "settings": { - "import/extensions": [ - ".js", - ".jsx", - ".ts", - ".tsx" - ] + "import/extensions": [".js", ".jsx", ".ts", ".tsx"] }, "rules": { "no-console": "off", "no-continue": "off", "no-restricted-syntax": "off", "no-plusplus": "off", - "no-param-reassign": "off", - "no-shadow": "off", + "no-param-reassign": "off", + "no-shadow": "off", "guard-for-in": "off", "import/extensions": "off", "import/no-unresolved": "off", "import/no-extraneous-dependencies": "off", "import/prefer-default-export": "off", - + "import/first": "off", // https://github.com/vuejs/vue-eslint-parser/issues/58 "@typescript-eslint/no-explicit-any": "off", "@typescript-eslint/explicit-module-boundary-types": "off", "vue/first-attribute-linebreak": 0 @@ -61,9 +53,8 @@ "vue/require-default-prop": 0, "vue/multi-word-component-names": 0, "vue/no-reserved-props": 0, - "vue/no-v-html": 0, - + "vue/no-v-html": 0 } } ] -} \ No newline at end of file +} diff --git a/src/config/style.ts b/src/config/style.ts index 6f700ef..3de08f3 100644 --- a/src/config/style.ts +++ b/src/config/style.ts @@ -8,6 +8,7 @@ export default { isFooterAside: false, isSidebarFixed: true, isHeaderFixed: true, + isUseTabsRouter: false, showHeader: true, backgroundTheme: 'blueGrey', brandTheme: 'default', diff --git a/src/interface.ts b/src/interface.ts index 6098e33..4a201b8 100644 --- a/src/interface.ts +++ b/src/interface.ts @@ -1,3 +1,4 @@ +import { RouteRecordName } from 'vue-router'; import STYLE_CONFIG from '@/config/style'; export interface ResDataType { @@ -37,3 +38,17 @@ export interface NotificationItem { date: string; quality: string; } + +export interface TRouterInfo { + path: string; + routeIdx?: number; + title?: string; + name?: RouteRecordName; + isAlive?: boolean; + isHome?: boolean; +} + +export interface TTabRouterType { + isRefreshing: boolean; + tabRouterList: Array; +} diff --git a/src/layouts/components/Content.vue b/src/layouts/components/Content.vue index a897267..d0ccb04 100644 --- a/src/layouts/components/Content.vue +++ b/src/layouts/components/Content.vue @@ -1,10 +1,30 @@ + + + diff --git a/src/pages/detail/advanced/index.vue b/src/pages/detail/advanced/index.vue index f7d0fd6..ec69747 100644 --- a/src/pages/detail/advanced/index.vue +++ b/src/pages/detail/advanced/index.vue @@ -109,6 +109,13 @@ + + + + diff --git a/src/pages/detail/base/index.vue b/src/pages/detail/base/index.vue index 447f5da..7a1d8ee 100644 --- a/src/pages/detail/base/index.vue +++ b/src/pages/detail/base/index.vue @@ -26,6 +26,13 @@ + + + + diff --git a/src/pages/detail/deploy/index.vue b/src/pages/detail/deploy/index.vue index e552a88..9397c43 100644 --- a/src/pages/detail/deploy/index.vue +++ b/src/pages/detail/deploy/index.vue @@ -68,6 +68,13 @@ + + + + diff --git a/src/pages/detail/secondary/index.vue b/src/pages/detail/secondary/index.vue index f330dfd..517eb2e 100644 --- a/src/pages/detail/secondary/index.vue +++ b/src/pages/detail/secondary/index.vue @@ -49,6 +49,13 @@ /> + + + + diff --git a/src/pages/form/base/index.vue b/src/pages/form/base/index.vue index 3f01427..ceddbb8 100644 --- a/src/pages/form/base/index.vue +++ b/src/pages/form/base/index.vue @@ -156,6 +156,13 @@ + + + + diff --git a/src/pages/form/step/index.vue b/src/pages/form/step/index.vue index e9f57f3..2ac7608 100644 --- a/src/pages/form/step/index.vue +++ b/src/pages/form/step/index.vue @@ -139,6 +139,13 @@ + + + + diff --git a/src/pages/list/base/index.vue b/src/pages/list/base/index.vue index 7f22a1e..4c8e6b8 100644 --- a/src/pages/list/base/index.vue +++ b/src/pages/list/base/index.vue @@ -66,6 +66,13 @@ /> + + + + diff --git a/src/pages/result/403/index.vue b/src/pages/result/403/index.vue index 470c07e..77e2433 100644 --- a/src/pages/result/403/index.vue +++ b/src/pages/result/403/index.vue @@ -3,7 +3,11 @@ 返回首页 - + diff --git a/src/pages/result/404/index.vue b/src/pages/result/404/index.vue index c41c3e6..8b209ec 100644 --- a/src/pages/result/404/index.vue +++ b/src/pages/result/404/index.vue @@ -4,6 +4,12 @@ + + diff --git a/src/pages/result/500/index.vue b/src/pages/result/500/index.vue index 957960a..c88bf03 100644 --- a/src/pages/result/500/index.vue +++ b/src/pages/result/500/index.vue @@ -3,7 +3,11 @@ 返回首页 - + diff --git a/src/pages/result/browser-incompatible/index.vue b/src/pages/result/browser-incompatible/index.vue index a83fbc8..a1e80c3 100644 --- a/src/pages/result/browser-incompatible/index.vue +++ b/src/pages/result/browser-incompatible/index.vue @@ -18,11 +18,16 @@ - + + diff --git a/src/router/modules/base.ts b/src/router/modules/base.ts index 9d6423c..e4ef588 100644 --- a/src/router/modules/base.ts +++ b/src/router/modules/base.ts @@ -11,13 +11,13 @@ export default [ children: [ { path: 'base', - name: 'dashboardBase', + name: 'DashboardBase', component: () => import('@/pages/dashboard/base/index.vue'), meta: { title: '概览仪表盘' }, }, { path: 'detail', - name: 'dashboardDetail', + name: 'DashboardDetail', component: () => import('@/pages/dashboard/detail/index.vue'), meta: { title: '统计报表' }, }, diff --git a/src/router/modules/components.ts b/src/router/modules/components.ts index 12451f0..48daa53 100644 --- a/src/router/modules/components.ts +++ b/src/router/modules/components.ts @@ -13,25 +13,25 @@ export default [ children: [ { path: 'base', - name: 'listBase', + name: 'ListBase', component: () => import('@/pages/list/base/index.vue'), meta: { title: '基础列表页' }, }, { path: 'card', - name: 'listCard', + name: 'ListCard', component: () => import('@/pages/list/card/index.vue'), meta: { title: '卡片列表页' }, }, { path: 'filter', - name: 'listFilter', + name: 'ListFilter', component: () => import('@/pages/list/filter/index.vue'), meta: { title: '筛选列表页' }, }, { path: 'tree', - name: 'listTree', + name: 'ListTree', component: () => import('@/pages/list/tree/index.vue'), meta: { title: '树状筛选列表页' }, }, @@ -46,13 +46,13 @@ export default [ children: [ { path: 'base', - name: 'formBase', + name: 'FormBase', component: () => import('@/pages/form/base/index.vue'), meta: { title: '基础表单页' }, }, { path: 'step', - name: 'formStep', + name: 'FormStep', component: () => import('@/pages/form/step/index.vue'), meta: { title: '分步表单页' }, }, @@ -67,25 +67,25 @@ export default [ children: [ { path: 'base', - name: 'detailBase', + name: 'DetailBase', component: () => import('@/pages/detail/base/index.vue'), meta: { title: '基础详情页' }, }, { path: 'advanced', - name: 'detailAdvanced', + name: 'DetailAdvanced', component: () => import('@/pages/detail/advanced/index.vue'), meta: { title: '多卡片详情页' }, }, { path: 'deploy', - name: 'detailDeploy', + name: 'DetailDeploy', component: () => import('@/pages/detail/deploy/index.vue'), meta: { title: '数据详情页' }, }, { path: 'secondary', - name: 'detailSecondary', + name: 'DetailSecondary', component: () => import('@/pages/detail/secondary/index.vue'), meta: { title: '二级详情页' }, }, @@ -100,43 +100,43 @@ export default [ children: [ { path: 'success', - name: 'resultSuccess', + name: 'ResultSuccess', component: () => import('@/pages/result/success/index.vue'), meta: { title: '成功页' }, }, { path: 'fail', - name: 'resultFail', + name: 'ResultFail', component: () => import('@/pages/result/fail/index.vue'), meta: { title: '失败页' }, }, { path: 'network-error', - name: 'warningNetworkError', + name: 'ResultNetworkError', component: () => import('@/pages/result/network-error/index.vue'), meta: { title: '网络异常' }, }, { path: '403', - name: 'warning403', + name: 'Result403', component: () => import('@/pages/result/403/index.vue'), meta: { title: '无权限' }, }, { path: '404', - name: 'warning404', + name: 'Result404', component: () => import('@/pages/result/404/index.vue'), meta: { title: '访问页面不存在页' }, }, { path: '500', - name: 'warning500', + name: 'Result500', component: () => import('@/pages/result/500/index.vue'), meta: { title: '服务器出错页' }, }, { path: 'browser-incompatible', - name: 'warningBrowserIncompatible', + name: 'ResultBrowserIncompatible', component: () => import('@/pages/result/browser-incompatible/index.vue'), meta: { title: '浏览器不兼容页' }, }, diff --git a/src/router/modules/others.ts b/src/router/modules/others.ts index 3e17447..35bab4b 100644 --- a/src/router/modules/others.ts +++ b/src/router/modules/others.ts @@ -11,7 +11,7 @@ export default [ children: [ { path: 'index', - name: 'userIndex', + name: 'UserIndex', component: () => import('@/pages/user/index.vue'), meta: { title: '个人中心' }, }, diff --git a/src/store/index.ts b/src/store/index.ts index d872601..20e1448 100644 --- a/src/store/index.ts +++ b/src/store/index.ts @@ -8,5 +8,6 @@ export * from './modules/notification'; export * from './modules/permission'; export * from './modules/user'; export * from './modules/setting'; +export * from './modules/tabs-router'; export default store; diff --git a/src/store/modules/tabs-router.ts b/src/store/modules/tabs-router.ts new file mode 100644 index 0000000..bfb8d6b --- /dev/null +++ b/src/store/modules/tabs-router.ts @@ -0,0 +1,51 @@ +import { defineStore } from 'pinia'; +import { TRouterInfo, TTabRouterType } from '@/interface'; +import { store } from '@/store'; + +const state = { + tabRouterList: [{ path: '/dashboard/base', routeIdx: 0, title: '仪表盘', name: 'DashboardBase', isHome: true }], + isRefreshing: false, +}; + +export const useTabsRouterStore = defineStore('tabsRouter', { + state: () => state, + getters: { + tabRouters: (state: TTabRouterType) => state.tabRouterList, + refreshing: (state: TTabRouterType) => state.isRefreshing, + }, + actions: { + toggleTabRouterAlive(routeIdx: number) { + this.isRefreshing = !this.isRefreshing; + this.tabRouters[routeIdx].isAlive = !this.tabRouterList[routeIdx].isAlive; + }, + appendTabRouterList(newRoute: TRouterInfo) { + if (!this.tabRouterList.find((route: TRouterInfo) => route.path === newRoute.path)) { + // eslint-disable-next-line no-param-reassign + this.tabRouterList = this.tabRouterList.concat(newRoute); + } + }, + subtractCurrentTabRouter(newRoute: TRouterInfo) { + const { routeIdx } = newRoute; + this.tabRouterList = this.tabRouterList.slice(0, routeIdx).concat(this.tabRouterList.slice(routeIdx + 1)); + }, + subtractTabRouterBehind(newRoute: TRouterInfo) { + const { routeIdx } = newRoute; + this.tabRouterList = this.tabRouterList.slice(0, routeIdx + 1); + }, + subtractTabRouterAhead(newRoute: TRouterInfo) { + const { routeIdx } = newRoute; + this.tabRouterList = this.tabRouterList.slice(routeIdx); + }, + subtractTabRouterOther(newRoute: TRouterInfo) { + const { routeIdx } = newRoute; + this.tabRouterList = [this.tabRouterList?.[routeIdx]]; + }, + removeTabRouterList() { + this.tabRouterList = []; + }, + }, +}); + +export function getTabsRouterStore() { + return useTabsRouterStore(store); +} diff --git a/src/style/layout.less b/src/style/layout.less index 49ce650..5754eb2 100644 --- a/src/style/layout.less +++ b/src/style/layout.less @@ -56,13 +56,22 @@ } } + &-content-layout { + padding: @spacer-3; + } + &-layout{ height: calc(100vh - 64px); overflow-y: scroll; - } - - &-content-layout { - padding: @spacer-3; + &-tabs-nav { + max-width: 100%; + position: fixed; + overflow: visible; + z-index: 999; + } + &-tabs-nav + .@{prefix}-content-layout { + padding-top: 48px + @spacer-3; + } } &-footer-layout { @@ -151,6 +160,12 @@ } } +.route-tabs-dropdown { + .t-icon { + margin-right: 8px; + } +} + .logo-container { cursor: pointer; display: inline-flex;