修复
This commit is contained in:
@@ -548,6 +548,8 @@ export interface InputPhysicalExamAddItem {
|
||||
scrm_account_name?: string | null;
|
||||
/** 项目名称(默认空值,传入项目名称过滤数据) */
|
||||
item_name?: string;
|
||||
/** 折扣率 */
|
||||
discount_rate?: number | null;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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<number>(100); // 折扣比例(如100代表10折,即原价)
|
||||
const [customDiscountRatio, setCustomDiscountRatio] = useState<number | null>(null); // 折扣比例(如100代表10折,即原价)
|
||||
const [customFinalPrice, setCustomFinalPrice] = useState<number>(0); // 最终结算价
|
||||
const [customApplyReason, setCustomApplyReason] = useState<string>(''); // 申请理由
|
||||
const [waitingSeconds, setWaitingSeconds] = useState<number>(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) => {
|
||||
<span className='text-xs text-gray-400 line-through'>原价:¥{origPrice.toFixed(2)}</span>
|
||||
)}
|
||||
|
||||
<span className='text-[13px] font-bold text-red-600'>折扣价:¥{currPrice.toFixed(2)}</span>
|
||||
<span className='text-[13px] font-bold text-[#447955]'>{getDiscountText(item)}</span>
|
||||
|
||||
<span className='text-[13px] font-bold text-red-600'>折后价:¥{currPrice.toFixed(2)}</span>
|
||||
{/*
|
||||
<div className='flex items-center justify-between gap-2'>
|
||||
<span></span>
|
||||
<span className={`text-[10px] px-2 rounded-full bg-[#EAFCF1] text-[#447955] whitespace-nowrap`}>
|
||||
{getDiscountText(item)}
|
||||
</span>
|
||||
</div>
|
||||
</div> */}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -1096,55 +1122,39 @@ export const ExamAddonPanel = ({ client, onGoToSign }: ExamAddonPanelProps) => {
|
||||
|
||||
{/* 底部汇总和支付 */}
|
||||
<div className='border-t pt-4 mt-6 flex items-center justify-between'>
|
||||
<div className='flex items-center gap-2'>
|
||||
<div className='space-y-1 text-sm'>
|
||||
<div className='text-gray-600'>
|
||||
加项原价合计: <span className='text-gray-900'>¥{totalOriginal.toFixed(2)}</span>
|
||||
原价: <span className='text-gray-900'>¥{totalOriginal.toFixed(2)}</span>
|
||||
</div>
|
||||
<div className='text-gray-600'>
|
||||
渠道折扣价: <span className='text-xl font-bold text-red-600'>¥{totalCurrent.toFixed(2)}</span>
|
||||
{discount > 0 && (
|
||||
<span className='text-gray-500 ml-1'>已优惠 ¥{discount.toFixed(2)}</span>
|
||||
)}
|
||||
优惠: <span className='font-bold text-red-600'>¥{discount.toFixed(2)}</span>
|
||||
</div>
|
||||
<div className='text-gray-600'>
|
||||
结算价: <span className='font-bold text-red-600'>¥{(totalCurrent).toFixed(2)}</span>
|
||||
</div>
|
||||
{/* <div className='text-xs text-gray-500'>结算方式: 个人支付 (微信 / 支付宝)</div> */}
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
{/* 添加自定义结算 */}
|
||||
{localStorage.getItem('authCode')?.includes('HisTijianPad_Btn_Tongji') && selectedItems.length > 0 && (
|
||||
<div className='flex flex-col items-end gap-2 relative'>
|
||||
{customSettlementStatus && (
|
||||
<div className='text-xs text-gray-600'>
|
||||
审批状态: <span className={cls(
|
||||
'font-semibold',
|
||||
customSettlementStatus.apply_status === 1 && 'text-blue-600', // 审核中
|
||||
customSettlementStatus.apply_status === 3 && 'text-green-600', // 审核通过
|
||||
customSettlementStatus.apply_status === 4 && 'text-red-600', // 审核不通过
|
||||
customSettlementStatus.apply_status === 2 && 'text-gray-600' // 取消申请
|
||||
)}>
|
||||
{customSettlementStatus.apply_status_name || '未知'}
|
||||
{customSettlementStatus.apply_status === 1 && ' (审核中...)'}
|
||||
</span>
|
||||
{customSettlementStatus.final_settlement_price !== null && customSettlementStatus.final_settlement_price !== undefined && (
|
||||
<span className='ml-2'>
|
||||
结算价: <span className='font-semibold text-red-600'>¥{customSettlementStatus.final_settlement_price.toFixed(2)}</span>
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
<Button
|
||||
onClick={() => setShowCustomSettlementModal(true)}
|
||||
disabled={customSettlementStatus?.apply_status === 1}
|
||||
className={cls(
|
||||
'px-3 py-1.5 text-xs text-white',
|
||||
customSettlementStatus?.apply_status === 1
|
||||
? 'bg-gray-400 cursor-not-allowed'
|
||||
: 'bg-blue-600 hover:bg-blue-700'
|
||||
)}
|
||||
className=
|
||||
'px-3 py-1.5 text-xs text-white bg-blue-600'
|
||||
>
|
||||
申请自定义结算
|
||||
{!customSettlementStatus || !customSettlementStatus.apply_status || customSettlementStatus.apply_status === 1
|
||||
? '申请自定义结算'
|
||||
: customSettlementStatus.apply_status === 3
|
||||
? '自定义结算(已通过)'
|
||||
: '自定义结算(未通过)'}
|
||||
</Button>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
|
||||
{paymentMessage && (
|
||||
@@ -1264,7 +1274,7 @@ export const ExamAddonPanel = ({ client, onGoToSign }: ExamAddonPanelProps) => {
|
||||
)}
|
||||
|
||||
<Button
|
||||
className='bg-[#269745] hover:bg-[#269745]/80 rounded-3xl text-white px-6 py-3 text-base font-medium'
|
||||
className='bg-blue-600 rounded-3xl text-white px-6 py-3 text-base font-medium'
|
||||
disabled={selectedCount === 0 || paymentLoading}
|
||||
onClick={handlePayment}
|
||||
>
|
||||
@@ -1273,7 +1283,8 @@ export const ExamAddonPanel = ({ client, onGoToSign }: ExamAddonPanelProps) => {
|
||||
</div>
|
||||
</div>
|
||||
{/* 二维码支付弹窗 */}
|
||||
{showQrcodeModal && qrcodeUrl && (
|
||||
{
|
||||
showQrcodeModal && qrcodeUrl && (
|
||||
<div className='fixed inset-0 z-[80] bg-black/80 flex items-center justify-center px-6'>
|
||||
<div className='bg-white rounded-2xl w-full max-w-md shadow-2xl p-6 flex flex-col gap-4'>
|
||||
<div className='flex items-center justify-between'>
|
||||
@@ -1307,10 +1318,12 @@ export const ExamAddonPanel = ({ client, onGoToSign }: ExamAddonPanelProps) => {
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
)
|
||||
}
|
||||
|
||||
{/* 自定义结算弹窗 */}
|
||||
{showCustomSettlementModal && (
|
||||
{
|
||||
showCustomSettlementModal && (
|
||||
<div className='fixed inset-0 z-50 flex items-center justify-center bg-black/30' onClick={() => setShowCustomSettlementModal(false)}>
|
||||
<div
|
||||
className='w-[500px] max-w-[95vw] bg-white rounded-2xl shadow-xl overflow-hidden'
|
||||
@@ -1381,21 +1394,26 @@ export const ExamAddonPanel = ({ client, onGoToSign }: ExamAddonPanelProps) => {
|
||||
<div className='flex items-center justify-between'>
|
||||
<label className='text-sm text-gray-700 font-medium'>折扣比例 (%)</label>
|
||||
<span className='text-sm font-semibold text-blue-600'>
|
||||
{(customDiscountRatio / 10).toFixed(1)}折
|
||||
{((customDiscountRatio ?? 0) / 10).toFixed(1)}折
|
||||
</span>
|
||||
</div>
|
||||
<div className='flex items-center gap-2'>
|
||||
<Input
|
||||
type='number'
|
||||
min='10'
|
||||
min='0'
|
||||
max='100'
|
||||
step='1'
|
||||
value={customDiscountRatio}
|
||||
value={customDiscountRatio ?? ''}
|
||||
onChange={(e) => {
|
||||
const val = Number(e.target.value);
|
||||
const raw = e.target.value;
|
||||
if (raw === '') {
|
||||
setCustomDiscountRatio(null);
|
||||
return;
|
||||
}
|
||||
const val = Number(raw);
|
||||
if (Number.isNaN(val)) return;
|
||||
if (val < 10) {
|
||||
setCustomDiscountRatio(10);
|
||||
if (val < 1) {
|
||||
setCustomDiscountRatio(1);
|
||||
} else if (val > 100) {
|
||||
setCustomDiscountRatio(100);
|
||||
} else {
|
||||
@@ -1404,10 +1422,10 @@ export const ExamAddonPanel = ({ client, onGoToSign }: ExamAddonPanelProps) => {
|
||||
}}
|
||||
className='w-28 text-sm'
|
||||
/>
|
||||
<span className='text-xs text-gray-500'>10-100,100 表示不打折</span>
|
||||
<span className='text-xs text-gray-500'>1-100,100 表示不打折</span>
|
||||
</div>
|
||||
<div className='text-xs text-gray-500'>
|
||||
最终结算价: <span className='font-semibold text-red-600'>¥{(totalCurrent * (customDiscountRatio / 100)).toFixed(2)}</span>
|
||||
最终结算价: <span className='font-semibold text-red-600'>¥{(totalCurrent * ((customDiscountRatio ?? 0) / 100)).toFixed(2)}</span>
|
||||
</div>
|
||||
</div>
|
||||
) : (
|
||||
@@ -1466,10 +1484,12 @@ export const ExamAddonPanel = ({ client, onGoToSign }: ExamAddonPanelProps) => {
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
)
|
||||
}
|
||||
|
||||
{/* 审核中全屏遮罩 */}
|
||||
{customSettlementStatus?.apply_status === 1 && (
|
||||
{
|
||||
customSettlementStatus?.apply_status === 1 && (
|
||||
<div className='fixed inset-0 bg-black/50 backdrop-blur-sm flex items-center justify-center z-50'>
|
||||
<div className='bg-white rounded-2xl p-6 max-w-md w-full mx-4 shadow-xl'>
|
||||
<div className='text-center mb-6'>
|
||||
@@ -1488,7 +1508,8 @@ export const ExamAddonPanel = ({ client, onGoToSign }: ExamAddonPanelProps) => {
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
)
|
||||
}
|
||||
</div >
|
||||
);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user