diff --git a/src/App.vue b/src/App.vue index 020167b8..fc9f4331 100644 --- a/src/App.vue +++ b/src/App.vue @@ -1,22 +1,48 @@ diff --git a/src/assets/background_dark.jpg b/src/assets/background_dark.jpg new file mode 100644 index 00000000..1b64e7df Binary files /dev/null and b/src/assets/background_dark.jpg differ diff --git a/src/assets/background.jpg b/src/assets/background_light.jpg similarity index 100% rename from src/assets/background.jpg rename to src/assets/background_light.jpg diff --git a/src/assets/svg/dark.svg b/src/assets/svg/dark.svg new file mode 100644 index 00000000..9b27cc61 --- /dev/null +++ b/src/assets/svg/dark.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/svg/light.svg b/src/assets/svg/light.svg new file mode 100644 index 00000000..161b3bd9 --- /dev/null +++ b/src/assets/svg/light.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/hooks/useTheme.ts b/src/hooks/useTheme.ts index 4ae9108c..e9cd450d 100644 --- a/src/hooks/useTheme.ts +++ b/src/hooks/useTheme.ts @@ -1,5 +1,5 @@ import { onBeforeMount } from 'vue'; -import { ConfigProvider, message } from 'ant-design-vue/lib'; +import { ConfigProvider, message } from 'ant-design-vue/es'; import { CACHE_LOCAL_PRIMARY_COLOR } from '@/constants/cache-keys-constants'; import { localGet, localSet } from '@/utils/cache-local-utils'; diff --git a/src/i18n/locales/en-US.ts b/src/i18n/locales/en-US.ts index aad058da..a277f380 100644 --- a/src/i18n/locales/en-US.ts +++ b/src/i18n/locales/en-US.ts @@ -192,6 +192,7 @@ export default { lockPasswd: "Unlock Password", lockPasswdTip: "No password can be set", fullscreen: "Full Screen", + theme: "Theme light/dark mode", logout: "Logout", profile: "Profile", settings: "Settings", @@ -317,6 +318,8 @@ export default { color: "Style color scheme", colorActions: "Overall style color scheme setting", colorRandomly: "Randomization", + theme: "Theme dark and light modes", + themeActions: "Toggle light/dark mode", navTheme: "Dark Menu", navThemeActions: "Menus that can only change the navigation mode", fixedHeader: "Fixed top navigation bar", @@ -1072,7 +1075,19 @@ export default { element:'Element', granularity:'Granularity', unit:'Unit', - } + }, + kpiKeyTarget:{ + "fullWidthLayout":"Full Width", + "twoColumnLayout":"Two Column", + "saveLayout": "Save Layout", + "restoreSaved": "Restore Layout", + "saveSuccess": " '{name}' saved successfully", + "restoreSavedSuccess": " '{name}' restored successfully", + "noSavedLayout": "No saved layout found for '{name}'", + "layout1": "Layout 1", + "layout2": "Layout 2", + "layout3": "Layout 3" + }, }, traceManage: { analysis: { @@ -1288,7 +1303,7 @@ export default { }, exportFile:{ fileName:'File Source', - downTip: "Confirm the download file name is [{fileName}] File?", + downTip: "Confirm the download file name is [{fileName}] File?", downTipErr: "Failed to get file", deleteTip: "Confirm the delete file name is [{fileName}] File?", deleteTipErr: "Failed to delete file", diff --git a/src/i18n/locales/zh-CN.ts b/src/i18n/locales/zh-CN.ts index 3f878c47..bce5a90c 100644 --- a/src/i18n/locales/zh-CN.ts +++ b/src/i18n/locales/zh-CN.ts @@ -192,6 +192,7 @@ export default { lockPasswd: "解锁密码", lockPasswdTip: "可不设置密码", fullscreen: "全屏显示", + theme: "主题明/暗模式", logout: "退出登录", profile: "个人中心", settings: "个人设置", @@ -317,6 +318,8 @@ export default { color: "风格配色", colorActions: "整体风格配色设置", colorRandomly: "随机", + theme: "主题明暗模式", + themeActions: "切换浅色/暗黑模式", navTheme: "深色菜单", navThemeActions: "只能改变导航模式的菜单", fixedHeader: "固定顶部导航栏", @@ -1072,7 +1075,19 @@ export default { element:'元素', granularity:'颗粒度', unit:'单位', - } + }, + kpiKeyTarget:{ + "fullWidthLayout":"全宽布局", + "twoColumnLayout":"两列布局", + "saveLayout": "保存布局", + "restoreSaved": "恢复布局", + "saveSuccess": " {name} 保存成功", + "restoreSavedSuccess": " {name} 恢复成功", + "noSavedLayout": "没有找到保存的布局 {name}", + "layout1": "布局1", + "layout2": "布局2", + "layout3": "布局3" + }, }, traceManage: { analysis: { @@ -1127,7 +1142,7 @@ export default { stopNotRun: "{title} 任务未运行", }, task: { - traceId: '跟踪编号', + traceId: '跟踪编号', trackType: '跟踪类型', trackTypePlease: '请选择跟踪类型', creater: '创建人', @@ -1288,7 +1303,7 @@ export default { }, exportFile:{ fileName:'文件来源', - downTip: "确认下载文件名为 【{fileName}】 文件?", + downTip: "确认下载文件名为 【{fileName}】 文件?", downTipErr: "文件获取失败", deleteTip: "确认删除文件名为 【{fileName}】 文件?", deleteTipErr: "文件删除失败", @@ -2110,7 +2125,7 @@ export default { hostSelectMore: "加载更多 {num}", hostSelectHeader: "主机列表", }, - ps:{ + ps:{ realTimeHigh:"高", realTimeLow:"低", realTimeRegular:"常规", diff --git a/src/layouts/BasicLayout.vue b/src/layouts/BasicLayout.vue index 9a3f9f4d..2d5dddcc 100644 --- a/src/layouts/BasicLayout.vue +++ b/src/layouts/BasicLayout.vue @@ -1,10 +1,9 @@ - + - + @@ -364,7 +362,7 @@ onUnmounted(() => { - + diff --git a/src/layouts/components/Tabs.vue b/src/layouts/components/Tabs.vue index b72f87b9..341bcd01 100644 --- a/src/layouts/components/Tabs.vue +++ b/src/layouts/components/Tabs.vue @@ -4,9 +4,9 @@ import { computed, watch } from 'vue'; import { useRouter } from 'vue-router'; import useTabsStore from '@/store/modules/tabs'; import useI18n from '@/hooks/useI18n'; -const { t } = useI18n(); const tabsStore = useTabsStore(); const router = useRouter(); +const { t } = useI18n(); defineProps({ /**标签栏宽度 */ @@ -112,7 +112,7 @@ watch(router.currentRoute, v => tabsStore.tabOpen(v), { immediate: true }); tabsStore.tabOpen(v), { immediate: true }); - + @@ -199,7 +199,18 @@ watch(router.currentRoute, v => tabsStore.tabOpen(v), { immediate: true }); } } +[data-theme='dark'] .tabs { + background: #141414; +} + .tabs :deep(.ant-tabs-nav:before) { border-bottom: none; } +.tabs :deep(.ant-tabs-nav-list .ant-tabs-tab) { + border-radius: 8px; +} +.tabs :deep(.ant-tabs-nav-list .ant-tabs-tab.ant-tabs-tab-active) { + border-bottom-right-radius: unset; + border-bottom-left-radius: unset; +} diff --git a/src/store/modules/layout.ts b/src/store/modules/layout.ts index c297498b..21c9cf34 100644 --- a/src/store/modules/layout.ts +++ b/src/store/modules/layout.ts @@ -1,16 +1,23 @@ -import { CACHE_LOCAL_PROCONFIG } from '@/constants/cache-keys-constants'; -import { localGetJSON, localSetJSON } from '@/utils/cache-local-utils'; +import { theme } from 'ant-design-vue/es'; +import type { ThemeConfig } from 'ant-design-vue/es/config-provider/context'; import { defineStore } from 'pinia'; +import { + CACHE_LOCAL_PRIMARY_COLOR, + CACHE_LOCAL_PROCONFIG, +} from '@/constants/cache-keys-constants'; +import { + localGet, + localGetJSON, + localSetJSON, +} from '@/utils/cache-local-utils'; /**布局参数类型 */ type LayoutStore = { - /**布局设置抽屉显示 */ - visible: boolean; /**布局配置 */ proConfig: { /**导航布局 */ layout: 'side' | 'top' | 'mix'; - /**全局主题色,需要导入样式文件 */ + /**全局主题色*/ theme: 'dark' | 'light'; /**菜单导航主题色 */ menuTheme: 'dark' | 'light'; @@ -29,10 +36,33 @@ type LayoutStore = { /**内容区域-导航标签项 */ tabRender: any | boolean | undefined; }; + /**主题配置 */ + themeConfig: ThemeConfig; /**水印内容 */ waterMarkContent: string; }; +/** + * 获取随机颜色范围 + * @returns 颜色 + */ +function getRandomColor(): string { + const colors: string[] = [ + '#f5222d', + '#fa541c', + '#fa8c16', + '#a0d911', + '#13c2c2', + '#1890ff', + '#722ed1', + '#eb2f96', + '#faad14', + '#52c41a', + ]; + const i = Math.floor(Math.random() * 10); + return colors[i]; +} + /**判断是否关闭内容区域 */ const proRender = (render: any) => (render === false ? false : undefined); @@ -40,7 +70,7 @@ const proRender = (render: any) => (render === false ? false : undefined); const proConfigLocal: LayoutStore['proConfig'] = localGetJSON( CACHE_LOCAL_PROCONFIG ) || { - layout: 'mix', + layout: 'side', theme: 'light', menuTheme: 'light', fixSiderbar: true, @@ -50,7 +80,6 @@ const proConfigLocal: LayoutStore['proConfig'] = localGetJSON( const useLayoutStore = defineStore('layout', { state: (): LayoutStore => ({ - visible: false, proConfig: { layout: proConfigLocal.layout, theme: proConfigLocal.theme, @@ -63,13 +92,27 @@ const useLayoutStore = defineStore('layout', { menuHeaderRender: proRender(proConfigLocal.menuHeaderRender), tabRender: proRender(proConfigLocal.tabRender), }, + themeConfig: { + algorithm: [theme.darkAlgorithm], + // algorithm: themeColor["dark"], + token: { + // colorBgContainer: "#fff", + colorPrimary: localGet(CACHE_LOCAL_PRIMARY_COLOR) || '#1890ff', + // borderRadius: 6, + }, + }, waterMarkContent: import.meta.env.VITE_APP_NAME, }), - actions: { - /**改变显示状态 */ - changeVisibleLayoutSetting() { - this.visible = !this.visible; + getters: { + getColorPrimary(): string { + let color = '#1890ff'; + if (this.themeConfig.token) { + color = this.themeConfig.token.colorPrimary || color; + } + return color; }, + }, + actions: { /**修改水印文字 */ changeWaterMark(text: string) { this.waterMarkContent = text; @@ -77,10 +120,48 @@ const useLayoutStore = defineStore('layout', { /**修改布局设置 */ changeConf(key: string, value: boolean | string | number | undefined) { if (Reflect.has(this.proConfig, key)) { + console.log(key, value); + if (key === 'theme') { + // const themeColor = { + // light: theme.defaultAlgorithm, + // compact: theme.compactAlgorithm, + // dark: theme.darkAlgorithm, + // }; + if (value === 'dark') { + document.documentElement.setAttribute('data-theme', 'dark'); + this.themeConfig.algorithm = [theme.darkAlgorithm]; + } else { + document.documentElement.setAttribute('data-theme', 'light'); + this.themeConfig.algorithm = [theme.defaultAlgorithm]; + } + } Reflect.set(this.proConfig, key, value); localSetJSON(CACHE_LOCAL_PROCONFIG, this.proConfig); } }, + /**主题色初始化 */ + initPrimaryColor() { + // 主题色初始化 + this.changePrimaryColor(this.getColorPrimary); + // 明暗模式初始化 + const themeMode = this.proConfig.theme; + document.documentElement.setAttribute('data-theme', themeMode); + this.changeConf('theme', themeMode); + }, + /** + * 主题色变更 + * @param color 颜色 + */ + changePrimaryColor(color?: string) { + if (!color) { + color = getRandomColor(); + } + + if (this.themeConfig && this.themeConfig.token) { + this.themeConfig.token.colorPrimary = color; + localStorage.setItem(CACHE_LOCAL_PRIMARY_COLOR, color); + } + }, }, }); diff --git a/src/store/modules/user.ts b/src/store/modules/user.ts index 1a9b1932..a7bb65a6 100644 --- a/src/store/modules/user.ts +++ b/src/store/modules/user.ts @@ -1,7 +1,7 @@ import defaultAvatar from '@/assets/images/default_avatar.png'; import useLayoutStore from './layout'; import { login, logout, getInfo } from '@/api/login'; -import { getToken, setToken, removeToken } from '@/plugins/auth-token'; +import { setToken, removeToken } from '@/plugins/auth-token'; import { defineStore } from 'pinia'; import { TOKEN_RESPONSE_FIELD } from '@/constants/token-constants'; import { RESULT_CODE_SUCCESS } from '@/constants/result-constants'; @@ -133,10 +133,10 @@ const useUserStore = defineStore('user', { } // 水印文字信息=用户昵称 手机号 - let waterMarkContent = this.userName; - if (this.phonenumber) { - waterMarkContent = `${this.userName} ${this.phonenumber}`; - } + // let waterMarkContent = this.userName; + // if (this.phonenumber) { + // waterMarkContent = `${this.userName} ${this.phonenumber}`; + // } // useLayoutStore().changeWaterMark(waterMarkContent); useLayoutStore().changeWaterMark(''); }