934 lines
43 KiB
JavaScript
934 lines
43 KiB
JavaScript
// 【重要】必须使用 const Component 作为组件变量名
|
||
// 账单管理 - 车辆资产管理后台(按 antd 规范)
|
||
|
||
const Component = function() {
|
||
var useState = React.useState;
|
||
var useCallback = React.useCallback;
|
||
var useMemo = React.useMemo;
|
||
var useEffect = React.useEffect;
|
||
|
||
var antd = window.antd;
|
||
var Breadcrumb = antd.Breadcrumb;
|
||
var Card = antd.Card;
|
||
var Select = antd.Select;
|
||
var Button = antd.Button;
|
||
var Table = antd.Table;
|
||
var Tag = antd.Tag;
|
||
var Modal = antd.Modal;
|
||
var Input = antd.Input;
|
||
var message = antd.message;
|
||
var Space = antd.Space;
|
||
var Row = antd.Row;
|
||
var Col = antd.Col;
|
||
|
||
// 当前视图:list | detail
|
||
var viewState = useState('list');
|
||
var currentView = viewState[0];
|
||
var setCurrentView = viewState[1];
|
||
|
||
// 分页
|
||
var pageState = useState(1);
|
||
var currentPage = pageState[0];
|
||
var setCurrentPage = pageState[1];
|
||
var pageSizeState = useState(10);
|
||
var pageSize = pageSizeState[0];
|
||
var setPageSize = pageSizeState[1];
|
||
|
||
// 选中项(Table rowSelection 用)
|
||
var selectedRowKeysState = useState([]);
|
||
var selectedRowKeys = selectedRowKeysState[0];
|
||
var setSelectedRowKeys = selectedRowKeysState[1];
|
||
|
||
// 筛选器(表单值)
|
||
var contractFilterState = useState(undefined);
|
||
var contractFilter = contractFilterState[0];
|
||
var setContractFilter = contractFilterState[1];
|
||
var projectFilterState = useState(undefined);
|
||
var projectFilter = projectFilterState[0];
|
||
var setProjectFilter = projectFilterState[1];
|
||
var customerFilterState = useState(undefined);
|
||
var customerFilter = customerFilterState[0];
|
||
var setCustomerFilter = customerFilterState[1];
|
||
var statusFilterState = useState([]);
|
||
var statusFilter = statusFilterState[0];
|
||
var setStatusFilter = statusFilterState[1];
|
||
|
||
// 已应用的筛选条件(点击查询后生效)
|
||
var appliedFilterState = useState({ contract: '', project: '', customer: '', status: [] });
|
||
var appliedFilter = appliedFilterState[0];
|
||
var setAppliedFilter = appliedFilterState[1];
|
||
|
||
// 弹窗:应付金额明细 | 服务费明细
|
||
var popoverState = useState({ type: null, data: null });
|
||
var popover = popoverState[0];
|
||
var setPopover = popoverState[1];
|
||
|
||
// 照片查看器
|
||
var photoViewerState = useState({ visible: false, photos: [], currentIndex: 0 });
|
||
var photoViewer = photoViewerState[0];
|
||
var setPhotoViewer = photoViewerState[1];
|
||
|
||
var viewingBillIdState = useState(null);
|
||
var viewingBillId = viewingBillIdState[0];
|
||
var setViewingBillId = viewingBillIdState[1];
|
||
|
||
// 详情模式:view | payment
|
||
var detailModeState = useState('view');
|
||
var detailMode = detailModeState[0];
|
||
var setDetailMode = detailModeState[1];
|
||
|
||
// 付款表单数据
|
||
var paymentFormState = useState({
|
||
discountAmount: '',
|
||
discountReason: '',
|
||
vehicleList: [],
|
||
hydrogenList: [],
|
||
violationList: [],
|
||
returnFeeList: []
|
||
});
|
||
var paymentForm = paymentFormState[0];
|
||
var setPaymentForm = paymentFormState[1];
|
||
|
||
// 列表内成本编辑
|
||
var editingListCellState = useState(null);
|
||
var editingListCell = editingListCellState[0];
|
||
var setEditingListCell = editingListCellState[1];
|
||
var editingInputValueState = useState('');
|
||
var editingInputValue = editingInputValueState[0];
|
||
var setEditingInputValue = editingInputValueState[1];
|
||
var listEditableCostsState = useState({});
|
||
var listEditableCosts = listEditableCostsState[0];
|
||
var setListEditableCosts = listEditableCostsState[1];
|
||
|
||
// 模拟选项与数据(与原文一致)
|
||
var contractOptions = useMemo(function() {
|
||
return [
|
||
{ value: 'HT001', label: 'HT001 - 租赁合同A' },
|
||
{ value: 'HT002', label: 'HT002 - 租赁合同B' },
|
||
{ value: 'HT003', label: 'HT003 - 租赁合同C' }
|
||
];
|
||
}, []);
|
||
var projectOptions = useMemo(function() {
|
||
return [
|
||
{ value: 'XM001', label: 'XM001 - 北京项目' },
|
||
{ value: 'XM002', label: 'XM002 - 上海项目' },
|
||
{ value: 'XM003', label: 'XM003 - 广州项目' }
|
||
];
|
||
}, []);
|
||
var customerOptions = useMemo(function() {
|
||
return [
|
||
{ value: 'KH001', label: 'KH001 - 科技公司A' },
|
||
{ value: 'KH002', label: 'KH002 - 制造企业B' },
|
||
{ value: 'KH003', label: 'KH003 - 物流公司C' }
|
||
];
|
||
}, []);
|
||
var statusOptions = [
|
||
{ value: 'paid', label: '已付款' },
|
||
{ value: 'partial', label: '部分付款' },
|
||
{ value: 'unpaid', label: '未付款' }
|
||
];
|
||
|
||
var mockBillList = useMemo(function() {
|
||
var list = [];
|
||
for (var i = 1; i <= 25; i++) {
|
||
var statuses = ['paid', 'partial', 'unpaid'];
|
||
var status = statuses[i % 3];
|
||
list.push({
|
||
id: 'BILL' + i,
|
||
contractCode: 'HT00' + (i % 3 + 1),
|
||
projectName: 'XM00' + (i % 3 + 1) + ' - 项目' + i,
|
||
customerName: 'KH00' + (i % 3 + 1) + ' - 客户' + i,
|
||
period: i,
|
||
payableAmount: (15000 + i * 500).toFixed(2),
|
||
paidAmount: status === 'paid' ? (15000 + i * 500).toFixed(2) : status === 'partial' ? (8000).toFixed(2) : '0.00',
|
||
discountAmount: (i % 5 === 0 ? 200 : 0).toFixed(2),
|
||
remark: status !== 'unpaid' ? '已付款备注' + i : '-',
|
||
vehicleCost: (5000 + i * 100).toFixed(2),
|
||
hydrogenCost: (300 + i * 20).toFixed(2),
|
||
otherCost: (200 + i * 10).toFixed(2),
|
||
status: status
|
||
});
|
||
}
|
||
return list;
|
||
}, []);
|
||
|
||
var mockPayableDetail = useMemo(function() {
|
||
return [
|
||
{ startDate: '2025-01-01', endDate: '2025-01-31', plateNo: '京A12345', rent: '8000.00', serviceFee: '500.00', deposit: '2000.00' },
|
||
{ startDate: '2025-01-01', endDate: '2025-01-31', plateNo: '京B67890', rent: '7000.00', serviceFee: '400.00', deposit: '1500.00' }
|
||
];
|
||
}, []);
|
||
|
||
var mockBillDetail = useMemo(function() {
|
||
return {
|
||
startDate: '2025-01-01',
|
||
endDate: '2025-01-31',
|
||
contractCode: 'HT001',
|
||
projectName: 'XM001 - 北京项目',
|
||
customerName: 'KH001 - 科技公司A',
|
||
department: '运营部',
|
||
responsible: '张三',
|
||
paymentCycle: '先付(付款周期:1个月)',
|
||
discountTotal: '200.00',
|
||
discountReason: '长期合作客户优惠,首期账单减免部分金额'
|
||
};
|
||
}, []);
|
||
|
||
var mockVehicleList = useMemo(function() {
|
||
return [
|
||
{ brand: '奔驰', model: 'E300L', plateNo: '京A12345', planDelivery: '2024-12-25', actualDelivery: '2024-12-28', billStart: '2025-01-01', billEnd: '2025-01-31', monthlyRent: '8000.00', paidMonthlyRent: '7600.00', serviceFee: '500.00', paidServiceFee: '480.00', deposit: '2000.00', paidDeposit: '2000.00', serviceItems: [{ name: '保养服务', price: '300.00', effectiveDate: '2025-01-01' }, { name: '保险', price: '200.00', effectiveDate: '2025-01-01' }] },
|
||
{ brand: '宝马', model: '530Li', plateNo: '京B67890', planDelivery: '2024-12-20', actualDelivery: '2024-12-22', billStart: '2025-01-01', billEnd: '2025-01-31', monthlyRent: '7000.00', paidMonthlyRent: '7000.00', serviceFee: '400.00', paidServiceFee: '380.00', deposit: '1500.00', paidDeposit: '1500.00', serviceItems: [{ name: '保养服务', price: '250.00', effectiveDate: '2025-01-01' }] }
|
||
];
|
||
}, []);
|
||
|
||
var mockReturnFeeData = useMemo(function() {
|
||
return {
|
||
totalAmount: '2850.00',
|
||
paidTotalAmount: '2700.00',
|
||
list: [
|
||
{ feeName: '车辆外观损伤费', amount: '800.00', paidAmount: '760.00', photos: ['https://picsum.photos/80/80?random=1', 'https://picsum.photos/80/80?random=2'], attachments: [{ name: '外观损伤说明.pdf' }] },
|
||
{ feeName: '轮胎磨损费', amount: '1200.00', paidAmount: '1150.00', photos: ['https://picsum.photos/80/80?random=3'], attachments: [{ name: '轮胎检测报告.pdf' }, { name: '维修单据.pdf' }] },
|
||
{ feeName: '内饰清洁费', amount: '450.00', paidAmount: '430.00', photos: ['https://picsum.photos/80/80?random=4', 'https://picsum.photos/80/80?random=5', 'https://picsum.photos/80/80?random=6'], attachments: [] },
|
||
{ feeName: '油量补充费', amount: '400.00', paidAmount: '360.00', photos: [], attachments: [{ name: '加油凭证.jpg' }] }
|
||
]
|
||
};
|
||
}, []);
|
||
|
||
var mockViolationData = useMemo(function() {
|
||
return {
|
||
violationCount: 3,
|
||
totalAmount: '650.00',
|
||
paidTotalAmount: '600.00',
|
||
list: [
|
||
{ violationTime: '2025-01-10 08:30:00', plateNo: '京A12345', violationType: '违停', location: '北京市朝阳区xxx路', fineAmount: '200.00', paidFineAmount: '200.00' },
|
||
{ violationTime: '2025-01-18 14:20:00', plateNo: '京B67890', violationType: '超速', location: '北京市海淀区xxx大道', fineAmount: '200.00', paidFineAmount: '180.00' },
|
||
{ violationTime: '2025-01-25 09:15:00', plateNo: '京A12345', violationType: '闯红灯', location: '北京市东城区xxx路口', fineAmount: '250.00', paidFineAmount: '220.00' }
|
||
]
|
||
};
|
||
}, []);
|
||
|
||
var mockHydrogenData = useMemo(function() {
|
||
return {
|
||
refuelCount: 12,
|
||
balance: '3580.00',
|
||
list: [
|
||
{ refuelTime: '2025-01-15 09:30:00', stationName: '北京朝阳加氢站', plateNo: '京A12345', amount: '15.5', costPrice: '28.00', feePrice: '434.00', paidFeePrice: '420.00' },
|
||
{ refuelTime: '2025-01-18 14:20:00', stationName: '北京海淀加氢站', plateNo: '京B67890', amount: '12.0', costPrice: '28.00', feePrice: '336.00', paidFeePrice: '336.00' },
|
||
{ refuelTime: '2025-01-22 11:00:00', stationName: '北京朝阳加氢站', plateNo: '京A12345', amount: '18.2', costPrice: '28.00', feePrice: '509.60', paidFeePrice: '490.00' }
|
||
]
|
||
};
|
||
}, []);
|
||
|
||
var vehicleBillTotals = useMemo(function() {
|
||
var list = mockVehicleList || [];
|
||
var monthlyRentTotal = 0, paidRentTotal = 0, serviceFeeTotal = 0, paidServiceFeeTotal = 0, depositTotal = 0, paidDepositTotal = 0;
|
||
list.forEach(function(v) {
|
||
monthlyRentTotal += parseFloat(v.monthlyRent || 0);
|
||
paidRentTotal += parseFloat(v.paidMonthlyRent || 0);
|
||
serviceFeeTotal += parseFloat(v.serviceFee || 0);
|
||
paidServiceFeeTotal += parseFloat(v.paidServiceFee || 0);
|
||
depositTotal += parseFloat(v.deposit || 0);
|
||
paidDepositTotal += parseFloat(v.paidDeposit || 0);
|
||
});
|
||
return {
|
||
monthlyRentTotal: monthlyRentTotal.toFixed(2),
|
||
paidRentTotal: paidRentTotal.toFixed(2),
|
||
serviceFeeTotal: serviceFeeTotal.toFixed(2),
|
||
paidServiceFeeTotal: paidServiceFeeTotal.toFixed(2),
|
||
depositTotal: depositTotal.toFixed(2),
|
||
paidDepositTotal: paidDepositTotal.toFixed(2)
|
||
};
|
||
}, [mockVehicleList]);
|
||
|
||
var billInfoTotals = useMemo(function() {
|
||
var monthlyRentTotal = parseFloat(vehicleBillTotals.monthlyRentTotal || 0);
|
||
var serviceFeeTotal = parseFloat(vehicleBillTotals.serviceFeeTotal || 0);
|
||
var depositTotal = parseFloat(vehicleBillTotals.depositTotal || 0);
|
||
var hydrogenTotal = 0;
|
||
(mockHydrogenData.list || []).forEach(function(item) { hydrogenTotal += parseFloat(item.feePrice || 0); });
|
||
var violationTotal = parseFloat(mockViolationData.totalAmount || 0);
|
||
var returnFeeTotal = parseFloat(mockReturnFeeData.totalAmount || 0);
|
||
var payableTotal = monthlyRentTotal + serviceFeeTotal + depositTotal + hydrogenTotal + violationTotal + returnFeeTotal;
|
||
var paidTotal = 0;
|
||
(mockVehicleList || []).forEach(function(v) {
|
||
paidTotal += parseFloat(v.paidMonthlyRent || 0) + parseFloat(v.paidServiceFee || 0) + parseFloat(v.paidDeposit || 0);
|
||
});
|
||
var discountTotal = parseFloat(mockBillDetail.discountTotal || 0);
|
||
var unpaidTotal = Math.max(0, payableTotal - paidTotal - discountTotal);
|
||
return {
|
||
payableTotal: payableTotal.toFixed(2),
|
||
paidTotal: paidTotal.toFixed(2),
|
||
unpaidTotal: unpaidTotal.toFixed(2)
|
||
};
|
||
}, [vehicleBillTotals, mockHydrogenData, mockViolationData, mockReturnFeeData, mockVehicleList, mockBillDetail]);
|
||
|
||
var vehicleTotals = billInfoTotals;
|
||
|
||
var filteredList = useMemo(function() {
|
||
var list = (mockBillList || []).slice();
|
||
var c = (appliedFilter.contract || '').trim();
|
||
var p = (appliedFilter.project || '').trim();
|
||
var cust = (appliedFilter.customer || '').trim();
|
||
var st = Array.isArray(appliedFilter.status) ? appliedFilter.status : [];
|
||
if (c) list = list.filter(function(item) { return String(item.contractCode || '').toLowerCase().indexOf(c.toLowerCase()) >= 0; });
|
||
if (p) list = list.filter(function(item) { return String(item.projectName || '').toLowerCase().indexOf(p.toLowerCase()) >= 0; });
|
||
if (cust) list = list.filter(function(item) { return String(item.customerName || '').toLowerCase().indexOf(cust.toLowerCase()) >= 0; });
|
||
if (st.length > 0) {
|
||
var statusSet = {};
|
||
st.forEach(function(s) { statusSet[s] = true; });
|
||
list = list.filter(function(item) { return statusSet[item.status]; });
|
||
}
|
||
return list;
|
||
}, [mockBillList, appliedFilter.contract, appliedFilter.project, appliedFilter.customer, appliedFilter.status]);
|
||
|
||
var totalCount = filteredList.length;
|
||
var paginatedList = useMemo(function() {
|
||
var start = (currentPage - 1) * pageSize;
|
||
return filteredList.slice(start, start + pageSize);
|
||
}, [filteredList, currentPage, pageSize]);
|
||
|
||
var handleSearch = useCallback(function() {
|
||
setAppliedFilter({
|
||
contract: (contractFilter != null && contractFilter !== '') ? String(contractFilter) : '',
|
||
project: (projectFilter != null && projectFilter !== '') ? String(projectFilter) : '',
|
||
customer: (customerFilter != null && customerFilter !== '') ? String(customerFilter) : '',
|
||
status: Array.isArray(statusFilter) ? statusFilter.slice() : []
|
||
});
|
||
setCurrentPage(1);
|
||
}, [contractFilter, projectFilter, customerFilter, statusFilter]);
|
||
|
||
var handleReset = useCallback(function() {
|
||
setContractFilter(undefined);
|
||
setProjectFilter(undefined);
|
||
setCustomerFilter(undefined);
|
||
setStatusFilter([]);
|
||
setAppliedFilter({ contract: '', project: '', customer: '', status: [] });
|
||
setCurrentPage(1);
|
||
}, []);
|
||
|
||
var handleExport = useCallback(function() {
|
||
if (selectedRowKeys.length === 0) {
|
||
message.warning('请先选择要导出的数据');
|
||
return;
|
||
}
|
||
message.success('导出 ' + selectedRowKeys.length + ' 条数据');
|
||
}, [selectedRowKeys.length]);
|
||
|
||
var handleView = useCallback(function(id, isPayment) {
|
||
setViewingBillId(id);
|
||
setDetailMode(isPayment ? 'payment' : 'view');
|
||
if (isPayment) {
|
||
var vl = mockVehicleList.map(function(v) {
|
||
return { paidMonthlyRent: v.paidMonthlyRent || '', paidServiceFee: v.paidServiceFee || '', paidDeposit: v.paidDeposit || '' };
|
||
});
|
||
var hl = mockHydrogenData.list.map(function(item) { return { paidFeePrice: item.paidFeePrice || '' }; });
|
||
var viol = mockViolationData.list.map(function(item) { return { paidFineAmount: item.paidFineAmount || '' }; });
|
||
var rfl = mockReturnFeeData.list.map(function(item) { return { paidAmount: item.paidAmount || '' }; });
|
||
setPaymentForm({
|
||
discountAmount: mockBillDetail.discountTotal || '',
|
||
discountReason: mockBillDetail.discountReason || '',
|
||
vehicleList: vl,
|
||
hydrogenList: hl,
|
||
violationList: viol,
|
||
returnFeeList: rfl
|
||
});
|
||
}
|
||
setCurrentView('detail');
|
||
}, []);
|
||
|
||
var handleBackToList = useCallback(function() {
|
||
setCurrentView('list');
|
||
setViewingBillId(null);
|
||
setDetailMode('view');
|
||
}, []);
|
||
|
||
var handlePaymentFormChange = useCallback(function(section, index, field, value) {
|
||
setPaymentForm(function(prev) {
|
||
var next = {
|
||
discountAmount: prev.discountAmount,
|
||
discountReason: prev.discountReason,
|
||
vehicleList: prev.vehicleList.slice(),
|
||
hydrogenList: prev.hydrogenList.slice(),
|
||
violationList: prev.violationList.slice(),
|
||
returnFeeList: prev.returnFeeList.slice()
|
||
};
|
||
if (section === 'bill') {
|
||
if (field === 'discountAmount') next.discountAmount = value;
|
||
if (field === 'discountReason') next.discountReason = value;
|
||
} else if (section === 'vehicle' && index >= 0 && index < next.vehicleList.length) {
|
||
next.vehicleList[index] = Object.assign({}, next.vehicleList[index], { [field]: value });
|
||
} else if (section === 'hydrogen' && index >= 0 && index < next.hydrogenList.length) {
|
||
next.hydrogenList[index] = Object.assign({}, next.hydrogenList[index], { [field]: value });
|
||
} else if (section === 'violation' && index >= 0 && index < next.violationList.length) {
|
||
next.violationList[index] = Object.assign({}, next.violationList[index], { [field]: value });
|
||
} else if (section === 'returnFee' && index >= 0 && index < next.returnFeeList.length) {
|
||
next.returnFeeList[index] = Object.assign({}, next.returnFeeList[index], { [field]: value });
|
||
}
|
||
return next;
|
||
});
|
||
}, []);
|
||
|
||
var handleSubmit = useCallback(function() {
|
||
var errors = [];
|
||
if (!paymentForm.discountAmount || String(paymentForm.discountAmount).trim() === '') errors.push('减免金额');
|
||
if (!paymentForm.discountReason || String(paymentForm.discountReason).trim() === '') errors.push('减免原因');
|
||
paymentForm.vehicleList.forEach(function(v, i) {
|
||
if (!v.paidMonthlyRent || String(v.paidMonthlyRent).trim() === '') errors.push('车辆账单-实付月租金(第' + (i + 1) + '行)');
|
||
if (!v.paidServiceFee || String(v.paidServiceFee).trim() === '') errors.push('车辆账单-实付服务费(第' + (i + 1) + '行)');
|
||
if (!v.paidDeposit || String(v.paidDeposit).trim() === '') errors.push('车辆账单-实付保证金(第' + (i + 1) + '行)');
|
||
});
|
||
paymentForm.hydrogenList.forEach(function(h, i) {
|
||
if (!h.paidFeePrice || String(h.paidFeePrice).trim() === '') errors.push('氢费账单-实付氢费金额(第' + (i + 1) + '行)');
|
||
});
|
||
paymentForm.violationList.forEach(function(v, i) {
|
||
if (!v.paidFineAmount || String(v.paidFineAmount).trim() === '') errors.push('违章费用-实付罚款金额(第' + (i + 1) + '行)');
|
||
});
|
||
paymentForm.returnFeeList.forEach(function(r, i) {
|
||
if (!r.paidAmount || String(r.paidAmount).trim() === '') errors.push('还车费用-实付金额(第' + (i + 1) + '行)');
|
||
});
|
||
if (errors.length > 0) {
|
||
message.warning('请填写必填项:' + errors.join('、'));
|
||
return;
|
||
}
|
||
message.success('提交成功');
|
||
handleBackToList();
|
||
}, [paymentForm, handleBackToList]);
|
||
|
||
var handleSave = useCallback(function() {
|
||
message.success('保存成功');
|
||
}, []);
|
||
|
||
function getStatusText(status) {
|
||
if (status === 'paid') return '已付款';
|
||
if (status === 'partial') return '部分付款';
|
||
return '未付款';
|
||
}
|
||
function getStatusTagColor(status) {
|
||
if (status === 'paid') return 'success';
|
||
if (status === 'partial') return 'warning';
|
||
return 'error';
|
||
}
|
||
|
||
// 列表表格列(含行内编辑氢费/其他成本)
|
||
function renderEditableCost(row, field, label) {
|
||
var rowId = row.id;
|
||
var val = (listEditableCosts[rowId] && listEditableCosts[rowId][field] !== undefined)
|
||
? listEditableCosts[rowId][field]
|
||
: (row[field] != null ? row[field] : '0.00');
|
||
var num = (parseFloat(val) || 0).toFixed(2);
|
||
var isEditing = editingListCell && editingListCell.rowId === rowId && editingListCell.field === field;
|
||
if (isEditing) {
|
||
return React.createElement(Space, { key: 'edit', size: 4 },
|
||
React.createElement(Input, {
|
||
value: editingInputValue,
|
||
onChange: function(e) { setEditingInputValue(e.target.value); },
|
||
onBlur: function() {
|
||
var n = parseFloat(editingInputValue);
|
||
var formatted = (isNaN(n) ? 0 : n).toFixed(2);
|
||
setListEditableCosts(function(prev) {
|
||
var next = Object.assign({}, prev);
|
||
next[rowId] = Object.assign({}, next[rowId], { [field]: formatted });
|
||
return next;
|
||
});
|
||
setEditingListCell(null);
|
||
setEditingInputValue('');
|
||
},
|
||
style: { width: 80 },
|
||
autoFocus: true
|
||
}),
|
||
React.createElement('span', null, '元')
|
||
);
|
||
}
|
||
return React.createElement('span', {
|
||
style: { cursor: 'pointer' },
|
||
onClick: function() {
|
||
setEditingInputValue(num);
|
||
setEditingListCell({ rowId: rowId, field: field });
|
||
}
|
||
}, num);
|
||
}
|
||
|
||
var listColumns = useMemo(function() {
|
||
return [
|
||
{ title: '付款状态', dataIndex: 'status', key: 'status', width: 100, render: function(s) { return React.createElement(Tag, { color: getStatusTagColor(s) }, getStatusText(s)); } },
|
||
{ title: '合同编码', dataIndex: 'contractCode', key: 'contractCode', width: 120 },
|
||
{ title: '项目名称', dataIndex: 'projectName', key: 'projectName', width: 160 },
|
||
{ title: '客户名称', dataIndex: 'customerName', key: 'customerName', width: 160 },
|
||
{ title: '当前期数', dataIndex: 'period', key: 'period', width: 90 },
|
||
{ title: '应付金额', dataIndex: 'payableAmount', key: 'payableAmount', width: 110, render: function(_, row) {
|
||
return React.createElement('a', {
|
||
onClick: function() { setPopover({ type: 'payable', data: mockPayableDetail }); },
|
||
style: { color: '#1677ff', fontWeight: 600, textDecoration: 'underline', cursor: 'pointer' }
|
||
}, row.payableAmount);
|
||
}},
|
||
{ title: '实付金额', dataIndex: 'paidAmount', key: 'paidAmount', width: 110 },
|
||
{ title: '减免金额', dataIndex: 'discountAmount', key: 'discountAmount', width: 100 },
|
||
{ title: '未付金额', key: 'unpaid', width: 100, render: function(_, row) {
|
||
return (parseFloat(row.payableAmount || 0) - parseFloat(row.paidAmount || 0) - parseFloat(row.discountAmount || 0)).toFixed(2);
|
||
}},
|
||
{ title: '备注', dataIndex: 'remark', key: 'remark', width: 120 },
|
||
{ title: '车辆成本(元)', dataIndex: 'vehicleCost', key: 'vehicleCost', width: 120, render: function(val) { return (parseFloat(val) || 0).toFixed(2); } },
|
||
{ title: '氢费成本(元)', key: 'hydrogenCost', width: 120, render: function(_, row) { return renderEditableCost(row, 'hydrogenCost', '氢费'); } },
|
||
{ title: '其他成本(元)', key: 'otherCost', width: 120, render: function(_, row) { return renderEditableCost(row, 'otherCost', '其他'); } },
|
||
{ title: '操作', key: 'action', width: 140, fixed: 'right', render: function(_, row) {
|
||
return React.createElement(Space, null,
|
||
React.createElement(Button, { type: 'link', size: 'small', onClick: function() { handleView(row.id, false); } }, '查看'),
|
||
React.createElement(Button, { type: 'link', size: 'small', style: { color: '#52c41a' }, onClick: function() { handleView(row.id, true); } }, '收费')
|
||
);
|
||
}}
|
||
];
|
||
}, [listEditableCosts, editingListCell, editingInputValue, handleView]);
|
||
|
||
var rowSelection = useMemo(function() {
|
||
return {
|
||
selectedRowKeys: selectedRowKeys,
|
||
onChange: function(keys) { setSelectedRowKeys(keys || []); }
|
||
};
|
||
}, [selectedRowKeys]);
|
||
|
||
var tablePagination = useMemo(function() {
|
||
return {
|
||
current: currentPage,
|
||
pageSize: pageSize,
|
||
total: totalCount,
|
||
showSizeChanger: true,
|
||
showTotal: function(t) { return '共 ' + t + ' 条'; },
|
||
pageSizeOptions: ['10', '20', '50'],
|
||
onChange: function(page, size) {
|
||
setCurrentPage(page);
|
||
if (size !== pageSize) setPageSize(size);
|
||
}
|
||
};
|
||
}, [currentPage, pageSize, totalCount]);
|
||
|
||
// —————— 详情视图 ——————
|
||
if (currentView === 'detail') {
|
||
var detailBreadcrumbItems = [
|
||
{ title: '运维管理' },
|
||
{ title: '业务管理' },
|
||
{ title: '租赁账单' },
|
||
{ title: detailMode === 'payment' ? '收费' : '查看' }
|
||
];
|
||
|
||
var billInfoCols = [
|
||
{ label: '账单开始日期', value: mockBillDetail.startDate },
|
||
{ label: '账单结束日期', value: mockBillDetail.endDate },
|
||
{ label: '合同编码', value: mockBillDetail.contractCode },
|
||
{ label: '项目名称', value: mockBillDetail.projectName },
|
||
{ label: '客户名称', value: mockBillDetail.customerName },
|
||
{ label: '业务部门', value: mockBillDetail.department },
|
||
{ label: '业务负责人', value: mockBillDetail.responsible },
|
||
{ label: '付款周期', value: mockBillDetail.paymentCycle }
|
||
];
|
||
|
||
return React.createElement('div', { style: { padding: 24, background: '#f5f5f5', minHeight: '100vh' } },
|
||
React.createElement(Breadcrumb, { items: detailBreadcrumbItems, style: { marginBottom: 16 } }),
|
||
React.createElement(Card, { style: { marginBottom: 16 } },
|
||
React.createElement('div', { style: { fontSize: 16, fontWeight: 600, marginBottom: 16, paddingBottom: 12, borderBottom: '1px solid #f0f0f0' } }, '账单信息'),
|
||
React.createElement(Row, { gutter: [24, 24] },
|
||
billInfoCols.map(function(item, i) {
|
||
return React.createElement(Col, { key: i, span: 8 },
|
||
React.createElement('div', { style: { marginBottom: 8 } },
|
||
React.createElement('span', { style: { color: '#666', marginRight: 8 } }, item.label + ':'),
|
||
React.createElement('span', null, item.value)
|
||
)
|
||
);
|
||
}),
|
||
React.createElement(Col, { span: 8 },
|
||
React.createElement('div', { style: { marginBottom: 8 } },
|
||
React.createElement('span', { style: { color: '#666', marginRight: 8 } }, '应付款总额:'),
|
||
React.createElement('span', { style: { color: '#1890ff', fontWeight: 600 } }, vehicleTotals.payableTotal + ' 元')
|
||
)
|
||
),
|
||
React.createElement(Col, { span: 8 },
|
||
React.createElement('div', { style: { marginBottom: 8 } },
|
||
React.createElement('span', { style: { color: '#666', marginRight: 8 } }, '实付款总额:'),
|
||
React.createElement('span', { style: { color: '#52c41a', fontWeight: 600 } }, vehicleTotals.paidTotal + ' 元')
|
||
)
|
||
),
|
||
React.createElement(Col, { span: 8 },
|
||
React.createElement('div', { style: { marginBottom: 8 } },
|
||
React.createElement('span', { style: { color: '#666', marginRight: 8 } }, '减免金额:'),
|
||
detailMode === 'payment'
|
||
? React.createElement(Input, {
|
||
value: paymentForm.discountAmount,
|
||
onChange: function(e) { handlePaymentFormChange('bill', -1, 'discountAmount', e.target.value); },
|
||
style: { width: 120 },
|
||
placeholder: '0.00',
|
||
addonAfter: '元'
|
||
})
|
||
: React.createElement('span', { style: { fontWeight: 600 } }, mockBillDetail.discountTotal + ' 元')
|
||
)
|
||
),
|
||
React.createElement(Col, { span: 8 },
|
||
React.createElement('div', { style: { marginBottom: 8 } },
|
||
React.createElement('span', { style: { color: '#666', marginRight: 8 } }, '未付款总额:'),
|
||
React.createElement('span', { style: { color: '#ff4d4f', fontWeight: 600 } }, vehicleTotals.unpaidTotal + ' 元')
|
||
)
|
||
),
|
||
React.createElement(Col, { span: 24 },
|
||
React.createElement('div', { style: { marginBottom: 8 } },
|
||
React.createElement('span', { style: { color: '#666', marginRight: 8 } }, '减免原因:'),
|
||
detailMode === 'payment'
|
||
? React.createElement(Input.TextArea, {
|
||
value: paymentForm.discountReason,
|
||
onChange: function(e) { handlePaymentFormChange('bill', -1, 'discountReason', e.target.value); },
|
||
placeholder: '请输入减免原因',
|
||
rows: 3,
|
||
style: { maxWidth: 400 }
|
||
})
|
||
: React.createElement('span', null, mockBillDetail.discountReason || '-')
|
||
)
|
||
)
|
||
)
|
||
),
|
||
// 车辆账单
|
||
React.createElement(Card, { title: '车辆账单', style: { marginBottom: 16 } },
|
||
React.createElement(Table, {
|
||
dataSource: mockVehicleList,
|
||
rowKey: 'plateNo',
|
||
pagination: false,
|
||
scroll: { x: 1200 },
|
||
columns: [
|
||
{ title: '品牌', dataIndex: 'brand', width: 80 },
|
||
{ title: '型号', dataIndex: 'model', width: 90 },
|
||
{ title: '车牌号', dataIndex: 'plateNo', width: 100 },
|
||
{ title: '计划交车日期', dataIndex: 'planDelivery', width: 120 },
|
||
{ title: '实际交车日期', dataIndex: 'actualDelivery', width: 120 },
|
||
{ title: '账单开始日期', dataIndex: 'billStart', width: 120 },
|
||
{ title: '计费结束日期', dataIndex: 'billEnd', width: 120 },
|
||
{ title: '车辆月租金', dataIndex: 'monthlyRent', width: 110 },
|
||
{ title: '实付月租金', dataIndex: 'paidMonthlyRent', width: 110, render: function(_, record, idx) {
|
||
if (detailMode !== 'payment') return (parseFloat(record.paidMonthlyRent || 0)).toFixed(2);
|
||
var pf = paymentForm.vehicleList[idx] || {};
|
||
return React.createElement(Input, { value: pf.paidMonthlyRent, onChange: function(e) { handlePaymentFormChange('vehicle', idx, 'paidMonthlyRent', e.target.value); }, style: { width: 100 }, addonAfter: '元' });
|
||
}},
|
||
{ title: '服务费', dataIndex: 'serviceFee', width: 90, render: function(val, record) {
|
||
if (detailMode === 'payment') return val;
|
||
return React.createElement('a', { onClick: function() { setPopover({ type: 'service', data: record.serviceItems }); } }, val);
|
||
}},
|
||
{ title: '实付服务费', dataIndex: 'paidServiceFee', width: 110, render: function(_, record, idx) {
|
||
if (detailMode !== 'payment') return (parseFloat(record.paidServiceFee || 0)).toFixed(2);
|
||
var pf = paymentForm.vehicleList[idx] || {};
|
||
return React.createElement(Input, { value: pf.paidServiceFee, onChange: function(e) { handlePaymentFormChange('vehicle', idx, 'paidServiceFee', e.target.value); }, style: { width: 100 }, addonAfter: '元' });
|
||
}},
|
||
{ title: '保证金', dataIndex: 'deposit', width: 90 },
|
||
{ title: '实付保证金', dataIndex: 'paidDeposit', width: 110, render: function(_, record, idx) {
|
||
if (detailMode !== 'payment') return (parseFloat(record.paidDeposit || 0)).toFixed(2);
|
||
var pf = paymentForm.vehicleList[idx] || {};
|
||
return React.createElement(Input, { value: pf.paidDeposit, onChange: function(e) { handlePaymentFormChange('vehicle', idx, 'paidDeposit', e.target.value); }, style: { width: 100 }, addonAfter: '元' });
|
||
}}
|
||
],
|
||
summary: function() {
|
||
return React.createElement(Table.Summary, null,
|
||
React.createElement(Table.Summary.Row, null,
|
||
React.createElement(Table.Summary.Cell, { index: 0, colSpan: 7 }, '总计'),
|
||
React.createElement(Table.Summary.Cell, { index: 7 }, vehicleBillTotals.monthlyRentTotal),
|
||
React.createElement(Table.Summary.Cell, { index: 8 }, vehicleBillTotals.paidRentTotal),
|
||
React.createElement(Table.Summary.Cell, { index: 9 }, vehicleBillTotals.serviceFeeTotal),
|
||
React.createElement(Table.Summary.Cell, { index: 10 }, vehicleBillTotals.paidServiceFeeTotal),
|
||
React.createElement(Table.Summary.Cell, { index: 11 }, vehicleBillTotals.depositTotal),
|
||
React.createElement(Table.Summary.Cell, { index: 12 }, vehicleBillTotals.paidDepositTotal)
|
||
)
|
||
);
|
||
}
|
||
})
|
||
),
|
||
// 氢费账单
|
||
React.createElement(Card, { title: '氢费账单', style: { marginBottom: 16 } },
|
||
React.createElement('div', { style: { marginBottom: 16 } },
|
||
React.createElement('span', { style: { marginRight: 24 } }, '加氢次数:', React.createElement('span', { style: { fontWeight: 600 } }, mockHydrogenData.refuelCount + ' 次')),
|
||
React.createElement('span', null, '当前氢费余额:', React.createElement('span', { style: { fontWeight: 600, color: '#1890ff' } }, mockHydrogenData.balance + ' 元'))
|
||
),
|
||
React.createElement(Table, {
|
||
dataSource: mockHydrogenData.list,
|
||
rowKey: function(item, i) { return i; },
|
||
pagination: false,
|
||
columns: [
|
||
{ title: '加氢时间', dataIndex: 'refuelTime', width: 180 },
|
||
{ title: '加氢站名称', dataIndex: 'stationName', width: 140 },
|
||
{ title: '车牌号', dataIndex: 'plateNo', width: 100 },
|
||
{ title: '加氢量', dataIndex: 'amount', width: 90 },
|
||
{ title: '成本单价(元/KG)', dataIndex: 'costPrice', width: 120 },
|
||
{ title: '氢费价格(元)', dataIndex: 'feePrice', width: 120 },
|
||
{ title: '实付氢费金额(元)', dataIndex: 'paidFeePrice', width: 140, render: function(_, record, i) {
|
||
if (detailMode !== 'payment') return (parseFloat(record.paidFeePrice || 0)).toFixed(2);
|
||
var pf = paymentForm.hydrogenList[i] || {};
|
||
return React.createElement(Input, { value: pf.paidFeePrice, onChange: function(e) { handlePaymentFormChange('hydrogen', i, 'paidFeePrice', e.target.value); }, style: { width: 100 }, addonAfter: '元' });
|
||
}}
|
||
],
|
||
summary: function() {
|
||
var totalFee = mockHydrogenData.list.reduce(function(s, item) { return s + parseFloat(item.feePrice || 0); }, 0).toFixed(2);
|
||
var totalPaid = mockHydrogenData.list.reduce(function(s, item) { return s + parseFloat(item.paidFeePrice || 0); }, 0).toFixed(2);
|
||
return React.createElement(Table.Summary, null,
|
||
React.createElement(Table.Summary.Row, null,
|
||
React.createElement(Table.Summary.Cell, { index: 0, colSpan: 5 }, '总计'),
|
||
React.createElement(Table.Summary.Cell, { index: 5 }, totalFee),
|
||
React.createElement(Table.Summary.Cell, { index: 6 }, totalPaid)
|
||
)
|
||
);
|
||
}
|
||
})
|
||
),
|
||
// 违章费用
|
||
React.createElement(Card, { title: '违章费用', style: { marginBottom: 16 } },
|
||
React.createElement('div', { style: { marginBottom: 16 } },
|
||
React.createElement('span', null, '违章次数:', React.createElement('span', { style: { fontWeight: 600 } }, mockViolationData.violationCount + ' 次'))
|
||
),
|
||
React.createElement(Table, {
|
||
dataSource: mockViolationData.list,
|
||
rowKey: function(item, i) { return i; },
|
||
pagination: false,
|
||
columns: [
|
||
{ title: '违章时间', dataIndex: 'violationTime', width: 180 },
|
||
{ title: '车牌号', dataIndex: 'plateNo', width: 100 },
|
||
{ title: '违章类型', dataIndex: 'violationType', width: 100 },
|
||
{ title: '违章地点', dataIndex: 'location', width: 200 },
|
||
{ title: '罚款金额', dataIndex: 'fineAmount', width: 100 },
|
||
{ title: '实付罚款金额(元)', dataIndex: 'paidFineAmount', width: 140, render: function(_, record, i) {
|
||
if (detailMode !== 'payment') return (parseFloat(record.paidFineAmount || 0)).toFixed(2);
|
||
var pf = paymentForm.violationList[i] || {};
|
||
return React.createElement(Input, { value: pf.paidFineAmount, onChange: function(e) { handlePaymentFormChange('violation', i, 'paidFineAmount', e.target.value); }, style: { width: 100 }, addonAfter: '元' });
|
||
}}
|
||
],
|
||
summary: function() {
|
||
var totalPaid = mockViolationData.list.reduce(function(s, item) { return s + parseFloat(item.paidFineAmount || 0); }, 0).toFixed(2);
|
||
return React.createElement(Table.Summary, null,
|
||
React.createElement(Table.Summary.Row, null,
|
||
React.createElement(Table.Summary.Cell, { index: 0, colSpan: 4 }, '总计'),
|
||
React.createElement(Table.Summary.Cell, { index: 4 }, mockViolationData.totalAmount),
|
||
React.createElement(Table.Summary.Cell, { index: 5 }, totalPaid)
|
||
)
|
||
);
|
||
}
|
||
})
|
||
),
|
||
// 还车费用
|
||
React.createElement(Card, { title: '还车费用', style: { marginBottom: 16 } },
|
||
React.createElement(Table, {
|
||
dataSource: mockReturnFeeData.list,
|
||
rowKey: function(item, i) { return i; },
|
||
pagination: false,
|
||
columns: [
|
||
{ title: '费用名称', dataIndex: 'feeName', width: 140 },
|
||
{ title: '金额', dataIndex: 'amount', width: 100 },
|
||
{ title: '实付金额(元)', dataIndex: 'paidAmount', width: 120, render: function(_, record, i) {
|
||
if (detailMode !== 'payment') return (parseFloat(record.paidAmount || 0)).toFixed(2);
|
||
var pf = paymentForm.returnFeeList[i] || {};
|
||
return React.createElement(Input, { value: pf.paidAmount, onChange: function(e) { handlePaymentFormChange('returnFee', i, 'paidAmount', e.target.value); }, style: { width: 100 }, addonAfter: '元' });
|
||
}},
|
||
{ title: '照片', dataIndex: 'photos', width: 200, render: function(photos) {
|
||
if (!photos || photos.length === 0) return '-';
|
||
return React.createElement(Space, null, photos.slice(0, 5).map(function(url, idx) {
|
||
return React.createElement('img', {
|
||
key: idx,
|
||
src: url,
|
||
alt: '',
|
||
style: { width: 40, height: 40, objectFit: 'cover', borderRadius: 4, cursor: 'pointer' },
|
||
onClick: function() { setPhotoViewer({ visible: true, photos: photos, currentIndex: idx }); }
|
||
});
|
||
}));
|
||
}},
|
||
{ title: '附件', dataIndex: 'attachments', render: function(attachments) {
|
||
if (!attachments || attachments.length === 0) return '-';
|
||
return React.createElement(Space, { wrap: true }, attachments.map(function(att, idx) {
|
||
return React.createElement('a', { key: idx, onClick: function() { message.info('下载附件:' + att.name); } }, att.name);
|
||
}));
|
||
}}
|
||
],
|
||
summary: function() {
|
||
var totalPaid = mockReturnFeeData.list.reduce(function(s, item) { return s + parseFloat(item.paidAmount || 0); }, 0).toFixed(2);
|
||
return React.createElement(Table.Summary, null,
|
||
React.createElement(Table.Summary.Row, null,
|
||
React.createElement(Table.Summary.Cell, { index: 0 }, '总计'),
|
||
React.createElement(Table.Summary.Cell, { index: 1 }, mockReturnFeeData.totalAmount),
|
||
React.createElement(Table.Summary.Cell, { index: 2 }, totalPaid),
|
||
React.createElement(Table.Summary.Cell, { index: 3 }, ''),
|
||
React.createElement(Table.Summary.Cell, { index: 4 }, '')
|
||
)
|
||
);
|
||
}
|
||
})
|
||
),
|
||
React.createElement('div', { style: { marginTop: 24, textAlign: 'center' } },
|
||
React.createElement(Space, null,
|
||
detailMode === 'payment' && React.createElement(Button, { type: 'primary', onClick: handleSubmit }, '提交审核'),
|
||
detailMode === 'payment' && React.createElement(Button, { onClick: handleSave }, '保存'),
|
||
detailMode === 'payment' && React.createElement(Button, { onClick: handleBackToList }, '取消'),
|
||
detailMode === 'view' && React.createElement(Button, { onClick: handleBackToList }, '返回')
|
||
)
|
||
),
|
||
// 照片查看器 Modal
|
||
React.createElement(Modal, {
|
||
title: '照片查看',
|
||
open: photoViewer.visible && photoViewer.photos.length > 0,
|
||
onCancel: function() { setPhotoViewer({ visible: false, photos: [], currentIndex: 0 }); },
|
||
footer: null,
|
||
width: '90vw',
|
||
centered: true
|
||
}, photoViewer.photos.length > 0 ? React.createElement('div', { style: { textAlign: 'center' } },
|
||
React.createElement('img', {
|
||
src: photoViewer.photos[photoViewer.currentIndex].replace('80/80', '600/600'),
|
||
alt: '',
|
||
style: { maxWidth: '100%', maxHeight: '70vh', objectFit: 'contain' }
|
||
}),
|
||
React.createElement('div', { style: { marginTop: 16 } },
|
||
React.createElement(Button, {
|
||
disabled: photoViewer.currentIndex <= 0,
|
||
onClick: function() { setPhotoViewer({ visible: true, photos: photoViewer.photos, currentIndex: photoViewer.currentIndex - 1 }); }
|
||
}, '上一张'),
|
||
React.createElement('span', { style: { margin: '0 16px' } }, (photoViewer.currentIndex + 1) + ' / ' + photoViewer.photos.length),
|
||
React.createElement(Button, {
|
||
disabled: photoViewer.currentIndex >= photoViewer.photos.length - 1,
|
||
onClick: function() { setPhotoViewer({ visible: true, photos: photoViewer.photos, currentIndex: photoViewer.currentIndex + 1 }); }
|
||
}, '下一张')
|
||
)
|
||
) : null),
|
||
// 服务费明细 Modal
|
||
popover.type === 'service' && React.createElement(Modal, {
|
||
title: '服务费明细',
|
||
open: true,
|
||
onCancel: function() { setPopover({ type: null, data: null }); },
|
||
footer: React.createElement(Button, { onClick: function() { setPopover({ type: null, data: null }); } }, '关闭')
|
||
}, React.createElement(Table, {
|
||
dataSource: popover.data,
|
||
rowKey: function(item, i) { return i; },
|
||
pagination: false,
|
||
columns: [
|
||
{ title: '服务项', dataIndex: 'name' },
|
||
{ title: '价格', dataIndex: 'price' },
|
||
{ title: '服务生效日期', dataIndex: 'effectiveDate' }
|
||
]
|
||
}))
|
||
);
|
||
}
|
||
|
||
// —————— 列表视图 ——————
|
||
var listBreadcrumbItems = [
|
||
{ title: '运维管理' },
|
||
{ title: '业务管理' },
|
||
{ title: '租赁账单' }
|
||
];
|
||
|
||
return React.createElement('div', { style: { padding: 24, background: '#f5f5f5', minHeight: '100vh' } },
|
||
React.createElement(Breadcrumb, { items: listBreadcrumbItems, style: { marginBottom: 16 } }),
|
||
React.createElement(Card, null,
|
||
React.createElement(Row, { gutter: [16, 16], style: { marginBottom: 16 }, align: 'middle' },
|
||
React.createElement(Col, null,
|
||
React.createElement('span', { style: { marginRight: 8 } }, '合同编码:'),
|
||
React.createElement(Select, {
|
||
placeholder: '请选择合同编码',
|
||
allowClear: true,
|
||
showSearch: true,
|
||
optionFilterProp: 'label',
|
||
value: contractFilter,
|
||
onChange: setContractFilter,
|
||
style: { width: 200 },
|
||
options: contractOptions
|
||
})
|
||
),
|
||
React.createElement(Col, null,
|
||
React.createElement('span', { style: { marginRight: 8 } }, '项目名称:'),
|
||
React.createElement(Select, {
|
||
placeholder: '请选择项目名称',
|
||
allowClear: true,
|
||
showSearch: true,
|
||
optionFilterProp: 'label',
|
||
value: projectFilter,
|
||
onChange: setProjectFilter,
|
||
style: { width: 200 },
|
||
options: projectOptions
|
||
})
|
||
),
|
||
React.createElement(Col, null,
|
||
React.createElement('span', { style: { marginRight: 8 } }, '客户名称:'),
|
||
React.createElement(Select, {
|
||
placeholder: '请选择客户名称',
|
||
allowClear: true,
|
||
showSearch: true,
|
||
optionFilterProp: 'label',
|
||
value: customerFilter,
|
||
onChange: setCustomerFilter,
|
||
style: { width: 200 },
|
||
options: customerOptions
|
||
})
|
||
),
|
||
React.createElement(Col, null,
|
||
React.createElement('span', { style: { marginRight: 8 } }, '付款状态:'),
|
||
React.createElement(Select, {
|
||
mode: 'multiple',
|
||
placeholder: '全部',
|
||
allowClear: true,
|
||
value: statusFilter,
|
||
onChange: setStatusFilter,
|
||
style: { width: 200 },
|
||
options: statusOptions,
|
||
maxTagCount: 'responsive'
|
||
})
|
||
),
|
||
React.createElement(Col, null,
|
||
React.createElement(Space, null,
|
||
React.createElement(Button, { type: 'primary', onClick: handleSearch }, '查询'),
|
||
React.createElement(Button, { onClick: handleReset }, '重置')
|
||
)
|
||
)
|
||
),
|
||
React.createElement('div', { style: { marginBottom: 16, display: 'flex', justifyContent: 'flex-end' } },
|
||
React.createElement(Button, { type: 'primary', onClick: handleExport }, '导出')
|
||
),
|
||
React.createElement(Table, {
|
||
rowSelection: rowSelection,
|
||
columns: listColumns,
|
||
dataSource: paginatedList,
|
||
rowKey: 'id',
|
||
pagination: tablePagination,
|
||
scroll: { x: 1600 },
|
||
size: 'middle'
|
||
})
|
||
),
|
||
// 应付金额明细 Modal(列表按内容一行显示、宽度随内容调整)
|
||
React.createElement(Modal, {
|
||
title: '应付金额明细',
|
||
open: popover.type === 'payable',
|
||
onCancel: function() { setPopover({ type: null, data: null }); },
|
||
footer: React.createElement(Button, { onClick: function() { setPopover({ type: null, data: null }); } }, '关闭'),
|
||
width: 'fit-content',
|
||
style: { maxWidth: '90vw' },
|
||
styles: { body: { paddingBottom: 24 } }
|
||
}, popover.type === 'payable' && popover.data ? React.createElement(Table, {
|
||
dataSource: popover.data,
|
||
rowKey: function(item, i) { return i; },
|
||
pagination: false,
|
||
tableLayout: 'auto',
|
||
style: { minWidth: 0 },
|
||
columns: [
|
||
{ title: '账单开始日期', dataIndex: 'startDate', onCell: function() { return { style: { whiteSpace: 'nowrap' } }; } },
|
||
{ title: '账单结束日期', dataIndex: 'endDate', onCell: function() { return { style: { whiteSpace: 'nowrap' } }; } },
|
||
{ title: '车牌号', dataIndex: 'plateNo', onCell: function() { return { style: { whiteSpace: 'nowrap' } }; } },
|
||
{ title: '车辆租金', dataIndex: 'rent', onCell: function() { return { style: { whiteSpace: 'nowrap' } }; } },
|
||
{ title: '服务费', dataIndex: 'serviceFee', onCell: function() { return { style: { whiteSpace: 'nowrap' } }; } },
|
||
{ title: '保证金', dataIndex: 'deposit', onCell: function() { return { style: { whiteSpace: 'nowrap' } }; } }
|
||
]
|
||
}) : null)
|
||
);
|
||
};
|
||
|
||
if (typeof window !== 'undefined') {
|
||
window.Component = Component;
|
||
if (document.readyState === 'loading') {
|
||
document.addEventListener('DOMContentLoaded', function() {
|
||
var rootEl = document.getElementById('root');
|
||
if (rootEl && window.ReactDOM && window.React) {
|
||
var root = ReactDOM.createRoot(rootEl);
|
||
root.render(React.createElement(Component));
|
||
}
|
||
});
|
||
} else {
|
||
var rootEl = document.getElementById('root');
|
||
if (rootEl && window.ReactDOM && window.React) {
|
||
var root = ReactDOM.createRoot(rootEl);
|
||
root.render(React.createElement(Component));
|
||
}
|
||
}
|
||
}
|