128 行
4.1 KiB
TypeScript
128 行
4.1 KiB
TypeScript
import { useEffect, useState } from "react";
|
|
import type { TravelPaymentChannel, TravelPaymentOrder } from "../../api/travelPayments";
|
|
import {
|
|
Dialog,
|
|
DialogContent,
|
|
DialogDescription,
|
|
DialogFooter,
|
|
DialogHeader,
|
|
DialogTitle,
|
|
} from "../ui/dialog";
|
|
import { Button } from "../ui/button";
|
|
import { Input } from "../ui/input";
|
|
import { Label } from "../ui/label";
|
|
|
|
const PAYMENT_CHANNEL_OPTIONS: Array<{ value: TravelPaymentChannel; label: string }> = [
|
|
{ value: "bank_transfer", label: "银行转账" },
|
|
{ value: "corporate_card", label: "企业卡" },
|
|
{ value: "virtual_card", label: "虚拟卡" },
|
|
{ value: "manual", label: "手工录入" },
|
|
{ value: "other", label: "其他" },
|
|
];
|
|
|
|
export type TravelOrderMarkPaidDialogProps = {
|
|
open: boolean;
|
|
order: TravelPaymentOrder | null;
|
|
pending?: boolean;
|
|
onOpenChange: (open: boolean) => void;
|
|
onConfirm: (payload: {
|
|
paymentVoucherNo: string | null;
|
|
paymentDate: string | null;
|
|
paymentChannel: TravelPaymentChannel | null;
|
|
}) => void;
|
|
};
|
|
|
|
export function TravelOrderMarkPaidDialog({
|
|
open,
|
|
order,
|
|
pending = false,
|
|
onOpenChange,
|
|
onConfirm,
|
|
}: TravelOrderMarkPaidDialogProps) {
|
|
const [paymentVoucherNo, setPaymentVoucherNo] = useState("");
|
|
const [paymentDate, setPaymentDate] = useState("");
|
|
const [paymentChannel, setPaymentChannel] = useState<TravelPaymentChannel | "">("bank_transfer");
|
|
|
|
useEffect(() => {
|
|
if (!open) {
|
|
return;
|
|
}
|
|
setPaymentVoucherNo(order?.paymentVoucherNo ?? "");
|
|
setPaymentDate(order?.paymentDate ?? "");
|
|
setPaymentChannel((order?.paymentChannel as TravelPaymentChannel | null) ?? "bank_transfer");
|
|
}, [open, order]);
|
|
|
|
return (
|
|
<Dialog open={open} onOpenChange={onOpenChange}>
|
|
<DialogContent>
|
|
<DialogHeader>
|
|
<DialogTitle>标记差旅订单已支付</DialogTitle>
|
|
<DialogDescription>
|
|
确认订单 `{order?.externalOrderNo ?? "-"}` 已完成对公支付;系统会按幂等键复用现有财务交接记录。
|
|
</DialogDescription>
|
|
</DialogHeader>
|
|
|
|
<div className="space-y-4">
|
|
<div className="grid gap-4 md:grid-cols-2">
|
|
<div>
|
|
<Label htmlFor="travel-order-payment-voucher">付款凭证号</Label>
|
|
<Input
|
|
id="travel-order-payment-voucher"
|
|
className="mt-1"
|
|
placeholder="可留空"
|
|
value={paymentVoucherNo}
|
|
onChange={(event) => setPaymentVoucherNo(event.target.value)}
|
|
/>
|
|
</div>
|
|
<div>
|
|
<Label htmlFor="travel-order-payment-date">付款日期</Label>
|
|
<Input
|
|
id="travel-order-payment-date"
|
|
className="mt-1"
|
|
type="date"
|
|
value={paymentDate}
|
|
onChange={(event) => setPaymentDate(event.target.value)}
|
|
/>
|
|
</div>
|
|
</div>
|
|
|
|
<div>
|
|
<Label htmlFor="travel-order-payment-channel">付款渠道</Label>
|
|
<select
|
|
id="travel-order-payment-channel"
|
|
className="select-std mt-1"
|
|
value={paymentChannel}
|
|
onChange={(event) => setPaymentChannel(event.target.value as TravelPaymentChannel | "")}
|
|
>
|
|
{PAYMENT_CHANNEL_OPTIONS.map((item) => (
|
|
<option key={item.value} value={item.value}>
|
|
{item.label}
|
|
</option>
|
|
))}
|
|
</select>
|
|
</div>
|
|
</div>
|
|
|
|
<DialogFooter>
|
|
<Button type="button" variant="secondary" onClick={() => onOpenChange(false)} disabled={pending}>
|
|
取消
|
|
</Button>
|
|
<Button
|
|
type="button"
|
|
onClick={() =>
|
|
onConfirm({
|
|
paymentVoucherNo: paymentVoucherNo.trim() || null,
|
|
paymentDate: paymentDate || null,
|
|
paymentChannel: paymentChannel || null,
|
|
})
|
|
}
|
|
disabled={pending}
|
|
>
|
|
{pending ? "提交中..." : "确认已支付"}
|
|
</Button>
|
|
</DialogFooter>
|
|
</DialogContent>
|
|
</Dialog>
|
|
);
|
|
}
|