修复
This commit is contained in:
@@ -548,6 +548,8 @@ export interface InputPhysicalExamAddItem {
|
|||||||
scrm_account_name?: string | null;
|
scrm_account_name?: string | null;
|
||||||
/** 项目名称(默认空值,传入项目名称过滤数据) */
|
/** 项目名称(默认空值,传入项目名称过滤数据) */
|
||||||
item_name?: string;
|
item_name?: string;
|
||||||
|
/** 折扣率 */
|
||||||
|
discount_rate?: number | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -85,7 +85,7 @@ export const ExamAddonPanel = ({ client, onGoToSign }: ExamAddonPanelProps) => {
|
|||||||
} | null>(null);
|
} | null>(null);
|
||||||
const [customSettlementLoading, setCustomSettlementLoading] = useState(false);
|
const [customSettlementLoading, setCustomSettlementLoading] = useState(false);
|
||||||
const [customSettlementType, setCustomSettlementType] = useState<1 | 2>(1); // 1-按比例折扣 2-自定义结算价
|
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 [customFinalPrice, setCustomFinalPrice] = useState<number>(0); // 最终结算价
|
||||||
const [customApplyReason, setCustomApplyReason] = useState<string>(''); // 申请理由
|
const [customApplyReason, setCustomApplyReason] = useState<string>(''); // 申请理由
|
||||||
const [waitingSeconds, setWaitingSeconds] = useState<number>(0); // 等待审核的秒数
|
const [waitingSeconds, setWaitingSeconds] = useState<number>(0); // 等待审核的秒数
|
||||||
@@ -123,24 +123,15 @@ export const ExamAddonPanel = ({ client, onGoToSign }: ExamAddonPanelProps) => {
|
|||||||
try {
|
try {
|
||||||
const res = await getAddItemCustomerInfo({ physical_exam_id });
|
const res = await getAddItemCustomerInfo({ physical_exam_id });
|
||||||
if (res.Status === 200) {
|
if (res.Status === 200) {
|
||||||
// 保存客户信息
|
// 保存客户信息,渠道信息使用 listChannelDiscount 中的 channel_id / channel_name
|
||||||
if (res.Data?.customerInfo) {
|
if (res.Data?.customerInfo) {
|
||||||
const channelInfo = res.Data.listChannelDiscount?.[0];
|
const firstChannel = 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;
|
|
||||||
|
|
||||||
setCustomerInfo({
|
setCustomerInfo({
|
||||||
patient_id: res.Data.customerInfo.patient_id,
|
patient_id: res.Data.customerInfo.patient_id,
|
||||||
customer_name: res.Data.customerInfo.customer_name,
|
customer_name: res.Data.customerInfo.customer_name,
|
||||||
phone: res.Data.customerInfo.phone,
|
phone: res.Data.customerInfo.phone,
|
||||||
scrm_account_id,
|
scrm_account_id: firstChannel?.channel_id ?? null,
|
||||||
scrm_account_name,
|
scrm_account_name: firstChannel?.channel_name ?? null,
|
||||||
});
|
});
|
||||||
customerInfoLoadedRef.current = true;
|
customerInfoLoadedRef.current = true;
|
||||||
// 设置挂账公司默认值
|
// 设置挂账公司默认值
|
||||||
@@ -237,11 +228,19 @@ export const ExamAddonPanel = ({ client, onGoToSign }: ExamAddonPanelProps) => {
|
|||||||
setAddonLoading(true);
|
setAddonLoading(true);
|
||||||
setAddonError(null);
|
setAddonError(null);
|
||||||
try {
|
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({
|
const res = await searchPhysicalExamAddItem({
|
||||||
physical_exam_id: Number(client.id),
|
physical_exam_id: Number(client.id),
|
||||||
scrm_account_id: customerInfo?.scrm_account_id || null,
|
scrm_account_id: customerInfo?.scrm_account_id || null,
|
||||||
scrm_account_name: customerInfo?.scrm_account_name || null,
|
scrm_account_name: customerInfo?.scrm_account_name || null,
|
||||||
item_name: debouncedAddonSearch.trim() || "",
|
item_name: debouncedAddonSearch.trim() || "",
|
||||||
|
discount_rate: discountRate,
|
||||||
});
|
});
|
||||||
if (res.Status === 200 && Array.isArray(res.Data)) {
|
if (res.Status === 200 && Array.isArray(res.Data)) {
|
||||||
const list: AddonItem[] = res.Data.map((item) => ({
|
const list: AddonItem[] = res.Data.map((item) => ({
|
||||||
@@ -275,7 +274,7 @@ export const ExamAddonPanel = ({ client, onGoToSign }: ExamAddonPanelProps) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
fetchList();
|
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]);
|
const allAddons = useMemo(() => addonList, [addonList]);
|
||||||
|
|
||||||
@@ -335,14 +334,19 @@ export const ExamAddonPanel = ({ client, onGoToSign }: ExamAddonPanelProps) => {
|
|||||||
return item.discount_name;
|
return item.discount_name;
|
||||||
};
|
};
|
||||||
|
|
||||||
// 构建折扣选项列表
|
// 构建折扣选项列表(带上渠道ID/名称,便于联动设置 scrm_account_id / scrm_account_name)
|
||||||
const discountOptions = useMemo(() => {
|
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) => {
|
channelDiscounts.forEach((item) => {
|
||||||
const rate = typeof item.discount_rate === 'number' && item.discount_rate > 0 ? item.discount_rate : 1;
|
const rate = typeof item.discount_rate === 'number' && item.discount_rate > 0 ? item.discount_rate : 1;
|
||||||
const percent = Math.round(rate * 100);
|
const percent = Math.round(rate * 100);
|
||||||
const label = item.discount_name || `${percent}%`;
|
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;
|
return options;
|
||||||
}, [channelDiscounts]);
|
}, [channelDiscounts]);
|
||||||
@@ -353,9 +357,21 @@ export const ExamAddonPanel = ({ client, onGoToSign }: ExamAddonPanelProps) => {
|
|||||||
return option?.label;
|
return option?.label;
|
||||||
}, [discountRatio, discountOptions]);
|
}, [discountRatio, discountOptions]);
|
||||||
|
|
||||||
// 处理折扣选择
|
// 处理折扣选择,同时更新 scrm_account_id / scrm_account_name
|
||||||
const handleDiscountSelect = (value: number) => {
|
const handleDiscountSelect = (value: number) => {
|
||||||
setDiscountRatio(value);
|
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);
|
setIsDiscountDropdownOpen(false);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -503,7 +519,7 @@ export const ExamAddonPanel = ({ client, onGoToSign }: ExamAddonPanelProps) => {
|
|||||||
stopCustomSettlementPolling();
|
stopCustomSettlementPolling();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}, 1000);
|
}, 1500);
|
||||||
}, [fetchCustomSettlementStatus]);
|
}, [fetchCustomSettlementStatus]);
|
||||||
|
|
||||||
// 停止轮询自定义结算审批状态
|
// 停止轮询自定义结算审批状态
|
||||||
@@ -559,6 +575,12 @@ export const ExamAddonPanel = ({ client, onGoToSign }: ExamAddonPanelProps) => {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const discountRatioValue = customSettlementType === 1 ? (customDiscountRatio ?? 0) : 0;
|
||||||
|
if (customSettlementType === 1 && (discountRatioValue <= 0 || discountRatioValue > 100)) {
|
||||||
|
setPaymentMessage('请输入有效折扣比例');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
setCustomSettlementLoading(true);
|
setCustomSettlementLoading(true);
|
||||||
setPaymentMessage(null);
|
setPaymentMessage(null);
|
||||||
|
|
||||||
@@ -575,7 +597,7 @@ export const ExamAddonPanel = ({ client, onGoToSign }: ExamAddonPanelProps) => {
|
|||||||
|
|
||||||
if (customSettlementType === 1) {
|
if (customSettlementType === 1) {
|
||||||
// 按比例折扣
|
// 按比例折扣
|
||||||
settlementPrice = originalPrice * (customDiscountRatio / 100);
|
settlementPrice = originalPrice * (discountRatioValue / 100);
|
||||||
} else {
|
} else {
|
||||||
// 自定义结算价
|
// 自定义结算价
|
||||||
settlementPrice = customFinalPrice / selectedItems.length; // 平均分配
|
settlementPrice = customFinalPrice / selectedItems.length; // 平均分配
|
||||||
@@ -595,7 +617,7 @@ export const ExamAddonPanel = ({ client, onGoToSign }: ExamAddonPanelProps) => {
|
|||||||
}, 0);
|
}, 0);
|
||||||
|
|
||||||
const final_settlement_price = customSettlementType === 1
|
const final_settlement_price = customSettlementType === 1
|
||||||
? original_settlement_price * (customDiscountRatio / 100)
|
? original_settlement_price * (discountRatioValue / 100)
|
||||||
: customFinalPrice;
|
: customFinalPrice;
|
||||||
|
|
||||||
const res = await customSettlementApply({
|
const res = await customSettlementApply({
|
||||||
@@ -603,7 +625,7 @@ export const ExamAddonPanel = ({ client, onGoToSign }: ExamAddonPanelProps) => {
|
|||||||
listAddItemDetail,
|
listAddItemDetail,
|
||||||
original_settlement_price,
|
original_settlement_price,
|
||||||
settlement_type: customSettlementType,
|
settlement_type: customSettlementType,
|
||||||
discount_ratio: customSettlementType === 1 ? customDiscountRatio : undefined,
|
discount_ratio: customSettlementType === 1 ? discountRatioValue : undefined,
|
||||||
final_settlement_price,
|
final_settlement_price,
|
||||||
apply_reason: customApplyReason.trim(),
|
apply_reason: customApplyReason.trim(),
|
||||||
});
|
});
|
||||||
@@ -647,6 +669,7 @@ export const ExamAddonPanel = ({ client, onGoToSign }: ExamAddonPanelProps) => {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
stopCustomSettlementPolling();
|
||||||
setCustomSettlementLoading(true);
|
setCustomSettlementLoading(true);
|
||||||
setPaymentMessage(null);
|
setPaymentMessage(null);
|
||||||
|
|
||||||
@@ -668,6 +691,7 @@ export const ExamAddonPanel = ({ client, onGoToSign }: ExamAddonPanelProps) => {
|
|||||||
|
|
||||||
if (res.Status === 200 && res.Data?.is_success === 1) {
|
if (res.Status === 200 && res.Data?.is_success === 1) {
|
||||||
setPaymentMessage('取消申请成功');
|
setPaymentMessage('取消申请成功');
|
||||||
|
setCustomDiscountRatio(null);
|
||||||
// 停止轮询
|
// 停止轮询
|
||||||
stopCustomSettlementPolling();
|
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-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'>
|
<div className='flex items-center justify-between gap-2'>
|
||||||
<span></span>
|
<span></span>
|
||||||
<span className={`text-[10px] px-2 rounded-full bg-[#EAFCF1] text-[#447955] whitespace-nowrap`}>
|
<span className={`text-[10px] px-2 rounded-full bg-[#EAFCF1] text-[#447955] whitespace-nowrap`}>
|
||||||
{getDiscountText(item)}
|
{getDiscountText(item)}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div> */}
|
||||||
</div>
|
</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='border-t pt-4 mt-6 flex items-center justify-between'>
|
||||||
<div className='space-y-1 text-sm'>
|
<div className='flex items-center gap-2'>
|
||||||
<div className='text-gray-600'>
|
<div className='space-y-1 text-sm'>
|
||||||
加项原价合计: <span className='text-gray-900'>¥{totalOriginal.toFixed(2)}</span>
|
<div className='text-gray-600'>
|
||||||
</div>
|
原价: <span className='text-gray-900'>¥{totalOriginal.toFixed(2)}</span>
|
||||||
<div className='text-gray-600'>
|
</div>
|
||||||
渠道折扣价: <span className='text-xl font-bold text-red-600'>¥{totalCurrent.toFixed(2)}</span>
|
<div className='text-gray-600'>
|
||||||
{discount > 0 && (
|
优惠: <span className='font-bold text-red-600'>¥{discount.toFixed(2)}</span>
|
||||||
<span className='text-gray-500 ml-1'>已优惠 ¥{discount.toFixed(2)}</span>
|
</div>
|
||||||
)}
|
<div className='text-gray-600'>
|
||||||
</div>
|
结算价: <span className='font-bold text-red-600'>¥{(totalCurrent).toFixed(2)}</span>
|
||||||
{/* <div className='text-xs text-gray-500'>结算方式: 个人支付 (微信 / 支付宝)</div> */}
|
</div>
|
||||||
</div>
|
{/* <div className='text-xs text-gray-500'>结算方式: 个人支付 (微信 / 支付宝)</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'
|
|
||||||
)}
|
|
||||||
>
|
|
||||||
申请自定义结算
|
|
||||||
</Button>
|
|
||||||
</div>
|
</div>
|
||||||
)}
|
|
||||||
|
|
||||||
|
{/* 添加自定义结算 */}
|
||||||
|
{localStorage.getItem('authCode')?.includes('HisTijianPad_Btn_Tongji') && selectedItems.length > 0 && (
|
||||||
|
<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'
|
||||||
|
>
|
||||||
|
{!customSettlementStatus || !customSettlementStatus.apply_status || customSettlementStatus.apply_status === 1
|
||||||
|
? '申请自定义结算'
|
||||||
|
: customSettlementStatus.apply_status === 3
|
||||||
|
? '自定义结算(已通过)'
|
||||||
|
: '自定义结算(未通过)'}
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
{paymentMessage && (
|
{paymentMessage && (
|
||||||
@@ -1264,7 +1274,7 @@ export const ExamAddonPanel = ({ client, onGoToSign }: ExamAddonPanelProps) => {
|
|||||||
)}
|
)}
|
||||||
|
|
||||||
<Button
|
<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}
|
disabled={selectedCount === 0 || paymentLoading}
|
||||||
onClick={handlePayment}
|
onClick={handlePayment}
|
||||||
>
|
>
|
||||||
@@ -1273,223 +1283,234 @@ export const ExamAddonPanel = ({ client, onGoToSign }: ExamAddonPanelProps) => {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{/* 二维码支付弹窗 */}
|
{/* 二维码支付弹窗 */}
|
||||||
{showQrcodeModal && qrcodeUrl && (
|
{
|
||||||
<div className='fixed inset-0 z-[80] bg-black/80 flex items-center justify-center px-6'>
|
showQrcodeModal && qrcodeUrl && (
|
||||||
<div className='bg-white rounded-2xl w-full max-w-md shadow-2xl p-6 flex flex-col gap-4'>
|
<div className='fixed inset-0 z-[80] bg-black/80 flex items-center justify-center px-6'>
|
||||||
<div className='flex items-center justify-between'>
|
<div className='bg-white rounded-2xl w-full max-w-md shadow-2xl p-6 flex flex-col gap-4'>
|
||||||
<div className='text-lg font-semibold text-gray-900'>扫码支付</div>
|
<div className='flex items-center justify-between'>
|
||||||
<Button
|
<div className='text-lg font-semibold text-gray-900'>扫码支付</div>
|
||||||
className='py-1 px-3'
|
<Button
|
||||||
onClick={() => {
|
className='py-1 px-3'
|
||||||
if (pollingTimerRef.current) {
|
onClick={() => {
|
||||||
clearInterval(pollingTimerRef.current);
|
if (pollingTimerRef.current) {
|
||||||
pollingTimerRef.current = null;
|
clearInterval(pollingTimerRef.current);
|
||||||
}
|
pollingTimerRef.current = null;
|
||||||
setShowQrcodeModal(false);
|
}
|
||||||
setQrcodeUrl(null);
|
setShowQrcodeModal(false);
|
||||||
}}
|
setQrcodeUrl(null);
|
||||||
>
|
}}
|
||||||
关闭
|
>
|
||||||
</Button>
|
关闭
|
||||||
</div>
|
</Button>
|
||||||
<div className='flex flex-col items-center gap-4'>
|
|
||||||
<div className='bg-white p-4 rounded-lg border-2 border-gray-200'>
|
|
||||||
<img src={qrcodeUrl} alt='支付二维码' className='w-64 h-64 object-contain' />
|
|
||||||
</div>
|
</div>
|
||||||
<div className='text-sm text-gray-600 text-center'>
|
<div className='flex flex-col items-center gap-4'>
|
||||||
请使用微信扫描上方二维码完成支付
|
<div className='bg-white p-4 rounded-lg border-2 border-gray-200'>
|
||||||
</div>
|
<img src={qrcodeUrl} alt='支付二维码' className='w-64 h-64 object-contain' />
|
||||||
{paymentMessage && (
|
|
||||||
<div className={`text-sm ${paymentMessage.includes('成功') ? 'text-green-600' : 'text-amber-600'}`}>
|
|
||||||
{paymentMessage}
|
|
||||||
</div>
|
</div>
|
||||||
)}
|
<div className='text-sm text-gray-600 text-center'>
|
||||||
|
请使用微信扫描上方二维码完成支付
|
||||||
|
</div>
|
||||||
|
{paymentMessage && (
|
||||||
|
<div className={`text-sm ${paymentMessage.includes('成功') ? 'text-green-600' : 'text-amber-600'}`}>
|
||||||
|
{paymentMessage}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
)
|
||||||
)}
|
}
|
||||||
|
|
||||||
{/* 自定义结算弹窗 */}
|
{/* 自定义结算弹窗 */}
|
||||||
{showCustomSettlementModal && (
|
{
|
||||||
<div className='fixed inset-0 z-50 flex items-center justify-center bg-black/30' onClick={() => setShowCustomSettlementModal(false)}>
|
showCustomSettlementModal && (
|
||||||
<div
|
<div className='fixed inset-0 z-50 flex items-center justify-center bg-black/30' onClick={() => setShowCustomSettlementModal(false)}>
|
||||||
className='w-[500px] max-w-[95vw] bg-white rounded-2xl shadow-xl overflow-hidden'
|
<div
|
||||||
onClick={(e) => e.stopPropagation()}
|
className='w-[500px] max-w-[95vw] bg-white rounded-2xl shadow-xl overflow-hidden'
|
||||||
>
|
onClick={(e) => e.stopPropagation()}
|
||||||
<div className='px-4 py-3 border-b flex items-center justify-between'>
|
>
|
||||||
<div className='font-semibold'>自定义结算申请</div>
|
<div className='px-4 py-3 border-b flex items-center justify-between'>
|
||||||
<button
|
<div className='font-semibold'>自定义结算申请</div>
|
||||||
className='text-xs text-gray-500 hover:text-gray-700'
|
<button
|
||||||
onClick={() => setShowCustomSettlementModal(false)}
|
className='text-xs text-gray-500 hover:text-gray-700'
|
||||||
>
|
onClick={() => setShowCustomSettlementModal(false)}
|
||||||
关闭
|
>
|
||||||
</button>
|
关闭
|
||||||
</div>
|
</button>
|
||||||
|
|
||||||
<div className='px-4 py-6 space-y-4'>
|
|
||||||
{/* 选中项目信息 */}
|
|
||||||
<div className='text-sm text-gray-700'>
|
|
||||||
<div className='font-medium mb-2'>选中项目 ({selectedItems.length}项):</div>
|
|
||||||
<div className='max-h-32 overflow-y-auto space-y-1'>
|
|
||||||
{selectedItems.map((item, idx) => (
|
|
||||||
<div key={idx} className='text-xs text-gray-600 flex justify-between'>
|
|
||||||
<span>{item.name}</span>
|
|
||||||
<span>¥{parseFloat(item.currentPrice || item.originalPrice || '0').toFixed(2)}</span>
|
|
||||||
</div>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
<div className='mt-2 pt-2 border-t text-sm font-semibold flex justify-between'>
|
|
||||||
<span>渠道折扣价合计:</span>
|
|
||||||
<span className='text-red-600'>¥{totalCurrent.toFixed(2)}</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* 结算方式 */}
|
<div className='px-4 py-6 space-y-4'>
|
||||||
<div className='space-y-2'>
|
{/* 选中项目信息 */}
|
||||||
<label className='text-sm text-gray-700 font-medium'>结算方式</label>
|
<div className='text-sm text-gray-700'>
|
||||||
<div className='flex gap-3'>
|
<div className='font-medium mb-2'>选中项目 ({selectedItems.length}项):</div>
|
||||||
<button
|
<div className='max-h-32 overflow-y-auto space-y-1'>
|
||||||
type='button'
|
{selectedItems.map((item, idx) => (
|
||||||
onClick={() => setCustomSettlementType(1)}
|
<div key={idx} className='text-xs text-gray-600 flex justify-between'>
|
||||||
className={cls(
|
<span>{item.name}</span>
|
||||||
'flex-1 px-4 py-2 rounded-lg border text-sm transition-colors',
|
<span>¥{parseFloat(item.currentPrice || item.originalPrice || '0').toFixed(2)}</span>
|
||||||
customSettlementType === 1
|
</div>
|
||||||
? 'bg-blue-50 border-blue-500 text-blue-700 font-medium'
|
))}
|
||||||
: 'bg-white border-gray-300 text-gray-700 hover:border-gray-400'
|
|
||||||
)}
|
|
||||||
>
|
|
||||||
按比例折扣
|
|
||||||
</button>
|
|
||||||
<button
|
|
||||||
type='button'
|
|
||||||
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'
|
|
||||||
)}
|
|
||||||
>
|
|
||||||
自定义结算价
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* 折扣比例或最终结算价 */}
|
|
||||||
{customSettlementType === 1 ? (
|
|
||||||
<div className='space-y-3'>
|
|
||||||
<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)}折
|
|
||||||
</span>
|
|
||||||
</div>
|
</div>
|
||||||
<div className='flex items-center gap-2'>
|
<div className='mt-2 pt-2 border-t text-sm font-semibold flex justify-between'>
|
||||||
|
<span>渠道折扣价合计:</span>
|
||||||
|
<span className='text-red-600'>¥{totalCurrent.toFixed(2)}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* 结算方式 */}
|
||||||
|
<div className='space-y-2'>
|
||||||
|
<label className='text-sm text-gray-700 font-medium'>结算方式</label>
|
||||||
|
<div className='flex gap-3'>
|
||||||
|
<button
|
||||||
|
type='button'
|
||||||
|
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'
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
按比例折扣
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
type='button'
|
||||||
|
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'
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
自定义结算价
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* 折扣比例或最终结算价 */}
|
||||||
|
{customSettlementType === 1 ? (
|
||||||
|
<div className='space-y-3'>
|
||||||
|
<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 ?? 0) / 10).toFixed(1)}折
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div className='flex items-center gap-2'>
|
||||||
|
<Input
|
||||||
|
type='number'
|
||||||
|
min='0'
|
||||||
|
max='100'
|
||||||
|
step='1'
|
||||||
|
value={customDiscountRatio ?? ''}
|
||||||
|
onChange={(e) => {
|
||||||
|
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'
|
||||||
|
/>
|
||||||
|
<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 ?? 0) / 100)).toFixed(2)}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<div className='space-y-2'>
|
||||||
|
<label className='text-sm text-gray-700 font-medium'>最终结算价 (¥)</label>
|
||||||
<Input
|
<Input
|
||||||
type='number'
|
type='number'
|
||||||
min='10'
|
min='0'
|
||||||
max='100'
|
step='0.01'
|
||||||
step='1'
|
value={customFinalPrice || ''}
|
||||||
value={customDiscountRatio}
|
|
||||||
onChange={(e) => {
|
onChange={(e) => {
|
||||||
const val = Number(e.target.value);
|
const val = Number(e.target.value);
|
||||||
if (Number.isNaN(val)) return;
|
if (val >= 0) {
|
||||||
if (val < 10) {
|
setCustomFinalPrice(val);
|
||||||
setCustomDiscountRatio(10);
|
|
||||||
} else if (val > 100) {
|
|
||||||
setCustomDiscountRatio(100);
|
|
||||||
} else {
|
|
||||||
setCustomDiscountRatio(val);
|
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
className='w-28 text-sm'
|
placeholder='请输入最终结算价'
|
||||||
|
className='text-sm'
|
||||||
/>
|
/>
|
||||||
<span className='text-xs text-gray-500'>10-100,100 表示不打折</span>
|
|
||||||
</div>
|
</div>
|
||||||
<div className='text-xs text-gray-500'>
|
)}
|
||||||
最终结算价: <span className='font-semibold text-red-600'>¥{(totalCurrent * (customDiscountRatio / 100)).toFixed(2)}</span>
|
|
||||||
</div>
|
{/* 申请理由 */}
|
||||||
</div>
|
|
||||||
) : (
|
|
||||||
<div className='space-y-2'>
|
<div className='space-y-2'>
|
||||||
<label className='text-sm text-gray-700 font-medium'>最终结算价 (¥)</label>
|
<label className='text-sm text-gray-700 font-medium'>申请理由 *</label>
|
||||||
<Input
|
<textarea
|
||||||
type='number'
|
value={customApplyReason}
|
||||||
min='0'
|
onChange={(e) => setCustomApplyReason(e.target.value)}
|
||||||
step='0.01'
|
placeholder='请输入申请理由'
|
||||||
value={customFinalPrice || ''}
|
rows={3}
|
||||||
onChange={(e) => {
|
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'
|
||||||
const val = Number(e.target.value);
|
|
||||||
if (val >= 0) {
|
|
||||||
setCustomFinalPrice(val);
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
placeholder='请输入最终结算价'
|
|
||||||
className='text-sm'
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
)}
|
|
||||||
|
|
||||||
{/* 申请理由 */}
|
{/* 提交按钮 */}
|
||||||
<div className='space-y-2'>
|
<div className='flex gap-3 pt-2'>
|
||||||
<label className='text-sm text-gray-700 font-medium'>申请理由 *</label>
|
<Button
|
||||||
<textarea
|
onClick={() => setShowCustomSettlementModal(false)}
|
||||||
value={customApplyReason}
|
className='flex-1 px-4 py-2 bg-gray-100 hover:bg-gray-200 text-gray-700'
|
||||||
onChange={(e) => setCustomApplyReason(e.target.value)}
|
>
|
||||||
placeholder='请输入申请理由'
|
取消
|
||||||
rows={3}
|
</Button>
|
||||||
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'
|
<Button
|
||||||
/>
|
onClick={handleSubmitCustomSettlement}
|
||||||
</div>
|
disabled={customSettlementLoading || !customApplyReason.trim()}
|
||||||
|
className={cls(
|
||||||
{/* 提交按钮 */}
|
'flex-1 px-4 py-2 text-white font-medium',
|
||||||
<div className='flex gap-3 pt-2'>
|
customSettlementLoading || !customApplyReason.trim()
|
||||||
<Button
|
? 'bg-gray-400 cursor-not-allowed'
|
||||||
onClick={() => setShowCustomSettlementModal(false)}
|
: 'bg-blue-600 hover:bg-blue-700'
|
||||||
className='flex-1 px-4 py-2 bg-gray-100 hover:bg-gray-200 text-gray-700'
|
)}
|
||||||
>
|
>
|
||||||
取消
|
{customSettlementLoading ? '提交中...' : '提交申请'}
|
||||||
</Button>
|
</Button>
|
||||||
<Button
|
</div>
|
||||||
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>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
)
|
||||||
)}
|
}
|
||||||
|
|
||||||
{/* 审核中全屏遮罩 */}
|
{/* 审核中全屏遮罩 */}
|
||||||
{customSettlementStatus?.apply_status === 1 && (
|
{
|
||||||
<div className='fixed inset-0 bg-black/50 backdrop-blur-sm flex items-center justify-center z-50'>
|
customSettlementStatus?.apply_status === 1 && (
|
||||||
<div className='bg-white rounded-2xl p-6 max-w-md w-full mx-4 shadow-xl'>
|
<div className='fixed inset-0 bg-black/50 backdrop-blur-sm flex items-center justify-center z-50'>
|
||||||
<div className='text-center mb-6'>
|
<div className='bg-white rounded-2xl p-6 max-w-md w-full mx-4 shadow-xl'>
|
||||||
<div className='text-lg font-semibold text-blue-600 mb-2'>审核中...</div>
|
<div className='text-center mb-6'>
|
||||||
<div className='text-sm text-gray-500 mb-1'>正在等待审核结果,请稍候</div>
|
<div className='text-lg font-semibold text-blue-600 mb-2'>审核中...</div>
|
||||||
<div className='text-xs text-gray-400'>已等待 {waitingSeconds} 秒</div>
|
<div className='text-sm text-gray-500 mb-1'>正在等待审核结果,请稍候</div>
|
||||||
</div>
|
<div className='text-xs text-gray-400'>已等待 {waitingSeconds} 秒</div>
|
||||||
<div className='flex justify-center'>
|
</div>
|
||||||
<Button
|
<div className='flex justify-center'>
|
||||||
onClick={handleCancelCustomSettlement}
|
<Button
|
||||||
disabled={customSettlementLoading}
|
onClick={handleCancelCustomSettlement}
|
||||||
className='px-6 py-2 bg-gray-500 hover:bg-gray-600 text-white disabled:opacity-50'
|
disabled={customSettlementLoading}
|
||||||
>
|
className='px-6 py-2 bg-gray-500 hover:bg-gray-600 text-white disabled:opacity-50'
|
||||||
{customSettlementLoading ? '取消中...' : '取消申请'}
|
>
|
||||||
</Button>
|
{customSettlementLoading ? '取消中...' : '取消申请'}
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
)
|
||||||
)}
|
}
|
||||||
</div>
|
</div >
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user