Compare commits

..

4 Commits

Author SHA1 Message Date
shanshanzhong147 883ffab1a6 修复(#14): 调整 USDT 提现方式枚举口径 2026-06-09 03:30:57 -07:00
shanshanzhong147 3aae43f539 修复(#14): 支持 USDT 提现方式展示 2026-06-09 02:14:51 -07:00
shanshanzhong147 1834b97fe2 修复(#134): 促销前端展示对齐 (expires_at / billing 补 promo_discount / 类型补字段)
PR Check / Lint, Check, Test and Build (push) Has been cancelled
Squash merge of fix/134-促销前端展示对齐 (4702dee).

HIF-79/HIF-113 落地后前端有三处对齐缺失:

- promo-info.tsx 仍读 promo.end_time,但后端 SubscribeDiscountPromo
  JSON 字段是 expires_at(×2 处)
- billing.tsx 缺 Promo Discount 行,PreOrderResponse 拿到 promo_discount
  时无处可渲染
- typings.d.ts: SubscribeDiscountPromo 缺 expires_at/rule_type,
  PreOrderResponse 缺 promo_discount

本次仅修字段对齐与展示行,不动业务逻辑、不动 OrderDetail 类型 (后端
当前未透出 promo_discount)。新增 billing.promoDiscount 中英文文案。
2026-06-02 20:27:54 -07:00
shanshanzhong147 23f51a1ef4 修复(#122): 合并促销价档位提交到测试环境
PR Check / Lint, Check, Test and Build (push) Has been cancelled
2026-05-29 04:15:40 -07:00
7 changed files with 41 additions and 24 deletions
+2 -2
View File
@@ -44,7 +44,7 @@ const WITHDRAWAL_METHOD_MAP: Record<number, string> = {
0: "其他", 0: "其他",
1: "支付宝", 1: "支付宝",
2: "微信", 2: "微信",
3: "银行卡", 3: "USDT(TRC20)",
}; };
const rejectSchema = z.object({ const rejectSchema = z.object({
@@ -143,7 +143,7 @@ export default function WithdrawalPage() {
const methodOptions = [ const methodOptions = [
{ value: "1", label: "支付宝" }, { value: "1", label: "支付宝" },
{ value: "2", label: "微信" }, { value: "2", label: "微信" },
{ value: "3", label: "银行卡" }, { value: "3", label: "USDT(TRC20)" },
{ value: "0", label: "其他" }, { value: "0", label: "其他" },
]; ];
@@ -9,6 +9,7 @@
"originalPrice": "Original Price (Monthly)", "originalPrice": "Original Price (Monthly)",
"price": "Price", "price": "Price",
"productDiscount": "Product Discount", "productDiscount": "Product Discount",
"promoDiscount": "Promo Discount",
"total": "Total" "total": "Total"
}, },
"buy": "Buy", "buy": "Buy",
@@ -9,6 +9,7 @@
"originalPrice": "原价(按月)", "originalPrice": "原价(按月)",
"price": "价格", "price": "价格",
"productDiscount": "商品折扣", "productDiscount": "商品折扣",
"promoDiscount": "促销优惠",
"total": "总价" "total": "总价"
}, },
"buy": "购买", "buy": "购买",
@@ -10,6 +10,7 @@ interface SubscribeBillingProps {
unit_price: number; unit_price: number;
unit_time: string; unit_time: string;
subscribe_discount: number; subscribe_discount: number;
promo_discount: number;
show_original_price?: boolean; show_original_price?: boolean;
} }
>; >;
@@ -66,6 +67,14 @@ export function SubscribeBilling({ order }: Readonly<SubscribeBillingProps>) {
<Display type="currency" value={order?.discount} /> <Display type="currency" value={order?.discount} />
</span> </span>
</li> </li>
<li>
<span className="text-muted-foreground">
{t("billing.promoDiscount", "Promo Discount")}
</span>
<span>
<Display type="currency" value={order?.promo_discount} />
</span>
</li>
<li> <li>
<span className="text-muted-foreground"> <span className="text-muted-foreground">
{t("billing.couponDiscount", "Coupon Discount")} {t("billing.couponDiscount", "Coupon Discount")}
@@ -18,10 +18,10 @@ export function PromoInfo({ discount }: Readonly<PromoInfoProps>) {
<span className="font-medium"> <span className="font-medium">
{promo.rule_name || t("promo.available", "Promo Available")} {promo.rule_name || t("promo.available", "Promo Available")}
</span> </span>
{promo.end_time && ( {promo.expires_at && (
<span className="text-muted-foreground text-xs"> <span className="text-muted-foreground text-xs">
{t("promo.validUntil", "Valid until")}:{" "} {t("promo.validUntil", "Valid until")}:{" "}
{new Date(promo.end_time * 1000).toLocaleString()} {new Date(promo.expires_at * 1000).toLocaleString()}
</span> </span>
)} )}
</div> </div>
+23 -19
View File
@@ -63,7 +63,7 @@ import { useGlobalStore } from "@/stores/global";
const WITHDRAWAL_METHODS = [ const WITHDRAWAL_METHODS = [
{ value: 1, label: "支付宝" }, { value: 1, label: "支付宝" },
{ value: 2, label: "微信" }, { value: 2, label: "微信" },
{ value: 3, label: "银行卡" }, { value: 3, label: "USDT(TRC20)" },
{ value: 0, label: "其他" }, { value: 0, label: "其他" },
] as const; ] as const;
@@ -111,13 +111,21 @@ function QrCodeView({ url }: { url: string }) {
<img <img
alt="收款码" alt="收款码"
className="h-16 w-16 cursor-zoom-in object-cover" className="h-16 w-16 cursor-zoom-in object-cover"
height={64}
src={url} src={url}
width={64}
/> />
</button> </button>
{zoomOpen && ( {zoomOpen && (
<Dialog onOpenChange={setZoomOpen} open={zoomOpen}> <Dialog onOpenChange={setZoomOpen} open={zoomOpen}>
<DialogContent className="max-w-sm"> <DialogContent className="max-w-sm">
<img alt="收款码" className="w-full" src={url} /> <img
alt="收款码"
className="w-full"
height={320}
src={url}
width={320}
/>
</DialogContent> </DialogContent>
</Dialog> </Dialog>
)} )}
@@ -153,18 +161,16 @@ const withdrawalFormSchema = z
if (!data.account) { if (!data.account) {
ctx.addIssue({ ctx.addIssue({
code: z.ZodIssueCode.custom, code: z.ZodIssueCode.custom,
message: "银行卡收款账号为必填", message: "USDT(TRC20) 地址为必填",
path: ["account"],
});
}
} else if (data.method === 0) {
if (!data.account && !data.content) {
ctx.addIssue({
code: z.ZodIssueCode.custom,
message: "收款账号和备注至少填一项",
path: ["account"], path: ["account"],
}); });
} }
} else if (data.method === 0 && !(data.account || data.content)) {
ctx.addIssue({
code: z.ZodIssueCode.custom,
message: "收款账号和备注至少填一项",
path: ["account"],
});
} }
}); });
@@ -421,9 +427,7 @@ export default function Affiliate() {
<FormItem> <FormItem>
<FormLabel> <FormLabel>
<span className="ml-1 text-destructive"> <span className="ml-1 text-destructive">*</span>
*
</span>
</FormLabel> </FormLabel>
{watchedQrCodeUrl ? ( {watchedQrCodeUrl ? (
<div className="relative inline-block"> <div className="relative inline-block">
@@ -446,7 +450,9 @@ export default function Affiliate() {
returnType="file" returnType="file"
> >
<div className="flex h-24 w-24 flex-col items-center justify-center rounded border-2 border-dashed text-muted-foreground text-xs"> <div className="flex h-24 w-24 flex-col items-center justify-center rounded border-2 border-dashed text-muted-foreground text-xs">
{qrUploading ? "上传中..." : "点击上传\n收款码"} {qrUploading
? "上传中..."
: "点击上传\n收款码"}
</div> </div>
</UploadImage> </UploadImage>
)} )}
@@ -474,7 +480,7 @@ export default function Affiliate() {
<Input <Input
placeholder={ placeholder={
watchedMethod === 3 watchedMethod === 3
? "请输入银行卡号或账户信息" ? "请输入 USDT(TRC20) 收款地址"
: "请输入收款账号(与备注至少填一项)" : "请输入收款账号(与备注至少填一项)"
} }
{...field} {...field}
@@ -519,9 +525,7 @@ export default function Affiliate() {
</Button> </Button>
<Button <Button
disabled={ disabled={
submitting || submitting || qrUploading || availableCommission <= 0
qrUploading ||
availableCommission <= 0
} }
form="withdrawal-form" form="withdrawal-form"
type="submit" type="submit"
+3 -1
View File
@@ -548,6 +548,7 @@ declare namespace API {
price: number; price: number;
amount: number; amount: number;
discount: number; discount: number;
promo_discount: number;
gift_amount: number; gift_amount: number;
coupon: string; coupon: string;
coupon_discount: number; coupon_discount: number;
@@ -1024,8 +1025,9 @@ declare namespace API {
type SubscribeDiscountPromo = { type SubscribeDiscountPromo = {
rule_name?: string; rule_name?: string;
rule_type?: string;
promo_price: number; promo_price: number;
end_time?: number; expires_at?: number;
}; };
type SubscribeGroup = { type SubscribeGroup = {