fix: resolve the issue of logout failure caused by the timezone store
This commit is contained in:
parent
ac6de0324c
commit
565be77e96
143
packages/@core/base/shared/src/utils/__tests__/date.test.ts
Normal file
143
packages/@core/base/shared/src/utils/__tests__/date.test.ts
Normal file
@ -0,0 +1,143 @@
|
||||
import dayjs from 'dayjs';
|
||||
import timezone from 'dayjs/plugin/timezone';
|
||||
import utc from 'dayjs/plugin/utc';
|
||||
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
|
||||
|
||||
import {
|
||||
formatDate,
|
||||
formatDateTime,
|
||||
getCurrentTimezone,
|
||||
getSystemTimezone,
|
||||
isDate,
|
||||
isDayjsObject,
|
||||
setCurrentTimezone,
|
||||
} from '../date';
|
||||
|
||||
dayjs.extend(utc);
|
||||
dayjs.extend(timezone);
|
||||
|
||||
describe('dateUtils', () => {
|
||||
const sampleISO = '2024-10-30T12:34:56Z';
|
||||
const sampleTimestamp = Date.parse(sampleISO);
|
||||
|
||||
beforeEach(() => {
|
||||
// 重置时区
|
||||
dayjs.tz.setDefault();
|
||||
setCurrentTimezone(); // 重置为系统默认
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
vi.restoreAllMocks();
|
||||
});
|
||||
|
||||
// ===============================
|
||||
// formatDate
|
||||
// ===============================
|
||||
describe('formatDate', () => {
|
||||
it('should format a valid ISO date string', () => {
|
||||
const formatted = formatDate(sampleISO, 'YYYY/MM/DD');
|
||||
expect(formatted).toMatch(/2024\/10\/30/);
|
||||
});
|
||||
|
||||
it('should format a timestamp correctly', () => {
|
||||
const formatted = formatDate(sampleTimestamp);
|
||||
expect(formatted).toMatch(/2024-10-30/);
|
||||
});
|
||||
|
||||
it('should format a Date object', () => {
|
||||
const formatted = formatDate(new Date(sampleISO));
|
||||
expect(formatted).toMatch(/2024-10-30/);
|
||||
});
|
||||
|
||||
it('should format a dayjs object', () => {
|
||||
const formatted = formatDate(dayjs(sampleISO));
|
||||
expect(formatted).toMatch(/2024-10-30/);
|
||||
});
|
||||
|
||||
it('should return original input if date is invalid', () => {
|
||||
const invalid = 'not-a-date';
|
||||
const spy = vi.spyOn(console, 'error').mockImplementation(() => {});
|
||||
const formatted = formatDate(invalid);
|
||||
expect(formatted).toBe(invalid);
|
||||
expect(spy).toHaveBeenCalledOnce();
|
||||
});
|
||||
|
||||
it('should apply given format', () => {
|
||||
const formatted = formatDate(sampleISO, 'YYYY-MM-DD HH:mm');
|
||||
expect(formatted).toMatch(/\d{4}-\d{2}-\d{2} \d{2}:\d{2}/);
|
||||
});
|
||||
});
|
||||
|
||||
// ===============================
|
||||
// formatDateTime
|
||||
// ===============================
|
||||
describe('formatDateTime', () => {
|
||||
it('should format date into full datetime', () => {
|
||||
const result = formatDateTime(sampleISO);
|
||||
expect(result).toMatch(/2024-10-30 \d{2}:\d{2}:\d{2}/);
|
||||
});
|
||||
});
|
||||
|
||||
// ===============================
|
||||
// isDate
|
||||
// ===============================
|
||||
describe('isDate', () => {
|
||||
it('should return true for Date instances', () => {
|
||||
expect(isDate(new Date())).toBe(true);
|
||||
});
|
||||
|
||||
it('should return false for non-Date values', () => {
|
||||
expect(isDate('2024-10-30')).toBe(false);
|
||||
expect(isDate(null)).toBe(false);
|
||||
expect(isDate(undefined)).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
// ===============================
|
||||
// isDayjsObject
|
||||
// ===============================
|
||||
describe('isDayjsObject', () => {
|
||||
it('should return true for dayjs objects', () => {
|
||||
expect(isDayjsObject(dayjs())).toBe(true);
|
||||
});
|
||||
|
||||
it('should return false for other values', () => {
|
||||
expect(isDayjsObject(new Date())).toBe(false);
|
||||
expect(isDayjsObject('string')).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
// ===============================
|
||||
// getSystemTimezone
|
||||
// ===============================
|
||||
describe('getSystemTimezone', () => {
|
||||
it('should return a valid IANA timezone string', () => {
|
||||
const tz = getSystemTimezone();
|
||||
expect(typeof tz).toBe('string');
|
||||
expect(tz).toMatch(/^[A-Z]+\/[A-Z_]+/i);
|
||||
});
|
||||
});
|
||||
|
||||
// ===============================
|
||||
// setCurrentTimezone / getCurrentTimezone
|
||||
// ===============================
|
||||
describe('setCurrentTimezone & getCurrentTimezone', () => {
|
||||
it('should set and retrieve the current timezone', () => {
|
||||
setCurrentTimezone('Asia/Shanghai');
|
||||
expect(getCurrentTimezone()).toBe('Asia/Shanghai');
|
||||
});
|
||||
|
||||
it('should reset to system timezone when called with no args', () => {
|
||||
const guessed = getSystemTimezone();
|
||||
setCurrentTimezone();
|
||||
expect(getCurrentTimezone()).toBe(guessed);
|
||||
});
|
||||
|
||||
it('should update dayjs default timezone', () => {
|
||||
setCurrentTimezone('America/New_York');
|
||||
const d = dayjs('2024-01-01T00:00:00Z');
|
||||
// 校验时区转换生效(小时变化)
|
||||
expect(d.tz().format('HH')).not.toBe('00');
|
||||
});
|
||||
});
|
||||
});
|
||||
@ -5,9 +5,11 @@ import utc from 'dayjs/plugin/utc';
|
||||
dayjs.extend(utc);
|
||||
dayjs.extend(timezone);
|
||||
|
||||
export function formatDate(time: number | string, format = 'YYYY-MM-DD') {
|
||||
type FormatDate = Date | dayjs.Dayjs | number | string;
|
||||
|
||||
export function formatDate(time: FormatDate, format = 'YYYY-MM-DD') {
|
||||
try {
|
||||
const date = dayjs(time);
|
||||
const date = dayjs.isDayjs(time) ? time : dayjs(time);
|
||||
if (!date.isValid()) {
|
||||
throw new Error('Invalid date');
|
||||
}
|
||||
@ -18,7 +20,7 @@ export function formatDate(time: number | string, format = 'YYYY-MM-DD') {
|
||||
}
|
||||
}
|
||||
|
||||
export function formatDateTime(time: number | string) {
|
||||
export function formatDateTime(time: FormatDate) {
|
||||
return formatDate(time, 'YYYY-MM-DD HH:mm:ss');
|
||||
}
|
||||
|
||||
@ -30,18 +32,32 @@ export function isDayjsObject(value: any): value is dayjs.Dayjs {
|
||||
return dayjs.isDayjs(value);
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置默认时区
|
||||
* @param timezone
|
||||
*/
|
||||
export const setDefaultTimezone = (timezone?: string) => {
|
||||
timezone ? dayjs.tz.setDefault(timezone) : dayjs.tz.setDefault();
|
||||
};
|
||||
|
||||
/**
|
||||
* 获取当前时区
|
||||
* @returns 当前时区
|
||||
*/
|
||||
export const getTimezone = () => {
|
||||
export const getSystemTimezone = () => {
|
||||
return dayjs.tz.guess();
|
||||
};
|
||||
|
||||
/**
|
||||
* 自定义设置的时区
|
||||
*/
|
||||
let currentTimezone = getSystemTimezone();
|
||||
|
||||
/**
|
||||
* 设置默认时区
|
||||
* @param timezone
|
||||
*/
|
||||
export const setCurrentTimezone = (timezone?: string) => {
|
||||
currentTimezone = timezone || getSystemTimezone();
|
||||
dayjs.tz.setDefault(currentTimezone);
|
||||
};
|
||||
|
||||
/**
|
||||
* 获取设置的时区
|
||||
* @returns 设置的时区
|
||||
*/
|
||||
export const getCurrentTimezone = () => {
|
||||
return currentTimezone;
|
||||
};
|
||||
|
||||
@ -1,7 +1,10 @@
|
||||
import { ref, unref } from 'vue';
|
||||
|
||||
import { DEFAULT_TIME_ZONE_OPTIONS } from '@vben-core/preferences';
|
||||
import { getTimezone, setDefaultTimezone } from '@vben-core/shared/utils';
|
||||
import {
|
||||
getCurrentTimezone,
|
||||
setCurrentTimezone,
|
||||
} from '@vben-core/shared/utils';
|
||||
|
||||
import { acceptHMRUpdate, defineStore } from 'pinia';
|
||||
|
||||
@ -59,9 +62,7 @@ const getTimezoneHandler = () => {
|
||||
const useTimezoneStore = defineStore(
|
||||
'core-timezone',
|
||||
() => {
|
||||
const timezoneRef = ref(
|
||||
getTimezone() || new Intl.DateTimeFormat().resolvedOptions().timeZone,
|
||||
);
|
||||
const timezoneRef = ref(getCurrentTimezone());
|
||||
|
||||
/**
|
||||
* 初始化时区
|
||||
@ -74,7 +75,7 @@ const useTimezoneStore = defineStore(
|
||||
timezoneRef.value = timezone;
|
||||
}
|
||||
// 设置dayjs默认时区
|
||||
setDefaultTimezone(unref(timezoneRef));
|
||||
setCurrentTimezone(unref(timezoneRef));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -87,7 +88,7 @@ const useTimezoneStore = defineStore(
|
||||
await timezoneHandler.setTimezone?.(timezone);
|
||||
timezoneRef.value = timezone;
|
||||
// 设置dayjs默认时区
|
||||
setDefaultTimezone(timezone);
|
||||
setCurrentTimezone(timezone);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -103,10 +104,15 @@ const useTimezoneStore = defineStore(
|
||||
console.error('Failed to initialize timezone during store setup:', error);
|
||||
});
|
||||
|
||||
function $reset() {
|
||||
timezoneRef.value = getCurrentTimezone();
|
||||
}
|
||||
|
||||
return {
|
||||
timezone: timezoneRef,
|
||||
setTimezone,
|
||||
getTimezoneOptions,
|
||||
$reset,
|
||||
};
|
||||
},
|
||||
{
|
||||
|
||||
Loading…
Reference in New Issue
Block a user