From 0a8339a405209adb2c2dc85d8bd968adfd22e9f2 Mon Sep 17 00:00:00 2001 From: zhongming4762 Date: Wed, 22 Oct 2025 19:52:01 +0800 Subject: [PATCH 01/23] feat: increase support for multiple time zones --- apps/backend-mock/api/profile/timezone.ts | 7 ++ apps/backend-mock/api/user/setTimezone.ts | 14 +++ apps/backend-mock/api/user/timezone.ts | 12 +++ apps/backend-mock/utils/mock-data.ts | 31 +++++++ apps/backend-mock/utils/timezone-utils.ts | 10 +++ apps/web-antd/src/api/core/index.ts | 1 + apps/web-antd/src/api/core/user-profile.ts | 23 +++++ apps/web-antd/src/layouts/basic.vue | 40 ++++++++- apps/web-antd/src/store/index.ts | 1 + apps/web-antd/src/store/user-profile.ts | 56 ++++++++++++ apps/web-ele/src/api/core/index.ts | 1 + apps/web-ele/src/api/core/user-profile.ts | 23 +++++ apps/web-ele/src/layouts/basic.vue | 40 ++++++++- apps/web-ele/src/store/index.ts | 1 + apps/web-ele/src/store/user-profile.ts | 56 ++++++++++++ apps/web-naive/src/api/core/index.ts | 1 + apps/web-naive/src/api/core/user-profile.ts | 23 +++++ apps/web-naive/src/layouts/basic.vue | 41 ++++++++- apps/web-naive/src/store/index.ts | 1 + apps/web-naive/src/store/user-profile.ts | 56 ++++++++++++ packages/@core/base/shared/src/utils/date.ts | 23 ++++- packages/@core/base/typings/src/index.ts | 1 + .../@core/base/typings/src/user-profile.d.ts | 9 ++ packages/@core/preferences/src/config.ts | 1 + packages/@core/preferences/src/types.ts | 2 + .../layouts/src/basic/header/header.vue | 10 ++- packages/effects/layouts/src/basic/layout.vue | 3 + packages/effects/layouts/src/widgets/index.ts | 1 + .../layouts/src/widgets/timezone/index.ts | 1 + .../src/widgets/timezone/timezone-button.vue | 89 +++++++++++++++++++ packages/locales/src/langs/en-US/ui.json | 4 + packages/locales/src/langs/zh-CN/ui.json | 4 + 32 files changed, 577 insertions(+), 9 deletions(-) create mode 100644 apps/backend-mock/api/profile/timezone.ts create mode 100644 apps/backend-mock/api/user/setTimezone.ts create mode 100644 apps/backend-mock/api/user/timezone.ts create mode 100644 apps/backend-mock/utils/timezone-utils.ts create mode 100644 apps/web-antd/src/api/core/user-profile.ts create mode 100644 apps/web-antd/src/store/user-profile.ts create mode 100644 apps/web-ele/src/api/core/user-profile.ts create mode 100644 apps/web-ele/src/store/user-profile.ts create mode 100644 apps/web-naive/src/api/core/user-profile.ts create mode 100644 apps/web-naive/src/store/user-profile.ts create mode 100644 packages/@core/base/typings/src/user-profile.d.ts create mode 100644 packages/effects/layouts/src/widgets/timezone/index.ts create mode 100644 packages/effects/layouts/src/widgets/timezone/timezone-button.vue diff --git a/apps/backend-mock/api/profile/timezone.ts b/apps/backend-mock/api/profile/timezone.ts new file mode 100644 index 00000000..20b54ca8 --- /dev/null +++ b/apps/backend-mock/api/profile/timezone.ts @@ -0,0 +1,7 @@ +import { eventHandler } from 'h3'; +import { TIME_ZONE_OPTIONS } from '~/utils/mock-data'; +import { useResponseSuccess } from '~/utils/response'; + +export default eventHandler(() => { + return useResponseSuccess(TIME_ZONE_OPTIONS); +}); diff --git a/apps/backend-mock/api/user/setTimezone.ts b/apps/backend-mock/api/user/setTimezone.ts new file mode 100644 index 00000000..2265e3cb --- /dev/null +++ b/apps/backend-mock/api/user/setTimezone.ts @@ -0,0 +1,14 @@ +import { eventHandler, readBody } from 'h3'; +import { verifyAccessToken } from '~/utils/jwt-utils'; +import { unAuthorizedResponse, useResponseSuccess } from '~/utils/response'; +import { setTimezone } from '~/utils/timezone-utils'; + +export default eventHandler(async (event) => { + const userinfo = verifyAccessToken(event); + if (!userinfo) { + return unAuthorizedResponse(event); + } + const { timezone } = await readBody(event); + setTimezone(timezone); + return useResponseSuccess(); +}); diff --git a/apps/backend-mock/api/user/timezone.ts b/apps/backend-mock/api/user/timezone.ts new file mode 100644 index 00000000..0cbcb6ec --- /dev/null +++ b/apps/backend-mock/api/user/timezone.ts @@ -0,0 +1,12 @@ +import { eventHandler } from 'h3'; +import { verifyAccessToken } from '~/utils/jwt-utils'; +import { unAuthorizedResponse, useResponseSuccess } from '~/utils/response'; +import { getTimezone } from '~/utils/timezone-utils'; + +export default eventHandler((event) => { + const userinfo = verifyAccessToken(event); + if (!userinfo) { + return unAuthorizedResponse(event); + } + return useResponseSuccess(getTimezone()); +}); diff --git a/apps/backend-mock/utils/mock-data.ts b/apps/backend-mock/utils/mock-data.ts index 192f30a0..5c534437 100644 --- a/apps/backend-mock/utils/mock-data.ts +++ b/apps/backend-mock/utils/mock-data.ts @@ -7,6 +7,11 @@ export interface UserInfo { homePath?: string; } +export interface TimeZoneOption { + offset: number; + timeZone: string; +} + export const MOCK_USERS: UserInfo[] = [ { id: 0, @@ -388,3 +393,29 @@ export function getMenuIds(menus: any[]) { }); return ids; } + +/** + * 时区选项 + */ +export const TIME_ZONE_OPTIONS: TimeZoneOption[] = [ + { + offset: -5, + timezone: 'America/New_York', + }, + { + offset: 0, + timezone: 'Europe/London', + }, + { + offset: 8, + timezone: 'Asia/Shanghai', + }, + { + offset: 9, + timezone: 'Asia/Tokyo', + }, + { + offset: 9, + timezone: 'Asia/Seoul', + }, +]; diff --git a/apps/backend-mock/utils/timezone-utils.ts b/apps/backend-mock/utils/timezone-utils.ts new file mode 100644 index 00000000..87d244ad --- /dev/null +++ b/apps/backend-mock/utils/timezone-utils.ts @@ -0,0 +1,10 @@ +let mockTimeZone: null | string = null; + +export const setTimezone = (timeZone: string) => { + mockTimeZone = timeZone; +}; + +export const getTimezone = () => { + console.log('mockTimeZone', mockTimeZone); + return mockTimeZone; +}; diff --git a/apps/web-antd/src/api/core/index.ts b/apps/web-antd/src/api/core/index.ts index 28a5aef4..e5d52a40 100644 --- a/apps/web-antd/src/api/core/index.ts +++ b/apps/web-antd/src/api/core/index.ts @@ -1,3 +1,4 @@ export * from './auth'; export * from './menu'; export * from './user'; +export * from './user-profile'; diff --git a/apps/web-antd/src/api/core/user-profile.ts b/apps/web-antd/src/api/core/user-profile.ts new file mode 100644 index 00000000..eefa9ab7 --- /dev/null +++ b/apps/web-antd/src/api/core/user-profile.ts @@ -0,0 +1,23 @@ +import type { TimezoneOption } from '@vben/types'; + +import { requestClient } from '#/api/request'; + +/** + * 获取系统支持的时区列表 + */ +export async function getTimezoneOptionsApi() { + return requestClient.get('/profile/timezone'); +} +/** + * 获取用户时区 + */ +export async function getUserTimezoneApi(): Promise { + return requestClient.get('/user/timezone'); +} +/** + * 设置用户时区 + * @param timezone 时区 + */ +export async function setUserTimezoneApi(timezone: string) { + return requestClient.post('/user/setTimezone', { timezone }); +} diff --git a/apps/web-antd/src/layouts/basic.vue b/apps/web-antd/src/layouts/basic.vue index 805b8a73..37c5ec26 100644 --- a/apps/web-antd/src/layouts/basic.vue +++ b/apps/web-antd/src/layouts/basic.vue @@ -1,7 +1,8 @@ + + + + diff --git a/packages/locales/src/langs/en-US/ui.json b/packages/locales/src/langs/en-US/ui.json index 0179c225..f920ee33 100644 --- a/packages/locales/src/langs/en-US/ui.json +++ b/packages/locales/src/langs/en-US/ui.json @@ -102,6 +102,10 @@ "errorPasswordTip": "Password error, please re-enter", "backToLogin": "Back to login", "entry": "Enter the system" + }, + "timezone": { + "setTimezone": "Set Timezone", + "setSuccess": "Timezone set successfully" } } } diff --git a/packages/locales/src/langs/zh-CN/ui.json b/packages/locales/src/langs/zh-CN/ui.json index da2dbeb0..3433bcb5 100644 --- a/packages/locales/src/langs/zh-CN/ui.json +++ b/packages/locales/src/langs/zh-CN/ui.json @@ -102,6 +102,10 @@ "errorPasswordTip": "密码错误,请重新输入", "backToLogin": "返回登录", "entry": "进入系统" + }, + "timezone": { + "setTimezone": "设置时区", + "setSuccess": "时区设置成功" } } } From b029f77b6ad3295b91056dc91dc3b43b339ba4fd Mon Sep 17 00:00:00 2001 From: zhongming4762 Date: Wed, 22 Oct 2025 20:18:25 +0800 Subject: [PATCH 02/23] feat: increase support for multiple time zones --- apps/backend-mock/utils/timezone-utils.ts | 1 - apps/web-antd/src/layouts/basic.vue | 9 ++++++--- apps/web-antd/src/store/user-profile.ts | 4 ++-- apps/web-ele/src/layouts/basic.vue | 9 ++++++--- apps/web-ele/src/store/user-profile.ts | 4 ++-- apps/web-naive/src/layouts/basic.vue | 9 ++++++--- apps/web-naive/src/store/user-profile.ts | 4 ++-- .../__tests__/__snapshots__/config.test.ts.snap | 3 +++ .../layouts/src/widgets/timezone/timezone-button.vue | 10 +++++----- packages/effects/plugins/src/echarts/use-echarts.ts | 2 +- 10 files changed, 33 insertions(+), 22 deletions(-) diff --git a/apps/backend-mock/utils/timezone-utils.ts b/apps/backend-mock/utils/timezone-utils.ts index 87d244ad..da35f920 100644 --- a/apps/backend-mock/utils/timezone-utils.ts +++ b/apps/backend-mock/utils/timezone-utils.ts @@ -5,6 +5,5 @@ export const setTimezone = (timeZone: string) => { }; export const getTimezone = () => { - console.log('mockTimeZone', mockTimeZone); return mockTimeZone; }; diff --git a/apps/web-antd/src/layouts/basic.vue b/apps/web-antd/src/layouts/basic.vue index 37c5ec26..742378f9 100644 --- a/apps/web-antd/src/layouts/basic.vue +++ b/apps/web-antd/src/layouts/basic.vue @@ -2,7 +2,7 @@ import type { ExtendedModalApi } from '@vben/common-ui'; import type { NotificationItem } from '@vben/layouts'; -import { computed, onMounted, ref, watch } from 'vue'; +import { computed, onMounted, ref, unref, watch } from 'vue'; import { AuthenticationLoginExpiredModal } from '@vben/common-ui'; import { VBEN_DOC_URL, VBEN_GITHUB_URL } from '@vben/constants'; @@ -66,7 +66,7 @@ const showDot = computed(() => ); const userProfileStore = useUserProfileStore(); -const computedTimezone = computed(() => userProfileStore.timezone); +const computedTimezone = computed(() => unref(userProfileStore.timezone)); const timezoneOptions = ref([]); onMounted(async () => { @@ -75,9 +75,12 @@ onMounted(async () => { ); }); const handleSetTimezone = async ( - timezone: string, modalApi: ExtendedModalApi, + timezone?: string, ) => { + if (!timezone) { + return; + } try { modalApi.setState({ confirmLoading: true }); await userProfileStore.setTimezone(timezone); diff --git a/apps/web-antd/src/store/user-profile.ts b/apps/web-antd/src/store/user-profile.ts index 02cb5b4a..0fd21569 100644 --- a/apps/web-antd/src/store/user-profile.ts +++ b/apps/web-antd/src/store/user-profile.ts @@ -17,11 +17,11 @@ const useUserProfileStore = defineStore('user-profile', () => { * @param timezone 时区字符串 */ async function setTimezone(timezone: string) { + // 保存用户的时区设置 + await setUserTimezoneApi(timezone); timezoneRef.value = timezone; // 设置dayjs默认时区 setDefaultTimezone(timezone); - // 保存用户的时区设置 - await setUserTimezoneApi(timezone); } /** diff --git a/apps/web-ele/src/layouts/basic.vue b/apps/web-ele/src/layouts/basic.vue index 6f775b91..5a9984f4 100644 --- a/apps/web-ele/src/layouts/basic.vue +++ b/apps/web-ele/src/layouts/basic.vue @@ -2,7 +2,7 @@ import type { ExtendedModalApi } from '@vben/common-ui'; import type { NotificationItem } from '@vben/layouts'; -import { computed, onMounted, ref, watch } from 'vue'; +import { computed, onMounted, ref, unref, watch } from 'vue'; import { AuthenticationLoginExpiredModal } from '@vben/common-ui'; import { VBEN_DOC_URL, VBEN_GITHUB_URL } from '@vben/constants'; @@ -66,7 +66,7 @@ const showDot = computed(() => ); const userProfileStore = useUserProfileStore(); -const computedTimezone = computed(() => userProfileStore.timezone); +const computedTimezone = computed(() => unref(userProfileStore.timezone)); const timezoneOptions = ref([]); onMounted(async () => { @@ -75,9 +75,12 @@ onMounted(async () => { ); }); const handleSetTimezone = async ( - timezone: string, modalApi: ExtendedModalApi, + timezone?: string, ) => { + if (!timezone) { + return; + } try { modalApi.setState({ confirmLoading: true }); await userProfileStore.setTimezone(timezone); diff --git a/apps/web-ele/src/store/user-profile.ts b/apps/web-ele/src/store/user-profile.ts index 02cb5b4a..0fd21569 100644 --- a/apps/web-ele/src/store/user-profile.ts +++ b/apps/web-ele/src/store/user-profile.ts @@ -17,11 +17,11 @@ const useUserProfileStore = defineStore('user-profile', () => { * @param timezone 时区字符串 */ async function setTimezone(timezone: string) { + // 保存用户的时区设置 + await setUserTimezoneApi(timezone); timezoneRef.value = timezone; // 设置dayjs默认时区 setDefaultTimezone(timezone); - // 保存用户的时区设置 - await setUserTimezoneApi(timezone); } /** diff --git a/apps/web-naive/src/layouts/basic.vue b/apps/web-naive/src/layouts/basic.vue index cac3e7de..f2afcdbb 100644 --- a/apps/web-naive/src/layouts/basic.vue +++ b/apps/web-naive/src/layouts/basic.vue @@ -2,7 +2,7 @@ import type { ExtendedModalApi } from '@vben/common-ui'; import type { NotificationItem } from '@vben/layouts'; -import { computed, onMounted, ref, watch } from 'vue'; +import { computed, onMounted, ref, unref, watch } from 'vue'; import { AuthenticationLoginExpiredModal } from '@vben/common-ui'; import { VBEN_DOC_URL, VBEN_GITHUB_URL } from '@vben/constants'; @@ -67,7 +67,7 @@ const showDot = computed(() => ); const userProfileStore = useUserProfileStore(); -const computedTimezone = computed(() => userProfileStore.timezone); +const computedTimezone = computed(() => unref(userProfileStore.timezone)); const timezoneOptions = ref([]); onMounted(async () => { @@ -76,9 +76,12 @@ onMounted(async () => { ); }); const handleSetTimezone = async ( - timezone: string, modalApi: ExtendedModalApi, + timezone?: string, ) => { + if (!timezone) { + return; + } try { modalApi.setState({ confirmLoading: true }); await userProfileStore.setTimezone(timezone); diff --git a/apps/web-naive/src/store/user-profile.ts b/apps/web-naive/src/store/user-profile.ts index 02cb5b4a..0fd21569 100644 --- a/apps/web-naive/src/store/user-profile.ts +++ b/apps/web-naive/src/store/user-profile.ts @@ -17,11 +17,11 @@ const useUserProfileStore = defineStore('user-profile', () => { * @param timezone 时区字符串 */ async function setTimezone(timezone: string) { + // 保存用户的时区设置 + await setUserTimezoneApi(timezone); timezoneRef.value = timezone; // 设置dayjs默认时区 setDefaultTimezone(timezone); - // 保存用户的时区设置 - await setUserTimezoneApi(timezone); } /** diff --git a/packages/@core/preferences/__tests__/__snapshots__/config.test.ts.snap b/packages/@core/preferences/__tests__/__snapshots__/config.test.ts.snap index 1cccbbb2..a6452b39 100644 --- a/packages/@core/preferences/__tests__/__snapshots__/config.test.ts.snap +++ b/packages/@core/preferences/__tests__/__snapshots__/config.test.ts.snap @@ -22,6 +22,7 @@ exports[`defaultPreferences immutability test > should not modify the config obj "enableCheckUpdates": true, "enablePreferences": true, "enableRefreshToken": false, + "enableStickyPreferencesNavigationBar": true, "isMobile": false, "layout": "sidebar-nav", "locale": "zh-CN", @@ -29,6 +30,7 @@ exports[`defaultPreferences immutability test > should not modify the config obj "name": "Vben Admin", "preferencesButtonPosition": "auto", "watermark": false, + "watermarkContent": "", "zIndex": 200, }, "breadcrumb": { @@ -131,6 +133,7 @@ exports[`defaultPreferences immutability test > should not modify the config obj "refresh": true, "sidebarToggle": true, "themeToggle": true, + "timezone": true, }, } `; diff --git a/packages/effects/layouts/src/widgets/timezone/timezone-button.vue b/packages/effects/layouts/src/widgets/timezone/timezone-button.vue index cc2fd3fe..dae20dd7 100644 --- a/packages/effects/layouts/src/widgets/timezone/timezone-button.vue +++ b/packages/effects/layouts/src/widgets/timezone/timezone-button.vue @@ -16,8 +16,8 @@ import { interface Props { timezoneOptions: string[]; okHandler?: ( - timezone: string, - modalApi: ExtendedModalApi, + modalApi?: ExtendedModalApi, + timezone?: string, ) => Promise | void; timezone?: string; } @@ -34,7 +34,7 @@ const TimezoneIcon = createIconifyIcon('fluent-mdl2:world-clock'); const [Modal, modalApi] = useVbenModal({ fullscreenButton: false, onConfirm: () => { - props.okHandler?.(unref(timezoneValue), modalApi); + props.okHandler?.(modalApi, unref(timezoneValue)); }, }); @@ -42,11 +42,11 @@ const handleClick = () => { modalApi.open(); }; -const timezoneValue = ref(props.timezone); +const timezoneValue = ref(unref(props.timezone)); watch( () => props.timezone, (newTimezone) => { - timezoneValue.value = newTimezone; + timezoneValue.value = unref(newTimezone); }, ); const handleClickItem = (timezone: string) => { diff --git a/packages/effects/plugins/src/echarts/use-echarts.ts b/packages/effects/plugins/src/echarts/use-echarts.ts index b5ff6d42..1a28fb12 100644 --- a/packages/effects/plugins/src/echarts/use-echarts.ts +++ b/packages/effects/plugins/src/echarts/use-echarts.ts @@ -69,7 +69,7 @@ function useEcharts(chartRef: Ref) { const renderEcharts = ( options: EChartsOption, - clear = true + clear = true, ): Promise> => { cacheOptions = options; const currentOptions = { From 61ce53b6868dc232eb489f4480c23a8707ba92cc Mon Sep 17 00:00:00 2001 From: zhongming4762 Date: Wed, 22 Oct 2025 20:23:55 +0800 Subject: [PATCH 03/23] feat: increase support for multiple time zones --- .../effects/layouts/src/widgets/timezone/timezone-button.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/effects/layouts/src/widgets/timezone/timezone-button.vue b/packages/effects/layouts/src/widgets/timezone/timezone-button.vue index dae20dd7..4b2a56e0 100644 --- a/packages/effects/layouts/src/widgets/timezone/timezone-button.vue +++ b/packages/effects/layouts/src/widgets/timezone/timezone-button.vue @@ -16,7 +16,7 @@ import { interface Props { timezoneOptions: string[]; okHandler?: ( - modalApi?: ExtendedModalApi, + modalApi: ExtendedModalApi, timezone?: string, ) => Promise | void; timezone?: string; From e3e5755903637255db62cfd5015d38aebb7cc40c Mon Sep 17 00:00:00 2001 From: zhongming4762 Date: Wed, 22 Oct 2025 20:29:53 +0800 Subject: [PATCH 04/23] feat: increase support for multiple time zones --- .../layouts/src/widgets/timezone/timezone-button.vue | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/packages/effects/layouts/src/widgets/timezone/timezone-button.vue b/packages/effects/layouts/src/widgets/timezone/timezone-button.vue index 4b2a56e0..11798ed5 100644 --- a/packages/effects/layouts/src/widgets/timezone/timezone-button.vue +++ b/packages/effects/layouts/src/widgets/timezone/timezone-button.vue @@ -22,12 +22,8 @@ interface Props { timezone?: string; } -interface Listener { - change: (timezone: string) => void; -} - const props = defineProps(); -const emit = defineEmits(); +const emit = defineEmits<{ change: [string] }>(); const TimezoneIcon = createIconifyIcon('fluent-mdl2:world-clock'); From e01803ce9d54e30ca6606757e827fa436de4d09a Mon Sep 17 00:00:00 2001 From: zhongming4762 Date: Wed, 22 Oct 2025 20:39:00 +0800 Subject: [PATCH 05/23] feat: increase support for multiple time zones --- apps/web-antd/src/store/user-profile.ts | 4 +++- apps/web-ele/src/store/user-profile.ts | 4 +++- apps/web-naive/src/store/user-profile.ts | 4 +++- .../effects/layouts/src/widgets/timezone/timezone-button.vue | 4 ++-- 4 files changed, 11 insertions(+), 5 deletions(-) diff --git a/apps/web-antd/src/store/user-profile.ts b/apps/web-antd/src/store/user-profile.ts index 0fd21569..6c552e4f 100644 --- a/apps/web-antd/src/store/user-profile.ts +++ b/apps/web-antd/src/store/user-profile.ts @@ -38,7 +38,9 @@ const useUserProfileStore = defineStore('user-profile', () => { } } - initTimezone(); + initTimezone().catch((error) => { + console.error('Failed to initialize timezone during store setup:', error); + }); return { timezone: timezoneRef, diff --git a/apps/web-ele/src/store/user-profile.ts b/apps/web-ele/src/store/user-profile.ts index 0fd21569..6c552e4f 100644 --- a/apps/web-ele/src/store/user-profile.ts +++ b/apps/web-ele/src/store/user-profile.ts @@ -38,7 +38,9 @@ const useUserProfileStore = defineStore('user-profile', () => { } } - initTimezone(); + initTimezone().catch((error) => { + console.error('Failed to initialize timezone during store setup:', error); + }); return { timezone: timezoneRef, diff --git a/apps/web-naive/src/store/user-profile.ts b/apps/web-naive/src/store/user-profile.ts index 0fd21569..6c552e4f 100644 --- a/apps/web-naive/src/store/user-profile.ts +++ b/apps/web-naive/src/store/user-profile.ts @@ -38,7 +38,9 @@ const useUserProfileStore = defineStore('user-profile', () => { } } - initTimezone(); + initTimezone().catch((error) => { + console.error('Failed to initialize timezone during store setup:', error); + }); return { timezone: timezoneRef, diff --git a/packages/effects/layouts/src/widgets/timezone/timezone-button.vue b/packages/effects/layouts/src/widgets/timezone/timezone-button.vue index 11798ed5..5a1c8318 100644 --- a/packages/effects/layouts/src/widgets/timezone/timezone-button.vue +++ b/packages/effects/layouts/src/widgets/timezone/timezone-button.vue @@ -70,7 +70,7 @@ const handleClickItem = (timezone: string) => { @click="handleClickItem(item)" > - + @@ -79,7 +79,7 @@ const handleClickItem = (timezone: string) => { From 6b6cdef42d41a4fbaafeb8095f10dce56f864c89 Mon Sep 17 00:00:00 2001 From: Jin Mao Date: Sun, 26 Oct 2025 15:00:47 +0800 Subject: [PATCH 06/23] =?UTF-8?q?chore:=20=E4=B8=80=E4=BA=9B=E8=B0=83?= =?UTF-8?q?=E6=95=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../preferences/__tests__/__snapshots__/config.test.ts.snap | 2 ++ packages/@core/preferences/src/config.ts | 3 ++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/packages/@core/preferences/__tests__/__snapshots__/config.test.ts.snap b/packages/@core/preferences/__tests__/__snapshots__/config.test.ts.snap index 1cccbbb2..b3f15980 100644 --- a/packages/@core/preferences/__tests__/__snapshots__/config.test.ts.snap +++ b/packages/@core/preferences/__tests__/__snapshots__/config.test.ts.snap @@ -22,6 +22,7 @@ exports[`defaultPreferences immutability test > should not modify the config obj "enableCheckUpdates": true, "enablePreferences": true, "enableRefreshToken": false, + "enableStickyPreferencesNavigationBar": true, "isMobile": false, "layout": "sidebar-nav", "locale": "zh-CN", @@ -29,6 +30,7 @@ exports[`defaultPreferences immutability test > should not modify the config obj "name": "Vben Admin", "preferencesButtonPosition": "auto", "watermark": false, + "watermarkContent": "", "zIndex": 200, }, "breadcrumb": { diff --git a/packages/@core/preferences/src/config.ts b/packages/@core/preferences/src/config.ts index b8b7212a..f6c1c2b7 100644 --- a/packages/@core/preferences/src/config.ts +++ b/packages/@core/preferences/src/config.ts @@ -1,4 +1,4 @@ -import type { Preferences } from './types'; +import type { Preferences } from "./types"; const defaultPreferences: Preferences = { app: { @@ -32,6 +32,7 @@ const defaultPreferences: Preferences = { watermark: false, watermarkContent: '', zIndex: 200, + }, breadcrumb: { enable: true, From 0e62862119e6956677c1b2070cb9f25e67e4344c Mon Sep 17 00:00:00 2001 From: Jin Mao Date: Sun, 26 Oct 2025 15:01:58 +0800 Subject: [PATCH 07/23] chore: fix lint --- .../plugins/src/echarts/use-echarts.ts | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/packages/effects/plugins/src/echarts/use-echarts.ts b/packages/effects/plugins/src/echarts/use-echarts.ts index b5ff6d42..22a791a2 100644 --- a/packages/effects/plugins/src/echarts/use-echarts.ts +++ b/packages/effects/plugins/src/echarts/use-echarts.ts @@ -1,24 +1,23 @@ -import type { EChartsOption } from 'echarts'; +import type { EChartsOption } from "echarts"; -import type { Ref } from 'vue'; +import type { Ref } from "vue"; +import { computed, nextTick, watch } from "vue"; -import type { Nullable } from '@vben/types'; +import type { Nullable } from "@vben/types"; -import type EchartsUI from './echarts-ui.vue'; +import type EchartsUI from "./echarts-ui.vue"; -import { computed, nextTick, watch } from 'vue'; - -import { usePreferences } from '@vben/preferences'; +import { usePreferences } from "@vben/preferences"; import { tryOnUnmounted, useDebounceFn, useResizeObserver, useTimeoutFn, - useWindowSize, -} from '@vueuse/core'; + useWindowSize +} from "@vueuse/core"; -import echarts from './echarts'; +import echarts from "./echarts"; type EchartsUIType = typeof EchartsUI | undefined; From cfbce0d7379566f19d899604671041d3941868ad Mon Sep 17 00:00:00 2001 From: Jin Mao Date: Sun, 26 Oct 2025 15:27:28 +0800 Subject: [PATCH 08/23] chore: fix lint --- packages/@core/preferences/src/config.ts | 3 +-- .../plugins/src/echarts/use-echarts.ts | 21 ++++++++++--------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/packages/@core/preferences/src/config.ts b/packages/@core/preferences/src/config.ts index f6c1c2b7..b8b7212a 100644 --- a/packages/@core/preferences/src/config.ts +++ b/packages/@core/preferences/src/config.ts @@ -1,4 +1,4 @@ -import type { Preferences } from "./types"; +import type { Preferences } from './types'; const defaultPreferences: Preferences = { app: { @@ -32,7 +32,6 @@ const defaultPreferences: Preferences = { watermark: false, watermarkContent: '', zIndex: 200, - }, breadcrumb: { enable: true, diff --git a/packages/effects/plugins/src/echarts/use-echarts.ts b/packages/effects/plugins/src/echarts/use-echarts.ts index 22a791a2..1a28fb12 100644 --- a/packages/effects/plugins/src/echarts/use-echarts.ts +++ b/packages/effects/plugins/src/echarts/use-echarts.ts @@ -1,23 +1,24 @@ -import type { EChartsOption } from "echarts"; +import type { EChartsOption } from 'echarts'; -import type { Ref } from "vue"; -import { computed, nextTick, watch } from "vue"; +import type { Ref } from 'vue'; -import type { Nullable } from "@vben/types"; +import type { Nullable } from '@vben/types'; -import type EchartsUI from "./echarts-ui.vue"; +import type EchartsUI from './echarts-ui.vue'; -import { usePreferences } from "@vben/preferences"; +import { computed, nextTick, watch } from 'vue'; + +import { usePreferences } from '@vben/preferences'; import { tryOnUnmounted, useDebounceFn, useResizeObserver, useTimeoutFn, - useWindowSize -} from "@vueuse/core"; + useWindowSize, +} from '@vueuse/core'; -import echarts from "./echarts"; +import echarts from './echarts'; type EchartsUIType = typeof EchartsUI | undefined; @@ -68,7 +69,7 @@ function useEcharts(chartRef: Ref) { const renderEcharts = ( options: EChartsOption, - clear = true + clear = true, ): Promise> => { cacheOptions = options; const currentOptions = { From 4d713db546c832da452dfe8455614de5f43ff49e Mon Sep 17 00:00:00 2001 From: zhongming4762 Date: Wed, 29 Oct 2025 19:47:10 +0800 Subject: [PATCH 09/23] feat: increase support for multiple time zones MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * 优化实现方法 --- .../timezone.ts => timezone/getTimezone.ts} | 0 .../getTimezoneOptions.ts} | 0 .../api/{user => timezone}/setTimezone.ts | 2 +- apps/backend-mock/utils/mock-data.ts | 4 +- apps/web-antd/src/api/core/index.ts | 1 - apps/web-antd/src/api/core/user-profile.ts | 23 ---- apps/web-antd/src/layouts/basic.vue | 43 +----- apps/web-antd/src/store/index.ts | 1 - apps/web-antd/src/store/user-profile.ts | 58 -------- apps/web-ele/src/api/core/index.ts | 1 - apps/web-ele/src/api/core/user-profile.ts | 23 ---- apps/web-ele/src/layouts/basic.vue | 43 +----- apps/web-ele/src/store/index.ts | 1 - apps/web-ele/src/store/user-profile.ts | 58 -------- apps/web-naive/src/api/core/index.ts | 1 - apps/web-naive/src/api/core/user-profile.ts | 23 ---- apps/web-naive/src/layouts/basic.vue | 44 +----- apps/web-naive/src/store/index.ts | 1 - apps/web-naive/src/store/user-profile.ts | 58 -------- packages/@core/base/typings/src/app.d.ts | 10 ++ packages/@core/base/typings/src/index.ts | 1 - .../@core/base/typings/src/user-profile.d.ts | 9 -- packages/@core/preferences/src/constants.ts | 35 ++++- .../layouts/src/basic/header/header.vue | 4 + .../src/widgets/timezone/timezone-button.vue | 71 +++++----- packages/stores/src/modules/index.ts | 1 + packages/stores/src/modules/timezone.ts | 125 ++++++++++++++++++ playground/src/api/core/index.ts | 1 + playground/src/api/core/timezone.ts | 30 +++++ playground/src/bootstrap.ts | 4 + playground/src/timezone-init.ts | 20 +++ 31 files changed, 273 insertions(+), 423 deletions(-) rename apps/backend-mock/api/{user/timezone.ts => timezone/getTimezone.ts} (100%) rename apps/backend-mock/api/{profile/timezone.ts => timezone/getTimezoneOptions.ts} (100%) rename apps/backend-mock/api/{user => timezone}/setTimezone.ts (93%) delete mode 100644 apps/web-antd/src/api/core/user-profile.ts delete mode 100644 apps/web-antd/src/store/user-profile.ts delete mode 100644 apps/web-ele/src/api/core/user-profile.ts delete mode 100644 apps/web-ele/src/store/user-profile.ts delete mode 100644 apps/web-naive/src/api/core/user-profile.ts delete mode 100644 apps/web-naive/src/store/user-profile.ts delete mode 100644 packages/@core/base/typings/src/user-profile.d.ts create mode 100644 packages/stores/src/modules/timezone.ts create mode 100644 playground/src/api/core/timezone.ts create mode 100644 playground/src/timezone-init.ts diff --git a/apps/backend-mock/api/user/timezone.ts b/apps/backend-mock/api/timezone/getTimezone.ts similarity index 100% rename from apps/backend-mock/api/user/timezone.ts rename to apps/backend-mock/api/timezone/getTimezone.ts diff --git a/apps/backend-mock/api/profile/timezone.ts b/apps/backend-mock/api/timezone/getTimezoneOptions.ts similarity index 100% rename from apps/backend-mock/api/profile/timezone.ts rename to apps/backend-mock/api/timezone/getTimezoneOptions.ts diff --git a/apps/backend-mock/api/user/setTimezone.ts b/apps/backend-mock/api/timezone/setTimezone.ts similarity index 93% rename from apps/backend-mock/api/user/setTimezone.ts rename to apps/backend-mock/api/timezone/setTimezone.ts index 2265e3cb..9ec00a50 100644 --- a/apps/backend-mock/api/user/setTimezone.ts +++ b/apps/backend-mock/api/timezone/setTimezone.ts @@ -10,5 +10,5 @@ export default eventHandler(async (event) => { } const { timezone } = await readBody(event); setTimezone(timezone); - return useResponseSuccess(); + return useResponseSuccess({}); }); diff --git a/apps/backend-mock/utils/mock-data.ts b/apps/backend-mock/utils/mock-data.ts index 5c534437..54cfa506 100644 --- a/apps/backend-mock/utils/mock-data.ts +++ b/apps/backend-mock/utils/mock-data.ts @@ -7,7 +7,7 @@ export interface UserInfo { homePath?: string; } -export interface TimeZoneOption { +export interface TimezoneOption { offset: number; timeZone: string; } @@ -397,7 +397,7 @@ export function getMenuIds(menus: any[]) { /** * 时区选项 */ -export const TIME_ZONE_OPTIONS: TimeZoneOption[] = [ +export const TIME_ZONE_OPTIONS: TimezoneOption[] = [ { offset: -5, timezone: 'America/New_York', diff --git a/apps/web-antd/src/api/core/index.ts b/apps/web-antd/src/api/core/index.ts index e5d52a40..28a5aef4 100644 --- a/apps/web-antd/src/api/core/index.ts +++ b/apps/web-antd/src/api/core/index.ts @@ -1,4 +1,3 @@ export * from './auth'; export * from './menu'; export * from './user'; -export * from './user-profile'; diff --git a/apps/web-antd/src/api/core/user-profile.ts b/apps/web-antd/src/api/core/user-profile.ts deleted file mode 100644 index eefa9ab7..00000000 --- a/apps/web-antd/src/api/core/user-profile.ts +++ /dev/null @@ -1,23 +0,0 @@ -import type { TimezoneOption } from '@vben/types'; - -import { requestClient } from '#/api/request'; - -/** - * 获取系统支持的时区列表 - */ -export async function getTimezoneOptionsApi() { - return requestClient.get('/profile/timezone'); -} -/** - * 获取用户时区 - */ -export async function getUserTimezoneApi(): Promise { - return requestClient.get('/user/timezone'); -} -/** - * 设置用户时区 - * @param timezone 时区 - */ -export async function setUserTimezoneApi(timezone: string) { - return requestClient.post('/user/setTimezone', { timezone }); -} diff --git a/apps/web-antd/src/layouts/basic.vue b/apps/web-antd/src/layouts/basic.vue index 742378f9..805b8a73 100644 --- a/apps/web-antd/src/layouts/basic.vue +++ b/apps/web-antd/src/layouts/basic.vue @@ -1,8 +1,7 @@