From 4ff6b73c2bb57764db2bcd8212d82f028e25e36d Mon Sep 17 00:00:00 2001 From: vben Date: Tue, 10 Nov 2020 22:45:39 +0800 Subject: [PATCH] perf: optimize settingDrawer code --- CHANGELOG.zh_CN.md | 4 + index.html | 3 +- mock/demo/table-demo.ts | 2 +- src/api/demo/error.ts | 4 +- src/api/demo/model/tableModel.ts | 4 +- src/api/demo/table.ts | 2 +- src/components/Form/src/types/index.ts | 1 - src/components/Menu/src/BasicMenu.tsx | 3 +- src/components/Menu/src/props.ts | 4 + src/components/Menu/src/useOpenKeys.ts | 16 +- src/layouts/default/LayoutContent.tsx | 4 - src/layouts/default/LayoutMenu.tsx | 30 +- src/layouts/default/LayoutSideBar.tsx | 6 +- src/layouts/default/index.tsx | 9 +- src/layouts/default/setting/SettingDrawer.tsx | 392 ++++-------------- src/layouts/default/setting/const.ts | 104 +++++ src/layouts/default/setting/handler.ts | 186 +++++++++ src/settings/projectSetting.ts | 2 + src/types/config.d.ts | 1 + src/types/global.d.ts | 14 +- src/useApp.ts | 6 +- src/views/dashboard/analysis/index.vue | 35 +- src/views/dashboard/workbench/index.vue | 15 +- src/views/sys/login/Login.vue | 6 +- vite.config.ts | 2 +- 25 files changed, 455 insertions(+), 400 deletions(-) create mode 100644 src/layouts/default/setting/const.ts create mode 100644 src/layouts/default/setting/handler.ts diff --git a/CHANGELOG.zh_CN.md b/CHANGELOG.zh_CN.md index c3f744761..93fc03ca4 100644 --- a/CHANGELOG.zh_CN.md +++ b/CHANGELOG.zh_CN.md @@ -4,6 +4,10 @@ - 表单项的`componentsProps`支持函数类型 +### ⚡ Performance Improvements + +- 优化 settingDrawer 代码 + ### 🐛 Bug Fixes - 修复多个富文本编辑器只显示一个 diff --git a/index.html b/index.html index d7a609d20..e729b5daa 100644 --- a/index.html +++ b/index.html @@ -30,8 +30,7 @@ .app-loading { width: 100%; height: 100%; - - /* background: #f0f2f5; */ + background: #f0f2f5; } .app-loading .app-loading-wrap { diff --git a/mock/demo/table-demo.ts b/mock/demo/table-demo.ts index 754007b9f..7db502b33 100644 --- a/mock/demo/table-demo.ts +++ b/mock/demo/table-demo.ts @@ -11,7 +11,7 @@ const demoList = (() => { address: '@city()', name: '@cname()', 'no|100000-10000000': 100000, - 'status|1': ['正常', '启用', '停用'], + 'status|1': ['normal', 'enable', 'disable'], }); } return result; diff --git a/src/api/demo/error.ts b/src/api/demo/error.ts index fca032955..84766dea2 100644 --- a/src/api/demo/error.ts +++ b/src/api/demo/error.ts @@ -1,12 +1,12 @@ import { defHttp } from '/@/utils/http/axios'; enum Api { - // 该地址不存在 + // The address does not exist Error = '/error', } /** - * @description: 触发ajax错误 + * @description: Trigger ajax error */ export function fireErrorApi() { return defHttp.request({ diff --git a/src/api/demo/model/tableModel.ts b/src/api/demo/model/tableModel.ts index 09b6a3031..322a8b481 100644 --- a/src/api/demo/model/tableModel.ts +++ b/src/api/demo/model/tableModel.ts @@ -1,6 +1,6 @@ import { BasicPageParams, BasicFetchResult } from '/@/api/model/baseModel'; /** - * @description: 请求列表接口参数 + * @description: Request list interface parameters */ export type DemoParams = BasicPageParams; @@ -15,6 +15,6 @@ export interface DemoListItem { } /** - * @description: 请求列表返回值 + * @description: Request list return value */ export type DemoListGetResultModel = BasicFetchResult; diff --git a/src/api/demo/table.ts b/src/api/demo/table.ts index e38208e73..2a82768dc 100644 --- a/src/api/demo/table.ts +++ b/src/api/demo/table.ts @@ -6,7 +6,7 @@ enum Api { } /** - * @description: 获取示例列表值 + * @description: Get sample list value */ export function demoListApi(params: DemoParams) { return defHttp.request({ diff --git a/src/components/Form/src/types/index.ts b/src/components/Form/src/types/index.ts index c9607c978..55d7c577f 100644 --- a/src/components/Form/src/types/index.ts +++ b/src/components/Form/src/types/index.ts @@ -89,7 +89,6 @@ export type ComponentType = | 'InputNumber' | 'InputCountDown' | 'Select' - | 'DictSelect' | 'SelectOptGroup' | 'SelectOption' | 'TreeSelect' diff --git a/src/components/Menu/src/BasicMenu.tsx b/src/components/Menu/src/BasicMenu.tsx index 2c38ca4c9..41ca01217 100644 --- a/src/components/Menu/src/BasicMenu.tsx +++ b/src/components/Menu/src/BasicMenu.tsx @@ -52,7 +52,8 @@ export default defineComponent({ toRef(props, 'items'), toRef(props, 'flatItems'), toRef(props, 'isAppMenu'), - toRef(props, 'mode') + toRef(props, 'mode'), + toRef(props, 'accordion') ); const getOpenKeys = computed(() => { diff --git a/src/components/Menu/src/props.ts b/src/components/Menu/src/props.ts index ad28f487e..1266a8fbb 100644 --- a/src/components/Menu/src/props.ts +++ b/src/components/Menu/src/props.ts @@ -58,6 +58,10 @@ export const basicProps = { type: Boolean as PropType, default: false, }, + accordion: { + type: Boolean as PropType, + default: true, + }, beforeClickFn: { type: Function as PropType, default: null, diff --git a/src/components/Menu/src/useOpenKeys.ts b/src/components/Menu/src/useOpenKeys.ts index 47d4ea319..7cf44404f 100644 --- a/src/components/Menu/src/useOpenKeys.ts +++ b/src/components/Menu/src/useOpenKeys.ts @@ -6,21 +6,31 @@ import type { Ref } from 'vue'; import { unref } from 'vue'; import { menuStore } from '/@/store/modules/menu'; import { getAllParentPath } from '/@/utils/helper/menuHelper'; +import { es6Unique } from '/@/utils'; export function useOpenKeys( menuState: MenuState, menus: Ref, flatMenusRef: Ref, isAppMenu: Ref, - mode: Ref + mode: Ref, + accordion: Ref ) { /** * @description:设置展开 */ function setOpenKeys(menu: MenuType) { const flatMenus = unref(flatMenusRef); - menuState.openKeys = getAllParentPath(flatMenus, menu.path); + if (!unref(accordion)) { + menuState.openKeys = es6Unique([ + ...menuState.openKeys, + ...getAllParentPath(flatMenus, menu.path), + ]); + } else { + menuState.openKeys = getAllParentPath(flatMenus, menu.path); + } } + /** * @description: 重置值 */ @@ -30,7 +40,7 @@ export function useOpenKeys( } function handleOpenChange(openKeys: string[]) { - if (unref(mode) === MenuModeEnum.HORIZONTAL) { + if (unref(mode) === MenuModeEnum.HORIZONTAL || !unref(accordion)) { menuState.openKeys = openKeys; } else { const rootSubMenuKeys: string[] = []; diff --git a/src/layouts/default/LayoutContent.tsx b/src/layouts/default/LayoutContent.tsx index 464fb3996..320f07310 100644 --- a/src/layouts/default/LayoutContent.tsx +++ b/src/layouts/default/LayoutContent.tsx @@ -2,11 +2,8 @@ import { defineComponent } from 'vue'; import { Layout } from 'ant-design-vue'; import { RouterView } from 'vue-router'; -// hooks - import { ContentEnum } from '/@/enums/appEnum'; import { appStore } from '/@/store/modules/app'; -// import PageLayout from '/@/layouts/page/index'; export default defineComponent({ name: 'DefaultLayoutContent', setup() { @@ -17,7 +14,6 @@ export default defineComponent({ return ( {() => } - {/* */} ); }; diff --git a/src/layouts/default/LayoutMenu.tsx b/src/layouts/default/LayoutMenu.tsx index 2ce75abe9..96932139c 100644 --- a/src/layouts/default/LayoutMenu.tsx +++ b/src/layouts/default/LayoutMenu.tsx @@ -55,27 +55,25 @@ export default defineComponent({ }, }, setup(props) { + // Menu array const menusRef = ref([]); + // flat menu array const flatMenusRef = ref([]); const { currentRoute, push } = useRouter(); - // const { addTab } = useTabs(); + // get app config const getProjectConfigRef = computed(() => { return appStore.getProjectConfig; }); + // get is Horizontal const getIsHorizontalRef = computed(() => { return unref(getProjectConfigRef).menuSetting.mode === MenuModeEnum.HORIZONTAL; }); const [throttleHandleSplitLeftMenu] = useThrottle(handleSplitLeftMenu, 50); - // watch( - // () => menuStore.getCurrentTopSplitMenuPathState, - // async (parentPath: string) => { - // throttleHandleSplitLeftMenu(parentPath); - // } - // ); + // Route change split menu watch( [() => unref(currentRoute).path, () => props.splitType], async ([path, splitType]: [string, MenuSplitTyeEnum]) => { @@ -88,23 +86,26 @@ export default defineComponent({ } ); + // Menu changes watch( - [() => permissionStore.getLastBuildMenuTimeState, permissionStore.getBackMenuListState], + [() => permissionStore.getLastBuildMenuTimeState, () => permissionStore.getBackMenuListState], () => { genMenus(); } ); + // split Menu changes watch([() => appStore.getProjectConfig.menuSetting.split], () => { if (props.splitType !== MenuSplitTyeEnum.LEFT && !unref(getIsHorizontalRef)) return; genMenus(); }); + // Handle left menu split async function handleSplitLeftMenu(parentPath: string) { const isSplitMenu = unref(getProjectConfigRef).menuSetting.split; if (!isSplitMenu) return; const { splitType } = props; - // 菜单分割模式-left + // spilt mode left if (splitType === MenuSplitTyeEnum.LEFT) { const children = await getChildrenMenus(parentPath); if (!children) { @@ -128,11 +129,11 @@ export default defineComponent({ } } + // get menus async function genMenus() { const isSplitMenu = unref(getProjectConfigRef).menuSetting.split; - // 普通模式 - + // normal mode const { splitType } = props; if (splitType === MenuSplitTyeEnum.NONE || !isSplitMenu) { flatMenusRef.value = await getFlatMenus(); @@ -140,7 +141,7 @@ export default defineComponent({ return; } - // 菜单分割模式-top + // split-top if (splitType === MenuSplitTyeEnum.TOP) { const parentPath = await getCurrentParentPath(unref(currentRoute).path); menuStore.commitCurrentTopSplitMenuPathState(parentPath); @@ -156,12 +157,11 @@ export default defineComponent({ const { path } = menu; if (path) { const { splitType } = props; - // 菜单分割模式-top + // split mode top if (splitType === MenuSplitTyeEnum.TOP) { menuStore.commitCurrentTopSplitMenuPathState(path); } push(path); - // addTab(path as PageEnum, true); } } @@ -205,6 +205,7 @@ export default defineComponent({ collapsed, collapsedShowTitle, collapsedShowSearch, + accordion, }, } = unref(getProjectConfigRef); @@ -227,6 +228,7 @@ export default defineComponent({ onClickSearchInput={handleClickSearchInput} appendClass={props.splitType === MenuSplitTyeEnum.TOP} isTop={props.isTop} + accordion={accordion} > {{ header: () => diff --git a/src/layouts/default/LayoutSideBar.tsx b/src/layouts/default/LayoutSideBar.tsx index 9367a35e9..9cbfe8949 100644 --- a/src/layouts/default/LayoutSideBar.tsx +++ b/src/layouts/default/LayoutSideBar.tsx @@ -4,9 +4,6 @@ import { Layout } from 'ant-design-vue'; import LayoutTrigger from './LayoutTrigger'; import { menuStore } from '/@/store/modules/menu'; -// import darkMiniIMg from '/@/assets/images/sidebar/dark-mini.png'; -// import lightMiniImg from '/@/assets/images/sidebar/light-mini.png'; -// import lightImg from '/@/assets/images/sidebar/light.png'; import { appStore } from '/@/store/modules/app'; import { MenuModeEnum, MenuSplitTyeEnum, TriggerEnum } from '/@/enums/menuEnum'; import { SIDE_BAR_MINI_WIDTH, SIDE_BAR_SHOW_TIT_MINI_WIDTH } from '/@/enums/appEnum'; @@ -44,7 +41,7 @@ export default defineComponent({ initRef.value = true; } - // 菜单区域拖拽 - 鼠标移动 + // Menu area drag and drop-mouse movement function handleMouseMove(ele: any, wrap: any, clientX: number) { document.onmousemove = function (innerE) { let iT = ele.left + ((innerE || event).clientX - clientX); @@ -98,7 +95,6 @@ export default defineComponent({ const side = unref(sideRef); const wrap = (side || {}).$el; - // const eleWidth = 6; ele && (ele.onmousedown = (e: any) => { menuStore.commitDragStartState(true); diff --git a/src/layouts/default/index.tsx b/src/layouts/default/index.tsx index 3116e096f..6ea8c0b80 100644 --- a/src/layouts/default/index.tsx +++ b/src/layouts/default/index.tsx @@ -19,12 +19,11 @@ import './index.less'; export default defineComponent({ name: 'DefaultLayout', setup() { - // ! 在这里才注册全局组件 - // ! 可以减少首屏代码体积 - // default layout是在登录后才加载的。所以不会打包到首屏去 + // ! Only register global components here + // ! Can reduce the size of the first screen code + // default layout It is loaded after login. So it won’t be packaged to the first screen registerGlobComp(); - // 获取项目配置 const { getFullContent } = useFullContent(); const getProjectConfigRef = computed(() => { @@ -56,8 +55,6 @@ export default defineComponent({ return split || (show && mode !== MenuModeEnum.HORIZONTAL && !unref(getFullContent)); }); - // Get project configuration - // const { getFullContent } = useFullContent(currentRoute); function getTarget(): any { const { headerSetting: { fixed }, diff --git a/src/layouts/default/setting/SettingDrawer.tsx b/src/layouts/default/setting/SettingDrawer.tsx index 0054425e8..d807c1cb5 100644 --- a/src/layouts/default/setting/SettingDrawer.tsx +++ b/src/layouts/default/setting/SettingDrawer.tsx @@ -2,14 +2,7 @@ import { defineComponent, computed, unref, ref } from 'vue'; import { BasicDrawer } from '/@/components/Drawer/index'; import { Divider, Switch, Tooltip, InputNumber, Select } from 'ant-design-vue'; import Button from '/@/components/Button/index.vue'; -import { - MenuModeEnum, - MenuTypeEnum, - MenuThemeEnum, - TopMenuAlignEnum, - TriggerEnum, -} from '/@/enums/menuEnum'; -import { ContentEnum, RouterTransitionEnum } from '/@/enums/appEnum'; +import { MenuModeEnum, MenuTypeEnum } from '/@/enums/menuEnum'; import { CopyOutlined, RedoOutlined, CheckOutlined } from '@ant-design/icons-vue'; import { appStore } from '/@/store/modules/app'; import { userStore } from '/@/store/modules/user'; @@ -24,70 +17,15 @@ import mixImg from '/@/assets/images/layout/menu-mix.svg'; import sidebarImg from '/@/assets/images/layout/menu-sidebar.svg'; import menuTopImg from '/@/assets/images/layout/menu-top.svg'; import { updateColorWeak, updateGrayMode } from '/@/setup/theme'; - -const themeOptions = [ - { - value: MenuThemeEnum.LIGHT, - label: '亮色', - }, - { - value: MenuThemeEnum.DARK, - label: '暗色', - }, -]; -const contentModeOptions = [ - { - value: ContentEnum.FULL, - label: '流式', - }, - { - value: ContentEnum.FIXED, - label: '定宽', - }, -]; -const topMenuAlignOptions = [ - { - value: TopMenuAlignEnum.CENTER, - label: '居中', - }, - { - value: TopMenuAlignEnum.START, - label: '居左', - }, - { - value: TopMenuAlignEnum.END, - label: '居右', - }, -]; - -const menuTriggerOptions = [ - { - value: TriggerEnum.NONE, - label: '不显示', - }, - { - value: TriggerEnum.FOOTER, - label: '底部', - }, - { - value: TriggerEnum.HEADER, - label: '顶部', - }, -]; - -const routerTransitionOptions = [ - RouterTransitionEnum.ZOOM_FADE, - RouterTransitionEnum.FADE, - RouterTransitionEnum.ZOOM_OUT, - RouterTransitionEnum.FADE_SIDE, - RouterTransitionEnum.FADE_BOTTOM, -].map((item) => { - return { - label: item, - value: item, - key: item, - }; -}); +import { baseHandler } from './handler'; +import { + HandlerEnum, + themeOptions, + contentModeOptions, + topMenuAlignOptions, + menuTriggerOptions, + routerTransitionOptions, +} from './const'; interface SwitchOptions { config?: DeepPartial; @@ -139,6 +77,25 @@ export default defineComponent({ }); } + function handleResetSetting() { + try { + appStore.commitProjectConfigState(defaultSetting); + const { colorWeak, grayMode } = defaultSetting; + // updateTheme(themeColor); + updateColorWeak(colorWeak); + updateGrayMode(grayMode); + createMessage.success('重置成功!'); + } catch (error) { + createMessage.error(error); + } + } + + function handleClearAndRedo() { + localStorage.clear(); + userStore.resumeAllState(); + location.reload(); + } + function renderSidebar() { const { headerSetting: { theme: headerTheme }, @@ -175,7 +132,7 @@ export default defineComponent({ {{ default: () => (
, renderSwitchItem('分割菜单', { handler: (e) => { - baseHandler('splitMenu', e); + baseHandler(HandlerEnum.MENU_SPLIT, e); }, def: split, disabled: !unref(getShowMenuRef) || type !== MenuTypeEnum.MIX, }), renderSelectItem('顶栏主题', { handler: (e) => { - baseHandler('headerMenu', e); + baseHandler(HandlerEnum.HEADER_THEME, e); }, def: headerTheme, options: themeOptions, @@ -207,7 +164,7 @@ export default defineComponent({ }), renderSelectItem('菜单主题', { handler: (e) => { - baseHandler('menuTheme', e); + baseHandler(HandlerEnum.MENU_THEME, e); }, def: menuTheme, options: themeOptions, @@ -230,48 +187,49 @@ export default defineComponent({ topMenuAlign, collapsedShowTitle, trigger, + accordion, } = {}, } = appStore.getProjectConfig; return [ renderSwitchItem('侧边菜单拖拽', { handler: (e) => { - baseHandler('hasDrag', e); + baseHandler(HandlerEnum.MENU_HAS_DRAG, e); }, def: hasDrag, disabled: !unref(getShowMenuRef), }), renderSwitchItem('侧边菜单搜索', { handler: (e) => { - baseHandler('showSearch', e); + baseHandler(HandlerEnum.MENU_SHOW_SEARCH, e); }, def: showSearch, disabled: !unref(getShowMenuRef), }), + renderSwitchItem('侧边菜单手风琴模式', { + handler: (e) => { + baseHandler(HandlerEnum.MENU_ACCORDION, e); + }, + def: accordion, + disabled: !unref(getShowMenuRef), + }), renderSwitchItem('折叠菜单', { handler: (e) => { - baseHandler('collapsed', e); + baseHandler(HandlerEnum.MENU_COLLAPSED, e); }, def: collapsed, disabled: !unref(getShowMenuRef), }), renderSwitchItem('折叠菜单显示名称', { handler: (e) => { - baseHandler('collapsedShowTitle', e); + baseHandler(HandlerEnum.MENU_COLLAPSED_SHOW_TITLE, e); }, def: collapsedShowTitle, disabled: !unref(getShowMenuRef) || !collapsed, }), - renderSwitchItem('固定header', { - handler: (e) => { - baseHandler('headerFixed', e); - }, - def: fixed, - disabled: !unref(getShowHeaderRef), - }), renderSelectItem('顶部菜单布局', { handler: (e) => { - baseHandler('topMenuAlign', e); + baseHandler(HandlerEnum.MENU_TOP_ALIGN, e); }, def: topMenuAlign, options: topMenuAlignOptions, @@ -279,14 +237,21 @@ export default defineComponent({ }), renderSelectItem('菜单折叠按钮', { handler: (e) => { - baseHandler('menuTrigger', e); + baseHandler(HandlerEnum.MENU_TRIGGER, e); }, def: trigger, options: menuTriggerOptions, }), + renderSwitchItem('固定header', { + handler: (e) => { + baseHandler(HandlerEnum.HEADER_FIXED, e); + }, + def: fixed, + disabled: !unref(getShowHeaderRef), + }), renderSelectItem('内容区域宽度', { handler: (e) => { - baseHandler('contentMode', e); + baseHandler(HandlerEnum.CONTENT_MODE, e); }, def: contentMode, options: contentModeOptions, @@ -297,8 +262,8 @@ export default defineComponent({ style="width:120px" size="small" min={0} - onChange={(e) => { - baseHandler('lockTime', e); + onChange={(e: any) => { + baseHandler(HandlerEnum.LOCK_TIME, e); }} defaultValue={appStore.getProjectConfig.lockTime} formatter={(value: string) => { @@ -321,7 +286,7 @@ export default defineComponent({ defaultValue={menuWidth} formatter={(value: string) => `${parseInt(value)}px`} onChange={(e: any) => { - baseHandler('menuWidth', e); + baseHandler(HandlerEnum.MENU_WIDTH, e); }} />
, @@ -334,19 +299,19 @@ export default defineComponent({ <> {renderSwitchItem('页面切换loading', { handler: (e) => { - baseHandler('openPageLoading', e); + baseHandler(HandlerEnum.OPEN_PAGE_LOADING, e); }, def: openPageLoading, })} {renderSwitchItem('切换动画', { handler: (e) => { - baseHandler('openRouterTransition', e); + baseHandler(HandlerEnum.OPEN_ROUTE_TRANSITION, e); }, def: openRouterTransition, })} {renderSelectItem('路由动画', { handler: (e) => { - baseHandler('routerTransition', e); + baseHandler(HandlerEnum.ROUTER_TRANSITION, e); }, def: routerTransition, options: routerTransitionOptions, @@ -370,289 +335,77 @@ export default defineComponent({ return [ renderSwitchItem('面包屑', { handler: (e) => { - baseHandler('showBreadCrumb', e); + baseHandler(HandlerEnum.SHOW_BREADCRUMB, e); }, def: showBreadCrumb, disabled: !unref(getShowHeaderRef), }), renderSwitchItem('面包屑图标', { handler: (e) => { - baseHandler('showBreadCrumbIcon', e); + baseHandler(HandlerEnum.SHOW_BREADCRUMB_ICON, e); }, def: showBreadCrumbIcon, disabled: !unref(getShowHeaderRef), }), renderSwitchItem('标签页', { handler: (e) => { - baseHandler('showMultiple', e); + baseHandler(HandlerEnum.TABS_SHOW, e); }, def: showMultiple, }), renderSwitchItem('标签页快捷按钮', { handler: (e) => { - baseHandler('showQuick', e); + baseHandler(HandlerEnum.TABS_SHOW_QUICK, e); }, def: showQuick, disabled: !unref(getShowTabsRef), }), renderSwitchItem('标签页图标', { handler: (e) => { - baseHandler('showTabIcon', e); + baseHandler(HandlerEnum.TABS_SHOW_ICON, e); }, def: showTabIcon, disabled: !unref(getShowTabsRef), }), renderSwitchItem('左侧菜单', { handler: (e) => { - baseHandler('showSidebar', e); + baseHandler(HandlerEnum.MENU_SHOW_SIDEBAR, e); }, def: showMenu, disabled: unref(getIsHorizontalRef), }), renderSwitchItem('顶栏', { handler: (e) => { - baseHandler('showHeader', e); + baseHandler(HandlerEnum.HEADER_SHOW, e); }, def: showHeader, }), renderSwitchItem('Logo', { handler: (e) => { - baseHandler('showLogo', e); + baseHandler(HandlerEnum.SHOW_LOGO, e); }, def: showLogo, }), renderSwitchItem('全屏内容', { handler: (e) => { - baseHandler('fullContent', e); + baseHandler(HandlerEnum.FULL_CONTENT, e); }, def: fullContent, }), renderSwitchItem('灰色模式', { handler: (e) => { - baseHandler('grayMode', e); + baseHandler(HandlerEnum.GRAY_MODE, e); }, def: grayMode, }), renderSwitchItem('色弱模式', { handler: (e) => { - baseHandler('colorWeak', e); + baseHandler(HandlerEnum.COLOR_WEAK, e); }, def: colorWeak, }), ]; } - function baseHandler(event: string, value: any) { - let config: DeepPartial = {}; - if (event === 'layout') { - const { mode, type, split } = value; - const splitOpt = split === undefined ? { split } : {}; - let headerSetting = {}; - if (type === MenuTypeEnum.TOP_MENU) { - headerSetting = { - theme: MenuThemeEnum.DARK, - }; - } - config = { - menuSetting: { - mode, - type, - collapsed: false, - show: true, - ...splitOpt, - }, - headerSetting, - }; - } - if (event === 'hasDrag') { - config = { - menuSetting: { - hasDrag: value, - }, - }; - } - if (event === 'menuTrigger') { - config = { - menuSetting: { - trigger: value, - }, - }; - } - if (event === 'openPageLoading') { - config = { - openPageLoading: value, - }; - } - if (event === 'topMenuAlign') { - config = { - menuSetting: { - topMenuAlign: value, - }, - }; - } - if (event === 'showBreadCrumb') { - config = { - showBreadCrumb: value, - }; - } - if (event === 'showBreadCrumbIcon') { - config = { - showBreadCrumbIcon: value, - }; - } - if (event === 'collapsed') { - config = { - menuSetting: { - collapsed: value, - }, - }; - } - if (event === 'menuWidth') { - config = { - menuSetting: { - menuWidth: value, - }, - }; - } - if (event === 'collapsedShowTitle') { - config = { - menuSetting: { - collapsedShowTitle: value, - }, - }; - } - if (event === 'lockTime') { - config = { - lockTime: value, - }; - } - if (event === 'showQuick') { - config = { - multiTabsSetting: { - showQuick: value, - }, - }; - } - if (event === 'showTabIcon') { - config = { - multiTabsSetting: { - showIcon: value, - }, - }; - } - if (event === 'contentMode') { - config = { - contentMode: value, - }; - } - if (event === 'menuTheme') { - config = { - menuSetting: { - theme: value, - }, - }; - } - if (event === 'splitMenu') { - config = { - menuSetting: { - split: value, - }, - }; - } - if (event === 'showMultiple') { - config = { - multiTabsSetting: { - show: value, - }, - }; - } - if (event === 'headerMenu') { - config = { - headerSetting: { - theme: value, - }, - }; - } - if (event === 'grayMode') { - config = { - grayMode: value, - }; - updateGrayMode(value); - } - if (event === 'colorWeak') { - config = { - colorWeak: value, - }; - updateColorWeak(value); - } - if (event === 'showLogo') { - config = { - showLogo: value, - }; - } - if (event === 'showSearch') { - config = { - menuSetting: { - showSearch: value, - }, - }; - } - if (event === 'showSidebar') { - config = { - menuSetting: { - show: value, - }, - }; - } - if (event === 'openRouterTransition') { - config = { - openRouterTransition: value, - }; - } - if (event === 'routerTransition') { - config = { - routerTransition: value, - }; - } - if (event === 'headerFixed') { - config = { - headerSetting: { - fixed: value, - }, - }; - } - if (event === 'fullContent') { - config = { - fullContent: value, - }; - } - if (event === 'showHeader') { - config = { - headerSetting: { - show: value, - }, - }; - } - appStore.commitProjectConfigState(config); - } - - function handleResetSetting() { - try { - appStore.commitProjectConfigState(defaultSetting); - const { colorWeak, grayMode } = defaultSetting; - // updateTheme(themeColor); - updateColorWeak(colorWeak); - updateGrayMode(grayMode); - createMessage.success('重置成功!'); - } catch (error) { - createMessage.error(error); - } - } - - function handleClearAndRedo() { - localStorage.clear(); - userStore.resumeAllState(); - location.reload(); - } function renderSelectItem(text: string, config?: SelectConfig) { const { handler, def, disabled = false, options } = config || {}; @@ -693,6 +446,7 @@ export default defineComponent({ ); } + return () => ( {{ diff --git a/src/layouts/default/setting/const.ts b/src/layouts/default/setting/const.ts new file mode 100644 index 000000000..0ef2ea0e8 --- /dev/null +++ b/src/layouts/default/setting/const.ts @@ -0,0 +1,104 @@ +import { ContentEnum, RouterTransitionEnum } from '/@/enums/appEnum'; +import { MenuThemeEnum, TopMenuAlignEnum, TriggerEnum } from '/@/enums/menuEnum'; + +export enum HandlerEnum { + CHANGE_LAYOUT, + // menu + MENU_HAS_DRAG, + MENU_ACCORDION, + MENU_TRIGGER, + MENU_TOP_ALIGN, + MENU_COLLAPSED, + MENU_COLLAPSED_SHOW_TITLE, + MENU_WIDTH, + MENU_SHOW_SIDEBAR, + MENU_THEME, + MENU_SPLIT, + MENU_SHOW_SEARCH, + + // header + HEADER_SHOW, + HEADER_THEME, + HEADER_FIXED, + + TABS_SHOW_QUICK, + TABS_SHOW, + TABS_SHOW_ICON, + + OPEN_PAGE_LOADING, + OPEN_ROUTE_TRANSITION, + ROUTER_TRANSITION, + LOCK_TIME, + FULL_CONTENT, + CONTENT_MODE, + SHOW_BREADCRUMB, + SHOW_BREADCRUMB_ICON, + GRAY_MODE, + COLOR_WEAK, + SHOW_LOGO, +} + +export const themeOptions = [ + { + value: MenuThemeEnum.LIGHT, + label: '亮色', + }, + { + value: MenuThemeEnum.DARK, + label: '暗色', + }, +]; + +export const contentModeOptions = [ + { + value: ContentEnum.FULL, + label: '流式', + }, + { + value: ContentEnum.FIXED, + label: '定宽', + }, +]; + +export const topMenuAlignOptions = [ + { + value: TopMenuAlignEnum.CENTER, + label: '居中', + }, + { + value: TopMenuAlignEnum.START, + label: '居左', + }, + { + value: TopMenuAlignEnum.END, + label: '居右', + }, +]; + +export const menuTriggerOptions = [ + { + value: TriggerEnum.NONE, + label: '不显示', + }, + { + value: TriggerEnum.FOOTER, + label: '底部', + }, + { + value: TriggerEnum.HEADER, + label: '顶部', + }, +]; + +export const routerTransitionOptions = [ + RouterTransitionEnum.ZOOM_FADE, + RouterTransitionEnum.FADE, + RouterTransitionEnum.ZOOM_OUT, + RouterTransitionEnum.FADE_SIDE, + RouterTransitionEnum.FADE_BOTTOM, +].map((item) => { + return { + label: item, + value: item, + }; +}); diff --git a/src/layouts/default/setting/handler.ts b/src/layouts/default/setting/handler.ts new file mode 100644 index 000000000..a30818b66 --- /dev/null +++ b/src/layouts/default/setting/handler.ts @@ -0,0 +1,186 @@ +import { HandlerEnum } from './const'; +import { MenuThemeEnum, MenuTypeEnum } from '/@/enums/menuEnum'; +import { updateColorWeak, updateGrayMode } from '/@/setup/theme'; +import { appStore } from '/@/store/modules/app'; +import { ProjectConfig } from '/@/types/config'; + +export function baseHandler(event: HandlerEnum, value: any) { + const config = handler(event, value); + appStore.commitProjectConfigState(config); +} + +export function handler(event: HandlerEnum, value: any): DeepPartial { + switch (event) { + case HandlerEnum.CHANGE_LAYOUT: + const { mode, type, split } = value; + const splitOpt = split === undefined ? { split } : {}; + let headerSetting = {}; + if (type === MenuTypeEnum.TOP_MENU) { + headerSetting = { + theme: MenuThemeEnum.DARK, + }; + } + return { + menuSetting: { + mode, + type, + collapsed: false, + show: true, + ...splitOpt, + }, + headerSetting, + }; + + case HandlerEnum.MENU_HAS_DRAG: + return { + menuSetting: { + hasDrag: value, + }, + }; + + case HandlerEnum.MENU_ACCORDION: + return { + menuSetting: { + accordion: value, + }, + }; + case HandlerEnum.MENU_TRIGGER: + return { + menuSetting: { + trigger: value, + }, + }; + case HandlerEnum.MENU_TOP_ALIGN: + return { + menuSetting: { + topMenuAlign: value, + }, + }; + case HandlerEnum.MENU_COLLAPSED: + return { + menuSetting: { + collapsed: value, + }, + }; + case HandlerEnum.MENU_WIDTH: + return { + menuSetting: { + menuWidth: value, + }, + }; + case HandlerEnum.MENU_COLLAPSED_SHOW_TITLE: + return { + menuSetting: { + collapsedShowTitle: value, + }, + }; + case HandlerEnum.MENU_SHOW_SIDEBAR: + return { + menuSetting: { + show: value, + }, + }; + case HandlerEnum.MENU_THEME: + return { + menuSetting: { + theme: value, + }, + }; + case HandlerEnum.MENU_SPLIT: + return { + menuSetting: { + split: value, + }, + }; + case HandlerEnum.MENU_SHOW_SEARCH: + return { + menuSetting: { + showSearch: value, + }, + }; + case HandlerEnum.OPEN_PAGE_LOADING: + return { + openPageLoading: value, + }; + case HandlerEnum.OPEN_ROUTE_TRANSITION: + return { + openRouterTransition: value, + }; + case HandlerEnum.ROUTER_TRANSITION: + return { + routerTransition: value, + }; + case HandlerEnum.LOCK_TIME: + return { + lockTime: value, + }; + case HandlerEnum.FULL_CONTENT: + return { + fullContent: value, + }; + case HandlerEnum.CONTENT_MODE: + return { + contentMode: value, + }; + case HandlerEnum.SHOW_BREADCRUMB: + return { + showBreadCrumb: value, + }; + case HandlerEnum.SHOW_BREADCRUMB_ICON: + return { + showBreadCrumbIcon: value, + }; + case HandlerEnum.GRAY_MODE: + updateGrayMode(value); + return { + grayMode: value, + }; + case HandlerEnum.COLOR_WEAK: + updateColorWeak(value); + return { + colorWeak: value, + }; + case HandlerEnum.SHOW_LOGO: + return { + showLogo: value, + }; + case HandlerEnum.TABS_SHOW_QUICK: + return { + multiTabsSetting: { + showQuick: value, + }, + }; + case HandlerEnum.TABS_SHOW_QUICK: + return { + multiTabsSetting: { + showIcon: value, + }, + }; + case HandlerEnum.TABS_SHOW: + return { + multiTabsSetting: { + show: value, + }, + }; + case HandlerEnum.HEADER_THEME: + return { + headerSetting: { + theme: value, + }, + }; + case HandlerEnum.HEADER_FIXED: + return { + headerSetting: { + fixed: value, + }, + }; + case HandlerEnum.HEADER_SHOW: + return { + headerSetting: { + show: value, + }, + }; + default: + return {}; + } +} diff --git a/src/settings/projectSetting.ts b/src/settings/projectSetting.ts index 5461c24f6..2249b27e7 100644 --- a/src/settings/projectSetting.ts +++ b/src/settings/projectSetting.ts @@ -74,6 +74,8 @@ const setting: ProjectConfig = { collapsedShowSearch: false, // 折叠触发器的位置 trigger: TriggerEnum.HEADER, + // 开启手风琴模式,只显示一个菜单 + accordion: true, }, // 消息配置 messageSetting: { diff --git a/src/types/config.d.ts b/src/types/config.d.ts index b2d145439..c6f22bca6 100644 --- a/src/types/config.d.ts +++ b/src/types/config.d.ts @@ -24,6 +24,7 @@ export interface MenuSetting { topMenuAlign: 'start' | 'center' | 'end'; collapsedShowSearch: boolean; trigger: TriggerEnum; + accordion: boolean; } export interface MultiTabsSetting { diff --git a/src/types/global.d.ts b/src/types/global.d.ts index ea395e115..115301da0 100644 --- a/src/types/global.d.ts +++ b/src/types/global.d.ts @@ -30,12 +30,16 @@ declare type Indexable = { declare type Hash = Indexable; +// declare type DeepPartial = { +// [P in keyof T]?: T[P] extends (infer U)[] +// ? RecursivePartial[] +// : T[P] extends object +// ? RecursivePartial +// : T[P]; +// }; + declare type DeepPartial = { - [P in keyof T]?: T[P] extends (infer U)[] - ? RecursivePartial[] - : T[P] extends object - ? RecursivePartial - : T[P]; + [P in keyof T]?: DeepPartial; }; declare type SelectOptions = { diff --git a/src/useApp.ts b/src/useApp.ts index 38f0c63f4..aa279fcc4 100644 --- a/src/useApp.ts +++ b/src/useApp.ts @@ -42,7 +42,7 @@ export function useThemeMode(mode: ThemeModeEnum) { }; } -// 初始化项目配置 +// Initial project configuration export function useInitAppConfigStore() { let projCfg: ProjectConfig = getLocal(PROJ_CFG_KEY) as ProjectConfig; if (!projCfg) { @@ -78,12 +78,12 @@ export function useConfigProvider() { }; } -// 初始化网络监听 +// Initialize network monitoring export function useListenerNetWork() { const { listenNetWork } = appStore.getProjectConfig; if (!listenNetWork) return; const { replace } = useRouter(); - // 检测网络状态 + // Check network status useNetWork({ onLineFn: () => { replace(PageEnum.BASE_HOME); diff --git a/src/views/dashboard/analysis/index.vue b/src/views/dashboard/analysis/index.vue index 4cfb93513..fd1599874 100644 --- a/src/views/dashboard/analysis/index.vue +++ b/src/views/dashboard/analysis/index.vue @@ -1,42 +1,42 @@