重构报销详情证据与动作区(reimbursement-detail-evidence-actions)

这个提交包含在:
2026-05-30 03:29:07 +08:00
父节点 65a8f64b92
当前提交 cb03f2b63d
共修改 9 个文件,包含 434 行新增和 446 行删除
@@ -1,63 +1,38 @@
import { useState } from "react";
import type { ReimbursementStatus } from "../../api/reimbursements";
import { Button } from "../../components/ui/button";
import { Input } from "../../components/ui/input";
import { Textarea } from "../../components/ui/textarea";
type PaymentChannel = "bank" | "alipay" | "wechat" | "cash" | "other";
function todayDateString() {
return new Date().toISOString().slice(0, 10);
}
export type PayPayload = {
paymentVoucherNo: string;
paymentDate: string;
paymentChannel: PaymentChannel;
paymentNote: string;
};
export interface ReimbursementActionsProps {
status: ReimbursementStatus;
canPay: boolean;
actionError: string;
submitDisabled?: boolean;
submitHint?: string;
submitNotice?: string;
showSubmitAction?: boolean;
showWithdrawAction?: boolean;
showPayAction?: boolean;
isPending: boolean;
onSubmit: () => void;
onWithdraw: (comment: string) => void;
onPay: (payload: PayPayload) => void;
}
export function ReimbursementActions({
status,
canPay,
actionError,
submitDisabled = false,
submitHint = "",
submitNotice = "",
showSubmitAction = true,
showWithdrawAction = true,
showPayAction = true,
isPending,
onSubmit,
onWithdraw,
onPay,
}: ReimbursementActionsProps) {
const [withdrawComment, setWithdrawComment] = useState("申请撤回并补充说明后重提");
const [paymentVoucherNo, setPaymentVoucherNo] = useState("");
const [paymentDate, setPaymentDate] = useState(todayDateString);
const [paymentChannel, setPaymentChannel] = useState<PaymentChannel>("bank");
const [paymentNote, setPaymentNote] = useState("");
const canShowSubmit = showSubmitAction && ["draft", "rejected"].includes(status);
const canShowWithdraw = showWithdrawAction && status === "reviewing";
const canShowPay = showPayAction && canPay && status === "approved";
if (!canShowSubmit && !canShowWithdraw && !canShowPay && !actionError && !submitHint && !submitNotice) {
if (!canShowSubmit && !canShowWithdraw && !actionError && !submitHint && !submitNotice) {
return null;
}
@@ -113,61 +88,6 @@ export function ReimbursementActions({
</Button>
</div>
) : null}
{canShowPay ? (
<div className="space-y-2 rounded-lg border border-zinc-200 p-4">
<p className="text-sm font-medium text-zinc-800">财务支付</p>
<Input
data-testid="reimbursement-pay-voucher-no"
onChange={(event) => setPaymentVoucherNo(event.target.value)}
placeholder="付款凭证号"
value={paymentVoucherNo}
/>
<Input
data-testid="reimbursement-pay-date"
onChange={(event) => setPaymentDate(event.target.value)}
type="date"
value={paymentDate}
/>
<select
className="select-std"
data-testid="reimbursement-pay-channel"
onChange={(event) =>
setPaymentChannel(event.target.value as PaymentChannel)
}
value={paymentChannel}
>
<option value="bank">银行转账</option>
<option value="alipay">支付宝</option>
<option value="wechat">微信</option>
<option value="cash">现金</option>
<option value="other">其他</option>
</select>
<Textarea
data-testid="reimbursement-pay-note"
onChange={(event) => setPaymentNote(event.target.value)}
placeholder="付款备注(可选,用于审计留痕)"
rows={2}
value={paymentNote}
/>
<Button
data-testid="reimbursement-pay"
variant="secondary"
disabled={isPending}
onClick={() =>
onPay({
paymentVoucherNo: paymentVoucherNo.trim(),
paymentDate,
paymentChannel,
paymentNote: paymentNote.trim(),
})
}
type="button"
>
执行支付
</Button>
</div>
) : null}
</div>
);
}