Commit ed41e5082fd2e6109c2ad3ff77199d15ac14342a

Authored by vben
1 parent 0362ab26

perf(setting-drawer): perf setting-drawer

build/vite/plugin/html.ts 0 → 100644
  1 +import type { Plugin } from 'vite';
  2 +import ViteHtmlPlugin from 'vite-plugin-html';
  3 +import { isProdFn, isSiteMode, ViteEnv } from '../../utils';
  4 +
  5 +import { hmScript } from '../hm';
  6 +// @ts-ignore
  7 +import pkg from '../../../package.json';
  8 +import { GLOB_CONFIG_FILE_NAME } from '../../constant';
  9 +
  10 +export function setupHtmlPlugin(plugins: Plugin[], env: ViteEnv) {
  11 + const { VITE_GLOB_APP_TITLE, VITE_PUBLIC_PATH } = env;
  12 +
  13 + const htmlPlugin = ViteHtmlPlugin({
  14 + // html title
  15 + title: VITE_GLOB_APP_TITLE,
  16 + minify: isProdFn(),
  17 + options: {
  18 + // Package and insert additional configuration files
  19 + injectConfig: isProdFn()
  20 + ? `<script src='${VITE_PUBLIC_PATH || './'}${GLOB_CONFIG_FILE_NAME}?v=${
  21 + pkg.version
  22 + }-${new Date().getTime()}'></script>`
  23 + : '',
  24 + // Insert Baidu statistics code
  25 + hmScript: isSiteMode() ? hmScript : '',
  26 + title: VITE_GLOB_APP_TITLE,
  27 + },
  28 + });
  29 +
  30 + plugins.push(htmlPlugin);
  31 + return plugins;
  32 +}
build/vite/plugin/index.ts
1 import type { Plugin as VitePlugin } from 'vite'; 1 import type { Plugin as VitePlugin } from 'vite';
2 import type { Plugin as rollupPlugin } from 'rollup'; 2 import type { Plugin as rollupPlugin } from 'rollup';
3 3
4 -import { createMockServer } from 'vite-plugin-mock';  
5 -import { VitePWA } from 'vite-plugin-pwa';  
6 -import ViteHtmlPlugin from 'vite-plugin-html';  
7 import PurgeIcons from 'vite-plugin-purge-icons'; 4 import PurgeIcons from 'vite-plugin-purge-icons';
8 5
9 import visualizer from 'rollup-plugin-visualizer'; 6 import visualizer from 'rollup-plugin-visualizer';
10 import gzipPlugin from './gzip/index'; 7 import gzipPlugin from './gzip/index';
11 8
12 -import { hmScript } from '../hm';  
13 -  
14 // @ts-ignore 9 // @ts-ignore
15 import pkg from '../../../package.json'; 10 import pkg from '../../../package.json';
16 -import { isDevFn, isProdFn, isSiteMode, ViteEnv, isReportMode, isBuildGzip } from '../../utils';  
17 -import { GLOB_CONFIG_FILE_NAME } from '../../constant'; 11 +import { isProdFn, isSiteMode, ViteEnv, isReportMode, isBuildGzip } from '../../utils';
  12 +import { setupHtmlPlugin } from './html';
  13 +import { setupPwaPlugin } from './pwa';
  14 +import { setupMockPlugin } from './mock';
