Commit ed41e5082fd2e6109c2ad3ff77199d15ac14342a
1 parent
0362ab26
perf(setting-drawer): perf setting-drawer
Showing
16 changed files
with
801 additions
and
563 deletions
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 | 1 | import type { Plugin as VitePlugin } from 'vite'; |
2 | 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 | 4 | import PurgeIcons from 'vite-plugin-purge-icons'; |
8 | 5 | |
9 | 6 | import visualizer from 'rollup-plugin-visualizer'; |
10 | 7 | import gzipPlugin from './gzip/index'; |
11 | 8 | |
12 | -import { hmScript } from '../hm'; | |
13 | - | |
14 | 9 | // @ts-ignore |
15 | 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 | 16 | // gen vite plugins |
20 | 17 | export function createVitePlugins(viteEnv: ViteEnv) { |
21 | - const { VITE_USE_MOCK, VITE_GLOB_APP_TITLE, VITE_PUBLIC_PATH, VITE_USE_PWA } = viteEnv; | |
22 | - | |
23 | 18 | const vitePlugins: VitePlugin[] = []; |
24 | 19 | |
25 | 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 | 27 | // vite-plugin-purge-icons |
46 | 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 | 30 | return vitePlugins; |
83 | 31 | } |
84 | 32 | |
... | ... | @@ -86,17 +34,15 @@ export function createVitePlugins(viteEnv: ViteEnv) { |
86 | 34 | export function createRollupPlugin() { |
87 | 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 | 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 | 103 | const isHorizontal = unref(getIsHorizontal) || getSplit.value; |
104 | 104 | |
105 | 105 | return { |
106 | - height: isHorizontal ? `calc(100%)` : `calc(100% - ${props.showLogo ? '48px' : '0px'})`, | |
106 | + height: isHorizontal ? '100%' : `calc(100% - ${props.showLogo ? '48px' : '0px'})`, | |
107 | 107 | overflowY: isHorizontal ? 'hidden' : 'auto', |
108 | 108 | }; |
109 | 109 | } | ... | ... |
src/hooks/web/useI18n.ts
... | ... | @@ -25,9 +25,9 @@ export function useI18n(namespace?: string) { |
25 | 25 | |
26 | 26 | return { |
27 | 27 | ...methods, |
28 | - t: (key: string, ...arg: Parameters<typeof t>) => { | |
28 | + t: (key: string, ...arg: Partial<Parameters<typeof t>>) => { | |
29 | 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 | 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 | 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 | 15 | import { useRootSetting } from '/@/hooks/setting/useRootSetting'; |
17 | 16 | import { useMenuSetting } from '/@/hooks/setting/useMenuSetting'; |
18 | 17 | import { useHeaderSetting } from '/@/hooks/setting/useHeaderSetting'; |
... | ... | @@ -20,8 +19,6 @@ import { useMultipleTabSetting } from '/@/hooks/setting/useMultipleTabSetting'; |
20 | 19 | import { useTransitionSetting } from '/@/hooks/setting/useTransitionSetting'; |
21 | 20 | import { useI18n } from '/@/hooks/web/useI18n'; |
22 | 21 | |
23 | -import { updateColorWeak, updateGrayMode } from '/@/setup/theme'; | |
24 | - | |
25 | 22 | import { baseHandler } from './handler'; |
26 | 23 | |
27 | 24 | import { |
... | ... | @@ -35,146 +32,8 @@ import { |
35 | 32 | |
36 | 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 | 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 | 37 | export default defineComponent({ |
179 | 38 | name: 'SettingDrawer', |
180 | 39 | setup(_, { attrs }) { |
... | ... | @@ -187,6 +46,7 @@ export default defineComponent({ |
187 | 46 | getFullContent, |
188 | 47 | getColorWeak, |
189 | 48 | getGrayMode, |
49 | + getLockTime, | |
190 | 50 | } = useRootSetting(); |
191 | 51 | |
192 | 52 | const { |
... | ... | @@ -229,38 +89,44 @@ export default defineComponent({ |
229 | 89 | function renderSidebar() { |
230 | 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 | 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 | 134 | * @description: |
269 | 135 | */ |
270 | 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 | 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 | 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 | 214 | max={600} |
369 | 215 | min={100} |
370 | 216 | step={10} |
217 | + event={HandlerEnum.MENU_WIDTH} | |
371 | 218 | disabled={!unref(getShowMenuRef)} |
372 | 219 | defaultValue={unref(getMenuWidth)} |
373 | 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 | 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 | 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 | 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 | 335 | <> |
542 | 336 | <Divider>{() => t('layout.setting.navMode')}</Divider> |
543 | 337 | {renderSidebar()} |
544 | - {renderTheme()} | |
338 | + <Divider>{() => t('layout.setting.headerTheme')}</Divider> | |
339 | + {renderHeaderTheme()} | |
340 | + <Divider>{() => t('layout.setting.sidebarTheme')}</Divider> | |
341 | + {renderSiderTheme()} | |
545 | 342 | <Divider>{() => t('layout.setting.interfaceFunction')}</Divider> |
546 | 343 | {renderFeatures()} |
547 | 344 | <Divider>{() => t('layout.setting.interfaceDisplay')}</Divider> |
... | ... | @@ -549,7 +346,7 @@ export default defineComponent({ |
549 | 346 | <Divider>{() => t('layout.setting.animation')}</Divider> |
550 | 347 | {renderTransition()} |
551 | 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 | 1 | <template> |
2 | - <div @click="openDrawer" class="setting-button"> | |
2 | + <div @click="openDrawer" :class="prefixCls"> | |
3 | 3 | <SettingOutlined /> |
4 | 4 | <SettingDrawer @register="register" /> |
5 | 5 | </div> |
... | ... | @@ -10,13 +10,17 @@ |
10 | 10 | import SettingDrawer from './SettingDrawer'; |
11 | 11 | |
12 | 12 | import { useDrawer } from '/@/components/Drawer'; |
13 | + import { useDesign } from '/@/hooks/web/useDesign'; | |
13 | 14 | |
14 | 15 | export default defineComponent({ |
15 | 16 | name: 'SettingBtn', |
16 | 17 | components: { SettingOutlined, SettingDrawer }, |
17 | 18 | setup() { |
18 | 19 | const [register, { openDrawer }] = useDrawer(); |
20 | + | |
21 | + const { prefixCls } = useDesign('setting-button'); | |
19 | 22 | return { |
23 | + prefixCls, | |
20 | 24 | register, |
21 | 25 | openDrawer, |
22 | 26 | }; |
... | ... | @@ -25,9 +29,9 @@ |
25 | 29 | </script> |
26 | 30 | <style lang="less"> |
27 | 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 | 35 | position: absolute; |
32 | 36 | top: 45%; |
33 | 37 | right: 0; | ... | ... |