修复回显
This commit is contained in:
@@ -29,6 +29,17 @@ interface ExamAddonPanelProps {
|
||||
|
||||
export const ExamAddonPanel = ({ client, onGoToSign }: ExamAddonPanelProps) => {
|
||||
const [addonList, setAddonList] = useState<AddonItem[]>([]);
|
||||
const allAddons = useMemo(() => addonList, [addonList]);
|
||||
const [selectedIds, setSelectedIds] = useState<Set<string>>(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<number>(0); // 等待审核的秒数
|
||||
const waitingTimerRef = useRef<number | null>(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<Set<string>>(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 (
|
||||
<div className='space-y-4'>
|
||||
{/* 标题和说明 */}
|
||||
@@ -1157,10 +1202,12 @@ export const ExamAddonPanel = ({ client, onGoToSign }: ExamAddonPanelProps) => {
|
||||
<div className='flex flex-col items-end gap-2 relative'>
|
||||
<Button
|
||||
onClick={() => setShowCustomSettlementModal(true)}
|
||||
className=
|
||||
'px-3 py-1.5 text-xs text-white bg-blue-600'
|
||||
className='px-3 py-1.5 text-xs text-white bg-blue-600'
|
||||
>
|
||||
{!customSettlementStatus || !customSettlementStatus.apply_status || customSettlementStatus.apply_status === 1
|
||||
{!customSettlementStatus ||
|
||||
!customSettlementStatus.apply_status ||
|
||||
customSettlementStatus.apply_status === 1 ||
|
||||
customSettlementStatus.add_item_id !== currentAddItemId
|
||||
? '申请自定义结算'
|
||||
: customSettlementStatus.apply_status === 3
|
||||
? '自定义结算(已通过)'
|
||||
@@ -1377,24 +1424,28 @@ export const ExamAddonPanel = ({ client, onGoToSign }: ExamAddonPanelProps) => {
|
||||
<div className='flex gap-3'>
|
||||
<button
|
||||
type='button'
|
||||
disabled={isApprovedOrRejected}
|
||||
onClick={() => setCustomSettlementType(1)}
|
||||
className={cls(
|
||||
'flex-1 px-4 py-2 rounded-lg border text-sm transition-colors',
|
||||
customSettlementType === 1
|
||||
? 'bg-blue-50 border-blue-500 text-blue-700 font-medium'
|
||||
: 'bg-white border-gray-300 text-gray-700 hover:border-gray-400'
|
||||
: 'bg-white border-gray-300 text-gray-700 hover:border-gray-400',
|
||||
isApprovedOrRejected && 'opacity-70 cursor-not-allowed'
|
||||
)}
|
||||
>
|
||||
按比例折扣
|
||||
</button>
|
||||
<button
|
||||
type='button'
|
||||
disabled={isApprovedOrRejected}
|
||||
onClick={() => setCustomSettlementType(2)}
|
||||
className={cls(
|
||||
'flex-1 px-4 py-2 rounded-lg border text-sm transition-colors',
|
||||
customSettlementType === 2
|
||||
? 'bg-blue-50 border-blue-500 text-blue-700 font-medium'
|
||||
: 'bg-white border-gray-300 text-gray-700 hover:border-gray-400'
|
||||
: 'bg-white border-gray-300 text-gray-700 hover:border-gray-400',
|
||||
isApprovedOrRejected && 'opacity-70 cursor-not-allowed'
|
||||
)}
|
||||
>
|
||||
自定义结算价
|
||||
@@ -1417,6 +1468,7 @@ export const ExamAddonPanel = ({ client, onGoToSign }: ExamAddonPanelProps) => {
|
||||
min='0'
|
||||
max='100'
|
||||
step='1'
|
||||
disabled={isApprovedOrRejected}
|
||||
value={customDiscountRatio ?? ''}
|
||||
onChange={(e) => {
|
||||
const raw = e.target.value;
|
||||
@@ -1449,6 +1501,7 @@ export const ExamAddonPanel = ({ client, onGoToSign }: ExamAddonPanelProps) => {
|
||||
type='number'
|
||||
min='0'
|
||||
step='0.01'
|
||||
disabled={isApprovedOrRejected}
|
||||
value={customFinalPrice || ''}
|
||||
onChange={(e) => {
|
||||
const val = Number(e.target.value);
|
||||
@@ -1467,10 +1520,14 @@ export const ExamAddonPanel = ({ client, onGoToSign }: ExamAddonPanelProps) => {
|
||||
<label className='text-sm text-gray-700 font-medium'>申请理由 *</label>
|
||||
<textarea
|
||||
value={customApplyReason}
|
||||
disabled={isApprovedOrRejected}
|
||||
onChange={(e) => setCustomApplyReason(e.target.value)}
|
||||
placeholder='请输入申请理由'
|
||||
rows={3}
|
||||
className='w-full px-3 py-2 border border-gray-300 rounded-lg text-sm focus:outline-none focus:ring-1 focus:ring-blue-500 focus:border-blue-500 resize-none'
|
||||
className={cls(
|
||||
'w-full px-3 py-2 border border-gray-300 rounded-lg text-sm focus:outline-none focus:ring-1 focus:ring-blue-500 focus:border-blue-500 resize-none',
|
||||
isApprovedOrRejected && 'bg-gray-50 opacity-70 cursor-not-allowed'
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -1480,20 +1537,22 @@ export const ExamAddonPanel = ({ client, onGoToSign }: ExamAddonPanelProps) => {
|
||||
onClick={() => setShowCustomSettlementModal(false)}
|
||||
className='flex-1 px-4 py-2 bg-gray-100 hover:bg-gray-200 text-gray-700'
|
||||
>
|
||||
取消
|
||||
</Button>
|
||||
<Button
|
||||
onClick={handleSubmitCustomSettlement}
|
||||
disabled={customSettlementLoading || !customApplyReason.trim()}
|
||||
className={cls(
|
||||
'flex-1 px-4 py-2 text-white font-medium',
|
||||
customSettlementLoading || !customApplyReason.trim()
|
||||
? 'bg-gray-400 cursor-not-allowed'
|
||||
: 'bg-blue-600 hover:bg-blue-700'
|
||||
)}
|
||||
>
|
||||
{customSettlementLoading ? '提交中...' : '提交申请'}
|
||||
{isApprovedOrRejected ? '关闭' : '取消'}
|
||||
</Button>
|
||||
{!isApprovedOrRejected && (
|
||||
<Button
|
||||
onClick={handleSubmitCustomSettlement}
|
||||
disabled={customSettlementLoading || !customApplyReason.trim()}
|
||||
className={cls(
|
||||
'flex-1 px-4 py-2 text-white font-medium',
|
||||
customSettlementLoading || !customApplyReason.trim()
|
||||
? 'bg-gray-400 cursor-not-allowed'
|
||||
: 'bg-blue-600 hover:bg-blue-700'
|
||||
)}
|
||||
>
|
||||
{customSettlementLoading ? '提交中...' : '提交申请'}
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user