Commit da04913ef324fff122732b445c1b1d1d662b87a3

Authored by vben
1 parent 7d9b521c

feat: added settingButtonPosition configuration close #275

CHANGELOG.zh_CN.md
  1 +## Wip
  2 +
  3 +### ✨ Features
  4 +
  5 +- 新增 `settingButtonPosition`配置项,用于配置`设置`按钮位置
  6 +
1 ## 2.0.0 (2021-02-18) 7 ## 2.0.0 (2021-02-18)
2 8
3 ## (破坏性更新) Breaking changes 9 ## (破坏性更新) Breaking changes
build/vite/plugin/compress.ts
1 /** 1 /**
2 * Used to package and output gzip. Note that this does not work properly in Vite, the specific reason is still being investigated 2 * Used to package and output gzip. Note that this does not work properly in Vite, the specific reason is still being investigated
  3 + * https://github.com/anncwb/vite-plugin-compression
3 */ 4 */
4 import type { Plugin } from 'vite'; 5 import type { Plugin } from 'vite';
5 6
build/vite/plugin/imagemin.ts
1 // Image resource files used to compress the output of the production environment 1 // Image resource files used to compress the output of the production environment
  2 +// https://github.com/anncwb/vite-plugin-imagemin
2 3
3 import viteImagemin from 'vite-plugin-imagemin'; 4 import viteImagemin from 'vite-plugin-imagemin';
4 5
build/vite/plugin/index.ts
@@ -4,7 +4,6 @@ import vue from '@vitejs/plugin-vue'; @@ -4,7 +4,6 @@ import vue from '@vitejs/plugin-vue';
4 import vueJsx from '@vitejs/plugin-vue-jsx'; 4 import vueJsx from '@vitejs/plugin-vue-jsx';
5 import legacy from '@vitejs/plugin-legacy'; 5 import legacy from '@vitejs/plugin-legacy';
6 6
7 -import windiCSS from 'vite-plugin-windicss';  
8 import PurgeIcons from 'vite-plugin-purge-icons'; 7 import PurgeIcons from 'vite-plugin-purge-icons';
9 8
10 import { ViteEnv } from '../../utils'; 9 import { ViteEnv } from '../../utils';
@@ -16,6 +15,7 @@ import { configStyleImportPlugin } from './styleImport'; @@ -16,6 +15,7 @@ import { configStyleImportPlugin } from './styleImport';
16 import { configVisualizerConfig } from './visualizer'; 15 import { configVisualizerConfig } from './visualizer';
17 import { configThemePlugin } from './theme'; 16 import { configThemePlugin } from './theme';
18 import { configImageminPlugin } from './imagemin'; 17 import { configImageminPlugin } from './imagemin';
  18 +import { configWindiCssPlugin } from './windicss';