18 15
19 // gen vite plugins 16 // gen vite plugins
20 export function createVitePlugins(viteEnv: ViteEnv) { 17 export function createVitePlugins(viteEnv: ViteEnv) {
21 - const { VITE_USE_MOCK, VITE_GLOB_APP_TITLE, VITE_PUBLIC_PATH, VITE_USE_PWA } = viteEnv;  
22 -  
23 const vitePlugins: VitePlugin[] = []; 18 const vitePlugins: VitePlugin[] = [];
24 19
25 // vite-plugin-html 20 // vite-plugin-html
26 - vitePlugins.push(  
27 - ViteHtmlPlugin({  
28 - // html title  
29 - title: VITE_GLOB_APP_TITLE,  
30 - minify: isProdFn(),  
31 - options: {  
32 - // Package and insert additional configuration files  
33 - injectConfig: isProdFn()  
34 - ? `<script src='${VITE_PUBLIC_PATH || './'}${GLOB_CONFIG_FILE_NAME}?v=${  
35 - pkg.version  
36 - }-${new Date().getTime()}'></script>`  
37 - : '',  
38 - // Insert Baidu statistics code  
39 - hmScript: isSiteMode() ? hmScript : '',  
40 - title: VITE_GLOB_APP_TITLE,  
41 - },  
42 - })  
43 - ); 21 + setupHtmlPlugin(vitePlugins, viteEnv);
  22 + // vite-plugin-pwa
  23 + setupPwaPlugin(vitePlugins, viteEnv);
  24 + // vite-plugin-mock
  25 + setupMockPlugin(vitePlugins, viteEnv);
44 26
45 // vite-plugin-purge-icons 27 // vite-plugin-purge-icons
46 vitePlugins.push(PurgeIcons()); 28 vitePlugins.push(PurgeIcons());
47 29
48 - if (isProdFn() && VITE_USE_PWA) {  
49 - vitePlugins.push(  
50 - VitePWA({  
51 - manifest: {  
52 - name: 'Vben Admin',  
53 - short_name: 'vben_admin',  
54 - icons: [  
55 - {  
56 - src: './resource/img/pwa-192x192.png',  
57 - sizes: '192x192',  
58 - type: 'image/png',  
59 - },  
60 - {  
61 - src: './resource/img/pwa-512x512.png',  
62 - sizes: '512x512',  
63 - type: 'image/png',  
64 - },  
65 - ],  
66 - },  
67 - })  
68 - );  
69 - }  
70 -  
71 - // vite-plugin-mock  
72 - if (isDevFn() && VITE_USE_MOCK) {  
73 - // open mock  
74 - vitePlugins.push(  
75 - createMockServer({  
76 - ignore: /^\_/,  
77 - mockPath: 'mock',  
78 - showTime: true,  
79 - })  
80 - );  
81 - }  
82 return vitePlugins; 30 return vitePlugins;
83 } 31 }
84 32
@@ -86,17 +34,15 @@ export function createVitePlugins(viteEnv: ViteEnv) { @@ -86,17 +34,15 @@ export function createVitePlugins(viteEnv: ViteEnv) {
86 export function createRollupPlugin() { 34 export function createRollupPlugin() {
87 const rollupPlugins: rollupPlugin[] = []; 35 const rollupPlugins: rollupPlugin[] = [];
88 36
89 - if (isProdFn()) {  
90 - if (isReportMode()) {  
91 - // rollup-plugin-visualizer  
92 - rollupPlugins.push(  
93 - visualizer({ filename: './build/.cache/stats.html', open: true }) as Plugin  
94 - );  
95 - }  
96 - if (isBuildGzip() || isSiteMode()) {  
97 - // rollup-plugin-gizp  
98 - rollupPlugins.push(gzipPlugin());  
99 - } 37 + if (!isProdFn() && isReportMode()) {
  38 + // rollup-plugin-visualizer
  39 + rollupPlugins.push(visualizer({ filename: './build/.cache/stats.html', open: true }) as Plugin);
100 } 40 }
  41 +
  42 + if (!isProdFn() && (isBuildGzip() || isSiteMode())) {
  43 + // rollup-plugin-gizp
  44 + rollupPlugins.push(gzipPlugin());
  45 + }
  46 +
101 return rollupPlugins; 47 return rollupPlugins;
102 } 48 }
build/vite/plugin/mock.ts 0 → 100644
  1 +import { createMockServer } from 'vite-plugin-mock';
  2 +import type { Plugin } from 'vite';
  3 +import { isDevFn, ViteEnv } from '../../utils';
  4 +
  5 +export function setupMockPlugin(plugins: Plugin[], env: ViteEnv) {
  6 + const { VITE_USE_MOCK } = env;
  7 + const mockPlugin = createMockServer({
  8 + ignore: /^\_/,
  9 + mockPath: 'mock',
  10 + showTime: true,
  11 + });
  12 + if (isDevFn() && VITE_USE_MOCK) {
  13 + plugins.push(mockPlugin);
  14 + }
  15 + return plugins;
  16 +}
build/vite/plugin/pwa.ts 0 → 100644
  1 +import { VitePWA } from 'vite-plugin-pwa';
  2 +import type { Plugin } from 'vite';
  3 +import { isProdFn, ViteEnv } from '../../utils';
  4 +
  5 +export function setupPwaPlugin(plugins: Plugin[], env: ViteEnv) {
  6 + const { VITE_USE_PWA } = env;
  7 +
  8 + const pwaPlugin = VitePWA({
  9 + manifest: {
  10 + name: 'Vben Admin',
  11 + short_name: 'vben_admin',
  12 + icons: [
  13 + {
  14 + src: './resource/img/pwa-192x192.png',
  15 + sizes: '192x192',
  16 + type: 'image/png',
  17 + },
  18 + {
  19 + src: './resource/img/pwa-512x512.png',
  20 + sizes: '512x512',
  21 + type: 'image/png',
  22 + },
  23 + ],
  24 + },
  25 + });
  26 +
  27 + if (isProdFn() && VITE_USE_PWA) {
  28 + plugins.push(pwaPlugin);
  29 + }
  30 + return plugins;
  31 +}
src/components/Menu/src/BasicMenu.tsx
@@ -103,7 +103,7 @@ export default defineComponent({ @@ -103,7 +103,7 @@ export default defineComponent({
103 const isHorizontal = unref(getIsHorizontal) || getSplit.value; 103 const isHorizontal = unref(getIsHorizontal) || getSplit.value;
104 104
105 return { 105 return {
106 - height: isHorizontal ? `calc(100%)` : `calc(100% - ${props.showLogo ? '48px' : '0px'})`, 106 + height: isHorizontal ? '100%' : `calc(100% - ${props.showLogo ? '48px' : '0px'})`,
107 overflowY: isHorizontal ? 'hidden' : 'auto', 107 overflowY: isHorizontal ? 'hidden' : 'auto',
108 }; 108 };
109 } 109 }
src/hooks/web/useI18n.ts
@@ -25,9 +25,9 @@ export function useI18n(namespace?: string) { @@ -25,9 +25,9 @@ export function useI18n(namespace?: string) {
25 25
26 return { 26 return {
27 ...methods, 27 ...methods,
28 - t: (key: string, ...arg: Parameters<typeof t>) => { 28 + t: (key: string, ...arg: Partial<Parameters<typeof t>>) => {
29 if (!key) return ''; 29 if (!key) return '';
30 - return t(getKey(key), ...arg); 30 + return t(getKey(key), ...(arg as Parameters<typeof t>));
31 }, 31 },
32 }; 32 };
33 } 33 }
src/layouts/default/setting/SettingDrawer.tsx
1 -import type { ProjectConfig } from '/@/types/config';  
2 -  
3 -import defaultSetting from '/@/settings/projectSetting';  
4 -  
5 -import { defineComponent, computed, unref, FunctionalComponent } from 'vue'; 1 +import { defineComponent, computed, unref } from 'vue';
6 import { BasicDrawer } from '/@/components/Drawer/index'; 2 import { BasicDrawer } from '/@/components/Drawer/index';
7 -import { Divider, Switch, Tooltip, InputNumber, Select } from 'ant-design-vue';  
8 -import { Button } from '/@/components/Button';  
9 -import { CopyOutlined, RedoOutlined, CheckOutlined } from '@ant-design/icons-vue'; 3 +import { Divider } from 'ant-design-vue';
  4 +import {
  5 + TypePicker,
  6 + ThemePicker,
  7 + SettingFooter,
  8 + SwitchItem,
  9 + SelectItem,
  10 + InputNumberItem,
  11 +} from './components';
10 12
11 import { MenuTypeEnum } from '/@/enums/menuEnum'; 13 import { MenuTypeEnum } from '/@/enums/menuEnum';
12 -import { appStore } from '/@/store/modules/app';  
13 14
14 -import { useMessage } from '/@/hooks/web/useMessage';  
15 -import { useCopyToClipboard } from '/@/hooks/web/useCopyToClipboard';  
16 import { useRootSetting } from '/@/hooks/setting/useRootSetting'; 15 import { useRootSetting } from '/@/hooks/setting/useRootSetting';
17 import { useMenuSetting } from '/@/hooks/setting/useMenuSetting'; 16 import { useMenuSetting } from '/@/hooks/setting/useMenuSetting';
18 import { useHeaderSetting } from '/@/hooks/setting/useHeaderSetting'; 17 import { useHeaderSetting } from '/@/hooks/setting/useHeaderSetting';
@@ -20,8 +19,6 @@ import { useMultipleTabSetting } from &#39;/@/hooks/setting/useMultipleTabSetting&#39;; @@ -20,8 +19,6 @@ import { useMultipleTabSetting } from &#39;/@/hooks/setting/useMultipleTabSetting&#39;;
20 import { useTransitionSetting } from '/@/hooks/setting/useTransitionSetting'; 19 import { useTransitionSetting } from '/@/hooks/setting/useTransitionSetting';
21 import { useI18n } from '/@/hooks/web/useI18n'; 20 import { useI18n } from '/@/hooks/web/useI18n';
22 21
23 -import { updateColorWeak, updateGrayMode } from '/@/setup/theme';  
24 -  
25 import { baseHandler } from './handler'; 22 import { baseHandler } from './handler';
26 23
27 import { 24 import {
@@ -35,146 +32,8 @@ import { @@ -35,146 +32,8 @@ import {
35 32
36 import { HEADER_PRESET_BG_COLOR_LIST, SIDE_BAR_BG_COLOR_LIST } from '/@/settings/colorSetting'; 33 import { HEADER_PRESET_BG_COLOR_LIST, SIDE_BAR_BG_COLOR_LIST } from '/@/settings/colorSetting';
37 34
38 -interface SwitchOptions {  
39 - config?: DeepPartial<ProjectConfig>;  
40 - def?: any;  
41 - disabled?: boolean;  
42 - handler?: Fn;  
43 -}  
44 -  
45 -interface SelectConfig {  
46 - options?: LabelValueOptions;  
47 - def?: any;  
48 - disabled?: boolean;  
49 - handler?: Fn;  
50 -}  
51 -  
52 -interface ThemePickerProps {  
53 - colorList: string[];  
54 - handler: Fn;  
55 - def: string;  
56 -}  
57 -  
58 -const { createSuccessModal, createMessage } = useMessage();  
59 const { t } = useI18n(); 35 const { t } = useI18n();
60 36
61 -/**  
62 - * Menu type Picker comp  
63 - */  
64 -const MenuTypePicker: FunctionalComponent = () => {  
65 - const { getIsHorizontal, getMenuType } = useMenuSetting();  
66 - return (  
67 - <div class={`setting-drawer__siderbar`}>  
68 - {menuTypeList.map((item) => {  
69 - const { title, type: ItemType, mode, src } = item;  
70 - return (  
71 - <Tooltip title={title} placement="bottom" key={title}>  
72 - {{  
73 - default: () => (  
74 - <div  
75 - onClick={baseHandler.bind(null, HandlerEnum.CHANGE_LAYOUT, {  
76 - mode: mode,  
77 - type: ItemType,  
78 - split: unref(getIsHorizontal) ? false : undefined,  
79 - })}  
80 - >  
81 - <CheckOutlined  
82 - class={['check-icon', unref(getMenuType) === ItemType ? 'active' : '']}  
83 - />  
84 - <img src={src} />  
85 - </div>  
86 - ),  
87 - }}  
88 - </Tooltip>  
89 - );  
90 - })}  
91 - </div>  
92 - );  
93 -};  
94 -  
95 -const ThemePicker: FunctionalComponent<ThemePickerProps> = (props) => {  
96 - return (  
97 - <div class={`setting-drawer__theme-item`}>  
98 - {props.colorList.map((color) => {  
99 - return (  
100 - <span  
101 - onClick={() => props.handler?.(color)}  
102 - key={color}  
103 - class={[props.def === color ? 'active' : '']}  
104 - style={{  
105 - background: color,  
106 - }}  
107 - >  
108 - <CheckOutlined class="icon" />  
109 - </span>  
110 - );  
111 - })}  
112 - </div>  
113 - );  
114 -};  
115 -  
116 -/**  
117 - * FooterButton component  
118 - */  
119 -const FooterButton: FunctionalComponent = () => {  
120 - const { getRootSetting } = useRootSetting();  
121 - function handleCopy() {  
122 - const { isSuccessRef } = useCopyToClipboard(JSON.stringify(unref(getRootSetting), null, 2));  
123 - unref(isSuccessRef) &&  
124 - createSuccessModal({  
125 - title: t('layout.setting.operatingTitle'),  
126 - content: t('layout.setting.operatingContent'),  
127 - });  
128 - }  
129 - function handleResetSetting() {  
130 - try {  
131 - appStore.commitProjectConfigState(defaultSetting);  
132 - const { colorWeak, grayMode } = defaultSetting;  
133 - // updateTheme(themeColor);  
134 - updateColorWeak(colorWeak);  
135 - updateGrayMode(grayMode);  
136 - createMessage.success(t('layout.setting.resetSuccess'));  
137 - } catch (error) {  
138 - createMessage.error(error);  
139 - }  
140 - }  
141 -  
142 - function handleClearAndRedo() {  
143 - localStorage.clear();  
144 - appStore.resumeAllState();  
145 - location.reload();  
146 - }  
147 -  
148 - return (  
149 - <div class="setting-drawer__footer">  
150 - <Button type="primary" block onClick={handleCopy}>  
151 - {() => (  
152 - <>  
153 - <CopyOutlined class="mr-2" />  
154 - {t('layout.setting.copyBtn')}  
155 - </>  
156 - )}  
157 - </Button>  
158 - <Button block class="mt-2" onClick={handleResetSetting} color="warning">  
159 - {() => (  
160 - <>  
161 - <RedoOutlined class="mr-2" />  
162 - {t('layout.setting.resetBtn')}  
163 - </>  
164 - )}  
165 - </Button>  
166 - <Button block class="mt-2" onClick={handleClearAndRedo} color="error">  
167 - {() => (  
168 - <>  
169 - <RedoOutlined class="mr-2" />  
170 - {t('layout.setting.clearBtn')}  
171 - </>  
172 - )}  
173 - </Button>  
174 - </div>  
175 - );  
176 -};  
177 -  
178 export default defineComponent({ 37 export default defineComponent({
179 name: 'SettingDrawer', 38 name: 'SettingDrawer',
180 setup(_, { attrs }) { 39 setup(_, { attrs }) {
@@ -187,6 +46,7 @@ export default defineComponent({ @@ -187,6 +46,7 @@ export default defineComponent({
187 getFullContent, 46 getFullContent,
188 getColorWeak, 47 getColorWeak,
189 getGrayMode, 48 getGrayMode,
  49 + getLockTime,
190 } = useRootSetting(); 50 } = useRootSetting();
191 51
192 const { 52 const {
@@ -229,38 +89,44 @@ export default defineComponent({ @@ -229,38 +89,44 @@ export default defineComponent({
229 function renderSidebar() { 89 function renderSidebar() {
230 return ( 90 return (
231 <> 91 <>
232 - <MenuTypePicker />  
233 - {renderSwitchItem(t('layout.setting.splitMenu'), {  
234 - handler: (e) => {  
235 - baseHandler(HandlerEnum.MENU_SPLIT, e);  
236 - },  
237 - def: unref(getSplit),  
238 - disabled: !unref(getShowMenuRef) || unref(getMenuType) !== MenuTypeEnum.MIX,  
239 - })} 92 + <TypePicker
  93 + menuTypeList={menuTypeList}
  94 + handler={(item: typeof menuTypeList[0]) => {
  95 + baseHandler(HandlerEnum.CHANGE_LAYOUT, {
  96 + mode: item.mode,
  97 + type: item.type,
  98 + split: unref(getIsHorizontal) ? false : undefined,
  99 + });
  100 + }}
  101 + def={unref(getMenuType)}
  102 + />
  103 + <SwitchItem
  104 + title={t('layout.setting.splitMenu')}
  105 + event={HandlerEnum.MENU_SPLIT}
  106 + def={unref(getSplit)}
  107 + disabled={!unref(getShowMenuRef) || unref(getMenuType) !== MenuTypeEnum.MIX}
  108 + />
240 </> 109 </>
241 ); 110 );
242 } 111 }
243 112
244 - function renderTheme() { 113 + function renderHeaderTheme() {
245 return ( 114 return (
246 - <>  
247 - <Divider>{() => t('layout.setting.headerTheme')}</Divider>  
248 - <ThemePicker  
249 - colorList={HEADER_PRESET_BG_COLOR_LIST}  
250 - def={unref(getHeaderBgColor)}  
251 - handler={(e) => {  
252 - baseHandler(HandlerEnum.HEADER_THEME, e);  
253 - }}  
254 - />  
255 - <Divider>{() => t('layout.setting.sidebarTheme')}</Divider>  
256 - <ThemePicker  
257 - colorList={SIDE_BAR_BG_COLOR_LIST}  
258 - def={unref(getMenuBgColor)}  
259 - handler={(e) => {  
260 - baseHandler(HandlerEnum.MENU_THEME, e);  
261 - }}  
262 - />  
263 - </> 115 + <ThemePicker
  116 + colorList={HEADER_PRESET_BG_COLOR_LIST}
  117 + def={unref(getHeaderBgColor)}
  118 + event={HandlerEnum.HEADER_THEME}
  119 + />
  120 + );
  121 + }
  122 +
  123 + function renderSiderTheme() {
  124 + return (
  125 + <ThemePicker
  126 + colorList={SIDE_BAR_BG_COLOR_LIST}
  127 + def={unref(getMenuBgColor)}
  128 + event={HandlerEnum.MENU_THEME}
  129 + />
264 ); 130 );
265 } 131 }
266 132
@@ -268,264 +134,192 @@ export default defineComponent({ @@ -268,264 +134,192 @@ export default defineComponent({
268 * @description: 134 * @description:
269 */ 135 */
270 function renderFeatures() { 136 function renderFeatures() {
271 - return [  
272 - renderSwitchItem(t('layout.setting.menuDrag'), {  
273 - handler: (e) => {  
274 - baseHandler(HandlerEnum.MENU_HAS_DRAG, e);  
275 - },  
276 - def: unref(getCanDrag),  
277 - disabled: !unref(getShowMenuRef),  
278 - }),  
279 - renderSwitchItem(t('layout.setting.menuSearch'), {  
280 - handler: (e) => {  
281 - baseHandler(HandlerEnum.HEADER_SEARCH, e);  
282 - },  
283 - def: unref(getShowSearch),  
284 - disabled: !unref(getShowHeader),  
285 - }),  
286 - renderSwitchItem(t('layout.setting.menuAccordion'), {  
287 - handler: (e) => {  
288 - baseHandler(HandlerEnum.MENU_ACCORDION, e);  
289 - },  
290 - def: unref(getAccordion),  
291 - disabled: !unref(getShowMenuRef),  
292 - }),  
293 - renderSwitchItem(t('layout.setting.menuCollapse'), {  
294 - handler: (e) => {  
295 - baseHandler(HandlerEnum.MENU_COLLAPSED, e);  
296 - },  
297 - def: unref(getCollapsed),  
298 - disabled: !unref(getShowMenuRef),  
299 - }),  
300 - renderSwitchItem(t('layout.setting.collapseMenuDisplayName'), {  
301 - handler: (e) => {  
302 - baseHandler(HandlerEnum.MENU_COLLAPSED_SHOW_TITLE, e);  
303 - },  
304 - def: unref(getCollapsedShowTitle),  
305 - disabled: !unref(getShowMenuRef) || !unref(getCollapsed),  
306 - }),  
307 - renderSwitchItem(t('layout.setting.fixedHeader'), {  
308 - handler: (e) => {  
309 - baseHandler(HandlerEnum.HEADER_FIXED, e);  
310 - },  
311 - def: unref(getHeaderFixed),  
312 - disabled: !unref(getShowHeader),  
313 - }),  
314 - renderSwitchItem(t('layout.setting.fixedSideBar'), {  
315 - handler: (e) => {  
316 - baseHandler(HandlerEnum.MENU_FIXED, e);  
317 - },  
318 - def: unref(getMenuFixed),  
319 - disabled: !unref(getShowMenuRef),  
320 - }),  
321 - renderSelectItem(t('layout.setting.topMenuLayout'), {  
322 - handler: (e) => {  
323 - baseHandler(HandlerEnum.MENU_TOP_ALIGN, e);  
324 - },  
325 - def: unref(getTopMenuAlign),  
326 - options: topMenuAlignOptions,  
327 - disabled: !unref(getShowHeader) || (!unref(getIsTopMenu) && !unref(getSplit)),  
328 - }),  
329 - renderSelectItem(t('layout.setting.menuCollapseButton'), {  
330 - handler: (e) => {  
331 - baseHandler(HandlerEnum.MENU_TRIGGER, e);  
332 - },  
333 - disabled: !unref(getShowMenuRef),  
334 - def: unref(getTrigger),  
335 - options: menuTriggerOptions,  
336 - }),  
337 -  
338 - renderSelectItem(t('layout.setting.contentMode'), {  
339 - handler: (e) => {  
340 - baseHandler(HandlerEnum.CONTENT_MODE, e);  
341 - },  
342 - def: unref(getContentMode),  
343 - options: contentModeOptions,  
344 - }),  
345 - <div class={`setting-drawer__cell-item`}>  
346 - <span>{t('layout.setting.autoScreenLock')}</span>  
347 - <InputNumber  
348 - style="width:126px"  
349 - size="small" 137 + return (
  138 + <>
  139 + <SwitchItem
  140 + title={t('layout.setting.menuDrag')}
  141 + event={HandlerEnum.MENU_HAS_DRAG}
  142 + def={unref(getCanDrag)}
  143 + disabled={!unref(getShowMenuRef)}
  144 + />
  145 + <SwitchItem
  146 + title={t('layout.setting.menuSearch')}
  147 + event={HandlerEnum.HEADER_SEARCH}
  148 + def={unref(getShowSearch)}
  149 + disabled={!unref(getShowHeader)}
  150 + />
  151 + <SwitchItem
  152 + title={t('layout.setting.menuAccordion')}
  153 + event={HandlerEnum.MENU_ACCORDION}
  154 + def={unref(getAccordion)}
  155 + disabled={!unref(getShowMenuRef)}
  156 + />
  157 + <SwitchItem
  158 + title={t('layout.setting.menuCollapse')}
  159 + event={HandlerEnum.MENU_COLLAPSED}
  160 + def={unref(getCollapsed)}
  161 + disabled={!unref(getShowMenuRef)}
  162 + />
  163 + <SwitchItem
  164 + title={t('layout.setting.collapseMenuDisplayName')}
  165 + event={HandlerEnum.MENU_COLLAPSED_SHOW_TITLE}
  166 + def={unref(getCollapsedShowTitle)}
  167 + disabled={!unref(getShowMenuRef) || !unref(getCollapsed)}
  168 + />
  169 + <SwitchItem
  170 + title={t('layout.setting.fixedHeader')}
  171 + event={HandlerEnum.HEADER_FIXED}
  172 + def={unref(getHeaderFixed)}
  173 + disabled={!unref(getShowHeader)}
  174 + />
  175 + <SwitchItem
  176 + title={t('layout.setting.fixedSideBar')}
  177 + event={HandlerEnum.MENU_FIXED}
  178 + def={unref(getMenuFixed)}
  179 + disabled={!unref(getShowMenuRef)}
  180 + />
  181 + <SelectItem
  182 + title={t('layout.setting.topMenuLayout')}
  183 + event={HandlerEnum.MENU_TOP_ALIGN}
  184 + def={unref(getTopMenuAlign)}
  185 + options={topMenuAlignOptions}
  186 + disabled={!unref(getShowHeader) || (!unref(getIsTopMenu) && !unref(getSplit))}
  187 + />
  188 + <SelectItem
  189 + title={t('layout.setting.menuCollapseButton')}
  190 + event={HandlerEnum.MENU_TRIGGER}
  191 + def={unref(getTrigger)}
  192 + options={menuTriggerOptions}
  193 + disabled={!unref(getShowMenuRef)}
  194 + />
  195 + <SelectItem
  196 + title={t('layout.setting.contentMode')}
  197 + event={HandlerEnum.CONTENT_MODE}
  198 + def={unref(getContentMode)}
  199 + options={contentModeOptions}
  200 + />
  201 + <InputNumberItem
  202 + title={t('layout.setting.autoScreenLock')}
350 min={0} 203 min={0}
351 - onChange={(e: any) => {  
352 - baseHandler(HandlerEnum.LOCK_TIME, e);  
353 - }}  
354 - defaultValue={appStore.getProjectConfig.lockTime} 204 + event={HandlerEnum.LOCK_TIME}
  205 + defaultValue={unref(getLockTime)}
355 formatter={(value: string) => { 206 formatter={(value: string) => {
356 - if (parseInt(value) === 0) {  
357 - return `0(${t('layout.setting.notAutoScreenLock')})`;  
358 - }  
359 - return `${value}${t('layout.setting.minute')}`; 207 + return parseInt(value) === 0
  208 + ? `0(${t('layout.setting.notAutoScreenLock')})`
  209 + : `${value}${t('layout.setting.minute')}`;
360 }} 210 }}
361 /> 211 />
362 - </div>,  
363 - <div class={`setting-drawer__cell-item`}>  
364 - <span>{t('layout.setting.expandedMenuWidth')}</span>  
365 - <InputNumber  
366 - style="width:126px"  
367 - size="small" 212 + <InputNumberItem
  213 + title={t('layout.setting.expandedMenuWidth')}
368 max={600} 214 max={600}
369 min={100} 215 min={100}
370 step={10} 216 step={10}
  217 + event={HandlerEnum.MENU_WIDTH}
371 disabled={!unref(getShowMenuRef)} 218 disabled={!unref(getShowMenuRef)}
372 defaultValue={unref(getMenuWidth)} 219 defaultValue={unref(getMenuWidth)}
373 formatter={(value: string) => `${parseInt(value)}px`} 220 formatter={(value: string) => `${parseInt(value)}px`}
374 - onChange={(e: any) => {  
375 - baseHandler(HandlerEnum.MENU_WIDTH, e);  
376 - }}  
377 /> 221 />
378 - </div>,  
379 - ]; 222 + </>
  223 + );
380 } 224 }
381 225
382 function renderContent() { 226 function renderContent() {
383 - return [  
384 - renderSwitchItem(t('layout.setting.breadcrumb'), {  
385 - handler: (e) => {  
386 - baseHandler(HandlerEnum.SHOW_BREADCRUMB, e);  
387 - },  
388 - def: unref(getShowBreadCrumb),  
389 - disabled: !unref(getShowHeader),  
390 - }),  
391 - renderSwitchItem(t('layout.setting.breadcrumbIcon'), {  
392 - handler: (e) => {  
393 - baseHandler(HandlerEnum.SHOW_BREADCRUMB_ICON, e);  
394 - },  
395 - def: unref(getShowBreadCrumbIcon),  
396 - disabled: !unref(getShowHeader),  
397 - }),  
398 - renderSwitchItem(t('layout.setting.tabs'), {  
399 - handler: (e) => {  
400 - baseHandler(HandlerEnum.TABS_SHOW, e);  
401 - },  
402 - def: unref(getShowMultipleTab),  
403 - }),  
404 - renderSwitchItem(t('layout.setting.tabsQuickBtn'), {  
405 - handler: (e) => {  
406 - baseHandler(HandlerEnum.TABS_SHOW_QUICK, e);  
407 - },  
408 - def: unref(getShowQuick),  
409 - disabled: !unref(getShowMultipleTab),  
410 - }),  
411 -  
412 - renderSwitchItem(t('layout.setting.sidebar'), {  
413 - handler: (e) => {  
414 - baseHandler(HandlerEnum.MENU_SHOW_SIDEBAR, e);  
415 - },  
416 - def: unref(getShowMenu),  
417 - disabled: unref(getIsHorizontal),  
418 - }),  
419 - renderSwitchItem(t('layout.setting.header'), {  
420 - handler: (e) => {  
421 - baseHandler(HandlerEnum.HEADER_SHOW, e);  
422 - },  
423 - def: unref(getShowHeader),  
424 - }),  
425 - renderSwitchItem('Logo', {  
426 - handler: (e) => {  
427 - baseHandler(HandlerEnum.SHOW_LOGO, e);  
428 - },  
429 - def: unref(getShowLogo),  
430 - }),  
431 - renderSwitchItem(t('layout.setting.footer'), {  
432 - handler: (e) => {  
433 - baseHandler(HandlerEnum.SHOW_FOOTER, e);  
434 - },  
435 - def: unref(getShowFooter),  
436 - }),  
437 - renderSwitchItem(t('layout.setting.fullContent'), {  
438 - handler: (e) => {  
439 - baseHandler(HandlerEnum.FULL_CONTENT, e);  
440 - },  
441 - def: unref(getFullContent),  
442 - }),  
443 - renderSwitchItem(t('layout.setting.grayMode'), {  
444 - handler: (e) => {  
445 - baseHandler(HandlerEnum.GRAY_MODE, e);  
446 - },  
447 - def: unref(getGrayMode),  
448 - }),  
449 - renderSwitchItem(t('layout.setting.colorWeak'), {  
450 - handler: (e) => {  
451 - baseHandler(HandlerEnum.COLOR_WEAK, e);  
452 - },  
453 - def: unref(getColorWeak),  
454 - }),  
455 - ];  
456 - }  
457 -  
458 - function renderTransition() {  
459 return ( 227 return (
460 <> 228 <>
461 - {renderSwitchItem(t('layout.setting.progress'), {  
462 - handler: (e) => {  
463 - baseHandler(HandlerEnum.OPEN_PROGRESS, e);  
464 - },  
465 - def: unref(getOpenNProgress),  
466 - })}  
467 - {renderSwitchItem(t('layout.setting.switchLoading'), {  
468 - handler: (e) => {  
469 - baseHandler(HandlerEnum.OPEN_PAGE_LOADING, e);  
470 - },  
471 - def: unref(getOpenPageLoading),  
472 - })} 229 + <SwitchItem
  230 + title={t('layout.setting.breadcrumb')}
  231 + event={HandlerEnum.SHOW_BREADCRUMB}
  232 + def={unref(getShowBreadCrumb)}
  233 + disabled={!unref(getShowHeader)}
  234 + />
  235 +
  236 + <SwitchItem
  237 + title={t('layout.setting.breadcrumbIcon')}
  238 + event={HandlerEnum.SHOW_BREADCRUMB_ICON}
  239 + def={unref(getShowBreadCrumbIcon)}
  240 + disabled={!unref(getShowHeader)}
  241 + />
  242 +
  243 + <SwitchItem
  244 + title={t('layout.setting.tabs')}
  245 + event={HandlerEnum.TABS_SHOW}
  246 + def={unref(getShowMultipleTab)}
  247 + />
  248 +
  249 + <SwitchItem
  250 + title={t('layout.setting.tabsQuickBtn')}
  251 + event={HandlerEnum.TABS_SHOW_QUICK}
  252 + def={unref(getShowQuick)}
  253 + disabled={!unref(getShowMultipleTab)}
  254 + />
  255 +
  256 + <SwitchItem
  257 + title={t('layout.setting.sidebar')}
  258 + event={HandlerEnum.MENU_SHOW_SIDEBAR}
  259 + def={unref(getShowMenu)}
  260 + disabled={unref(getIsHorizontal)}
  261 + />
  262 +
  263 + <SwitchItem
  264 + title={t('layout.setting.header')}
  265 + event={HandlerEnum.HEADER_SHOW}
  266 + def={unref(getShowHeader)}
  267 + />
  268 + <SwitchItem title="Logo" event={HandlerEnum.SHOW_LOGO} def={unref(getShowLogo)} />
  269 + <SwitchItem
  270 + title={t('layout.setting.footer')}
  271 + event={HandlerEnum.SHOW_FOOTER}
  272 + def={unref(getShowFooter)}
  273 + />
  274 + <SwitchItem
  275 + title={t('layout.setting.fullContent')}
  276 + event={HandlerEnum.FULL_CONTENT}
  277 + def={unref(getFullContent)}
  278 + />
473 279
474 - {renderSwitchItem(t('layout.setting.switchAnimation'), {  
475 - handler: (e) => {  
476 - baseHandler(HandlerEnum.OPEN_ROUTE_TRANSITION, e);  
477 - },  
478 - def: unref(getEnableTransition),  
479 - })} 280 + <SwitchItem
  281 + title={t('layout.setting.grayMode')}
  282 + event={HandlerEnum.GRAY_MODE}
  283 + def={unref(getGrayMode)}
  284 + />
480 285
481 - {renderSelectItem(t('layout.setting.animationType'), {  
482 - handler: (e) => {  
483 - baseHandler(HandlerEnum.ROUTER_TRANSITION, e);  
484 - },  
485 - def: unref(getBasicTransition),  
486 - options: routerTransitionOptions,  
487 - disabled: !unref(getEnableTransition),  
488 - })} 286 + <SwitchItem
  287 + title={t('layout.setting.colorWeak')}
  288 + event={HandlerEnum.COLOR_WEAK}
  289 + def={unref(getColorWeak)}
  290 + />
489 </> 291 </>
490 ); 292 );
491 } 293 }
492 294
493 - function renderSelectItem(text: string, config?: SelectConfig) {  
494 - const { handler, def, disabled = false, options } = config || {};  
495 - const opt = def ? { value: def, defaultValue: def } : {}; 295 + function renderTransition() {
496 return ( 296 return (
497 - <div class={`setting-drawer__cell-item`}>  
498 - <span>{text}</span>  
499 - <Select  
500 - {...opt}  
501 - disabled={disabled}  
502 - size="small"  
503 - style={{ width: '126px' }}  
504 - onChange={(e) => {  
505 - handler && handler(e);  
506 - }}  
507 - options={options} 297 + <>
  298 + <SwitchItem
  299 + title={t('layout.setting.progress')}
  300 + event={HandlerEnum.OPEN_PROGRESS}
  301 + def={unref(getOpenNProgress)}
  302 + />
  303 + <SwitchItem
  304 + title={t('layout.setting.switchLoading')}
  305 + event={HandlerEnum.OPEN_PAGE_LOADING}
  306 + def={unref(getOpenPageLoading)}
508 /> 307 />
509 - </div>  
510 - );  
511 - }  
512 308
513 - function renderSwitchItem(text: string, options?: SwitchOptions) {  
514 - const { handler, def, disabled = false } = options || {};  
515 - const opt = def ? { checked: def } : {};  
516 - return (  
517 - <div class={`setting-drawer__cell-item`}>  
518 - <span>{text}</span>  
519 - <Switch  
520 - {...opt}  
521 - disabled={disabled}  
522 - onChange={(e: any) => {  
523 - handler && handler(e);  
524 - }}  
525 - checkedChildren={t('layout.setting.on')}  
526 - unCheckedChildren={t('layout.setting.off')} 309 + <SwitchItem
  310 + title={t('layout.setting.switchAnimation')}
  311 + event={HandlerEnum.OPEN_ROUTE_TRANSITION}
  312 + def={unref(getEnableTransition)}
527 /> 313 />
528 - </div> 314 +
  315 + <SelectItem
  316 + title={t('layout.setting.animationType')}
  317 + event={HandlerEnum.ROUTER_TRANSITION}
  318 + def={unref(getBasicTransition)}
  319 + options={routerTransitionOptions}
  320 + disabled={!unref(getEnableTransition)}
  321 + />
  322 + </>
529 ); 323 );
530 } 324 }
531 325
@@ -541,7 +335,10 @@ export default defineComponent({ @@ -541,7 +335,10 @@ export default defineComponent({
541 <> 335 <>
542 <Divider>{() => t('layout.setting.navMode')}</Divider> 336 <Divider>{() => t('layout.setting.navMode')}</Divider>
543 {renderSidebar()} 337 {renderSidebar()}
544 - {renderTheme()} 338 + <Divider>{() => t('layout.setting.headerTheme')}</Divider>
  339 + {renderHeaderTheme()}
  340 + <Divider>{() => t('layout.setting.sidebarTheme')}</Divider>
  341 + {renderSiderTheme()}
545 <Divider>{() => t('layout.setting.interfaceFunction')}</Divider> 342 <Divider>{() => t('layout.setting.interfaceFunction')}</Divider>
546 {renderFeatures()} 343 {renderFeatures()}
547 <Divider>{() => t('layout.setting.interfaceDisplay')}</Divider> 344 <Divider>{() => t('layout.setting.interfaceDisplay')}</Divider>
@@ -549,7 +346,7 @@ export default defineComponent({ @@ -549,7 +346,7 @@ export default defineComponent({
549 <Divider>{() => t('layout.setting.animation')}</Divider> 346 <Divider>{() => t('layout.setting.animation')}</Divider>
550 {renderTransition()} 347 {renderTransition()}
551 <Divider /> 348 <Divider />
552 - <FooterButton /> 349 + <SettingFooter />
553 </> 350 </>
554 ), 351 ),
555 }} 352 }}
src/layouts/default/setting/components/InputNumberItem.vue 0 → 100644
  1 +<template>
  2 + <div :class="prefixCls">
  3 + <span> {{ title }}</span>
  4 + <InputNumber
  5 + v-bind="$attrs"
  6 + size="small"
  7 + :class="`${prefixCls}-input-number`"
  8 + @change="handleChange"
  9 + />
  10 + </div>
  11 +</template>
  12 +<script lang="ts">
  13 + import { defineComponent, PropType } from 'vue';
  14 +
  15 + import { InputNumber } from 'ant-design-vue';
  16 + import { useDesign } from '/@/hooks/web/useDesign';
  17 + import { baseHandler } from '../handler';
  18 + import { HandlerEnum } from '../enum';
  19 +
  20 + export default defineComponent({
  21 + name: 'InputNumberItem',
  22 + components: { InputNumber },
  23 + props: {
  24 + event: {
  25 + type: Number as PropType<HandlerEnum>,
  26 + default: () => {},
  27 + },
  28 + title: {
  29 + type: String,
  30 + },
  31 + },
  32 + setup(props) {
  33 + const { prefixCls } = useDesign('setting-input-number-item');
  34 +
  35 + function handleChange(e: ChangeEvent) {
  36 + props.event && baseHandler(props.event, e);
  37 + }
  38 + return {
  39 + prefixCls,
  40 + handleChange,
  41 + };
  42 + },
  43 + });
  44 +</script>
  45 +<style lang="less" scoped>
  46 + @import (reference) '../../../../design/index.less';
  47 + @prefix-cls: ~'@{namespace}-setting-input-number-item';
  48 +
  49 + .@{prefix-cls} {
  50 + display: flex;
  51 + justify-content: space-between;
  52 + margin: 16px 0;
  53 +
  54 + &-input-number {
  55 + width: 126px;
  56 + }
  57 + }
  58 +</style>
src/layouts/default/setting/components/SelectItem.vue 0 → 100644
  1 +<template>
  2 + <div :class="prefixCls">
  3 + <span> {{ title }}</span>
  4 + <Select
  5 + v-bind="getBindValue"
  6 + :class="`${prefixCls}-select`"
  7 + @change="handleChange"
  8 + :disabled="disabled"
  9 + size="small"
  10 + :options="options"
  11 + />
  12 + </div>
  13 +</template>
  14 +<script lang="ts">
  15 + import { defineComponent, PropType, computed } from 'vue';
  16 +
  17 + import { Select } from 'ant-design-vue';
  18 + import { useDesign } from '/@/hooks/web/useDesign';
  19 + import { baseHandler } from '../handler';
  20 + import { HandlerEnum } from '../enum';
  21 +
  22 + export default defineComponent({
  23 + name: 'SelectItem',
  24 + components: { Select },
  25 + props: {
  26 + event: {
  27 + type: Number as PropType<HandlerEnum>,
  28 + default: () => {},
  29 + },
  30 + disabled: {
  31 + type: Boolean,
  32 + },
  33 + title: {
  34 + type: String,
  35 + },
  36 + def: {
  37 + type: [String, Number] as PropType<string | number>,
  38 + },
  39 + initValue: {
  40 + type: [String, Number] as PropType<string | number>,
  41 + },
  42 + options: {
  43 + type: Array as PropType<LabelValueOptions>,
  44 + default: [],
  45 + },
  46 + },
  47 + setup(props) {
  48 + const { prefixCls } = useDesign('setting-select-item');
  49 + const getBindValue = computed(() => {
  50 + return props.def ? { value: props.def, defaultValue: props.initValue || props.def } : {};
  51 + });
  52 +
  53 + function handleChange(e: ChangeEvent) {
  54 + props.event && baseHandler(props.event, e);
  55 + }
  56 + return {
  57 + prefixCls,
  58 + handleChange,
  59 + getBindValue,
  60 + };
  61 + },
  62 + });
  63 +</script>
  64 +<style lang="less" scoped>
  65 + @import (reference) '../../../../design/index.less';
  66 + @prefix-cls: ~'@{namespace}-setting-select-item';
  67 +
  68 + .@{prefix-cls} {
  69 + display: flex;
  70 + justify-content: space-between;
  71 + margin: 16px 0;
  72 +
  73 + &-select {
  74 + width: 126px;
  75 + }
  76 + }
  77 +</style>
src/layouts/default/setting/components/SettingFooter.vue 0 → 100644
  1 +<template>
  2 + <div :class="prefixCls">
  3 + <a-button type="primary" block @click="handleCopy">
  4 + <CopyOutlined class="mr-2" />
  5 + {{ t('layout.setting.copyBtn') }}
  6 + </a-button>
  7 +
  8 + <a-button color="warning" block @click="handleResetSetting" class="my-3">
  9 + <RedoOutlined class="mr-2" />
  10 + {{ t('layout.setting.resetBtn') }}
  11 + </a-button>
  12 +
  13 + <a-button color="error" block @click="handleClearAndRedo">
  14 + <RedoOutlined class="mr-2" />
  15 + {{ t('layout.setting.clearBtn') }}
  16 + </a-button>
  17 + </div>
  18 +</template>
  19 +<script lang="ts">
  20 + import { defineComponent, unref } from 'vue';
  21 +
  22 + import { useDesign } from '/@/hooks/web/useDesign';
  23 + import { useI18n } from '/@/hooks/web/useI18n';
  24 + import { CopyOutlined, RedoOutlined } from '@ant-design/icons-vue';
  25 + import { appStore } from '/@/store/modules/app';
  26 + import defaultSetting from '/@/settings/projectSetting';
  27 + import { useMessage } from '/@/hooks/web/useMessage';
  28 + import { useCopyToClipboard } from '/@/hooks/web/useCopyToClipboard';
  29 + import { useRootSetting } from '/@/hooks/setting/useRootSetting';
  30 + import { updateColorWeak, updateGrayMode } from '/@/setup/theme';
  31 +
  32 + export default defineComponent({
  33 + name: 'SettingFooter',
  34 + components: { CopyOutlined, RedoOutlined },
  35 + setup() {
  36 + const { getRootSetting } = useRootSetting();
  37 + const { prefixCls } = useDesign('setting-footer');
  38 + const { t } = useI18n();
  39 + const { createSuccessModal, createMessage } = useMessage();
  40 +
  41 + function handleCopy() {
  42 + const { isSuccessRef } = useCopyToClipboard(JSON.stringify(unref(getRootSetting), null, 2));
  43 + unref(isSuccessRef) &&
  44 + createSuccessModal({
  45 + title: t('layout.setting.operatingTitle'),
  46 + content: t('layout.setting.operatingContent'),
  47 + });
  48 + }
  49 + function handleResetSetting() {
  50 + try {
  51 + appStore.commitProjectConfigState(defaultSetting);
  52 + const { colorWeak, grayMode } = defaultSetting;
  53 + // updateTheme(themeColor);
  54 + updateColorWeak(colorWeak);
  55 + updateGrayMode(grayMode);
  56 + createMessage.success(t('layout.setting.resetSuccess'));
  57 + } catch (error) {
  58 + createMessage.error(error);
  59 + }
  60 + }
  61 +
  62 + function handleClearAndRedo() {
  63 + localStorage.clear();
  64 + appStore.resumeAllState();
  65 + location.reload();
  66 + }
  67 + return {
  68 + prefixCls,
  69 + t,
  70 + handleCopy,
  71 + handleResetSetting,
  72 + handleClearAndRedo,
  73 + };
  74 + },
  75 + });
  76 +</script>
  77 +<style lang="less" scoped>
  78 + @import (reference) '../../../../design/index.less';
  79 + @prefix-cls: ~'@{namespace}-setting-footer';
  80 +
  81 + .@{prefix-cls} {
  82 + display: flex;
  83 + flex-direction: column;
  84 + align-items: center;
  85 + }
  86 +</style>
src/layouts/default/setting/components/SwitchItem.vue 0 → 100644
  1 +<template>
  2 + <div :class="prefixCls">
  3 + <span> {{ title }}</span>
  4 + <Switch
  5 + v-bind="getBindValue"
  6 + @change="handleChange"
  7 + :disabled="disabled"
  8 + :checkedChildren="t('layout.setting.on')"
  9 + :unCheckedChildren="t('layout.setting.off')"
  10 + />
  11 + </div>
  12 +</template>
  13 +<script lang="ts">
  14 + import { defineComponent, PropType, computed } from 'vue';
  15 +
  16 + import { Switch } from 'ant-design-vue';
  17 + import { useDesign } from '/@/hooks/web/useDesign';
  18 + import { useI18n } from '/@/hooks/web/useI18n';
  19 + import { baseHandler } from '../handler';
  20 + import { HandlerEnum } from '../enum';
  21 +
  22 + export default defineComponent({
  23 + name: 'SwitchItem',
  24 + components: { Switch },
  25 + props: {
  26 + event: {
  27 + type: Number as PropType<HandlerEnum>,
  28 + default: () => {},
  29 + },
  30 + disabled: {
  31 + type: Boolean,
  32 + },
  33 + title: {
  34 + type: String,
  35 + },
  36 + def: {
  37 + type: Boolean,
  38 + },
  39 + },
  40 + setup(props) {
  41 + const { prefixCls } = useDesign('setting-switch-item');
  42 + const { t } = useI18n();
  43 +
  44 + const getBindValue = computed(() => {
  45 + return props.def ? { checked: props.def } : {};
  46 + });
  47 + function handleChange(e: ChangeEvent) {
  48 + props.event && baseHandler(props.event, e);
  49 + }
  50 + return {
  51 + prefixCls,
  52 + t,
  53 + handleChange,
  54 + getBindValue,
  55 + };
  56 + },
  57 + });
  58 +</script>
  59 +<style lang="less" scoped>
  60 + @import (reference) '../../../../design/index.less';
  61 + @prefix-cls: ~'@{namespace}-setting-switch-item';
  62 +
  63 + .@{prefix-cls} {
  64 + display: flex;
  65 + justify-content: space-between;
  66 + margin: 16px 0;
  67 + }
  68 +</style>
src/layouts/default/setting/components/ThemePicker.vue 0 → 100644
  1 +<template>
  2 + <div :class="prefixCls">
  3 + <template v-for="color in colorList || []" :key="color">
  4 + <span
  5 + @click="handleClick(color)"
  6 + :class="[
  7 + `${prefixCls}__item`,
  8 + {
  9 + [`${prefixCls}__item--active`]: def === color,
  10 + },
  11 + ]"
  12 + :style="{ background: color }"
  13 + >
  14 + <CheckOutlined />
  15 + </span>
  16 + </template>
  17 + </div>
  18 +</template>
  19 +<script lang="ts">
  20 + import { defineComponent, PropType } from 'vue';
  21 + import { CheckOutlined } from '@ant-design/icons-vue';
  22 +
  23 + import { useDesign } from '/@/hooks/web/useDesign';
  24 +
  25 + import { baseHandler } from '../handler';
  26 + import { HandlerEnum } from '../enum';
  27 +
  28 + export default defineComponent({
  29 + name: 'ThemePicker',
  30 + components: { CheckOutlined },
  31 + props: {
  32 + colorList: {
  33 + type: Array as PropType<string[]>,
  34 + defualt: [],
  35 + },
  36 + event: {
  37 + type: Number as PropType<HandlerEnum>,
  38 + default: () => {},
  39 + },
  40 + def: {
  41 + type: String,
  42 + },
  43 + },
  44 + setup(props) {
  45 + const { prefixCls } = useDesign('setting-theme-picker');
  46 +
  47 + function handleClick(color: string) {
  48 + props.event && baseHandler(props.event, color);
  49 + }
  50 + return {
  51 + prefixCls,
  52 + handleClick,
  53 + };
  54 + },
  55 + });
  56 +</script>
  57 +<style lang="less">
  58 + @import (reference) '../../../../design/index.less';
  59 + @prefix-cls: ~'@{namespace}-setting-theme-picker';
  60 +
  61 + .@{prefix-cls} {
  62 + display: flex;
  63 + flex-wrap: wrap;
  64 + margin: 16px 0;
  65 + justify-content: space-around;
  66 +
  67 + &__item {
  68 + width: 20px;
  69 + height: 20px;
  70 + cursor: pointer;
  71 + border: 1px solid #ddd;
  72 + border-radius: 2px;
  73 +
  74 + svg {
  75 + display: none;
  76 + }
  77 +
  78 + &--active {
  79 + border: 1px solid lighten(@primary-color, 10%);
  80 +
  81 + svg {
  82 + display: inline-block;
  83 + margin: 0 0 3px 3px;
  84 + font-size: 12px;
  85 + fill: @white !important;
  86 + }
  87 + }
  88 + }
  89 + }
  90 +</style>
src/layouts/default/setting/components/TypePicker.vue 0 → 100644
  1 +<template>
  2 + <div :class="prefixCls">
  3 + <template v-for="item in menuTypeList || []" :key="item.title">
  4 + <Tooltip :title="item.title" placement="bottom">
  5 + <div
  6 + @click="handler(item)"
  7 + :class="[
  8 + `${prefixCls}__item`,
  9 + {
  10 + [`${prefixCls}__item--active`]: def === item.type,
  11 + },
  12 + ]"
  13 + >
  14 + <img :src="item.src" />
  15 + </div>
  16 + </Tooltip>
  17 + </template>
  18 + </div>
  19 +</template>
  20 +<script lang="ts">
  21 + import { defineComponent, PropType } from 'vue';
  22 +
  23 + import { Tooltip } from 'ant-design-vue';
  24 + import { useDesign } from '/@/hooks/web/useDesign';
  25 +
  26 + import { menuTypeList } from '../enum';
  27 + export default defineComponent({
  28 + name: 'MenuTypePicker',
  29 + components: { Tooltip },
  30 + props: {
  31 + menuTypeList: {
  32 + type: Array as PropType<typeof menuTypeList>,
  33 + defualt: [],
  34 + },
  35 + handler: {
  36 + type: Function as PropType<Fn>,
  37 + default: () => {},
  38 + },
  39 + def: {
  40 + type: String,
  41 + },
  42 + },
  43 + setup() {
  44 + const { prefixCls } = useDesign('setting-menu-type-picker');
  45 +
  46 + return {
  47 + prefixCls,
  48 + };
  49 + },
  50 + });
  51 +</script>
  52 +<style lang="less" scoped>
  53 + @import (reference) '../../../../design/index.less';
  54 + @prefix-cls: ~'@{namespace}-setting-menu-type-picker';
  55 +
  56 + .@{prefix-cls} {
  57 + display: flex;
  58 +
  59 + &__item {
  60 + position: relative;
  61 + width: 70px;
  62 + height: 50px;
  63 + margin: 0 20px 20px 0;
  64 + cursor: pointer;
  65 + border-radius: 6px;
  66 +
  67 + &::after {
  68 + position: absolute;
  69 + top: 50%;
  70 + left: 50%;
  71 + width: 0;
  72 + height: 0;
  73 + content: '';
  74 + opacity: 0;
  75 + transition: all 0.3s;
  76 + }
  77 +
  78 + &:hover,
  79 + &--active {
  80 + &::after {
  81 + top: -8px;
  82 + left: -4px;
  83 + width: 80px;
  84 + height: 64px;
  85 + border: 2px solid @primary-color;
  86 + border-radius: 6px;
  87 + opacity: 1;
  88 + }
  89 + }
  90 + }
  91 +
  92 + img {
  93 + width: 100%;
  94 + height: 100%;
  95 + cursor: pointer;
  96 + }
  97 + }
  98 +</style>
src/layouts/default/setting/components/index.ts 0 → 100644
  1 +import { createAsyncComponent } from '/@/utils/factory/createAsyncComponent';
  2 +
  3 +export const TypePicker = createAsyncComponent(() => import('./TypePicker.vue'));
  4 +export const ThemePicker = createAsyncComponent(() => import('./ThemePicker.vue'));
  5 +export const SettingFooter = createAsyncComponent(() => import('./SettingFooter.vue'));
  6 +export const SwitchItem = createAsyncComponent(() => import('./SwitchItem.vue'));
  7 +export const SelectItem = createAsyncComponent(() => import('./SelectItem.vue'));
  8 +export const InputNumberItem = createAsyncComponent(() => import('./InputNumberItem.vue'));
src/layouts/default/setting/index.less deleted 100644 → 0
1 -.setting-drawer {  
2 - .ant-drawer-body {  
3 - padding-top: 0;  
4 - background: @white;  
5 - }  
6 -  
7 - &__footer {  
8 - display: flex;  
9 - flex-direction: column;  
10 - align-items: center;  
11 - }  
12 -  
13 - &__cell-item {  
14 - display: flex;  
15 - justify-content: space-between;  
16 - margin: 16px 0;  
17 - }  
18 -  
19 - &__theme-item {  
20 - display: flex;  
21 - flex-wrap: wrap;  
22 - margin: 16px 0;  
23 - justify-content: space-around;  
24 -  
25 - > span {  
26 - width: 20px;  
27 - height: 20px;  
28 - cursor: pointer;  
29 - border: 1px solid #ddd;  
30 - border-radius: 2px;  
31 -  
32 - svg {  
33 - display: none;  
34 - }  
35 -  
36 - &.active {  
37 - border: 1px solid lighten(@primary-color, 10%);  
38 -  
39 - svg {  
40 - display: inline-block;  
41 - margin: 0 0 3px 3px;  
42 - font-size: 12px;  
43 - fill: @white;  
44 - }  
45 - }  
46 - }  
47 - }  
48 -  
49 - &__siderbar {  
50 - display: flex;  
51 -  
52 - > div {  
53 - position: relative;  
54 -  
55 - .check-icon {  
56 - position: absolute;  
57 - top: 40%;  
58 - left: 40%;  
59 - display: none;  
60 - color: @primary-color;  
61 -  
62 - &.active {  
63 - display: inline-block;  
64 - }  
65 - }  
66 - }  
67 -  
68 - img {  
69 - margin-right: 10px;  
70 - cursor: pointer;  
71 - }  
72 - }  
73 -}  
src/layouts/default/setting/index.vue
1 <template> 1 <template>
2 - <div @click="openDrawer" class="setting-button"> 2 + <div @click="openDrawer" :class="prefixCls">
3 <SettingOutlined /> 3 <SettingOutlined />
4 <SettingDrawer @register="register" /> 4 <SettingDrawer @register="register" />
5 </div> 5 </div>
@@ -10,13 +10,17 @@ @@ -10,13 +10,17 @@
10 import SettingDrawer from './SettingDrawer'; 10 import SettingDrawer from './SettingDrawer';
11 11
12 import { useDrawer } from '/@/components/Drawer'; 12 import { useDrawer } from '/@/components/Drawer';
  13 + import { useDesign } from '/@/hooks/web/useDesign';
13 14
14 export default defineComponent({ 15 export default defineComponent({
15 name: 'SettingBtn', 16 name: 'SettingBtn',
16 components: { SettingOutlined, SettingDrawer }, 17 components: { SettingOutlined, SettingDrawer },
17 setup() { 18 setup() {
18 const [register, { openDrawer }] = useDrawer(); 19 const [register, { openDrawer }] = useDrawer();
  20 +
  21 + const { prefixCls } = useDesign('setting-button');
19 return { 22 return {
  23 + prefixCls,
20 register, 24 register,
21 openDrawer, 25 openDrawer,
22 }; 26 };
@@ -25,9 +29,9 @@ @@ -25,9 +29,9 @@
25 </script> 29 </script>
26 <style lang="less"> 30 <style lang="less">
27 @import (reference) '../../../design/index.less'; 31 @import (reference) '../../../design/index.less';
28 - @import './index.less'; 32 + @prefix-cls: ~'@{namespace}-setting-button';
29 33
30 - .setting-button { 34 + .@{prefix-cls} {
31 position: absolute; 35 position: absolute;
32 top: 45%; 36 top: 45%;
33 right: 0; 37 right: 0;