feat(projects): 主题配置抽屉: 迁移其他功能

This commit is contained in:
Soybean 2022-01-09 13:25:42 +08:00
parent 912bfdf439
commit 6d132c5977
10 changed files with 269 additions and 6 deletions

View File

@ -23,6 +23,7 @@
"dependencies": { "dependencies": {
"@vueuse/core": "^7.5.3", "@vueuse/core": "^7.5.3",
"axios": "^0.24.0", "axios": "^0.24.0",
"clipboard": "^2.0.8",
"colord": "^2.9.2", "colord": "^2.9.2",
"crypto-js": "^4.1.1", "crypto-js": "^4.1.1",
"dayjs": "^1.10.7", "dayjs": "^1.10.7",

View File

@ -15,6 +15,7 @@ specifiers:
'@vue/eslint-config-typescript': ^10.0.0 '@vue/eslint-config-typescript': ^10.0.0
'@vueuse/core': ^7.5.3 '@vueuse/core': ^7.5.3
axios: ^0.24.0 axios: ^0.24.0
clipboard: ^2.0.8
colord: ^2.9.2 colord: ^2.9.2
commitizen: ^4.2.4 commitizen: ^4.2.4
cross-env: ^7.0.3 cross-env: ^7.0.3
@ -57,6 +58,7 @@ specifiers:
dependencies: dependencies:
'@vueuse/core': registry.npmmirror.com/@vueuse/core/7.5.3_vue@3.2.26 '@vueuse/core': registry.npmmirror.com/@vueuse/core/7.5.3_vue@3.2.26
axios: registry.npmmirror.com/axios/0.24.0 axios: registry.npmmirror.com/axios/0.24.0
clipboard: registry.npmmirror.com/clipboard/2.0.8
colord: registry.npmmirror.com/colord/2.9.2 colord: registry.npmmirror.com/colord/2.9.2
crypto-js: registry.npmmirror.com/crypto-js/4.1.1 crypto-js: registry.npmmirror.com/crypto-js/4.1.1
dayjs: registry.npmmirror.com/dayjs/1.10.7 dayjs: registry.npmmirror.com/dayjs/1.10.7
@ -711,6 +713,12 @@ packages:
engines: {node: '>=0.4.0'} engines: {node: '>=0.4.0'}
dev: false dev: false
registry.nlark.com/delegate/3.2.0:
resolution: {integrity: sha1-tmtxwxWFIuirV0T3INjKDCr1kWY=, registry: http://registry.npm.taobao.org/, tarball: https://registry.nlark.com/delegate/download/delegate-3.2.0.tgz}
name: delegate
version: 3.2.0
dev: false
registry.nlark.com/detect-file/1.0.0: registry.nlark.com/detect-file/1.0.0:
resolution: {integrity: sha1-8NZtA2cqglyxtzvbP+YjEMjlUrc=, registry: http://registry.npm.taobao.org/, tarball: https://registry.nlark.com/detect-file/download/detect-file-1.0.0.tgz} resolution: {integrity: sha1-8NZtA2cqglyxtzvbP+YjEMjlUrc=, registry: http://registry.npm.taobao.org/, tarball: https://registry.nlark.com/detect-file/download/detect-file-1.0.0.tgz}
name: detect-file name: detect-file
@ -1258,6 +1266,14 @@ packages:
slash: registry.nlark.com/slash/3.0.0 slash: registry.nlark.com/slash/3.0.0
dev: true dev: true
registry.nlark.com/good-listener/1.2.2:
resolution: {integrity: sha1-1TswzfkxPf+33JoNR3CWqm0UXFA=, registry: http://registry.npm.taobao.org/, tarball: https://registry.nlark.com/good-listener/download/good-listener-1.2.2.tgz}
name: good-listener
version: 1.2.2
dependencies:
delegate: registry.nlark.com/delegate/3.2.0
dev: false
registry.nlark.com/hard-rejection/2.1.0: registry.nlark.com/hard-rejection/2.1.0:
resolution: {integrity: sha1-HG7aXBaFxjlCdm15u0Cudzzs2IM=, registry: http://registry.npm.taobao.org/, tarball: https://registry.nlark.com/hard-rejection/download/hard-rejection-2.1.0.tgz} resolution: {integrity: sha1-HG7aXBaFxjlCdm15u0Cudzzs2IM=, registry: http://registry.npm.taobao.org/, tarball: https://registry.nlark.com/hard-rejection/download/hard-rejection-2.1.0.tgz}
name: hard-rejection name: hard-rejection
@ -2471,6 +2487,12 @@ packages:
version: 2.1.2 version: 2.1.2
dev: true dev: true
registry.nlark.com/select/1.1.2:
resolution: {integrity: sha1-DnNQrN7ICxEIUoeG7B1EGNEbOW0=, registry: http://registry.npm.taobao.org/, tarball: https://registry.nlark.com/select/download/select-1.1.2.tgz}
name: select
version: 1.1.2
dev: false
registry.nlark.com/semver/5.7.1: registry.nlark.com/semver/5.7.1:
resolution: {integrity: sha1-qVT5Ma66UI0we78Gnv8MAclhFvc=, registry: http://registry.npm.taobao.org/, tarball: https://registry.nlark.com/semver/download/semver-5.7.1.tgz?cache=0&sync_timestamp=1631500167672&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fsemver%2Fdownload%2Fsemver-5.7.1.tgz} resolution: {integrity: sha1-qVT5Ma66UI0we78Gnv8MAclhFvc=, registry: http://registry.npm.taobao.org/, tarball: https://registry.nlark.com/semver/download/semver-5.7.1.tgz?cache=0&sync_timestamp=1631500167672&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fsemver%2Fdownload%2Fsemver-5.7.1.tgz}
name: semver name: semver
@ -2745,6 +2767,12 @@ packages:
readable-stream: registry.nlark.com/readable-stream/3.6.0 readable-stream: registry.nlark.com/readable-stream/3.6.0
dev: true dev: true
registry.nlark.com/tiny-emitter/2.1.0:
resolution: {integrity: sha1-HRpW7fxRxD6GPLtTgqcjMONVVCM=, registry: http://registry.npm.taobao.org/, tarball: https://registry.nlark.com/tiny-emitter/download/tiny-emitter-2.1.0.tgz}
name: tiny-emitter
version: 2.1.0
dev: false
registry.nlark.com/tmp/0.0.33: registry.nlark.com/tmp/0.0.33:
resolution: {integrity: sha1-bTQzWIl2jSGyvNoKonfO07G/rfk=, registry: http://registry.npm.taobao.org/, tarball: https://registry.nlark.com/tmp/download/tmp-0.0.33.tgz} resolution: {integrity: sha1-bTQzWIl2jSGyvNoKonfO07G/rfk=, registry: http://registry.npm.taobao.org/, tarball: https://registry.nlark.com/tmp/download/tmp-0.0.33.tgz}
name: tmp name: tmp
@ -4227,6 +4255,16 @@ packages:
string-width: registry.npmmirror.com/string-width/5.0.1 string-width: registry.npmmirror.com/string-width/5.0.1
dev: true dev: true
registry.npmmirror.com/clipboard/2.0.8:
resolution: {integrity: sha512-Y6WO0unAIQp5bLmk1zdThRhgJt/x3ks6f30s3oE3H1mgIEU33XyQjEf8gsf6DxC7NPX8Y1SsNWjUjL/ywLnnbQ==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/clipboard/download/clipboard-2.0.8.tgz}
name: clipboard
version: 2.0.8
dependencies:
good-listener: registry.nlark.com/good-listener/1.2.2
select: registry.nlark.com/select/1.1.2
tiny-emitter: registry.nlark.com/tiny-emitter/2.1.0
dev: false
registry.npmmirror.com/color-convert/1.9.3: registry.npmmirror.com/color-convert/1.9.3:
resolution: {integrity: sha1-u3GFBpDh8TZWfeYp0tVHHe2kweg=, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/color-convert/download/color-convert-1.9.3.tgz} resolution: {integrity: sha1-u3GFBpDh8TZWfeYp0tVHHe2kweg=, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/color-convert/download/color-convert-1.9.3.tgz}
name: color-convert name: color-convert

View File

@ -0,0 +1,80 @@
<template>
<n-divider title-placement="center">界面功能</n-divider>
<n-space vertical size="large">
<setting-menu label="固定头部和多页签">
<n-switch :value="theme.fixedHeaderAndTab" @update:value="setIsFixedHeaderAndTab" />
</setting-menu>
<setting-menu label="顶部菜单位置">
<n-select
class="w-120px"
size="small"
:value="theme.menu.horizontalPosition"
:options="theme.menu.horizontalPositionList"
@update:value="setHorizontalMenuPosition"
/>
</setting-menu>
<setting-menu label="头部高度">
<n-input-number
class="w-120px"
size="small"
:value="theme.header.height"
:step="1"
@update:value="handleSetNumber($event, setHeaderHeight)"
/>
</setting-menu>
<setting-menu label="多页签高度">
<n-input-number
class="w-120px"
size="small"
:value="theme.tab.height"
:step="1"
@update:value="handleSetNumber($event, setTabHeight)"
/>
</setting-menu>
<setting-menu label="多页签缓存">
<n-switch :value="theme.tab.isCache" @update:value="setTabIsCache" />
</setting-menu>
<setting-menu label="侧边栏展开宽度">
<n-input-number
class="w-120px"
size="small"
:value="theme.sider.width"
:step="10"
@update:value="handleSetNumber($event, setSiderWidth)"
/>
</setting-menu>
<setting-menu label="左侧混合侧边栏展开宽度">
<n-input-number
class="w-120px"
size="small"
:value="theme.sider.mixWidth"
:step="5"
@update:value="handleSetNumber($event, setMixSiderWidth)"
/>
</setting-menu>
</n-space>
</template>
<script lang="ts" setup>
import { NDivider, NSpace, NSwitch, NSelect, NInputNumber } from 'naive-ui';
import { useThemeStore } from '@/store';
import SettingMenu from '../SettingMenu/index.vue';
const theme = useThemeStore();
const {
setHorizontalMenuPosition,
setIsFixedHeaderAndTab,
setHeaderHeight,
setTabHeight,
setSiderWidth,
setMixSiderWidth,
setTabIsCache
} = useThemeStore();
function handleSetNumber(value: number | null, callback: (value: number) => void) {
if (value !== null) {
callback(value);
}
}
</script>
<style scoped></style>

View File

@ -0,0 +1,52 @@
<template>
<n-divider title-placement="center">界面显示</n-divider>
<n-space vertical size="large">
<setting-menu label="面包屑">
<n-switch :value="theme.header.crumb.visible" @update:value="setHeaderCrumbVisible" />
</setting-menu>
<setting-menu label="面包屑图标">
<n-switch :value="theme.header.crumb.showIcon" @update:value="setHeaderCrumbIconVisible" />
</setting-menu>
<setting-menu label="多页签">
<n-switch :value="theme.tab.visible" @update:value="setTabVisible" />
</setting-menu>
<setting-menu label="多页签风格">
<n-select
class="w-120px"
size="small"
:value="theme.tab.mode"
:options="theme.tab.modeList"
@update:value="setTabMode"
/>
</setting-menu>
<setting-menu label="页面切换动画">
<n-switch :value="theme.page.animate" @update:value="setPageIsAnimate" />
</setting-menu>
<setting-menu label="页面切换动画类型">
<n-select
class="w-120px"
size="small"
:value="theme.page.animateMode"
:options="theme.page.animateModeList"
@update:value="setPageAnimateMode"
/>
</setting-menu>
</n-space>
</template>
<script lang="ts" setup>
import { NDivider, NSpace, NSwitch, NSelect } from 'naive-ui';
import { useThemeStore } from '@/store';
import SettingMenu from '../SettingMenu/index.vue';
const theme = useThemeStore();
const {
setHeaderCrumbVisible,
setHeaderCrumbIconVisible,
setTabVisible,
setTabMode,
setPageIsAnimate,
setPageAnimateMode
} = useThemeStore();
</script>
<style scoped></style>

View File

@ -0,0 +1,16 @@
<template>
<div class="flex-y-center justify-between">
<span>{{ label }}</span>
<slot></slot>
</div>
</template>
<script lang="ts" setup>
interface Props {
/** 文本 */
label: string;
}
defineProps<Props>();
</script>
<style scoped></style>

View File

@ -0,0 +1,57 @@
<template>
<n-divider title-placement="center">主题配置</n-divider>
<n-space vertical>
<div ref="copyRef" :data-clipboard-text="dataClipboardText">
<n-button type="primary" :block="true">拷贝当前配置</n-button>
</div>
<n-button type="warning" :block="true" @click="handleResetConfig">重置当前配置</n-button>
</n-space>
</template>
<script setup lang="ts">
import { ref, watch, onMounted, onUnmounted } from 'vue';
import { NDivider, NSpace, NButton } from 'naive-ui';
import Clipboard from 'clipboard';
import { useThemeStore } from '@/store';
const theme = useThemeStore();
const copyRef = ref<HTMLElement | null>(null);
const dataClipboardText = ref(getClipboardText());
function getClipboardText() {
return JSON.stringify(theme.$state);
}
function handleResetConfig() {
theme.resetThemeStore();
window.$message?.success('已重置配置,请重新拷贝!');
}
function clipboardEventListener() {
const copy = new Clipboard(copyRef.value!);
copy.on('success', () => {
window.$dialog?.success({
title: '操作成功',
content: '复制成功,请替换 src/settings/theme.json的内容',
positiveText: '确定'
});
});
}
const stopHandle = watch(
() => theme.$state,
() => {
dataClipboardText.value = getClipboardText();
},
{ deep: true }
);
onMounted(() => {
clipboardEventListener();
});
onUnmounted(() => {
stopHandle();
});
</script>
<style scoped></style>

View File

@ -2,5 +2,8 @@ import DrawerButton from './DrawerButton/index.vue';
import DarkMode from './DarkMode/index.vue'; import DarkMode from './DarkMode/index.vue';
import LayoutMode from './LayoutMode/index.vue'; import LayoutMode from './LayoutMode/index.vue';
import ThemeColorSelect from './ThemeColorSelect/index.vue'; import ThemeColorSelect from './ThemeColorSelect/index.vue';
import PageFunc from './PageFunc/index.vue';
import PageView from './PageView/index.vue';
import ThemeConfig from './ThemeConfig/index.vue';
export { DarkMode, DrawerButton, LayoutMode, ThemeColorSelect }; export { DrawerButton, DarkMode, LayoutMode, ThemeColorSelect, PageFunc, PageView, ThemeConfig };

View File

@ -4,6 +4,9 @@
<dark-mode /> <dark-mode />
<layout-mode /> <layout-mode />
<theme-color-select /> <theme-color-select />
<page-func />
<page-view />
<theme-config />
</n-drawer-content> </n-drawer-content>
</n-drawer> </n-drawer>
<drawer-button /> <drawer-button />
@ -12,7 +15,7 @@
<script setup lang="ts"> <script setup lang="ts">
import { NDrawer, NDrawerContent } from 'naive-ui'; import { NDrawer, NDrawerContent } from 'naive-ui';
import { useAppStore } from '@/store'; import { useAppStore } from '@/store';
import { DrawerButton, DarkMode, LayoutMode, ThemeColorSelect } from './components'; import { DrawerButton, DarkMode, LayoutMode, ThemeColorSelect, PageFunc, PageView, ThemeConfig } from './components';
const app = useAppStore(); const app = useAppStore();
</script> </script>

View File

@ -32,7 +32,6 @@ interface AuthStore {
export const useAuthStore = defineStore('auth-store', () => { export const useAuthStore = defineStore('auth-store', () => {
const { toLogin, toLoginRedirect } = useRouterPush(false); const { toLogin, toLoginRedirect } = useRouterPush(false);
const { loading: loginLoding, startLoading: startLoginLoading, endLoading: endLoginLoading } = useLoading();
const userInfo: Auth.UserInfo = reactive(getUserInfo()); const userInfo: Auth.UserInfo = reactive(getUserInfo());
function handleSetUserInfo(data: Auth.UserInfo) { function handleSetUserInfo(data: Auth.UserInfo) {
@ -46,12 +45,18 @@ export const useAuthStore = defineStore('auth-store', () => {
const isLogin = computed(() => Boolean(token.value)); const isLogin = computed(() => Boolean(token.value));
const { loading: loginLoding, startLoading: startLoginLoading, endLoading: endLoginLoading } = useLoading();
function resetStore() {
handleSetUserInfo(getUserInfo());
handleSetToken(getToken());
}
function resetAuthStore(pushRoute: boolean = true) { function resetAuthStore(pushRoute: boolean = true) {
const auth = useAuthStore();
const route = unref(globalRouter.currentRoute); const route = unref(globalRouter.currentRoute);
clearAuthStorage(); clearAuthStorage();
auth.$reset(); resetStore();
if (pushRoute && route.meta.requiresAuth) { if (pushRoute && route.meta.requiresAuth) {
toLogin(); toLogin();

View File

@ -67,6 +67,8 @@ interface ThemeStore extends LayoutFunc, HeaderFunc, TabFunc, SiderFunc, FooterF
naiveThemeOverrides: ComputedRef<GlobalThemeOverrides>; naiveThemeOverrides: ComputedRef<GlobalThemeOverrides>;
/** naive-ui暗黑主题 */ /** naive-ui暗黑主题 */
naiveTheme: ComputedRef<BuiltInGlobalTheme | undefined>; naiveTheme: ComputedRef<BuiltInGlobalTheme | undefined>;
/** 重置状态 */
resetThemeStore(): void;
} }
export const useThemeStore = defineStore('theme-store', () => { export const useThemeStore = defineStore('theme-store', () => {
@ -148,6 +150,11 @@ export const useThemeStore = defineStore('theme-store', () => {
); );
const naiveTheme = computed(() => (darkMode.value ? darkTheme : undefined)); const naiveTheme = computed(() => (darkMode.value ? darkTheme : undefined));
/** 重置theme状态 */
function resetThemeStore() {
setDarkMode(false);
}
/** 初始化css vars, 并添加至html */ /** 初始化css vars, 并添加至html */
function initThemeCssVars() { function initThemeCssVars() {
const updatedThemeVars = { ...naiveThemeOverrides.value.common }; const updatedThemeVars = { ...naiveThemeOverrides.value.common };
@ -214,7 +221,8 @@ export const useThemeStore = defineStore('theme-store', () => {
setPageIsAnimate, setPageIsAnimate,
setPageAnimateMode, setPageAnimateMode,
naiveThemeOverrides, naiveThemeOverrides,
naiveTheme naiveTheme,
resetThemeStore
}; };
return themeStore; return themeStore;