feat(web): 租赁账单、安全培训扫码、提车应收款等模块更新与新增

Made-with: Cursor
This commit is contained in:
王冕
2026-03-11 09:10:28 +08:00
parent 4bc7ad9741
commit 30e3d9f156
17 changed files with 3712 additions and 1384 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,305 @@
// 【重要】必须使用 const Component 作为组件变量名
// 财务管理 - 提车应收款-查看2026年3月10日版本
const Component = function () {
var useState = React.useState;
var useMemo = React.useMemo;
var antd = window.antd;
var Breadcrumb = antd.Breadcrumb;
var Card = antd.Card;
var Button = antd.Button;
var Popover = antd.Popover;
var Steps = antd.Steps;
var Tooltip = antd.Tooltip;
var message = antd.message;
var servicePopoverOpen = useState(null);
// 模拟:项目信息
var projectInfo = useMemo(function () {
return {
contractCode: 'HT-ZL-2025-001',
contractType: '正式合同',
projectName: '嘉兴氢能示范项目',
customerName: '嘉兴某某物流有限公司',
paymentMethod: '预付',
paymentCycle: '6个月',
contractStart: '2025-01-15',
contractEnd: '2026-01-14',
businessDept: '业务1部',
businessPerson: '张经理'
};
}, []);
// 模拟:本单提车收款单已选车辆及填写内容(只读展示)
var vehicles = useMemo(function () {
return [
{ key: 'v1', index: 1, brand: '东风', model: 'DFH1180', plateNo: '浙A12345', receivableRent: 30000, actualRent: '29800.00', rentRemark: '首期六期一次性付清', receivableDeposit: 10000, serviceItems: [{ name: '代处理费用', receivable: 200, actual: '200.00', discount: '0.00', remark: '' }, { name: '保险上浮', receivable: 500, actual: '480.00', discount: '20.00', remark: '客户协商' }], receivableService: 700, actualService: '680.00', discountAmount: '200.00', discountRemark: '首月优惠', discountProof: [{ name: '优惠审批单.pdf' }] },
{ key: 'v2', index: 2, brand: '福田', model: 'BJ1180', plateNo: '浙A23456', receivableRent: 27000, actualRent: '27000.00', rentRemark: '', receivableDeposit: 8000, serviceItems: [{ name: '保养费用', receivable: 300, actual: '300.00', discount: '0.00', remark: '含首保' }], receivableService: 300, actualService: '300.00', discountAmount: '0.00', discountRemark: '', discountProof: [] },
{ key: 'v3', index: 3, brand: '重汽', model: 'ZZ1187', plateNo: '浙A34567', receivableRent: 31200, actualRent: '31200.00', rentRemark: '按合同约定', receivableDeposit: 10000, serviceItems: [{ name: '代处理费用', receivable: 180, actual: '180.00', discount: '0.00', remark: '' }, { name: '上牌服务', receivable: 400, actual: '400.00', discount: '0.00', remark: '已含上牌' }], receivableService: 580, actualService: '580.00', discountAmount: '0.00', discountRemark: '', discountProof: [] },
{ key: 'v4', index: 4, brand: '陕汽', model: 'SX1313', plateNo: '', receivableRent: 28800, actualRent: '28500.00', rentRemark: '待交车后补全', receivableDeposit: 9000, serviceItems: [{ name: '保险上浮', receivable: 350, actual: '350.00', discount: '0.00', remark: '' }], receivableService: 350, actualService: '350.00', discountAmount: '300.00', discountRemark: '客户协商减免', discountProof: [] }
];
}, []);
var totals = useMemo(function () {
var receivableRent = 0, actualRent = 0, receivableDeposit = 0, receivableService = 0, actualService = 0, discountTotal = 0;
vehicles.forEach(function (v) {
receivableRent += Number(v.receivableRent) || 0;
actualRent += parseFloat(v.actualRent) || 0;
receivableDeposit += Number(v.receivableDeposit) || 0;
receivableService += Number(v.receivableService) || 0;
actualService += parseFloat(v.actualService) || 0;
discountTotal += parseFloat(v.discountAmount) || 0;
});
return {
receivableRent: receivableRent.toFixed(2),
actualRent: actualRent.toFixed(2),
receivableDeposit: receivableDeposit.toFixed(2),
receivableService: receivableService.toFixed(2),
actualService: actualService.toFixed(2),
discountTotal: discountTotal.toFixed(2)
};
}, [vehicles]);
var receivableTotal = (parseFloat(totals.receivableRent) + parseFloat(totals.receivableDeposit) + parseFloat(totals.receivableService)).toFixed(2);
var actualTotal = (parseFloat(totals.actualRent) + parseFloat(totals.receivableDeposit) + parseFloat(totals.actualService) - parseFloat(totals.discountTotal)).toFixed(2);
var receivablePopoverContent = React.createElement('div', { style: { padding: 8, minWidth: 220 } },
React.createElement('table', { style: { width: '100%', borderCollapse: 'collapse', fontSize: 13 } },
React.createElement('thead', null,
React.createElement('tr', null,
React.createElement('th', { style: { textAlign: 'left', padding: '6px 8px', borderBottom: '1px solid #f0f0f0' } }, '项目'),
React.createElement('th', { style: { textAlign: 'right', padding: '6px 8px', borderBottom: '1px solid #f0f0f0' } }, '金额')
)
),
React.createElement('tbody', null,
React.createElement('tr', null, React.createElement('td', { style: { padding: '6px 8px' } }, '总计应收车辆月租金'), React.createElement('td', { style: { textAlign: 'right', padding: '6px 8px' } }, totals.receivableRent + ' 元')),
React.createElement('tr', null, React.createElement('td', { style: { padding: '6px 8px' } }, '总计应收车辆保证金'), React.createElement('td', { style: { textAlign: 'right', padding: '6px 8px' } }, totals.receivableDeposit + ' 元')),
React.createElement('tr', null, React.createElement('td', { style: { padding: '6px 8px' } }, '总计应收服务费'), React.createElement('td', { style: { textAlign: 'right', padding: '6px 8px' } }, totals.receivableService + ' 元'))
)
)
);
var actualPopoverContent = React.createElement('div', { style: { padding: 8, minWidth: 220 } },
React.createElement('table', { style: { width: '100%', borderCollapse: 'collapse', fontSize: 13 } },
React.createElement('thead', null,
React.createElement('tr', null,
React.createElement('th', { style: { textAlign: 'left', padding: '6px 8px', borderBottom: '1px solid #f0f0f0' } }, '项目'),
React.createElement('th', { style: { textAlign: 'right', padding: '6px 8px', borderBottom: '1px solid #f0f0f0' } }, '金额')
)
),
React.createElement('tbody', null,
React.createElement('tr', null, React.createElement('td', { style: { padding: '6px 8px' } }, '总计实收车辆月租金'), React.createElement('td', { style: { textAlign: 'right', padding: '6px 8px' } }, totals.actualRent + ' 元')),
React.createElement('tr', null, React.createElement('td', { style: { padding: '6px 8px' } }, '总计应收车辆保证金'), React.createElement('td', { style: { textAlign: 'right', padding: '6px 8px' } }, totals.receivableDeposit + ' 元')),
React.createElement('tr', null, React.createElement('td', { style: { padding: '6px 8px' } }, '总计实收服务费'), React.createElement('td', { style: { textAlign: 'right', padding: '6px 8px' } }, totals.actualService + ' 元')),
React.createElement('tr', null, React.createElement('td', { style: { padding: '6px 8px' } }, '总计减免金额'), React.createElement('td', { style: { textAlign: 'right', padding: '6px 8px' } }, totals.discountTotal + ' 元'))
)
)
);
// 客户付款信息:到账/开票历史
var paymentList = useMemo(function () {
return [
{ id: '1', arrivalTime: '2026-03-01 10:00', arrivalAmount: '50000.00', invoiceTime: '2026-03-02 14:30', invoiceFiles: [{ name: '发票-HT-ZL-2025-001-001.pdf' }], remark: '首笔到账' },
{ id: '2', arrivalTime: '2026-03-10 09:00', arrivalAmount: '35280.00', invoiceTime: '2026-03-11 11:00', invoiceFiles: [{ name: '发票-HT-ZL-2025-001-002.pdf' }], remark: '第二笔' }
];
}, []);
var sumArrival = paymentList.reduce(function (s, r) { return s + (parseFloat(r.arrivalAmount) || 0); }, 0);
var unpaidAmount = (parseFloat(actualTotal) - sumArrival).toFixed(2);
if (parseFloat(unpaidAmount) < 0) unpaidAmount = '0.00';
// 审批情况:竖向步骤条
var approvalSteps = useMemo(function () {
return [
{ title: '业务部主管', department: '业务1部', status: '已通过', person: '张经理', approveTime: '2026-02-28 09:30' },
{ title: '财务部', department: '财务部', status: '已通过', person: '李财务', approveTime: '2026-02-28 10:15' },
{ title: '事业部主管', department: '事业部', status: '待审批', person: '-', approveTime: '-' }
];
}, []);
var layoutStyle = { padding: '16px 24px', background: '#f5f5f5', minHeight: '100vh' };
var cardStyle = { marginBottom: 16 };
var labelStyle = { marginBottom: 6, fontSize: 14, color: 'rgba(0,0,0,0.65)' };
var formRowStyle = { display: 'grid', gridTemplateColumns: '1fr 1fr 1fr', gap: '16px 24px', marginBottom: 16 };
var formItemStyle = { marginBottom: 12 };
var highlightStyle = { color: '#1890ff', fontWeight: 600, cursor: 'pointer' };
var valueStyle = { color: 'rgba(0,0,0,0.85)', fontSize: 14, lineHeight: '22px', minHeight: 22 };
var thBase = { padding: '10px 12px', border: '1px solid #f0f0f0', whiteSpace: 'nowrap', backgroundColor: '#fafafa' };
var tdBase = { padding: '8px 12px', border: '1px solid #f0f0f0', fontSize: 13 };
function handleBack() {
if (window.__receivableBack) window.__receivableBack();
else message.info('返回提车应收款列表(原型)');
}
return React.createElement('div', { style: layoutStyle },
React.createElement('div', { style: { marginBottom: 16 } },
React.createElement(Breadcrumb, {
items: [
{ title: '财务管理' },
{ title: '提车应收款' },
{ title: '提车收款单' }
]
})
),
React.createElement(Card, { title: '项目信息', style: cardStyle },
React.createElement('div', { style: formRowStyle },
React.createElement('div', { style: formItemStyle }, React.createElement('div', { style: labelStyle }, '合同编码'), React.createElement('div', { style: valueStyle }, projectInfo.contractCode || '—')),
React.createElement('div', { style: formItemStyle }, React.createElement('div', { style: labelStyle }, '合同类型'), React.createElement('div', { style: valueStyle }, projectInfo.contractType || '—')),
React.createElement('div', { style: formItemStyle }, React.createElement('div', { style: labelStyle }, '项目名称'), React.createElement('div', { style: valueStyle }, projectInfo.projectName || '—')),
React.createElement('div', { style: formItemStyle }, React.createElement('div', { style: labelStyle }, '客户名称'), React.createElement('div', { style: valueStyle }, projectInfo.customerName || '—')),
React.createElement('div', { style: formItemStyle }, React.createElement('div', { style: labelStyle }, '付款方式'), React.createElement('div', { style: valueStyle }, projectInfo.paymentMethod || '—')),
React.createElement('div', { style: formItemStyle }, React.createElement('div', { style: labelStyle }, '付款周期'), React.createElement('div', { style: valueStyle }, projectInfo.paymentCycle || '—')),
React.createElement('div', { style: formItemStyle }, React.createElement('div', { style: labelStyle }, '合同生效时间'), React.createElement('div', { style: valueStyle }, projectInfo.contractStart || '—')),
React.createElement('div', { style: formItemStyle }, React.createElement('div', { style: labelStyle }, '合同结束时间'), React.createElement('div', { style: valueStyle }, projectInfo.contractEnd || '—')),
React.createElement('div', { style: formItemStyle }, React.createElement('div', { style: labelStyle }, '业务部门'), React.createElement('div', { style: valueStyle }, projectInfo.businessDept || '—')),
React.createElement('div', { style: formItemStyle }, React.createElement('div', { style: labelStyle }, '业务负责人'), React.createElement('div', { style: valueStyle }, projectInfo.businessPerson || '—'))
)
),
React.createElement(Card, { title: '提车应收款信息', style: cardStyle },
React.createElement(React.Fragment, null,
React.createElement('div', { style: { marginBottom: 16, display: 'flex', gap: 24, alignItems: 'center' } },
React.createElement(Popover, { content: receivablePopoverContent, title: '应收款明细', trigger: 'click' },
React.createElement('span', { style: { cursor: 'pointer' } }, '应收款总额:', React.createElement('span', { style: highlightStyle }, receivableTotal, ' 元'))
),
React.createElement(Popover, { content: actualPopoverContent, title: '实收款明细', trigger: 'click' },
React.createElement('span', { style: { cursor: 'pointer' } }, '实收款总额:', React.createElement('span', { style: highlightStyle }, actualTotal, ' 元'))
)
),
React.createElement('div', { style: { overflowX: 'auto', marginBottom: 0 } },
React.createElement('table', { style: { width: '100%', minWidth: 1500, borderCollapse: 'collapse', fontSize: 13, tableLayout: 'fixed' } },
React.createElement('thead', null,
React.createElement('tr', null,
React.createElement('th', { style: Object.assign({}, thBase, { width: 50 }) }, '序号'),
React.createElement('th', { style: Object.assign({}, thBase, { width: 80 }) }, '品牌'),
React.createElement('th', { style: Object.assign({}, thBase, { width: 90 }) }, '型号'),
React.createElement('th', { style: Object.assign({}, thBase, { width: 100 }) }, '车牌号'),
React.createElement('th', { style: Object.assign({}, thBase, { textAlign: 'right', width: 120 }) }, '应收车辆月租金'),
React.createElement('th', { style: Object.assign({}, thBase, { width: 120 }) }, '实收车辆月租金'),
React.createElement('th', { style: Object.assign({}, thBase, { width: 130 }) }, '车辆租金备注'),
React.createElement('th', { style: Object.assign({}, thBase, { width: 100 }) }, '减免金额'),
React.createElement('th', { style: Object.assign({}, thBase, { width: 120 }) }, '减免金额备注'),
React.createElement('th', { style: Object.assign({}, thBase, { width: 100 }) }, '减免证明'),
React.createElement('th', { style: Object.assign({}, thBase, { textAlign: 'right', width: 110 }) }, '应收车辆保证金'),
React.createElement('th', { style: Object.assign({}, thBase, { width: 90 }) }, '服务费项目'),
React.createElement('th', { style: Object.assign({}, thBase, { textAlign: 'right', width: 90 }) }, '应收服务费'),
React.createElement('th', { style: Object.assign({}, thBase, { textAlign: 'right', width: 100 }) }, '实收服务费')
)
),
React.createElement('tbody', null,
vehicles.map(function (row) {
var servicePopover = React.createElement('div', { style: { padding: 8, minWidth: 320 } },
React.createElement('div', { style: { fontWeight: 600, marginBottom: 8 } }, '服务费项目'),
React.createElement('table', { style: { width: '100%', borderCollapse: 'collapse', fontSize: 12 } },
React.createElement('thead', null,
React.createElement('tr', null,
React.createElement('th', { style: { textAlign: 'left', padding: '6px 8px', borderBottom: '1px solid #f0f0f0' } }, '服务项目'),
React.createElement('th', { style: { textAlign: 'right', padding: '6px 8px', borderBottom: '1px solid #f0f0f0' } }, '应收费用'),
React.createElement('th', { style: { textAlign: 'right', padding: '6px 8px', borderBottom: '1px solid #f0f0f0' } }, '实收费用'),
React.createElement('th', { style: { textAlign: 'right', padding: '6px 8px', borderBottom: '1px solid #f0f0f0' } }, '减免费用'),
React.createElement('th', { style: { textAlign: 'left', padding: '6px 8px', borderBottom: '1px solid #f0f0f0' } }, '备注')
)
),
React.createElement('tbody', null,
(row.serviceItems || []).map(function (s, si) {
return React.createElement('tr', { key: si },
React.createElement('td', { style: { padding: '6px 8px' } }, s.name),
React.createElement('td', { style: { textAlign: 'right', padding: '6px 8px' } }, (s.receivable != null ? s.receivable : '') + ' 元'),
React.createElement('td', { style: { textAlign: 'right', padding: '6px 8px' } }, (s.actual != null ? s.actual : '') + ' 元'),
React.createElement('td', { style: { textAlign: 'right', padding: '6px 8px' } }, (s.discount != null ? s.discount : '0.00') + ' 元'),
React.createElement('td', { style: { padding: '6px 8px' } }, s.remark || '—')
);
})
)
)
);
var proofNames = (row.discountProof || []).map(function (p) { return p.name; }).join('、') || '—';
return React.createElement('tr', { key: row.key },
React.createElement('td', { style: tdBase }, row.index),
React.createElement('td', { style: tdBase }, row.brand),
React.createElement('td', { style: tdBase }, row.model),
React.createElement('td', { style: tdBase }, row.plateNo || '—'),
React.createElement('td', { style: Object.assign({}, tdBase, { textAlign: 'right' }) }, (row.receivableRent || 0) + ' 元'),
React.createElement('td', { style: tdBase }, (row.actualRent || '0.00') + ' 元'),
React.createElement('td', { style: tdBase }, row.rentRemark || '—'),
React.createElement('td', { style: tdBase }, (row.discountAmount || '0.00') + ' 元'),
React.createElement('td', { style: tdBase }, row.discountRemark || '—'),
React.createElement('td', { style: tdBase }, proofNames),
React.createElement('td', { style: Object.assign({}, tdBase, { textAlign: 'right' }) }, (row.receivableDeposit || 0) + ' 元'),
React.createElement('td', { style: tdBase },
React.createElement(Popover, { content: servicePopover, title: null, trigger: 'click', open: servicePopoverOpen[0] === row.key, onOpenChange: function (open) { servicePopoverOpen[1](open ? row.key : null); } },
React.createElement(Button, { type: 'link', size: 'small', style: { padding: 0 } }, '管理')
)
),
React.createElement('td', { style: Object.assign({}, tdBase, { textAlign: 'right' }) }, (row.receivableService || 0) + ' 元'),
React.createElement('td', { style: Object.assign({}, tdBase, { textAlign: 'right' }) }, (row.actualService || '0.00') + ' 元')
);
})
)
)
),
React.createElement('div', { style: { marginTop: 16, display: 'grid', gridTemplateColumns: '1fr 1fr 1fr 1fr', gap: 16, maxWidth: 800 } },
React.createElement('div', { style: formItemStyle }, React.createElement('div', { style: labelStyle }, '氢费预付款应收金额'), React.createElement('div', { style: valueStyle }, '3580.00 元')),
React.createElement('div', { style: formItemStyle }, React.createElement('div', { style: labelStyle }, '氢费预付款实收金额'), React.createElement('div', { style: valueStyle }, '3500.00 元')),
React.createElement('div', { style: formItemStyle }, React.createElement('div', { style: labelStyle }, '减免金额'), React.createElement('div', { style: valueStyle }, '80.00 元')),
React.createElement('div', { style: formItemStyle }, React.createElement('div', { style: labelStyle }, '减免金额备注'), React.createElement('div', { style: valueStyle }, '预付款批量减免'))
),
React.createElement('div', { style: { display: 'grid', gridTemplateColumns: '1fr 1fr', gap: '16px 24px', marginTop: 16 } },
React.createElement('div', { style: formItemStyle }, React.createElement('div', { style: labelStyle }, '开票方式'), React.createElement('div', { style: valueStyle }, '先开票后付款')),
React.createElement('div', { style: Object.assign({}, formItemStyle, { gridColumn: '1 / -1' }) }, React.createElement('div', { style: labelStyle }, '开票备注'), React.createElement('div', { style: valueStyle }, '增值税专用发票税率13%,开票项目:*现代服务*车辆租赁费;备注:嘉兴氢能示范项目-提车首付款'))
)
)
),
React.createElement(Card, { title: '客户付款信息', style: cardStyle },
React.createElement('div', { style: { marginBottom: 12, fontSize: 14 } }, '未付金额:', React.createElement('span', { style: highlightStyle }, unpaidAmount, ' 元')),
React.createElement('table', { style: { width: '100%', borderCollapse: 'collapse', fontSize: 13 } },
React.createElement('thead', null,
React.createElement('tr', null,
React.createElement('th', { style: Object.assign({}, thBase, { width: 160 }) }, '到账时间'),
React.createElement('th', { style: Object.assign({}, thBase, { width: 120 }) }, '到账金额'),
React.createElement('th', { style: Object.assign({}, thBase, { width: 160 }) }, '开票时间'),
React.createElement('th', { style: thBase }, '发票附件'),
React.createElement('th', { style: thBase }, '备注')
)
),
React.createElement('tbody', null,
paymentList.map(function (r) {
var files = (r.invoiceFiles || []).map(function (f, i) { return React.createElement(Button, { key: i, type: 'link', size: 'small', style: { padding: 0, height: 'auto' }, onClick: function () { message.info('预览:' + (f.name || '附件')); } }, f.name || '附件'); });
var remarkEl = r.remark && r.remark.length > 20
? React.createElement(Tooltip, { title: r.remark }, React.createElement('span', { style: { display: 'inline-block', maxWidth: 160, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' } }, r.remark))
: (r.remark || '—');
return React.createElement('tr', { key: r.id },
React.createElement('td', { style: tdBase }, r.arrivalTime || '—'),
React.createElement('td', { style: tdBase }, r.arrivalAmount ? r.arrivalAmount + ' 元' : '—'),
React.createElement('td', { style: tdBase }, r.invoiceTime || '—'),
React.createElement('td', { style: tdBase }, files.length ? React.createElement('span', null, files) : '—'),
React.createElement('td', { style: tdBase }, remarkEl)
);
})
)
)
),
React.createElement(Card, { title: '审批情况', style: cardStyle },
React.createElement(Steps, {
direction: 'vertical',
current: approvalSteps.findIndex(function (s) { return s.status === '待审批'; }) >= 0 ? approvalSteps.findIndex(function (s) { return s.status === '待审批'; }) : approvalSteps.length,
style: { paddingLeft: 8 },
items: approvalSteps.map(function (step, idx) {
return {
title: step.department || step.title,
description: React.createElement('div', { style: { marginTop: 4, fontSize: 13, color: 'rgba(0,0,0,0.65)' } },
React.createElement('div', null, '审批状态:', step.status),
React.createElement('div', null, '审批人:', step.person),
React.createElement('div', null, '审批时间:', step.approveTime)
),
status: step.status === '已通过' ? 'finish' : step.status === '待审批' ? 'wait' : 'process'
};
})
})
),
React.createElement('div', { style: { marginTop: 24 } },
React.createElement(Button, { onClick: handleBack }, '返回')
)
);
};

View File

@@ -0,0 +1,465 @@
// 【重要】必须使用 const Component 作为组件变量名
// 财务管理 - 提车应收款2026年3月5日版本
const Component = function () {
var useState = React.useState;
var useMemo = React.useMemo;
var antd = window.antd;
var Breadcrumb = antd.Breadcrumb;
var Card = antd.Card;
var Table = antd.Table;
var Button = antd.Button;
var Select = antd.Select;
var Input = antd.Input;
var Space = antd.Space;
var Popover = antd.Popover;
var Tag = antd.Tag;
var Modal = antd.Modal;
var message = antd.message;
// 筛选条件
var filterContractCode = useState(undefined);
var filterProjectName = useState(undefined);
var filterCustomerName = useState(undefined);
var filterBusinessDept = useState(undefined);
var filterBusinessPerson = useState(undefined);
// 主表展开行:只允许同时展开一行,展开新的则收起其他
var expandedRowKeysState = useState([]);
var expandedRowKeys = expandedRowKeysState[0];
var setExpandedRowKeys = expandedRowKeysState[1];
var deleteConfirmVisible = useState(false);
var deleteConfirmRecord = useState(null);
var deleteConfirmParentRecord = useState(null);
var requirementModalVisible = useState(false);
var filterExpanded = useState(false);
// 主表数据:按合同编码聚合,每条主表下有多条提车应收款明细(子表)
var mainListData = [
{
contractCode: 'HT-ZL-2025-001',
contractType: '正式合同',
projectName: '嘉兴氢能示范项目',
customerName: '嘉兴某某物流有限公司',
businessDept: '业务1部',
businessPerson: '张经理',
contractEffectiveDate: '2025-01-15',
totalReceivable: 256800.00,
totalActual: 255700.00,
totalDiscount: 1100.00,
totalFinanceReceived: 209900.00,
children: [
{ seq: 1, auditStatus: '审批通过', creator: '张三', chargeTime: '2026-02-20 10:00', deliveryCount: 3, deliveryVehicles: [{ brand: '东风', model: 'DFH1180', plateNo: '浙A12345' }, { brand: '福田', model: 'BJ1180', plateNo: '浙A23456' }, { brand: '重汽', model: 'ZZ1187', plateNo: '浙A34567' }], receivableTotal: 98700.00, actualTotal: 98200.00, discountTotal: 500.00, discountProof: '首月优惠审批单', arrivalAmount: 98200.00, arrivalTime: '2026-02-21 14:30', financeReceived: 98200.00, isInvoiced: '已开票', invoiceMethod: '先开票后付款', invoiceTime: '2026-02-22 11:00', invoicedAmount: 98200.00, invoiceAttachment: '发票-HT-ZL-2025-001-001.pdf' },
{ seq: 2, auditStatus: '待审批', creator: '李四', chargeTime: '2026-03-01 09:30', deliveryCount: 2, deliveryVehicles: [{ brand: '陕汽', model: 'SX1313', plateNo: '浙A45678' }, { brand: '解放', model: 'J6P', plateNo: '浙A56789' }], receivableTotal: 57300.00, actualTotal: 57300.00, discountTotal: 0.00, discountProof: '-', arrivalAmount: 57300.00, arrivalTime: '2026-03-02 10:00', financeReceived: 57300.00, isInvoiced: '部分开票', invoiceMethod: '先付款后开票', invoiceTime: '-', invoicedAmount: '0.00', invoiceAttachment: '-' },
{ seq: 3, auditStatus: '审批中', creator: '王五', chargeTime: '2026-03-10 11:00', deliveryCount: 1, deliveryVehicles: [{ brand: '江淮', model: '格尔发K5', plateNo: '浙A67890' }], receivableTotal: 32800.00, actualTotal: 32800.00, discountTotal: 0.00, discountProof: '-', arrivalAmount: 32800.00, arrivalTime: '2026-03-11 09:00', financeReceived: 32800.00, isInvoiced: '未开票', invoiceMethod: '先付款后开票', invoiceTime: '-', invoicedAmount: '0.00', invoiceAttachment: '-' },
{ seq: 4, auditStatus: '已驳回', creator: '赵六', chargeTime: '2026-03-15 14:20', deliveryCount: 2, deliveryVehicles: [{ brand: '东风', model: 'DFH1250', plateNo: '浙A11111' }, { brand: '福田', model: '欧曼EST', plateNo: '浙A22222' }], receivableTotal: 45800.00, actualTotal: 45800.00, discountTotal: 0.00, discountProof: '-', arrivalAmount: 0.00, arrivalTime: '-', financeReceived: 0.00, isInvoiced: '未开票', invoiceMethod: '先付款后开票', invoiceTime: '-', invoicedAmount: '0.00', invoiceAttachment: '-' },
{ seq: 5, auditStatus: '审批通过', creator: '张三', chargeTime: '2026-03-20 09:00', deliveryCount: 2, deliveryVehicles: [{ brand: '重汽', model: '豪沃T7H', plateNo: '浙B33333' }, { brand: '陕汽', model: '德龙X3000', plateNo: '浙B44444' }], receivableTotal: 22200.00, actualTotal: 21600.00, discountTotal: 600.00, discountProof: '客户协商减免', arrivalAmount: 21600.00, arrivalTime: '2026-03-21 10:30', financeReceived: 21600.00, isInvoiced: '已开票', invoiceMethod: '先开票后付款', invoiceTime: '2026-03-22 14:00', invoicedAmount: 21600.00, invoiceAttachment: '发票-HT-ZL-2025-001-005.pdf' }
]
},
{
contractCode: 'HT-ZL-2025-002',
contractType: '正式合同',
projectName: '上海物流租赁项目',
customerName: '上海某某运输公司',
businessDept: '业务2部',
businessPerson: '李专员',
contractEffectiveDate: '2025-02-01',
totalReceivable: 132600.00,
totalActual: 132600.00,
totalDiscount: 0.00,
totalFinanceReceived: 132600.00,
children: [
{ seq: 1, auditStatus: '审批通过', creator: '李专员', chargeTime: '2026-02-28 14:00', deliveryCount: 2, deliveryVehicles: [{ brand: '江淮', model: '格尔发K5', plateNo: '沪B11111' }, { brand: '东风', model: 'DFH1250', plateNo: '沪B22222' }], receivableTotal: 65800.00, actualTotal: 65800.00, discountTotal: 0.00, discountProof: '-', arrivalAmount: 65800.00, arrivalTime: '2026-03-01 09:00', financeReceived: 65800.00, isInvoiced: '已开票', invoiceMethod: '先开票后付款', invoiceTime: '2026-03-02 15:20', invoicedAmount: 65800.00, invoiceAttachment: '发票-HT-ZL-2025-002.pdf' },
{ seq: 2, auditStatus: '审批通过', creator: '李专员', chargeTime: '2026-03-08 10:30', deliveryCount: 1, deliveryVehicles: [{ brand: '解放', model: 'JH6', plateNo: '沪B33333' }], receivableTotal: 33400.00, actualTotal: 33400.00, discountTotal: 0.00, discountProof: '-', arrivalAmount: 33400.00, arrivalTime: '2026-03-09 11:00', financeReceived: 33400.00, isInvoiced: '部分开票', invoiceMethod: '先付款后开票', invoiceTime: '-', invoicedAmount: '0.00', invoiceAttachment: '-' },
{ seq: 3, auditStatus: '待审批', creator: '李专员', chargeTime: '2026-03-18 16:00', deliveryCount: 2, deliveryVehicles: [{ brand: '福田', model: 'BJ1180', plateNo: '沪B44444' }, { brand: '重汽', model: 'ZZ1187', plateNo: '沪B55555' }], receivableTotal: 33400.00, actualTotal: 33400.00, discountTotal: 0.00, discountProof: '-', arrivalAmount: 33400.00, arrivalTime: '2026-03-19 09:00', financeReceived: 33400.00, isInvoiced: '未开票', invoiceMethod: '先开票后付款', invoiceTime: '-', invoicedAmount: '0.00', invoiceAttachment: '-' }
]
},
{
contractCode: 'HT-ZL-2025-003',
contractType: '正式合同',
projectName: '杭州城配租赁项目',
customerName: '杭州某某租赁有限公司',
businessDept: '业务3部',
businessPerson: '王专员',
contractEffectiveDate: '2025-02-10',
totalReceivable: 82400.00,
totalActual: 82400.00,
totalDiscount: 0.00,
totalFinanceReceived: 41200.00,
children: [
{ seq: 1, auditStatus: '已驳回', creator: '王专员', chargeTime: '2026-03-05 11:00', deliveryCount: 1, deliveryVehicles: [{ brand: '福田', model: '欧曼EST', plateNo: '浙C33333' }], receivableTotal: 41200.00, actualTotal: 41200.00, discountTotal: 0.00, discountProof: '-', arrivalAmount: 0.00, arrivalTime: '-', financeReceived: 0.00, isInvoiced: '未开票', invoiceMethod: '先付款后开票', invoiceTime: '-', invoicedAmount: '0.00', invoiceAttachment: '-' },
{ seq: 2, auditStatus: '审批通过', creator: '王专员', chargeTime: '2026-03-12 09:15', deliveryCount: 1, deliveryVehicles: [{ brand: '东风', model: 'DFH1180', plateNo: '浙C44444' }], receivableTotal: 41200.00, actualTotal: 41200.00, discountTotal: 0.00, discountProof: '-', arrivalAmount: 41200.00, arrivalTime: '2026-03-13 14:00', financeReceived: 41200.00, isInvoiced: '已开票', invoiceMethod: '先开票后付款', invoiceTime: '2026-03-14 10:00', invoicedAmount: 41200.00, invoiceAttachment: '发票-HT-ZL-2025-003.pdf' }
]
}
];
var mainListState = useState(mainListData);
var mainList = mainListState[0];
var setMainList = mainListState[1];
var filterOptions = useMemo(function () {
var list = mainList;
var codes = [], projects = [], customers = [], depts = [], persons = [];
list.forEach(function (r) {
if (r.contractCode && codes.indexOf(r.contractCode) === -1) codes.push(r.contractCode);
if (r.projectName && projects.indexOf(r.projectName) === -1) projects.push(r.projectName);
if (r.customerName && customers.indexOf(r.customerName) === -1) customers.push(r.customerName);
if (r.businessDept && depts.indexOf(r.businessDept) === -1) depts.push(r.businessDept);
if (r.businessPerson && persons.indexOf(r.businessPerson) === -1) persons.push(r.businessPerson);
});
return {
contractCode: codes.map(function (v) { return { value: v, label: v }; }),
projectName: projects.map(function (v) { return { value: v, label: v }; }),
customerName: customers.map(function (v) { return { value: v, label: v }; }),
businessDept: depts.map(function (v) { return { value: v, label: v }; }),
businessPerson: persons.map(function (v) { return { value: v, label: v }; })
};
}, [mainList]);
var filteredMainList = useMemo(function () {
var list = mainList;
var code = filterContractCode[0];
var project = filterProjectName[0];
var customer = filterCustomerName[0];
var dept = filterBusinessDept[0];
var person = filterBusinessPerson[0];
if (code) list = list.filter(function (r) { return r.contractCode === code; });
if (project) list = list.filter(function (r) { return r.projectName === project; });
if (customer) list = list.filter(function (r) { return r.customerName === customer; });
if (dept) list = list.filter(function (r) { return r.businessDept === dept; });
if (person) list = list.filter(function (r) { return r.businessPerson === person; });
return list;
}, [mainList, filterContractCode[0], filterProjectName[0], filterCustomerName[0], filterBusinessDept[0], filterBusinessPerson[0]]);
// 主表 dataSource 去掉 children避免 Table 把子节点当树形数据渲染出多余空白行;子表数据通过 _detailList 在展开行内使用
var mainTableDataSource = useMemo(function () {
return filteredMainList.map(function (r) {
var o = {};
for (var k in r) if (k !== 'children') o[k] = r[k];
o._detailList = r.children || [];
return o;
});
}, [filteredMainList]);
function fmtMoney(v) {
if (v === null || v === undefined) return '0.00元';
var n = typeof v === 'number' ? v : parseFloat(v);
return (isNaN(n) ? '0.00' : n.toFixed(2)) + '元';
}
function goCollect(record) {
if (window.__receivableToCollect) window.__receivableToCollect(record);
else message.info('跳转至提车应收款-收款(原型)');
}
function goView(record) {
message.info('查看提车收款单详情(原型)');
}
function goEdit(record) {
if (window.__receivableToEdit) window.__receivableToEdit(record);
else message.info('跳转至提车应收款-编辑(原型)');
}
function goInvoice(record) {
if (window.__receivableToInvoice) window.__receivableToInvoice(record);
else message.info('跳转至开票(原型)');
}
var layoutStyle = { padding: '16px 24px', background: '#f5f5f5', minHeight: '100vh' };
var cardStyle = { marginBottom: 16 };
var filterLabelStyle = { marginBottom: 6, fontSize: 14, color: 'rgba(0,0,0,0.65)' };
var filterItemStyle = { marginBottom: 12 };
var filterControlStyle = { width: '100%' };
// 主表列(宽度压缩在一屏内显示)
var mainColumns = [
{ title: '合同编码', dataIndex: 'contractCode', key: 'contractCode', width: 120, ellipsis: true, render: function (v) { return v || '—'; } },
{ title: '合同类型', dataIndex: 'contractType', key: 'contractType', width: 88, ellipsis: true, render: function (v) { return v || '—'; } },
{ title: '项目名称', dataIndex: 'projectName', key: 'projectName', width: 120, ellipsis: true, render: function (v) { return v || '—'; } },
{ title: '客户名称', dataIndex: 'customerName', key: 'customerName', width: 120, ellipsis: true, render: function (v) { return v || '—'; } },
{ title: '合同生效日期', dataIndex: 'contractEffectiveDate', key: 'contractEffectiveDate', width: 110, render: function (v) { return v || '—'; } },
{ title: '业务部门', dataIndex: 'businessDept', key: 'businessDept', width: 100, render: function (v) { return v || '—'; } },
{ title: '业务负责人', dataIndex: 'businessPerson', key: 'businessPerson', width: 100, render: function (v) { return v || '—'; } },
{
title: '操作',
key: 'action',
width: 100,
fixed: 'right',
render: function (_, record) {
return React.createElement(Button, { type: 'link', size: 'small', onClick: function () { goCollect(record); } }, '提车收款单');
}
}
];
// 子表:提车数量气泡用 state 控制当前展开的行
var deliveryPopoverOpen = useState(null);
function renderDeliveryPopover(record) {
var vehicles = record.deliveryVehicles || [];
var listStyle = { width: '100%', borderCollapse: 'collapse', fontSize: 13 };
var thStyle = { padding: '6px 10px', textAlign: 'left', borderBottom: '1px solid #f0f0f0', backgroundColor: '#fafafa', fontWeight: 600 };
var tdStyle = { padding: '6px 10px', borderBottom: '1px solid #f0f0f0' };
var content = vehicles.length === 0 ? React.createElement('div', { style: { padding: 8 } }, '—') : React.createElement('div', { style: { padding: 0, minWidth: 200 } },
React.createElement('table', { style: listStyle },
React.createElement('thead', null,
React.createElement('tr', null,
React.createElement('th', { style: thStyle }, '品牌'),
React.createElement('th', { style: thStyle }, '型号'),
React.createElement('th', { style: thStyle }, '车牌号')
)
),
React.createElement('tbody', null,
vehicles.map(function (v, i) {
return React.createElement('tr', { key: i },
React.createElement('td', { style: tdStyle }, v.brand || '—'),
React.createElement('td', { style: tdStyle }, v.model || '—'),
React.createElement('td', { style: tdStyle }, v.plateNo || '—')
);
})
)
)
);
var popoverKey = (record._parentCode || '') + '-' + record.seq + '-' + (record.chargeTime || '');
return React.createElement(Popover, {
content: content,
title: '车辆详情',
trigger: 'click',
open: deliveryPopoverOpen[0] === popoverKey,
onOpenChange: function (open) { deliveryPopoverOpen[1](open ? popoverKey : null); }
}, React.createElement(Button, { type: 'link', size: 'small', style: { padding: 0 } }, String(record.deliveryCount)));
}
// 子表左缩进与主表展开列宽一致,使序号左侧边框与合同编码左侧边框对齐
var expandColumnWidth = 48;
var subColumns = [
{ title: '序号', dataIndex: 'seq', key: 'seq', width: 52, align: 'center' },
{
title: '审批状态',
dataIndex: 'auditStatus',
key: 'auditStatus',
width: 90,
render: function (v, record) {
var status = (record && record.auditStatus != null) ? String(record.auditStatus).trim() : (v != null ? String(v).trim() : '');
var isRejected = status === '已驳回' || status === '审批驳回';
var color = status === '审批通过' ? 'success' : status === '待审批' ? 'processing' : status === '审批中' ? 'warning' : isRejected ? 'error' : 'default';
var text = isRejected ? '审批驳回' : (status || '—');
return React.createElement(Tag, { color: color }, text);
}
},
{ title: '创建时间', dataIndex: 'chargeTime', key: 'chargeTime', width: 128, render: function (v) { return v || '—'; } },
{ title: '创建人', dataIndex: 'creator', key: 'creator', width: 88, render: function (v) { return v || '—'; } },
{ title: '提车数量', key: 'deliveryCount', width: 76, render: function (_, record) { return renderDeliveryPopover(record); } },
{ title: '应收款总额', dataIndex: 'receivableTotal', key: 'receivableTotal', width: 98, align: 'right', render: function (v) { return fmtMoney(v); } },
{ title: '实收款总额', dataIndex: 'actualTotal', key: 'actualTotal', width: 98, align: 'right', render: function (v) { return fmtMoney(v); } },
{ title: '减免总金额', dataIndex: 'discountTotal', key: 'discountTotal', width: 88, align: 'right', render: function (v) { return fmtMoney(v); } },
{ title: '实际到账金额', dataIndex: 'arrivalAmount', key: 'arrivalAmount', width: 100, align: 'right', render: function (v, record) { if (record && record.auditStatus === '待审批') return '—'; return fmtMoney(v); } },
{ title: '是否已开票', dataIndex: 'isInvoiced', key: 'isInvoiced', width: 88, render: function (v, record) { if (record && record.auditStatus === '待审批') return '—'; if (v === true || v === '已开票') return '已开票'; if (v === '部分开票') return '部分开票'; return '未开票'; } },
{ title: '已开票金额', dataIndex: 'invoicedAmount', key: 'invoicedAmount', width: 100, align: 'right', render: function (v, record) { if (record && record.auditStatus === '待审批') return '—'; var n = typeof v === 'number' ? v : parseFloat(v); return fmtMoney(isNaN(n) ? 0 : n); } },
{
title: '操作',
key: 'action',
width: 180,
fixed: 'right',
render: function (_, record) {
var auditStatus = record && record.auditStatus;
var isPending = auditStatus === '待审批';
var isRejected = auditStatus === '已驳回' || auditStatus === '审批驳回';
var isApproved = auditStatus === '审批通过';
var canEdit = isPending || isRejected;
var parentRecord = record && record._parentRecord;
function handleDelete() {
deleteConfirmRecord[1](record);
deleteConfirmParentRecord[1](parentRecord);
deleteConfirmVisible[1](true);
}
return React.createElement(Space, { size: 'small' },
React.createElement(Button, { type: 'link', size: 'small', onClick: function () { goView(record); } }, '查看'),
canEdit ? React.createElement(Button, { type: 'link', size: 'small', onClick: function () { goEdit(record); } }, '编辑') : null,
(isPending || isRejected) ? React.createElement(Button, { type: 'link', size: 'small', danger: true, onClick: handleDelete }, '删除') : null,
isApproved ? React.createElement(Button, { type: 'link', size: 'small', onClick: function () { goInvoice(record); } }, '开票') : null
);
}
}
];
function confirmDeleteSub() {
var parent = deleteConfirmParentRecord[0];
var row = deleteConfirmRecord[0];
var list = (parent && (parent._detailList || parent.children)) || [];
if (parent && row && list.length >= 0) {
var newChildren = list.filter(function (r) { return !(r.seq === row.seq && r.chargeTime === row.chargeTime); });
// 删除后序号重新生成 1、2、3...
newChildren = newChildren.map(function (r, index) { var o = {}; for (var k in r) o[k] = r[k]; o.seq = index + 1; return o; });
setMainList(function (prev) {
return prev.map(function (p) {
if (p.contractCode !== parent.contractCode) return p;
var next = {}; for (var k in p) next[k] = p[k]; next.children = newChildren; return next;
});
});
}
deleteConfirmVisible[1](false);
deleteConfirmRecord[1](null);
deleteConfirmParentRecord[1](null);
message.success('已删除');
}
function expandRowRender(record) {
var rows = (record._detailList || []).map(function (r) { var o = {}; for (var k in r) o[k] = r[k]; o._parentCode = record.contractCode; o._parentRecord = record; return o; });
var sumReceivable = rows.reduce(function (acc, r) { return acc + (Number(r.receivableTotal) || 0); }, 0);
var sumActual = rows.reduce(function (acc, r) { return acc + (Number(r.actualTotal) || 0); }, 0);
var sumDiscount = rows.reduce(function (acc, r) { return acc + (Number(r.discountTotal) || 0); }, 0);
var sumArrival = rows.reduce(function (acc, r) { return acc + (Number(r.arrivalAmount) || 0); }, 0);
var sumInvoiced = rows.reduce(function (acc, r) { return acc + (Number(r.invoicedAmount) || 0); }, 0);
var summaryStyle = { backgroundColor: '#fafafa', fontWeight: 600 };
return React.createElement('div', {
style: { marginBottom: 0, paddingLeft: expandColumnWidth, boxSizing: 'border-box' },
draggable: false,
onDragStart: function (e) { e.preventDefault(); }
},
React.createElement(Table, {
rowKey: function (r) { return (record.contractCode || '') + '-' + (r.seq || r.chargeTime || Math.random()); },
columns: subColumns,
dataSource: rows,
pagination: false,
size: 'small',
bordered: true,
summary: rows.length > 0 ? function () {
return React.createElement(Table.Summary, null,
React.createElement(Table.Summary.Row, { style: summaryStyle },
React.createElement(Table.Summary.Cell, { index: 0, align: 'center' }, '总计'),
React.createElement(Table.Summary.Cell, { index: 1 }, ''),
React.createElement(Table.Summary.Cell, { index: 2 }, ''),
React.createElement(Table.Summary.Cell, { index: 3 }, ''),
React.createElement(Table.Summary.Cell, { index: 4 }, ''),
React.createElement(Table.Summary.Cell, { index: 5, align: 'right' }, fmtMoney(sumReceivable)),
React.createElement(Table.Summary.Cell, { index: 6, align: 'right' }, fmtMoney(sumActual)),
React.createElement(Table.Summary.Cell, { index: 7, align: 'right' }, fmtMoney(sumDiscount)),
React.createElement(Table.Summary.Cell, { index: 8, align: 'right' }, fmtMoney(sumArrival)),
React.createElement(Table.Summary.Cell, { index: 9 }, ''),
React.createElement(Table.Summary.Cell, { index: 10, align: 'right' }, fmtMoney(sumInvoiced)),
React.createElement(Table.Summary.Cell, { index: 11 }, '')
)
);
} : null
})
);
}
var requirementContent = '提车应收款2026年3月5日版本\n一个「数字化资产ONEOS运管平台」中的「财务管理」「提车应收款」模块\n#面包屑:财务管理-提车应收款;\n\n页面分为2个卡片\n1.筛选:\n#支持合同编码/项目名称/客户名称/业务部门/业务负责人等筛选方式;\n1.1.合同编码:选择器,支持输入框内手动输入下拉模糊匹配对应项;\n1.2.项目名称:选择器,支持输入框内手动输入下拉模糊匹配对应项;\n1.3.客户名称:选择器,支持输入框内手动输入下拉模糊匹配对应项;\n1.4.业务部门:选择器,支持选择所有业务部门;\n1.5.业务负责人:选择器,支持选择所有业务负责人;\n\n2.列表:\n#列表展示方式为:嵌套子表格,分为主表和子表,可点击主表展开子表,一个合同编码可以展开多个提车应收款明细;\n2.1.主表显示字段为:合同编码、合同类型、项目名称、客户名称、合同生效日期、业务部门、业务负责人、操作;\n2.1.1.合同编码:显示该提车应收款租赁合同对应合同编码;\n2.1.2.合同类型:显示该租赁合同对应合同类型,显示该合同为试用合同还是正式合同;\n2.1.3.项目名称:显示该租赁合同对应项目名称;\n2.1.4.客户名称:显示该租赁合同对应客户名称;\n2.1.5.合同生效日期显示该租赁合同生效日期格式为YYYY-MM-DD\n2.1.6.业务部门:显示该租赁合同对应业务部门名称;\n2.1.7.业务负责人:显示该租赁合同对应业务负责人;\n2.1.8.操作:提车收款单;\n 2.1.8.1.提车收款单:点击提车收款单,跳转提车收款单页进行子表创建;\n主表右下角为分页符支持选择单页显示多少条数据\n\n2.2.子表显示字段为:序号、审批状态、创建时间、提车数量、应收款总额、实收款总额、减免总金额、实际到账金额、是否已开票、已开票金额、操作;\n2.2.1.序号按照提车首付款收费单据提交时间从最早开始显示第1条按照顺序1.2.3....\n2.2.2.审批状态:审批通过、待审批、审批中、审批驳回;\n 2.2.2.1.审批通过:该审批通过最终节点审批,显示为审批通过;\n 2.2.2.2.待审批:审批提车收款单仅保存,但未提交审批;\n 2.2.2.3.审批中:已发起审批流程,但未完成最终节点审批;\n 2.2.2.4.审批驳回:发起审批流程,但任意节点被驳回。被驳回的提车收款单支持重新修改后提交审批;\n2.2.3.创建时间显示提车收款单创建时间格式为YYYY-MM-DD HH:MM\n2.2.4.创建人:显示已提车收款单创建人姓名;\n2.2.5.提车数量:显示该提车收费单对应提车数量,点击提车数量弹出气泡卡片,卡片中列表显示品牌、型号、车牌号;\n2.2.6.应收款金额按照该提车收费单据应收款金额格式为xx.xx元\n2.2.7.实收款金额按照该提车收费单据实收款金额格式为xx.xx元\n2.2.8.减免金额按照该提车收费单减免总金额显示当前子表对应减免总额格式为xx.xx元\n2.2.9.实际到账金额显示该提车收费单财务填写的实际到账金额格式为xx.xx元\n2.2.10.是否已开票:显示财务是否完成开票,已开票显示为:已开票,未开票显示为:未开票,部分开票显示为:部分开票;\n2.2.11.已开票金额显示财务已开票金额格式为xx.xx元\n2.2.12.总计:显示应收款总额、实收款总额、减免总金额、实际到账金额、已开票金额等所有子表求和数据;\n2.2.13.操作:查看、编辑、删除、开票;\n 2.2.12.1.查看:点击查看后,跳转提车应收款-查看页面,审批通过、待审批、审批中、审批驳回均可点击查看来查看提车收款单详情;\n 2.2.12.2.编辑:点击编辑后,跳转提车应收款-编辑页面,待审批、审批驳回均可进行编辑操作;\n 2.2.12.2.删除:待审批、审批驳回状态子表支持删除功能,点击弹出二次确认,点击确认后删除该记录;\n 2.2.12.3.开票:点击开票后,进入提车应收款-开票页面,审批通过状态子表才显示,开票由财务人员操作,需要做权限控制,其他用户没有开票入口;';
return React.createElement('div', { style: layoutStyle },
React.createElement('div', { style: { display: 'flex', alignItems: 'center', justifyContent: 'space-between', marginBottom: 16 } },
React.createElement(Breadcrumb, {
items: [
{ title: '财务管理' },
{ title: '提车应收款' }
]
}),
React.createElement(Button, { type: 'link', style: { padding: 0 }, onClick: function () { requirementModalVisible[1](true); } }, '查看需求说明')
),
React.createElement(Card, { title: '筛选', style: cardStyle },
React.createElement('div', {
style: { display: 'grid', gridTemplateColumns: '1fr 1fr 1fr', gap: '16px 24px', alignItems: 'start' }
},
React.createElement('div', { style: filterItemStyle },
React.createElement('div', { style: filterLabelStyle }, '合同编码'),
React.createElement(Select, {
placeholder: '请选择或输入合同编码',
allowClear: true,
showSearch: true,
style: filterControlStyle,
value: filterContractCode[0],
onChange: function (v) { filterContractCode[1](v); },
options: filterOptions.contractCode,
filterOption: function (input, opt) { return (opt.label || '').toString().toLowerCase().indexOf((input || '').toLowerCase()) !== -1; }
})
),
React.createElement('div', { style: filterItemStyle },
React.createElement('div', { style: filterLabelStyle }, '项目名称'),
React.createElement(Select, {
placeholder: '请选择或输入项目名称',
allowClear: true,
showSearch: true,
style: filterControlStyle,
value: filterProjectName[0],
onChange: function (v) { filterProjectName[1](v); },
options: filterOptions.projectName,
filterOption: function (input, opt) { return (opt.label || '').toString().toLowerCase().indexOf((input || '').toLowerCase()) !== -1; }
})
),
React.createElement('div', { style: filterItemStyle },
React.createElement('div', { style: filterLabelStyle }, '客户名称'),
React.createElement(Select, {
placeholder: '请选择或输入客户名称',
allowClear: true,
showSearch: true,
style: filterControlStyle,
value: filterCustomerName[0],
onChange: function (v) { filterCustomerName[1](v); },
options: filterOptions.customerName,
filterOption: function (input, opt) { return (opt.label || '').toString().toLowerCase().indexOf((input || '').toLowerCase()) !== -1; }
})
),
filterExpanded[0] ? React.createElement('div', { style: filterItemStyle },
React.createElement('div', { style: filterLabelStyle }, '业务部门'),
React.createElement(Select, {
placeholder: '请选择业务部门',
allowClear: true,
style: filterControlStyle,
value: filterBusinessDept[0],
onChange: function (v) { filterBusinessDept[1](v); },
options: filterOptions.businessDept
})
) : null,
filterExpanded[0] ? React.createElement('div', { style: filterItemStyle },
React.createElement('div', { style: filterLabelStyle }, '业务负责人'),
React.createElement(Select, {
placeholder: '请选择业务负责人',
allowClear: true,
style: filterControlStyle,
value: filterBusinessPerson[0],
onChange: function (v) { filterBusinessPerson[1](v); },
options: filterOptions.businessPerson
})
) : null
),
React.createElement('div', { style: { display: 'flex', justifyContent: 'flex-end', gap: 8, marginTop: 16 } },
React.createElement(Button, { onClick: function () { filterContractCode[1](undefined); filterProjectName[1](undefined); filterCustomerName[1](undefined); filterBusinessDept[1](undefined); filterBusinessPerson[1](undefined); } }, '重置'),
React.createElement(Button, { type: 'primary' }, '查询'),
React.createElement(Button, { type: 'link', size: 'small', onClick: function () { filterExpanded[1](!filterExpanded[0]); } }, filterExpanded[0] ? '收起' : '展开')
)
),
React.createElement(Card, { title: '列表', style: cardStyle },
React.createElement(Table, {
rowKey: 'contractCode',
columns: mainColumns,
dataSource: mainTableDataSource,
expandable: {
expandedRowKeys: expandedRowKeys,
onExpandedRowsChange: function (keys) {
setExpandedRowKeys(keys.length ? [keys[keys.length - 1]] : []);
},
expandedRowRender: expandRowRender,
rowExpandable: function (record) { return (record._detailList && record._detailList.length > 0); },
columnWidth: expandColumnWidth
},
pagination: { pageSize: 10, showSizeChanger: true, showTotal: function (t) { return '共 ' + t + ' 条'; } },
size: 'middle',
bordered: true,
scroll: { x: 758 }
})
),
React.createElement(Modal, {
title: '确认删除',
open: deleteConfirmVisible[0],
onCancel: function () { deleteConfirmVisible[1](false); deleteConfirmRecord[1](null); deleteConfirmParentRecord[1](null); },
onOk: confirmDeleteSub,
okText: '确认',
cancelText: '取消'
}, '确定要删除该提车收款单记录吗?'),
React.createElement(Modal, {
title: '需求说明',
open: requirementModalVisible[0],
onCancel: function () { requirementModalVisible[1](false); },
width: 720,
footer: React.createElement(Button, { onClick: function () { requirementModalVisible[1](false); } }, '关闭'),
bodyStyle: { maxHeight: '70vh', overflow: 'auto' }
}, React.createElement('div', { style: { padding: '8px 0' } },
React.createElement('div', { style: { whiteSpace: 'pre-wrap', fontSize: 13, lineHeight: 1.6 } }, requirementContent))
)
);
};

View File

@@ -1,292 +0,0 @@
// 【重要】必须使用 const Component 作为组件变量名
// 提车应收款 - 收费明细(租赁费用管理-提车应收款,第二步由财务填写)
const Component = function() {
var useState = React.useState;
var useCallback = React.useCallback;
var useMemo = React.useMemo;
var antd = window.antd;
var DatePicker = antd ? antd.DatePicker : null;
var Input = antd ? antd.Input : null;
var Upload = antd ? antd.Upload : null;
var Button = antd ? antd.Button : null;
// 模拟:项目信息、车辆(业务提交后数据)、氢费(业务提交后)、开票基础信息
var mockProject = useMemo(function() {
return { contractCode: 'HT-ZL-2025-001', contractType: '正式合同', projectName: '北京朝阳区租赁项目', customerName: '某某科技有限公司', paymentMethod: '预付', paymentCycle: '1个月', department: '运营部', responsible: '张三' };
}, []);
var mockVehicleList = useMemo(function() {
return [
{ brand: '奔驰', model: 'E300L', plateNo: '京A12345', payableRent: '8000.00', rentRemark: '首月', deposit: '2000.00', serviceItems: [{ name: '保养服务', fee: '300.00', remark: '' }, { name: '保险', fee: '200.00', remark: '' }], serviceTotal: '500.00', discount: '0', discountRemark: '' },
{ brand: '宝马', model: '530Li', plateNo: '京B67890', payableRent: '7000.00', rentRemark: '', deposit: '1500.00', serviceItems: [{ name: '保养服务', fee: '250.00', remark: '' }], serviceTotal: '250.00', discount: '0', discountRemark: '' }
];
}, []);
var mockHydrogen = useMemo(function() {
return { paidTotal: '3580.00', discount: '0.00', discountRemark: '' };
}, []);
var mockInvoice = useMemo(function() {
return { customerName: '某某科技有限公司', taxId: '91330400MA2XXXXX1', address: '浙江省嘉兴市南湖区科技大道1号', phone: '0571-88888888', account: '6222021234567890123', bank: '中国工商银行嘉兴分行', mailingAddress: '浙江省嘉兴市南湖区科技大道1号' };
}, []);
var totalPayable = useMemo(function() {
var sum = 0;
for (var i = 0; i < mockVehicleList.length; i++) {
var r = mockVehicleList[i];
sum += parseFloat(r.payableRent) || 0;
sum += parseFloat(r.deposit) || 0;
sum += parseFloat(r.serviceTotal) || 0;
sum -= parseFloat(r.discount) || 0;
}
return sum.toFixed(2);
}, [mockVehicleList]);
var hydrogenPayableTotal = useMemo(function() {
var p = parseFloat(mockHydrogen.paidTotal) || 0;
var d = parseFloat(mockHydrogen.discount) || 0;
return (p - d >= 0 ? p - d : 0).toFixed(2);
}, [mockHydrogen]);
var invoiceAmount = useMemo(function() {
return (parseFloat(totalPayable) + parseFloat(hydrogenPayableTotal)).toFixed(2);
}, [totalPayable, hydrogenPayableTotal]);
var serviceModalRowState = useState(null);
var serviceModalRow = serviceModalRowState[0];
var setServiceModalRow = serviceModalRowState[1];
var cancelConfirmVisibleState = useState(false);
var cancelConfirmVisible = cancelConfirmVisibleState[0];
var setCancelConfirmVisible = cancelConfirmVisibleState[1];
var requirementVisibleState = useState(false);
var requirementVisible = requirementVisibleState[0];
var setRequirementVisible = requirementVisibleState[1];
var invoiceFormState = useState({ invoiceTime: '', remark: '', invoiceFiles: [] });
var invoiceForm = invoiceFormState[0];
var setInvoiceForm = invoiceFormState[1];
var handleSubmit = useCallback(function() {
alert('提交成功,跳转至提车应收款列表页');
}, []);
var handleCancelClick = useCallback(function() { setCancelConfirmVisible(true); }, []);
var handleCancelConfirm = useCallback(function(confirmed) {
setCancelConfirmVisible(false);
if (confirmed) alert('已返回提车应收款列表');
}, []);
var requirementContent = '「车辆管理系统」中的「租赁费用管理」模块下「提车应收款」中「收费明细」模块,第二步由财务填写;\n\n#提车应收款-收款明细\n\n整个页面从上至下为项目信息、车辆首付款、氢费预付款、开票信息4个卡片模块组成\n\n1.项目信息:\n1.1.上方为表单,显示合同编码、合同类型、项目名称、客户名称、付款方式、付款周期、业务部门、业务负责人;\n1.1.1.合同编码:显示租赁合同编号;\n1.1.2.合同类型:显示租赁合同类型,类型有正式合同/试用合同;\n1.1.3.项目名称:显示租赁合同项目名称;\n1.1.4.客户名称:显示租赁合同客户名称;\n1.1.5.付款方式:显示租赁合同付款方式,类型有预付/后付;\n1.1.6.付款周期显示付款周期类型有1个月-12个月\n1.1.7.业务部门:显示租赁合同对应业务部门;\n1.1.8.业务负责人:显示租赁合同对应业务负责人;\n\n2.提车应收款:\n2.1.上方为提车应收款应收总额;\n2.1.1.提车应收款总额显示总金额格式为xx.xx元计算方式为所有应付车辆租金+所有应付保证金+所有应付服务费-所有减免金额;\n2.2.车辆账单:品牌/型号/车牌号/应收车辆租金/车辆租金备注/应收保证金/服务费项目/应收服务费/减免金额/减免金额备注\n2.2.1.品牌:显示租赁合同中对应品牌;\n2.2.2.型号:显示租赁合同中对应型号;\n2.2.3.车牌号:显示租赁合同中对应车牌号,如无则显示为-\n2.2.4.应收车辆租金:显示业务提交的应收车辆租金;\n2.2.5.车辆租金备注:显示业务提交的车辆租金备注;\n2.2.6.应收保证金:显示业务提交的应收车辆保证金;\n2.2.7.服务费项目:点击查看,弹出气泡卡片,卡片中为列表,列表显示租赁合同所有已填写服务项目,列表字段为:服务项目、应收费用、服务费用备注;\n 2.2.8.1.服务项目:显示所有租赁合同中已添加的服务项目名称;\n 2.2.8.2.应收费用:显示所有业务提交的费用金额;\n 2.2.8.3.服务费用备注:显示所有业务提交的备注信息;\n2.1.8.应收服务费:根据服务费项目所有服务项目应付费用计算总和得出,不可修改;\n2.1.9.减免金额显示业务提交的减免金额格式为xx.xx元\n2.1.10.减免金额备注:显示业务提交的减免金额备注信息;\n\n3.氢费预付款:\n3.1.上方为氢费预付款应收总额/氢费预付款应收金额/减免金额/减免金额备注;\n3.1.1.氢费应收总额显示总金额格式为xx.xx元计算方式为氢费预付款实付总额-减免金额;\n3.1.2.氢费预付款应收金额显示业务填写的氢费预付款应收金额格式为xx.xx元\n3.1.2.减免金额显示业务填写的减免金额格式为xx.xx元\n3.1.3.减免金额备注:显示业务填写的减免金额备注;\n\n\n4.开票信息:\n4.1.开票金额显示总金额格式为xx.xx元计算方式为提车应收款总额+氢费应收总额;\n4.2.之后为表单,显示客户名称、纳税人识别号、地址、电话、账户、开户行、邮寄地址、开票时间、发票附件、备注:\n4.2.1.客户名称:显示租赁合同客户名称;\n4.2.2.纳税人识别号:显示租赁合同对应客户纳税人识别号;\n4.2.3.地址:显示租赁合同对应客户地址;\n4.2.4.电话:显示租赁合同对应客户电话;\n4.2.5.账户:显示租赁合同对应客户账户;\n4.2.6.开户行:显示租赁合同对应客户开户行;\n4.2.7.邮寄地址:显示租赁合同对应客户邮寄地址;\n4.2.8.开票金额显示总金额格式为xx.xx元计算方式为提车应收款总额+氢费应收总额;\n4.2.9.开票时间:选填项,日期选择器,精确至天;;\n4.2.10.发票附件:选填项,附件上传按钮,点击后上传发票附件,支持多附件(满足可能会有多张发票组合的情况);\n4.2.11.备注:选填项,文本域,用于记录财务相关备注;\n\n5.页面底部为提交、取消;\n5.1.提交:点击提交,提示:提交成功,跳转至:提车应收款列表页;\n5.2.取消:点击取消,进行二次确认气泡提示,提示为:取消将会丢失所有已添加数据,是否确认取消,点击是则返回提车应收款列表页;点击否则关闭二次确认继续操作;';
var styles = useMemo(function() {
return {
page: { padding: '16px 24px', background: '#f5f5f5', minHeight: '100vh', fontFamily: '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif' },
breadcrumb: { marginBottom: 16, fontSize: 14, color: '#666' },
card: { background: '#fff', borderRadius: 8, padding: 24, marginBottom: 16, boxShadow: '0 1px 2px rgba(0,0,0,0.03)' },
cardTitle: { fontSize: 16, fontWeight: 600, marginBottom: 16, paddingBottom: 12, borderBottom: '1px solid #f0f0f0' },
detailRow: { display: 'grid', gridTemplateColumns: 'repeat(3, 1fr)', gap: '24px', marginBottom: 12, fontSize: 14 },
formCol: { display: 'flex', flexDirection: 'column', gap: 4 },
formLabel: { color: '#666', fontSize: 14 },
formValue: { color: '#333', fontSize: 14 },
table: { width: '100%', borderCollapse: 'collapse', fontSize: 14 },
th: { textAlign: 'left', padding: '12px 16px', backgroundColor: '#fafafa', borderBottom: '1px solid #f0f0f0', fontWeight: 600, color: '#333', whiteSpace: 'nowrap' },
td: { padding: '12px 16px', borderBottom: '1px solid #f0f0f0', color: '#333' },
linkBtn: { color: '#1890ff', cursor: 'pointer', background: 'none', border: 'none', padding: 0, fontSize: 14 },
totalLine: { marginBottom: 16, fontSize: 14 },
totalAmount: { color: '#1890ff', fontWeight: 600, fontSize: 16 },
footer: { marginTop: 24, display: 'flex', justifyContent: 'center', gap: 12 },
primaryBtn: { padding: '8px 24px', backgroundColor: '#1890ff', color: '#fff', border: 'none', borderRadius: 4, cursor: 'pointer', fontSize: 14 },
defaultBtn: { padding: '8px 24px', backgroundColor: '#fff', color: '#666', border: '1px solid #d9d9d9', borderRadius: 4, cursor: 'pointer', fontSize: 14 },
formInput: { padding: '8px 12px', border: '1px solid #d9d9d9', borderRadius: 4, fontSize: 14, width: '100%', maxWidth: 200 },
modalOverlay: { position: 'fixed', top: 0, left: 0, right: 0, bottom: 0, backgroundColor: 'rgba(0,0,0,0.45)', display: 'flex', alignItems: 'center', justifyContent: 'center', zIndex: 1000 },
modalCard: { backgroundColor: '#fff', borderRadius: 8, padding: 24, maxWidth: '90%', maxHeight: '80vh', overflow: 'auto' },
modalHeader: { display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 16 },
modalTitle: { fontSize: 16, fontWeight: 600 },
modalClose: { padding: '4px 12px', backgroundColor: '#f5f5f5', border: 'none', borderRadius: 4, cursor: 'pointer' },
modalBody: { maxHeight: '60vh', overflowY: 'auto', whiteSpace: 'pre-wrap', fontSize: 14, lineHeight: 1.6, color: '#333' },
pageHeader: { display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 16, flexWrap: 'wrap', gap: 8 },
requirementLink: { color: '#1890ff', cursor: 'pointer', fontSize: 14, background: 'none', border: 'none', padding: 0 }
};
}, []);
var projectCard = React.createElement('div', { style: styles.card },
React.createElement('div', { style: styles.cardTitle }, '项目信息'),
React.createElement('div', { style: styles.detailRow },
React.createElement('div', { style: styles.formCol }, React.createElement('div', { style: styles.formLabel }, '合同编码'), React.createElement('div', { style: styles.formValue }, mockProject.contractCode)),
React.createElement('div', { style: styles.formCol }, React.createElement('div', { style: styles.formLabel }, '合同类型'), React.createElement('div', { style: styles.formValue }, mockProject.contractType)),
React.createElement('div', { style: styles.formCol }, React.createElement('div', { style: styles.formLabel }, '项目名称'), React.createElement('div', { style: styles.formValue }, mockProject.projectName))
),
React.createElement('div', { style: styles.detailRow },
React.createElement('div', { style: styles.formCol }, React.createElement('div', { style: styles.formLabel }, '客户名称'), React.createElement('div', { style: styles.formValue }, mockProject.customerName)),
React.createElement('div', { style: styles.formCol }, React.createElement('div', { style: styles.formLabel }, '付款方式'), React.createElement('div', { style: styles.formValue }, mockProject.paymentMethod)),
React.createElement('div', { style: styles.formCol }, React.createElement('div', { style: styles.formLabel }, '付款周期'), React.createElement('div', { style: styles.formValue }, mockProject.paymentCycle))
),
React.createElement('div', { style: styles.detailRow },
React.createElement('div', { style: styles.formCol }, React.createElement('div', { style: styles.formLabel }, '业务部门'), React.createElement('div', { style: styles.formValue }, mockProject.department)),
React.createElement('div', { style: styles.formCol }, React.createElement('div', { style: styles.formLabel }, '业务负责人'), React.createElement('div', { style: styles.formValue }, mockProject.responsible)),
React.createElement('div', { style: styles.formCol }, null)
)
);
var vehicleTableHeader = React.createElement('thead', null,
React.createElement('tr', null,
React.createElement('th', { style: styles.th }, '品牌'),
React.createElement('th', { style: styles.th }, '型号'),
React.createElement('th', { style: styles.th }, '车牌号'),
React.createElement('th', { style: styles.th }, '应收车辆租金'),
React.createElement('th', { style: styles.th }, '车辆租金备注'),
React.createElement('th', { style: styles.th }, '应收保证金'),
React.createElement('th', { style: styles.th }, '服务费项目'),
React.createElement('th', { style: styles.th }, '应收服务费'),
React.createElement('th', { style: styles.th }, '减免金额'),
React.createElement('th', { style: styles.th }, '减免金额备注')
)
);
var vehicleTableBody = React.createElement('tbody', null,
mockVehicleList.map(function(row, rowIndex) {
return React.createElement('tr', { key: rowIndex },
React.createElement('td', { style: styles.td }, row.brand),
React.createElement('td', { style: styles.td }, row.model),
React.createElement('td', { style: styles.td }, row.plateNo || '-'),
React.createElement('td', { style: styles.td }, row.payableRent),
React.createElement('td', { style: styles.td }, row.rentRemark || '-'),
React.createElement('td', { style: styles.td }, row.deposit),
React.createElement('td', { style: styles.td },
React.createElement('button', { type: 'button', style: styles.linkBtn, onClick: function() { setServiceModalRow(rowIndex); } }, '查看')
),
React.createElement('td', { style: styles.td }, row.serviceTotal || '0.00'),
React.createElement('td', { style: styles.td }, (function() { var v = parseFloat(row.discount); return (isNaN(v) ? '0.00' : v.toFixed(2)) + ' 元'; })()),
React.createElement('td', { style: styles.td }, row.discountRemark || '-')
);
})
);
var vehicleBillCard = React.createElement('div', { style: styles.card },
React.createElement('div', { style: styles.cardTitle }, '提车应收款'),
React.createElement('div', { style: styles.totalLine },
React.createElement('span', { style: { marginRight: 8 } }, '提车应收款总额:'),
React.createElement('span', { style: styles.totalAmount }, totalPayable + ' 元')
),
React.createElement('table', { style: styles.table }, vehicleTableHeader, vehicleTableBody)
);
var hydrogenCard = React.createElement('div', { style: styles.card },
React.createElement('div', { style: styles.cardTitle }, '氢费预付款'),
React.createElement('div', { style: styles.totalLine },
React.createElement('span', { style: { marginRight: 8 } }, '氢费应收总额:'),
React.createElement('span', { style: styles.totalAmount }, hydrogenPayableTotal + ' 元')
),
React.createElement('div', { style: styles.detailRow },
React.createElement('div', { style: styles.formCol }, React.createElement('div', { style: styles.formLabel }, '氢费预付款应收金额'), React.createElement('div', { style: styles.formValue }, mockHydrogen.paidTotal + ' 元')),
React.createElement('div', { style: styles.formCol }, React.createElement('div', { style: styles.formLabel }, '减免金额'), React.createElement('div', { style: styles.formValue }, mockHydrogen.discount + ' 元')),
React.createElement('div', { style: styles.formCol }, React.createElement('div', { style: styles.formLabel }, '减免金额备注'), React.createElement('div', { style: styles.formValue }, mockHydrogen.discountRemark || '-'))
)
);
var dayjs = window.dayjs || null;
var invoiceTimeValue = null;
if (invoiceForm.invoiceTime && dayjs) {
var d = dayjs(invoiceForm.invoiceTime, 'YYYY-MM-DD');
invoiceTimeValue = d && d.isValid && d.isValid() ? d : null;
}
var datePickerEl = DatePicker ? React.createElement(DatePicker, {
style: { width: '100%' },
format: 'YYYY-MM-DD',
placeholder: '请选择开票日期',
value: invoiceTimeValue,
onChange: function(d, dateStr) { setInvoiceForm(function(prev) { return Object.assign({}, prev, { invoiceTime: dateStr || '' }); }); }
}) : React.createElement('input', { type: 'date', style: styles.formInput, value: invoiceForm.invoiceTime, onChange: function(e) { setInvoiceForm(function(prev) { return Object.assign({}, prev, { invoiceTime: e.target.value }); }); } });
var uploadButton = Button ? React.createElement(Button, null, '上传附件') : React.createElement('button', { type: 'button', style: styles.defaultBtn }, '上传附件');
var uploadEl = Upload ? React.createElement(Upload, {
accept: '.pdf',
multiple: true,
fileList: invoiceForm.invoiceFiles || [],
onChange: function(info) { setInvoiceForm(function(prev) { return Object.assign({}, prev, { invoiceFiles: info.fileList }); }); },
beforeUpload: function() { return false; },
showUploadList: true
}, uploadButton) : React.createElement('div', { style: { fontSize: 14, color: '#999' } }, '(需加载 antd Upload');
var remarkEl = Input && Input.TextArea ? React.createElement(Input.TextArea, {
placeholder: '选填,用于记录财务相关备注',
value: invoiceForm.remark || '',
onChange: function(e) { setInvoiceForm(function(prev) { return Object.assign({}, prev, { remark: e.target.value }); }); },
rows: 3,
style: { width: '100%' }
}) : React.createElement('textarea', { style: Object.assign({}, styles.formInput, { minHeight: 60, resize: 'vertical' }), value: invoiceForm.remark || '', onChange: function(e) { setInvoiceForm(function(prev) { return Object.assign({}, prev, { remark: e.target.value }); }); }, placeholder: '选填,用于记录财务相关备注' });
var invoiceCard = React.createElement('div', { style: styles.card },
React.createElement('div', { style: styles.cardTitle }, '开票信息'),
React.createElement('div', { style: styles.totalLine },
React.createElement('span', { style: { marginRight: 8 } }, '开票金额:'),
React.createElement('span', { style: styles.totalAmount }, invoiceAmount + ' 元')
),
React.createElement('div', { style: styles.detailRow },
React.createElement('div', { style: styles.formCol }, React.createElement('div', { style: styles.formLabel }, '客户名称'), React.createElement('div', { style: styles.formValue }, mockInvoice.customerName)),
React.createElement('div', { style: styles.formCol }, React.createElement('div', { style: styles.formLabel }, '纳税人识别号'), React.createElement('div', { style: styles.formValue }, mockInvoice.taxId)),
React.createElement('div', { style: styles.formCol }, React.createElement('div', { style: styles.formLabel }, '地址'), React.createElement('div', { style: styles.formValue }, mockInvoice.address))
),
React.createElement('div', { style: styles.detailRow },
React.createElement('div', { style: styles.formCol }, React.createElement('div', { style: styles.formLabel }, '电话'), React.createElement('div', { style: styles.formValue }, mockInvoice.phone)),
React.createElement('div', { style: styles.formCol }, React.createElement('div', { style: styles.formLabel }, '账户'), React.createElement('div', { style: styles.formValue }, mockInvoice.account)),
React.createElement('div', { style: styles.formCol }, React.createElement('div', { style: styles.formLabel }, '开户行'), React.createElement('div', { style: styles.formValue }, mockInvoice.bank))
),
React.createElement('div', { style: styles.detailRow },
React.createElement('div', { style: styles.formCol }, React.createElement('div', { style: styles.formLabel }, '邮寄地址'), React.createElement('div', { style: styles.formValue }, mockInvoice.mailingAddress)),
React.createElement('div', { style: styles.formCol }, null),
React.createElement('div', { style: styles.formCol }, null)
),
React.createElement('div', { style: styles.detailRow },
React.createElement('div', { style: styles.formCol }, React.createElement('div', { style: styles.formLabel }, '开票时间'), React.createElement('div', { style: { width: '100%' } }, datePickerEl)),
React.createElement('div', { style: styles.formCol }, React.createElement('div', { style: styles.formLabel }, '发票附件'), React.createElement('div', { style: { width: '100%' } }, uploadEl)),
React.createElement('div', { style: styles.formCol }, React.createElement('div', { style: styles.formLabel }, '备注'), React.createElement('div', { style: { width: '100%' } }, remarkEl))
)
);
var serviceModal = null;
if (serviceModalRow !== null && mockVehicleList[serviceModalRow]) {
var r = mockVehicleList[serviceModalRow];
var serviceList = r.serviceItems || [];
serviceModal = React.createElement('div', { style: styles.modalOverlay, onClick: function() { setServiceModalRow(null); } },
React.createElement('div', { style: styles.modalCard, onClick: function(e) { e.stopPropagation(); } },
React.createElement('div', { style: styles.modalHeader },
React.createElement('span', { style: styles.modalTitle }, '服务费项目'),
React.createElement('button', { type: 'button', style: styles.modalClose, onClick: function() { setServiceModalRow(null); } }, '关闭')
),
React.createElement('table', { style: styles.table },
React.createElement('thead', null, React.createElement('tr', null, React.createElement('th', { style: styles.th }, '服务项目'), React.createElement('th', { style: styles.th }, '应收费用'), React.createElement('th', { style: styles.th }, '服务费用备注'))),
React.createElement('tbody', null, serviceList.map(function(item, i) { return React.createElement('tr', { key: i }, React.createElement('td', { style: styles.td }, item.name), React.createElement('td', { style: styles.td }, item.fee), React.createElement('td', { style: styles.td }, item.remark || '-')); }))
)
)
);
}
var footer = React.createElement('div', { style: styles.footer },
React.createElement('button', { type: 'button', style: styles.primaryBtn, onClick: handleSubmit }, '提交'),
React.createElement('button', { type: 'button', style: styles.defaultBtn, onClick: handleCancelClick }, '取消')
);
var requirementModal = requirementVisible ? React.createElement('div', { style: styles.modalOverlay, onClick: function() { setRequirementVisible(false); } },
React.createElement('div', { style: styles.modalCard, onClick: function(e) { e.stopPropagation(); } },
React.createElement('div', { style: styles.modalHeader }, React.createElement('span', { style: styles.modalTitle }, '需求说明'), React.createElement('button', { type: 'button', style: styles.modalClose, onClick: function() { setRequirementVisible(false); } }, '关闭')),
React.createElement('div', { style: styles.modalBody }, requirementContent)
)
) : null;
var cancelConfirmModal = cancelConfirmVisible ? React.createElement('div', { style: styles.modalOverlay, onClick: function() { setCancelConfirmVisible(false); } },
React.createElement('div', { style: styles.modalCard, onClick: function(e) { e.stopPropagation(); } },
React.createElement('div', { style: styles.modalHeader }, React.createElement('span', { style: styles.modalTitle }, '提示'), null),
React.createElement('div', { style: { marginBottom: 20, fontSize: 14, color: '#333' } }, '取消将会丢失所有已添加数据,是否确认取消?'),
React.createElement('div', { style: { display: 'flex', justifyContent: 'flex-end', gap: 12 } },
React.createElement('button', { type: 'button', style: styles.defaultBtn, onClick: function() { handleCancelConfirm(false); } }, '否'),
React.createElement('button', { type: 'button', style: styles.primaryBtn, onClick: function() { handleCancelConfirm(true); } }, '是')
)
)
) : null;
return React.createElement('div', { style: styles.page },
React.createElement('div', { style: styles.pageHeader },
React.createElement('div', { style: styles.breadcrumb }, '租赁费用管理 > 提车应收款 > 收费明细 > 财务提交'),
React.createElement('button', { type: 'button', style: styles.requirementLink, onClick: function() { setRequirementVisible(true); } }, '查看需求说明')
),
projectCard,
vehicleBillCard,
hydrogenCard,
invoiceCard,
footer,
serviceModal,
requirementModal,
cancelConfirmModal
);
};

File diff suppressed because one or more lines are too long