// 【重要】必须使用 const Component 作为组件变量名 // 提车应收款(财务管理 - 运维管理-财务管理-提车应收款,antd 规范布局) const Component = function() { var useState = React.useState; var useCallback = React.useCallback; var useMemo = React.useMemo; var antd = window.antd; var Breadcrumb = antd.Breadcrumb; var Select = antd.Select; var Button = antd.Button; var Table = antd.Table; var Card = antd.Card; var DatePicker = antd.DatePicker; var Modal = antd.Modal; var Space = antd.Space; var message = antd.message; var App = antd.App; var RangePicker = DatePicker.RangePicker; var dayjs = window.dayjs || null; // 筛选条件(表单输入) var _contractCode = useState(undefined); var _projectName = useState(undefined); var _customerName = useState(undefined); var _auditStatus = useState(undefined); var _chargeOperator = useState(undefined); var _chargeTimeRange = useState(null); var _invoiceTimeRange = useState(null); var _invoiceOperator = useState(undefined); // 已生效筛选(点击查询后) var _appliedFilter = useState({ contractCode: undefined, projectName: undefined, customerName: undefined, auditStatus: undefined, chargeOperator: undefined, chargeTimeRange: null, invoiceTimeRange: null, invoiceOperator: undefined }); // 列表多选(默认全选由 Table rowSelection 控制) var _selectedRowKeys = useState([]); // 撤回二次确认 var _withdrawModalVisible = useState(false); var _withdrawRecord = useState(null); // 筛选展开(默认只显示第一行,点击更多展开、收起关闭) var _filterExpanded = useState(false); // 查看需求说明弹窗 var _requirementModalVisible = useState(false); // 需求说明文案 var requirementContent = '「车辆管理系统」中的「财务管理」模块下「提车应收款」模块\n1.面包屑:\n1.1.运维管理-财务管理-提车应收款\n页面由筛选卡片、列表卡片组成;\n\n2.筛选:\n2.1.合同编码:用来通过提车应收款筛选车辆租赁合同编码;选择器,支持从输入框输入内容模糊搜索,选择器支持点击删除,下拉显示匹配项;\n2.2.项目名称:用来通过提车应收款筛选车辆租赁合同对应项目名称;选择器,支持从输入框输入内容模糊搜索,选择器支持点击删除,下拉显示匹配项;\n2.3.客户名称:用来通过提车应收款筛选车辆租赁合同对应客户名称,选择器,支持从输入框输入内容模糊搜索,选择器支持点击删除,下拉显示匹配项;\n2.4.审核状态:用来通过审核状态筛选对应提车应收款数据,选择器,选项为:全部、待提交、审批中、审批完成、审批驳回、撤回;\n2.5.收费情况操作人:用来通过收费情况操作人筛选对应提车应收款数据,选择器,支持从输入框输入内容模糊搜索,选择器支持点击删除,下拉显示匹配项,选项为:全部、所有操作人;\n2.6.收费情况提交时间:日期选择器,支持单输入框双日历选择开始-结束时间,提示信息为:请选择开始时间、请选择结束时间;\n2.7.开票时间:日期选择器,支持单输入框双日历选择开始-结束时间,提示信息为:请选择开始时间、请选择结束时间;\n2.8.开票操作人:用来通过收费情况操作人筛选对应提车应收款数据,选择器,支持从输入框输入内容模糊搜索,选择器支持点击删除,下拉显示匹配项,选项为:全部、所有操作人;\n2.9.右侧为查询和重置按钮,筛选条件以且的模式进行筛选,点击重置清空条件,点击查询与列表进行联动;\n\n3.列表:\n合同到达生效日期立刻生成提车应收款数据,以列表进行显示,列表第一列为多选框,默认全选,可手动取消选择某行数据,配合导出按钮进行对应数据导出;\n列表字段依次为:合同编码、项目名称、客户名称、业务部门、业务负责人、合同生效日期、应收总金额、减免总金额、审核状态、收费情况操作人、收费情况提交时间、开票时间、开票操作人、操作;\n右上角为导出按钮,支持筛选后多选行数据进行导出;\n3.1.合同编码:显示该笔提车应收款对应车辆租赁合同-合同编码;\n3.2.项目名称:显示该笔提车应收款对应车辆租赁合同-项目名称;\n3.3.客户名称:显示该笔提车应收款对应车辆租赁合同-客户名称;\n3.4.业务部门:显示该笔提车应收款对应车辆租赁合同-业务部门;\n3.5.业务负责人:显示该笔提车应收款对应车辆租赁合同-业务负责人;\n3.6.合同生效日期:显示该笔提车应收款对应车辆租赁合同-合同生效日期;\n3.7.应收总金额:显示该笔提车提车应收款总金额,格式为:xx.xx元。从收费明细中计算(业务提交审核前会根据业务实际填写金额重新计算),计算方式为:提车应收款总额+氢费预付款总额;\n3.8.减免总金额:显示收费明细中所有减免总金额总额,无则显示为0.00元;\n3.9.审核状态:分为待提交、审批中、审批完成、审批驳回、撤回;\n 3.9.1.待提交:生成提车应收款后收费明细未修改或仅保存,且未提交审批;操作可:查看、收费明细;\n 3.9.2.审批中:生成提车应收款后收费明细已提交审批,但未完成最终节点审批;操作可:查看、撤回;\n 3.9.3.审批完成:提车应收款已完成最终节点审批,最终节点审批后不可撤回;操作可:查看、开票信息;\n 3.9.4.审批驳回:提车应收款在任意审批节点被驳回,被驳回后显示为审批驳回,可重新编辑后再次提交审批;操作可:查看、收费明细;\n 3.9.5.撤回:提车应收款在状态为审批中时可自行撤回,撤回后显示为撤回,可重新编辑后再次提交审批;操作可:查看、收费明细;\n3.10.收费情况操作人:提车应收款中点击收费明细,并点击提交审核的操作人,如撤回或驳回后由其他操作人提交审核,则显示最后一次操作的操作人;\n3.14.收费情况提交时间:提车应收款收费明细最后一次提交时间,格式为:YYYY-MM-DD HH:MM;\n3.15.开票时间:提车应收款完成审批后,在开票信息中填报的开票时间,格式为:YYYY-MM-DD,如未开票则显示:待开票;\n3.16.开票操作人:提车应收款开票信息开票时间、发票附件提交时,记录提交人,如未开票则显示为-;\n3.17.操作:查看、收费明细、撤回、开票信息;\n 3.17.1.查看:点击跳转查看提车应收款页;\n 3.17.2.收费明细:点击跳转收费明细页;\n 3.17.3.撤回:点击弹出气泡卡片进行二次确认,提示内容:是否确认撤回该流程。点击确认后提示撤回成功/失败(撤回过程中已完成最终节点审批则提示撤回失败);\n 3.17.4.开票信息:点击跳转开票信息页;\n3.18.分页:列表右下角为分页功能,支持选择单页显示数据条目数;'; // 选项 var contractCodeOptions = [ { value: 'HT-ZL-2025-001', label: 'HT-ZL-2025-001' }, { value: 'HT-ZL-2025-002', label: 'HT-ZL-2025-002' }, { value: 'HT-ZL-2025-003', label: 'HT-ZL-2025-003' }, { value: 'HT-ZL-2024-088', label: 'HT-ZL-2024-088' } ]; var projectNameOptions = [ { value: '北京朝阳区租赁项目', label: '北京朝阳区租赁项目' }, { value: '上海浦东车辆租赁', label: '上海浦东车辆租赁' }, { value: '广州天河运营项目', label: '广州天河运营项目' } ]; var customerNameOptions = [ { value: '某某科技有限公司', label: '某某科技有限公司' }, { value: '某某物流有限公司', label: '某某物流有限公司' }, { value: '某某制造有限公司', label: '某某制造有限公司' } ]; var auditStatusOptions = [ { value: '全部', label: '全部' }, { value: '待提交', label: '待提交' }, { value: '审批中', label: '审批中' }, { value: '审批完成', label: '审批完成' }, { value: '审批驳回', label: '审批驳回' }, { value: '撤回', label: '撤回' } ]; var operatorOptions = [ { value: '全部', label: '全部' }, { value: '张三', label: '张三' }, { value: '李四', label: '李四' }, { value: '王五', label: '王五' } ]; var auditStatusMap = { draft: '待提交', auditing: '审批中', completed: '审批完成', rejected: '审批驳回', withdrawn: '撤回' }; var rawList = useMemo(function() { var list = []; var contracts = ['HT-ZL-2025-001', 'HT-ZL-2025-002', 'HT-ZL-2025-003', 'HT-ZL-2024-088']; var projects = ['北京朝阳区租赁项目', '上海浦东车辆租赁', '广州天河运营项目']; var customers = ['某某科技有限公司', '某某物流有限公司', '某某制造有限公司']; var depts = ['运营部', '业务1部', '业务2部']; var owners = ['张三', '李四', '王五']; var statuses = ['draft', 'auditing', 'completed', 'rejected', 'withdrawn']; for (var i = 1; i <= 25; i++) { var audit = statuses[i % 5]; list.push({ id: 'AR' + i, contractCode: contracts[i % contracts.length], projectName: projects[i % projects.length], customerName: customers[i % customers.length], department: depts[i % 3], responsible: owners[i % 3], effectiveDate: '2025-' + (String((i % 12) + 1)).padStart(2, '0') + '-' + (String((i % 28) + 1)).padStart(2, '0'), receivableTotal: (12000 + i * 500).toFixed(2), discountTotal: (i % 4 === 0 ? 200 : 0).toFixed(2), auditStatus: audit, chargeOperator: audit === 'draft' || audit === 'withdrawn' ? '-' : '张三', chargeSubmitTime: audit === 'draft' || audit === 'withdrawn' ? '-' : '2025-02-20 14:30', invoiceTime: audit === 'completed' ? '2025-02-25' : '待开票', invoiceOperator: audit === 'completed' ? '李四' : '-' }); } return list; }, []); var appliedFilter = _appliedFilter[0]; var filteredList = useMemo(function() { var list = rawList.slice(); var f = appliedFilter; if (f.contractCode) list = list.filter(function(r) { return r.contractCode === f.contractCode; }); if (f.projectName) list = list.filter(function(r) { return r.projectName === f.projectName; }); if (f.customerName) list = list.filter(function(r) { return r.customerName === f.customerName; }); if (f.auditStatus && f.auditStatus !== '全部') { var statusKey = null; for (var k in auditStatusMap) { if (auditStatusMap[k] === f.auditStatus) { statusKey = k; break; } } if (statusKey) list = list.filter(function(r) { return r.auditStatus === statusKey; }); } if (f.chargeOperator && f.chargeOperator !== '全部') { list = list.filter(function(r) { return r.chargeOperator === f.chargeOperator; }); } if (f.chargeTimeRange && f.chargeTimeRange.length === 2 && f.chargeTimeRange[0] && f.chargeTimeRange[1]) { var startStr = f.chargeTimeRange[0].format ? f.chargeTimeRange[0].format('YYYY-MM-DD') : ''; var endStr = f.chargeTimeRange[1].format ? f.chargeTimeRange[1].format('YYYY-MM-DD') : ''; if (startStr || endStr) { list = list.filter(function(r) { var t = (r.chargeSubmitTime || '').split(' ')[0]; if (!t || t === '-') return false; if (startStr && t < startStr) return false; if (endStr && t > endStr) return false; return true; }); } } if (f.invoiceTimeRange && f.invoiceTimeRange.length === 2 && f.invoiceTimeRange[0] && f.invoiceTimeRange[1]) { var isStart = f.invoiceTimeRange[0].format ? f.invoiceTimeRange[0].format('YYYY-MM-DD') : ''; var ieEnd = f.invoiceTimeRange[1].format ? f.invoiceTimeRange[1].format('YYYY-MM-DD') : ''; if (isStart || ieEnd) { list = list.filter(function(r) { var t = r.invoiceTime === '待开票' ? '' : r.invoiceTime; if (!t) return false; if (isStart && t < isStart) return false; if (ieEnd && t > ieEnd) return false; return true; }); } } if (f.invoiceOperator && f.invoiceOperator !== '全部') { list = list.filter(function(r) { return r.invoiceOperator === f.invoiceOperator; }); } return list; }, [rawList, appliedFilter]); var handleQuery = useCallback(function() { _appliedFilter[1]({ contractCode: _contractCode[0], projectName: _projectName[0], customerName: _customerName[0], auditStatus: _auditStatus[0], chargeOperator: _chargeOperator[0], chargeTimeRange: _chargeTimeRange[0], invoiceTimeRange: _invoiceTimeRange[0], invoiceOperator: _invoiceOperator[0] }); }, []); var handleReset = useCallback(function() { _contractCode[1](undefined); _projectName[1](undefined); _customerName[1](undefined); _auditStatus[1](undefined); _chargeOperator[1](undefined); _chargeTimeRange[1](null); _invoiceTimeRange[1](null); _invoiceOperator[1](undefined); _appliedFilter[1]({ contractCode: undefined, projectName: undefined, customerName: undefined, auditStatus: undefined, chargeOperator: undefined, chargeTimeRange: null, invoiceTimeRange: null, invoiceOperator: undefined }); _selectedRowKeys[1]([]); }, []); var handleExport = useCallback(function() { var keys = _selectedRowKeys[0].length > 0 ? _selectedRowKeys[0] : filteredList.map(function(r) { return r.id; }); message.info('导出已选数据,共 ' + keys.length + ' 条'); }, [_selectedRowKeys[0], filteredList]); var handleWithdraw = useCallback(function(record) { _withdrawRecord[1](record); _withdrawModalVisible[1](true); }, []); var handleWithdrawOk = useCallback(function() { message.success('撤回成功'); _withdrawModalVisible[1](false); _withdrawRecord[1](null); }, []); var filterLabelStyle = { marginBottom: 6, fontSize: 14, color: 'rgba(0,0,0,0.65)' }; var filterItemStyle = { marginBottom: 12 }; var filterControlStyle = { width: '100%' }; var layoutStyle = { padding: '16px 24px', background: '#f5f5f5', minHeight: '100vh' }; var filterItems = [ React.createElement('div', { key: 'contractCode', style: filterItemStyle }, React.createElement('div', { style: filterLabelStyle }, '合同编码'), React.createElement(Select, { placeholder: '请选择或输入合同编码', style: filterControlStyle, value: _contractCode[0], onChange: function(v) { _contractCode[1](v); }, allowClear: true, showSearch: true, options: contractCodeOptions, filterOption: function(input, opt) { return (opt.label || '').toString().toLowerCase().indexOf((input || '').toLowerCase()) !== -1; } })), React.createElement('div', { key: 'projectName', style: filterItemStyle }, React.createElement('div', { style: filterLabelStyle }, '项目名称'), React.createElement(Select, { placeholder: '请选择或输入项目名称', style: filterControlStyle, value: _projectName[0], onChange: function(v) { _projectName[1](v); }, allowClear: true, showSearch: true, options: projectNameOptions, filterOption: function(input, opt) { return (opt.label || '').toString().toLowerCase().indexOf((input || '').toLowerCase()) !== -1; } })), React.createElement('div', { key: 'customerName', style: filterItemStyle }, React.createElement('div', { style: filterLabelStyle }, '客户名称'), React.createElement(Select, { placeholder: '请选择或输入客户名称', style: filterControlStyle, value: _customerName[0], onChange: function(v) { _customerName[1](v); }, allowClear: true, showSearch: true, options: customerNameOptions, filterOption: function(input, opt) { return (opt.label || '').toString().toLowerCase().indexOf((input || '').toLowerCase()) !== -1; } })), React.createElement('div', { key: 'auditStatus', style: filterItemStyle }, React.createElement('div', { style: filterLabelStyle }, '审核状态'), React.createElement(Select, { placeholder: '请选择', style: filterControlStyle, value: _auditStatus[0], onChange: function(v) { _auditStatus[1](v); }, allowClear: true, options: auditStatusOptions })), React.createElement('div', { key: 'chargeOperator', style: filterItemStyle }, React.createElement('div', { style: filterLabelStyle }, '收费情况操作人'), React.createElement(Select, { placeholder: '请选择或输入操作人', style: filterControlStyle, value: _chargeOperator[0], onChange: function(v) { _chargeOperator[1](v); }, allowClear: true, showSearch: true, options: operatorOptions, filterOption: function(input, opt) { return (opt.label || '').toString().toLowerCase().indexOf((input || '').toLowerCase()) !== -1; } })), React.createElement('div', { key: 'chargeTimeRange', style: filterItemStyle }, React.createElement('div', { style: filterLabelStyle }, '收费情况提交时间'), React.createElement(RangePicker, { style: filterControlStyle, placeholder: ['请选择开始时间', '请选择结束时间'], value: _chargeTimeRange[0], onChange: function(v) { _chargeTimeRange[1](v); } })), React.createElement('div', { key: 'invoiceTimeRange', style: filterItemStyle }, React.createElement('div', { style: filterLabelStyle }, '开票时间'), React.createElement(RangePicker, { style: filterControlStyle, placeholder: ['请选择开始时间', '请选择结束时间'], value: _invoiceTimeRange[0], onChange: function(v) { _invoiceTimeRange[1](v); } })), React.createElement('div', { key: 'invoiceOperator', style: filterItemStyle }, React.createElement('div', { style: filterLabelStyle }, '开票操作人'), React.createElement(Select, { placeholder: '请选择或输入操作人', style: filterControlStyle, value: _invoiceOperator[0], onChange: function(v) { _invoiceOperator[1](v); }, allowClear: true, showSearch: true, options: operatorOptions, filterOption: function(input, opt) { return (opt.label || '').toString().toLowerCase().indexOf((input || '').toLowerCase()) !== -1; } })) ]; var columns = [ { title: '合同编码', dataIndex: 'contractCode', key: 'contractCode', width: 130, fixed: 'left' }, { title: '项目名称', dataIndex: 'projectName', key: 'projectName', width: 160 }, { title: '客户名称', dataIndex: 'customerName', key: 'customerName', width: 140 }, { title: '业务部门', dataIndex: 'department', key: 'department', width: 100 }, { title: '业务负责人', dataIndex: 'responsible', key: 'responsible', width: 100 }, { title: '合同生效日期', dataIndex: 'effectiveDate', key: 'effectiveDate', width: 120 }, { title: '应收总金额', key: 'receivableTotal', width: 110, render: function(_, r) { return (r.receivableTotal || '0.00') + ' 元'; } }, { title: '减免总金额', key: 'discountTotal', width: 110, render: function(_, r) { return (r.discountTotal || '0.00') + ' 元'; } }, { title: '审核状态', key: 'auditStatus', width: 100, render: function(_, r) { return auditStatusMap[r.auditStatus] || '-'; } }, { title: '收费情况操作人', dataIndex: 'chargeOperator', key: 'chargeOperator', width: 120 }, { title: '收费情况提交时间', dataIndex: 'chargeSubmitTime', key: 'chargeSubmitTime', width: 160 }, { title: '开票时间', dataIndex: 'invoiceTime', key: 'invoiceTime', width: 110 }, { title: '开票操作人', dataIndex: 'invoiceOperator', key: 'invoiceOperator', width: 110 }, { title: '操作', key: 'action', width: 200, fixed: 'right', render: function(_, record) { var audit = record.auditStatus; var showCharge = audit === 'draft' || audit === 'rejected' || audit === 'withdrawn'; var showWithdraw = audit === 'auditing'; var showInvoice = audit === 'completed'; return React.createElement(Space, { size: 4, wrap: true }, React.createElement(Button, { type: 'link', size: 'small', onClick: function() { message.info('跳转查看提车应收款页'); } }, '查看'), showCharge ? React.createElement(Button, { type: 'link', size: 'small', onClick: function() { message.info('跳转收费明细页'); } }, '收费明细') : null, showWithdraw ? React.createElement(Button, { type: 'link', size: 'small', onClick: function() { handleWithdraw(record); } }, '撤回') : null, showInvoice ? React.createElement(Button, { type: 'link', size: 'small', onClick: function() { message.info('跳转开票信息页'); } }, '开票信息') : null ); } } ]; // 默认全选当前页:在 pagination 变化时把当前页 id 加入 selectedRowKeys(仅做初始化倾向,实际由 Table 受控) // 筛选结果变化后默认全选(查询/重置后与列表联动) React.useEffect(function() { _selectedRowKeys[1](filteredList.map(function(r) { return r.id; })); }, [filteredList]); var rowSelection = { selectedRowKeys: _selectedRowKeys[0], onChange: function(keys) { _selectedRowKeys[1](keys); }, getCheckboxProps: function(record) { return { name: record.id }; }, fixed: true }; // 筛选默认第一行(3 项),展开显示全部 8 项 var filterCount = _filterExpanded[0] ? 8 : 3; var filterNodes = []; for (var fi = 0; fi < filterCount && fi < filterItems.length; fi++) { filterNodes.push(filterItems[fi]); } // 多选选中时列表行不添加选中样式(选中行与未选中行背景一致) var tableRowClassStyle = '.receivable-list-table .ant-table-tbody .ant-table-row-selected > td { background: #fff !important; }'; return React.createElement(App, null, React.createElement('div', { style: layoutStyle }, React.createElement('div', { style: { display: 'flex', alignItems: 'center', justifyContent: 'space-between', marginBottom: 16 } }, React.createElement(Breadcrumb, { items: [ { title: '运维管理' }, { title: '财务管理' }, { title: '提车应收款' } ] }), React.createElement(Button, { type: 'link', style: { padding: 0 }, onClick: function() { _requirementModalVisible[1](true); } }, '查看需求说明') ), React.createElement(Card, { style: { marginBottom: 16 } }, React.createElement('div', { style: { display: 'grid', gridTemplateColumns: '1fr 1fr 1fr', gap: '16px 24px', alignItems: 'start' } }, filterNodes), React.createElement('div', { style: { display: 'flex', justifyContent: 'flex-end', gap: 8, marginTop: 16 } }, React.createElement(Button, { onClick: handleReset }, '重置'), React.createElement(Button, { type: 'primary', onClick: handleQuery }, '查询'), React.createElement(Button, { type: 'link', size: 'small', onClick: function() { _filterExpanded[1](!_filterExpanded[0]); } }, _filterExpanded[0] ? '收起' : '更多') ) ), React.createElement('div', { style: { marginBottom: 16, display: 'flex', justifyContent: 'flex-end' } }, React.createElement(Button, { onClick: handleExport }, '导出') ), React.createElement(Card, null, React.createElement(React.Fragment, null, React.createElement('style', null, tableRowClassStyle), React.createElement('div', { className: 'receivable-list-table' }, React.createElement(Table, { rowKey: 'id', rowSelection: rowSelection, columns: columns, dataSource: filteredList, scroll: { x: 1800 }, size: 'small', pagination: { showSizeChanger: true, showQuickJumper: true, showTotal: function(t) { return '共 ' + t + ' 条'; } } }) ) ) ), React.createElement(Modal, { title: '提示', open: _withdrawModalVisible[0], onCancel: function() { _withdrawModalVisible[1](false); _withdrawRecord[1](null); }, onOk: handleWithdrawOk, okText: '确认', cancelText: '取消' }, React.createElement('div', { style: { fontSize: 14, color: 'rgba(0,0,0,0.65)' } }, '是否确认撤回该流程?')), 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', whiteSpace: 'pre-wrap', fontSize: 14, lineHeight: 1.6, color: 'rgba(0,0,0,0.85)' } }, requirementContent)) ) ); };