新增加项需求
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
import { useEffect, useMemo, useState, useRef } from 'react';
|
||||
import { useEffect, useMemo, useState, useRef, useCallback } from 'react';
|
||||
|
||||
import type { ExamClient } from '../../data/mockData';
|
||||
import { searchPhysicalExamAddItem, getAddItemCustomerInfo, getChannelCompanyList, createNativePaymentQrcode, checkNativePaymentStatus, getAddItemBillPdf } from '../../api';
|
||||
import { searchPhysicalExamAddItem, getAddItemCustomerInfo, getChannelCompanyList, createNativePaymentQrcode, checkNativePaymentStatus, getAddItemBillPdf, getCustomSettlementApproveStatus, customSettlementApply, customSettlementApplyCancel } from '../../api';
|
||||
import { Button, Input } from '../ui';
|
||||
import { cls } from '../../utils/cls';
|
||||
import nozImage from '../../assets/image/noz.png';
|
||||
@@ -72,6 +72,24 @@ export const ExamAddonPanel = ({ client, onGoToSign }: ExamAddonPanelProps) => {
|
||||
const [paymentLoading, setPaymentLoading] = useState(false);
|
||||
const [paymentMessage, setPaymentMessage] = useState<string | null>(null);
|
||||
const pollingTimerRef = useRef<number | null>(null);
|
||||
// 跟踪客户信息是否已加载(用于避免重复请求加项列表)
|
||||
const customerInfoLoadedRef = useRef<boolean>(false);
|
||||
// 自定义结算相关状态
|
||||
const customSettlementPollingTimerRef = useRef<number | null>(null);
|
||||
const lastFetchStatusTimeRef = useRef<number>(0); // 上次获取审批状态的时间戳
|
||||
const [showCustomSettlementModal, setShowCustomSettlementModal] = useState(false);
|
||||
const [customSettlementStatus, setCustomSettlementStatus] = useState<{
|
||||
apply_status?: number;
|
||||
apply_status_name?: string | null;
|
||||
final_settlement_price?: number | null;
|
||||
} | 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 [customFinalPrice, setCustomFinalPrice] = useState<number>(0); // 最终结算价
|
||||
const [customApplyReason, setCustomApplyReason] = useState<string>(''); // 申请理由
|
||||
const [waitingSeconds, setWaitingSeconds] = useState<number>(0); // 等待审核的秒数
|
||||
const waitingTimerRef = useRef<number | null>(null); // 等待计时器
|
||||
|
||||
// 点击外部关闭下拉框
|
||||
useEffect(() => {
|
||||
@@ -124,6 +142,7 @@ export const ExamAddonPanel = ({ client, onGoToSign }: ExamAddonPanelProps) => {
|
||||
scrm_account_id,
|
||||
scrm_account_name,
|
||||
});
|
||||
customerInfoLoadedRef.current = true;
|
||||
// 设置挂账公司默认值
|
||||
const companyName = res.Data.customerInfo.company_name;
|
||||
if (companyName && companyName.trim() !== '') {
|
||||
@@ -149,9 +168,14 @@ export const ExamAddonPanel = ({ client, onGoToSign }: ExamAddonPanelProps) => {
|
||||
}
|
||||
} catch (err) {
|
||||
console.error('获取加项客户信息失败', err);
|
||||
} finally {
|
||||
// 无论成功或失败,都标记为已尝试加载
|
||||
customerInfoLoadedRef.current = true;
|
||||
}
|
||||
};
|
||||
|
||||
// 当 client.id 变化时,重置加载状态
|
||||
customerInfoLoadedRef.current = false;
|
||||
fetchCustomerInfo();
|
||||
}, [client.id]);
|
||||
|
||||
@@ -205,6 +229,10 @@ export const ExamAddonPanel = ({ client, onGoToSign }: ExamAddonPanelProps) => {
|
||||
|
||||
// 拉取加项列表
|
||||
useEffect(() => {
|
||||
if (!customerInfoLoadedRef.current && customerInfo === null) {
|
||||
return;
|
||||
}
|
||||
|
||||
const fetchList = async () => {
|
||||
setAddonLoading(true);
|
||||
setAddonError(null);
|
||||
@@ -249,7 +277,7 @@ export const ExamAddonPanel = ({ client, onGoToSign }: ExamAddonPanelProps) => {
|
||||
}
|
||||
};
|
||||
fetchList();
|
||||
}, [debouncedAddonSearch, customerInfo?.scrm_account_id, customerInfo?.scrm_account_name, client.id]);
|
||||
}, [debouncedAddonSearch, customerInfo?.scrm_account_id, customerInfo?.scrm_account_name, client.id, customerInfo]);
|
||||
|
||||
const allAddons = useMemo(() => addonList, [addonList]);
|
||||
|
||||
@@ -279,9 +307,15 @@ export const ExamAddonPanel = ({ client, onGoToSign }: ExamAddonPanelProps) => {
|
||||
const totalOriginal = selectedItems.reduce((sum, item) => {
|
||||
return sum + parseFloat(item.originalPrice || item.currentPrice || '0');
|
||||
}, 0);
|
||||
const totalCurrent = selectedItems.reduce((sum, item) => {
|
||||
const totalCurrentBase = selectedItems.reduce((sum, item) => {
|
||||
return sum + parseFloat(item.currentPrice || item.originalPrice || '0');
|
||||
}, 0);
|
||||
|
||||
// 如果自定义结算审核通过,使用审核后的金额
|
||||
const totalCurrent = (customSettlementStatus?.apply_status === 3 && typeof customSettlementStatus.final_settlement_price === 'number')
|
||||
? customSettlementStatus.final_settlement_price
|
||||
: totalCurrentBase;
|
||||
|
||||
const discount = totalOriginal - totalCurrent;
|
||||
|
||||
// 获取标签样式
|
||||
@@ -382,6 +416,277 @@ 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) {
|
||||
setCustomSettlementStatus(null);
|
||||
return false;
|
||||
}
|
||||
|
||||
// 节流:如果距离上次调用不足0.8秒,则跳过
|
||||
const now = Date.now();
|
||||
const timeSinceLastCall = now - lastFetchStatusTimeRef.current;
|
||||
if (timeSinceLastCall < 800) {
|
||||
// 返回当前状态是否需要轮询
|
||||
return customSettlementStatus?.apply_status === 1;
|
||||
}
|
||||
lastFetchStatusTimeRef.current = now;
|
||||
|
||||
try {
|
||||
const res = await getCustomSettlementApproveStatus({
|
||||
physical_exam_id,
|
||||
add_item_id,
|
||||
});
|
||||
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,
|
||||
};
|
||||
setCustomSettlementStatus(status);
|
||||
// 如果状态变为审核中,重置等待时间
|
||||
if (res.Data.apply_status === 1 && customSettlementStatus?.apply_status !== 1) {
|
||||
setWaitingSeconds(0);
|
||||
}
|
||||
// 返回是否需要继续轮询(1-审核中 需要轮询)
|
||||
return res.Data.apply_status === 1;
|
||||
} else {
|
||||
setCustomSettlementStatus(null);
|
||||
return false;
|
||||
}
|
||||
} catch (err) {
|
||||
console.error('获取自定义结算审批状态失败', err);
|
||||
setCustomSettlementStatus(null);
|
||||
return false;
|
||||
}
|
||||
}, [client.id, selectedIds, allAddons, customSettlementStatus]);
|
||||
|
||||
// 当选中加项变化时,获取审批状态
|
||||
useEffect(() => {
|
||||
const currentSelectedItems = allAddons.filter(item => selectedIds.has(item.id || item.name));
|
||||
if (currentSelectedItems.length > 0) {
|
||||
fetchCustomSettlementStatus().then((shouldPoll) => {
|
||||
// 如果需要轮询(审核中),开始轮询
|
||||
if (shouldPoll) {
|
||||
startCustomSettlementPolling();
|
||||
} else {
|
||||
stopCustomSettlementPolling();
|
||||
}
|
||||
});
|
||||
} else {
|
||||
setCustomSettlementStatus(null);
|
||||
stopCustomSettlementPolling();
|
||||
}
|
||||
}, [selectedIds, client.id, allAddons, fetchCustomSettlementStatus]);
|
||||
|
||||
// 开始轮询自定义结算审批状态
|
||||
const startCustomSettlementPolling = useCallback(() => {
|
||||
// 清除之前的定时器
|
||||
stopCustomSettlementPolling();
|
||||
|
||||
// 每1秒轮询一次
|
||||
customSettlementPollingTimerRef.current = window.setInterval(() => {
|
||||
fetchCustomSettlementStatus().then((shouldPoll) => {
|
||||
// 如果不再需要轮询(审核完成),停止轮询
|
||||
if (!shouldPoll) {
|
||||
stopCustomSettlementPolling();
|
||||
}
|
||||
});
|
||||
}, 1000);
|
||||
}, [fetchCustomSettlementStatus]);
|
||||
|
||||
// 停止轮询自定义结算审批状态
|
||||
const stopCustomSettlementPolling = useCallback(() => {
|
||||
if (customSettlementPollingTimerRef.current) {
|
||||
clearInterval(customSettlementPollingTimerRef.current);
|
||||
customSettlementPollingTimerRef.current = null;
|
||||
}
|
||||
}, []);
|
||||
|
||||
// 清理轮询定时器
|
||||
useEffect(() => {
|
||||
return () => {
|
||||
stopCustomSettlementPolling();
|
||||
};
|
||||
}, [stopCustomSettlementPolling]);
|
||||
|
||||
// 等待计时器:当审核中时开始计时
|
||||
useEffect(() => {
|
||||
if (customSettlementStatus?.apply_status === 1) {
|
||||
// 开始计时
|
||||
setWaitingSeconds(0);
|
||||
waitingTimerRef.current = window.setInterval(() => {
|
||||
setWaitingSeconds((prev) => prev + 1);
|
||||
}, 1000);
|
||||
} else {
|
||||
// 停止计时并重置
|
||||
if (waitingTimerRef.current) {
|
||||
clearInterval(waitingTimerRef.current);
|
||||
waitingTimerRef.current = null;
|
||||
}
|
||||
setWaitingSeconds(0);
|
||||
}
|
||||
|
||||
return () => {
|
||||
if (waitingTimerRef.current) {
|
||||
clearInterval(waitingTimerRef.current);
|
||||
waitingTimerRef.current = null;
|
||||
}
|
||||
};
|
||||
}, [customSettlementStatus?.apply_status]);
|
||||
|
||||
// 提交自定义结算申请
|
||||
const handleSubmitCustomSettlement = async () => {
|
||||
const physical_exam_id = Number(client.id);
|
||||
if (!physical_exam_id || selectedItems.length === 0) {
|
||||
setPaymentMessage('请先选择加项项目');
|
||||
return;
|
||||
}
|
||||
|
||||
if (!customApplyReason.trim()) {
|
||||
setPaymentMessage('请输入申请理由');
|
||||
return;
|
||||
}
|
||||
|
||||
setCustomSettlementLoading(true);
|
||||
setPaymentMessage(null);
|
||||
|
||||
try {
|
||||
// 构建加项项目明细列表
|
||||
const listAddItemDetail = selectedItems
|
||||
.map(item => {
|
||||
const combinationItemCode = item.combinationItemCode;
|
||||
if (combinationItemCode === null || combinationItemCode === undefined) {
|
||||
return null;
|
||||
}
|
||||
const originalPrice = parseFloat(item.originalPrice || '0');
|
||||
let settlementPrice = originalPrice;
|
||||
|
||||
if (customSettlementType === 1) {
|
||||
// 按比例折扣
|
||||
settlementPrice = originalPrice * (customDiscountRatio / 100);
|
||||
} else {
|
||||
// 自定义结算价
|
||||
settlementPrice = customFinalPrice / selectedItems.length; // 平均分配
|
||||
}
|
||||
|
||||
return {
|
||||
combination_item_code: String(combinationItemCode),
|
||||
combination_item_name: item.name,
|
||||
original_price: originalPrice,
|
||||
settlement_price: settlementPrice,
|
||||
};
|
||||
})
|
||||
.filter((item): item is { combination_item_code: string; combination_item_name: string; original_price: number; settlement_price: number } => item !== null);
|
||||
|
||||
const original_settlement_price = selectedItems.reduce((sum, item) => {
|
||||
return sum + parseFloat(item.currentPrice || item.originalPrice || '0');
|
||||
}, 0);
|
||||
|
||||
const final_settlement_price = customSettlementType === 1
|
||||
? original_settlement_price * (customDiscountRatio / 100)
|
||||
: customFinalPrice;
|
||||
|
||||
const res = await customSettlementApply({
|
||||
physical_exam_id,
|
||||
listAddItemDetail,
|
||||
original_settlement_price,
|
||||
settlement_type: customSettlementType,
|
||||
discount_ratio: customSettlementType === 1 ? customDiscountRatio : undefined,
|
||||
final_settlement_price,
|
||||
apply_reason: customApplyReason.trim(),
|
||||
});
|
||||
|
||||
if (res.Status === 200) {
|
||||
setPaymentMessage('自定义结算申请提交成功');
|
||||
setShowCustomSettlementModal(false);
|
||||
// 重置表单
|
||||
setCustomSettlementType(1);
|
||||
setCustomDiscountRatio(100);
|
||||
setCustomFinalPrice(0);
|
||||
setCustomApplyReason('');
|
||||
// 重新获取审批状态并开始轮询
|
||||
setTimeout(() => {
|
||||
fetchCustomSettlementStatus().then((shouldPoll) => {
|
||||
if (shouldPoll) {
|
||||
startCustomSettlementPolling();
|
||||
}
|
||||
});
|
||||
}, 500);
|
||||
} else {
|
||||
setPaymentMessage(res.Message || '提交失败,请稍后重试');
|
||||
}
|
||||
} catch (err) {
|
||||
console.error('提交自定义结算申请失败', err);
|
||||
setPaymentMessage('提交失败,请稍后重试');
|
||||
} finally {
|
||||
setCustomSettlementLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
// 取消自定义结算申请
|
||||
const handleCancelCustomSettlement = async () => {
|
||||
const physical_exam_id = Number(client.id);
|
||||
if (!physical_exam_id || selectedItems.length === 0) {
|
||||
setPaymentMessage('请先选择加项项目');
|
||||
return;
|
||||
}
|
||||
|
||||
if (!window.confirm('确定要取消自定义结算申请吗?')) {
|
||||
return;
|
||||
}
|
||||
|
||||
setCustomSettlementLoading(true);
|
||||
setPaymentMessage(null);
|
||||
|
||||
try {
|
||||
const add_item_id = selectedItems
|
||||
.map(item => item.combinationItemCode)
|
||||
.filter((code): code is number => code !== null && code !== undefined)
|
||||
.join(',');
|
||||
|
||||
if (!add_item_id) {
|
||||
setPaymentMessage('无法获取加项项目ID');
|
||||
return;
|
||||
}
|
||||
|
||||
const res = await customSettlementApplyCancel({
|
||||
physical_exam_id,
|
||||
add_item_id,
|
||||
});
|
||||
|
||||
if (res.Status === 200 && res.Data?.is_success === 1) {
|
||||
setPaymentMessage('取消申请成功');
|
||||
// 停止轮询
|
||||
stopCustomSettlementPolling();
|
||||
// 重新获取审批状态
|
||||
setTimeout(() => {
|
||||
fetchCustomSettlementStatus();
|
||||
}, 500);
|
||||
} else {
|
||||
setPaymentMessage(res.Message || '取消申请失败,请稍后重试');
|
||||
}
|
||||
} catch (err) {
|
||||
console.error('取消自定义结算申请失败', err);
|
||||
setPaymentMessage('取消申请失败,请稍后重试');
|
||||
} finally {
|
||||
setCustomSettlementLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
// 获取加项PDF(按本次支付的组合代码生成对应的加项单)
|
||||
const fetchAddItemBillPdf = async (examId: number, combinationItemCodes: string) => {
|
||||
try {
|
||||
@@ -797,9 +1102,46 @@ export const ExamAddonPanel = ({ client, onGoToSign }: ExamAddonPanelProps) => {
|
||||
{/* <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'
|
||||
)}
|
||||
>
|
||||
自定义结算
|
||||
</Button>
|
||||
</div>
|
||||
)}
|
||||
|
||||
|
||||
{paymentMessage && (
|
||||
<div className={`text-sm text-center mt-2 ${paymentMessage.includes('成功') ? 'text-green-600' : 'text-amber-600'}`}>
|
||||
{paymentMessage}
|
||||
</div>
|
||||
)}
|
||||
|
||||
@@ -959,6 +1301,191 @@ export const ExamAddonPanel = ({ client, onGoToSign }: ExamAddonPanelProps) => {
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* 自定义结算弹窗 */}
|
||||
{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'
|
||||
onClick={(e) => e.stopPropagation()}
|
||||
>
|
||||
<div className='px-4 py-3 border-b flex items-center justify-between'>
|
||||
<div className='font-semibold'>自定义结算申请</div>
|
||||
<button
|
||||
className='text-xs text-gray-500 hover:text-gray-700'
|
||||
onClick={() => setShowCustomSettlementModal(false)}
|
||||
>
|
||||
关闭
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<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 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 / 10}折</span>
|
||||
</div>
|
||||
<div className='relative'>
|
||||
<input
|
||||
type='range'
|
||||
min='10'
|
||||
max='100'
|
||||
step='5'
|
||||
value={customDiscountRatio}
|
||||
onChange={(e) => {
|
||||
setCustomDiscountRatio(Number(e.target.value));
|
||||
}}
|
||||
className='w-full h-2 bg-gray-200 rounded-lg appearance-none cursor-pointer accent-blue-600'
|
||||
style={{
|
||||
background: `linear-gradient(to right, #3b82f6 0%, #3b82f6 ${((customDiscountRatio - 10) / (100 - 10)) * 100}%, #e5e7eb ${((customDiscountRatio - 10) / (100 - 10)) * 100}%, #e5e7eb 100%)`
|
||||
}}
|
||||
/>
|
||||
{/* 刻度标记 */}
|
||||
<div className='flex justify-between mt-1 px-1'>
|
||||
{[10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80, 85, 90, 95, 100].map((value) => (
|
||||
<span
|
||||
key={value}
|
||||
className='text-[10px] text-gray-400'
|
||||
style={{ width: '10px' }}
|
||||
>
|
||||
{value / 10}
|
||||
</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'>
|
||||
<label className='text-sm text-gray-700 font-medium'>最终结算价 (¥)</label>
|
||||
<Input
|
||||
type='number'
|
||||
min='0'
|
||||
step='0.01'
|
||||
value={customFinalPrice || ''}
|
||||
onChange={(e) => {
|
||||
const val = Number(e.target.value);
|
||||
if (val >= 0) {
|
||||
setCustomFinalPrice(val);
|
||||
}
|
||||
}}
|
||||
placeholder='请输入最终结算价'
|
||||
className='text-sm'
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* 申请理由 */}
|
||||
<div className='space-y-2'>
|
||||
<label className='text-sm text-gray-700 font-medium'>申请理由 *</label>
|
||||
<textarea
|
||||
value={customApplyReason}
|
||||
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'
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* 提交按钮 */}
|
||||
<div className='flex gap-3 pt-2'>
|
||||
<Button
|
||||
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 ? '提交中...' : '提交申请'}
|
||||
</Button>
|
||||
</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'>
|
||||
<div className='bg-white rounded-2xl p-6 max-w-md w-full mx-4 shadow-xl'>
|
||||
<div className='text-center mb-6'>
|
||||
<div className='text-lg font-semibold text-blue-600 mb-2'>审核中...</div>
|
||||
<div className='text-sm text-gray-500 mb-1'>正在等待审核结果,请稍候</div>
|
||||
<div className='text-xs text-gray-400'>已等待 {waitingSeconds} 秒</div>
|
||||
</div>
|
||||
<div className='flex justify-center'>
|
||||
<Button
|
||||
onClick={handleCancelCustomSettlement}
|
||||
disabled={customSettlementLoading}
|
||||
className='px-6 py-2 bg-gray-500 hover:bg-gray-600 text-white disabled:opacity-50'
|
||||
>
|
||||
{customSettlementLoading ? '取消中...' : '取消申请'}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user