feat(web): 同步交车任务、租赁合同、提车应收款等调整
- 更新多处页面交互与需求说明弹窗文案 - 新增 ETC 管理相关原型页面与需求说明目录内容 Made-with: Cursor
This commit is contained in:
458
web端/业务管理/ETC管理.jsx
Normal file
458
web端/业务管理/ETC管理.jsx
Normal file
@@ -0,0 +1,458 @@
|
||||
// 【重要】必须使用 const Component 作为组件变量名
|
||||
// 业务管理 - ETC管理(2026年3月10日版本)
|
||||
// 模块:充值明细 / ETC账单明细 / ETC余额管理
|
||||
|
||||
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 Tabs = antd.Tabs;
|
||||
var Button = antd.Button;
|
||||
var Select = antd.Select;
|
||||
var Input = antd.Input;
|
||||
var DatePicker = antd.DatePicker;
|
||||
var Modal = antd.Modal;
|
||||
var message = antd.message;
|
||||
var Tag = antd.Tag;
|
||||
var Upload = antd.Upload;
|
||||
|
||||
var activeTab = useState('recharge');
|
||||
var setActiveTab = activeTab[1];
|
||||
|
||||
// ========== 充值明细 Tab ==========
|
||||
var filterCustomer = useState(undefined);
|
||||
var filterRemitStart = useState(null);
|
||||
var filterRemitEnd = useState(null);
|
||||
var filterReceiveCompany = useState(undefined);
|
||||
var filterEntryType = useState(undefined);
|
||||
var filterRechargeNo = useState('');
|
||||
var filterAuditStatus = useState(undefined);
|
||||
var addRechargeVisible = useState(false);
|
||||
var deleteConfirmVisible = useState(false);
|
||||
var deleteConfirmRecord = useState(null);
|
||||
var rechargeList = useState([
|
||||
{ id: 'r1', auditStatus: '已入账', rechargeNo: 'ETC202603010001', customerName: '嘉兴某某物流有限公司', etcBalance: 12580.00, remitAccount: '嘉兴某某物流有限公司', remitDate: '2026-03-01', receiveCompany: '浙江羚牛氢能科技有限公司', entryType: '合同预付', receiveBank: '工商银行杭州分行', amount: 10000.00, creator: '张经理', createTime: '2026-03-01 10:00', attachment: '凭证.pdf', updateTime: '2026-03-01 10:00' },
|
||||
{ id: 'r2', auditStatus: '待审核', rechargeNo: 'ETC202603050002', customerName: '上海某某运输公司', etcBalance: 8600.00, remitAccount: '上海某某运输公司', remitDate: '2026-03-05', receiveCompany: '羚牛新能源科技上海有限公司', entryType: '线下充值', receiveBank: '建设银行上海分行', amount: 5000.00, creator: '李专员', createTime: '2026-03-05 14:30', attachment: '', updateTime: '2026-03-05 14:30' },
|
||||
{ id: 'r3', auditStatus: '已驳回', rechargeNo: 'ETC202603080003', customerName: '杭州某某租赁有限公司', etcBalance: 3200.00, remitAccount: '杭州某某租赁有限公司', remitDate: '2026-03-08', receiveCompany: '浙江羚牛氢能科技有限公司', entryType: '资金冲红', receiveBank: '农业银行杭州分行', amount: -500.00, creator: '王专员', createTime: '2026-03-08 09:15', attachment: '冲红说明.pdf', updateTime: '2026-03-08 11:00' }
|
||||
]);
|
||||
var rechargeData = rechargeList[0];
|
||||
var setRechargeList = rechargeList[1];
|
||||
|
||||
// 新增充值表单
|
||||
var addFormCustomer = useState(undefined);
|
||||
var addFormRemitAccount = useState('');
|
||||
var addFormEtcBalance = useState('');
|
||||
var addFormRemitDate = useState(null);
|
||||
var addFormReceiveCompany = useState(undefined);
|
||||
var addFormOpType = useState(undefined);
|
||||
var addFormAmount = useState('');
|
||||
var addFormReceiveBank = useState(undefined);
|
||||
var addFormFiles = useState([]);
|
||||
|
||||
var receiveCompanyOptions = [
|
||||
{ label: '羚牛新能源科技上海有限公司', value: '羚牛新能源科技上海有限公司' },
|
||||
{ label: '浙江羚牛氢能科技有限公司', value: '浙江羚牛氢能科技有限公司' }
|
||||
];
|
||||
var entryTypeOptions = [
|
||||
{ label: '合同预付', value: '合同预付' },
|
||||
{ label: '线下充值', value: '线下充值' },
|
||||
{ label: '资金冲红', value: '资金冲红' }
|
||||
];
|
||||
var opTypeOptions = [
|
||||
{ label: '普通充值', value: '普通充值' },
|
||||
{ label: '资金冲红', value: '资金冲红' }
|
||||
];
|
||||
|
||||
var filteredRecharge = useMemo(function () {
|
||||
var list = rechargeData;
|
||||
if (filterCustomer[0]) list = list.filter(function (r) { return r.customerName === filterCustomer[0]; });
|
||||
if (filterReceiveCompany[0]) list = list.filter(function (r) { return r.receiveCompany === filterReceiveCompany[0]; });
|
||||
if (filterEntryType[0]) list = list.filter(function (r) { return r.entryType === filterEntryType[0]; });
|
||||
if (filterAuditStatus[0]) list = list.filter(function (r) { return r.auditStatus === filterAuditStatus[0]; });
|
||||
if ((filterRechargeNo[0] || '').trim()) {
|
||||
var kw = (filterRechargeNo[0] || '').trim().toLowerCase();
|
||||
list = list.filter(function (r) { return (r.rechargeNo || '').toLowerCase().indexOf(kw) !== -1; });
|
||||
}
|
||||
return list;
|
||||
}, [rechargeData, filterCustomer[0], filterReceiveCompany[0], filterEntryType[0], filterAuditStatus[0], filterRechargeNo[0]]);
|
||||
|
||||
var rechargeColumns = [
|
||||
{ title: '审核状态', dataIndex: 'auditStatus', key: 'auditStatus', width: 88, render: function (v) { var color = v === '已入账' ? 'success' : v === '待审核' ? 'processing' : 'error'; return React.createElement(Tag, { color: color }, v); } },
|
||||
{ title: '充值编号', dataIndex: 'rechargeNo', key: 'rechargeNo', width: 160, ellipsis: true },
|
||||
{ title: '客户名称', dataIndex: 'customerName', key: 'customerName', width: 160, ellipsis: true },
|
||||
{ title: 'ETC账户余额', dataIndex: 'etcBalance', key: 'etcBalance', width: 120, align: 'right', render: function (v) { return (v != null ? Number(v).toFixed(2) : '0.00') + ' 元'; } },
|
||||
{ title: '汇款账户名', dataIndex: 'remitAccount', key: 'remitAccount', width: 140, ellipsis: true },
|
||||
{ title: '汇款日期', dataIndex: 'remitDate', key: 'remitDate', width: 110 },
|
||||
{ title: '收款公司', dataIndex: 'receiveCompany', key: 'receiveCompany', width: 200, ellipsis: true },
|
||||
{ title: '入账类型', dataIndex: 'entryType', key: 'entryType', width: 100 },
|
||||
{ title: '收款银行', dataIndex: 'receiveBank', key: 'receiveBank', width: 140, ellipsis: true },
|
||||
{ title: '充值金额', dataIndex: 'amount', key: 'amount', width: 100, align: 'right', render: function (v) { return (v != null ? Number(v).toFixed(2) : '0.00') + ' 元'; } },
|
||||
{ title: '创建人', dataIndex: 'creator', key: 'creator', width: 90 },
|
||||
{ title: '创建时间', dataIndex: 'createTime', key: 'createTime', width: 160 },
|
||||
{ title: '附件', dataIndex: 'attachment', key: 'attachment', width: 90, render: function (v) { return v ? React.createElement(Button, { type: 'link', size: 'small', onClick: function () { message.info('预览:' + v); } }, '预览') : '—'; } },
|
||||
{ title: '更新时间', dataIndex: 'updateTime', key: 'updateTime', width: 160 },
|
||||
{ title: '操作', key: 'action', width: 160, fixed: 'right', render: function (_, record) {
|
||||
return React.createElement(React.Fragment, null,
|
||||
React.createElement(Button, { type: 'link', size: 'small', onClick: function () { message.info('查看 ' + record.rechargeNo); } }, '查看'),
|
||||
React.createElement(Button, { type: 'link', size: 'small', onClick: function () { message.info('编辑 ' + record.rechargeNo); } }, '编辑'),
|
||||
React.createElement(Button, { type: 'link', size: 'small', danger: true, onClick: function () { deleteConfirmRecord[1](record); deleteConfirmVisible[1](true); } }, '删除')
|
||||
);
|
||||
} }
|
||||
];
|
||||
|
||||
var handleDeleteRecharge = function () {
|
||||
var r = deleteConfirmRecord[0];
|
||||
if (r) setRechargeList(function (prev) { return prev.filter(function (x) { return x.id !== r.id; }); });
|
||||
deleteConfirmVisible[1](false);
|
||||
deleteConfirmRecord[1](null);
|
||||
message.success('已删除');
|
||||
};
|
||||
|
||||
var handleAddRechargeSubmit = function () {
|
||||
message.success('充值信息已提交');
|
||||
addRechargeVisible[1](false);
|
||||
};
|
||||
|
||||
// ========== ETC账单明细 Tab ==========
|
||||
var billFilterYear = useState(2026);
|
||||
var billFilterDateRange = useState(null);
|
||||
var billFilterBillDateRange = useState(null);
|
||||
var billFilterPassDate = useState(null);
|
||||
var billFilterPlate = useState('');
|
||||
var billFilterVehicleNature = useState(undefined);
|
||||
var billFilterCustomer = useState('');
|
||||
var billFilterReconciled = useState(undefined);
|
||||
var invoiceConfirmVisible = useState(false);
|
||||
var billList = useState([
|
||||
{ id: 'b1', year: 2026, month: 3, week: 2, salesman: '张经理', billDate: '2026/3/10', plateNo: '浙A12345', passTime: '2026-03-10 08:56:48', entry: '杭州南', exit: '嘉兴东', fee: 45.50, vehicleType: '18T', nature: '租赁', customerName: '嘉兴某某物流有限公司', isInvoiced: '否', invoiceAmount: 0, remark: '' },
|
||||
{ id: 'b2', year: 2026, month: 3, week: 2, salesman: '张经理', billDate: '2026/3/10', plateNo: '浙A23456', passTime: '2026-03-10 09:12:00', entry: '嘉兴东', exit: '上海枫泾', fee: 128.00, vehicleType: '18T', nature: '租赁', customerName: '嘉兴某某物流有限公司', isInvoiced: '是', invoiceAmount: 128.00, remark: '' },
|
||||
{ id: 'b3', year: 2026, month: 3, week: 2, salesman: '李专员', billDate: '2026/3/9', plateNo: '沪B11111', passTime: '2026-03-09 14:30:22', entry: '上海徐泾', exit: '苏州城区', fee: 86.00, vehicleType: '4.5T', nature: '自营', customerName: '上海某某运输公司', isInvoiced: '否', invoiceAmount: 0, remark: '' }
|
||||
]);
|
||||
var billData = billList[0];
|
||||
var totalEtcFee = useMemo(function () { return billData.reduce(function (acc, r) { return acc + (Number(r.fee) || 0); }, 0); }, [billData]);
|
||||
|
||||
var billColumns = [
|
||||
{ title: '年份', dataIndex: 'year', key: 'year', width: 72 },
|
||||
{ title: '月份', dataIndex: 'month', key: 'month', width: 64 },
|
||||
{ title: '周', dataIndex: 'week', key: 'week', width: 56 },
|
||||
{ title: '业务员', dataIndex: 'salesman', key: 'salesman', width: 90 },
|
||||
{ title: '账单日期', dataIndex: 'billDate', key: 'billDate', width: 100 },
|
||||
{ title: '车牌号', dataIndex: 'plateNo', key: 'plateNo', width: 100 },
|
||||
{ title: '通行时间', dataIndex: 'passTime', key: 'passTime', width: 172 },
|
||||
{ title: '入口', dataIndex: 'entry', key: 'entry', width: 100 },
|
||||
{ title: '出口', dataIndex: 'exit', key: 'exit', width: 100 },
|
||||
{ title: '通行费用', dataIndex: 'fee', key: 'fee', width: 96, align: 'right', render: function (v) { return (v != null ? Number(v).toFixed(2) : '0.00') + ' 元'; } },
|
||||
{ title: '车型', dataIndex: 'vehicleType', key: 'vehicleType', width: 72 },
|
||||
{ title: '性质', dataIndex: 'nature', key: 'nature', width: 72 },
|
||||
{ title: '客户名称', dataIndex: 'customerName', key: 'customerName', width: 160, ellipsis: true },
|
||||
{ title: '是否已开票', dataIndex: 'isInvoiced', key: 'isInvoiced', width: 96 },
|
||||
{ title: '开票金额', dataIndex: 'invoiceAmount', key: 'invoiceAmount', width: 96, align: 'right', render: function (v) { return (v != null ? Number(v).toFixed(2) : '0.00') + ' 元'; } },
|
||||
{ title: '备注', dataIndex: 'remark', key: 'remark', width: 100, ellipsis: true },
|
||||
{ title: '操作', key: 'action', width: 160, fixed: 'right', render: function (_, record) {
|
||||
return React.createElement(React.Fragment, null,
|
||||
React.createElement(Button, { type: 'link', size: 'small', danger: true, onClick: function () { message.info('删除 ' + record.id); } }, '删除'),
|
||||
React.createElement(Button, { type: 'link', size: 'small', onClick: function () { message.info('编辑 ' + record.id); } }, '编辑'),
|
||||
React.createElement(Button, { type: 'link', size: 'small', onClick: function () { message.info('查看 ' + record.id); } }, '查看')
|
||||
);
|
||||
} }
|
||||
];
|
||||
|
||||
// ========== ETC余额管理 Tab ==========
|
||||
var balanceFilterCustomer = useState(undefined);
|
||||
var balanceFilterStatus = useState(undefined);
|
||||
var balanceFilterProject = useState(undefined);
|
||||
var balanceFilterMin = useState('');
|
||||
var balanceFilterMax = useState('');
|
||||
var thresholdModalVisible = useState(false);
|
||||
var thresholdModalRecord = useState(null);
|
||||
var balanceList = useState([
|
||||
{ id: 'c1', type: 'customer', customerName: '嘉兴某某物流有限公司', projectCount: 2, status: '正常', totalBalance: 12580.00, rechargeTotal: 20000.00, consumeTotal: 7420.00, lastRemitDate: '2026-03-01', threshold: 1000, projects: [
|
||||
{ id: 'c1-p1', type: 'project', projectName: '嘉兴氢能示范项目' },
|
||||
{ id: 'c1-p2', type: 'project', projectName: '嘉兴城配项目' }
|
||||
]},
|
||||
{ id: 'c2', type: 'customer', customerName: '上海某某运输公司', projectCount: 1, status: '预警', totalBalance: 860.00, rechargeTotal: 5000.00, consumeTotal: 4140.00, lastRemitDate: '2026-03-05', threshold: 1000, projects: [
|
||||
{ id: 'c2-p1', type: 'project', projectName: '上海物流租赁项目' }
|
||||
]},
|
||||
{ id: 'c3', type: 'customer', customerName: '杭州某某租赁有限公司', projectCount: 1, status: '欠费', totalBalance: -200.00, rechargeTotal: 3000.00, consumeTotal: 3200.00, lastRemitDate: '2026-02-20', threshold: 500, projects: [
|
||||
{ id: 'c3-p1', type: 'project', projectName: '杭州城配租赁项目' }
|
||||
]}
|
||||
]);
|
||||
var balanceData = balanceList[0];
|
||||
|
||||
var balanceColumns = [
|
||||
{ title: '客户名称/项目名称', key: 'name', width: 220, render: function (_, record) {
|
||||
if (record.type === 'customer') return React.createElement('span', { style: { fontWeight: 600 } }, record.customerName);
|
||||
return React.createElement('span', { style: { paddingLeft: 24 } }, record.projectName);
|
||||
} },
|
||||
{ title: '项目数量', dataIndex: 'projectCount', key: 'projectCount', width: 92 },
|
||||
{ title: '状态值', dataIndex: 'status', key: 'status', width: 88, render: function (v) {
|
||||
if (!v) return '—';
|
||||
var color = v === '正常' ? 'success' : v === '预警' ? 'warning' : 'error';
|
||||
return React.createElement(Tag, { color: color }, v);
|
||||
} },
|
||||
{ title: '总账户余额', dataIndex: 'totalBalance', key: 'totalBalance', width: 120, align: 'right', render: function (v) { return v != null ? (Number(v).toFixed(2) + ' 元') : '—'; } },
|
||||
{ title: '客户充值余额', dataIndex: 'rechargeTotal', key: 'rechargeTotal', width: 120, align: 'right', render: function (v) { return v != null ? (Number(v).toFixed(2) + ' 元') : '—'; } },
|
||||
{ title: '客户消耗ETC费用', dataIndex: 'consumeTotal', key: 'consumeTotal', width: 130, align: 'right', render: function (v) { return v != null ? (Number(v).toFixed(2) + ' 元') : '—'; } },
|
||||
{ title: '最近汇款日期', dataIndex: 'lastRemitDate', key: 'lastRemitDate', width: 118 },
|
||||
{ title: '操作', key: 'action', width: 180, fixed: 'right', render: function (_, record) {
|
||||
if (record.type === 'customer') {
|
||||
return React.createElement(React.Fragment, null,
|
||||
React.createElement(Button, { type: 'link', size: 'small', onClick: function () { thresholdModalRecord[1](record); thresholdModalVisible[1](true); } }, '阈值设置'),
|
||||
React.createElement(Button, { type: 'link', size: 'small', onClick: function () { message.info('跳转账单明细:' + record.customerName); } }, '账单明细')
|
||||
);
|
||||
}
|
||||
return React.createElement(Button, { type: 'link', size: 'small', onClick: function () { message.info('项目账单明细:' + record.projectName); } }, '账单明细');
|
||||
} }
|
||||
];
|
||||
|
||||
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: 'repeat(3, 1fr)', gap: '16px 24px', marginBottom: 16 };
|
||||
var formItemStyle = { marginBottom: 12 };
|
||||
|
||||
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: 'ETC管理' }
|
||||
]
|
||||
})
|
||||
),
|
||||
React.createElement(Card, { style: cardStyle },
|
||||
React.createElement(Tabs, {
|
||||
activeKey: activeTab[0],
|
||||
onChange: setActiveTab,
|
||||
items: [
|
||||
{
|
||||
key: 'recharge',
|
||||
label: '充值明细',
|
||||
children: React.createElement(React.Fragment, null,
|
||||
React.createElement('div', { style: formRowStyle },
|
||||
React.createElement('div', { style: formItemStyle },
|
||||
React.createElement('div', { style: labelStyle }, '客户名称'),
|
||||
React.createElement(Select, { placeholder: '请选择客户', allowClear: true, style: { width: '100%' }, value: filterCustomer[0], onChange: filterCustomer[1], options: [{ label: '嘉兴某某物流有限公司', value: '嘉兴某某物流有限公司' }, { label: '上海某某运输公司', value: '上海某某运输公司' }, { label: '杭州某某租赁有限公司', value: '杭州某某租赁有限公司' }] })
|
||||
),
|
||||
React.createElement('div', { style: formItemStyle },
|
||||
React.createElement('div', { style: labelStyle }, '汇款日期'),
|
||||
React.createElement(DatePicker.RangePicker, { style: { width: '100%' }, value: [filterRemitStart[0], filterRemitEnd[0]], onChange: function (dates) { filterRemitStart[1](dates && dates[0] || null); filterRemitEnd[1](dates && dates[1] || null); } })
|
||||
),
|
||||
React.createElement('div', { style: formItemStyle },
|
||||
React.createElement('div', { style: labelStyle }, '收款公司'),
|
||||
React.createElement(Select, { placeholder: '请选择', allowClear: true, style: { width: '100%' }, value: filterReceiveCompany[0], onChange: filterReceiveCompany[1], options: receiveCompanyOptions })
|
||||
),
|
||||
React.createElement('div', { style: formItemStyle },
|
||||
React.createElement('div', { style: labelStyle }, '入账类型'),
|
||||
React.createElement(Select, { placeholder: '请选择', allowClear: true, style: { width: '100%' }, value: filterEntryType[0], onChange: filterEntryType[1], options: entryTypeOptions })
|
||||
),
|
||||
React.createElement('div', { style: formItemStyle },
|
||||
React.createElement('div', { style: labelStyle }, '充值编号'),
|
||||
React.createElement(Input, { placeholder: '请输入充值编号', value: filterRechargeNo[0], onChange: function (e) { filterRechargeNo[1](e.target.value); } })
|
||||
),
|
||||
React.createElement('div', { style: formItemStyle },
|
||||
React.createElement('div', { style: labelStyle }, '审核状态'),
|
||||
React.createElement(Select, { placeholder: '请选择', allowClear: true, style: { width: '100%' }, value: filterAuditStatus[0], onChange: filterAuditStatus[1], options: [{ label: '待审核', value: '待审核' }, { label: '已驳回', value: '已驳回' }, { label: '已入账', value: '已入账' }] })
|
||||
)
|
||||
),
|
||||
React.createElement('div', { style: { marginBottom: 16, display: 'flex', gap: 8 } },
|
||||
React.createElement(Button, { onClick: function () { filterCustomer[1](undefined); filterRemitStart[1](null); filterRemitEnd[1](null); filterReceiveCompany[1](undefined); filterEntryType[1](undefined); filterRechargeNo[1](''); filterAuditStatus[1](undefined); } }, '重置'),
|
||||
React.createElement(Button, { type: 'primary', onClick: function () { message.info('查询'); } }, '查询'),
|
||||
React.createElement(Button, { type: 'primary', onClick: function () { addRechargeVisible[1](true); } }, '新增')
|
||||
),
|
||||
React.createElement(Table, { rowKey: 'id', columns: rechargeColumns, dataSource: filteredRecharge, scroll: { x: 1800 }, pagination: { showSizeChanger: true, showTotal: function (t) { return '共 ' + t + ' 条'; } } })
|
||||
)
|
||||
},
|
||||
{
|
||||
key: 'bill',
|
||||
label: 'ETC账单明细',
|
||||
children: React.createElement(React.Fragment, null,
|
||||
React.createElement('div', { style: { marginBottom: 16, padding: 16, background: '#e6f7ff', borderRadius: 8, border: '1px solid #91d5ff' } },
|
||||
React.createElement('span', { style: { fontSize: 14, color: 'rgba(0,0,0,0.65)' } }, '总ETC通行金额:'),
|
||||
React.createElement('span', { style: { fontSize: 20, fontWeight: 600, color: '#1890ff', marginLeft: 8 } }, totalEtcFee.toFixed(2), ' 元')
|
||||
),
|
||||
React.createElement('div', { style: formRowStyle },
|
||||
React.createElement('div', { style: formItemStyle },
|
||||
React.createElement('div', { style: labelStyle }, '年份'),
|
||||
React.createElement(Select, { style: { width: '100%' }, value: billFilterYear[0], onChange: billFilterYear[1], options: [{ label: '2026', value: 2026 }, { label: '2027', value: 2027 }] })
|
||||
),
|
||||
React.createElement('div', { style: formItemStyle },
|
||||
React.createElement('div', { style: labelStyle }, '时间区间'),
|
||||
React.createElement(DatePicker.RangePicker, { style: { width: '100%' }, value: billFilterDateRange[0], onChange: billFilterDateRange[1] })
|
||||
),
|
||||
React.createElement('div', { style: formItemStyle },
|
||||
React.createElement('div', { style: labelStyle }, '账单日期'),
|
||||
React.createElement(DatePicker.RangePicker, { style: { width: '100%' }, value: billFilterBillDateRange[0], onChange: billFilterBillDateRange[1] })
|
||||
),
|
||||
React.createElement('div', { style: formItemStyle },
|
||||
React.createElement('div', { style: labelStyle }, '通行日期'),
|
||||
React.createElement(DatePicker, { style: { width: '100%' }, value: billFilterPassDate[0], onChange: billFilterPassDate[1] })
|
||||
),
|
||||
React.createElement('div', { style: formItemStyle },
|
||||
React.createElement('div', { style: labelStyle }, '车牌号'),
|
||||
React.createElement(Input, { placeholder: '请输入车牌号', value: billFilterPlate[0], onChange: function (e) { billFilterPlate[1](e.target.value); } })
|
||||
),
|
||||
React.createElement('div', { style: formItemStyle },
|
||||
React.createElement('div', { style: labelStyle }, '车辆性质'),
|
||||
React.createElement(Select, { placeholder: '请选择', allowClear: true, style: { width: '100%' }, value: billFilterVehicleNature[0], onChange: billFilterVehicleNature[1], options: [{ label: '租赁', value: '租赁' }, { label: '自营', value: '自营' }, { label: '异动', value: '异动' }, { label: '维修', value: '维修' }, { label: '库存', value: '库存' }] })
|
||||
),
|
||||
React.createElement('div', { style: formItemStyle },
|
||||
React.createElement('div', { style: labelStyle }, '客户名称'),
|
||||
React.createElement(Input, { placeholder: '请输入客户名称', value: billFilterCustomer[0], onChange: function (e) { billFilterCustomer[1](e.target.value); } })
|
||||
),
|
||||
React.createElement('div', { style: formItemStyle },
|
||||
React.createElement('div', { style: labelStyle }, '是否对账'),
|
||||
React.createElement(Select, { placeholder: '请选择', allowClear: true, style: { width: '100%' }, value: billFilterReconciled[0], onChange: billFilterReconciled[1], options: [{ label: '是', value: '是' }, { label: '否', value: '否' }] })
|
||||
)
|
||||
),
|
||||
React.createElement('div', { style: { marginBottom: 16 } },
|
||||
React.createElement(Button, { type: 'primary', onClick: function () { invoiceConfirmVisible[1](true); } }, '提交开票')
|
||||
),
|
||||
React.createElement(Table, { rowKey: 'id', columns: billColumns, dataSource: billData, scroll: { x: 1900 }, pagination: { showSizeChanger: true, showTotal: function (t) { return '共 ' + t + ' 条'; } } })
|
||||
)
|
||||
},
|
||||
{
|
||||
key: 'balance',
|
||||
label: 'ETC余额管理',
|
||||
children: React.createElement(React.Fragment, null,
|
||||
React.createElement('div', { style: formRowStyle },
|
||||
React.createElement('div', { style: formItemStyle },
|
||||
React.createElement('div', { style: labelStyle }, '客户名称'),
|
||||
React.createElement(Input, { placeholder: '请输入客户名称', value: balanceFilterCustomer[0], onChange: function (e) { balanceFilterCustomer[1](e.target.value); } })
|
||||
),
|
||||
React.createElement('div', { style: formItemStyle },
|
||||
React.createElement('div', { style: labelStyle }, '状态值'),
|
||||
React.createElement(Select, { placeholder: '请选择', allowClear: true, style: { width: '100%' }, value: balanceFilterStatus[0], onChange: balanceFilterStatus[1], options: [{ label: '正常', value: '正常' }, { label: '预警', value: '预警' }, { label: '欠费', value: '欠费' }] })
|
||||
),
|
||||
React.createElement('div', { style: formItemStyle },
|
||||
React.createElement('div', { style: labelStyle }, '项目名称'),
|
||||
React.createElement(Input, { placeholder: '请输入项目名称', value: balanceFilterProject[0], onChange: function (e) { balanceFilterProject[1](e.target.value); } })
|
||||
),
|
||||
React.createElement('div', { style: formItemStyle },
|
||||
React.createElement('div', { style: labelStyle }, '余额范围'),
|
||||
React.createElement('div', { style: { display: 'flex', alignItems: 'center', gap: 8 } },
|
||||
React.createElement(Input, { placeholder: '最小值', value: balanceFilterMin[0], onChange: function (e) { balanceFilterMin[1](e.target.value); } }),
|
||||
React.createElement('span', null, '-'),
|
||||
React.createElement(Input, { placeholder: '最大值', value: balanceFilterMax[0], onChange: function (e) { balanceFilterMax[1](e.target.value); } })
|
||||
)
|
||||
)
|
||||
),
|
||||
React.createElement('div', { style: { marginBottom: 16 } },
|
||||
React.createElement(Button, { onClick: function () { message.info('导出'); } }, '导出'),
|
||||
React.createElement(Button, { style: { marginLeft: 8 } }, '批量阈值设置')
|
||||
),
|
||||
React.createElement(Table, {
|
||||
rowKey: 'id',
|
||||
columns: balanceColumns,
|
||||
dataSource: balanceData,
|
||||
scroll: { x: 1200 },
|
||||
pagination: false,
|
||||
expandable: {
|
||||
expandedRowRender: function (record) {
|
||||
if (!record.projects || !record.projects.length) return null;
|
||||
return React.createElement('div', { style: { padding: '8px 24px', background: '#fafafa' } },
|
||||
record.projects.map(function (p) { return React.createElement('div', { key: p.id, style: { padding: '4px 0' } }, p.projectName); })
|
||||
);
|
||||
},
|
||||
rowExpandable: function (record) { return record.projects && record.projects.length > 0; }
|
||||
}
|
||||
})
|
||||
)
|
||||
}
|
||||
]
|
||||
})
|
||||
),
|
||||
// 新增充值信息弹窗
|
||||
React.createElement(Modal, {
|
||||
title: '新增充值信息',
|
||||
open: addRechargeVisible[0],
|
||||
onCancel: function () { addRechargeVisible[1](false); },
|
||||
width: 640,
|
||||
footer: [
|
||||
React.createElement(Button, { key: 'cancel', onClick: function () { addRechargeVisible[1](false); } }, '取消'),
|
||||
React.createElement(Button, { key: 'submit', type: 'primary', onClick: handleAddRechargeSubmit }, '提交')
|
||||
]
|
||||
}, React.createElement(React.Fragment, null,
|
||||
React.createElement('div', { style: { fontSize: 15, fontWeight: 600, marginBottom: 12, paddingBottom: 8, borderBottom: '1px solid #f0f0f0' } }, '客户信息'),
|
||||
React.createElement('div', { style: formRowStyle },
|
||||
React.createElement('div', { style: formItemStyle },
|
||||
React.createElement('div', { style: labelStyle }, React.createElement('span', { style: { color: '#ff4d4f' } }, '*'), '客户名称'),
|
||||
React.createElement(Select, { placeholder: '请选择/录入客户', allowClear: true, style: { width: '100%' }, value: addFormCustomer[0], onChange: function (v) { addFormCustomer[1](v); addFormRemitAccount[1](v ? v + '(自动带出)' : ''); addFormEtcBalance[1](v ? '12580.00' : ''); }, options: [{ label: '嘉兴某某物流有限公司', value: '嘉兴某某物流有限公司' }, { label: '上海某某运输公司', value: '上海某某运输公司' }] })
|
||||
),
|
||||
React.createElement('div', { style: formItemStyle },
|
||||
React.createElement('div', { style: labelStyle }, '汇款账户名'),
|
||||
React.createElement(Input, { value: addFormRemitAccount[0], disabled: true, placeholder: '选择客户后自动带出' })
|
||||
),
|
||||
React.createElement('div', { style: formItemStyle },
|
||||
React.createElement('div', { style: labelStyle }, 'ETC账户余额'),
|
||||
React.createElement(Input, { value: addFormEtcBalance[0], disabled: true, placeholder: '选择客户后同步展示' })
|
||||
),
|
||||
React.createElement('div', { style: formItemStyle },
|
||||
React.createElement('div', { style: labelStyle }, React.createElement('span', { style: { color: '#ff4d4f' } }, '*'), '汇款日期'),
|
||||
React.createElement(DatePicker, { style: { width: '100%' }, value: addFormRemitDate[0], onChange: addFormRemitDate[1] })
|
||||
)
|
||||
),
|
||||
React.createElement('div', { style: { fontSize: 15, fontWeight: 600, marginBottom: 12, marginTop: 20, paddingBottom: 8, borderBottom: '1px solid #f0f0f0' } }, '我司信息'),
|
||||
React.createElement('div', { style: formRowStyle },
|
||||
React.createElement('div', { style: formItemStyle },
|
||||
React.createElement('div', { style: labelStyle }, React.createElement('span', { style: { color: '#ff4d4f' } }, '*'), '收款公司'),
|
||||
React.createElement(Select, { placeholder: '请选择', style: { width: '100%' }, value: addFormReceiveCompany[0], onChange: addFormReceiveCompany[1], options: receiveCompanyOptions })
|
||||
),
|
||||
React.createElement('div', { style: formItemStyle },
|
||||
React.createElement('div', { style: labelStyle }, React.createElement('span', { style: { color: '#ff4d4f' } }, '*'), '操作类型'),
|
||||
React.createElement(Select, { placeholder: '请选择', style: { width: '100%' }, value: addFormOpType[0], onChange: addFormOpType[1], options: opTypeOptions })
|
||||
),
|
||||
React.createElement('div', { style: formItemStyle },
|
||||
React.createElement('div', { style: labelStyle }, React.createElement('span', { style: { color: '#ff4d4f' } }, '*'), '充值金额(¥)'),
|
||||
React.createElement(Input, { type: 'number', placeholder: '请输入', value: addFormAmount[0], onChange: function (e) { addFormAmount[1](e.target.value); } }),
|
||||
React.createElement('div', { style: { fontSize: 12, color: '#666', marginTop: 4 } }, '当前账户余额 + 本次变动金额 = 预计账户余额(选择客户后展示)')
|
||||
),
|
||||
React.createElement('div', { style: formItemStyle },
|
||||
React.createElement('div', { style: labelStyle }, React.createElement('span', { style: { color: '#ff4d4f' } }, '*'), '收款银行'),
|
||||
React.createElement(Select, { placeholder: '请选择', style: { width: '100%' }, value: addFormReceiveBank[0], onChange: addFormReceiveBank[1], options: [{ label: '工商银行杭州分行', value: '工商银行杭州分行' }, { label: '建设银行上海分行', value: '建设银行上海分行' }, { label: '农业银行杭州分行', value: '农业银行杭州分行' }] })
|
||||
)
|
||||
),
|
||||
React.createElement('div', { style: { fontSize: 15, fontWeight: 600, marginBottom: 12, marginTop: 20, paddingBottom: 8, borderBottom: '1px solid #f0f0f0' } }, '凭证上传'),
|
||||
React.createElement('div', { style: formItemStyle },
|
||||
React.createElement(Upload, { multiple: true, fileList: addFormFiles[0], beforeUpload: function () { return false; }, onChange: function (info) { addFormFiles[1](info.fileList.slice(-5)); } },
|
||||
React.createElement(Button, null, '点击上传或拖拽文件')
|
||||
)
|
||||
)
|
||||
)),
|
||||
// 删除二次确认
|
||||
React.createElement(Modal, {
|
||||
title: '确认删除',
|
||||
open: deleteConfirmVisible[0],
|
||||
onOk: handleDeleteRecharge,
|
||||
onCancel: function () { deleteConfirmVisible[1](false); deleteConfirmRecord[1](null); },
|
||||
okText: '确认',
|
||||
cancelText: '取消'
|
||||
}, '确认删除该条充值记录?'),
|
||||
// 提交开票二次确认
|
||||
React.createElement(Modal, {
|
||||
title: '确认开票',
|
||||
open: invoiceConfirmVisible[0],
|
||||
onOk: function () { invoiceConfirmVisible[1](false); message.success('开票操作已提交'); },
|
||||
onCancel: function () { invoiceConfirmVisible[1](false); },
|
||||
okText: '确认',
|
||||
cancelText: '取消'
|
||||
}, '确认无误后执行开票操作?'),
|
||||
// 阈值设置弹窗
|
||||
React.createElement(Modal, {
|
||||
title: '阈值设置',
|
||||
open: thresholdModalVisible[0],
|
||||
onOk: function () { thresholdModalVisible[1](false); thresholdModalRecord[1](null); message.success('阈值已保存'); },
|
||||
onCancel: function () { thresholdModalVisible[1](false); thresholdModalRecord[1](null); },
|
||||
okText: '确定',
|
||||
cancelText: '取消'
|
||||
}, thresholdModalRecord[0] ? React.createElement('div', { style: formItemStyle },
|
||||
React.createElement('div', { style: labelStyle }, '客户:' + (thresholdModalRecord[0].customerName || '')),
|
||||
React.createElement('div', { style: labelStyle }, '余额阈值(需大于0)'),
|
||||
React.createElement(Input, { type: 'number', placeholder: '请输入阈值', defaultValue: thresholdModalRecord[0].threshold })
|
||||
) : null)
|
||||
);
|
||||
};
|
||||
1119
web端/业务管理/交车任务.jsx
1119
web端/业务管理/交车任务.jsx
File diff suppressed because it is too large
Load Diff
@@ -7,6 +7,7 @@ const Component = function() {
|
||||
var Select = antd.Select;
|
||||
var Button = antd.Button;
|
||||
var DatePicker = antd.DatePicker;
|
||||
var Modal = antd.Modal;
|
||||
var message = antd.message;
|
||||
var Option = Select.Option;
|
||||
var Checkbox = antd.Checkbox;
|
||||
@@ -25,6 +26,11 @@ const Component = function() {
|
||||
var billingDateValue = billingDate[0];
|
||||
var setBillingDate = billingDate[1];
|
||||
|
||||
// 续签合同:是否需要还车(勾选“不需要还车”则可选已交车车辆),续签时默认不勾选
|
||||
var noReturnCarCheckedState = React.useState(false);
|
||||
var noReturnCarChecked = noReturnCarCheckedState[0];
|
||||
var setNoReturnCarChecked = noReturnCarCheckedState[1];
|
||||
|
||||
var selectedRowKeys = React.useState([]);
|
||||
var checkedRowKeys = selectedRowKeys[0];
|
||||
var setCheckedRowKeys = selectedRowKeys[1];
|
||||
@@ -33,9 +39,7 @@ const Component = function() {
|
||||
var errors = formErrors[0];
|
||||
var setErrors = formErrors[1];
|
||||
|
||||
var reqSpecState = React.useState(false);
|
||||
var reqSpecOpen = reqSpecState[0];
|
||||
var setReqSpecOpen = reqSpecState[1];
|
||||
var reqModalOpen = React.useState(false);
|
||||
|
||||
// Mock:项目列表及车辆样例。deliveryStatus: 'none' 可选,'submitted' 已提交交车任务不可选,'completed' 已完成交车不显示
|
||||
var projectList = [
|
||||
@@ -46,6 +50,13 @@ const Component = function() {
|
||||
{ key: 'v4', brand: '重汽', model: '豪沃氢能牵引车', plateNo: '浙F20001', vin: 'ZZ4257N386FZ12345', monthRent: '15000', serviceFee: '1000', deposit: '35000', remark: '', deliveryStatus: 'none' },
|
||||
{ key: 'v5', brand: '陕汽', model: '德龙氢能自卸', plateNo: '浙F20002', vin: 'SX1313GR456123456', monthRent: '13200', serviceFee: '880', deposit: '32000', remark: '固定线路', deliveryStatus: 'none' }
|
||||
]},
|
||||
{ id: 'p1_r', name: '嘉兴某某物流氢能运输项目(续签合同)', isRenewal: true, contractCode: 'JXZL20270116YW101235B', customerName: '嘉兴某某物流有限公司', deliveryRegion: '浙江省 / 嘉兴市', deliveryLocation: '浙江省嘉兴市南湖区科技大道1号', vehicles: [
|
||||
{ key: 'v1r_1', brand: '东风', model: '氢燃料电池重卡 H31', plateNo: '浙A10001', vin: 'LFV2BJCH8K3123456', monthRent: '12800', serviceFee: '800', deposit: '30000', remark: '续签合同车辆', deliveryStatus: 'none' },
|
||||
{ key: 'v1r_0', brand: '东风', model: '氢燃料电池重卡 H31', plateNo: '浙A09999', vin: 'LFV2BJCH8K3000000', monthRent: '12800', serviceFee: '800', deposit: '30000', remark: '续签:已交车车辆样例', deliveryStatus: 'completed' },
|
||||
{ key: 'v1r_0b', brand: '福田', model: '智蓝氢能轻卡', plateNo: '浙A08888', vin: 'LZYTBACR2M1000001', monthRent: '8500', serviceFee: '500', deposit: '20000', remark: '续签:已交车车辆样例', deliveryStatus: 'completed' },
|
||||
{ key: 'v1r_0c', brand: '重汽', model: '豪沃氢能牵引车', plateNo: '浙A07777', vin: 'ZZ4257N386FZ00002', monthRent: '15000', serviceFee: '1000', deposit: '35000', remark: '续签:已交车车辆样例', deliveryStatus: 'completed' },
|
||||
{ key: 'v1r_2', brand: '福田', model: '智蓝氢能轻卡', plateNo: '', vin: 'LZYTBACR2M1234567', monthRent: '8500', serviceFee: '500', deposit: '20000', remark: '续签待上牌', deliveryStatus: 'none' }
|
||||
]},
|
||||
{ id: 'p2', name: '上海某某运输氢能租赁项目', contractCode: 'SHZL20260201YW200123A', customerName: '上海某某运输公司', deliveryRegion: '上海市 / 上海市', deliveryLocation: '上海市浦东新区张江高科技园区', vehicles: [
|
||||
{ key: 'v6', brand: '上汽红岩', model: '杰狮氢能牵引', plateNo: '沪A30003', vin: 'SH1313HY789012345', monthRent: '14500', serviceFee: '950', deposit: '34000', remark: '', deliveryStatus: 'submitted' },
|
||||
{ key: 'v7', brand: '宇通', model: '氢能公交 ZK6126', plateNo: '沪B40001', vin: 'LZYTAGCF8K4567890', monthRent: '22000', serviceFee: '1200', deposit: '50000', remark: '示范线路', deliveryStatus: 'none' },
|
||||
@@ -60,13 +71,31 @@ const Component = function() {
|
||||
];
|
||||
|
||||
var selectedProject = projectList.find(function(p) { return p.id === selectedProjectId; });
|
||||
var isRenewalProject = !!(selectedProject && selectedProject.isRenewal);
|
||||
var vehicleListRaw = selectedProject ? selectedProject.vehicles : [];
|
||||
var vehicleList = vehicleListRaw.filter(function(v) { return v.deliveryStatus !== 'completed'; });
|
||||
var selectableVehicles = vehicleList.filter(function(v) { return v.deliveryStatus !== 'submitted'; });
|
||||
// 2.8.1 勾选「不需要还车」:只显示已交未还车辆;2.8.2 不勾选:显示已交未还+续签新增车辆,已交未还不可勾选。非续签:已完成交车不显示,已提交不可选。
|
||||
var vehicleList = vehicleListRaw.filter(function(v) {
|
||||
if (v.deliveryStatus === 'completed') {
|
||||
if (!isRenewalProject) return false;
|
||||
return true;
|
||||
}
|
||||
if (v.deliveryStatus === 'submitted') return true;
|
||||
if (isRenewalProject && !!noReturnCarChecked) return false;
|
||||
return true;
|
||||
});
|
||||
var selectableVehicles = vehicleList.filter(function(v) {
|
||||
if (v.deliveryStatus === 'submitted') return false;
|
||||
if (v.deliveryStatus === 'completed') return isRenewalProject && !!noReturnCarChecked;
|
||||
return true;
|
||||
});
|
||||
|
||||
var handleProjectChange = function(id) {
|
||||
setSelectedProjectId(id || '');
|
||||
var nextId = id || '';
|
||||
setSelectedProjectId(nextId);
|
||||
var nextProject = projectList.find(function(p) { return p.id === nextId; });
|
||||
var isRenewal = !!(nextProject && nextProject.isRenewal);
|
||||
setCheckedRowKeys([]);
|
||||
setNoReturnCarChecked(false);
|
||||
};
|
||||
|
||||
var todayStr = (function() {
|
||||
@@ -84,14 +113,15 @@ const Component = function() {
|
||||
return null;
|
||||
};
|
||||
|
||||
var expectedDeliveryError = validateExpectedDelivery();
|
||||
var needExpectedDelivery = !(isRenewalProject && noReturnCarChecked);
|
||||
var expectedDeliveryError = needExpectedDelivery ? validateExpectedDelivery() : null;
|
||||
|
||||
var billingDateError = !billingDateValue ? '请选择开始计费日期' : null;
|
||||
|
||||
var handleSubmit = function() {
|
||||
var err = {};
|
||||
if (!selectedProjectId) err.projectName = '请选择项目名称';
|
||||
if (expectedDeliveryError) err.expectedDelivery = expectedDeliveryError;
|
||||
if (needExpectedDelivery && expectedDeliveryError) err.expectedDelivery = expectedDeliveryError;
|
||||
if (billingDateError) err.billingDate = billingDateError;
|
||||
if (checkedRowKeys.length === 0 && selectableVehicles.length > 0) err.vehicles = '请至少选择一辆车';
|
||||
setErrors(err);
|
||||
@@ -114,6 +144,17 @@ const Component = function() {
|
||||
else setCheckedRowKeys(function(prev) { return prev.filter(function(k) { return k !== record.key; }); });
|
||||
};
|
||||
|
||||
var onToggleNoReturnCar = function(e) {
|
||||
var next = !!(e && e.target ? e.target.checked : e);
|
||||
setNoReturnCarChecked(next);
|
||||
if (!next) {
|
||||
setCheckedRowKeys(function(prev) {
|
||||
var completedKeys = vehicleList.filter(function(v) { return v && v.deliveryStatus === 'completed'; }).map(function(v) { return v.key; });
|
||||
return prev.filter(function(k) { return completedKeys.indexOf(k) === -1; });
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
var styles = {
|
||||
page: { padding: '16px 24px 48px', backgroundColor: '#f5f5f5', minHeight: '100vh', fontFamily: '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif', fontSize: 14 },
|
||||
breadcrumb: { marginBottom: 16, color: '#666' },
|
||||
@@ -139,37 +180,6 @@ const Component = function() {
|
||||
modalBody: { padding: 20, overflow: 'auto', flex: 1 }
|
||||
};
|
||||
|
||||
var reqSpecBlock = { marginBottom: 16 };
|
||||
var reqSpecH2 = { fontSize: 14, fontWeight: 600, color: '#333', marginBottom: 6 };
|
||||
var reqSpecP = { fontSize: 13, color: '#666', marginBottom: 4 };
|
||||
var reqSpecLi = { fontSize: 13, color: '#666', marginBottom: 2, paddingLeft: 8 };
|
||||
|
||||
var reqSpecDoc = React.createElement('div', { style: { padding: '0 4px' } },
|
||||
React.createElement('div', { style: reqSpecBlock }, React.createElement('div', { style: reqSpecH2 }, '交车任务')),
|
||||
React.createElement('div', { style: reqSpecBlock }, React.createElement('div', { style: reqSpecH2 }, '1.面包屑:'), React.createElement('div', { style: reqSpecLi }, '1.1.业务管理-交车任务-新增交车任务')),
|
||||
React.createElement('div', { style: reqSpecBlock }, React.createElement('div', { style: reqSpecH2 }, '2.表单:'),
|
||||
React.createElement('div', { style: reqSpecLi }, '2.1.选择项目名称:必选项,选择器,默认提示文本:请选择或输入项目名称,支持从输入框内输入内容进行模糊搜索,对应自营合同、租赁合同-「项目名称」字段;'),
|
||||
React.createElement('div', { style: reqSpecLi }, '2.2.合同编码:输入框(禁用状态),根据所选项目名称自动反写合同编码;'),
|
||||
React.createElement('div', { style: reqSpecLi }, '2.3.客户名称:输入框(禁用状态),根据所选项目名称自动反写客户名称;'),
|
||||
React.createElement('div', { style: reqSpecLi }, '2.4.交车区域:输入框(禁用状态),根据所选项目名称自动反写交车区域。提交时根据交车区域,为对应区域运维人员分配对应交车任务;'),
|
||||
React.createElement('div', { style: reqSpecLi }, '2.5.交车地点:输入框(禁用状态),根据所选项目名称自动反写交车地点;'),
|
||||
React.createElement('div', { style: reqSpecLi }, '2.6.预计交车日期:必填项,日期选择器,支持某天或某个时间段两种模式,格式为YYYY-MM-DD或YYYY-MM-DD至YYYY-MM-DD,结束日期不能早于开始日期,并且结束日期不能早于当前日期;'),
|
||||
React.createElement('div', { style: reqSpecLi }, '2.7.开始计费日期:必填项,日期选择器,支持单日选择,格式为YYYY-MM-DD;'),
|
||||
React.createElement('div', { style: reqSpecLi }, '2.8.下方为列表,列表拉取该车辆租赁合同对应所有车辆信息(该合同下已提交过交车任务的车辆不可选,已完成交车的车辆不显示在列表中),列表字段为:全选/多选、品牌、型号、车牌号、车辆识别代码、车辆月租金、服务费、保证金、备注;'),
|
||||
React.createElement('div', { style: reqSpecLi }, '2.8.1.全选/多选:支持全选、多选模式,选择对应车辆后,点击提交自动生成被选中车辆交车任务,需要至少选择1辆,才能进行提交,该合同下已提交过交车任务的车辆不可选,已完成交车的车辆不显示在列表中;'),
|
||||
React.createElement('div', { style: reqSpecLi }, '2.8.2.品牌:输入框(禁用状态),根据所选项目名称自动反写品牌;'),
|
||||
React.createElement('div', { style: reqSpecLi }, '2.8.3.型号:输入框(禁用状态),根据所选项目名称自动反写型号;'),
|
||||
React.createElement('div', { style: reqSpecLi }, '2.8.4.车牌号:输入框(禁用状态),根据所选项目名称自动反写车牌号,车牌号可能为空,为空时显示为-;'),
|
||||
React.createElement('div', { style: reqSpecLi }, '2.8.5.车辆识别代码:输入框(禁用状态),根据所选项目名称自动反写车辆识别代码;'),
|
||||
React.createElement('div', { style: reqSpecLi }, '2.8.6.车辆月租金:输入框(禁用状态),根据所选项目名称自动反写车辆月租金,后缀为元;'),
|
||||
React.createElement('div', { style: reqSpecLi }, '2.8.7.服务费:输入框(禁用状态),根据所选项目名称自动反写服务费,后缀为元;'),
|
||||
React.createElement('div', { style: reqSpecLi }, '2.8.8.保证金:输入框(禁用状态),根据所选项目名称自动反写保证金,后缀为元;'),
|
||||
React.createElement('div', { style: reqSpecLi }, '2.8.9.备注:输入框(禁用状态),根据所选项目名称自动反写备注信息,备注为空时显示为-;'),
|
||||
React.createElement('div', { style: reqSpecLi }, '2.9.页面底部为提交、取消;')
|
||||
));
|
||||
|
||||
var reqSpecModalContent = reqSpecOpen ? React.createElement('div', { style: styles.modalMask, onClick: function(e) { if (e.target === e.currentTarget) setReqSpecOpen(false); } }, React.createElement('div', { style: styles.modalBox, onClick: function(e) { e.stopPropagation(); } }, React.createElement('div', { style: styles.modalHeader }, '需求说明'), React.createElement('div', { style: Object.assign({}, styles.modalBody, { maxHeight: '70vh', padding: '20px 24px' }) }, reqSpecDoc), React.createElement('div', { style: { padding: '12px 20px', borderTop: '1px solid #f0f0f0', textAlign: 'right' } }, React.createElement(Button, { onClick: function() { setReqSpecOpen(false); } }, '关闭')))) : null;
|
||||
|
||||
var FormItem = function(props) {
|
||||
return React.createElement('div', { style: styles.formCol },
|
||||
React.createElement('label', { style: styles.label }, props.required ? React.createElement('span', { style: styles.labelRequired }, '*') : null, props.label),
|
||||
@@ -183,7 +193,7 @@ const Component = function() {
|
||||
var formRow1 = React.createElement('div', { style: styles.formRow },
|
||||
React.createElement(FormItem, { label: '选择项目名称', required: true, error: errors.projectName },
|
||||
React.createElement(Select, {
|
||||
placeholder: '请选择或输入项目名称',
|
||||
placeholder: '请选择或输入项目名称(对应自营合同、租赁合同-项目名称)',
|
||||
style: { width: '100%' },
|
||||
value: selectedProjectId || undefined,
|
||||
onChange: handleProjectChange,
|
||||
@@ -199,7 +209,7 @@ const Component = function() {
|
||||
);
|
||||
|
||||
var formRow2 = React.createElement('div', { style: styles.formRow },
|
||||
React.createElement(FormItem, { label: '预计交车日期', required: true, error: errors.expectedDelivery },
|
||||
needExpectedDelivery ? React.createElement(FormItem, { label: '预计交车日期', required: true, error: errors.expectedDelivery },
|
||||
React.createElement(RangePicker, {
|
||||
style: { width: '100%' },
|
||||
format: 'YYYY-MM-DD',
|
||||
@@ -207,7 +217,7 @@ const Component = function() {
|
||||
value: expectedDeliveryValue,
|
||||
onChange: function(dates) { setExpectedDelivery(dates && dates.length === 2 ? dates : null); },
|
||||
status: errors.expectedDelivery ? 'error' : undefined
|
||||
})),
|
||||
})) : null,
|
||||
React.createElement(FormItem, { label: '开始计费日期', required: true, error: errors.billingDate },
|
||||
React.createElement(DatePicker, {
|
||||
style: { width: '100%' },
|
||||
@@ -216,7 +226,17 @@ const Component = function() {
|
||||
value: billingDateValue,
|
||||
onChange: function(d, dateStr) { setBillingDate(d); },
|
||||
status: errors.billingDate ? 'error' : undefined
|
||||
}))
|
||||
})),
|
||||
isRenewalProject ? React.createElement(FormItem, { label: '已交车辆是否需要还车' },
|
||||
React.createElement('div', { style: { display: 'flex', alignItems: 'flex-start', gap: 8, lineHeight: 1.6 } },
|
||||
React.createElement(Checkbox, { checked: !!noReturnCarChecked, onChange: onToggleNoReturnCar }, '不需要还车'),
|
||||
React.createElement('span', { style: { color: '#8c8c8c', fontSize: 12, marginTop: 2 } },
|
||||
'勾选不需要还车,则车辆无需交车,',
|
||||
React.createElement('br', null),
|
||||
'只设置开始计费日期即可重新生成账单'
|
||||
)
|
||||
)
|
||||
) : null
|
||||
);
|
||||
|
||||
var allSelectableChecked = selectableVehicles.length > 0 && selectableVehicles.every(function(v) { return checkedRowKeys.indexOf(v.key) !== -1; });
|
||||
@@ -245,14 +265,25 @@ const Component = function() {
|
||||
? React.createElement('tr', null, React.createElement('td', { colSpan: 9, style: Object.assign({}, styles.td, { textAlign: 'center', color: '#999' }) }, '请先选择项目名称,将自动带出该合同下车辆信息'))
|
||||
: vehicleList.map(function(row) {
|
||||
var isSubmitted = row.deliveryStatus === 'submitted';
|
||||
var isCompleted = row.deliveryStatus === 'completed';
|
||||
var completedSelectable = isRenewalProject && !!noReturnCarChecked;
|
||||
return React.createElement('tr', { key: row.key },
|
||||
React.createElement('td', { style: styles.td },
|
||||
isSubmitted
|
||||
? React.createElement(Tooltip, { title: '该车辆已有交车任务' },
|
||||
? React.createElement(Tooltip, { title: '该车辆已创建交车任务' },
|
||||
React.createElement('span', { style: { display: 'inline-flex', alignItems: 'center', gap: 6, cursor: 'not-allowed' } },
|
||||
React.createElement(Checkbox, { disabled: true, checked: false }),
|
||||
React.createElement('span', { style: { color: '#999', fontSize: 12 } }, '已提交')))
|
||||
: React.createElement(Checkbox, { checked: checkedRowKeys.indexOf(row.key) !== -1, onChange: function(e) { onSelectRow(row, e.target.checked); } })),
|
||||
: isCompleted
|
||||
? React.createElement(Tooltip, { title: '该车辆已完成交车' },
|
||||
React.createElement('span', { style: { display: 'inline-flex', alignItems: 'center' } },
|
||||
React.createElement(Checkbox, {
|
||||
disabled: !completedSelectable,
|
||||
checked: completedSelectable ? (checkedRowKeys.indexOf(row.key) !== -1) : true,
|
||||
onChange: function(e) { onSelectRow(row, e.target.checked); }
|
||||
})
|
||||
))
|
||||
: React.createElement(Checkbox, { checked: checkedRowKeys.indexOf(row.key) !== -1, onChange: function(e) { onSelectRow(row, e.target.checked); } })),
|
||||
React.createElement('td', { style: styles.td }, React.createElement(Input, { value: row.brand, disabled: true, style: styles.inputDisabled })),
|
||||
React.createElement('td', { style: styles.td }, React.createElement(Input, { value: row.model, disabled: true, style: styles.inputDisabled })),
|
||||
React.createElement('td', { style: styles.td }, React.createElement(Input, { value: row.plateNo || '-', disabled: true, style: styles.inputDisabled })),
|
||||
@@ -276,6 +307,8 @@ const Component = function() {
|
||||
);
|
||||
}
|
||||
|
||||
var reqSpecText = '新增交车任务\n一个「数字化资产ONEOS运管平台」中的「新增交车任务」模块\n1.面包屑:\n1.1.业务管理-交车任务-新增交车任务\n\n2.表单:\n2.1.选择项目名称:必选项,选择器,默认提示文本:请选择或输入项目名称,支持从输入框内输入内容进行模糊搜索,对应自营合同、租赁合同-「项目名称」字段;;\n2.2.合同编码:输入框(禁用状态),根据所选项目名称自动反写合同编码;\n2.3.客户名称:输入框(禁用状态),根据所选项目名称自动反写客户名称;\n2.4.交车区域:输入框(禁用状态),根据所选项目名称自动反写交车区域。提交时根据交车区域,为对应区域运维人员分配对应交车任务;\n2.5.交车地点:输入框(禁用状态),根据所选项目名称自动反写交车地点;\n2.6.预计交车日期:必填项,日期选择器,支持某天或某个时间段两种模式,格式为YYYY-MM-DD或YYYY-MM-DD至YYYY-MM-DD,结束日期不能早于开始日期,并且结束日期不能早于当前日期;\n 2.6.1.如勾选不需要还车,则预计交车日期隐藏,不需要设置;\n2.7.开始计费日期:必填项,日期选择器,支持单日选择,格式为YYYY-MM-DD;\n2.8.已交车辆是否需要还车:勾选框,内容为不需要还车,默认不勾选,不勾选时,无法在车辆列表勾选已交未还的车辆,勾选后,已交未还的车辆也可以勾选,但不会生成新交车任务,只是按照开始计费日期生成账单;\n 2.8.1.勾选时,车辆列表只显示已交未还的车辆清单,不能添加新车(避免已交未还部分车辆开始计费日期计算不精确);\n 2.8.2.不勾选时,车辆列表显示已交未还的车辆清单及续签合同新增车辆,但是已交未还部分的车辆不可勾选;\n2.9.下方为列表,列表拉取该车辆租赁合同对应所有车辆信息(该合同下已提交过交车任务的车辆不可选,已完成交车的车辆不显示在列表中),列表字段为:全选/多选、品牌、型号、车牌号、车辆识别代码、车辆月租金、服务费、保证金、备注;\n 2.9.1.全选/多选:支持全选、多选模式,选择对应车辆后,点击提交自动生成被选中车辆交车任务,需要至少选择1辆,才能进行提交,该合同下已提交过交车任务和已交车的车辆不可选,多选框为禁用状态,悬浮时提示:该车辆已完成交车/该车辆已创建交车任务;\n 2.9.2.品牌:输入框(禁用状态),根据所选项目名称自动反写品牌;\n 2.9.3.型号:输入框(禁用状态),根据所选项目名称自动反写型号;\n 2.9.4.车牌号:输入框(禁用状态),根据所选项目名称自动反写车牌号,车牌号可能为空,为空时显示为-;\n 2.9.5.车辆识别代码:输入框(禁用状态),根据所选项目名称自动反写车辆识别代码;\n 2.9.6.车辆月租金:输入框(禁用状态),根据所选项目名称自动反写车辆月租金,后缀为元;\n 2.9.7.服务费:输入框(禁用状态),根据所选项目名称自动反写服务费,后缀为元;\n 2.9.8.保证金:输入框(禁用状态),根据所选项目名称自动反写保证金,后缀为元;\n 2.9.9.备注:输入框(禁用状态),根据所选项目名称自动反写备注信息,备注为空时显示为-;\n2.10.页面底部为提交、取消;';
|
||||
|
||||
return React.createElement('div', { style: styles.page },
|
||||
React.createElement('div', { style: { display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 16 } },
|
||||
React.createElement('div', { style: styles.breadcrumb },
|
||||
@@ -284,7 +317,7 @@ const Component = function() {
|
||||
React.createElement('span', null, '交车任务'),
|
||||
React.createElement('span', { style: styles.breadcrumbSep }, ' / '),
|
||||
React.createElement('span', { style: { color: '#1890ff' } }, '新增交车任务')),
|
||||
React.createElement('span', { style: { color: '#1890ff', cursor: 'pointer', fontSize: 14 }, onClick: function() { setReqSpecOpen(true); } }, '查看需求说明')),
|
||||
React.createElement(Button, { type: 'link', style: { padding: 0 }, onClick: function() { reqModalOpen[1](true); } }, '查看需求说明')),
|
||||
React.createElement('div', { style: styles.card },
|
||||
React.createElement('div', { style: styles.cardHeader }, React.createElement('span', { style: styles.cardTitle }, '交车任务')),
|
||||
React.createElement('div', { style: styles.cardBody },
|
||||
@@ -292,9 +325,17 @@ const Component = function() {
|
||||
formRow2,
|
||||
tableEl)),
|
||||
React.createElement('div', { style: { height: 60 } }),
|
||||
reqSpecModalContent,
|
||||
React.createElement('div', { style: styles.footer },
|
||||
React.createElement(Button, { type: 'primary', onClick: handleSubmit }, '提交'),
|
||||
React.createElement(Button, { onClick: handleCancel }, '取消'))
|
||||
React.createElement(Button, { onClick: handleCancel }, '取消')),
|
||||
React.createElement(Modal, {
|
||||
title: '需求说明',
|
||||
open: reqModalOpen[0],
|
||||
onCancel: function() { reqModalOpen[1](false); },
|
||||
width: 720,
|
||||
footer: React.createElement(Button, { onClick: function() { reqModalOpen[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 } }, reqSpecText)))
|
||||
);
|
||||
};
|
||||
|
||||
449
web端/业务管理/租赁账单-收费明细.jsx
Normal file
449
web端/业务管理/租赁账单-收费明细.jsx
Normal file
@@ -0,0 +1,449 @@
|
||||
// 【重要】必须使用 const Component 作为组件变量名
|
||||
// 租赁账单-收费明细(2026年3月11日版本)
|
||||
|
||||
const Component = function () {
|
||||
var useState = React.useState;
|
||||
var useCallback = React.useCallback;
|
||||
var useMemo = React.useMemo;
|
||||
|
||||
var antd = window.antd;
|
||||
var Breadcrumb = antd.Breadcrumb;
|
||||
var Card = antd.Card;
|
||||
var Input = antd.Input;
|
||||
var Button = antd.Button;
|
||||
var Popover = antd.Popover;
|
||||
var Modal = antd.Modal;
|
||||
var message = antd.message;
|
||||
|
||||
var servicePopoverRowIndex = useState(null);
|
||||
var submitConfirmVisible = useState(false);
|
||||
var cancelConfirmVisible = useState(false);
|
||||
var requirementModalVisible = useState(false);
|
||||
|
||||
// 模拟:当前账单信息(由路由/接口传入,此处为第1期账单)
|
||||
var billInfo = useMemo(function () {
|
||||
return {
|
||||
contractCode: 'HT-ZL-2025-001',
|
||||
contractType: '正式合同',
|
||||
projectName: '嘉兴氢能示范项目',
|
||||
customerName: '嘉兴某某物流有限公司',
|
||||
deliveryTaskCode: 'JT-2025-001-A',
|
||||
billCode: 'HT-ZL-2025-0010001',
|
||||
period: 1,
|
||||
billStartDate: '2025-01-01',
|
||||
billEndDate: '2025-01-31'
|
||||
};
|
||||
}, []);
|
||||
|
||||
var isFirstPeriod = billInfo.period === 1;
|
||||
|
||||
// 车辆明细(该账单对应车辆及费用)
|
||||
var vehicleRows = useState([
|
||||
{ key: 'v1', index: 1, brand: '东风', model: 'DFH1180', plateNo: '浙A12345', receivableRent: 30000, actualRent: '29800.00', rentRemark: '首期六期一次性付清', discountAmount: '200.00', discountRemark: '首月优惠', discountProof: [{ name: '优惠审批单.pdf' }], 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' },
|
||||
{ key: 'v2', index: 2, brand: '福田', model: 'BJ1180', plateNo: '浙A23456', receivableRent: 27000, actualRent: '27000.00', rentRemark: '', discountAmount: '0.00', discountRemark: '', discountProof: [], receivableDeposit: 8000, serviceItems: [{ name: '保养费用', receivable: 300, actual: '300.00', discount: '0.00', remark: '含首保' }], receivableService: 300, actualService: '300.00' },
|
||||
{ key: 'v3', index: 3, brand: '重汽', model: 'ZZ1187', plateNo: '浙A34567', receivableRent: 31200, actualRent: '31200.00', rentRemark: '', discountAmount: '0.00', discountRemark: '', discountProof: [], 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' }
|
||||
]);
|
||||
var vehicles = vehicleRows[0];
|
||||
var setVehicles = vehicleRows[1];
|
||||
|
||||
var hydrogenRow = useState({ receivable: '3580.00', actual: '3500.00', discount: '80.00', discountRemark: '预付款批量减免' });
|
||||
var hydrogen = hydrogenRow[0];
|
||||
var setHydrogen = hydrogenRow[1];
|
||||
|
||||
var updateVehicle = useCallback(function (key, field, value) {
|
||||
setVehicles(function (prev) {
|
||||
return prev.map(function (r) {
|
||||
if (r.key !== key) return r;
|
||||
var next = Object.assign({}, r);
|
||||
next[field] = value;
|
||||
if (field === 'serviceItems') {
|
||||
var total = 0;
|
||||
(value || []).forEach(function (s) { total += parseFloat(s.actual) || 0; });
|
||||
next.actualService = total.toFixed(2);
|
||||
}
|
||||
return next;
|
||||
});
|
||||
});
|
||||
}, []);
|
||||
|
||||
var updateServiceItem = useCallback(function (vehicleKey, itemIndex, field, value) {
|
||||
setVehicles(function (prev) {
|
||||
return prev.map(function (r) {
|
||||
if (r.key !== vehicleKey) return r;
|
||||
var items = (r.serviceItems || []).slice();
|
||||
if (!items[itemIndex]) return r;
|
||||
items[itemIndex] = Object.assign({}, items[itemIndex], { [field]: value });
|
||||
var total = 0;
|
||||
items.forEach(function (s) { total += parseFloat(s.actual) || 0; });
|
||||
return Object.assign({}, r, { serviceItems: items, actualService: total.toFixed(2) });
|
||||
});
|
||||
});
|
||||
}, []);
|
||||
|
||||
// 应收款总额 = 应收车辆月租金总和 + 应收车辆保证金总和 + 应收服务费总和 + 氢费预付款应收金额
|
||||
var totals = useMemo(function () {
|
||||
var receivableRent = 0, actualRent = 0, receivableDeposit = 0, receivableService = 0, actualService = 0, discountTotal = 0, serviceDiscountTotal = 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;
|
||||
(v.serviceItems || []).forEach(function (s) { serviceDiscountTotal += parseFloat(s.discount) || 0; });
|
||||
});
|
||||
var hydrogenReceivable = parseFloat(hydrogen.receivable) || 0;
|
||||
var hydrogenActual = parseFloat(hydrogen.actual) || 0;
|
||||
var hydrogenDiscount = parseFloat(hydrogen.discount) || 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),
|
||||
serviceDiscountTotal: serviceDiscountTotal.toFixed(2),
|
||||
hydrogenReceivable: hydrogenReceivable.toFixed(2),
|
||||
hydrogenActual: hydrogenActual.toFixed(2),
|
||||
hydrogenDiscount: hydrogenDiscount.toFixed(2)
|
||||
};
|
||||
}, [vehicles, hydrogen]);
|
||||
|
||||
var receivableTotal = useMemo(function () {
|
||||
return (parseFloat(totals.receivableRent) + parseFloat(totals.receivableDeposit) + parseFloat(totals.receivableService) + (isFirstPeriod ? parseFloat(totals.hydrogenReceivable) : 0)).toFixed(2);
|
||||
}, [totals, isFirstPeriod]);
|
||||
|
||||
var actualTotal = useMemo(function () {
|
||||
var base = parseFloat(totals.actualRent) + parseFloat(totals.receivableDeposit) + parseFloat(totals.actualService) - parseFloat(totals.discountTotal) - parseFloat(totals.serviceDiscountTotal);
|
||||
if (isFirstPeriod) base += parseFloat(totals.hydrogenActual) - parseFloat(totals.hydrogenDiscount);
|
||||
return base.toFixed(2);
|
||||
}, [totals, isFirstPeriod]);
|
||||
|
||||
var invoiceTotal = useMemo(function () {
|
||||
// 开票金额:同“实收款总额”展示格式,但不包含应收车辆保证金
|
||||
var base = parseFloat(totals.actualRent) + parseFloat(totals.actualService) - parseFloat(totals.discountTotal) - parseFloat(totals.serviceDiscountTotal);
|
||||
if (isFirstPeriod) base += parseFloat(totals.hydrogenActual) - parseFloat(totals.hydrogenDiscount);
|
||||
return base.toFixed(2);
|
||||
}, [totals, isFirstPeriod]);
|
||||
|
||||
var receivablePopoverContent = useMemo(function () {
|
||||
var rows = [
|
||||
['总计应收车辆月租金', totals.receivableRent + ' 元'],
|
||||
['总计应收车辆保证金', totals.receivableDeposit + ' 元'],
|
||||
['总计应收服务费', totals.receivableService + ' 元']
|
||||
];
|
||||
if (isFirstPeriod) rows.push(['氢费预付款应收金额', totals.hydrogenReceivable + ' 元']);
|
||||
return 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,
|
||||
rows.map(function (r, i) { return React.createElement('tr', { key: i }, React.createElement('td', { style: { padding: '6px 8px' } }, r[0]), React.createElement('td', { style: { textAlign: 'right', padding: '6px 8px' } }, r[1])); })
|
||||
)
|
||||
)
|
||||
);
|
||||
}, [totals, isFirstPeriod]);
|
||||
|
||||
var actualPopoverContent = useMemo(function () {
|
||||
var rows = [
|
||||
['总计实收车辆月租金', totals.actualRent + ' 元'],
|
||||
['总计应收车辆保证金', totals.receivableDeposit + ' 元'],
|
||||
['总计实收服务费', totals.actualService + ' 元'],
|
||||
['总计减免金额', totals.discountTotal + ' 元'],
|
||||
['服务费各项减免费用总和', totals.serviceDiscountTotal + ' 元']
|
||||
];
|
||||
if (isFirstPeriod) {
|
||||
rows.push(['氢费预付款实收金额', totals.hydrogenActual + ' 元']);
|
||||
rows.push(['氢费预付款减免金额', totals.hydrogenDiscount + ' 元']);
|
||||
}
|
||||
return React.createElement('div', { style: { padding: 8, minWidth: 240 } },
|
||||
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,
|
||||
rows.map(function (r, i) { return React.createElement('tr', { key: i }, React.createElement('td', { style: { padding: '6px 8px' } }, r[0]), React.createElement('td', { style: { textAlign: 'right', padding: '6px 8px' } }, r[1])); })
|
||||
)
|
||||
)
|
||||
);
|
||||
}, [totals, isFirstPeriod]);
|
||||
|
||||
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 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' };
|
||||
var highlightStyle = { color: '#1890ff', fontWeight: 600, cursor: 'pointer' };
|
||||
var requiredStar = { color: '#ff4d4f', marginRight: 2 };
|
||||
|
||||
var activeServiceIndex = servicePopoverRowIndex[0];
|
||||
var setServicePopoverRowIndex = servicePopoverRowIndex[1];
|
||||
|
||||
function handleSubmit() {
|
||||
submitConfirmVisible[1](true);
|
||||
}
|
||||
function handleSubmitConfirm() {
|
||||
submitConfirmVisible[1](false);
|
||||
message.success('提交成功');
|
||||
if (window.__billChargeDetailBack) window.__billChargeDetailBack();
|
||||
}
|
||||
function handleSave() {
|
||||
message.success('保存成功');
|
||||
if (window.__billChargeDetailBack) window.__billChargeDetailBack();
|
||||
}
|
||||
function handleCancel() {
|
||||
cancelConfirmVisible[1](true);
|
||||
}
|
||||
function handleCancelConfirm() {
|
||||
cancelConfirmVisible[1](false);
|
||||
if (window.__billChargeDetailBack) window.__billChargeDetailBack();
|
||||
else message.info('返回租赁账单列表(原型)');
|
||||
}
|
||||
|
||||
var requirementContent = '租赁账单-收费明细(2026年3月11日版本)\n一个「数字化资产ONEOS运管平台」中的「租赁账单」「收费明细」模块\n#面包屑:业务管理-租赁账单-收费明细;\n1.账单信息:\n#显示该账单对应合同及账单信息,显示以下字段:\n 1.1.合同编码:显示该账单对应合同编码;\n 1.2.合同类型:显示该账单对应合同类型,包括正式合同、试用合同;\n 1.3.项目名称:显示该账单对应合同中项目名称;\n 1.4.客户名称:显示该账单对应合同中客户名称;\n 1.5.交车任务编码:显示交车任务对应编码;\n 1.6.账单编码:显示该账单编码,账单编码规则为:[合同编码][账单编号]组成,主要用于后期与用友YS系统打通时获取财务收款及发票相关数据;\n 前缀为合同编码,后缀为账单编号,规则为:ZD+4位编号,为该合同下第x份账单,例如:ZD0001为该合同下第1份账单,依次类推;\n 例如:JXZL20260216YW101235AZD0001即为JXZL20260216YW101235A合同下第1份账单;;\n 1.7.账单期数:显示该账单期数;\n 1.8.账单开始日期:显示账单开始日期,根据租赁合同及交车任务开始计费日期按规则生成,格式为:YYYY-MM-DD;\n 1.9.账单结束日期:显示账单结束日期,根据租赁合同及交车任务开始计费日期按规则生成,格式为:YYYY-MM-DD;\n2.账单明细:\n#顶部显示应收款总额、实收款总额;\n 2.1.应收款总额:「应收车辆月租金总和」+「应收车辆保证金总和」+「应收服务费总和」+「氢费预付款应收金额」\n 2.2.实收款总额:「实收车辆月租金总和」+「应收车辆保证金总和」+「实收服务费总和」+「氢费预付款实收金额」-「减免费用总和」「服务费各项减免费用总和」\n 2.3.开票金额:「实收车辆月租金总和」+「实收服务费总和」-「减免费用总和」「服务费各项减免费用总和」\n\n#显示该账单对应车辆列表及相关费用信息,显示以下字段;\n 2.3.序号:与租赁合同及交车任务中该车辆序号一致;\n 2.4.品牌:与租赁合同及交车任务中该车辆品牌一致;\n 2.5.型号:与租赁合同及交车任务中该车辆型号一致;\n 2.6.车牌号:与租赁合同及交车任务中该车辆车牌号一致;\n 2.7.应收车辆月租金:与租赁合同中该车辆车辆月租金一致,格式为:xx.xx元;\n 2.8.实收车辆月租金:输入框,2位小数,后缀为元,默认为与应收车辆月租金一致;\n 2.9.车辆租金备注:输入框,支持自定义输入;\n 2.10.减免金额:输入框,2位小数,后缀为元,默认为0.00元;\n 2.11.减免金额备注:输入框,支持自定义输入;\n 2.12.减免证明:附件上传按钮,点击支持多文件上传,已上传文件一行显示一条,支持点击预览,格式支持各类图片、doc、docx、pdf等格式;\n 2.13.应收车辆保证金:首期与合同中车辆保证金一致,第二期开始为0.00,格式为:xx.xx元;\n 2.14.服务费项目:点击管理,弹出气泡卡片,气泡卡片标题为服务费项目,下方为列表,显示服务项目、应收费用、实收费用、备注;\n 2.14.1.服务项目:显示租赁合同中所有服务项目名称;\n 2.14.2.应收费用:显示租赁合同中所有服务项目对应费用,格式为:xx.xx元;\n 2.14.3.实收费用:必填项,输入框,默认反写应收费用,支持修改,由业务员自行输入实收费用金额,精确至2位小数,后缀为元,默认与应收费用一致;\n 2.14.4.减免费用:选填项,输入框,默认为:0.00,精确至2位小数,后缀为元;\n 2.14.4.备注:选填项,输入框,由业务员自行输入备注信息;\n 2.15.应收服务费:显示当前车辆所有服务费应收费用总和,格式为:xx.xx元;\n 2.16.实收服务费:显示当前车辆所有服务费实收费用总和,格式为:xx.xx元;\n#列表下方为氢费预付款情况,首期账单显示,第二期账单开始无此区域内容显示;\n 2.17.氢费预付款应收金额:显示合同中氢费预付款金额;\n 2.18.氢费预付款实收金额:输入框,2位小数,后缀为元,默认与氢费预付款应收金额一致;\n 2.19.减免金额:输入框,2位小数,后缀为元;\n 2.20.减免金额备注:输入框,支持自定义输入;\n\n3.下方为提交审核、保存、取消按钮\n 3.1.提交审核:点击提交审核按钮,进入审核流程;\n 3.2.保存:点击保存按钮,保存当前表单已填数据,不做校验;\n';
|
||||
|
||||
return React.createElement('div', { style: layoutStyle },
|
||||
React.createElement('div', { style: { marginBottom: 16, display: 'flex', alignItems: 'center', justifyContent: 'space-between' } },
|
||||
React.createElement(Breadcrumb, {
|
||||
items: [
|
||||
{ title: '业务管理' },
|
||||
{ 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: formRowStyle },
|
||||
React.createElement('div', { style: formItemStyle },
|
||||
React.createElement('div', { style: labelStyle }, '合同编码'),
|
||||
React.createElement('div', { style: valueStyle }, billInfo.contractCode || '—')
|
||||
),
|
||||
React.createElement('div', { style: formItemStyle },
|
||||
React.createElement('div', { style: labelStyle }, '合同类型'),
|
||||
React.createElement('div', { style: valueStyle }, billInfo.contractType || '—')
|
||||
),
|
||||
React.createElement('div', { style: formItemStyle },
|
||||
React.createElement('div', { style: labelStyle }, '项目名称'),
|
||||
React.createElement('div', { style: valueStyle }, billInfo.projectName || '—')
|
||||
),
|
||||
React.createElement('div', { style: formItemStyle },
|
||||
React.createElement('div', { style: labelStyle }, '客户名称'),
|
||||
React.createElement('div', { style: valueStyle }, billInfo.customerName || '—')
|
||||
),
|
||||
React.createElement('div', { style: formItemStyle },
|
||||
React.createElement('div', { style: labelStyle }, '交车任务编码'),
|
||||
React.createElement('div', { style: valueStyle }, billInfo.deliveryTaskCode || '—')
|
||||
),
|
||||
React.createElement('div', { style: formItemStyle },
|
||||
React.createElement('div', { style: labelStyle }, '账单编码'),
|
||||
React.createElement('div', { style: valueStyle }, billInfo.billCode || '—')
|
||||
),
|
||||
React.createElement('div', { style: formItemStyle },
|
||||
React.createElement('div', { style: labelStyle }, '账单期数'),
|
||||
React.createElement('div', { style: valueStyle }, billInfo.period != null ? billInfo.period : '—')
|
||||
),
|
||||
React.createElement('div', { style: formItemStyle },
|
||||
React.createElement('div', { style: labelStyle }, '账单开始日期'),
|
||||
React.createElement('div', { style: valueStyle }, billInfo.billStartDate || '—')
|
||||
),
|
||||
React.createElement('div', { style: formItemStyle },
|
||||
React.createElement('div', { style: labelStyle }, '账单结束日期'),
|
||||
React.createElement('div', { style: valueStyle }, billInfo.billEndDate || '—')
|
||||
)
|
||||
)
|
||||
),
|
||||
React.createElement(Card, { title: '账单明细', style: cardStyle },
|
||||
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('span', { style: { cursor: 'default' } }, '开票金额:', React.createElement('span', { style: highlightStyle }, invoiceTotal, ' 元'))
|
||||
),
|
||||
React.createElement('div', { style: { overflowX: 'auto', marginBottom: 16 } },
|
||||
React.createElement('table', { style: { width: '100%', minWidth: 1600, borderCollapse: 'collapse', fontSize: 13, tableLayout: 'fixed' } },
|
||||
React.createElement('thead', null,
|
||||
React.createElement('tr', { style: { backgroundColor: '#fafafa' } },
|
||||
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: 130 }) }, '实收车辆月租金'),
|
||||
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, { width: 120 }) }, '减免金额备注'),
|
||||
React.createElement('th', { style: Object.assign({}, thBase, { width: 130 }) }, '减免证明'),
|
||||
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: 90 }) }, '实收服务费')
|
||||
)
|
||||
),
|
||||
React.createElement('tbody', null,
|
||||
vehicles.map(function (row) {
|
||||
var servicePopover = React.createElement('div', { style: { padding: 8, minWidth: 360 } },
|
||||
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('span', null, React.createElement('span', { style: requiredStar }, '*'), '实收费用')),
|
||||
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: { padding: '6px 8px' } },
|
||||
React.createElement(Input, { size: 'small', value: s.actual, suffix: '元', onChange: function (e) { updateServiceItem(row.key, si, 'actual', e.target.value); } })
|
||||
),
|
||||
React.createElement('td', { style: { padding: '6px 8px' } },
|
||||
React.createElement(Input, { size: 'small', value: s.discount, suffix: '元', onChange: function (e) { updateServiceItem(row.key, si, 'discount', e.target.value); } })
|
||||
),
|
||||
React.createElement('td', { style: { padding: '6px 8px' } },
|
||||
React.createElement(Input, { size: 'small', value: s.remark, placeholder: '备注', onChange: function (e) { updateServiceItem(row.key, si, 'remark', e.target.value); } })
|
||||
)
|
||||
);
|
||||
})
|
||||
)
|
||||
)
|
||||
);
|
||||
var proofList = row.discountProof || [];
|
||||
var onProofUpload = function (e) {
|
||||
var files = e.target.files;
|
||||
if (!files || !files.length) return;
|
||||
var next = proofList.slice();
|
||||
for (var i = 0; i < files.length; i++) { next.push({ name: files[i].name }); }
|
||||
updateVehicle(row.key, 'discountProof', next);
|
||||
e.target.value = '';
|
||||
};
|
||||
var removeProof = function (idx) {
|
||||
var next = (row.discountProof || []).slice();
|
||||
next.splice(idx, 1);
|
||||
updateVehicle(row.key, 'discountProof', next);
|
||||
};
|
||||
var depositDisplay = isFirstPeriod ? (row.receivableDeposit || 0) : '0.00';
|
||||
return React.createElement('tr', { key: row.key },
|
||||
React.createElement('td', { style: { padding: '8px 12px', border: '1px solid #f0f0f0' } }, row.index),
|
||||
React.createElement('td', { style: { padding: '8px 12px', border: '1px solid #f0f0f0' } }, row.brand),
|
||||
React.createElement('td', { style: { padding: '8px 12px', border: '1px solid #f0f0f0' } }, row.model),
|
||||
React.createElement('td', { style: { padding: '8px 12px', border: '1px solid #f0f0f0' } }, row.plateNo || '—'),
|
||||
React.createElement('td', { style: { padding: '8px 12px', border: '1px solid #f0f0f0', textAlign: 'right' } }, (row.receivableRent != null ? row.receivableRent : 0) + ' 元'),
|
||||
React.createElement('td', { style: { padding: '8px 12px', border: '1px solid #f0f0f0' } },
|
||||
React.createElement(Input, { size: 'small', value: row.actualRent, suffix: '元', onChange: function (e) { updateVehicle(row.key, 'actualRent', e.target.value); } })
|
||||
),
|
||||
React.createElement('td', { style: { padding: '8px 12px', border: '1px solid #f0f0f0' } },
|
||||
React.createElement(Input, { size: 'small', value: row.rentRemark, onChange: function (e) { updateVehicle(row.key, 'rentRemark', e.target.value); } })
|
||||
),
|
||||
React.createElement('td', { style: { padding: '8px 12px', border: '1px solid #f0f0f0' } },
|
||||
React.createElement(Input, { size: 'small', value: row.discountAmount, suffix: '元', onChange: function (e) { updateVehicle(row.key, 'discountAmount', e.target.value); } })
|
||||
),
|
||||
React.createElement('td', { style: { padding: '8px 12px', border: '1px solid #f0f0f0' } },
|
||||
React.createElement(Input, { size: 'small', value: row.discountRemark, onChange: function (e) { updateVehicle(row.key, 'discountRemark', e.target.value); } })
|
||||
),
|
||||
React.createElement('td', { style: { padding: '8px 12px', border: '1px solid #f0f0f0' } },
|
||||
React.createElement('div', { style: { display: 'flex', flexDirection: 'column', gap: 4, fontSize: 12 } },
|
||||
proofList.map(function (p, pidx) {
|
||||
return React.createElement('div', { key: pidx, style: { display: 'flex', alignItems: 'center', gap: 4 } },
|
||||
React.createElement(Button, { type: 'link', size: 'small', style: { padding: 0, height: 'auto' }, onClick: function () { message.info('预览:' + (p.name || '附件')); } }, p.name || '附件'),
|
||||
React.createElement(Button, { type: 'link', size: 'small', danger: true, style: { padding: 0, minWidth: 'auto' }, onClick: function () { removeProof(pidx); } }, '删除')
|
||||
);
|
||||
}),
|
||||
React.createElement('span', null,
|
||||
React.createElement('input', { type: 'file', multiple: true, accept: '.jpg,.jpeg,.png,.pdf,.doc,.docx', style: { display: 'none' }, id: 'proof-' + row.key, onChange: onProofUpload }),
|
||||
React.createElement(Button, { type: 'default', size: 'small', onClick: function () { var el = document.getElementById('proof-' + row.key); if (el) el.click(); } }, '附件上传')
|
||||
)
|
||||
)
|
||||
),
|
||||
React.createElement('td', { style: { padding: '8px 12px', border: '1px solid #f0f0f0', textAlign: 'right' } }, (depositDisplay !== undefined && depositDisplay !== null ? depositDisplay : '0.00') + ' 元'),
|
||||
React.createElement('td', { style: { padding: '8px 12px', border: '1px solid #f0f0f0' } },
|
||||
React.createElement(Popover, {
|
||||
content: servicePopover,
|
||||
title: null,
|
||||
trigger: 'click',
|
||||
open: activeServiceIndex === row.key,
|
||||
onOpenChange: function (open) { setServicePopoverRowIndex(open ? row.key : null); }
|
||||
},
|
||||
React.createElement(Button, { type: 'link', size: 'small' }, '管理')
|
||||
)
|
||||
),
|
||||
React.createElement('td', { style: { padding: '8px 12px', border: '1px solid #f0f0f0', textAlign: 'right' } }, (row.receivableService != null ? row.receivableService : '0.00') + ' 元'),
|
||||
React.createElement('td', { style: { padding: '8px 12px', border: '1px solid #f0f0f0', textAlign: 'right' } }, (row.actualService || '0.00') + ' 元')
|
||||
);
|
||||
})
|
||||
)
|
||||
)
|
||||
),
|
||||
isFirstPeriod ? React.createElement('div', { style: { marginTop: 16 } },
|
||||
React.createElement('div', { style: { fontSize: 14, fontWeight: 500, marginBottom: 8 } }, '氢费预付款情况'),
|
||||
React.createElement('div', { style: { display: 'grid', gridTemplateColumns: '1fr 1fr 1fr 1fr', gap: 16, maxWidth: 800 } },
|
||||
React.createElement('div', { style: formItemStyle },
|
||||
React.createElement('div', { style: labelStyle }, '氢费预付款应收金额'),
|
||||
React.createElement(Input, { value: hydrogen.receivable + ' 元', disabled: true })
|
||||
),
|
||||
React.createElement('div', { style: formItemStyle },
|
||||
React.createElement('div', { style: labelStyle }, '氢费预付款实收金额'),
|
||||
React.createElement(Input, { value: hydrogen.actual, suffix: '元', onChange: function (e) { setHydrogen(function (p) { return Object.assign({}, p, { actual: e.target.value }); }); } })
|
||||
),
|
||||
React.createElement('div', { style: formItemStyle },
|
||||
React.createElement('div', { style: labelStyle }, '减免金额'),
|
||||
React.createElement(Input, { value: hydrogen.discount, suffix: '元', onChange: function (e) { setHydrogen(function (p) { return Object.assign({}, p, { discount: e.target.value }); }); } })
|
||||
),
|
||||
React.createElement('div', { style: formItemStyle },
|
||||
React.createElement('div', { style: labelStyle }, '减免金额备注'),
|
||||
React.createElement(Input, { value: hydrogen.discountRemark, onChange: function (e) { setHydrogen(function (p) { return Object.assign({}, p, { discountRemark: e.target.value }); }); } })
|
||||
)
|
||||
)
|
||||
) : null
|
||||
),
|
||||
React.createElement('div', { style: { display: 'flex', gap: 8, marginTop: 24 } },
|
||||
React.createElement(Button, { type: 'primary', onClick: handleSubmit }, '提交'),
|
||||
React.createElement(Button, { onClick: handleSave }, '保存'),
|
||||
React.createElement(Button, { onClick: handleCancel }, '取消')
|
||||
),
|
||||
React.createElement(Modal, {
|
||||
title: '确认',
|
||||
open: submitConfirmVisible[0],
|
||||
onCancel: function () { submitConfirmVisible[1](false); },
|
||||
onOk: handleSubmitConfirm,
|
||||
okText: '确认',
|
||||
cancelText: '取消'
|
||||
}, '请确认账单金额无误'),
|
||||
React.createElement(Modal, {
|
||||
title: '确认取消',
|
||||
open: cancelConfirmVisible[0],
|
||||
onCancel: function () { cancelConfirmVisible[1](false); },
|
||||
onOk: handleCancelConfirm,
|
||||
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)
|
||||
))
|
||||
);
|
||||
};
|
||||
345
web端/业务管理/租赁账单-查看.jsx
Normal file
345
web端/业务管理/租赁账单-查看.jsx
Normal file
@@ -0,0 +1,345 @@
|
||||
// 【重要】必须使用 const Component 作为组件变量名
|
||||
// 租赁账单-查看(2026年3月11日版本)
|
||||
|
||||
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 Table = antd.Table;
|
||||
var Modal = antd.Modal;
|
||||
var message = antd.message;
|
||||
|
||||
var requirementModalVisible = useState(false);
|
||||
var servicePopoverRowIndex = useState(null);
|
||||
|
||||
// 模拟:当前账单信息(由路由/接口传入)
|
||||
var billInfo = useMemo(function () {
|
||||
return {
|
||||
contractCode: 'HT-ZL-2025-001',
|
||||
contractType: '正式合同',
|
||||
projectName: '嘉兴氢能示范项目',
|
||||
customerName: '嘉兴某某物流有限公司',
|
||||
deliveryTaskCode: 'JT-2025-001-A',
|
||||
billCode: 'HT-ZL-2025-0010001',
|
||||
period: 1,
|
||||
billStartDate: '2025-01-01',
|
||||
billEndDate: '2025-01-31'
|
||||
};
|
||||
}, []);
|
||||
|
||||
var isFirstPeriod = billInfo.period === 1;
|
||||
|
||||
// 车辆明细(只读展示)
|
||||
var vehicles = useMemo(function () {
|
||||
return [
|
||||
{ key: 'v1', index: 1, brand: '东风', model: 'DFH1180', plateNo: '浙A12345', receivableRent: 30000, actualRent: '29800.00', rentRemark: '首期六期一次性付清', discountAmount: '200.00', discountRemark: '首月优惠', discountProof: [{ name: '优惠审批单.pdf' }], 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' },
|
||||
{ key: 'v2', index: 2, brand: '福田', model: 'BJ1180', plateNo: '浙A23456', receivableRent: 27000, actualRent: '27000.00', rentRemark: '', discountAmount: '0.00', discountRemark: '', discountProof: [], receivableDeposit: 8000, serviceItems: [{ name: '保养费用', receivable: 300, actual: '300.00', discount: '0.00', remark: '含首保' }], receivableService: 300, actualService: '300.00' },
|
||||
{ key: 'v3', index: 3, brand: '重汽', model: 'ZZ1187', plateNo: '浙A34567', receivableRent: 31200, actualRent: '31200.00', rentRemark: '', discountAmount: '0.00', discountRemark: '', discountProof: [], 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' }
|
||||
];
|
||||
}, []);
|
||||
|
||||
var hydrogen = useMemo(function () {
|
||||
return { receivable: '3580.00', actual: '3500.00', discount: '80.00', discountRemark: '预付款批量减免' };
|
||||
}, []);
|
||||
|
||||
var totals = useMemo(function () {
|
||||
var receivableRent = 0, actualRent = 0, receivableDeposit = 0, receivableService = 0, actualService = 0, discountTotal = 0, serviceDiscountTotal = 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;
|
||||
(v.serviceItems || []).forEach(function (s) { serviceDiscountTotal += parseFloat(s.discount) || 0; });
|
||||
});
|
||||
var hydrogenReceivable = parseFloat(hydrogen.receivable) || 0;
|
||||
var hydrogenActual = parseFloat(hydrogen.actual) || 0;
|
||||
var hydrogenDiscount = parseFloat(hydrogen.discount) || 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),
|
||||
serviceDiscountTotal: serviceDiscountTotal.toFixed(2),
|
||||
hydrogenReceivable: hydrogenReceivable.toFixed(2),
|
||||
hydrogenActual: hydrogenActual.toFixed(2),
|
||||
hydrogenDiscount: hydrogenDiscount.toFixed(2)
|
||||
};
|
||||
}, [vehicles, hydrogen]);
|
||||
|
||||
var receivableTotal = useMemo(function () {
|
||||
return (parseFloat(totals.receivableRent) + parseFloat(totals.receivableDeposit) + parseFloat(totals.receivableService) + (isFirstPeriod ? parseFloat(totals.hydrogenReceivable) : 0)).toFixed(2);
|
||||
}, [totals, isFirstPeriod]);
|
||||
|
||||
var actualTotal = useMemo(function () {
|
||||
var base = parseFloat(totals.actualRent) + parseFloat(totals.receivableDeposit) + parseFloat(totals.actualService) - parseFloat(totals.discountTotal) - parseFloat(totals.serviceDiscountTotal);
|
||||
if (isFirstPeriod) base += parseFloat(totals.hydrogenActual) - parseFloat(totals.hydrogenDiscount);
|
||||
return base.toFixed(2);
|
||||
}, [totals, isFirstPeriod]);
|
||||
|
||||
var invoiceTotal = useMemo(function () {
|
||||
// 开票总额:同“实收款总额”展示格式,但不包含应收车辆保证金
|
||||
var base = parseFloat(totals.actualRent) + parseFloat(totals.actualService) - parseFloat(totals.discountTotal) - parseFloat(totals.serviceDiscountTotal);
|
||||
if (isFirstPeriod) base += parseFloat(totals.hydrogenActual) - parseFloat(totals.hydrogenDiscount);
|
||||
return base.toFixed(2);
|
||||
}, [totals, isFirstPeriod]);
|
||||
|
||||
var receivablePopoverContent = useMemo(function () {
|
||||
var rows = [
|
||||
['总计应收车辆月租金', totals.receivableRent + ' 元'],
|
||||
['总计应收车辆保证金', totals.receivableDeposit + ' 元'],
|
||||
['总计应收服务费', totals.receivableService + ' 元']
|
||||
];
|
||||
if (isFirstPeriod) rows.push(['氢费预付款应收金额', totals.hydrogenReceivable + ' 元']);
|
||||
return 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,
|
||||
rows.map(function (r, i) { return React.createElement('tr', { key: i }, React.createElement('td', { style: { padding: '6px 8px' } }, r[0]), React.createElement('td', { style: { textAlign: 'right', padding: '6px 8px' } }, r[1])); })
|
||||
)
|
||||
)
|
||||
);
|
||||
}, [totals, isFirstPeriod]);
|
||||
|
||||
var actualPopoverContent = useMemo(function () {
|
||||
var rows = [
|
||||
['总计实收车辆月租金', totals.actualRent + ' 元'],
|
||||
['总计应收车辆保证金', totals.receivableDeposit + ' 元'],
|
||||
['总计实收服务费', totals.actualService + ' 元'],
|
||||
['总计减免金额', totals.discountTotal + ' 元'],
|
||||
['服务费各项减免费用总和', totals.serviceDiscountTotal + ' 元']
|
||||
];
|
||||
if (isFirstPeriod) {
|
||||
rows.push(['氢费预付款实收金额', totals.hydrogenActual + ' 元']);
|
||||
rows.push(['氢费预付款减免金额', totals.hydrogenDiscount + ' 元']);
|
||||
}
|
||||
return React.createElement('div', { style: { padding: 8, minWidth: 240 } },
|
||||
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,
|
||||
rows.map(function (r, i) { return React.createElement('tr', { key: i }, React.createElement('td', { style: { padding: '6px 8px' } }, r[0]), React.createElement('td', { style: { textAlign: 'right', padding: '6px 8px' } }, r[1])); })
|
||||
)
|
||||
)
|
||||
);
|
||||
}, [totals, isFirstPeriod]);
|
||||
|
||||
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 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' };
|
||||
var highlightStyle = { color: '#1890ff', fontWeight: 600, cursor: 'pointer' };
|
||||
|
||||
var activeServiceIndex = servicePopoverRowIndex[0];
|
||||
var setServicePopoverRowIndex = servicePopoverRowIndex[1];
|
||||
|
||||
function handleBack() {
|
||||
if (window.__billViewBack) window.__billViewBack();
|
||||
else message.info('返回租赁账单列表(原型)');
|
||||
}
|
||||
|
||||
var requirementContent = '租赁账单-查看(2026年3月11日版本)\n一个「数字化资产ONEOS运管平台」中的「租赁账单」「查看」模块\n#面包屑:业务管理-租赁账单-收费明细;\n1.账单信息:\n#显示该账单对应合同及账单信息,显示以下字段:\n 1.1.合同编码:显示该账单对应合同编码;\n 1.2.合同类型:显示该账单对应合同类型,包括正式合同、试用合同;\n 1.3.项目名称:显示该账单对应合同中项目名称;\n 1.4.客户名称:显示该账单对应合同中客户名称;\n 1.5.交车任务编码:显示交车任务对应编码;\n 1.6.账单编码:显示该账单编码,账单编码规则为:[合同编码][账单编号]组成,主要用于后期与用友YS系统打通时获取财务收款及发票相关数据;\n 前缀为合同编码,后缀为账单编号,规则为:ZD+4位编号,为该合同下第x份账单,例如:ZD0001为该合同下第1份账单,依次类推;\n 例如:JXZL20260216YW101235AZD0001即为JXZL20260216YW101235A合同下第1份账单;\n 1.7.账单期数:显示该账单期数;\n 1.8.账单开始日期:显示账单开始日期,根据租赁合同及交车任务开始计费日期按规则生成,格式为:YYYY-MM-DD;\n 1.9.账单结束日期:显示账单结束日期,根据租赁合同及交车任务开始计费日期按规则生成,格式为:YYYY-MM-DD;\n2.账单明细:\n#顶部显示应收款总额、实收款总额;\n 2.1.应收款总额:「应收车辆月租金总和」+「应收车辆保证金总和」+「应收服务费总和」+「氢费预付款应收金额」\n 2.2.实收款总额:「实收车辆月租金总和」+「应收车辆保证金总和」+「实收服务费总和」+「氢费预付款实收金额」-「减免费用总和」「服务费各项减免费用总和」\n\n#显示该账单对应车辆列表及相关费用信息,显示以下字段;\n 2.3.序号:与租赁合同及交车任务中该车辆序号一致;\n 2.4.品牌:与租赁合同及交车任务中该车辆品牌一致;\n 2.5.型号:与租赁合同及交车任务中该车辆型号一致;\n 2.6.车牌号:与租赁合同及交车任务中该车辆车牌号一致;\n 2.7.应收车辆月租金:与租赁合同中该车辆车辆月租金一致,格式为:xx.xx元;\n 2.8.实收车辆月租金:与收费明细中实收车辆月租金一致,格式为:xx.xx元;\n 2.9.车辆租金备注:显示收费明细中已填写备注信息;\n 2.10.减免金额:显示收费明细中已填写减免金额;\n 2.11.减免金额备注:显示收费明细中减免金额备注信息;\n 2.12.减免证明:显示已上传减免证明文件,已上传文件一行显示一条,支持点击预览,格式支持各类图片、doc、docx、pdf等格式;\n 2.13.应收车辆保证金:首期与合同中车辆保证金一致,第二期开始为0.00,格式为:xx.xx元;\n 2.14.服务费项目:点击管理,弹出气泡卡片,气泡卡片标题为服务费项目,下方为列表,显示服务项目、应收费用、实收费用、备注;\n 2.14.1.服务项目:显示租赁合同中所有服务项目名称;\n 2.14.2.应收费用:显示租赁合同中所有服务项目对应费用,格式为:xx.xx元;\n 2.14.3.实收费用:显示收费明细中填写的实收费用金额,精确至2位小数,后缀为元,默认与应收费用一致;\n 2.14.4.减免费用:显示收费明细中填写的减免费用金额,精确至2位小数,后缀为元;\n 2.14.4.备注:显示收费明细中填写的备注信息;\n 2.15.应收服务费:显示当前车辆所有服务费应收费用总和,格式为:xx.xx元;\n 2.16.实收服务费:显示当前车辆所有服务费实收费用总和,格式为:xx.xx元;\n#列表下方为氢费预付款情况,首期账单显示,第二期账单开始无此区域内容显示;\n 2.17.氢费预付款应收金额:显示合同中氢费预付款金额;\n 2.18.氢费预付款实收金额:显示收费明细中填写的氢费预付款实收金额,格式为:xx.xx元;\n 2.19.减免金额:显示收费明细中填写的减免金额,格式为:xx.xx元;\n 2.20.减免金额备注:显示收费明细中填写的减免金额备注信息;\n\n3.下方为返回按钮\n 3.1.返回:点击返回按钮,返回租赁账单列表页面;\n';
|
||||
|
||||
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: '租赁账单' },
|
||||
{ title: '查看' }
|
||||
]
|
||||
}),
|
||||
React.createElement(Button, { type: 'link', style: { padding: 0 }, onClick: function () { requirementModalVisible[1](true); } }, '查看需求说明')
|
||||
),
|
||||
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 }, billInfo.contractCode || '—')
|
||||
),
|
||||
React.createElement('div', { style: formItemStyle },
|
||||
React.createElement('div', { style: labelStyle }, '合同类型'),
|
||||
React.createElement('div', { style: valueStyle }, billInfo.contractType || '—')
|
||||
),
|
||||
React.createElement('div', { style: formItemStyle },
|
||||
React.createElement('div', { style: labelStyle }, '项目名称'),
|
||||
React.createElement('div', { style: valueStyle }, billInfo.projectName || '—')
|
||||
),
|
||||
React.createElement('div', { style: formItemStyle },
|
||||
React.createElement('div', { style: labelStyle }, '客户名称'),
|
||||
React.createElement('div', { style: valueStyle }, billInfo.customerName || '—')
|
||||
),
|
||||
React.createElement('div', { style: formItemStyle },
|
||||
React.createElement('div', { style: labelStyle }, '交车任务编码'),
|
||||
React.createElement('div', { style: valueStyle }, billInfo.deliveryTaskCode || '—')
|
||||
),
|
||||
React.createElement('div', { style: formItemStyle },
|
||||
React.createElement('div', { style: labelStyle }, '账单编码'),
|
||||
React.createElement('div', { style: valueStyle }, billInfo.billCode || '—')
|
||||
),
|
||||
React.createElement('div', { style: formItemStyle },
|
||||
React.createElement('div', { style: labelStyle }, '账单期数'),
|
||||
React.createElement('div', { style: valueStyle }, billInfo.period != null ? billInfo.period : '—')
|
||||
),
|
||||
React.createElement('div', { style: formItemStyle },
|
||||
React.createElement('div', { style: labelStyle }, '账单开始日期'),
|
||||
React.createElement('div', { style: valueStyle }, billInfo.billStartDate || '—')
|
||||
),
|
||||
React.createElement('div', { style: formItemStyle },
|
||||
React.createElement('div', { style: labelStyle }, '账单结束日期'),
|
||||
React.createElement('div', { style: valueStyle }, billInfo.billEndDate || '—')
|
||||
)
|
||||
)
|
||||
),
|
||||
React.createElement(Card, { title: '账单明细', style: cardStyle },
|
||||
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('span', { style: { cursor: 'default' } }, '开票总额:', React.createElement('span', { style: highlightStyle }, invoiceTotal, ' 元'))
|
||||
),
|
||||
React.createElement('div', { style: { overflowX: 'auto', marginBottom: 16 } },
|
||||
React.createElement('table', { style: { width: '100%', minWidth: 1500, borderCollapse: 'collapse', fontSize: 13, tableLayout: 'fixed' } },
|
||||
React.createElement('thead', null,
|
||||
React.createElement('tr', { style: { backgroundColor: '#fafafa' } },
|
||||
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: 110 }) }, '应收车辆月租金'),
|
||||
React.createElement('th', { style: Object.assign({}, thBase, { textAlign: 'right', width: 110 }) }, '实收车辆月租金'),
|
||||
React.createElement('th', { style: Object.assign({}, thBase, { width: 110 }) }, '车辆租金备注'),
|
||||
React.createElement('th', { style: Object.assign({}, thBase, { textAlign: 'right', width: 90 }) }, '减免金额'),
|
||||
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, { 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: 90 }) }, '实收服务费')
|
||||
)
|
||||
),
|
||||
React.createElement('tbody', null,
|
||||
vehicles.map(function (row) {
|
||||
var servicePopover = React.createElement('div', { style: { padding: 8, minWidth: 340 } },
|
||||
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 proofList = row.discountProof || [];
|
||||
var depositDisplay = isFirstPeriod ? (row.receivableDeposit || 0) : '0.00';
|
||||
return React.createElement('tr', { key: row.key },
|
||||
React.createElement('td', { style: { padding: '8px 12px', border: '1px solid #f0f0f0' } }, row.index),
|
||||
React.createElement('td', { style: { padding: '8px 12px', border: '1px solid #f0f0f0' } }, row.brand),
|
||||
React.createElement('td', { style: { padding: '8px 12px', border: '1px solid #f0f0f0' } }, row.model),
|
||||
React.createElement('td', { style: { padding: '8px 12px', border: '1px solid #f0f0f0' } }, row.plateNo || '—'),
|
||||
React.createElement('td', { style: { padding: '8px 12px', border: '1px solid #f0f0f0', textAlign: 'right' } }, (row.receivableRent != null ? row.receivableRent : 0) + ' 元'),
|
||||
React.createElement('td', { style: { padding: '8px 12px', border: '1px solid #f0f0f0', textAlign: 'right' } }, (row.actualRent || '0.00') + ' 元'),
|
||||
React.createElement('td', { style: { padding: '8px 12px', border: '1px solid #f0f0f0' } }, row.rentRemark || '—'),
|
||||
React.createElement('td', { style: { padding: '8px 12px', border: '1px solid #f0f0f0', textAlign: 'right' } }, (row.discountAmount || '0.00') + ' 元'),
|
||||
React.createElement('td', { style: { padding: '8px 12px', border: '1px solid #f0f0f0' } }, row.discountRemark || '—'),
|
||||
React.createElement('td', { style: { padding: '8px 12px', border: '1px solid #f0f0f0' } },
|
||||
proofList.length === 0 ? '—' : React.createElement('div', { style: { display: 'flex', flexDirection: 'column', gap: 2, fontSize: 12 } },
|
||||
proofList.map(function (p, pidx) {
|
||||
return React.createElement(Button, { key: pidx, type: 'link', size: 'small', style: { padding: 0, height: 'auto', textAlign: 'left' }, onClick: function () { message.info('预览:' + (p.name || '附件')); } }, p.name || '附件');
|
||||
})
|
||||
)
|
||||
),
|
||||
React.createElement('td', { style: { padding: '8px 12px', border: '1px solid #f0f0f0', textAlign: 'right' } }, (depositDisplay !== undefined && depositDisplay !== null ? depositDisplay : '0.00') + ' 元'),
|
||||
React.createElement('td', { style: { padding: '8px 12px', border: '1px solid #f0f0f0' } },
|
||||
React.createElement(Popover, {
|
||||
content: servicePopover,
|
||||
title: null,
|
||||
trigger: 'click',
|
||||
open: activeServiceIndex === row.key,
|
||||
onOpenChange: function (open) { setServicePopoverRowIndex(open ? row.key : null); }
|
||||
},
|
||||
React.createElement(Button, { type: 'link', size: 'small' }, '管理')
|
||||
)
|
||||
),
|
||||
React.createElement('td', { style: { padding: '8px 12px', border: '1px solid #f0f0f0', textAlign: 'right' } }, (row.receivableService != null ? row.receivableService : '0.00') + ' 元'),
|
||||
React.createElement('td', { style: { padding: '8px 12px', border: '1px solid #f0f0f0', textAlign: 'right' } }, (row.actualService || '0.00') + ' 元')
|
||||
);
|
||||
})
|
||||
)
|
||||
)
|
||||
),
|
||||
isFirstPeriod ? React.createElement('div', { style: { marginTop: 16 } },
|
||||
React.createElement('div', { style: { fontSize: 14, fontWeight: 500, marginBottom: 8 } }, '氢费预付款情况'),
|
||||
React.createElement('div', { style: { 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 }, hydrogen.receivable + ' 元')
|
||||
),
|
||||
React.createElement('div', { style: formItemStyle },
|
||||
React.createElement('div', { style: labelStyle }, '氢费预付款实收金额'),
|
||||
React.createElement('div', { style: valueStyle }, hydrogen.actual + ' 元')
|
||||
),
|
||||
React.createElement('div', { style: formItemStyle },
|
||||
React.createElement('div', { style: labelStyle }, '减免金额'),
|
||||
React.createElement('div', { style: valueStyle }, hydrogen.discount + ' 元')
|
||||
),
|
||||
React.createElement('div', { style: formItemStyle },
|
||||
React.createElement('div', { style: labelStyle }, '减免金额备注'),
|
||||
React.createElement('div', { style: valueStyle }, hydrogen.discountRemark || '—')
|
||||
)
|
||||
)
|
||||
) : null
|
||||
),
|
||||
React.createElement('div', { style: { marginTop: 24 } },
|
||||
React.createElement(Button, { onClick: handleBack }, '返回')
|
||||
),
|
||||
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))
|
||||
)
|
||||
);
|
||||
};
|
||||
@@ -14,8 +14,10 @@ const Component = function () {
|
||||
var Input = antd.Input;
|
||||
var Space = antd.Space;
|
||||
var Popover = antd.Popover;
|
||||
var Modal = antd.Modal;
|
||||
var message = antd.message;
|
||||
|
||||
var requirementModalVisible = useState(false);
|
||||
var filterContractCode = useState(undefined);
|
||||
var filterProjectName = useState(undefined);
|
||||
var filterCustomerName = useState(undefined);
|
||||
@@ -25,6 +27,15 @@ const Component = function () {
|
||||
var filterExpanded = useState(false);
|
||||
var expandedRowKeysState = useState([]);
|
||||
var deliveryPopoverOpen = useState(null);
|
||||
var costEditsState = useState({});
|
||||
var costEdits = costEditsState[0];
|
||||
var setCostEdits = costEditsState[1];
|
||||
var editingCostState = useState(null); // { key, field }
|
||||
var editingCost = editingCostState[0];
|
||||
var setEditingCost = editingCostState[1];
|
||||
var editingCostValueState = useState('');
|
||||
var editingCostValue = editingCostValueState[0];
|
||||
var setEditingCostValue = editingCostValueState[1];
|
||||
var expandedRowKeys = expandedRowKeysState[0];
|
||||
var setExpandedRowKeys = expandedRowKeysState[1];
|
||||
|
||||
@@ -40,9 +51,9 @@ const Component = function () {
|
||||
businessDept: '业务1部',
|
||||
businessPerson: '张经理',
|
||||
children: [
|
||||
{ period: 1, billStartDate: '2025-01-01', billEndDate: '2025-01-31', deliveryCount: 3, deliveryVehicles: [{ brand: '东风', model: 'DFH1180', plateNo: '浙A12345' }, { brand: '福田', model: 'BJ1180', plateNo: '浙A23456' }, { brand: '重汽', model: 'ZZ1187', plateNo: '浙A34567' }], receivableTotal: 45800.00, actualTotal: 45500.00, discountTotal: 300.00, arrivalAmount: 45500.00, isInvoiced: '已开票', invoiceAmount: 45500.00 },
|
||||
{ period: 2, billStartDate: '2025-02-01', billEndDate: '2025-02-28', deliveryCount: 2, deliveryVehicles: [{ brand: '陕汽', model: 'SX1313', plateNo: '浙A45678' }, { brand: '解放', model: 'J6P', plateNo: '浙A56789' }], receivableTotal: 45800.00, actualTotal: 45800.00, discountTotal: 0.00, arrivalAmount: 45800.00, isInvoiced: '已开票', invoiceAmount: 45800.00 },
|
||||
{ period: 3, billStartDate: '2025-03-01', billEndDate: '2025-03-31', deliveryCount: 2, deliveryVehicles: [{ brand: '江淮', model: '格尔发K5', plateNo: '浙A67890' }, { brand: '东风', model: 'DFH1250', plateNo: '浙A11111' }], receivableTotal: 45800.00, actualTotal: 45000.00, discountTotal: 800.00, arrivalAmount: 42000.00, isInvoiced: '部分开票', invoiceAmount: 42000.00 }
|
||||
{ period: 1, status: '已提交', billStartDate: '2025-01-01', billEndDate: '2025-01-31', deliveryCount: 3, deliveryVehicles: [{ brand: '东风', model: 'DFH1180', plateNo: '浙A12345' }, { brand: '福田', model: 'BJ1180', plateNo: '浙A23456' }, { brand: '重汽', model: 'ZZ1187', plateNo: '浙A34567' }], receivableTotal: 45800.00, actualTotal: 45500.00, discountTotal: 300.00, hydrogenCost: 1200.00, otherCost: 300.00 },
|
||||
{ period: 2, status: '待提交', billStartDate: '2025-02-01', billEndDate: '2025-02-28', deliveryCount: 2, deliveryVehicles: [{ brand: '陕汽', model: 'SX1313', plateNo: '浙A45678' }, { brand: '解放', model: 'J6P', plateNo: '浙A56789' }], receivableTotal: 45800.00, actualTotal: 45800.00, discountTotal: 0.00, hydrogenCost: 900.00, otherCost: 180.00 },
|
||||
{ period: 3, status: '待提交', billStartDate: '2025-03-01', billEndDate: '2025-03-31', deliveryCount: 2, deliveryVehicles: [{ brand: '江淮', model: '格尔发K5', plateNo: '浙A67890' }, { brand: '东风', model: 'DFH1250', plateNo: '浙A11111' }], receivableTotal: 45800.00, actualTotal: 45000.00, discountTotal: 800.00, hydrogenCost: 650.00, otherCost: 220.00 }
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -55,8 +66,8 @@ const Component = function () {
|
||||
businessDept: '业务2部',
|
||||
businessPerson: '李专员',
|
||||
children: [
|
||||
{ period: 1, billStartDate: '2025-02-01', billEndDate: '2025-02-28', deliveryCount: 2, deliveryVehicles: [{ brand: '江淮', model: '格尔发K5', plateNo: '沪B11111' }, { brand: '东风', model: 'DFH1250', plateNo: '沪B22222' }], receivableTotal: 33400.00, actualTotal: 33400.00, discountTotal: 0.00, arrivalAmount: 33400.00, isInvoiced: '已开票', invoiceAmount: 33400.00 },
|
||||
{ period: 2, billStartDate: '2025-03-01', billEndDate: '2025-03-31', deliveryCount: 1, deliveryVehicles: [{ brand: '解放', model: 'JH6', plateNo: '沪B33333' }], receivableTotal: 33400.00, actualTotal: 33400.00, discountTotal: 0.00, arrivalAmount: 0.00, isInvoiced: '未开票', invoiceAmount: 0.00 }
|
||||
{ period: 1, status: '已提交', billStartDate: '2025-02-01', billEndDate: '2025-02-28', deliveryCount: 2, deliveryVehicles: [{ brand: '江淮', model: '格尔发K5', plateNo: '沪B11111' }, { brand: '东风', model: 'DFH1250', plateNo: '沪B22222' }], receivableTotal: 33400.00, actualTotal: 33400.00, discountTotal: 0.00, hydrogenCost: 780.00, otherCost: 160.00 },
|
||||
{ period: 2, status: '待提交', billStartDate: '2025-03-01', billEndDate: '2025-03-31', deliveryCount: 1, deliveryVehicles: [{ brand: '解放', model: 'JH6', plateNo: '沪B33333' }], receivableTotal: 33400.00, actualTotal: 33400.00, discountTotal: 0.00, hydrogenCost: 0.00, otherCost: 0.00 }
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -69,7 +80,7 @@ const Component = function () {
|
||||
businessDept: '业务3部',
|
||||
businessPerson: '王专员',
|
||||
children: [
|
||||
{ period: 1, billStartDate: '2025-02-10', billEndDate: '2025-03-09', deliveryCount: 1, deliveryVehicles: [{ brand: '福田', model: '欧曼EST', plateNo: '浙C33333' }], receivableTotal: 41200.00, actualTotal: 41200.00, discountTotal: 0.00, arrivalAmount: 41200.00, isInvoiced: '已开票', invoiceAmount: 41200.00 }
|
||||
{ period: 1, status: '已提交', billStartDate: '2025-02-10', billEndDate: '2025-03-09', deliveryCount: 1, deliveryVehicles: [{ brand: '福田', model: '欧曼EST', plateNo: '浙C33333' }], receivableTotal: 41200.00, actualTotal: 41200.00, discountTotal: 0.00, hydrogenCost: 500.00, otherCost: 120.00 }
|
||||
]
|
||||
}
|
||||
];
|
||||
@@ -125,6 +136,92 @@ const Component = function () {
|
||||
return (isNaN(n) ? '0.00' : n.toFixed(2)) + '元';
|
||||
}
|
||||
|
||||
function pad4(n) {
|
||||
var s = String(n == null ? '' : n);
|
||||
return ('0000' + s).slice(-4);
|
||||
}
|
||||
|
||||
function calcDays(startStr, endStr) {
|
||||
if (!startStr || !endStr) return 0;
|
||||
var start = new Date(startStr + 'T00:00:00');
|
||||
var end = new Date(endStr + 'T00:00:00');
|
||||
var ms = end.getTime() - start.getTime();
|
||||
if (!isFinite(ms)) return 0;
|
||||
var days = Math.floor(ms / 86400000) + 1;
|
||||
return days < 0 ? 0 : days;
|
||||
}
|
||||
|
||||
var modelCostPerDayMap = useMemo(function () {
|
||||
return {
|
||||
'DFH1180': 120,
|
||||
'BJ1180': 95,
|
||||
'ZZ1187': 130,
|
||||
'SX1313': 110,
|
||||
'J6P': 125,
|
||||
'格尔发K5': 90,
|
||||
'DFH1250': 140,
|
||||
'JH6': 118,
|
||||
'欧曼EST': 150
|
||||
};
|
||||
}, []);
|
||||
|
||||
function calcVehicleCost(record) {
|
||||
var days = calcDays(record.billStartDate, record.billEndDate);
|
||||
var vehicles = record.deliveryVehicles || [];
|
||||
var sum = 0;
|
||||
for (var i = 0; i < vehicles.length; i++) {
|
||||
var m = vehicles[i] && vehicles[i].model;
|
||||
var costPerDay = modelCostPerDayMap[m] || 0;
|
||||
sum += costPerDay * days;
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
|
||||
function getCostKey(record) {
|
||||
var p = record._parentRecord;
|
||||
var code = (p && p.contractCode) || '';
|
||||
var period = record.period != null ? record.period : '';
|
||||
return code + '-ZD' + pad4(period);
|
||||
}
|
||||
|
||||
function renderEditableCost(field, record) {
|
||||
var key = getCostKey(record);
|
||||
var map = costEdits[key] || {};
|
||||
var v = map[field];
|
||||
if (v === undefined) v = record[field];
|
||||
var isEditing = editingCost && editingCost.key === key && editingCost.field === field;
|
||||
if (isEditing) {
|
||||
return React.createElement(Input, {
|
||||
autoFocus: true,
|
||||
value: editingCostValue,
|
||||
onChange: function (e) { setEditingCostValue(e.target.value); },
|
||||
onBlur: function () {
|
||||
var raw = (editingCostValue || '').trim();
|
||||
var num = raw === '' ? 0 : parseFloat(raw);
|
||||
var next = isNaN(num) ? 0 : Math.round(num * 100) / 100;
|
||||
setCostEdits(function (prev) {
|
||||
var p = Object.assign({}, prev || {});
|
||||
var row = Object.assign({}, p[key] || {});
|
||||
row[field] = next;
|
||||
p[key] = row;
|
||||
return p;
|
||||
});
|
||||
setEditingCost(null);
|
||||
setEditingCostValue('');
|
||||
},
|
||||
onPressEnter: function () { if (document && document.activeElement) document.activeElement.blur(); },
|
||||
suffix: '元'
|
||||
});
|
||||
}
|
||||
return React.createElement('span', {
|
||||
style: { cursor: 'pointer' },
|
||||
onClick: function () {
|
||||
setEditingCost({ key: key, field: field });
|
||||
setEditingCostValue((v == null || v === '') ? '' : String(Number(v).toFixed(2)));
|
||||
}
|
||||
}, fmtMoney(v));
|
||||
}
|
||||
|
||||
function goView(record, parent) {
|
||||
message.info('查看账单详情(原型)');
|
||||
}
|
||||
@@ -132,6 +229,15 @@ const Component = function () {
|
||||
message.info('收费明细(原型)');
|
||||
}
|
||||
|
||||
function renderSubActions(record, parentRecord) {
|
||||
var status = record && record.status;
|
||||
var isSubmitted = status === '已提交';
|
||||
return React.createElement(Space, { size: 'small' },
|
||||
React.createElement(Button, { type: 'link', size: 'small', onClick: function () { goView(record, parentRecord); } }, '查看'),
|
||||
isSubmitted ? null : React.createElement(Button, { type: 'link', size: 'small', onClick: function () { goChargeDetail(record, parentRecord); } }, '收费明细')
|
||||
);
|
||||
}
|
||||
|
||||
// 子表提车数量气泡:列表显示 品牌、型号、车牌号
|
||||
function renderDeliveryPopover(record) {
|
||||
var vehicles = record.deliveryVehicles || [];
|
||||
@@ -189,17 +295,18 @@ const Component = function () {
|
||||
];
|
||||
|
||||
var subColumns = [
|
||||
{ title: '账单编码', dataIndex: 'billNo', key: 'billNo', width: 200, ellipsis: true, render: function (v, record) { var p = record._parentRecord; var code = (p && p.contractCode) || ''; var period = record.period != null ? record.period : ''; var suffix = period !== '' ? ('0000' + period).slice(-4) : ''; return code + suffix || '—'; } },
|
||||
{ title: '账单编号', dataIndex: 'billNo', key: 'billNo', width: 220, ellipsis: true, render: function (v, record) { var p = record._parentRecord; var code = (p && p.contractCode) || ''; var period = record.period != null ? record.period : ''; return code ? (code + 'ZD' + pad4(period)) : '—'; } },
|
||||
{ title: '账单期数', dataIndex: 'period', key: 'period', width: 90, align: 'center', render: function (v) { return v != null ? v : '—'; } },
|
||||
{ title: '状态', dataIndex: 'status', key: 'status', width: 90, render: function (v) { return v || '—'; } },
|
||||
{ title: '账单开始日期', dataIndex: 'billStartDate', key: 'billStartDate', width: 120, render: function (v) { return v || '—'; } },
|
||||
{ title: '账单结束日期', dataIndex: 'billEndDate', key: 'billEndDate', width: 120, render: function (v) { return v || '—'; } },
|
||||
{ title: '提车数量', key: 'deliveryCount', width: 88, align: 'center', render: function (_, record) { return renderDeliveryPopover(record); } },
|
||||
{ title: '应收款总额', dataIndex: 'receivableTotal', key: 'receivableTotal', width: 110, align: 'right', render: function (v) { return fmtMoney(v); } },
|
||||
{ title: '实收款总额', dataIndex: 'actualTotal', key: 'actualTotal', width: 110, align: 'right', render: function (v) { return fmtMoney(v); } },
|
||||
{ title: '减免总金额', dataIndex: 'discountTotal', key: 'discountTotal', width: 100, align: 'right', render: function (v) { return fmtMoney(v); } },
|
||||
{ title: '实际到账金额', dataIndex: 'arrivalAmount', key: 'arrivalAmount', width: 118, align: 'right', render: function (v) { return fmtMoney(v); } },
|
||||
{ title: '是否已开票', dataIndex: 'isInvoiced', key: 'isInvoiced', width: 96, render: function (v) { return v === '已开票' ? '已开票' : v === '部分开票' ? '部分开票' : (v === '未开票' ? '未开票' : (v || '—')); } },
|
||||
{ title: '开票金额', dataIndex: 'invoiceAmount', key: 'invoiceAmount', width: 100, align: 'right', render: function (v) { return fmtMoney(v); } },
|
||||
{ title: '车辆成本', key: 'vehicleCost', width: 110, align: 'right', render: function (_, record) { return fmtMoney(calcVehicleCost(record)); } },
|
||||
{ title: '氢费成本', dataIndex: 'hydrogenCost', key: 'hydrogenCost', width: 110, align: 'right', render: function (_, record) { return renderEditableCost('hydrogenCost', record); } },
|
||||
{ title: '其他成本', dataIndex: 'otherCost', key: 'otherCost', width: 110, align: 'right', render: function (_, record) { return renderEditableCost('otherCost', record); } },
|
||||
{
|
||||
title: '操作',
|
||||
key: 'action',
|
||||
@@ -207,10 +314,7 @@ const Component = function () {
|
||||
fixed: 'right',
|
||||
render: function (_, record, rowIndex, extra) {
|
||||
var parentRecord = (extra && extra._parentRecord) || record._parentRecord;
|
||||
return React.createElement(Space, { size: 'small' },
|
||||
React.createElement(Button, { type: 'link', size: 'small', onClick: function () { goView(record, parentRecord); } }, '查看'),
|
||||
React.createElement(Button, { type: 'link', size: 'small', onClick: function () { goChargeDetail(record, parentRecord); } }, '收费明细')
|
||||
);
|
||||
return renderSubActions(record, parentRecord);
|
||||
}
|
||||
}
|
||||
];
|
||||
@@ -225,7 +329,7 @@ const Component = function () {
|
||||
draggable: false,
|
||||
onDragStart: function (e) { e.preventDefault(); }
|
||||
},
|
||||
React.createElement(Table, {
|
||||
React.createElement(Table, {
|
||||
rowKey: function (r) { return (record.contractCode || '') + '-' + (r.period != null ? r.period : r._rowIndex); },
|
||||
columns: subColumns.map(function (col) {
|
||||
if (col.key !== 'action') return col;
|
||||
@@ -235,10 +339,7 @@ const Component = function () {
|
||||
width: col.width,
|
||||
fixed: col.fixed,
|
||||
render: function (val, row) {
|
||||
return React.createElement(Space, { size: 'small' },
|
||||
React.createElement(Button, { type: 'link', size: 'small', onClick: function () { goView(row, record); } }, '查看'),
|
||||
React.createElement(Button, { type: 'link', size: 'small', onClick: function () { goChargeDetail(row, record); } }, '收费明细')
|
||||
);
|
||||
return renderSubActions(row, record);
|
||||
}
|
||||
};
|
||||
}),
|
||||
@@ -246,19 +347,22 @@ const Component = function () {
|
||||
pagination: false,
|
||||
size: 'small',
|
||||
bordered: true,
|
||||
scroll: { x: 1300 }
|
||||
scroll: { x: 1450 }
|
||||
})
|
||||
);
|
||||
};
|
||||
|
||||
var requirementContent = '租赁账单(2026年3月10日版本)\n一个「数字化资产ONEOS运管平台」中的「租赁账单」模块\n#面包屑:业务管理-租赁账单;\n1.筛选:\n#支持合同编码/项目名称/客户名称/业务部门/业务负责人等筛选方式;\n1.1.合同编码:选择器,支持输入框内手动输入下拉模糊匹配对应项;\n1.2.项目名称:选择器,支持输入框内手动输入下拉模糊匹配对应项;\n1.3.客户名称:选择器,支持输入框内手动输入下拉模糊匹配对应项;\n1.4.业务部门:选择器,支持选择所有业务部门;\n1.5.业务负责人:选择器,支持选择所有业务负责人;\n1.6.交车任务编码:输入框,支持模糊搜索;\n1.7.右侧为重置、查询按钮;\n\n2.租赁账单列表:\n列表展示方式为:嵌套子表格,分为主表和子表\n2.1.主表:显示以下字段:合同编码、合同类型、项目名称、客户名称、合同生效日期、业务部门、业务负责人;\n 2.1.1.合同编码:显示车辆租赁合同编码;\n 2.1.2.合同类型:显示该租赁合同对应合同类型,显示该合同为试用合同还是正式合同;\n 2.1.3.项目名称:显示该租赁合同对应项目名称;\n 2.1.4.客户名称:显示该租赁合同对应客户名称;\n 2.1.5.合同生效日期:显示该租赁合同生效日期,格式为:YYYY-MM-DD;\n 2.1.6.交车任务编码:显示交车任务编码;\n 2.1.7.业务部门:显示该租赁合同对应业务部门名称;\n 2.1.8.业务负责人:显示该租赁合同对应业务负责人;\n 2.1.9.主表右下方为分页符,支持分页和选择单页显示数据条数;\n\n2.2.子表:显示以下字段:账单编号、账单期数、账单开始日期、账单结束日期、应收款总额、实收款总额、减免总金额、实际到账金额、是否已开票、开票金额、操作;\n 2.2.1.账单编号:[合同编码][账单编号]组成,主要用于后期与用友YS系统打通时获取财务收款及发票相关数据;\n 前缀为合同编码,后缀为账单编号,规则为:ZD+4位编号,为该合同下第x份账单,例如:ZD0001为该合同下第1份账单,依次类推;\n 例如:JXZL20260216YW101235AZD0001即为JXZL20260216YW101235A合同下第1份账单;\n 2.2.2.账单期数:显示该笔账单对应期数;\n 2.2.3.处理状态:已提交、待提交、已结清;\n 2.2.3.1.已提交:业务人员已通过点击收费明细,对收费项进行过维护并经过二次确认后提交;\n 2.2.3.2.待提交:业务人员未完成收费明细填报;\n 2.2.3.3.已结清:(等对接财务系统后,到账金额等于实收金额总额后算作已结清);\n 2.2.3.账单开始日期:显示该笔账单开始日期,格式为:YYYY-MM-DD;\n 2.2.4.账单结束日期:显示该笔账单结束日期,格式为:YYYY-MM-DD;\n 2.2.5.提车数量:显示提车数量,格式为:xx辆,点击弹出气泡卡片,卡片内为列表,显示:品牌、型号、车牌号;\n 2.2.6.应收款总额:显示该笔账单应收款总额,格式为:xx.xx元,计算方式:「所有车辆月租金总和」+「所有车辆服务费总和」;\n 2.2.7.实收款总额:显示该笔账单实收款总额,格式为:xx.xx元,计算方式:「所有车辆月租金总和」+「所有车辆服务费总和」-「减免总金额」;\n 2.2.8.减免总金额:显示该笔账单减免总金额,格式为:xx.xx元,计算方式:「所有减免金额总和」;\n 2.2.9.车辆成本:根据型号成本表中对应型号车辆成本,租赁订单包含车辆型号*实际账单天数计算得出;\n 2.2.10.氢费成本:显示格式为:xx.xx元,点击变为输入框,后缀为元,支持2位小数,失焦后保存;\n 2.2.11.其他成本:显示格式为:xx.xx元,点击变为输入框,后缀为元,支持2位小数,失焦后保存;\n\n 2.2.12.操作:查看、收费明细;\n 2.2.12.1.查看:点击跳转租赁账单-查看页;\n 2.2.12.2.收费明细:提交后收费明细将不可修改;\n\n';
|
||||
|
||||
return React.createElement('div', { style: layoutStyle },
|
||||
React.createElement('div', { style: { marginBottom: 16 } },
|
||||
React.createElement('div', { style: { display: 'flex', alignItems: 'center', justifyContent: 'space-between', marginBottom: 16 } },
|
||||
React.createElement(Breadcrumb, {
|
||||
items: [
|
||||
{ title: '业务管理' },
|
||||
{ title: '租赁账单' }
|
||||
{ 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' } },
|
||||
@@ -357,6 +461,16 @@ const Component = function () {
|
||||
bordered: true,
|
||||
scroll: { x: 958 }
|
||||
})
|
||||
),
|
||||
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))
|
||||
)
|
||||
);
|
||||
};
|
||||
|
||||
@@ -7,6 +7,7 @@ const Component = function() {
|
||||
var Select = antd.Select;
|
||||
var Button = antd.Button;
|
||||
var DatePicker = antd.DatePicker;
|
||||
var Modal = antd.Modal;
|
||||
var message = antd.message;
|
||||
var Option = Select.Option;
|
||||
var Checkbox = antd.Checkbox;
|
||||
@@ -17,14 +18,28 @@ const Component = function() {
|
||||
var selectedProjectId = projectId[0];
|
||||
var setSelectedProjectId = projectId[1];
|
||||
|
||||
var expectedDelivery = React.useState(null);
|
||||
var expectedDelivery = React.useState(function() {
|
||||
if (typeof window !== 'undefined' && window.dayjs) {
|
||||
return [window.dayjs('2026-03-01'), window.dayjs('2026-03-05')];
|
||||
}
|
||||
return null;
|
||||
});
|
||||
var expectedDeliveryValue = expectedDelivery[0];
|
||||
var setExpectedDelivery = expectedDelivery[1];
|
||||
|
||||
var billingDate = React.useState(null);
|
||||
var billingDate = React.useState(function() {
|
||||
if (typeof window !== 'undefined' && window.dayjs) {
|
||||
return window.dayjs('2026-03-06');
|
||||
}
|
||||
return null;
|
||||
});
|
||||
var billingDateValue = billingDate[0];
|
||||
var setBillingDate = billingDate[1];
|
||||
|
||||
var noReturnCarCheckedState = React.useState(false);
|
||||
var noReturnCarChecked = noReturnCarCheckedState[0];
|
||||
var setNoReturnCarChecked = noReturnCarCheckedState[1];
|
||||
|
||||
var selectedRowKeys = React.useState(['v3', 'v4']);
|
||||
var checkedRowKeys = selectedRowKeys[0];
|
||||
var setCheckedRowKeys = selectedRowKeys[1];
|
||||
@@ -33,11 +48,9 @@ const Component = function() {
|
||||
var errors = formErrors[0];
|
||||
var setErrors = formErrors[1];
|
||||
|
||||
var reqSpecState = React.useState(false);
|
||||
var reqSpecOpen = reqSpecState[0];
|
||||
var setReqSpecOpen = reqSpecState[1];
|
||||
var reqModalOpen = React.useState(false);
|
||||
|
||||
// Mock:项目列表及车辆样例。deliveryStatus: 'none' 可选,'submitted' 已提交交车任务不可选,'completed' 已完成交车不显示
|
||||
// Mock:项目列表及车辆(与新增交车任务一致,含续签项目)
|
||||
var projectList = [
|
||||
{ id: 'p1', name: '嘉兴某某物流氢能运输项目', contractCode: 'JXZL20260216YW101235A', customerName: '嘉兴某某物流有限公司', deliveryRegion: '浙江省 / 嘉兴市', deliveryLocation: '浙江省嘉兴市南湖区科技大道1号', vehicles: [
|
||||
{ key: 'v1', brand: '东风', model: '氢燃料电池重卡 H31', plateNo: '浙A10001', vin: 'LFV2BJCH8K3123456', monthRent: '12800', serviceFee: '800', deposit: '30000', remark: '首车', deliveryStatus: 'submitted' },
|
||||
@@ -46,6 +59,13 @@ const Component = function() {
|
||||
{ key: 'v4', brand: '重汽', model: '豪沃氢能牵引车', plateNo: '浙F20001', vin: 'ZZ4257N386FZ12345', monthRent: '15000', serviceFee: '1000', deposit: '35000', remark: '', deliveryStatus: 'none' },
|
||||
{ key: 'v5', brand: '陕汽', model: '德龙氢能自卸', plateNo: '浙F20002', vin: 'SX1313GR456123456', monthRent: '13200', serviceFee: '880', deposit: '32000', remark: '固定线路', deliveryStatus: 'none' }
|
||||
]},
|
||||
{ id: 'p1_r', name: '嘉兴某某物流氢能运输项目(续签合同)', isRenewal: true, contractCode: 'JXZL20270116YW101235B', customerName: '嘉兴某某物流有限公司', deliveryRegion: '浙江省 / 嘉兴市', deliveryLocation: '浙江省嘉兴市南湖区科技大道1号', vehicles: [
|
||||
{ key: 'v1r_1', brand: '东风', model: '氢燃料电池重卡 H31', plateNo: '浙A10001', vin: 'LFV2BJCH8K3123456', monthRent: '12800', serviceFee: '800', deposit: '30000', remark: '续签合同车辆', deliveryStatus: 'none' },
|
||||
{ key: 'v1r_0', brand: '东风', model: '氢燃料电池重卡 H31', plateNo: '浙A09999', vin: 'LFV2BJCH8K3000000', monthRent: '12800', serviceFee: '800', deposit: '30000', remark: '续签:已交车车辆样例', deliveryStatus: 'completed' },
|
||||
{ key: 'v1r_0b', brand: '福田', model: '智蓝氢能轻卡', plateNo: '浙A08888', vin: 'LZYTBACR2M1000001', monthRent: '8500', serviceFee: '500', deposit: '20000', remark: '续签:已交车车辆样例', deliveryStatus: 'completed' },
|
||||
{ key: 'v1r_0c', brand: '重汽', model: '豪沃氢能牵引车', plateNo: '浙A07777', vin: 'ZZ4257N386FZ00002', monthRent: '15000', serviceFee: '1000', deposit: '35000', remark: '续签:已交车车辆样例', deliveryStatus: 'completed' },
|
||||
{ key: 'v1r_2', brand: '福田', model: '智蓝氢能轻卡', plateNo: '', vin: 'LZYTBACR2M1234567', monthRent: '8500', serviceFee: '500', deposit: '20000', remark: '续签待上牌', deliveryStatus: 'none' }
|
||||
]},
|
||||
{ id: 'p2', name: '上海某某运输氢能租赁项目', contractCode: 'SHZL20260201YW200123A', customerName: '上海某某运输公司', deliveryRegion: '上海市 / 上海市', deliveryLocation: '上海市浦东新区张江高科技园区', vehicles: [
|
||||
{ key: 'v6', brand: '上汽红岩', model: '杰狮氢能牵引', plateNo: '沪A30003', vin: 'SH1313HY789012345', monthRent: '14500', serviceFee: '950', deposit: '34000', remark: '', deliveryStatus: 'submitted' },
|
||||
{ key: 'v7', brand: '宇通', model: '氢能公交 ZK6126', plateNo: '沪B40001', vin: 'LZYTAGCF8K4567890', monthRent: '22000', serviceFee: '1200', deposit: '50000', remark: '示范线路', deliveryStatus: 'none' },
|
||||
@@ -60,13 +80,24 @@ const Component = function() {
|
||||
];
|
||||
|
||||
var selectedProject = projectList.find(function(p) { return p.id === selectedProjectId; });
|
||||
var isRenewalProject = !!(selectedProject && selectedProject.isRenewal);
|
||||
var vehicleListRaw = selectedProject ? selectedProject.vehicles : [];
|
||||
var vehicleList = vehicleListRaw.filter(function(v) { return v.deliveryStatus !== 'completed'; });
|
||||
var selectableVehicles = vehicleList.filter(function(v) { return v.deliveryStatus !== 'submitted'; });
|
||||
var vehicleList = vehicleListRaw.filter(function(v) {
|
||||
if (v.deliveryStatus === 'completed') { if (!isRenewalProject) return false; return true; }
|
||||
if (v.deliveryStatus === 'submitted') return true;
|
||||
if (isRenewalProject && !!noReturnCarChecked) return false;
|
||||
return true;
|
||||
});
|
||||
var selectableVehicles = vehicleList.filter(function(v) {
|
||||
if (v.deliveryStatus === 'submitted') return false;
|
||||
if (v.deliveryStatus === 'completed') return isRenewalProject && !!noReturnCarChecked;
|
||||
return true;
|
||||
});
|
||||
|
||||
var handleProjectChange = function(id) {
|
||||
setSelectedProjectId(id || '');
|
||||
setCheckedRowKeys([]);
|
||||
setNoReturnCarChecked(false);
|
||||
};
|
||||
|
||||
var todayStr = (function() {
|
||||
@@ -84,14 +115,15 @@ const Component = function() {
|
||||
return null;
|
||||
};
|
||||
|
||||
var expectedDeliveryError = validateExpectedDelivery();
|
||||
var needExpectedDelivery = !(isRenewalProject && noReturnCarChecked);
|
||||
var expectedDeliveryError = needExpectedDelivery ? validateExpectedDelivery() : null;
|
||||
|
||||
var billingDateError = !billingDateValue ? '请选择开始计费日期' : null;
|
||||
|
||||
var handleSubmit = function() {
|
||||
var err = {};
|
||||
if (!selectedProjectId) err.projectName = '请选择项目名称';
|
||||
if (expectedDeliveryError) err.expectedDelivery = expectedDeliveryError;
|
||||
if (needExpectedDelivery && expectedDeliveryError) err.expectedDelivery = expectedDeliveryError;
|
||||
if (billingDateError) err.billingDate = billingDateError;
|
||||
if (checkedRowKeys.length === 0 && selectableVehicles.length > 0) err.vehicles = '请至少选择一辆车';
|
||||
setErrors(err);
|
||||
@@ -99,6 +131,17 @@ const Component = function() {
|
||||
message.success('交车任务已保存。');
|
||||
};
|
||||
|
||||
var onToggleNoReturnCar = function(e) {
|
||||
var next = !!(e && e.target ? e.target.checked : e);
|
||||
setNoReturnCarChecked(next);
|
||||
if (!next) {
|
||||
setCheckedRowKeys(function(prev) {
|
||||
var completedKeys = vehicleList.filter(function(v) { return v && v.deliveryStatus === 'completed'; }).map(function(v) { return v.key; });
|
||||
return prev.filter(function(k) { return completedKeys.indexOf(k) === -1; });
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
var handleCancel = function() {
|
||||
message.info('取消');
|
||||
};
|
||||
@@ -138,21 +181,7 @@ const Component = function() {
|
||||
modalBody: { padding: 20, overflow: 'auto', flex: 1 }
|
||||
};
|
||||
|
||||
var reqSpecBlock = { marginBottom: 16 };
|
||||
var reqSpecH2 = { fontSize: 14, fontWeight: 600, color: '#333', marginBottom: 6 };
|
||||
var reqSpecLi = { fontSize: 13, color: '#666', marginBottom: 2, paddingLeft: 8 };
|
||||
|
||||
var reqSpecDoc = React.createElement('div', { style: { padding: '0 4px' } },
|
||||
React.createElement('div', { style: reqSpecBlock }, React.createElement('div', { style: reqSpecH2 }, '交车任务')),
|
||||
React.createElement('div', { style: reqSpecBlock }, React.createElement('div', { style: reqSpecH2 }, '1.面包屑:'), React.createElement('div', { style: reqSpecLi }, '1.1.业务管理-交车任务-编辑交车任务')),
|
||||
React.createElement('div', { style: reqSpecBlock }, React.createElement('div', { style: reqSpecH2 }, '2.表单:'),
|
||||
React.createElement('div', { style: reqSpecLi }, '2.1.选择项目名称:已选择禁用,不可修改;'),
|
||||
React.createElement('div', { style: reqSpecLi }, '2.2.合同编码、客户名称、交车区域、交车地点、预计交车日期、开始计费日期、车辆列表等可修改;'),
|
||||
React.createElement('div', { style: reqSpecLi }, '预计交车日期:不能早于当前日期'),
|
||||
React.createElement('div', { style: reqSpecLi }, '2.9.页面底部为提交、取消;')
|
||||
));
|
||||
|
||||
var reqSpecModalContent = reqSpecOpen ? React.createElement('div', { style: styles.modalMask, onClick: function(e) { if (e.target === e.currentTarget) setReqSpecOpen(false); } }, React.createElement('div', { style: styles.modalBox, onClick: function(e) { e.stopPropagation(); } }, React.createElement('div', { style: styles.modalHeader }, '需求说明'), React.createElement('div', { style: Object.assign({}, styles.modalBody, { maxHeight: '70vh', padding: '20px 24px' }) }, reqSpecDoc), React.createElement('div', { style: { padding: '12px 20px', borderTop: '1px solid #f0f0f0', textAlign: 'right' } }, React.createElement(Button, { onClick: function() { setReqSpecOpen(false); } }, '关闭')))) : null;
|
||||
var reqSpecText = '编辑交车任务\n一个「数字化资产ONEOS运管平台」中的「交车任务」「编辑」模块\n1.面包屑:\n1.1.业务管理-交车任务-编辑\n\n2.表单:\n2.1.选择项目名称:必选项,反写新增时写入的数据,选择器,默认提示文本:请选择或输入项目名称,支持从输入框内输入内容进行模糊搜索,对应自营合同、租赁合同-「项目名称」字段;;\n2.2.合同编码:输入框(禁用状态),根据所选项目名称自动反写合同编码;\n2.3.客户名称:输入框(禁用状态),根据所选项目名称自动反写客户名称;\n2.4.交车区域:输入框(禁用状态),根据所选项目名称自动反写交车区域。提交时根据交车区域,为对应区域运维人员分配对应交车任务;\n2.5.交车地点:输入框(禁用状态),根据所选项目名称自动反写交车地点;\n2.6.预计交车日期:必填项,反写新增时写入的数据,日期选择器,支持某天或某个时间段两种模式,格式为YYYY-MM-DD或YYYY-MM-DD至YYYY-MM-DD,结束日期不能早于开始日期,并且结束日期不能早于当前日期;\n 2.6.1.如勾选不需要还车,则预计交车日期隐藏,不需要设置;\n2.7.开始计费日期:必填项,反写新增时写入的数据,日期选择器,支持单日选择,格式为YYYY-MM-DD;\n2.8.已交车辆是否需要还车:勾选框,反写新增时写入的数据,内容为不需要还车,默认不勾选,不勾选时,无法在车辆列表勾选已交未还的车辆,勾选后,已交未还的车辆也可以勾选,但不会生成新交车任务,只是按照开始计费日期生成账单;\n 2.8.1.勾选时,车辆列表只显示已交未还的车辆清单,不能添加新车(避免已交未还部分车辆开始计费日期计算不精确);\n 2.8.2.不勾选时,车辆列表显示已交未还的车辆清单及续签合同新增车辆,但是已交未还部分的车辆不可勾选;\n2.9.下方为列表,列表拉取该车辆租赁合同对应所有车辆信息(该合同下已提交过交车任务的车辆不可选,已完成交车的车辆不显示在列表中),列表字段为:全选/多选、品牌、型号、车牌号、车辆识别代码、车辆月租金、服务费、保证金、备注;\n 2.9.1.全选/多选:支持全选、多选模式,反写新增时写入的数据,选择对应车辆后,点击提交自动生成被选中车辆交车任务,需要至少选择1辆,才能进行提交,该合同下已提交过交车任务和已交车的车辆不可选,多选框为禁用状态,悬浮时提示:该车辆已完成交车/该车辆已创建交车任务;\n 2.9.2.品牌:输入框(禁用状态),根据所选项目名称自动反写品牌;\n 2.9.3.型号:输入框(禁用状态),根据所选项目名称自动反写型号;\n 2.9.4.车牌号:输入框(禁用状态),根据所选项目名称自动反写车牌号,车牌号可能为空,为空时显示为-;\n 2.9.5.车辆识别代码:输入框(禁用状态),根据所选项目名称自动反写车辆识别代码;\n 2.9.6.车辆月租金:输入框(禁用状态),根据所选项目名称自动反写车辆月租金,后缀为元;\n 2.9.7.服务费:输入框(禁用状态),根据所选项目名称自动反写服务费,后缀为元;\n 2.9.8.保证金:输入框(禁用状态),根据所选项目名称自动反写保证金,后缀为元;\n 2.9.9.备注:输入框(禁用状态),根据所选项目名称自动反写备注信息,备注为空时显示为-;\n2.10.页面底部为提交、取消;';
|
||||
|
||||
var FormItem = function(props) {
|
||||
return React.createElement('div', { style: styles.formCol },
|
||||
@@ -167,7 +196,7 @@ const Component = function() {
|
||||
var formRow1 = React.createElement('div', { style: styles.formRow },
|
||||
React.createElement(FormItem, { label: '选择项目名称', required: true, error: errors.projectName },
|
||||
React.createElement(Select, {
|
||||
placeholder: '请选择或输入项目名称',
|
||||
placeholder: '请选择或输入项目名称(对应自营合同、租赁合同-项目名称)',
|
||||
style: { width: '100%' },
|
||||
value: selectedProjectId || undefined,
|
||||
disabled: true,
|
||||
@@ -182,7 +211,7 @@ const Component = function() {
|
||||
);
|
||||
|
||||
var formRow2 = React.createElement('div', { style: styles.formRow },
|
||||
React.createElement(FormItem, { label: '预计交车日期', required: true, error: errors.expectedDelivery },
|
||||
needExpectedDelivery ? React.createElement(FormItem, { label: '预计交车日期', required: true, error: errors.expectedDelivery },
|
||||
React.createElement(RangePicker, {
|
||||
style: { width: '100%' },
|
||||
format: 'YYYY-MM-DD',
|
||||
@@ -190,7 +219,7 @@ const Component = function() {
|
||||
value: expectedDeliveryValue,
|
||||
onChange: function(dates) { setExpectedDelivery(dates && dates.length === 2 ? dates : null); },
|
||||
status: errors.expectedDelivery ? 'error' : undefined
|
||||
})),
|
||||
})) : null,
|
||||
React.createElement(FormItem, { label: '开始计费日期', required: true, error: errors.billingDate },
|
||||
React.createElement(DatePicker, {
|
||||
style: { width: '100%' },
|
||||
@@ -199,7 +228,17 @@ const Component = function() {
|
||||
value: billingDateValue,
|
||||
onChange: function(d, dateStr) { setBillingDate(d); },
|
||||
status: errors.billingDate ? 'error' : undefined
|
||||
}))
|
||||
})),
|
||||
isRenewalProject ? React.createElement(FormItem, { label: '已交车辆是否需要还车' },
|
||||
React.createElement('div', { style: { display: 'flex', alignItems: 'flex-start', gap: 8, lineHeight: 1.6 } },
|
||||
React.createElement(Checkbox, { checked: !!noReturnCarChecked, onChange: onToggleNoReturnCar }, '不需要还车'),
|
||||
React.createElement('span', { style: { color: '#8c8c8c', fontSize: 12, marginTop: 2 } },
|
||||
'勾选不需要还车,则车辆无需交车,',
|
||||
React.createElement('br', null),
|
||||
'只设置开始计费日期即可重新生成账单'
|
||||
)
|
||||
)
|
||||
) : null
|
||||
);
|
||||
|
||||
var allSelectableChecked = selectableVehicles.length > 0 && selectableVehicles.every(function(v) { return checkedRowKeys.indexOf(v.key) !== -1; });
|
||||
@@ -225,17 +264,27 @@ const Component = function() {
|
||||
|
||||
var tableBody = React.createElement('tbody', null,
|
||||
vehicleList.length === 0
|
||||
? React.createElement('tr', null, React.createElement('td', { colSpan: 9, style: Object.assign({}, styles.td, { textAlign: 'center', color: '#999' }) }, '该合同下暂无车辆信息'))
|
||||
? React.createElement('tr', null, React.createElement('td', { colSpan: 9, style: Object.assign({}, styles.td, { textAlign: 'center', color: '#999' }) }, '请先选择项目名称,将自动带出该合同下车辆信息'))
|
||||
: vehicleList.map(function(row) {
|
||||
var isSubmitted = row.deliveryStatus === 'submitted';
|
||||
var isCompleted = row.deliveryStatus === 'completed';
|
||||
var completedSelectable = isRenewalProject && !!noReturnCarChecked;
|
||||
return React.createElement('tr', { key: row.key },
|
||||
React.createElement('td', { style: styles.td },
|
||||
isSubmitted
|
||||
? React.createElement(Tooltip, { title: '该车辆已有交车任务' },
|
||||
React.createElement('span', { style: { display: 'inline-flex', alignItems: 'center', gap: 6, cursor: 'not-allowed' } },
|
||||
React.createElement(Checkbox, { disabled: true, checked: false }),
|
||||
React.createElement('span', { style: { color: '#999', fontSize: 12 } }, '已提交')))
|
||||
: React.createElement(Checkbox, { checked: checkedRowKeys.indexOf(row.key) !== -1, onChange: function(e) { onSelectRow(row, e.target.checked); } })),
|
||||
? React.createElement(Tooltip, { title: '该车辆已创建交车任务' },
|
||||
React.createElement('span', { style: { display: 'inline-flex', alignItems: 'center', cursor: 'not-allowed' } },
|
||||
React.createElement(Checkbox, { disabled: true, checked: false })))
|
||||
: isCompleted
|
||||
? React.createElement(Tooltip, { title: '该车辆已完成交车' },
|
||||
React.createElement('span', { style: { display: 'inline-flex', alignItems: 'center' } },
|
||||
React.createElement(Checkbox, {
|
||||
disabled: !completedSelectable,
|
||||
checked: completedSelectable ? (checkedRowKeys.indexOf(row.key) !== -1) : false,
|
||||
onChange: function(e) { onSelectRow(row, e.target.checked); }
|
||||
})
|
||||
))
|
||||
: React.createElement(Checkbox, { checked: checkedRowKeys.indexOf(row.key) !== -1, onChange: function(e) { onSelectRow(row, e.target.checked); } })),
|
||||
React.createElement('td', { style: styles.td }, React.createElement(Input, { value: row.brand, disabled: true, style: styles.inputDisabled })),
|
||||
React.createElement('td', { style: styles.td }, React.createElement(Input, { value: row.model, disabled: true, style: styles.inputDisabled })),
|
||||
React.createElement('td', { style: styles.td }, React.createElement(Input, { value: row.plateNo || '-', disabled: true, style: styles.inputDisabled })),
|
||||
@@ -267,7 +316,7 @@ const Component = function() {
|
||||
React.createElement('span', null, '交车任务'),
|
||||
React.createElement('span', { style: styles.breadcrumbSep }, ' / '),
|
||||
React.createElement('span', { style: { color: '#1890ff' } }, '编辑交车任务')),
|
||||
React.createElement('span', { style: { color: '#1890ff', cursor: 'pointer', fontSize: 14 }, onClick: function() { setReqSpecOpen(true); } }, '查看需求说明')),
|
||||
React.createElement(Button, { type: 'link', style: { padding: 0 }, onClick: function() { reqModalOpen[1](true); } }, '查看需求说明')),
|
||||
React.createElement('div', { style: styles.card },
|
||||
React.createElement('div', { style: styles.cardHeader }, React.createElement('span', { style: styles.cardTitle }, '交车任务')),
|
||||
React.createElement('div', { style: styles.cardBody },
|
||||
@@ -275,7 +324,15 @@ const Component = function() {
|
||||
formRow2,
|
||||
tableEl)),
|
||||
React.createElement('div', { style: { height: 60 } }),
|
||||
reqSpecModalContent,
|
||||
React.createElement(Modal, {
|
||||
title: '需求说明',
|
||||
open: reqModalOpen[0],
|
||||
onCancel: function() { reqModalOpen[1](false); },
|
||||
width: 720,
|
||||
footer: React.createElement(Button, { onClick: function() { reqModalOpen[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 } }, reqSpecText))),
|
||||
React.createElement('div', { style: styles.footer },
|
||||
React.createElement(Button, { type: 'primary', onClick: handleSubmit }, '提交'),
|
||||
React.createElement(Button, { onClick: handleCancel }, '取消'))
|
||||
|
||||
Reference in New Issue
Block a user