From d09bfc4ec6dc3b17f43b8446d26b838aab7b826c Mon Sep 17 00:00:00 2001 From: xianyi Date: Wed, 28 Jan 2026 11:41:34 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/api/types.ts | 2 + src/components/exam/ExamAddonPanel.tsx | 545 +++++++++++++------------ 2 files changed, 285 insertions(+), 262 deletions(-) diff --git a/src/api/types.ts b/src/api/types.ts index 029a0fa..00e6dd1 100644 --- a/src/api/types.ts +++ b/src/api/types.ts @@ -548,6 +548,8 @@ export interface InputPhysicalExamAddItem { scrm_account_name?: string | null; /** 项目名称(默认空值,传入项目名称过滤数据) */ item_name?: string; + /** 折扣率 */ + discount_rate?: number | null; } /** diff --git a/src/components/exam/ExamAddonPanel.tsx b/src/components/exam/ExamAddonPanel.tsx index 5905a95..527bd00 100644 --- a/src/components/exam/ExamAddonPanel.tsx +++ b/src/components/exam/ExamAddonPanel.tsx @@ -85,7 +85,7 @@ export const ExamAddonPanel = ({ client, onGoToSign }: ExamAddonPanelProps) => { } | null>(null); const [customSettlementLoading, setCustomSettlementLoading] = useState(false); const [customSettlementType, setCustomSettlementType] = useState<1 | 2>(1); // 1-按比例折扣 2-自定义结算价 - const [customDiscountRatio, setCustomDiscountRatio] = useState(100); // 折扣比例(如100代表10折,即原价) + const [customDiscountRatio, setCustomDiscountRatio] = useState(null); // 折扣比例(如100代表10折,即原价) const [customFinalPrice, setCustomFinalPrice] = useState(0); // 最终结算价 const [customApplyReason, setCustomApplyReason] = useState(''); // 申请理由 const [waitingSeconds, setWaitingSeconds] = useState(0); // 等待审核的秒数 @@ -123,24 +123,15 @@ export const ExamAddonPanel = ({ client, onGoToSign }: ExamAddonPanelProps) => { try { const res = await getAddItemCustomerInfo({ physical_exam_id }); if (res.Status === 200) { - // 保存客户信息 + // 保存客户信息,渠道信息使用 listChannelDiscount 中的 channel_id / channel_name if (res.Data?.customerInfo) { - const channelInfo = res.Data.listChannelDiscount?.[0]; - const scrm_account_id = - res.Data.customerInfo.scrm_account_id ?? - channelInfo?.channel_id ?? - null; - const scrm_account_name = - res.Data.customerInfo.scrm_account_name ?? - channelInfo?.channel_name ?? - null; - + const firstChannel = res.Data.listChannelDiscount?.[0]; setCustomerInfo({ patient_id: res.Data.customerInfo.patient_id, customer_name: res.Data.customerInfo.customer_name, phone: res.Data.customerInfo.phone, - scrm_account_id, - scrm_account_name, + scrm_account_id: firstChannel?.channel_id ?? null, + scrm_account_name: firstChannel?.channel_name ?? null, }); customerInfoLoadedRef.current = true; // 设置挂账公司默认值 @@ -237,11 +228,19 @@ export const ExamAddonPanel = ({ client, onGoToSign }: ExamAddonPanelProps) => { setAddonLoading(true); setAddonError(null); try { + console.log("请求数据 1", customerInfo, customerInfo?.scrm_account_id); + + const selectedChannel = channelDiscounts.find( + (item) => item.discount_rate === discountRatio + ); + const discountRate = selectedChannel?.discount_rate ?? null; + const res = await searchPhysicalExamAddItem({ physical_exam_id: Number(client.id), scrm_account_id: customerInfo?.scrm_account_id || null, scrm_account_name: customerInfo?.scrm_account_name || null, item_name: debouncedAddonSearch.trim() || "", + discount_rate: discountRate, }); if (res.Status === 200 && Array.isArray(res.Data)) { const list: AddonItem[] = res.Data.map((item) => ({ @@ -275,7 +274,7 @@ export const ExamAddonPanel = ({ client, onGoToSign }: ExamAddonPanelProps) => { } }; fetchList(); - }, [debouncedAddonSearch, customerInfo?.scrm_account_id, customerInfo?.scrm_account_name, client.id, customerInfo]); + }, [debouncedAddonSearch, customerInfo?.scrm_account_id, customerInfo?.scrm_account_name, client.id, customerInfo, channelDiscounts, discountRatio]); const allAddons = useMemo(() => addonList, [addonList]); @@ -335,14 +334,19 @@ export const ExamAddonPanel = ({ client, onGoToSign }: ExamAddonPanelProps) => { return item.discount_name; }; - // 构建折扣选项列表 + // 构建折扣选项列表(带上渠道ID/名称,便于联动设置 scrm_account_id / scrm_account_name) const discountOptions = useMemo(() => { - const options: Array<{ value: number; label: string }> = []; + const options: Array<{ value: number; label: string; channel_id?: string | null; channel_name?: string | null }> = []; channelDiscounts.forEach((item) => { const rate = typeof item.discount_rate === 'number' && item.discount_rate > 0 ? item.discount_rate : 1; const percent = Math.round(rate * 100); const label = item.discount_name || `${percent}%`; - options.push({ value: rate, label }); + options.push({ + value: rate, + label, + channel_id: item.channel_id ?? null, + channel_name: item.channel_name ?? null, + }); }); return options; }, [channelDiscounts]); @@ -353,9 +357,21 @@ export const ExamAddonPanel = ({ client, onGoToSign }: ExamAddonPanelProps) => { return option?.label; }, [discountRatio, discountOptions]); - // 处理折扣选择 + // 处理折扣选择,同时更新 scrm_account_id / scrm_account_name const handleDiscountSelect = (value: number) => { setDiscountRatio(value); + const matched = discountOptions.find(opt => opt.value === value); + if (matched && (matched.channel_id || matched.channel_name)) { + setCustomerInfo((prev) => + prev + ? { + ...prev, + scrm_account_id: matched.channel_id ?? null, + scrm_account_name: matched.channel_name ?? null, + } + : prev + ); + } setIsDiscountDropdownOpen(false); }; @@ -503,7 +519,7 @@ export const ExamAddonPanel = ({ client, onGoToSign }: ExamAddonPanelProps) => { stopCustomSettlementPolling(); } }); - }, 1000); + }, 1500); }, [fetchCustomSettlementStatus]); // 停止轮询自定义结算审批状态 @@ -559,6 +575,12 @@ export const ExamAddonPanel = ({ client, onGoToSign }: ExamAddonPanelProps) => { return; } + const discountRatioValue = customSettlementType === 1 ? (customDiscountRatio ?? 0) : 0; + if (customSettlementType === 1 && (discountRatioValue <= 0 || discountRatioValue > 100)) { + setPaymentMessage('请输入有效折扣比例'); + return; + } + setCustomSettlementLoading(true); setPaymentMessage(null); @@ -575,7 +597,7 @@ export const ExamAddonPanel = ({ client, onGoToSign }: ExamAddonPanelProps) => { if (customSettlementType === 1) { // 按比例折扣 - settlementPrice = originalPrice * (customDiscountRatio / 100); + settlementPrice = originalPrice * (discountRatioValue / 100); } else { // 自定义结算价 settlementPrice = customFinalPrice / selectedItems.length; // 平均分配 @@ -595,7 +617,7 @@ export const ExamAddonPanel = ({ client, onGoToSign }: ExamAddonPanelProps) => { }, 0); const final_settlement_price = customSettlementType === 1 - ? original_settlement_price * (customDiscountRatio / 100) + ? original_settlement_price * (discountRatioValue / 100) : customFinalPrice; const res = await customSettlementApply({ @@ -603,7 +625,7 @@ export const ExamAddonPanel = ({ client, onGoToSign }: ExamAddonPanelProps) => { listAddItemDetail, original_settlement_price, settlement_type: customSettlementType, - discount_ratio: customSettlementType === 1 ? customDiscountRatio : undefined, + discount_ratio: customSettlementType === 1 ? discountRatioValue : undefined, final_settlement_price, apply_reason: customApplyReason.trim(), }); @@ -647,6 +669,7 @@ export const ExamAddonPanel = ({ client, onGoToSign }: ExamAddonPanelProps) => { return; } + stopCustomSettlementPolling(); setCustomSettlementLoading(true); setPaymentMessage(null); @@ -668,6 +691,7 @@ export const ExamAddonPanel = ({ client, onGoToSign }: ExamAddonPanelProps) => { if (res.Status === 200 && res.Data?.is_success === 1) { setPaymentMessage('取消申请成功'); + setCustomDiscountRatio(null); // 停止轮询 stopCustomSettlementPolling(); // 重新获取审批状态 @@ -1078,14 +1102,16 @@ export const ExamAddonPanel = ({ client, onGoToSign }: ExamAddonPanelProps) => { 原价:¥{origPrice.toFixed(2)} )} - 折扣价:¥{currPrice.toFixed(2)} + {getDiscountText(item)} + 折后价:¥{currPrice.toFixed(2)} + {/*
{getDiscountText(item)} -
+ */} @@ -1096,55 +1122,39 @@ export const ExamAddonPanel = ({ client, onGoToSign }: ExamAddonPanelProps) => { {/* 底部汇总和支付 */}
-
-
- 加项原价合计: ¥{totalOriginal.toFixed(2)} -
-
- 渠道折扣价: ¥{totalCurrent.toFixed(2)} - {discount > 0 && ( - 已优惠 ¥{discount.toFixed(2)} - )} -
- {/*
结算方式: 个人支付 (微信 / 支付宝)
*/} -
+
+
+
+ 原价: ¥{totalOriginal.toFixed(2)} +
+
+ 优惠: ¥{discount.toFixed(2)} +
+
+ 结算价: ¥{(totalCurrent).toFixed(2)} +
+ {/*
结算方式: 个人支付 (微信 / 支付宝)
*/} - {/* 添加自定义结算 */} - {localStorage.getItem('authCode')?.includes('HisTijianPad_Btn_Tongji') && selectedItems.length > 0 && ( -
- {customSettlementStatus && ( -
- 审批状态: - {customSettlementStatus.apply_status_name || '未知'} - {customSettlementStatus.apply_status === 1 && ' (审核中...)'} - - {customSettlementStatus.final_settlement_price !== null && customSettlementStatus.final_settlement_price !== undefined && ( - - 结算价: ¥{customSettlementStatus.final_settlement_price.toFixed(2)} - - )} -
- )} -
- )} + + + {/* 添加自定义结算 */} + {localStorage.getItem('authCode')?.includes('HisTijianPad_Btn_Tongji') && selectedItems.length > 0 && ( +
+ +
+ )} +
{paymentMessage && ( @@ -1264,7 +1274,7 @@ export const ExamAddonPanel = ({ client, onGoToSign }: ExamAddonPanelProps) => { )}
{/* 二维码支付弹窗 */} - {showQrcodeModal && qrcodeUrl && ( -
-
-
-
扫码支付
- -
-
-
- 支付二维码 + { + showQrcodeModal && qrcodeUrl && ( +
+
+
+
扫码支付
+
-
- 请使用微信扫描上方二维码完成支付 -
- {paymentMessage && ( -
- {paymentMessage} +
+
+ 支付二维码
- )} +
+ 请使用微信扫描上方二维码完成支付 +
+ {paymentMessage && ( +
+ {paymentMessage} +
+ )} +
-
- )} + ) + } {/* 自定义结算弹窗 */} - {showCustomSettlementModal && ( -
setShowCustomSettlementModal(false)}> -
e.stopPropagation()} - > -
-
自定义结算申请
- -
- -
- {/* 选中项目信息 */} -
-
选中项目 ({selectedItems.length}项):
-
- {selectedItems.map((item, idx) => ( -
- {item.name} - ¥{parseFloat(item.currentPrice || item.originalPrice || '0').toFixed(2)} -
- ))} -
-
- 渠道折扣价合计: - ¥{totalCurrent.toFixed(2)} -
+ { + showCustomSettlementModal && ( +
setShowCustomSettlementModal(false)}> +
e.stopPropagation()} + > +
+
自定义结算申请
+
- {/* 结算方式 */} -
- -
- - -
-
- - {/* 折扣比例或最终结算价 */} - {customSettlementType === 1 ? ( -
-
- - - {(customDiscountRatio / 10).toFixed(1)}折 - +
+ {/* 选中项目信息 */} +
+
选中项目 ({selectedItems.length}项):
+
+ {selectedItems.map((item, idx) => ( +
+ {item.name} + ¥{parseFloat(item.currentPrice || item.originalPrice || '0').toFixed(2)} +
+ ))}
-
+
+ 渠道折扣价合计: + ¥{totalCurrent.toFixed(2)} +
+
+ + {/* 结算方式 */} +
+ +
+ + +
+
+ + {/* 折扣比例或最终结算价 */} + {customSettlementType === 1 ? ( +
+
+ + + {((customDiscountRatio ?? 0) / 10).toFixed(1)}折 + +
+
+ { + const raw = e.target.value; + if (raw === '') { + setCustomDiscountRatio(null); + return; + } + const val = Number(raw); + if (Number.isNaN(val)) return; + if (val < 1) { + setCustomDiscountRatio(1); + } else if (val > 100) { + setCustomDiscountRatio(100); + } else { + setCustomDiscountRatio(val); + } + }} + className='w-28 text-sm' + /> + 1-100,100 表示不打折 +
+
+ 最终结算价: ¥{(totalCurrent * ((customDiscountRatio ?? 0) / 100)).toFixed(2)} +
+
+ ) : ( +
+ { const val = Number(e.target.value); - if (Number.isNaN(val)) return; - if (val < 10) { - setCustomDiscountRatio(10); - } else if (val > 100) { - setCustomDiscountRatio(100); - } else { - setCustomDiscountRatio(val); + if (val >= 0) { + setCustomFinalPrice(val); } }} - className='w-28 text-sm' + placeholder='请输入最终结算价' + className='text-sm' /> - 10-100,100 表示不打折
-
- 最终结算价: ¥{(totalCurrent * (customDiscountRatio / 100)).toFixed(2)} -
-
- ) : ( + )} + + {/* 申请理由 */}
- - { - const val = Number(e.target.value); - if (val >= 0) { - setCustomFinalPrice(val); - } - }} - placeholder='请输入最终结算价' - className='text-sm' + +