From 0a8339a405209adb2c2dc85d8bd968adfd22e9f2 Mon Sep 17 00:00:00 2001 From: zhongming4762 Date: Wed, 22 Oct 2025 19:52:01 +0800 Subject: [PATCH] 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": "时区设置成功" } } }