19 19
20 export function createVitePlugins(viteEnv: ViteEnv, isBuild: boolean) { 20 export function createVitePlugins(viteEnv: ViteEnv, isBuild: boolean) {
21 const { VITE_USE_IMAGEMIN, VITE_USE_MOCK, VITE_LEGACY, VITE_BUILD_COMPRESS } = viteEnv; 21 const { VITE_USE_IMAGEMIN, VITE_USE_MOCK, VITE_LEGACY, VITE_BUILD_COMPRESS } = viteEnv;
@@ -25,7 +25,6 @@ export function createVitePlugins(viteEnv: ViteEnv, isBuild: boolean) { @@ -25,7 +25,6 @@ export function createVitePlugins(viteEnv: ViteEnv, isBuild: boolean) {
25 vue(), 25 vue(),
26 // have to 26 // have to
27 vueJsx(), 27 vueJsx(),
28 - ...windiCSS(),  
29 ]; 28 ];
30 29
31 // @vitejs/plugin-legacy 30 // @vitejs/plugin-legacy
@@ -34,6 +33,9 @@ export function createVitePlugins(viteEnv: ViteEnv, isBuild: boolean) { @@ -34,6 +33,9 @@ export function createVitePlugins(viteEnv: ViteEnv, isBuild: boolean) {
34 // vite-plugin-html 33 // vite-plugin-html
35 vitePlugins.push(configHtmlPlugin(viteEnv, isBuild)); 34 vitePlugins.push(configHtmlPlugin(viteEnv, isBuild));
36 35
  36 + // vite-plugin-windicss
  37 + vitePlugins.push(configWindiCssPlugin());
  38 +
37 // vite-plugin-mock 39 // vite-plugin-mock
38 VITE_USE_MOCK && vitePlugins.push(configMockPlugin(isBuild)); 40 VITE_USE_MOCK && vitePlugins.push(configMockPlugin(isBuild));
39 41
build/vite/plugin/windicss.ts 0 → 100644
  1 +import windiCSS from 'vite-plugin-windicss';
  2 +
  3 +import type { Plugin } from 'vite';
  4 +
  5 +export function configWindiCssPlugin(): Plugin[] {
  6 + return windiCSS({
  7 + safelist: 'shadow shadow-xl',
  8 + preflight: {
  9 + enableAll: true,
  10 + },
  11 + });
  12 +}
package.json
@@ -107,7 +107,7 @@ @@ -107,7 +107,7 @@
107 "vite-plugin-pwa": "^0.4.7", 107 "vite-plugin-pwa": "^0.4.7",
108 "vite-plugin-style-import": "^0.7.2", 108 "vite-plugin-style-import": "^0.7.2",
109 "vite-plugin-theme": "^0.4.3", 109 "vite-plugin-theme": "^0.4.3",
110 - "vite-plugin-windicss": "0.2.2", 110 + "vite-plugin-windicss": "0.3.3",
111 "vue-eslint-parser": "^7.5.0", 111 "vue-eslint-parser": "^7.5.0",
112 "yargs": "^16.2.0" 112 "yargs": "^16.2.0"
113 }, 113 },
src/enums/appEnum.ts
@@ -22,6 +22,12 @@ export enum ThemeEnum { @@ -22,6 +22,12 @@ export enum ThemeEnum {
22 LIGHT = 'light', 22 LIGHT = 'light',
23 } 23 }
24 24
  25 +export enum SettingButtonPositionEnum {
  26 + AUTO = 'auto',
  27 + HEADER = 'header',
  28 + FIXED = 'fixed',
  29 +}
  30 +
25 /** 31 /**
26 * 权限模式 32 * 权限模式
27 */ 33 */
src/hooks/event/useKeyPress.ts
@@ -160,13 +160,5 @@ export function getTargetElement( @@ -160,13 +160,5 @@ export function getTargetElement(
160 if (!target) { 160 if (!target) {
161 return defaultElement; 161 return defaultElement;
162 } 162 }
163 -  
164 - let targetElement: TargetElement | undefined | null;  
165 -  
166 - if (isFunction(target)) {  
167 - targetElement = target();  
168 - } else {  
169 - targetElement = unref(target);  
170 - }  
171 - return targetElement; 163 + return isFunction(target) ? target() : unref(target);
172 } 164 }
src/hooks/setting/useRootSetting.ts
@@ -16,6 +16,8 @@ const getPageLoading = computed(() => appStore.getPageLoading); @@ -16,6 +16,8 @@ const getPageLoading = computed(() => appStore.getPageLoading);
16 16
17 const getOpenKeepAlive = computed(() => unref(getRootSetting).openKeepAlive); 17 const getOpenKeepAlive = computed(() => unref(getRootSetting).openKeepAlive);
18 18
  19 +const getSettingButtonPosition = computed(() => unref(getRootSetting).settingButtonPosition);
  20 +
19 const getCanEmbedIFramePage = computed(() => unref(getRootSetting).canEmbedIFramePage); 21 const getCanEmbedIFramePage = computed(() => unref(getRootSetting).canEmbedIFramePage);
20 22
21 const getPermissionMode = computed(() => unref(getRootSetting).permissionMode); 23 const getPermissionMode = computed(() => unref(getRootSetting).permissionMode);
@@ -58,6 +60,7 @@ export function useRootSetting() { @@ -58,6 +60,7 @@ export function useRootSetting() {
58 return { 60 return {
59 setRootSetting, 61 setRootSetting,
60 62
  63 + getSettingButtonPosition,
61 getFullContent, 64 getFullContent,
62 getColorWeak, 65 getColorWeak,
63 getGrayMode, 66 getGrayMode,
src/hooks/web/useFullScreen.ts
@@ -57,12 +57,7 @@ export function useFullscreen( @@ -57,12 +57,7 @@ export function useFullscreen(
57 57
58 async function toggleFullscreen(): Promise<void> { 58 async function toggleFullscreen(): Promise<void> {
59 if (!unref(target)) return; 59 if (!unref(target)) return;
60 -  
61 - if (isFullscreen()) {  
62 - return exitFullscreen();  
63 - } else {  
64 - return enterFullscreen();  
65 - } 60 + return isFullscreen() ? exitFullscreen() : enterFullscreen();
66 } 61 }
67 62
68 return { 63 return {
src/layouts/default/feature/index.vue
1 -<template>  
2 - <LayoutLockPage />  
3 - <BackTop v-if="getUseOpenBackTop" :target="getTarget" />  
4 -</template>  
5 <script lang="ts"> 1 <script lang="ts">
6 - import { defineComponent } from 'vue';  
7 - import { createAsyncComponent } from '/@/utils/factory/createAsyncComponent'; 2 + import { defineComponent, computed, unref } from 'vue';
8 import { BackTop } from 'ant-design-vue'; 3 import { BackTop } from 'ant-design-vue';
  4 +
9 import { useRootSetting } from '/@/hooks/setting/useRootSetting'; 5 import { useRootSetting } from '/@/hooks/setting/useRootSetting';
  6 + import { useHeaderSetting } from '/@/hooks/setting/useHeaderSetting';
  7 + import { useDesign } from '/@/hooks/web/useDesign';
  8 +
  9 + import { SettingButtonPositionEnum } from '/@/enums/appEnum';
  10 + import { createAsyncComponent } from '/@/utils/factory/createAsyncComponent';
10 11
11 export default defineComponent({ 12 export default defineComponent({
12 name: 'LayoutFeatures', 13 name: 'LayoutFeatures',
13 components: { 14 components: {
14 BackTop, 15 BackTop,
15 LayoutLockPage: createAsyncComponent(() => import('/@/views/sys/lock/index.vue')), 16 LayoutLockPage: createAsyncComponent(() => import('/@/views/sys/lock/index.vue')),
  17 + SettingDrawer: createAsyncComponent(() => import('/@/layouts/default/setting/index.vue')),
16 }, 18 },
17 setup() { 19 setup() {
18 - const { getUseOpenBackTop } = useRootSetting(); 20 + const {
  21 + getUseOpenBackTop,
  22 + getShowSettingButton,
  23 + getSettingButtonPosition,
  24 + getFullContent,
  25 + } = useRootSetting();
  26 +
  27 + const { prefixCls } = useDesign('setting-drawer-fearure');
  28 + const { getShowHeader } = useHeaderSetting();
  29 +
  30 + const getIsFixedSettingDrawer = computed(() => {
  31 + if (!unref(getShowSettingButton)) {
  32 + return false;
  33 + }
  34 + const settingButtonPosition = unref(getSettingButtonPosition);
  35 +
  36 + if (settingButtonPosition === SettingButtonPositionEnum.AUTO) {
  37 + return !unref(getShowHeader) || unref(getFullContent);
  38 + }
  39 + return settingButtonPosition === SettingButtonPositionEnum.FIXED;
  40 + });
19 41
20 return { 42 return {
21 getTarget: () => document.body, 43 getTarget: () => document.body,
22 getUseOpenBackTop, 44 getUseOpenBackTop,
  45 + getIsFixedSettingDrawer,
  46 + prefixCls,
23 }; 47 };
24 }, 48 },
25 }); 49 });
26 </script> 50 </script>
  51 +
  52 +<template>
  53 + <LayoutLockPage />
  54 + <BackTop v-if="getUseOpenBackTop" :target="getTarget" />
  55 + <SettingDrawer v-if="getIsFixedSettingDrawer" :class="prefixCls" />
  56 +</template>
  57 +
  58 +<style lang="less">
  59 + @prefix-cls: ~'@{namespace}-setting-drawer-fearure';
  60 +
  61 + .@{prefix-cls} {
  62 + position: absolute;
  63 + top: 45%;
  64 + right: 0;
  65 + z-index: 10;
  66 + display: flex;
  67 + padding: 10px;
  68 + color: @white;
  69 + cursor: pointer;
  70 + background: @primary-color;
  71 + border-radius: 6px 0 0 6px;
  72 + justify-content: center;
  73 + align-items: center;
  74 +
  75 + svg {
  76 + width: 1em;
  77 + height: 1em;
  78 + }
  79 + }
  80 +</style>
src/layouts/default/header/components/user-dropdown/index.vue
@@ -22,7 +22,7 @@ @@ -22,7 +22,7 @@
22 icon="ion:lock-closed-outline" 22 icon="ion:lock-closed-outline"
23 /> 23 />
24 <MenuItem 24 <MenuItem
25 - key="loginOut" 25 + key="logout"
26 :text="t('layout.header.dropdownItemLoginOut')" 26 :text="t('layout.header.dropdownItemLoginOut')"
27 icon="ion:power-outline" 27 icon="ion:power-outline"
28 /> 28 />
@@ -51,7 +51,7 @@ @@ -51,7 +51,7 @@
51 51
52 import { createAsyncComponent } from '/@/utils/factory/createAsyncComponent'; 52 import { createAsyncComponent } from '/@/utils/factory/createAsyncComponent';
53 53
54 - type MenuEvent = 'loginOut' | 'doc' | 'lock'; 54 + type MenuEvent = 'logout' | 'doc' | 'lock';
55 55
56 export default defineComponent({ 56 export default defineComponent({
57 name: 'UserDropdown', 57 name: 'UserDropdown',
@@ -93,7 +93,7 @@ @@ -93,7 +93,7 @@
93 93
94 function handleMenuClick(e: { key: MenuEvent }) { 94 function handleMenuClick(e: { key: MenuEvent }) {
95 switch (e.key) { 95 switch (e.key) {
96 - case 'loginOut': 96 + case 'logout':
97 handleLoginOut(); 97 handleLoginOut();
98 break; 98 break;
99 case 'doc': 99 case 'doc':
src/layouts/default/header/index.vue
@@ -50,7 +50,7 @@ @@ -50,7 +50,7 @@
50 50
51 <UserDropDown :theme="getHeaderTheme" /> 51 <UserDropDown :theme="getHeaderTheme" />
52 52
53 - <SettingDrawer v-if="getShowSettingButton" :class="`${prefixCls}-action__item`" /> 53 + <SettingDrawer v-if="getShowSetting" :class="`${prefixCls}-action__item`" />
54 </div> 54 </div>
55 </Header> 55 </Header>
56 </template> 56 </template>
@@ -72,6 +72,7 @@ @@ -72,6 +72,7 @@
72 import { useLocaleSetting } from '/@/hooks/setting/useLocaleSetting'; 72 import { useLocaleSetting } from '/@/hooks/setting/useLocaleSetting';
73 73
74 import { MenuModeEnum, MenuSplitTyeEnum } from '/@/enums/menuEnum'; 74 import { MenuModeEnum, MenuSplitTyeEnum } from '/@/enums/menuEnum';
  75 + import { SettingButtonPositionEnum } from '/@/enums/appEnum';
75 import { AppLocalePicker } from '/@/components/Application'; 76 import { AppLocalePicker } from '/@/components/Application';
76 77
77 import { UserDropDown, LayoutBreadcrumb, FullScreen, Notify, ErrorAction } from './components'; 78 import { UserDropDown, LayoutBreadcrumb, FullScreen, Notify, ErrorAction } from './components';
@@ -112,7 +113,11 @@ @@ -112,7 +113,11 @@
112 getIsMixSidebar, 113 getIsMixSidebar,
113 } = useMenuSetting(); 114 } = useMenuSetting();
114 const { getShowLocale } = useLocaleSetting(); 115 const { getShowLocale } = useLocaleSetting();
115 - const { getUseErrorHandle, getShowSettingButton } = useRootSetting(); 116 + const {
  117 + getUseErrorHandle,
  118 + getShowSettingButton,
  119 + getSettingButtonPosition,
  120 + } = useRootSetting();
116 121
117 const { 122 const {
118 getHeaderTheme, 123 getHeaderTheme,
@@ -122,6 +127,7 @@ @@ -122,6 +127,7 @@
122 getShowContent, 127 getShowContent,
123 getShowBread, 128 getShowBread,
124 getShowHeaderLogo, 129 getShowHeaderLogo,
  130 + getShowHeader,
125 } = useHeaderSetting(); 131 } = useHeaderSetting();
126 132
127 const { getIsMobile } = useAppInject(); 133 const { getIsMobile } = useAppInject();
@@ -138,6 +144,18 @@ @@ -138,6 +144,18 @@
138 ]; 144 ];
139 }); 145 });
140 146
  147 + const getShowSetting = computed(() => {
  148 + if (!unref(getShowSettingButton)) {
  149 + return false;
  150 + }
  151 + const settingButtonPosition = unref(getSettingButtonPosition);
  152 +
  153 + if (settingButtonPosition === SettingButtonPositionEnum.AUTO) {
  154 + return unref(getShowHeader);
  155 + }
  156 + return settingButtonPosition === SettingButtonPositionEnum.HEADER;
  157 + });
  158 +
141 const getLogoWidth = computed(() => { 159 const getLogoWidth = computed(() => {
142 if (!unref(getIsMixMode) || unref(getIsMobile)) { 160 if (!unref(getIsMixMode) || unref(getIsMobile)) {
143 return {}; 161 return {};
@@ -175,6 +193,7 @@ @@ -175,6 +193,7 @@
175 getLogoWidth, 193 getLogoWidth,
176 getIsMixSidebar, 194 getIsMixSidebar,
177 getShowSettingButton, 195 getShowSettingButton,
  196 + getShowSetting,
178 }; 197 };
179 }, 198 },
180 }); 199 });
src/layouts/default/setting/index.vue
1 <template> 1 <template>
2 - <div @click="openDrawer" :class="prefixCls"> 2 + <div @click="openDrawer">
3 <Icon icon="ion:settings-outline" /> 3 <Icon icon="ion:settings-outline" />
4 <SettingDrawer @register="register" /> 4 <SettingDrawer @register="register" />
5 </div> 5 </div>
@@ -10,7 +10,6 @@ @@ -10,7 +10,6 @@
10 import Icon from '/@/components/Icon'; 10 import Icon from '/@/components/Icon';
11 11
12 import { useDrawer } from '/@/components/Drawer'; 12 import { useDrawer } from '/@/components/Drawer';
13 - import { useDesign } from '/@/hooks/web/useDesign';  
14 13
15 export default defineComponent({ 14 export default defineComponent({
16 name: 'SettingButton', 15 name: 'SettingButton',
@@ -18,9 +17,7 @@ @@ -18,9 +17,7 @@
18 setup() { 17 setup() {
19 const [register, { openDrawer }] = useDrawer(); 18 const [register, { openDrawer }] = useDrawer();
20 19
21 - const { prefixCls } = useDesign('setting-button');  
22 return { 20 return {
23 - prefixCls,  
24 register, 21 register,
25 openDrawer, 22 openDrawer,
26 }; 23 };
src/locales/lang/en/sys/app.ts
1 export default { 1 export default {
2 - loginOutTip: 'Reminder',  
3 - loginOutMessage: 'Confirm to exit the system?', 2 + logoutTip: 'Reminder',
  3 + logoutMessage: 'Confirm to exit the system?',
4 menuLoading: 'Menu loading...', 4 menuLoading: 'Menu loading...',
5 }; 5 };
src/locales/lang/zh_CN/sys/app.ts
1 export default { 1 export default {
2 - loginOutTip: '温馨提醒',  
3 - loginOutMessage: '是否确认退出系统?', 2 + logoutTip: '温馨提醒',
  3 + logoutMessage: '是否确认退出系统?',
4 menuLoading: '菜单加载中...', 4 menuLoading: '菜单加载中...',
5 }; 5 };
src/settings/projectSetting.ts
@@ -2,7 +2,13 @@ import type { ProjectConfig } from &#39;/@/types/config&#39;; @@ -2,7 +2,13 @@ import type { ProjectConfig } from &#39;/@/types/config&#39;;
2 2
3 import { MenuTypeEnum, MenuModeEnum, TriggerEnum, MixSidebarTriggerEnum } from '/@/enums/menuEnum'; 3 import { MenuTypeEnum, MenuModeEnum, TriggerEnum, MixSidebarTriggerEnum } from '/@/enums/menuEnum';
4 import { CacheTypeEnum } from '/@/enums/cacheEnum'; 4 import { CacheTypeEnum } from '/@/enums/cacheEnum';
5 -import { ContentEnum, PermissionModeEnum, ThemeEnum, RouterTransitionEnum } from '/@/enums/appEnum'; 5 +import {
  6 + ContentEnum,
  7 + PermissionModeEnum,
  8 + ThemeEnum,
  9 + RouterTransitionEnum,
  10 + SettingButtonPositionEnum,
  11 +} from '/@/enums/appEnum';
6 import { primaryColor, themeMode } from '../../build/config/themeConfig'; 12 import { primaryColor, themeMode } from '../../build/config/themeConfig';
7 13
8 // ! You need to clear the browser cache after the change 14 // ! You need to clear the browser cache after the change
@@ -10,6 +16,9 @@ const setting: ProjectConfig = { @@ -10,6 +16,9 @@ const setting: ProjectConfig = {
10 // Whether to show the configuration button 16 // Whether to show the configuration button
11 showSettingButton: true, 17 showSettingButton: true,
12 18
  19 + // `Settings` button position
  20 + settingButtonPosition: SettingButtonPositionEnum.AUTO,
  21 +
13 // Permission mode 22 // Permission mode
14 permissionMode: PermissionModeEnum.ROLE, 23 permissionMode: PermissionModeEnum.ROLE,
15 24
src/store/modules/permission.ts
@@ -98,22 +98,22 @@ class Permission extends VuexModule { @@ -98,22 +98,22 @@ class Permission extends VuexModule {
98 if (!roles) return true; 98 if (!roles) return true;
99 return roleList.some((role) => roles.includes(role)); 99 return roleList.some((role) => roles.includes(role));
100 }); 100 });
101 - // 如果确定不需要做后台动态权限,请将下面整个判断注释 101 + // If you are sure that you do not need to do background dynamic permissions, please comment the entire judgment below
102 } else if (permissionMode === PermissionModeEnum.BACK) { 102 } else if (permissionMode === PermissionModeEnum.BACK) {
103 createMessage.loading({ 103 createMessage.loading({
104 content: t('sys.app.menuLoading'), 104 content: t('sys.app.menuLoading'),
105 duration: 1, 105 duration: 1,
106 }); 106 });
107 - // 这里获取后台路由菜单逻辑自行修改 107 + // Here to get the background routing menu logic to modify by yourself
108 const paramId = id || userStore.getUserInfoState.userId; 108 const paramId = id || userStore.getUserInfoState.userId;
109 if (!paramId) { 109 if (!paramId) {
110 throw new Error('paramId is undefined!'); 110 throw new Error('paramId is undefined!');
111 } 111 }
112 let routeList = (await getMenuListById({ id: paramId })) as AppRouteRecordRaw[]; 112 let routeList = (await getMenuListById({ id: paramId })) as AppRouteRecordRaw[];
113 113
114 - // 动态引入组件 114 + // Dynamically introduce components
115 routeList = transformObjToRoute(routeList); 115 routeList = transformObjToRoute(routeList);
116 - // 后台路由转菜单结构 116 + // Background routing to menu structure
117 const backMenuList = transformRouteToMenu(routeList); 117 const backMenuList = transformRouteToMenu(routeList);
118 118
119 this.commitBackMenuListState(backMenuList); 119 this.commitBackMenuListState(backMenuList);
src/store/modules/user.ts
@@ -131,10 +131,10 @@ class User extends VuexModule { @@ -131,10 +131,10 @@ class User extends VuexModule {
131 } 131 }
132 132
133 /** 133 /**
134 - * @description: login out 134 + * @description: logout
135 */ 135 */
136 @Action 136 @Action
137 - async loginOut(goLogin = false) { 137 + async logout(goLogin = false) {
138 goLogin && router.push(PageEnum.BASE_LOGIN); 138 goLogin && router.push(PageEnum.BASE_LOGIN);
139 } 139 }
140 140
@@ -147,10 +147,10 @@ class User extends VuexModule { @@ -147,10 +147,10 @@ class User extends VuexModule {
147 const { t } = useI18n(); 147 const { t } = useI18n();
148 createConfirm({ 148 createConfirm({
149 iconType: 'warning', 149 iconType: 'warning',
150 - title: t('sys.app.loginOutTip'),  
151 - content: t('sys.app.loginOutMessage'), 150 + title: t('sys.app.logoutTip'),
  151 + content: t('sys.app.logoutMessage'),
152 onOk: async () => { 152 onOk: async () => {
153 - await this.loginOut(true); 153 + await this.logout(true);
154 }, 154 },
155 }); 155 });
156 } 156 }
src/types/config.d.ts
1 import { MenuTypeEnum, MenuModeEnum, TriggerEnum, MixSidebarTriggerEnum } from '/@/enums/menuEnum'; 1 import { MenuTypeEnum, MenuModeEnum, TriggerEnum, MixSidebarTriggerEnum } from '/@/enums/menuEnum';
2 -import { ContentEnum, PermissionModeEnum, ThemeEnum, RouterTransitionEnum } from '/@/enums/appEnum'; 2 +import {
  3 + ContentEnum,
  4 + PermissionModeEnum,
  5 + ThemeEnum,
  6 + RouterTransitionEnum,
  7 + SettingButtonPositionEnum,
  8 +} from '/@/enums/appEnum';
3 import { CacheTypeEnum } from '/@/enums/cacheEnum'; 9 import { CacheTypeEnum } from '/@/enums/cacheEnum';
4 import type { LocaleType } from '/@/locales/types'; 10 import type { LocaleType } from '/@/locales/types';
5 import { ThemeMode } from '../../build/config/lessModifyVars'; 11 import { ThemeMode } from '../../build/config/lessModifyVars';
@@ -88,6 +94,7 @@ export interface ProjectConfig { @@ -88,6 +94,7 @@ export interface ProjectConfig {
88 94
89 // 是否显示配置按钮 95 // 是否显示配置按钮
90 showSettingButton: boolean; 96 showSettingButton: boolean;
  97 + settingButtonPosition: SettingButtonPositionEnum;
91 // 权限模式 98 // 权限模式
92 permissionMode: PermissionModeEnum; 99 permissionMode: PermissionModeEnum;
93 // 网站灰色模式,用于可能悼念的日期开启 100 // 网站灰色模式,用于可能悼念的日期开启
src/utils/helper/treeHelper.ts
@@ -100,9 +100,9 @@ export function findPath&lt;T = any&gt;( @@ -100,9 +100,9 @@ export function findPath&lt;T = any&gt;(
100 100
101 export function findPathAll(tree: any, func: Fn, config: Partial<TreeHelperConfig> = {}) { 101 export function findPathAll(tree: any, func: Fn, config: Partial<TreeHelperConfig> = {}) {
102 config = getConfig(config); 102 config = getConfig(config);
103 - const path = []; 103 + const path: any[] = [];
104 const list = [...tree]; 104 const list = [...tree];
105 - const result = []; 105 + const result: any[] = [];
106 const visitedSet = new Set(), 106 const visitedSet = new Set(),
107 { children } = config; 107 { children } = config;
108 while (list.length) { 108 while (list.length) {
@@ -153,14 +153,14 @@ export function forEach&lt;T = any&gt;( @@ -153,14 +153,14 @@ export function forEach&lt;T = any&gt;(
153 } 153 }
154 154
155 /** 155 /**
156 - * @description: 提取tree指定结构 156 + * @description: Extract tree specified structure
157 */ 157 */
158 export function treeMap<T = any>(treeData: T[], opt: { children?: string; conversion: Fn }): T[] { 158 export function treeMap<T = any>(treeData: T[], opt: { children?: string; conversion: Fn }): T[] {
159 return treeData.map((item) => treeMapEach(item, opt)); 159 return treeData.map((item) => treeMapEach(item, opt));
160 } 160 }
161 161
162 /** 162 /**
163 - * @description: 提取tree指定结构 163 + * @description: Extract tree specified structure
164 */ 164 */
165 export function treeMapEach( 165 export function treeMapEach(
166 data: any, 166 data: any,
src/utils/http/axios/checkStatus.ts
@@ -15,7 +15,7 @@ export function checkStatus(status: number, msg: string): void { @@ -15,7 +15,7 @@ export function checkStatus(status: number, msg: string): void {
15 // Return to the current page after successful login. This step needs to be operated on the login page. 15 // Return to the current page after successful login. This step needs to be operated on the login page.
16 case 401: 16 case 401:
17 error(t('sys.api.errMsg401')); 17 error(t('sys.api.errMsg401'));
18 - userStore.loginOut(true); 18 + userStore.logout(true);
19 break; 19 break;
20 case 403: 20 case 403:
21 error(t('sys.api.errMsg403')); 21 error(t('sys.api.errMsg403'));
src/utils/index.ts
@@ -23,17 +23,11 @@ export function getPopupContainer(node?: HTMLElement): HTMLElement { @@ -23,17 +23,11 @@ export function getPopupContainer(node?: HTMLElement): HTMLElement {
23 */ 23 */
24 export function setObjToUrlParams(baseUrl: string, obj: any): string { 24 export function setObjToUrlParams(baseUrl: string, obj: any): string {
25 let parameters = ''; 25 let parameters = '';
26 - let url = '';  
27 for (const key in obj) { 26 for (const key in obj) {
28 parameters += key + '=' + encodeURIComponent(obj[key]) + '&'; 27 parameters += key + '=' + encodeURIComponent(obj[key]) + '&';
29 } 28 }
30 parameters = parameters.replace(/&$/, ''); 29 parameters = parameters.replace(/&$/, '');
31 - if (/\?$/.test(baseUrl)) {  
32 - url = baseUrl + parameters;  
33 - } else {  
34 - url = baseUrl.replace(/\/?$/, '?') + parameters;  
35 - }  
36 - return url; 30 + return /\?$/.test(baseUrl) ? baseUrl + parameters : baseUrl.replace(/\/?$/, '?') + parameters;
37 } 31 }
38 32
39 export function deepMerge<T = any>(src: any = {}, target: any = {}): T { 33 export function deepMerge<T = any>(src: any = {}, target: any = {}): T {
@@ -45,7 +39,7 @@ export function deepMerge&lt;T = any&gt;(src: any = {}, target: any = {}): T { @@ -45,7 +39,7 @@ export function deepMerge&lt;T = any&gt;(src: any = {}, target: any = {}): T {
45 } 39 }
46 40
47 /** 41 /**
48 - * @description: 根据数组中某个对象值去重 42 + * @description: Deduplication according to the value of an object in the array
49 */ 43 */
50 export function unique<T = any>(arr: T[], key: string): T[] { 44 export function unique<T = any>(arr: T[], key: string): T[] {
51 const map = new Map(); 45 const map = new Map();
@@ -56,7 +50,7 @@ export function unique&lt;T = any&gt;(arr: T[], key: string): T[] { @@ -56,7 +50,7 @@ export function unique&lt;T = any&gt;(arr: T[], key: string): T[] {
56 } 50 }
57 51
58 /** 52 /**
59 - * @description: es6数组去重复 53 + * @description: es6 array to repeat
60 */ 54 */
61 export function es6Unique<T>(arr: T[]): T[] { 55 export function es6Unique<T>(arr: T[]): T[] {
62 return Array.from(new Set(arr)); 56 return Array.from(new Set(arr));
src/views/sys/lock/LockPage.vue
@@ -115,7 +115,7 @@ @@ -115,7 +115,7 @@
115 } 115 }
116 116
117 function goLogin() { 117 function goLogin() {
118 - userStore.loginOut(true); 118 + userStore.logout(true);
119 lockStore.resetLockInfo(); 119 lockStore.resetLockInfo();
120 } 120 }
121 121
@@ -287,6 +287,7 @@ @@ -287,6 +287,7 @@
287 287
288 &-img { 288 &-img {
289 width: 70px; 289 width: 70px;
  290 + margin: 0 auto;
290 border-radius: 50%; 291 border-radius: 50%;
291 } 292 }
292 293
yarn.lock
@@ -9370,12 +9370,13 @@ vite-plugin-theme@^0.4.3: @@ -9370,12 +9370,13 @@ vite-plugin-theme@^0.4.3:
9370 es-module-lexer "^0.3.26" 9370 es-module-lexer "^0.3.26"
9371 tinycolor2 "^1.4.2" 9371 tinycolor2 "^1.4.2"
9372 9372
9373 -vite-plugin-windicss@0.2.2:  
9374 - version "0.2.2"  
9375 - resolved "https://registry.npmjs.org/vite-plugin-windicss/-/vite-plugin-windicss-0.2.2.tgz#2abf1533153f5dc214a9e1a06fb58274e5892c19"  
9376 - integrity sha512-P+iyrcuLjLfjiYP+bBisfKbg9bmeQMUBpjsTFJ9kWWX2fyqo968CHmS3euz+MzRcK5ZECccpOxx60ZXzc12VAw== 9373 +vite-plugin-windicss@0.3.3:
  9374 + version "0.3.3"
  9375 + resolved "https://registry.npmjs.org/vite-plugin-windicss/-/vite-plugin-windicss-0.3.3.tgz#9ff2fc485dd5cf1717cde6eed462fd9893ea9eab"
  9376 + integrity sha512-2gm0sTexkmvx9PR4NP1UESly8hX2souOruQztu1qghfw4M3tlUUvwneRpJG5HVJCKCctmAgYRcW4e04TE5R1fA==
9377 dependencies: 9377 dependencies:
9378 fast-glob "^3.2.5" 9378 fast-glob "^3.2.5"
  9379 + micromatch "^4.0.2"
9379 windicss "^2.1.11" 9380 windicss "^2.1.11"
9380 9381
9381 vite@2.0.1: 9382 vite@2.0.1: