Skip to content

Commit bcfc565

Browse files
committed
Merge branch 'dev' of github.com:jumpserver/clients into dev
2 parents 5cfdf73 + bb9fe08 commit bcfc565

1 file changed

Lines changed: 128 additions & 5 deletions

File tree

ui/components/SideBar/profile.vue

Lines changed: 128 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,12 @@
22
import type { DropdownMenuItem } from "@nuxt/ui";
33
import type { UnlistenFn } from "@tauri-apps/api/event";
44
import type { WebviewWindow } from "@tauri-apps/api/webviewWindow";
5-
import type { PermissionOrgs, PermOrgItem, UserData, UserIntiInfo, LangType } from "~/types/index";
5+
import type { PermissionOrgs, PermOrgItem, UserData, UserIntiInfo, LangType, ThemeType } from "~/types/index";
66
77
import { resolveLanguageFromCookies } from "~/utils";
88
import { LogicalPosition } from "@tauri-apps/api/dpi";
99
import { useUserInfoStore } from "~/store/modules/userInfo";
10+
import { useSettingManager } from "~/composables/useSettingManager";
1011
1112
const props = defineProps<{ collapse: boolean }>();
1213
@@ -15,10 +16,14 @@ const appConfig = useAppConfig();
1516
const userInfoStore = useUserInfoStore();
1617
1718
const { isMacOS } = usePlatform();
18-
const { t, setLocale } = useI18n();
19+
const { t, setLocale, locales } = useI18n();
1920
// prettier-ignore
2021
const { loggedIn, currentSite, userMap, currentUser, currentLanguage } = storeToRefs(userInfoStore);
2122
23+
const { setLang, theme, primaryColorLight, primaryColorDark } = useSettingManager();
24+
const { manualSetTheme, enableFollowSystem, followSystem, userTheme } = useThemeAdapter();
25+
const { applyPrimaryColor } = useColor();
26+
2227
const inputSite = ref("");
2328
const errorMessage = ref("");
2429
const openModal = ref(false);
@@ -33,8 +38,89 @@ const inputRef = ref<ComponentPublicInstance | null>(null);
3338
useEventBus().on("login", openLoginPage);
3439
3540
const normalizedInputSite = computed(() => normalizeSite(inputSite.value));
41+
const selectedLanguage = ref<LangType>(currentLanguage.value);
42+
43+
// TODO 后续逻辑统一到一个位置
44+
const languageItems = computed(() => {
45+
const arr = (locales.value as any[]) || [];
46+
return arr.map((l: any) => ({
47+
id: l.code || l,
48+
label: l.name || l
49+
}));
50+
});
51+
52+
const languageChildren = computed(() => [
53+
languageItems.value.map((item) => ({
54+
label: item.label,
55+
type: "checkbox",
56+
checked: selectedLanguage.value === (item.id as LangType),
57+
onUpdateChecked: (checked: boolean) => {
58+
if (!checked) return;
59+
handleLanguageChange(item.id as LangType);
60+
}
61+
}))
62+
]);
63+
64+
const appearanceOptions = computed(() => [
65+
{ id: "withSystem", label: t("Common.WithSystem") },
66+
{ id: "light", label: t("Common.Light") },
67+
{ id: "dark", label: t("Common.Dark") }
68+
]);
69+
70+
const selectedAppearance = computed<ThemeType>({
71+
get: () => {
72+
if (followSystem.value) return "withSystem";
73+
74+
const saved = (theme.value || "") as ThemeType;
75+
if (saved === "dark" || saved === "light") return saved;
76+
77+
const current = (userTheme.value || "") as ThemeType;
78+
if (current === "dark" || current === "light") return current;
79+
80+
return "light";
81+
},
82+
set: (id: ThemeType) => {
83+
if (id === "withSystem") {
84+
void enableFollowSystem().then(() => {
85+
useTauriEventEmit("theme-changed", { mode: "withSystem" });
86+
nextTick().then(() => applyCurrentThemeColor(true));
87+
});
88+
return;
89+
}
90+
91+
manualSetTheme(id as any);
92+
useTauriEventEmit("theme-changed", { mode: id });
93+
nextTick().then(() => applyCurrentThemeColor(true));
94+
}
95+
});
96+
97+
const appearanceChildren = computed(() => [
98+
appearanceOptions.value.map((opt) => ({
99+
label: opt.label,
100+
type: "checkbox",
101+
checked: selectedAppearance.value === (opt.id as ThemeType),
102+
onUpdateChecked: (checked: boolean) => {
103+
if (!checked) return;
104+
if (selectedAppearance.value !== (opt.id as ThemeType)) {
105+
selectedAppearance.value = opt.id as ThemeType;
106+
}
107+
}
108+
}))
109+
]);
36110
37111
const profileMenuItems = computed<DropdownMenuItem[][]>(() => [
112+
[
113+
{
114+
label: t("Common.Appearance"),
115+
icon: "solar:palette-linear",
116+
children: appearanceChildren.value
117+
},
118+
{
119+
label: t("Common.Language"),
120+
icon: "solar:global-outline",
121+
children: languageChildren.value
122+
}
123+
],
38124
[
39125
{
40126
label: t("Login.AddAccount"),
@@ -68,10 +154,41 @@ watch(
68154
async (lang: LangType) => {
69155
const target = lang === "zh" ? "zh" : "en";
70156
await setLocale(target);
157+
if (lang && lang !== selectedLanguage.value) {
158+
selectedLanguage.value = lang;
159+
}
71160
},
72161
{ immediate: true }
73162
);
74163
164+
watch(
165+
() => userTheme.value,
166+
() => {
167+
applyCurrentThemeColor();
168+
}
169+
);
170+
171+
const applyCurrentThemeColor = (broadcast = false) => {
172+
const modeNow = (userTheme.value as string) || (selectedAppearance.value as string);
173+
const hexNow = modeNow === "dark" ? primaryColorDark.value : primaryColorLight.value;
174+
175+
if (hexNow) {
176+
applyPrimaryColor(hexNow);
177+
if (broadcast) {
178+
useTauriEventEmit("primary-color-changed", { hex: hexNow, mode: modeNow });
179+
}
180+
}
181+
};
182+
183+
const handleLanguageChange = (code: LangType) => {
184+
if (!code || code === selectedLanguage.value) return;
185+
186+
selectedLanguage.value = code;
187+
setLang(code);
188+
userInfoStore.applyLanguageToAll(code);
189+
useTauriEventEmit("language-changed", { code });
190+
};
191+
75192
/**
76193
* @description 标准化站点输入:去除首尾空格 + 去除末尾斜杠
77194
* @param value 站点输入
@@ -140,8 +257,12 @@ function switchAccountChildren() {
140257
141258
return {
142259
label,
143-
icon: isCurrent ? "i-lucide-check" : "i-lucide-user",
144-
onClick: () => handleSwitchAccount(u.site)
260+
type: "checkbox",
261+
checked: isCurrent,
262+
onUpdateChecked: (checked: boolean) => {
263+
if (!checked || isCurrent) return;
264+
handleSwitchAccount(u.site);
265+
}
145266
} as DropdownMenuItem;
146267
});
147268
@@ -305,6 +426,8 @@ const handleVersions = (version: string[] | string, appVersion: string) => {
305426
};
306427
307428
onMounted(async () => {
429+
applyCurrentThemeColor();
430+
308431
unlistenErrorPageRef.value = await useTauriEventListen("error-page", (event) => {
309432
const { status, reason } = event.payload as {
310433
status: string;
@@ -380,7 +503,7 @@ onMounted(async () => {
380503
userInfoStore.setCurrentOrg(currentOrgData);
381504
userInfoStore.setUserLoggedIn(true);
382505
383-
await setLocale(language)
506+
await setLocale(language);
384507
385508
nextTick(() => {
386509
toast.add({

0 commit comments

Comments
 (0)