fix(ui): 修复修改流水弹窗无回显问题,并锁定标的与类型字段防止篡改

This commit is contained in:
kennethcheng 2026-04-29 01:56:50 +08:00
parent 7c2f464f2c
commit eaeb143190
2 changed files with 57 additions and 3 deletions

View File

@ -389,6 +389,7 @@ export default function DashboardPage() {
<UpdateTransactionDialog <UpdateTransactionDialog
open={!!updateTarget} open={!!updateTarget}
onOpenChange={(open) => !open && setUpdateTarget(null)} onOpenChange={(open) => !open && setUpdateTarget(null)}
assets={assets}
transaction={updateTarget} transaction={updateTarget}
onSuccess={handleUpdateSubmit} onSuccess={handleUpdateSubmit}
/> />

View File

@ -1,6 +1,6 @@
'use client'; 'use client';
import { useState, useTransition } from 'react'; import { useState, useTransition, useEffect } from 'react';
import { useForm } from 'react-hook-form'; import { useForm } from 'react-hook-form';
import { zodResolver } from '@hookform/resolvers/zod'; import { zodResolver } from '@hookform/resolvers/zod';
import { z } from 'zod'; import { z } from 'zod';
@ -32,6 +32,20 @@ import { Button } from '@/components/ui/button';
import { toast } from 'sonner'; import { toast } from 'sonner';
import { updateTransaction } from '@/actions/transaction'; import { updateTransaction } from '@/actions/transaction';
const txTypeLabels: Record<string, string> = {
BUY: '买入 (BUY)',
SELL: '卖出 (SELL)',
DIVIDEND: '分红 (DIVIDEND)',
AIRDROP: '空投 (AIRDROP)',
FEE: '手续费 (FEE)',
};
interface Asset {
id: string;
symbol: string;
name: string | null;
}
const updateTransactionSchema = z.object({ const updateTransactionSchema = z.object({
quantity: z.string().regex(/^-?\d+(\.\d+)?$/, '数量必须是数字'), quantity: z.string().regex(/^-?\d+(\.\d+)?$/, '数量必须是数字'),
price: z.string().regex(/^-?\d+(\.\d+)?$/, '价格必须是数字'), price: z.string().regex(/^-?\d+(\.\d+)?$/, '价格必须是数字'),
@ -45,8 +59,10 @@ type UpdateForm = z.infer<typeof updateTransactionSchema>;
interface UpdateTransactionDialogProps { interface UpdateTransactionDialogProps {
open: boolean; open: boolean;
onOpenChange: (open: boolean) => void; onOpenChange: (open: boolean) => void;
assets?: Asset[];
transaction: { transaction: {
id: string; id: string;
assetId: string;
txType: string; txType: string;
quantity: string; quantity: string;
price: string; price: string;
@ -60,6 +76,7 @@ interface UpdateTransactionDialogProps {
export function UpdateTransactionDialog({ export function UpdateTransactionDialog({
open, open,
onOpenChange, onOpenChange,
assets,
transaction, transaction,
onSuccess, onSuccess,
}: UpdateTransactionDialogProps) { }: UpdateTransactionDialogProps) {
@ -76,7 +93,7 @@ export function UpdateTransactionDialog({
}, },
}); });
useState(() => { useEffect(() => {
if (transaction && open) { if (transaction && open) {
form.reset({ form.reset({
quantity: transaction.quantity.toString(), quantity: transaction.quantity.toString(),
@ -88,7 +105,7 @@ export function UpdateTransactionDialog({
: '', : '',
}); });
} }
}); }, [transaction, open, form]);
function handleSubmit(values: UpdateForm) { function handleSubmit(values: UpdateForm) {
if (!transaction) return; if (!transaction) return;
@ -120,6 +137,42 @@ export function UpdateTransactionDialog({
</DialogHeader> </DialogHeader>
<Form {...form}> <Form {...form}>
<form onSubmit={form.handleSubmit(handleSubmit)} className="space-y-4"> <form onSubmit={form.handleSubmit(handleSubmit)} className="space-y-4">
<div className="grid grid-cols-2 gap-4">
<FormItem>
<FormLabel></FormLabel>
<Select disabled>
<FormControl>
<SelectTrigger>
<SelectValue placeholder="选择资产" />
</SelectTrigger>
</FormControl>
<SelectContent>
{assets?.map((asset) => (
<SelectItem key={asset.id} value={asset.id}>
{asset.symbol}{asset.name ? ` (${asset.name})` : ''}
</SelectItem>
))}
</SelectContent>
</Select>
</FormItem>
<FormItem>
<FormLabel></FormLabel>
<Select disabled>
<FormControl>
<SelectTrigger>
<SelectValue placeholder="选择交易类型" />
</SelectTrigger>
</FormControl>
<SelectContent>
{Object.entries(txTypeLabels).map(([value, label]) => (
<SelectItem key={value} value={value}>
{label}
</SelectItem>
))}
</SelectContent>
</Select>
</FormItem>
</div>
<div className="grid grid-cols-2 gap-4"> <div className="grid grid-cols-2 gap-4">
<FormField <FormField
control={form.control} control={form.control}