diff --git a/src/hooks/use-admin-datetime-formatter.ts b/src/hooks/use-admin-datetime-formatter.ts new file mode 100644 index 0000000..d26bea6 --- /dev/null +++ b/src/hooks/use-admin-datetime-formatter.ts @@ -0,0 +1,21 @@ +"use client"; + +import { useCallback } from "react"; + +import { formatAdminInstant } from "@/lib/admin-datetime"; +import { getAdminRequestLocale } from "@/lib/admin-locale"; + +/** + * 按当前界面语言 + **浏览器本地时区** 格式化时间。 + */ +export function useAdminDateTimeFormatter(): ( + iso: string | null | undefined, +) => string { + return useCallback( + (iso) => + formatAdminInstant(iso, { + locale: getAdminRequestLocale(), + }), + [], + ); +} diff --git a/src/lib/admin-datetime.ts b/src/lib/admin-datetime.ts new file mode 100644 index 0000000..aa3ad78 --- /dev/null +++ b/src/lib/admin-datetime.ts @@ -0,0 +1,36 @@ +import type { AdminApiLocale } from "@/lib/admin-locale"; + +function pad2(n: number): string { + return String(n).padStart(2, "0"); +} + +/** + * 将接口返回的 ISO 时间串格式化为 **浏览器本地时区** 下的 + * `YYYY-MM-DD HH:mm:ss`(与《01-界面文档》时间展示习惯一致,且列宽稳定)。 + * + * 不使用 `Intl` 拼接 `GMT+8` 等时区后缀,避免在表格里挤出过长、重叠的字符串。 + * + * `@param options.locale` 与调用方保持一致,便于日后按界面语言微调格式。 + */ +export function formatAdminInstant( + iso: string | null | undefined, + _options: { + locale: AdminApiLocale; + }, +): string { + if (iso == null || iso === "") { + return "—"; + } + const ms = Date.parse(iso); + if (Number.isNaN(ms)) { + return "—"; + } + const date = new Date(ms); + const y = date.getFullYear(); + const m = pad2(date.getMonth() + 1); + const d = pad2(date.getDate()); + const h = pad2(date.getHours()); + const min = pad2(date.getMinutes()); + const s = pad2(date.getSeconds()); + return `${y}-${m}-${d} ${h}:${min}:${s}`; +} diff --git a/src/modules/wallet/wallet-console.tsx b/src/modules/wallet/wallet-console.tsx index 357baad..0c4e0c4 100644 --- a/src/modules/wallet/wallet-console.tsx +++ b/src/modules/wallet/wallet-console.tsx @@ -24,6 +24,7 @@ import { TableRow, } from "@/components/ui/table"; import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"; +import { useAdminDateTimeFormatter } from "@/hooks/use-admin-datetime-formatter"; import { LotteryApiBizError } from "@/types/api/errors"; import type { AdminPlayerWalletsData, @@ -36,11 +37,6 @@ function formatMinorUnits(minor: number, currencyCode: string): string { return `${major.toFixed(2)} ${currencyCode}`; } -function formatTs(iso: string | null | undefined): string { - if (!iso) return "—"; - return iso.replace("T", " ").slice(0, 19); -} - /** 长单号/流水号:单行截断;点击复制全文,悬停可看全文 */ function CellMonoId({ value, @@ -164,6 +160,7 @@ export function WalletConsole(): React.ReactElement { } function TransferOrdersPanel(): React.ReactElement { + const formatTs = useAdminDateTimeFormatter(); const [data, setData] = useState(null); const [loading, setLoading] = useState(true); const [err, setErr] = useState(null); @@ -324,8 +321,12 @@ function TransferOrdersPanel(): React.ReactElement { 方向 金额 状态 - 请求时间 - 完成时间 + + 请求时间 + + + 完成时间 + 操作 @@ -359,10 +360,10 @@ function TransferOrdersPanel(): React.ReactElement { {row.status} - + {formatTs(row.created_at)} - + {formatTs(row.finished_at)} @@ -406,6 +407,7 @@ function TransferOrdersPanel(): React.ReactElement { } function WalletTxnsPanel(): React.ReactElement { + const formatTs = useAdminDateTimeFormatter(); const [data, setData] = useState(null); const [loading, setLoading] = useState(true); const [err, setErr] = useState(null); @@ -576,8 +578,12 @@ function WalletTxnsPanel(): React.ReactElement { 类型 金额 状态 - 请求时间 - 完成时间 + + 请求时间 + + + 完成时间 + 操作 @@ -611,10 +617,10 @@ function WalletTxnsPanel(): React.ReactElement { {row.status} - + {formatTs(row.created_at)} - + {formatTs(row.updated_at)}