diff --git a/web端/财务管理/提车收款-收费明细-业务提交.jsx b/web端/财务管理/提车收款-收费明细-业务提交.jsx new file mode 100644 index 0000000..a393423 --- /dev/null +++ b/web端/财务管理/提车收款-收费明细-业务提交.jsx @@ -0,0 +1,461 @@ +// 【重要】必须使用 const Component 作为组件变量名 +// 提车应收款 - 收费明细(租赁费用管理-提车应收款,第一步由业务填写) + +const Component = function() { + var useState = React.useState; + var useCallback = React.useCallback; + var useMemo = React.useMemo; + + // 模拟:项目信息(只读) + 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', monthlyRent: '8000.00', deposit: '2000.00', serviceItems: [{ name: '保养服务', fee: '300.00', remark: '' }, { name: '保险', fee: '200.00', remark: '' }] }, + { brand: '宝马', model: '530Li', plateNo: '京B67890', monthlyRent: '7000.00', deposit: '1500.00', serviceItems: [{ name: '保养服务', fee: '250.00', remark: '' }] } + ]; + }, []); + + // 模拟:氢费配置(租赁合同:客户承担+预付款时才有氢费预付款应收) + var mockHydrogen = useMemo(function() { + return { + bearer: '客户', // 客户承担 | 其他 + paymentMethod: '预付', // 预付 | 后付 + prepaymentAmount: '3580.00' // 氢气预付款金额 + }; + }, []); + + // 模拟:开票信息(只读) + var mockInvoice = useMemo(function() { + return { + customerName: '某某科技有限公司', + taxId: '91330400MA2XXXXX1', + address: '浙江省嘉兴市南湖区科技大道1号', + phone: '0571-88888888', + account: '6222021234567890123', + bank: '中国工商银行嘉兴分行', + mailingAddress: '浙江省嘉兴市南湖区科技大道1号' + }; + }, []); + + // 可编辑提车应收款行:应收车辆租金、车辆租金备注、应收保证金(只读)、服务费项(应收费用/备注可编辑)、减免金额、减免金额备注 + var vehicleRowsState = useState([]); + var vehicleRows = vehicleRowsState[0]; + var setVehicleRows = vehicleRowsState[1]; + // 服务费弹窗:当前打开的行索引,null 表示关闭 + var serviceModalRowState = useState(null); + var serviceModalRow = serviceModalRowState[0]; + var setServiceModalRow = serviceModalRowState[1]; + // 查看需求说明弹窗 + var requirementVisibleState = useState(false); + var requirementVisible = requirementVisibleState[0]; + var setRequirementVisible = requirementVisibleState[1]; + // 取消二次确认弹窗 + var cancelConfirmVisibleState = useState(false); + var cancelConfirmVisible = cancelConfirmVisibleState[0]; + var setCancelConfirmVisible = cancelConfirmVisibleState[1]; + + // 需求说明文案(#提车应收款-收款明细) + 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.应收车辆租金:必填项,默认显示1个月车辆租金,按照合同车辆月租金反写,可修改;\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.减免金额:选填项,默认为0,可修改,2位小数;\n2.1.10.减免金额备注:选填项,输入框,可自行备注减免情况;\n\n3.氢费预付款:\n3.1.上方为氢费预付款应收总额/氢费预付款应收金额/减免金额/减免金额备注;\n3.1.1.氢费应收总额:显示总金额,格式为xx.xx元,计算方式为:氢费预付款实付总额-减免金额;\n3.1.2.氢费预付款应收金额:必填项,输入框,支持两位小数,格式为xx.xx元,默认为与租赁合同氢气预付款金额相同;当租赁合同氢费设置为客户承担、预付款时才有,与氢气预付款金额相同,其他费用模式下,氢气预付款为0;\n3.1.2.减免金额:必填项,输入框,支持两位小数,格式为xx.xx元,默认为0.00元;\n3.1.3.减免金额备注:选填项,输入框,可自行输入;\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.取消:点击取消,进行二次确认气泡提示,提示为:取消将会丢失所有已添加数据,是否确认取消,点击是则返回提车应收款列表页;点击否则关闭二次确认继续操作;\n\n6.审批流程:\n6.1.标准情况(车辆租金、服务费金额≥租赁合同配置的单月租金*付款周期或氢费金额=租赁合同配置的氢费预付款金额):业务->财务主管(吕红/宋欣怡);\n6.2.非标情况(车辆租金、服务费金额<租赁合同配置的单月租金*付款周期或氢费金额<租赁合同配置的氢费预付款金额);业务->财务主管(吕红/宋欣怡)->更上级领导(待定,可能是董事长),流程请待确认完成之后,再进行设置;'; + + // 氢费预付款表单:应收金额(必填,默认=合同氢气预付款金额)、减免金额、减免金额备注;应收总额=应收金额-减免金额(只读) + var hydrogenFormState = useState(function() { + var isCustomerPrepay = (mockHydrogen.bearer === '客户' && mockHydrogen.paymentMethod === '预付'); + var paid = isCustomerPrepay ? (mockHydrogen.prepaymentAmount || '0.00') : '0.00'; + return { paidTotal: paid, discount: '0.00', discountRemark: '' }; + }); + var hydrogenForm = hydrogenFormState[0]; + var setHydrogenForm = hydrogenFormState[1]; + // 氢费应收总额 = 应收金额 - 减免金额(只读显示) + var hydrogenPayableTotal = useMemo(function() { + var paid = parseFloat(hydrogenForm.paidTotal) || 0; + var discount = parseFloat(hydrogenForm.discount) || 0; + var v = paid - discount; + return (v >= 0 ? v : 0).toFixed(2); + }, [hydrogenForm.paidTotal, hydrogenForm.discount]); + + function formatTwoDecimals(val) { + var n = parseFloat(String(val).replace(/[^\d.-]/g, '')); + if (isNaN(n)) return '0.00'; + return n.toFixed(2); + } + + React.useEffect(function() { + var rows = mockVehicleList.map(function(v) { + var serviceItems = (v.serviceItems || []).map(function(s) { + return { name: s.name, fee: s.fee || '', remark: s.remark || '' }; + }); + return { + brand: v.brand, + model: v.model, + plateNo: v.plateNo || '-', + payableRent: v.monthlyRent || '', + rentRemark: '', + deposit: v.deposit || '', + depositRemark: '', + serviceItems: serviceItems, + discount: '0', + discountRemark: '' + }; + }); + setVehicleRows(rows); + }, [mockVehicleList]); + + // 单行应收服务费 = 该行服务费项应收费用之和 + function getRowServiceTotal(row) { + var total = 0; + var list = row.serviceItems || []; + for (var i = 0; i < list.length; i++) { + var n = parseFloat(list[i].fee); + if (!isNaN(n)) total += n; + } + return total.toFixed(2); + } + // 提车应收款总额 = 所有应收车辆租金 + 所有应收保证金 + 所有应收服务费 - 所有减免金额 + var totalPayable = useMemo(function() { + var rentSum = 0, depositSum = 0, serviceSum = 0, discountSum = 0; + for (var i = 0; i < vehicleRows.length; i++) { + var r = vehicleRows[i]; + rentSum += parseFloat(r.payableRent) || 0; + depositSum += parseFloat(r.deposit) || 0; + serviceSum += parseFloat(getRowServiceTotal(r)) || 0; + discountSum += parseFloat(r.discount) || 0; + } + return (rentSum + depositSum + serviceSum - discountSum).toFixed(2); + }, [vehicleRows]); + + var handleVehicleChange = useCallback(function(rowIndex, field, value) { + setVehicleRows(function(prev) { + var next = prev.slice(); + var row = next[rowIndex] ? Object.assign({}, next[rowIndex]) : next[rowIndex]; + row[field] = value; + next[rowIndex] = row; + return next; + }); + }, []); + var handleServiceItemChange = useCallback(function(rowIndex, itemIndex, field, value) { + setVehicleRows(function(prev) { + var next = prev.slice(); + var row = next[rowIndex] ? Object.assign({}, next[rowIndex]) : next[rowIndex]; + var items = (row.serviceItems || []).slice(); + var item = items[itemIndex] ? Object.assign({}, items[itemIndex]) : items[itemIndex]; + item[field] = value; + items[itemIndex] = item; + row.serviceItems = items; + next[rowIndex] = row; + return next; + }); + }, []); + + var handleSubmit = useCallback(function() { + var err = []; + for (var i = 0; i < vehicleRows.length; i++) { + var r = vehicleRows[i]; + if (!r.payableRent || String(r.payableRent).trim() === '') err.push('第' + (i + 1) + '行应收车辆租金'); + if (!r.deposit || String(r.deposit).trim() === '') err.push('第' + (i + 1) + '行应收保证金'); + var items = r.serviceItems || []; + for (var j = 0; j < items.length; j++) { + if (!items[j].fee || String(items[j].fee).trim() === '') err.push('第' + (i + 1) + '行服务费项「' + (items[j].name || '') + '」应收费用'); + } + } + if (!hydrogenForm.paidTotal || String(hydrogenForm.paidTotal).trim() === '') err.push('氢费预付款应收金额'); + if (!hydrogenForm.discount || String(hydrogenForm.discount).trim() === '') err.push('氢费减免金额'); + if (err.length > 0) { + alert('请填写必填项:' + err.join('、')); + return; + } + alert('提交成功,该条记录已移至审核中心,审核状态为待审核'); + }, [vehicleRows, hydrogenForm]); + var handleCancelClick = useCallback(function() { + setCancelConfirmVisible(true); + }, []); + var handleCancelConfirm = useCallback(function(confirmed) { + setCancelConfirmVisible(false); + if (confirmed) { + alert('已返回提车应收款列表'); + } + }, []); + + 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 }, + requiredMark: { color: '#ff4d4f', marginRight: 4 }, + 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' }, + formInput: { padding: '8px 12px', border: '1px solid #d9d9d9', borderRadius: 4, fontSize: 14, width: '100%', maxWidth: 140 }, + 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 }, + 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, textDecoration: 'none', background: 'none', border: 'none', padding: 0 } + }; + }, []); + + // 项目信息卡片(3列) + 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('span', { style: styles.requiredMark }, '*'), '应收车辆租金'), + React.createElement('th', { style: styles.th }, '车辆租金备注'), + React.createElement('th', { style: styles.th }, React.createElement('span', { style: styles.requiredMark }, '*'), '应收保证金'), + 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, + vehicleRows.map(function(row, rowIndex) { + var serviceTotal = getRowServiceTotal(row); + 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 }, + React.createElement('input', { type: 'text', style: styles.formInput, value: row.payableRent, onChange: function(e) { handleVehicleChange(rowIndex, 'payableRent', e.target.value); } }) + ), + React.createElement('td', { style: styles.td }, + React.createElement('input', { type: 'text', style: Object.assign({}, styles.formInput, { maxWidth: 120 }), value: row.rentRemark, onChange: function(e) { handleVehicleChange(rowIndex, 'rentRemark', e.target.value); }, placeholder: '选填' }) + ), + 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 }, serviceTotal), + React.createElement('td', { style: styles.td }, + React.createElement('input', { type: 'text', style: styles.formInput, value: row.discount, onChange: function(e) { handleVehicleChange(rowIndex, 'discount', e.target.value); }, placeholder: '0' }) + ), + React.createElement('td', { style: styles.td }, + React.createElement('input', { type: 'text', style: Object.assign({}, styles.formInput, { maxWidth: 120 }), value: row.discountRemark, onChange: function(e) { handleVehicleChange(rowIndex, 'discountRemark', e.target.value); }, placeholder: '选填' }) + ) + ); + }) + ); + + 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('span', { style: styles.requiredMark }, '*'), '氢费预付款应收金额'), + React.createElement('div', { style: { display: 'flex', alignItems: 'center', gap: 8 } }, + React.createElement('input', { + type: 'text', + style: styles.formInput, + value: hydrogenForm.paidTotal, + onChange: function(e) { setHydrogenForm(function(prev) { return Object.assign({}, prev, { paidTotal: e.target.value }); }); }, + onBlur: function(e) { setHydrogenForm(function(prev) { return Object.assign({}, prev, { paidTotal: formatTwoDecimals(prev.paidTotal) }); }); }, + placeholder: '0.00' + }), + React.createElement('span', { style: { fontSize: 14, color: '#333' } }, '元') + ) + ), + React.createElement('div', { style: styles.formCol }, + React.createElement('div', { style: styles.formLabel }, React.createElement('span', { style: styles.requiredMark }, '*'), '减免金额'), + React.createElement('div', { style: { display: 'flex', alignItems: 'center', gap: 8 } }, + React.createElement('input', { + type: 'text', + style: styles.formInput, + value: hydrogenForm.discount, + onChange: function(e) { setHydrogenForm(function(prev) { return Object.assign({}, prev, { discount: e.target.value }); }); }, + onBlur: function(e) { setHydrogenForm(function(prev) { return Object.assign({}, prev, { discount: formatTwoDecimals(prev.discount) }); }); }, + placeholder: '0.00' + }), + React.createElement('span', { style: { fontSize: 14, color: '#333' } }, '元') + ) + ), + React.createElement('div', { style: styles.formCol }, + React.createElement('div', { style: styles.formLabel }, '减免金额备注'), + React.createElement('input', { + type: 'text', + style: styles.formInput, + value: hydrogenForm.discountRemark, + onChange: function(e) { setHydrogenForm(function(prev) { return Object.assign({}, prev, { discountRemark: e.target.value }); }); }, + placeholder: '选填' + }) + ) + ) + ); + + // 开票金额 = 提车应收款总额 + 氢费应收总额 + var invoiceAmount = useMemo(function() { + var a = parseFloat(totalPayable) || 0; + var b = parseFloat(hydrogenPayableTotal) || 0; + return (a + b).toFixed(2); + }, [totalPayable, hydrogenPayableTotal]); + + // 开票信息卡片:第1行开票金额;第2行起客户名称等表单;最后一行开票时间/发票附件/备注 + 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: styles.formValue }, '待开票')), + React.createElement('div', { style: styles.formCol }, React.createElement('div', { style: styles.formLabel }, '发票附件'), React.createElement('div', { style: styles.formValue }, '待上传')), + React.createElement('div', { style: styles.formCol }, React.createElement('div', { style: styles.formLabel }, '备注'), React.createElement('div', { style: styles.formValue }, '无')) + ) + ); + + // 服务费项目弹窗 + var serviceModal = null; + if (serviceModalRow !== null && vehicleRows[serviceModalRow]) { + var r = vehicleRows[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('span', { style: styles.requiredMark }, '*'), '应收费用'), + React.createElement('th', { style: styles.th }, '服务费用备注') + ) + ), + React.createElement('tbody', null, + serviceList.map(function(item, itemIndex) { + return React.createElement('tr', { key: itemIndex }, + React.createElement('td', { style: styles.td }, item.name), + React.createElement('td', { style: styles.td }, + React.createElement('input', { type: 'text', style: styles.formInput, value: item.fee, onChange: function(e) { handleServiceItemChange(serviceModalRow, itemIndex, 'fee', e.target.value); } }) + ), + React.createElement('td', { style: styles.td }, + React.createElement('input', { type: 'text', style: Object.assign({}, styles.formInput, { maxWidth: 200 }), value: item.remark, onChange: function(e) { handleServiceItemChange(serviceModalRow, itemIndex, 'remark', e.target.value); }, placeholder: '选填' }) + ) + ); + }) + ) + ) + ) + ); + } + + 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 + ); +}; diff --git a/web端/车辆租赁合同/2026-02-27租赁合同修改点.zip b/web端/车辆租赁合同/2026-02-27租赁合同修改点.zip deleted file mode 100644 index 5fe66bb..0000000 Binary files a/web端/车辆租赁合同/2026-02-27租赁合同修改点.zip and /dev/null differ diff --git a/web端/车辆租赁合同/新增租赁合同.jsx b/web端/车辆租赁合同/新增租赁合同.jsx index 9dc4b85..49acb07 100644 --- a/web端/车辆租赁合同/新增租赁合同.jsx +++ b/web端/车辆租赁合同/新增租赁合同.jsx @@ -161,7 +161,12 @@ const Component = function() { var feeTemplateOtherFees = [{ project: '上门送车费', standard: '100元/次', serviceFee: '50' }, { project: '上门收车费', standard: '100元/次', serviceFee: '50' }, { project: '清洗费', standard: '80元/次', serviceFee: '30' }]; var brandList = ['品牌A', '品牌B', '品牌C', '品牌D']; var modelByBrand = { '品牌A': ['型号A1', '型号A2', '型号A3'], '品牌B': ['型号B1', '型号B2'], '品牌C': ['型号C1', '型号C2', '型号C3'], '品牌D': ['型号D1'] }; - var vehicleList = [{ plateNo: '浙A10001', vin: 'L1234567890ABCDEF' }, { plateNo: '浙B20002', vin: 'L2234567890ABCDEF' }, { plateNo: '沪A30003', vin: 'L3234567890ABCDEF' }, { plateNo: '粤A40004', vin: 'L4234567890ABCDEF' }]; + var vehicleList = [ + { plateNo: '浙A10001', vin: 'L1234567890ABCDEF', brand: '品牌A', model: '型号A1' }, + { plateNo: '浙B20002', vin: 'L2234567890ABCDEF', brand: '品牌A', model: '型号A2' }, + { plateNo: '沪A30003', vin: 'L3234567890ABCDEF', brand: '品牌B', model: '型号B1' }, + { plateNo: '粤A40004', vin: 'L4234567890ABCDEF', brand: '品牌C', model: '型号C1' } + ]; var serviceItemOptions = ['代处理费用', '罚款', '违章处理违约金', '未参加安全培训', '车辆出险', '年检年审违约', '停车费', '设备损坏金(包含易损件)', '清洗费', '上门收车人工费', '上门收车送车行驶费', '上门收车基础服务费', '保险上浮', '保养费用', '补办驾驶证', '补办牌照', '补办营运证', '补办加氢证', '借用备用钥匙', '补配钥匙', '租金', '氢气费-客', '退还车氢量差', '能源费补缴', '能源费退款', '送车上门人工费', '送车上门送车行驶费', '送车上门基础服务费', '保证金', '氢气预付费', '维修费用', 'ETC-客', 'ETC卡缺损费', 'ETC设备缺损费', '电费-客', '未结算保养费', '未结算维修费', '车损费', '工具损坏或丢失费', '证件费', '广告损坏费', '送车服务费', '接车服务费', '补办行驶证', '超赔险', '轮胎磨损费', '无忧包', '轮胎保', '养护保', '尾板']; var filteredCustomers = customerList.filter(function(c) { return !customerSearch || c.name.indexOf(customerSearch) !== -1; }); @@ -238,6 +243,7 @@ const Component = function() { if (!paymentPeriod) errs.paymentPeriod = '请选择付款周期'; if (!signingCompany) errs.signingCompany = '请选择签约公司'; if (!deliveryProvince || !deliveryCity) errs.deliveryRegion = '请选择交车区域'; + if (!deliveryLocation || !String(deliveryLocation).trim()) errs.deliveryLocation = '请输入交车地点'; var authInvalid = authorizedList.some(function(a) { return !a.name || !a.name.trim() || !a.phone || !a.phone.trim() || !a.idCard || !a.idCard.trim(); }); if (authInvalid) errs.authorizedList = '请完整填写被授权人姓名、联系电话、身份证'; var rentalInvalid = rentalOrders.some(function(r) { return !r.brand || !r.model || !(r.monthRent && String(r.monthRent).trim()) || !(r.deposit && String(r.deposit).trim()); }); @@ -250,7 +256,7 @@ const Component = function() { if (!billingMethod) errs.billingMethod = '请选择账单计算方式'; setFormErrors(errs); if (Object.keys(errs).length > 0) { - var firstId = errs.customer || errs.businessDept || errs.businessOwner ? 'card-customer' : (errs.projectName || errs.contractType || errs.effectiveDate || errs.paymentMethod || errs.endDate || errs.paymentPeriod || errs.signingCompany || errs.deliveryRegion || errs.contractOriginal) ? 'card-contract' : errs.authorizedList ? 'card-authorized' : (errs.rentalOrders || errs.hydrogenBearer || errs.hydrogenPaymentMethod || errs.hydrogenPrepay || errs.returnHydrogenPrice) ? 'card-rental' : errs.feeTemplate ? 'card-fee' : 'card-billing'; + var firstId = errs.customer || errs.businessDept || errs.businessOwner ? 'card-customer' : (errs.projectName || errs.contractType || errs.effectiveDate || errs.paymentMethod || errs.endDate || errs.paymentPeriod || errs.signingCompany || errs.deliveryRegion || errs.deliveryLocation || errs.contractOriginal) ? 'card-contract' : errs.authorizedList ? 'card-authorized' : (errs.rentalOrders || errs.hydrogenBearer || errs.hydrogenPaymentMethod || errs.hydrogenPrepay || errs.returnHydrogenPrice) ? 'card-rental' : errs.feeTemplate ? 'card-fee' : 'card-billing'; setCc1(false); setCc2(false); setCc3(false); setCc4(false); setCc5(false); setCc6(false); setTimeout(function() { var el = document.getElementById(firstId); if (el) el.scrollIntoView({ behavior: 'smooth', block: 'start' }); }, 100); return false; @@ -290,7 +296,17 @@ const Component = function() { newRow[field] = value; if (field === 'plateNo') { var v = vehicleList.find(function(x) { return x.plateNo === value; }); - newRow.vin = v ? v.vin : ''; + if (v) { + newRow.vin = v.vin || ''; + if (v.brand || v.model) { + if (!cur.brand && !cur.model) { + newRow.brand = v.brand || ''; + newRow.model = v.model || ''; + } + } + } else { + newRow.vin = ''; + } } if (field === 'brand') newRow.model = ''; next[index] = newRow; @@ -459,7 +475,6 @@ const Component = function() { var contractFormRow1 = React.createElement('div', { style: styles.formRow }, React.createElement(FormItem, { label: '项目名称', required: true, error: formErrors.projectName }, React.createElement(Input, { placeholder: '请输入项目名称', value: projectName, onChange: function(e) { setProjectName(e.target.value); }, status: formErrors.projectName ? 'error' : undefined, style: { width: '100%' } })), - React.createElement(FormItem, { label: '合同编码' }, React.createElement(Input, { value: contractCode, disabled: true, style: { width: '100%' } })), React.createElement(FormItem, { label: '合同类型', required: true, error: formErrors.contractType }, React.createElement(Select, { placeholder: '请选择合同类型', style: { width: '100%' }, value: contractType || undefined, onChange: function(v) { setContractType(v || ''); }, status: formErrors.contractType ? 'error' : undefined }, React.createElement(Option, { value: '正式合同' }, '正式合同'), React.createElement(Option, { value: '试用合同' }, '试用合同'))), React.createElement(FormItem, { label: '生效日期', required: true, error: formErrors.effectiveDate }, React.createElement(DatePicker, { style: { width: '100%' }, format: 'YYYY-MM-DD', placeholder: '请选择生效日期', value: effectiveDate && window.moment ? window.moment(effectiveDate, 'YYYY-MM-DD') : null, onChange: function(d, dateStr) { setEffectiveDate(dateStr || ''); }, status: formErrors.effectiveDate ? 'error' : undefined })), React.createElement(FormItem, { label: '付款方式', required: true, error: formErrors.paymentMethod }, React.createElement(Select, { placeholder: '请选择付款方式', style: { width: '100%' }, value: paymentMethod || undefined, onChange: function(v) { setPaymentMethod(v || ''); }, status: formErrors.paymentMethod ? 'error' : undefined }, React.createElement(Option, { value: '预付' }, '预付'), React.createElement(Option, { value: '后付' }, '后付'))), @@ -468,32 +483,34 @@ const Component = function() { React.createElement(FormItem, { label: '付款周期', required: true, error: formErrors.paymentPeriod }, React.createElement(Select, { placeholder: '请选择', style: { width: '100%' }, value: paymentPeriod || undefined, onChange: function(v) { setPaymentPeriod(v || ''); }, status: formErrors.paymentPeriod ? 'error' : undefined }, [1,2,3,4,5,6,7,8,9,10,11,12].map(function(n) { return React.createElement(Option, { key: n, value: String(n) }, n + '个月'); }))), React.createElement(FormItem, { label: '签约公司', required: true, error: formErrors.signingCompany }, React.createElement(Select, { placeholder: '请选择', style: { width: '100%' }, value: signingCompany || undefined, onChange: function(v) { setSigningCompany(v || ''); }, status: formErrors.signingCompany ? 'error' : undefined }, orgList.map(function(o, i) { return React.createElement(Option, { key: i, value: o }, o); }))), React.createElement('div', { style: styles.formCol }, - React.createElement(FormItem, { label: '交车区域', required: true, error: formErrors.deliveryRegion }, React.createElement('div', { id: 'delivery-region-wrap', style: { position: 'relative' } }, React.createElement(Input, { style: Object.assign({}, formErrors.deliveryRegion ? { borderColor: '#ff4d4f' } : {}, { cursor: 'pointer', caretColor: 'transparent', width: '100%' }), placeholder: '请选择省-市', value: deliveryRegionDisplay, readOnly: true, onClick: function() { setDeliveryRegionOpen(!deliveryRegionOpen); } }), deliveryRegionOpen ? React.createElement('div', { style: styles.regionCascader, onMouseDown: function() { deliveryRegionClickInsideRef.current = true; } }, React.createElement('div', { style: styles.regionCascaderCol }, regionList.map(function(r, i) { var isActive = r.province === deliveryProvince; return React.createElement('div', { key: i, style: Object.assign({}, styles.regionCascaderItem, isActive ? { backgroundColor: '#e6f7ff', color: '#1890ff' } : {}), onMouseEnter: function(e) { if (!isActive) e.currentTarget.style.backgroundColor = '#f5f5f5'; }, onMouseLeave: function(e) { if (!isActive) e.currentTarget.style.backgroundColor = 'transparent'; }, onMouseDown: function(e) { e.preventDefault(); setDeliveryProvince(r.province); setDeliveryCity(''); } }, r.province); })), React.createElement('div', { style: styles.regionCascaderColLast }, deliveryProvince ? (regionList.find(function(x) { return x.province === deliveryProvince; }) || { cities: [] }).cities.map(function(c, i) { var isActive = c === deliveryCity; return React.createElement('div', { key: i, style: Object.assign({}, styles.regionCascaderItem, isActive ? { backgroundColor: '#e6f7ff', color: '#1890ff' } : {}), onMouseEnter: function(e) { if (!isActive) e.currentTarget.style.backgroundColor = '#f5f5f5'; }, onMouseLeave: function(e) { if (!isActive) e.currentTarget.style.backgroundColor = 'transparent'; }, onMouseDown: function(e) { e.preventDefault(); selectDeliveryRegion(deliveryProvince, c); } }, c); }) : React.createElement('div', { style: { padding: 16, color: '#999', fontSize: 13 } }, '请先选择省'))) : null)), - React.createElement(FormItem, { label: '合同原件', required: true, error: formErrors.contractOriginal }, - contractOriginal - ? React.createElement('div', { style: { display: 'flex', alignItems: 'center', gap: 12, flexWrap: 'wrap' } }, - React.createElement('div', { style: { display: 'flex', alignItems: 'center', gap: 8, flexWrap: 'wrap' } }, - React.createElement('a', { href: '#', style: { color: '#1890ff' }, onClick: function(e) { e.preventDefault(); openContractOriginal(); } }, contractOriginal.name), - contractOriginal.size || contractOriginal.uploadTime ? React.createElement('span', { style: { color: '#999', fontSize: 12 } }, (contractOriginal.size ? contractOriginal.size : '') + (contractOriginal.size && contractOriginal.uploadTime ? ' · ' : '') + (contractOriginal.uploadTime || '')) : null - ), - React.createElement(Button, { type: 'button', size: 'small', danger: true, onClick: function() { setContractOriginal(null); } }, '删除') - ) - : React.createElement('div', { style: { display: 'flex', alignItems: 'center', gap: 8 } }, - React.createElement('input', { ref: contractOriginalRef, type: 'file', style: { display: 'none' }, onChange: function(e) { - var f = e.target.files && e.target.files[0]; - if (f) { - var sizeDisplay = f.size >= 1024 * 1024 ? (f.size / 1024 / 1024).toFixed(1) + ' MB' : (f.size / 1024).toFixed(1) + ' KB'; - var now = window.moment ? window.moment() : new Date(); - var uploadTimeStr = window.moment ? now.format('YYYY-MM-DD HH:mm') : now.getFullYear() + '-' + String(now.getMonth() + 1).padStart(2, '0') + '-' + String(now.getDate()).padStart(2, '0') + ' ' + String(now.getHours()).padStart(2, '0') + ':' + String(now.getMinutes()).padStart(2, '0'); - setContractOriginal({ name: f.name, file: f, size: sizeDisplay, uploadTime: uploadTimeStr }); - } - e.target.value = ''; - } }), - React.createElement(Button, { type: 'default', style: { padding: '8px 16px', border: '1px solid #d9d9d9', borderRadius: 4, backgroundColor: '#fff', color: '#333', cursor: 'pointer', fontSize: 14 }, onClick: function() { if (contractOriginalRef.current) contractOriginalRef.current.click(); } }, '上传附件') - ) - ) + React.createElement(FormItem, { label: '交车区域', required: true, error: formErrors.deliveryRegion }, React.createElement('div', { id: 'delivery-region-wrap', style: { position: 'relative' } }, React.createElement(Input, { style: Object.assign({}, formErrors.deliveryRegion ? { borderColor: '#ff4d4f' } : {}, { cursor: 'pointer', caretColor: 'transparent', width: '100%' }), placeholder: '请选择省-市', value: deliveryRegionDisplay, readOnly: true, onClick: function() { setDeliveryRegionOpen(!deliveryRegionOpen); } }), deliveryRegionOpen ? React.createElement('div', { style: styles.regionCascader, onMouseDown: function() { deliveryRegionClickInsideRef.current = true; } }, React.createElement('div', { style: styles.regionCascaderCol }, regionList.map(function(r, i) { var isActive = r.province === deliveryProvince; return React.createElement('div', { key: i, style: Object.assign({}, styles.regionCascaderItem, isActive ? { backgroundColor: '#e6f7ff', color: '#1890ff' } : {}), onMouseEnter: function(e) { if (!isActive) e.currentTarget.style.backgroundColor = '#f5f5f5'; }, onMouseLeave: function(e) { if (!isActive) e.currentTarget.style.backgroundColor = 'transparent'; }, onMouseDown: function(e) { e.preventDefault(); setDeliveryProvince(r.province); setDeliveryCity(''); } }, r.province); })), React.createElement('div', { style: styles.regionCascaderColLast }, deliveryProvince ? (regionList.find(function(x) { return x.province === deliveryProvince; }) || { cities: [] }).cities.map(function(c, i) { var isActive = c === deliveryCity; return React.createElement('div', { key: i, style: Object.assign({}, styles.regionCascaderItem, isActive ? { backgroundColor: '#e6f7ff', color: '#1890ff' } : {}), onMouseEnter: function(e) { if (!isActive) e.currentTarget.style.backgroundColor = '#f5f5f5'; }, onMouseLeave: function(e) { if (!isActive) e.currentTarget.style.backgroundColor = 'transparent'; }, onMouseDown: function(e) { e.preventDefault(); selectDeliveryRegion(deliveryProvince, c); } }, c); }) : React.createElement('div', { style: { padding: 16, color: '#999', fontSize: 13 } }, '请先选择省'))) : null)) ), - React.createElement(FormItem, { label: '交车地点' }, React.createElement(Input, { placeholder: '请输入交车地点', value: deliveryLocation, onChange: function(e) { setDeliveryLocation(e.target.value); }, style: { width: '100%' } })) + React.createElement(FormItem, { label: '交车地点', required: true, error: formErrors.deliveryLocation }, React.createElement(Input, { placeholder: '请输入交车地点', value: deliveryLocation, onChange: function(e) { setDeliveryLocation(e.target.value); }, status: formErrors.deliveryLocation ? 'error' : undefined, style: { width: '100%' } })) + ); + var contractFormRow1Part2 = React.createElement('div', { style: styles.formRow }, + React.createElement(FormItem, { label: '合同原件', required: true, error: formErrors.contractOriginal }, + contractOriginal + ? React.createElement('div', { style: { display: 'flex', alignItems: 'center', gap: 12, flexWrap: 'wrap' } }, + React.createElement('div', { style: { display: 'flex', alignItems: 'center', gap: 8, flexWrap: 'wrap' } }, + React.createElement('a', { href: '#', style: { color: '#1890ff' }, onClick: function(e) { e.preventDefault(); openContractOriginal(); } }, contractOriginal.name), + contractOriginal.size || contractOriginal.uploadTime ? React.createElement('span', { style: { color: '#999', fontSize: 12 } }, (contractOriginal.size ? contractOriginal.size : '') + (contractOriginal.size && contractOriginal.uploadTime ? ' · ' : '') + (contractOriginal.uploadTime || '')) : null + ), + React.createElement(Button, { type: 'button', size: 'small', danger: true, onClick: function() { setContractOriginal(null); } }, '删除') + ) + : React.createElement('div', { style: { display: 'flex', alignItems: 'center', gap: 8 } }, + React.createElement('input', { ref: contractOriginalRef, type: 'file', style: { display: 'none' }, onChange: function(e) { + var f = e.target.files && e.target.files[0]; + if (f) { + var sizeDisplay = f.size >= 1024 * 1024 ? (f.size / 1024 / 1024).toFixed(1) + ' MB' : (f.size / 1024).toFixed(1) + ' KB'; + var now = window.moment ? window.moment() : new Date(); + var uploadTimeStr = window.moment ? now.format('YYYY-MM-DD HH:mm') : now.getFullYear() + '-' + String(now.getMonth() + 1).padStart(2, '0') + '-' + String(now.getDate()).padStart(2, '0') + ' ' + String(now.getHours()).padStart(2, '0') + ':' + String(now.getMinutes()).padStart(2, '0'); + setContractOriginal({ name: f.name, file: f, size: sizeDisplay, uploadTime: uploadTimeStr }); + } + e.target.value = ''; + } }), + React.createElement(Button, { type: 'default', style: { padding: '8px 16px', border: '1px solid #d9d9d9', borderRadius: 4, backgroundColor: '#fff', color: '#333', cursor: 'pointer', fontSize: 14 }, onClick: function() { if (contractOriginalRef.current) contractOriginalRef.current.click(); } }, '上传附件') + ) + ) ); var contractFormRow2 = React.createElement('div', { style: styles.formRow }, React.createElement(FormItem, { label: '备注', fullWidth: true }, React.createElement(Input.TextArea, { placeholder: '请输入备注信息', value: remarks, onChange: function(e) { setRemarks(e.target.value); }, style: styles.textarea, rows: 4 }))); @@ -642,7 +659,7 @@ const Component = function() { React.createElement('button', { style: styles.anchorItem, onClick: function() { scrollToCard('card-billing'); } }, '账单计算方式') ), React.createElement('div', { id: 'card-customer' }, React.createElement(CardBlock, { id: 'card-customer', title: '客户基本信息', collapsed: cc1, setCollapsed: setCc1 }, customerFields)), - React.createElement('div', { id: 'card-contract', style: { marginTop: 16 } }, React.createElement(CardBlock, { title: '合同基本信息', collapsed: cc2, setCollapsed: setCc2 }, React.createElement('div', null, contractFormRow1, contractFormRow2))), + React.createElement('div', { id: 'card-contract', style: { marginTop: 16 } }, React.createElement(CardBlock, { title: '合同基本信息', collapsed: cc2, setCollapsed: setCc2 }, React.createElement('div', null, contractFormRow1, contractFormRow1Part2, contractFormRow2))), React.createElement('div', { id: 'card-authorized', style: { marginTop: 16 } }, React.createElement(CardBlock, { title: '被授权人信息', collapsed: cc3, setCollapsed: setCc3 }, authorizedContent)), React.createElement('div', { id: 'card-rental', style: { marginTop: 16 } }, React.createElement(CardBlock, { title: '租赁订单信息', collapsed: cc4, setCollapsed: setCc4 }, rentalContent)), React.createElement('div', { id: 'card-fee', style: { marginTop: 16 } }, React.createElement(CardBlock, { title: '其他费用信息', collapsed: cc5, setCollapsed: setCc5 }, feeContent)),