import {useRef,useState} from "react" import {Text,View} from "react-native" import {useLocalSearchParams,useRouter} from "expo-router" import {useQueryClient} from "@tanstack/react-query" import * as Crypto from "expo-crypto" import {useSession} from "../../src/state/session" import {useAccounts} from "../../src/state/accounts" import {Body,Button,ErrorMessage,Field,Panel,Screen,Title,styles} from "../../src/components/ui" import type {Fill} from "../../src/lib/fills" export default function RecordFill(){ const params=useLocalSearchParams<{plan_id?:string;symbol?:string;exchange?:string;name?:string;side?:string}>(),router=useRouter(),cache=useQueryClient(),{client}=useSession(),{selected:account}=useAccounts() const [side,setSide]=useState(params.side==="SELL"?"SELL":"BUY"),[symbol,setSymbol]=useState(params.symbol??""),[exchange,setExchange]=useState(params.exchange??"SSE"),[name,setName]=useState(params.name??"") const [quantity,setQuantity]=useState(""),[price,setPrice]=useState(""),[fee,setFee]=useState(""),[occurred,setOccurred]=useState(()=>new Date().toISOString()),[sellable,setSellable]=useState(""),[note,setNote]=useState("") const [review,setReview]=useState(false),[busy,setBusy]=useState(false),[error,setError]=useState("") const pending=useRef<{account_id:string;idempotency_key:string;[key:string]:unknown}|null>(null) async function save(){if(!account)return;setBusy(true);setError("");try{ if(!pending.current)pending.current={account_id:account.id,plan_id:side==="BUY"&¶ms.plan_id?params.plan_id:null,idempotency_key:Crypto.randomUUID(),side,symbol,exchange,name,quantity,price,fee,occurred_at:new Date(occurred).toISOString(),sellable_at:side==="BUY"?new Date(sellable).toISOString():null,note} await client("/api/v1/fills",{method:"POST",body:pending.current});await Promise.all(["portfolio","fills","accounts","budget","plans"].map(key=>cache.invalidateQueries({queryKey:[key]})));router.replace("/(tabs)/portfolio") }catch(e){setError(e instanceof Error?e.message:"录入失败,请重试。")}finally{setBusy(false)}} async function check(){if(!pending.current)return;setBusy(true);setError("");try{const fills=await client(`/api/v1/accounts/${pending.current.account_id}/fills`);if(fills.some(f=>f.idempotency_key===pending.current!.idempotency_key)){await cache.invalidateQueries();router.replace("/(tabs)/portfolio")}else{pending.current=null;setReview(false)}}catch(e){setError(e instanceof Error?e.message:"暂时无法核对,请重试。")}finally{setBusy(false)}} const disabled=busy||!!pending.current return 记录模拟成交只记录已发生的模拟成交,不提交券商订单。当前使用手工设定的模拟可卖时间,不自动推断交易日或真实 T+1。当前账户:{account?.name??"未选择"}。成交录入按发生时间顺序;纠错采用冲正,原记录保留。{account?.mode!=="simulation"&&}