feat: 优化多语言文案接入并升级大厅与钱包交互体验
- 补充大厅下注结果、快速填单、查中奖、分页与通用操作多语言文案 - 移除多处界面默认文案回退,统一改用 i18n 配置输出 - 优化大厅快速填单、开奖结果入口与注单筛选区域视觉交互 - 重构钱包转入转出弹窗与流水卡片样式,增强金额与状态信息展示
This commit is contained in:
@@ -8,17 +8,17 @@ export function ticketStatusDisplay(
|
||||
): { label: string; dotClass: string; ring?: boolean } {
|
||||
const total = winMinor + jackpotMinor;
|
||||
if (status === "success") {
|
||||
return { label: t?.("ticketStatus.success") ?? "待开奖", dotClass: "bg-sky-500" };
|
||||
return { label: t?.("ticketStatus.success") ?? status, dotClass: "bg-sky-500" };
|
||||
}
|
||||
if (status === "pending_payout") {
|
||||
return { label: t?.("ticketStatus.pending_payout") ?? "已中奖待派彩", dotClass: "bg-amber-500" };
|
||||
return { label: t?.("ticketStatus.pending_payout") ?? status, dotClass: "bg-amber-500" };
|
||||
}
|
||||
if (status === "settled_win" && total > 0) {
|
||||
return { label: t?.("ticketStatus.settled_win") ?? "已派彩", dotClass: "bg-emerald-500" };
|
||||
return { label: t?.("ticketStatus.settled_win") ?? status, dotClass: "bg-emerald-500" };
|
||||
}
|
||||
if (status === "settled_lose" || status === "settled_win") {
|
||||
return {
|
||||
label: t?.("ticketStatus.settled_lose") ?? "未中奖",
|
||||
label: t?.("ticketStatus.settled_lose") ?? status,
|
||||
dotClass: "bg-background",
|
||||
ring: true,
|
||||
};
|
||||
|
||||
@@ -264,7 +264,7 @@ export function TicketOrderDetailScreen({ ticketNo }: { ticketNo: string }) {
|
||||
) : null}
|
||||
{!hasSettlement ? (
|
||||
<p className="rounded-lg border border-[#dce7f7] bg-[#f8fbff] px-3 py-2 text-xs text-[#32518d]">
|
||||
{t("orders.matchPendingSettlement", { defaultValue: "已开奖,等待系统结算后显示中奖结果。" })}
|
||||
{t("orders.matchPendingSettlement")}
|
||||
</p>
|
||||
) : null}
|
||||
</div>
|
||||
@@ -272,7 +272,7 @@ export function TicketOrderDetailScreen({ ticketNo }: { ticketNo: string }) {
|
||||
<div className="rounded-lg border border-[#dce7f7] bg-[#f8fbff] px-3 py-3 text-xs">
|
||||
<p className="font-bold text-[#0b3f96]">{t("orders.drawNumbers")}</p>
|
||||
<p className="mt-1 text-[#32518d]">
|
||||
{t("orders.drawPendingMatch", { defaultValue: "本期开奖号码尚未发布,暂不能判断是否中奖。" })}
|
||||
{t("orders.drawPendingMatch")}
|
||||
</p>
|
||||
</div>
|
||||
)}
|
||||
@@ -310,7 +310,7 @@ export function TicketOrderDetailScreen({ ticketNo }: { ticketNo: string }) {
|
||||
{matchResult && hasSettlement ? (
|
||||
<div className="rounded-lg border border-[#dce7f7] bg-[#f8fbff] px-3 py-3 text-xs">
|
||||
<p className="font-bold text-[#0b3f96]">
|
||||
{t("orders.matchResult", { defaultValue: "匹配结果" })}
|
||||
{t("orders.matchResult")}
|
||||
</p>
|
||||
<p className="mt-1 text-slate-600">
|
||||
{matchResult.matched
|
||||
@@ -332,7 +332,7 @@ export function TicketOrderDetailScreen({ ticketNo }: { ticketNo: string }) {
|
||||
{timeline.length > 0 ? (
|
||||
<div className="rounded-xl border border-[#e8eef7] bg-[#f8fbff] px-3 py-3">
|
||||
<p className="text-sm font-bold text-[#0b3f96]">
|
||||
{t("orders.timeline", { defaultValue: "时间线" })}
|
||||
{t("orders.timeline")}
|
||||
</p>
|
||||
<div className="mt-2 space-y-2">
|
||||
{timeline.map((row) => (
|
||||
|
||||
@@ -83,7 +83,7 @@ export function TicketOrdersListScreen() {
|
||||
}, []);
|
||||
|
||||
const dateLabel = useMemo(() => {
|
||||
if (!fromDate && !toDate) return t("orders.dateRange", { defaultValue: "日期范围" });
|
||||
if (!fromDate && !toDate) return t("orders.dateRange");
|
||||
if (fromDate && toDate) return `${formatCompactDate(fromDate)} ~ ${formatCompactDate(toDate)}`;
|
||||
return `${fromDate ? formatCompactDate(fromDate) : "..." } ~ ${toDate ? formatCompactDate(toDate) : "..."}`;
|
||||
}, [formatCompactDate, fromDate, t, toDate]);
|
||||
@@ -156,20 +156,20 @@ export function TicketOrdersListScreen() {
|
||||
containerClassName="max-w-[720px]"
|
||||
>
|
||||
<div className="space-y-4">
|
||||
<div className="rounded-xl border border-[#e6edf8] bg-white p-3 shadow-[0_8px_24px_rgba(15,23,42,0.04)] sm:p-4">
|
||||
<div className="flex flex-col gap-3 sm:flex-row sm:items-end sm:justify-between">
|
||||
<div className="rounded-2xl border border-[#dfe9f8] bg-white p-3 shadow-[0_10px_28px_rgba(15,23,42,0.05)] sm:p-4">
|
||||
<div className="flex items-center justify-between gap-3">
|
||||
<div className="min-w-0 flex-1">
|
||||
<p className="text-xs font-bold text-[#32518d]">
|
||||
<p className="text-[11px] font-black uppercase tracking-wide text-[#6f86ad]">
|
||||
{drawNoFilter ? t("orders.filteredIssue") : t("orders.totalRecords")}
|
||||
</p>
|
||||
<p className="mt-1 truncate font-mono text-lg font-black text-[#0b3f96]">
|
||||
<p className="mt-0.5 truncate font-mono text-2xl font-black leading-none text-[#0b3f96]">
|
||||
{drawNoFilter || total}
|
||||
</p>
|
||||
</div>
|
||||
<div className="flex shrink-0 items-center gap-2 self-start sm:self-auto">
|
||||
<div className="flex shrink-0 items-center gap-2">
|
||||
<Link
|
||||
href="/hall"
|
||||
className="inline-flex h-10 shrink-0 items-center rounded-full bg-[#e5002c] px-5 text-sm font-bold text-white"
|
||||
className="inline-flex h-9 shrink-0 items-center rounded-full bg-[#e5002c] px-5 text-sm font-black text-white shadow-[0_8px_18px_rgba(229,0,44,0.22)]"
|
||||
>
|
||||
{t("orders.betNow")}
|
||||
</Link>
|
||||
@@ -177,7 +177,7 @@ export function TicketOrdersListScreen() {
|
||||
<Button
|
||||
type="button"
|
||||
variant="outline"
|
||||
className="h-10 rounded-full border-[#dce7f7] bg-white px-4 text-sm font-semibold text-[#32518d] hover:bg-[#f8fbff]"
|
||||
className="h-9 rounded-full border-[#dce7f7] bg-white px-3 text-xs font-bold text-[#32518d] hover:bg-[#f8fbff]"
|
||||
onClick={() => {
|
||||
setQueryDrawNo(drawNoFilter);
|
||||
setQueryNumber("");
|
||||
@@ -194,25 +194,25 @@ export function TicketOrdersListScreen() {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="mt-4 grid grid-cols-1 gap-2 min-[420px]:grid-cols-2 lg:grid-cols-4">
|
||||
<div className="flex h-10 items-center rounded-full border border-[#dce7f7] bg-[#fbfdff] px-3">
|
||||
<div className="mt-3 grid grid-cols-2 gap-2 lg:grid-cols-4">
|
||||
<div className="flex h-9 min-w-0 items-center rounded-full border border-[#dce7f7] bg-[#fbfdff] px-3">
|
||||
<Input
|
||||
value={queryDrawNo}
|
||||
onChange={(e) => setQueryDrawNo(e.target.value)}
|
||||
placeholder={t("orders.drawNo")}
|
||||
aria-label={t("orders.drawNo")}
|
||||
className="h-8 border-0 bg-transparent px-0 text-sm shadow-none focus-visible:ring-0"
|
||||
className="h-7 border-0 bg-transparent px-0 text-sm shadow-none focus-visible:ring-0"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="flex h-10 items-center gap-2 rounded-full border border-[#dce7f7] bg-[#fbfdff] px-3">
|
||||
<div className="flex h-9 min-w-0 items-center gap-2 rounded-full border border-[#dce7f7] bg-[#fbfdff] px-3">
|
||||
<Search className="size-3.5 shrink-0 text-slate-400" />
|
||||
<Input
|
||||
value={queryNumber}
|
||||
onChange={(e) => setQueryNumber(e.target.value)}
|
||||
placeholder={t("orders.number")}
|
||||
aria-label={t("orders.number")}
|
||||
className="h-8 border-0 bg-transparent px-0 text-sm shadow-none focus-visible:ring-0"
|
||||
className="h-7 border-0 bg-transparent px-0 text-sm shadow-none focus-visible:ring-0"
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -222,7 +222,7 @@ export function TicketOrdersListScreen() {
|
||||
<Button
|
||||
type="button"
|
||||
variant="outline"
|
||||
className="h-10 w-full justify-start gap-2 rounded-full border-[#dce7f7] bg-[#fbfdff] px-3 text-left text-sm font-semibold text-[#32518d] hover:bg-white"
|
||||
className="h-9 w-full justify-start gap-2 rounded-full border-[#dce7f7] bg-[#fbfdff] px-3 text-left text-sm font-bold text-[#32518d] hover:bg-white"
|
||||
>
|
||||
<CalendarRange className="size-4 text-[#7890b8]" />
|
||||
<span className="truncate">{dateLabel}</span>
|
||||
@@ -256,10 +256,10 @@ export function TicketOrdersListScreen() {
|
||||
setToDate("");
|
||||
}}
|
||||
>
|
||||
清除
|
||||
{t("actions.clear")}
|
||||
</Button>
|
||||
<Button type="button" variant="secondary" size="xs" onClick={() => setRangeOpen(false)}>
|
||||
完成
|
||||
{t("actions.done")}
|
||||
</Button>
|
||||
</div>
|
||||
</PopoverContent>
|
||||
@@ -271,10 +271,10 @@ export function TicketOrdersListScreen() {
|
||||
<Button
|
||||
type="button"
|
||||
variant="outline"
|
||||
className="h-10 w-full justify-between gap-2 rounded-full border-[#dce7f7] bg-[#fbfdff] px-3 text-sm font-semibold text-[#32518d] hover:bg-white"
|
||||
className="h-9 w-full justify-between gap-2 rounded-full border-[#dce7f7] bg-[#fbfdff] px-3 text-sm font-bold text-[#32518d] hover:bg-white"
|
||||
>
|
||||
<span className="flex min-w-0 items-center gap-1.5">
|
||||
<span className="shrink-0">状态</span>
|
||||
<span className="shrink-0">{t("orders.status")}</span>
|
||||
{queryStatuses.length ? (
|
||||
<span className="inline-flex h-4 min-w-4 items-center justify-center rounded-full bg-[#0b56b7] px-1 text-[10px] font-black text-white">
|
||||
{queryStatuses.length}
|
||||
@@ -290,7 +290,7 @@ export function TicketOrdersListScreen() {
|
||||
<PopoverContent align="start" className="w-56 border-[#dce7f7] p-2 shadow-[0_16px_40px_rgba(15,23,42,0.14)]">
|
||||
<div className="space-y-1">
|
||||
<p className="px-1 pb-1 text-[11px] font-bold text-[#32518d]">
|
||||
{t("orders.statusFilter", { defaultValue: "状态筛选" })}
|
||||
{t("orders.statusFilter")}
|
||||
</p>
|
||||
{STATUS_OPTIONS.map((status) => {
|
||||
const checked = queryStatuses.includes(status);
|
||||
@@ -408,7 +408,7 @@ export function TicketOrdersListScreen() {
|
||||
disabled={loadingMore}
|
||||
onClick={() => void fetchPage(page + 1, true)}
|
||||
>
|
||||
{loadingMore ? t("actions.loading", { defaultValue: "加载中..." }) : t("actions.loadMore", { defaultValue: "加载更多" })}
|
||||
{loadingMore ? t("actions.loading") : t("actions.loadMore")}
|
||||
</Button>
|
||||
) : !isMobile && lastPage > 1 ? (
|
||||
<div className="flex flex-wrap items-center justify-center gap-2 rounded-xl border border-[#e6edf8] bg-white px-3 py-3">
|
||||
@@ -420,7 +420,7 @@ export function TicketOrdersListScreen() {
|
||||
disabled={loading || page <= 1}
|
||||
onClick={() => void fetchPage(Math.max(1, page - 1), false)}
|
||||
>
|
||||
{t("actions.previous", { defaultValue: "上一页" })}
|
||||
{t("actions.previous")}
|
||||
</Button>
|
||||
{visiblePages.map((p) => (
|
||||
<Button
|
||||
@@ -448,12 +448,12 @@ export function TicketOrdersListScreen() {
|
||||
disabled={loading || page >= lastPage}
|
||||
onClick={() => void fetchPage(Math.min(lastPage, page + 1), false)}
|
||||
>
|
||||
{t("actions.next", { defaultValue: "下一页" })}
|
||||
{t("actions.next")}
|
||||
</Button>
|
||||
</div>
|
||||
) : (
|
||||
<p className="py-2 text-center text-xs text-slate-400">
|
||||
{t("orders.noMore", { defaultValue: "没有更多注单" })}
|
||||
{t("orders.noMore")}
|
||||
</p>
|
||||
)}
|
||||
</>
|
||||
|
||||
Reference in New Issue
Block a user