Skip to content

Commit 58e1ac5

Browse files
committed
feat(style): setting the global theme color gradient
1 parent ddc93b5 commit 58e1ac5

21 files changed

Lines changed: 361 additions & 97 deletions

File tree

pnpm-lock.yaml

Lines changed: 10 additions & 10 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/App.vue

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<template>
2-
<n-config-provider :locale="zhCN" :date-locale="dateZhCN">
2+
<n-config-provider :locale="zhCN" :date-locale="dateZhCN" :theme-overrides="ThemeOverride">
33
<n-message-provider>
44
<n-spin :show="isLoading">
55
<router-view />
@@ -12,12 +12,15 @@
1212
import { computed, onBeforeMount } from 'vue';
1313
import { zhCN, dateZhCN } from 'naive-ui';
1414
import { NConfigProvider } from 'naive-ui';
15+
import { useTheme } from '@/hooks/useTheme.ts';
1516
import { useTranslations } from '@/hooks/useTranslate.ts';
1617
import { useGlobalStore } from '@/stores/modules/global.ts';
1718
import { useLoadingStore } from '@/stores/modules/loading.ts';
19+
import { LightThemeOverrides, DarkThemeOverrides } from './themeOverride.ts';
1820
1921
import { setFavicon } from '@/utils';
2022
23+
const { initTheme } = useTheme();
2124
const globalStore = useGlobalStore();
2225
const loadingStore = useLoadingStore();
2326
const { updateTranslations } = useTranslations();
@@ -26,7 +29,11 @@ const isLoading = computed(() => {
2629
return loadingStore.isLoading;
2730
});
2831
32+
console.log(LightThemeOverrides, DarkThemeOverrides);
33+
2934
onBeforeMount(() => {
35+
// 初始化主题样式
36+
initTheme();
3037
// 设置语言
3138
setCurrentLanguage();
3239
// 设置 ico

src/config/index.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,8 @@
1+
// 主题颜色
2+
export const DEFAULT_PRIMARY: string = '#1ab394';
3+
4+
// cookie 中的语言设置项
15
export const LANG_COOKIE_NAME = 'django_language';
6+
7+
// 支持的语言列表
28
export const SUPPORTED_LANG_CODES: string[] = ['en', 'zh', 'ja', 'zh-hant'];

src/hooks/useTheme.ts

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
import { storeToRefs } from 'pinia';
2+
import { useI18n } from 'vue-i18n';
3+
import { Theme } from '@/styles/types';
4+
import { DEFAULT_PRIMARY } from '@/config';
5+
import { createDiscreteApi } from 'naive-ui';
6+
import { asideTheme } from '@/styles/theme/aside.ts';
7+
import { getLightColor, getDarkColor } from '@/utils';
8+
import { useGlobalStore } from '@/stores/modules/global.ts';
9+
10+
/**
11+
* @description 全局主题 hooks
12+
* */
13+
14+
export const useTheme = () => {
15+
const globalStore = useGlobalStore();
16+
17+
const { t } = useI18n();
18+
const { message } = createDiscreteApi(['message']);
19+
const { isDark, primary } = storeToRefs(globalStore);
20+
21+
/**
22+
* @description 切换黑暗模式 同时修改主题颜色
23+
*/
24+
const switchDark = (): void => {
25+
const html: HTMLElement = document.documentElement;
26+
27+
if (isDark.value) {
28+
html.setAttribute('class', 'dark');
29+
} else {
30+
html.setAttribute('class', '');
31+
}
32+
33+
changePrimary(primary.value);
34+
setAsideTheme();
35+
};
36+
37+
/**
38+
* @description 切换主题颜色
39+
*/
40+
const changePrimary = (val: string | null) => {
41+
if (!val) {
42+
val = DEFAULT_PRIMARY;
43+
message.success(`${t('Theme reset')} ${DEFAULT_PRIMARY}`);
44+
}
45+
46+
// 计算主题颜色变化
47+
document.documentElement.style.setProperty('--el-color-primary', val);
48+
document.documentElement.style.setProperty(
49+
'--el-color-primary-dark-2',
50+
isDark.value ? `${getLightColor(val, 0.2)}` : `${getDarkColor(val, 0.3)}`
51+
);
52+
53+
for (let i = 1; i <= 9; i++) {
54+
const primaryColor = isDark.value
55+
? `${getDarkColor(val, i / 10)}`
56+
: `${getLightColor(val, i / 10)}`;
57+
document.documentElement.style.setProperty(`--el-color-primary-light-${i}`, primaryColor);
58+
}
59+
60+
globalStore.setGlobalState('primary', val);
61+
};
62+
63+
/**
64+
* @description 设置侧边样式
65+
*/
66+
const setAsideTheme = () => {
67+
let type: Theme.ThemeType = 'light';
68+
69+
if (isDark.value) type = 'dark';
70+
71+
const theme = asideTheme[type!];
72+
for (const [key, value] of Object.entries(theme)) {
73+
document.documentElement.style.setProperty(key, value);
74+
}
75+
};
76+
77+
/**
78+
* 初始化样式
79+
*/
80+
const initTheme = () => {
81+
switchDark();
82+
};
83+
84+
return {
85+
initTheme,
86+
switchDark,
87+
setAsideTheme,
88+
changePrimary
89+
};
90+
};

src/languages/modules/en.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,5 +8,6 @@ export default {
88
notParenthesis: 'Parentheses are not allowed.',
99
InvalidJson: 'Invalid JSON format.',
1010
requiredHasUserNameMapped: 'Username attr is required.',
11-
'Web Terminal': 'Web Terminal'
11+
'Web Terminal': 'Web Terminal',
12+
'Theme reset': 'The theme color has been reset to'
1213
};

src/languages/modules/zh.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,5 +8,6 @@ export default {
88
notParenthesis: '不能包含括号。',
99
InvalidJson: 'JSON 格式错误.',
1010
requiredHasUserNameMapped: '用户名属性是必需的。',
11-
'Web Terminal': 'Web 终端'
11+
'Web Terminal': 'Web 终端',
12+
'Theme reset': '主题颜色已重置为'
1213
};
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
<template>
2+
<div>File</div>
3+
</template>
4+
5+
<script setup lang="ts"></script>
6+
7+
<style scoped lang="scss"></style>

src/layouts/components/Header/components/Logo/index.vue

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,8 @@ defineProps<{
1010

1111
<style scoped lang="scss">
1212
.n-image {
13-
padding: 0 20px;
13+
justify-content: center;
14+
width: 100%;
1415
&:hover {
1516
cursor: pointer;
1617
background-color: green;
Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,18 @@
11
<template>
2-
<svg-icon :name="name" :icon-style="iconStyle"></svg-icon>
2+
<n-dropdown trigger="hover" :show-arrow="true" placement="right" :options="options">
3+
<svg-icon :name="name" :icon-style="iconStyle" />
4+
</n-dropdown>
35
</template>
46

57
<script setup lang="ts">
68
import { CSSProperties } from 'vue';
9+
import { optionsDetail } from '@/layouts/components/Header/types';
10+
711
import SvgIcon from '@/components/SvgIcon/index.vue';
812
913
defineProps<{
1014
name: string;
15+
options: optionsDetail[];
1116
iconStyle: CSSProperties;
1217
}>();
1318
</script>

src/layouts/components/Header/headerLeft.vue

Lines changed: 39 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,46 @@
11
<template>
2-
<div>
3-
<n-flex class="header-left">
4-
<logo :logo-image="logoImage!" />
5-
<n-space class="action-options">
6-
<action-options :options="options" />
7-
</n-space>
2+
<n-flex justify="center" align="center" class="top-item">
3+
<logo :logo-image="logoImage!" />
4+
<n-flex>
5+
<svg-icon class="tree-icon" :name="icon.name" :icon-style="iconStyle" />
86
</n-flex>
9-
</div>
7+
8+
<n-space class="action-options">
9+
<!-- <action-options :options="options" />-->
10+
</n-space>
11+
</n-flex>
1012
</template>
1113

1214
<script setup lang="ts">
1315
import { useI18n } from 'vue-i18n';
14-
import { onMounted, reactive, watchEffect } from 'vue';
16+
import { type CSSProperties, onMounted, reactive, watchEffect } from 'vue';
1517
import { useGlobalStore } from '@/stores/modules/global';
1618
import { useTranslations } from '@/hooks/useTranslate';
1719
1820
import type { IActionOptions } from './types/index.ts';
1921
2022
import Logo from './components/Logo/index.vue';
21-
import ActionOptions from './components/ActionOptions/index.vue';
23+
// import ActionOptions from './components/ActionOptions/index.vue';
24+
import SvgIcon from '@/components/SvgIcon/index.vue';
25+
import Profile from '@/layouts/components/Header/components/Profile/index.vue';
2226
2327
const { t } = useI18n();
2428
const globalStore = useGlobalStore();
2529
const { updateTranslations } = useTranslations();
2630
31+
const iconStyle: CSSProperties = {
32+
fill: '#fff',
33+
width: '25px',
34+
height: '25px',
35+
transition: 'fill 0.3s'
36+
};
37+
38+
const icon = {
39+
iconStyle,
40+
name: 'tree',
41+
component: Profile
42+
};
43+
2744
const logoImage = globalStore.interface.logo_logout;
2845
const options = reactive<IActionOptions[]>([]);
2946
@@ -149,33 +166,6 @@ const updateOptions = () => {
149166
key: 'Tabs',
150167
label: t('Tabs'),
151168
children: []
152-
},
153-
{
154-
key: 'Help',
155-
label: t('Help'),
156-
children: [
157-
{
158-
key: 'Document',
159-
click: () => {
160-
console.log('Document');
161-
},
162-
label: t('Document')
163-
},
164-
{
165-
key: 'Support',
166-
click: () => {
167-
console.log('Support');
168-
},
169-
label: t('Support')
170-
},
171-
{
172-
key: 'Download',
173-
click: () => {
174-
console.log('Download');
175-
},
176-
label: t('Download')
177-
}
178-
]
179169
}
180170
]
181171
);
@@ -186,4 +176,16 @@ watchEffect(() => {
186176
});
187177
</script>
188178

189-
<style scoped lang="scss"></style>
179+
<style scoped lang="scss">
180+
.top-item {
181+
gap: 15px 12px !important;
182+
width: 100%;
183+
margin-top: 15px;
184+
cursor: pointer;
185+
}
186+
:deep(.tree-icon) {
187+
svg:hover {
188+
fill: #000000 !important;
189+
}
190+
}
191+
</style>

0 commit comments

Comments
 (0)