运维/财务:完善交车单编辑/查看与还车应结款页面

- 交车单编辑页:布局对齐、检查单合并、照片必填与需求说明
- 新增交车单查看页:只读展示与样例数据
- 还车应结款相关页面与需求说明补齐

Made-with: Cursor
This commit is contained in:
王冕
2026-03-18 22:10:05 +08:00
parent e842a778a4
commit 92d3b97bca
18 changed files with 6636 additions and 719 deletions

View File

@@ -0,0 +1,303 @@
// 【重要】必须使用 const Component 作为组件变量名
// 运维管理 - 车辆管理 - 证照管理
const Component = function () {
var useState = React.useState;
var useMemo = React.useMemo;
var useCallback = React.useCallback;
var antd = window.antd;
var Breadcrumb = antd.Breadcrumb;
var Card = antd.Card;
var Table = antd.Table;
var Button = antd.Button;
var Select = antd.Select;
var Input = antd.Input;
var DatePicker = antd.DatePicker;
var Modal = antd.Modal;
var message = antd.message;
function pad2(n) { return n < 10 ? '0' + n : '' + n; }
function fmtDate(d) { return d.getFullYear() + '-' + pad2(d.getMonth() + 1) + '-' + pad2(d.getDate()); }
function todayPlus(days) { var d = new Date(); d.setDate(d.getDate() + days); return fmtDate(d); }
var layoutStyle = { padding: '16px 24px', background: '#f5f5f5', minHeight: '100vh' };
var cardStyle = { marginBottom: 16 };
// 筛选
var filtersState = useState({
customerName: undefined,
contractCode: undefined,
plateNo: undefined,
vin: undefined,
licenseInspectValid: null,
operationPermitValid: null,
passPermitValid: null
});
var filters = filtersState[0];
var setFilters = filtersState[1];
var moreOpenState = useState(false);
// mock 列表数据
var tableDataState = useState(function () {
var rows = [];
for (var i = 1; i <= 20; i++) {
rows.push({
key: 'row-' + i,
plateNo: i < 10 ? ('粤A1234' + i) : ('京A5432' + i),
vin: 'LJ8ABC' + (100000 + i),
licenseRegDate: todayPlus(-500 - i),
licenseScrapDate: todayPlus(2000 + i),
licenseValidDate: todayPlus(60 + i),
operationCertNo: 'YYZ-' + (10000 + i),
operationRegDate: todayPlus(-480 - i),
operationInspectValid: todayPlus(90 + i),
operationValid: todayPlus(365 + i),
passPermitNo: 'TXZ-' + (20000 + i),
passArea: i % 3 === 0 ? '上海市-浦东新区' : i % 3 === 1 ? '广东省-广州市' : '北京市-朝阳区',
passValid: todayPlus(120 + i),
h2CertCode: 'JQZ-' + (30000 + i),
h2CertInspectDate: todayPlus(-30 - i),
h2CardCode: 'JQK-' + (40000 + i),
safetyValveInspectDate: todayPlus(-20 - i),
safetyValveCycleMonth: 12,
pressureGaugeInspectDate: todayPlus(-10 - i),
pressureGaugeCycleMonth: 12,
h2BottleVendor: i % 2 === 0 ? '亿华' : '中集',
h2BottleInspectDate: todayPlus(-5 - i),
h2BottleCycleMonth: 24
});
}
return rows;
});
var tableData = tableDataState[0];
var setTableData = tableDataState[1];
// 下拉选项(来自列表 mock
var options = useMemo(function () {
var customers = ['嘉兴某某物流有限公司', '上海某某运输公司', '北京某某租赁有限公司'];
var contracts = ['HI-2024-001', 'HI-2024-002', 'HI-2024-003'];
return {
customerName: customers.map(function (v) { return { value: v, label: v }; }),
contractCode: contracts.map(function (v) { return { value: v, label: v }; }),
plateNo: tableData.map(function (r) { return r.plateNo; }).slice(0, 20).map(function (v) { return { value: v, label: v }; }),
vin: tableData.map(function (r) { return r.vin; }).slice(0, 20).map(function (v) { return { value: v, label: v }; })
};
}, [tableData]);
var filteredData = useMemo(function () {
var list = tableData;
if (filters.customerName) {
// mock按 index 分组匹配
list = list.filter(function (_, idx) { return (idx % 3) === 0; });
}
if (filters.contractCode) {
list = list.filter(function (_, idx) { return (idx % 3) === 1; });
}
if (filters.plateNo) list = list.filter(function (r) { return r.plateNo === filters.plateNo; });
if (filters.vin) list = list.filter(function (r) { return r.vin === filters.vin; });
return list;
}, [tableData, filters.customerName, filters.contractCode, filters.plateNo, filters.vin]);
// 选中
var selectedRowKeysState = useState([]);
// 导入弹窗
var importOpenState = useState(false);
var importFileState = useState(null);
function resetFilters() {
setFilters({
customerName: undefined,
contractCode: undefined,
plateNo: undefined,
vin: undefined,
licenseInspectValid: null,
operationPermitValid: null,
passPermitValid: null
});
message.success('已重置');
}
function handleQuery() {
message.success('已查询(原型)');
}
function openAdd() {
message.info('进入证照录入页(原型)');
}
function confirmDeleteSelected() {
var keys = selectedRowKeysState[0] || [];
if (!keys.length) return;
Modal.confirm({
title: '确认删除',
content: '确定要删除选中的证照记录吗?删除后将无法恢复。',
okText: '确认删除',
cancelText: '取消',
onOk: function () {
setTableData(function (p) { return p.filter(function (r) { return keys.indexOf(r.key) === -1; }); });
selectedRowKeysState[1]([]);
message.success('已删除');
}
});
}
function openExport() {
message.info('导出当前筛选结果(原型)');
}
function openImport() {
importFileState[1](null);
importOpenState[1](true);
}
function onPickImportFile(e) {
var f = e && e.target && e.target.files && e.target.files[0];
if (!f) return;
var name = String(f.name || '').toLowerCase();
if (!(name.endsWith('.xls') || name.endsWith('.xlsx'))) {
message.error('仅支持 .xls、.xlsx 格式');
return;
}
importFileState[1](f);
}
function doImportUpload() {
if (!importFileState[0]) {
message.error('请先选取要上传的文件');
return;
}
message.success('上传成功(原型)');
importOpenState[1](false);
}
// 表格列
var columns = useMemo(function () {
return [
{ title: '车牌号', dataIndex: 'plateNo', key: 'plateNo', width: 110, fixed: 'left' },
{
title: 'vin码',
dataIndex: 'vin',
key: 'vin',
width: 150,
render: function (v) {
return React.createElement('span', { style: { color: '#f5222d', fontWeight: 600 } }, v || '-');
}
},
{ title: '行驶证 注册日期', dataIndex: 'licenseRegDate', key: 'licenseRegDate', width: 140 },
{ title: '行驶证 强制报废日期', dataIndex: 'licenseScrapDate', key: 'licenseScrapDate', width: 160 },
{ title: '行驶证 有效期', dataIndex: 'licenseValidDate', key: 'licenseValidDate', width: 130 },
{ title: '营运证 编号', dataIndex: 'operationCertNo', key: 'operationCertNo', width: 140 },
{ title: '营运证 注册日期', dataIndex: 'operationRegDate', key: 'operationRegDate', width: 140 },
{ title: '营运证 审验有效期', dataIndex: 'operationInspectValid', key: 'operationInspectValid', width: 160 },
{ title: '营运证 有效期', dataIndex: 'operationValid', key: 'operationValid', width: 140 },
{ title: '通行证 编号', dataIndex: 'passPermitNo', key: 'passPermitNo', width: 140 },
{ title: '通行区域', dataIndex: 'passArea', key: 'passArea', width: 160, ellipsis: true },
{ title: '通行证 有效期', dataIndex: 'passValid', key: 'passValid', width: 140 },
{ title: '加氢证 编码', dataIndex: 'h2CertCode', key: 'h2CertCode', width: 140 },
{ title: '加氢证 检验日期', dataIndex: 'h2CertInspectDate', key: 'h2CertInspectDate', width: 150 },
{ title: '加氢卡 编码', dataIndex: 'h2CardCode', key: 'h2CardCode', width: 140 },
{ title: '安全阀 检验日期', dataIndex: 'safetyValveInspectDate', key: 'safetyValveInspectDate', width: 150 },
{ title: '安全阀 检验周期:单位 (月)', dataIndex: 'safetyValveCycleMonth', key: 'safetyValveCycleMonth', width: 200 },
{ title: '压力表 检验日期', dataIndex: 'pressureGaugeInspectDate', key: 'pressureGaugeInspectDate', width: 150 },
{ title: '压力表 检验周期:单位 (月)', dataIndex: 'pressureGaugeCycleMonth', key: 'pressureGaugeCycleMonth', width: 200 },
{ title: '氢气瓶 厂家', dataIndex: 'h2BottleVendor', key: 'h2BottleVendor', width: 120 },
{ title: '氢气瓶 检验日期', dataIndex: 'h2BottleInspectDate', key: 'h2BottleInspectDate', width: 150 },
{ title: '氢气瓶 检验周期:单位 (月)', dataIndex: 'h2BottleCycleMonth', key: 'h2BottleCycleMonth', width: 200 },
{
title: '操作',
key: 'action',
width: 120,
fixed: 'right',
render: function (_, r) {
return React.createElement('div', { style: { display: 'flex', gap: 8 } },
React.createElement(Button, { type: 'link', size: 'small', onClick: function () { message.info('编辑:' + (r.plateNo || '')); } }, '编辑'),
React.createElement(Button, { type: 'link', size: 'small', onClick: function () { message.info('查看:' + (r.plateNo || '')); } }, '查看')
);
}
}
];
}, []);
function filterOption(input, opt) {
return String((opt && opt.label) || '').toLowerCase().indexOf(String(input || '').toLowerCase()) !== -1;
}
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(Card, { title: '筛选与操作区', style: cardStyle },
React.createElement('div', { style: { display: 'flex', alignItems: 'flex-start', justifyContent: 'space-between', gap: 16 } },
React.createElement('div', { style: { flex: 1 } },
React.createElement('div', { style: { display: 'grid', gridTemplateColumns: 'repeat(4, minmax(0, 1fr))', gap: 12 } },
React.createElement(Select, { placeholder: '请选择客户名称', value: filters.customerName, onChange: function (v) { setFilters(function (p) { var n = {}; for (var k in p) n[k] = p[k]; n.customerName = v; return n; }); }, allowClear: true, showSearch: true, filterOption: filterOption, options: options.customerName }),
React.createElement(Select, { placeholder: '请选择合同编码', value: filters.contractCode, onChange: function (v) { setFilters(function (p) { var n = {}; for (var k in p) n[k] = p[k]; n.contractCode = v; return n; }); }, allowClear: true, showSearch: true, filterOption: filterOption, options: options.contractCode }),
React.createElement(Select, { placeholder: '请选择单车车牌号', value: filters.plateNo, onChange: function (v) { setFilters(function (p) { var n = {}; for (var k in p) n[k] = p[k]; n.plateNo = v; return n; }); }, allowClear: true, showSearch: true, filterOption: filterOption, options: options.plateNo }),
React.createElement(Select, { placeholder: '请选择车辆VIN', value: filters.vin, onChange: function (v) { setFilters(function (p) { var n = {}; for (var k in p) n[k] = p[k]; n.vin = v; return n; }); }, allowClear: true, showSearch: true, filterOption: filterOption, options: options.vin })
),
moreOpenState[0]
? React.createElement('div', { style: { marginTop: 12, display: 'grid', gridTemplateColumns: 'repeat(4, minmax(0, 1fr))', gap: 12 } },
React.createElement(DatePicker, { placeholder: '请选择审验有效期', style: { width: '100%' }, value: filters.licenseInspectValid, onChange: function (v) { setFilters(function (p) { var n = {}; for (var k in p) n[k] = p[k]; n.licenseInspectValid = v; return n; }); } }),
React.createElement(DatePicker, { placeholder: '请选择证件有效期', style: { width: '100%' }, value: filters.operationPermitValid, onChange: function (v) { setFilters(function (p) { var n = {}; for (var k in p) n[k] = p[k]; n.operationPermitValid = v; return n; }); } }),
React.createElement(DatePicker, { placeholder: '请选择有效期', style: { width: '100%' }, value: filters.passPermitValid, onChange: function (v) { setFilters(function (p) { var n = {}; for (var k in p) n[k] = p[k]; n.passPermitValid = v; return n; }); } }),
React.createElement('div', null)
)
: null,
React.createElement('div', { style: { marginTop: 12, display: 'flex', alignItems: 'center', gap: 8 } },
React.createElement(Button, { type: 'link', onClick: function () { moreOpenState[1](!moreOpenState[0]); } }, moreOpenState[0] ? '收起条件 ▲' : '更多条件 ▼'),
React.createElement(Button, { onClick: resetFilters }, '重置'),
React.createElement(Button, { type: 'primary', onClick: handleQuery }, '查询')
)
),
React.createElement('div', { style: { width: 360, display: 'flex', flexDirection: 'column', alignItems: 'flex-end', gap: 10 } },
React.createElement('div', { style: { color: '#666', fontSize: 13 } },
'选中 ', (selectedRowKeysState[0] || []).length, '/', (filteredData || []).length, ' 条'
),
React.createElement('div', { style: { display: 'flex', gap: 8, flexWrap: 'wrap', justifyContent: 'flex-end' } },
React.createElement(Button, { type: 'primary', onClick: openAdd }, '+ 新增'),
React.createElement(Button, { danger: true, disabled: !(selectedRowKeysState[0] || []).length, onClick: confirmDeleteSelected }, '删除'),
React.createElement(Button, { onClick: openExport }, '导出'),
React.createElement(Button, { onClick: openImport }, '导入')
)
)
)
),
React.createElement(Card, { title: '证照列表', style: cardStyle },
React.createElement(Table, {
rowKey: 'key',
size: 'middle',
bordered: true,
columns: columns,
dataSource: filteredData,
rowSelection: {
selectedRowKeys: selectedRowKeysState[0],
onChange: function (keys) { selectedRowKeysState[1](keys || []); }
},
scroll: { x: 2600 },
pagination: { pageSize: 20, showSizeChanger: true, pageSizeOptions: ['20', '50', '100'], showTotal: function (t) { return '共 ' + t + ' 条'; }, showQuickJumper: true }
})
),
React.createElement(Modal, {
title: '证件导入',
open: importOpenState[0],
onCancel: function () { importOpenState[1](false); },
okText: '上传',
cancelText: '取消',
onOk: doImportUpload
},
React.createElement('div', { style: { marginBottom: 12, color: '#666', fontSize: 13 } }, '*支持文件类型 .xls .xlsx'),
React.createElement('div', { style: { display: 'flex', alignItems: 'center', gap: 10, marginBottom: 12 } },
React.createElement(Button, { onClick: function () { message.info('下载模板:证件信息模板.xlsx原型'); } }, '模板下载'),
React.createElement('input', { type: 'file', accept: '.xls,.xlsx', onChange: onPickImportFile })
),
React.createElement('div', { style: { fontSize: 13, color: '#333' } }, '已选文件:', (importFileState[0] && importFileState[0].name) ? importFileState[0].name : '—')
)
);
};