diff --git a/src/api/types.ts b/src/api/types.ts index a4e1203..bcf29ad 100644 --- a/src/api/types.ts +++ b/src/api/types.ts @@ -1410,6 +1410,10 @@ export interface OutputCustomSettlementApplyApprove { apply_status_name?: string | null; /** 最终结算金额 */ final_settlement_price?: number | null; + /** 申请理由 */ + apply_reason?: string; + /** 折扣 */ + discount_ratio?: number | null; } /** diff --git a/src/components/exam/ExamAddonPanel.tsx b/src/components/exam/ExamAddonPanel.tsx index 5dada20..7eee1d7 100644 --- a/src/components/exam/ExamAddonPanel.tsx +++ b/src/components/exam/ExamAddonPanel.tsx @@ -29,6 +29,17 @@ interface ExamAddonPanelProps { export const ExamAddonPanel = ({ client, onGoToSign }: ExamAddonPanelProps) => { const [addonList, setAddonList] = useState([]); + const allAddons = useMemo(() => addonList, [addonList]); + const [selectedIds, setSelectedIds] = useState>(new Set()); + + const currentAddItemId = useMemo(() => { + const currentSelectedItems = allAddons.filter(item => selectedIds.has(item.id || item.name)); + return currentSelectedItems + .map(item => item.combinationItemCode) + .filter((code): code is number => code !== null && code !== undefined) + .join(','); + }, [allAddons, selectedIds]); + // 防抖:内部输入值(用于显示) const [addonSearchInput, setAddonSearchInput] = useState(''); // 防抖:实际用于 API 调用的值(延迟更新) @@ -82,6 +93,10 @@ export const ExamAddonPanel = ({ client, onGoToSign }: ExamAddonPanelProps) => { apply_status?: number; apply_status_name?: string | null; final_settlement_price?: number | null; + apply_reason?: string | null; + settlement_type?: number | null; + discount_ratio?: number | null; + add_item_id?: string | null; } | null>(null); const [customSettlementLoading, setCustomSettlementLoading] = useState(false); const [customSettlementType, setCustomSettlementType] = useState<1 | 2>(1); // 1-按比例折扣 2-自定义结算价 @@ -91,6 +106,33 @@ export const ExamAddonPanel = ({ client, onGoToSign }: ExamAddonPanelProps) => { const [waitingSeconds, setWaitingSeconds] = useState(0); // 等待审核的秒数 const waitingTimerRef = useRef(null); // 等待计时器 + useEffect(() => { + if (showCustomSettlementModal && customSettlementStatus) { + // 已通过(3) 或 已拒绝(4) 且 add_item_id 匹配才需要回显 + if ((customSettlementStatus.apply_status === 3 || customSettlementStatus.apply_status === 4) && + customSettlementStatus.add_item_id === currentAddItemId) { + if (customSettlementStatus.settlement_type === 1 || customSettlementStatus.settlement_type === 2) { + setCustomSettlementType(customSettlementStatus.settlement_type as 1 | 2); + } + if (typeof customSettlementStatus.discount_ratio === 'number') { + setCustomDiscountRatio(customSettlementStatus.discount_ratio); + } + if (typeof customSettlementStatus.final_settlement_price === 'number') { + setCustomFinalPrice(customSettlementStatus.final_settlement_price); + } + if (customSettlementStatus.apply_reason) { + setCustomApplyReason(customSettlementStatus.apply_reason); + } + } else { + // 其他状态(如取消后再点开)重置表单为默认值 + setCustomSettlementType(1); + setCustomDiscountRatio(null); + setCustomFinalPrice(0); + setCustomApplyReason(''); + } + } + }, [showCustomSettlementModal, customSettlementStatus, currentAddItemId]); + // 点击外部关闭下拉框 useEffect(() => { const handleClickOutside = (event: MouseEvent) => { @@ -276,10 +318,6 @@ export const ExamAddonPanel = ({ client, onGoToSign }: ExamAddonPanelProps) => { fetchList(); }, [debouncedAddonSearch, customerInfo?.scrm_account_id, customerInfo?.scrm_account_name, client.id, customerInfo, channelDiscounts, discountRatio]); - const allAddons = useMemo(() => addonList, [addonList]); - - const [selectedIds, setSelectedIds] = useState>(new Set()); - const maxSelect = 15; const selectedCount = selectedIds.size; @@ -433,19 +471,8 @@ export const ExamAddonPanel = ({ client, onGoToSign }: ExamAddonPanelProps) => { // 获取自定义结算审批状态(带节流,最多每秒一次) const fetchCustomSettlementStatus = useCallback(async () => { const physical_exam_id = Number(client.id); - const currentSelectedItems = allAddons.filter(item => selectedIds.has(item.id || item.name)); - if (!physical_exam_id || currentSelectedItems.length === 0) { - setCustomSettlementStatus(null); - return false; - } - - const add_item_id = currentSelectedItems - .map(item => item.combinationItemCode) - .filter((code): code is number => code !== null && code !== undefined) - .join(','); - - if (!add_item_id) { + if (!physical_exam_id || !currentAddItemId) { setCustomSettlementStatus(null); return false; } @@ -454,7 +481,7 @@ export const ExamAddonPanel = ({ client, onGoToSign }: ExamAddonPanelProps) => { const now = Date.now(); const timeSinceLastCall = now - lastFetchStatusTimeRef.current; if (timeSinceLastCall < 800) { - // 返回当前状态是否需要轮询 + // 从 ref 获取当前状态判断是否需要轮询 return customSettlementStatus?.apply_status === 1; } lastFetchStatusTimeRef.current = now; @@ -462,19 +489,27 @@ export const ExamAddonPanel = ({ client, onGoToSign }: ExamAddonPanelProps) => { try { const res = await getCustomSettlementApproveStatus({ physical_exam_id, - add_item_id, + add_item_id: currentAddItemId, }); if (res.Status === 200 && res.Data) { const status = { apply_status: res.Data.apply_status, apply_status_name: res.Data.apply_status_name, final_settlement_price: res.Data.final_settlement_price, + apply_reason: (res.Data as any).apply_reason, + settlement_type: (res.Data as any).settlement_type, + discount_ratio: (res.Data as any).discount_ratio, + add_item_id: currentAddItemId, }; - setCustomSettlementStatus(status); - // 如果状态变为审核中,重置等待时间 - if (res.Data.apply_status === 1 && customSettlementStatus?.apply_status !== 1) { - setWaitingSeconds(0); - } + + // 获取旧状态用于判断是否刚进入审核中 + setCustomSettlementStatus(prev => { + if (status.apply_status === 1 && prev?.apply_status !== 1) { + setWaitingSeconds(0); + } + return status; + }); + // 返回是否需要继续轮询(1-审核中 需要轮询) return res.Data.apply_status === 1; } else { @@ -486,12 +521,19 @@ export const ExamAddonPanel = ({ client, onGoToSign }: ExamAddonPanelProps) => { setCustomSettlementStatus(null); return false; } - }, [client.id, selectedIds, allAddons, customSettlementStatus]); + }, [client.id, currentAddItemId]); // 当选中加项变化时,获取审批状态 useEffect(() => { - const currentSelectedItems = allAddons.filter(item => selectedIds.has(item.id || item.name)); - if (currentSelectedItems.length > 0) { + // 切换选中项时,先清零状态,避免错误回显旧数据 + setCustomSettlementStatus(null); + setCustomSettlementType(1); + setCustomDiscountRatio(null); + setCustomFinalPrice(0); + setCustomApplyReason(''); + lastFetchStatusTimeRef.current = 0; // 强制立即发起新请求 + + if (currentAddItemId) { fetchCustomSettlementStatus().then((shouldPoll) => { // 如果需要轮询(审核中),开始轮询 if (shouldPoll) { @@ -501,10 +543,9 @@ export const ExamAddonPanel = ({ client, onGoToSign }: ExamAddonPanelProps) => { } }); } else { - setCustomSettlementStatus(null); stopCustomSettlementPolling(); } - }, [selectedIds, client.id, allAddons, fetchCustomSettlementStatus]); + }, [currentAddItemId, client.id]); // 移除 fetchCustomSettlementStatus 依赖,避免由于状态更新导致的死循环 // 开始轮询自定义结算审批状态 const startCustomSettlementPolling = useCallback(() => { @@ -975,6 +1016,10 @@ export const ExamAddonPanel = ({ client, onGoToSign }: ExamAddonPanelProps) => { } }; + const isApprovedOrRejected = + (customSettlementStatus?.apply_status === 3 || customSettlementStatus?.apply_status === 4) && + customSettlementStatus?.add_item_id === currentAddItemId; + return (
{/* 标题和说明 */} @@ -1157,10 +1202,12 @@ export const ExamAddonPanel = ({ client, onGoToSign }: ExamAddonPanelProps) => {