refactor: 使用管理员日期时间格式化器更新请求和完成时间的显示
This commit is contained in:
21
src/hooks/use-admin-datetime-formatter.ts
Normal file
21
src/hooks/use-admin-datetime-formatter.ts
Normal file
@@ -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(),
|
||||
}),
|
||||
[],
|
||||
);
|
||||
}
|
||||
36
src/lib/admin-datetime.ts
Normal file
36
src/lib/admin-datetime.ts
Normal file
@@ -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}`;
|
||||
}
|
||||
@@ -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<AdminTransferOrderListData | null>(null);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [err, setErr] = useState<string | null>(null);
|
||||
@@ -324,8 +321,12 @@ function TransferOrdersPanel(): React.ReactElement {
|
||||
<TableHead className="w-14">方向</TableHead>
|
||||
<TableHead className="whitespace-nowrap">金额</TableHead>
|
||||
<TableHead className="whitespace-nowrap">状态</TableHead>
|
||||
<TableHead className="whitespace-nowrap">请求时间</TableHead>
|
||||
<TableHead className="whitespace-nowrap">完成时间</TableHead>
|
||||
<TableHead className="min-w-0 whitespace-normal leading-tight">
|
||||
请求时间
|
||||
</TableHead>
|
||||
<TableHead className="min-w-0 whitespace-normal leading-tight">
|
||||
完成时间
|
||||
</TableHead>
|
||||
<TableHead className="w-24">操作</TableHead>
|
||||
</TableRow>
|
||||
</TableHeader>
|
||||
@@ -359,10 +360,10 @@ function TransferOrdersPanel(): React.ReactElement {
|
||||
<TableCell>
|
||||
<Badge variant={statusBadgeVariant(row.status)}>{row.status}</Badge>
|
||||
</TableCell>
|
||||
<TableCell className="whitespace-nowrap text-xs text-muted-foreground">
|
||||
<TableCell className="min-w-0 whitespace-normal font-mono text-[11px] leading-snug text-muted-foreground">
|
||||
{formatTs(row.created_at)}
|
||||
</TableCell>
|
||||
<TableCell className="whitespace-nowrap text-xs text-muted-foreground">
|
||||
<TableCell className="min-w-0 whitespace-normal font-mono text-[11px] leading-snug text-muted-foreground">
|
||||
{formatTs(row.finished_at)}
|
||||
</TableCell>
|
||||
<TableCell className="text-xs text-muted-foreground">—</TableCell>
|
||||
@@ -406,6 +407,7 @@ function TransferOrdersPanel(): React.ReactElement {
|
||||
}
|
||||
|
||||
function WalletTxnsPanel(): React.ReactElement {
|
||||
const formatTs = useAdminDateTimeFormatter();
|
||||
const [data, setData] = useState<AdminWalletTxnListData | null>(null);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [err, setErr] = useState<string | null>(null);
|
||||
@@ -576,8 +578,12 @@ function WalletTxnsPanel(): React.ReactElement {
|
||||
<TableHead className="whitespace-nowrap">类型</TableHead>
|
||||
<TableHead className="whitespace-nowrap">金额</TableHead>
|
||||
<TableHead className="whitespace-nowrap">状态</TableHead>
|
||||
<TableHead className="whitespace-nowrap">请求时间</TableHead>
|
||||
<TableHead className="whitespace-nowrap">完成时间</TableHead>
|
||||
<TableHead className="min-w-0 whitespace-normal leading-tight">
|
||||
请求时间
|
||||
</TableHead>
|
||||
<TableHead className="min-w-0 whitespace-normal leading-tight">
|
||||
完成时间
|
||||
</TableHead>
|
||||
<TableHead className="w-24">操作</TableHead>
|
||||
</TableRow>
|
||||
</TableHeader>
|
||||
@@ -611,10 +617,10 @@ function WalletTxnsPanel(): React.ReactElement {
|
||||
<TableCell>
|
||||
<Badge variant={statusBadgeVariant(row.status)}>{row.status}</Badge>
|
||||
</TableCell>
|
||||
<TableCell className="whitespace-nowrap text-xs text-muted-foreground">
|
||||
<TableCell className="min-w-0 whitespace-normal font-mono text-[11px] leading-snug text-muted-foreground">
|
||||
{formatTs(row.created_at)}
|
||||
</TableCell>
|
||||
<TableCell className="whitespace-nowrap text-xs text-muted-foreground">
|
||||
<TableCell className="min-w-0 whitespace-normal font-mono text-[11px] leading-snug text-muted-foreground">
|
||||
{formatTs(row.updated_at)}
|
||||
</TableCell>
|
||||
<TableCell className="text-xs text-muted-foreground">—</TableCell>
|
||||
|
||||
Reference in New Issue
Block a user