From c75d1656e3931073fc03dd6542de8e2ed00faa19 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=86=95?= Date: Thu, 19 Mar 2026 20:19:48 +0800 Subject: [PATCH] =?UTF-8?q?web=E7=AB=AF:=20=E8=BD=A6=E8=BE=86/=E8=BF=90?= =?UTF-8?q?=E7=BB=B4=E6=A8=A1=E5=9D=97=E6=9B=B4=E6=96=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 车辆管理、车辆管理-查看:详情 Tab(后装设备/租赁/事故/违章/异动/调拨/证照管理等) - 车辆业务:异动管理列表与查看页、调拨相关页面与需求说明 - 需求说明文档补充 Made-with: Cursor --- web端/车辆管理.jsx | 1 + web端/运维管理/车辆业务/异动管理-查看.jsx | 347 ++ web端/运维管理/车辆业务/异动管理.jsx | 480 +++ web端/运维管理/车辆业务/异动管理.新增.jsx | 564 +++ web端/运维管理/车辆业务/调拨管理-接收记录.jsx | 447 +++ web端/运维管理/车辆业务/调拨管理-新增.jsx | 552 +++ web端/运维管理/车辆业务/调拨管理-查看.jsx | 302 ++ web端/运维管理/车辆业务/调拨管理-编辑.jsx | 547 +++ web端/运维管理/车辆业务/调拨管理.jsx | 3253 +++++------------ web端/运维管理/车辆管理-查看.jsx | 944 ++++- web端/需求说明/运维管理-车务管理/异动-新增 | 25 + web端/需求说明/运维管理-车务管理/异动管理 | 28 + web端/需求说明/运维管理-车务管理/调拨管理 | 64 + .../运维管理-车务管理/调拨管理-接收记录 | 28 + .../需求说明/运维管理-车务管理/调拨管理-新增 | 26 + web端/需求说明/运维管理-车务管理/还车管理 | 51 + .../需求说明/运维管理-车务管理/还车管理-查看 | 46 + 17 files changed, 5456 insertions(+), 2249 deletions(-) create mode 100644 web端/运维管理/车辆业务/异动管理-查看.jsx create mode 100644 web端/运维管理/车辆业务/异动管理.jsx create mode 100644 web端/运维管理/车辆业务/异动管理.新增.jsx create mode 100644 web端/运维管理/车辆业务/调拨管理-接收记录.jsx create mode 100644 web端/运维管理/车辆业务/调拨管理-新增.jsx create mode 100644 web端/运维管理/车辆业务/调拨管理-查看.jsx create mode 100644 web端/运维管理/车辆业务/调拨管理-编辑.jsx create mode 100644 web端/需求说明/运维管理-车务管理/异动-新增 create mode 100644 web端/需求说明/运维管理-车务管理/异动管理 create mode 100644 web端/需求说明/运维管理-车务管理/调拨管理 create mode 100644 web端/需求说明/运维管理-车务管理/调拨管理-接收记录 create mode 100644 web端/需求说明/运维管理-车务管理/调拨管理-新增 create mode 100644 web端/需求说明/运维管理-车务管理/还车管理 create mode 100644 web端/需求说明/运维管理-车务管理/还车管理-查看 diff --git a/web端/车辆管理.jsx b/web端/车辆管理.jsx index c820ecf..e8467ee 100644 --- a/web端/车辆管理.jsx +++ b/web端/车辆管理.jsx @@ -457,6 +457,7 @@ const Component = function () { React.createElement('div', { style: sectionTitleStyle }, React.createElement('span', { style: sectionIconStyle }), '保养参数'), React.createElement(Table, { size: 'small', rowKey: 'key', columns: maintenanceColumns, dataSource: maintenanceTableData, pagination: false }) ); + var detailTabItems = [ { key: '型号参数', label: '型号参数', children: modelParamContent }, { key: '后装设备', label: '后装设备', children: React.createElement('div', { style: tabContentCardStyle }, tabContent('后装设备列表(原型占位)')) }, diff --git a/web端/运维管理/车辆业务/异动管理-查看.jsx b/web端/运维管理/车辆业务/异动管理-查看.jsx new file mode 100644 index 0000000..f1f3464 --- /dev/null +++ b/web端/运维管理/车辆业务/异动管理-查看.jsx @@ -0,0 +1,347 @@ +// 【重要】必须使用 const Component 作为组件变量名 +// 运维管理 - 车辆业务 - 异动管理 - 查看(只读) + +const Component = function () { + var useState = React.useState; + var useMemo = React.useMemo; + + var antd = window.antd; + var App = antd.App; + var Breadcrumb = antd.Breadcrumb; + var Card = antd.Card; + var Button = antd.Button; + var Input = antd.Input; + var Select = antd.Select; + var DatePicker = antd.DatePicker; + var Table = antd.Table; + var Modal = antd.Modal; + var message = antd.message; + + function getInitialDateTime(str) { + try { + if (window.dayjs) return window.dayjs(str); + } catch (e1) {} + try { + if (window.moment) return window.moment(str, 'YYYY-MM-DD HH:mm'); + } catch (e2) {} + return null; + } + + var layoutStyle = { padding: '16px 24px', background: '#f5f5f5', minHeight: '100vh' }; + var labelStyle = { marginBottom: 6, fontSize: 14, color: 'rgba(0,0,0,0.65)' }; + var formItemStyle = { marginBottom: 12 }; + var controlStyle = { width: '100%' }; + + var destinationTypeOptions = useMemo(function () { + return [ + { value: '停车场', label: '停车场' }, + { value: '维修站', label: '维修站' }, + { value: '其他', label: '其他' } + ]; + }, []); + + var destinationParkingOptions = useMemo(function () { + return [ + { value: '天河智慧停车场', label: '天河智慧停车场' }, + { value: '南山科技园停车场', label: '南山科技园停车场' }, + { value: '西湖景区停车场', label: '西湖景区停车场' }, + { value: '宁波江北停车场', label: '宁波江北停车场' }, + { value: '张江园区停车场', label: '张江园区停车场' } + ]; + }, []); + + var destinationRepairOptions = useMemo(function () { + return [ + { value: '杭州拱墅维修站', label: '杭州拱墅维修站' }, + { value: '广州天河维修站', label: '广州天河维修站' }, + { value: '上海浦东维修站', label: '上海浦东维修站' } + ]; + }, []); + + var changeTypeOptions = useMemo(function () { + return [ + { value: '维修', label: '维修' }, + { value: '保养', label: '保养' }, + { value: '年审', label: '年审' }, + { value: '其他', label: '其他' } + ]; + }, []); + + var approvalStatusOptions = useMemo(function () { + return [ + { value: '待提交', label: '待提交' }, + { value: '审批中', label: '审批中' }, + { value: '审批完成', label: '审批完成' }, + { value: '驳回', label: '驳回' }, + { value: '撤回', label: '撤回' } + ]; + }, []); + + // 原型:详情接口返回的只读数据(字段与「异动管理.新增」一致,并含审批状态) + var form = { + startTime: getInitialDateTime('2026-02-20 09:30'), + plannedEndTime: getInitialDateTime('2026-02-22 18:00'), + destinationType: '维修站', + destinationName: '广州天河维修站', + destinationNameOther: '', + changeType: '维修', + plannedMileageKm: '45.50', + remark: '车辆需进站检修制动系统,预计两日内完成。', + approvalStatus: '审批中' + }; + + var vehicles = [ + { + id: 1, + plateNo: '粤A12345', + vehicleType: '厢式货车', + brand: '东风', + model: 'DFH1180', + departParking: '天河智慧停车场', + startMileageKm: '15230.12', + startHydrogen: '28.30', + h2Unit: 'MPa', + startElectricKwh: '68.40' + }, + { + id: 2, + plateNo: '浙A11111', + vehicleType: 'SUV', + brand: '小鹏', + model: 'P7', + departParking: '西湖景区停车场', + startMileageKm: '12010.00', + startHydrogen: '60.00', + h2Unit: '%', + startElectricKwh: '55.20' + } + ]; + + var destinationNameLabel = form.destinationType === '维修站' ? '维修站' : (form.destinationType === '停车场' ? '停车场' : '目的地名称'); + + var destinationNameNode = (function () { + if (form.destinationType === '其他') { + return React.createElement(Input, { + value: form.destinationNameOther || '-', + disabled: true + }); + } + var opts = form.destinationType === '维修站' ? destinationRepairOptions : destinationParkingOptions; + return React.createElement(Select, { + style: controlStyle, + value: form.destinationName, + options: opts, + disabled: true + }); + })(); + + var requirementModalState = useState(false); + var requirementModalOpen = requirementModalState[0]; + var setRequirementModalOpen = requirementModalState[1]; + + var requirementDocContent = [ + '一个「数字化资产ONEOS运管平台」中的「异动管理」「查看」模块', + '#面包屑:运维管理-车辆业务-异动管理-查看', + '页面布局与字段与「异动管理.新增」一致,所有表单项均为只读,仅供查询展示。', + '', + '1.异动情况:异动开始/预计结束日期、审批状态、异动目的地、目的地名称、异动类型、预计异动里程、备注 — 全部禁用不可编辑。', + '2.车辆信息:车牌号、车辆类型、品牌、型号、出发停车场、异动开始里程、异动开始氢量、异动开始电量 — 全部禁用;无新增行与删除操作。', + '3.底部仅提供「返回」按钮,返回异动管理列表(原型)。' + ].join('\n'); + + var vehicleColumns = useMemo(function () { + return [ + { + title: '车牌号', + key: 'plateNo', + width: 140, + render: function (_, r) { + return React.createElement(Input, { value: r.plateNo || '-', disabled: true }); + } + }, + { + title: '车辆类型', + key: 'vehicleType', + width: 120, + render: function (_, r) { + return React.createElement(Input, { value: r.vehicleType || '-', disabled: true }); + } + }, + { + title: '品牌', + key: 'brand', + width: 100, + render: function (_, r) { + return React.createElement(Input, { value: r.brand || '-', disabled: true }); + } + }, + { + title: '型号', + key: 'model', + width: 120, + render: function (_, r) { + return React.createElement(Input, { value: r.model || '-', disabled: true }); + } + }, + { + title: '出发停车场', + key: 'departParking', + width: 160, + render: function (_, r) { + return React.createElement(Input, { value: r.departParking || '-', disabled: true }); + } + }, + { + title: '异动开始里程', + key: 'startMileageKm', + width: 160, + render: function (_, r) { + return React.createElement(Input, { value: r.startMileageKm || '-', disabled: true, addonAfter: 'km' }); + } + }, + { + title: '异动开始氢量', + key: 'startHydrogen', + width: 150, + render: function (_, r) { + var unit = r.h2Unit || ''; + return React.createElement(Input, { value: r.startHydrogen || '-', disabled: true, addonAfter: unit || '-' }); + } + }, + { + title: '异动开始电量', + key: 'startElectricKwh', + width: 150, + render: function (_, r) { + return React.createElement(Input, { value: r.startElectricKwh || '-', disabled: true, addonAfter: 'kWh' }); + } + } + ]; + }, []); + + return React.createElement(App, null, + React.createElement('div', { style: layoutStyle }, + React.createElement('div', { style: { display: 'flex', alignItems: 'center', justifyContent: 'space-between', marginBottom: 16, flexWrap: 'wrap', gap: 8 } }, + React.createElement(Breadcrumb, { items: [{ title: '运维管理' }, { title: '车辆业务' }, { title: '异动管理' }, { title: '查看' }] }), + React.createElement(Button, { type: 'link', style: { padding: 0 }, onClick: function () { setRequirementModalOpen(true); } }, '查看需求说明') + ), + + React.createElement(Modal, { + title: '需求说明', + open: requirementModalOpen, + onCancel: function () { setRequirementModalOpen(false); }, + width: 720, + footer: React.createElement(Button, { onClick: function () { setRequirementModalOpen(false); } }, '关闭'), + bodyStyle: { maxHeight: '70vh', overflow: 'auto' } + }, React.createElement('div', { style: { whiteSpace: 'pre-wrap', fontSize: 13, lineHeight: 1.6, color: 'rgba(0,0,0,0.85)' } }, requirementDocContent)), + + React.createElement(Card, { title: '异动情况', style: { marginBottom: 16 } }, + React.createElement('div', { style: { display: 'grid', gridTemplateColumns: '1fr 1fr 1fr', gap: '16px 24px', alignItems: 'start' } }, + React.createElement('div', { style: formItemStyle }, + React.createElement('div', { style: labelStyle }, '异动开始日期'), + React.createElement(DatePicker, { + style: controlStyle, + showTime: { format: 'HH:mm' }, + format: 'YYYY-MM-DD HH:mm', + value: form.startTime, + disabled: true, + inputReadOnly: true + }) + ), + React.createElement('div', { style: formItemStyle }, + React.createElement('div', { style: labelStyle }, '异动预计结束日期'), + React.createElement(DatePicker, { + style: controlStyle, + showTime: { format: 'HH:mm' }, + format: 'YYYY-MM-DD HH:mm', + value: form.plannedEndTime, + disabled: true, + inputReadOnly: true + }) + ), + React.createElement('div', { style: formItemStyle }, + React.createElement('div', { style: labelStyle }, '审批状态'), + React.createElement(Select, { + style: controlStyle, + value: form.approvalStatus, + options: approvalStatusOptions, + disabled: true + }) + ), + + React.createElement('div', { style: formItemStyle }, + React.createElement('div', { style: labelStyle }, '异动目的地'), + React.createElement(Select, { + style: controlStyle, + value: form.destinationType, + options: destinationTypeOptions, + disabled: true + }) + ), + React.createElement('div', { style: formItemStyle }, + React.createElement('div', { style: labelStyle }, destinationNameLabel), + destinationNameNode + ), + React.createElement('div', { style: formItemStyle }, + React.createElement('div', { style: labelStyle }, '异动类型'), + React.createElement(Select, { + style: controlStyle, + value: form.changeType, + options: changeTypeOptions, + disabled: true + }) + ), + + React.createElement('div', { style: formItemStyle }, + React.createElement('div', { style: labelStyle }, '预计异动里程'), + React.createElement(Input, { + value: form.plannedMileageKm || '-', + disabled: true, + addonAfter: 'km' + }) + ), + React.createElement('div', { style: formItemStyle }), + React.createElement('div', { style: formItemStyle }), + + React.createElement('div', { style: Object.assign({}, formItemStyle, { gridColumn: 'span 3' }) }, + React.createElement('div', { style: labelStyle }, '备注'), + React.createElement(Input.TextArea, { + value: form.remark || '-', + disabled: true, + autoSize: { minRows: 3, maxRows: 6 } + }) + ) + ) + ), + + React.createElement(Card, { title: '车辆信息', style: { marginBottom: 16 } }, + React.createElement(Table, { + rowKey: 'id', + columns: vehicleColumns, + dataSource: vehicles, + size: 'small', + pagination: false, + scroll: { x: 1180 } + }) + ), + + React.createElement('div', { style: { height: 56 } }), + React.createElement('div', { + style: { + position: 'fixed', + left: 0, + right: 0, + bottom: 0, + padding: '12px 24px', + background: '#fff', + borderTop: '1px solid #f0f0f0', + display: 'flex', + gap: 8, + zIndex: 10 + } + }, + React.createElement(Button, { onClick: function () { message.info('返回异动管理列表(原型)'); } }, '返回') + ) + ) + ); +}; diff --git a/web端/运维管理/车辆业务/异动管理.jsx b/web端/运维管理/车辆业务/异动管理.jsx new file mode 100644 index 0000000..201e63c --- /dev/null +++ b/web端/运维管理/车辆业务/异动管理.jsx @@ -0,0 +1,480 @@ +// 【重要】必须使用 const Component 作为组件变量名 +// 运维管理 - 车辆业务 - 异动管理(列表页) + +const Component = function () { + var useState = React.useState; + var useMemo = React.useMemo; + var useCallback = React.useCallback; + + var antd = window.antd; + var App = antd.App; + var Breadcrumb = antd.Breadcrumb; + var Card = antd.Card; + var Button = antd.Button; + var Table = antd.Table; + var Select = antd.Select; + var DatePicker = antd.DatePicker; + var message = antd.message; + var Modal = antd.Modal; + + var RangePicker = DatePicker.RangePicker; + + function filterOption(input, option) { + var label = (option && (option.label || option.children)) || ''; + return String(label).toLowerCase().indexOf(String(input || '').toLowerCase()) >= 0; + } + + function fmtYMDHM(v) { + if (v === null || v === undefined) return '-'; + var s = String(v).trim(); + if (!s) return '-'; + if (/^\d{4}-\d{2}-\d{2}\s+\d{2}:\d{2}/.test(s)) return s.slice(0, 16); + if (/^\d{4}-\d{2}-\d{2}$/.test(s)) return s + ' 00:00'; + try { + var d = new Date(s.replace(/-/g, '/')); + if (isNaN(d.getTime())) return s; + var p2 = function (n) { return n < 10 ? '0' + n : '' + n; }; + return d.getFullYear() + '-' + p2(d.getMonth() + 1) + '-' + p2(d.getDate()) + ' ' + p2(d.getHours()) + ':' + p2(d.getMinutes()); + } catch (e) { + return s; + } + } + + function canShowMovementEdit(approvalStatus) { + var s = String(approvalStatus || ''); + return s === '待提交' || s === '驳回' || s === '撤回'; + } + + var layoutStyle = { padding: '16px 24px', background: '#f5f5f5', minHeight: '100vh' }; + var filterLabelStyle = { marginBottom: 6, fontSize: 14, color: 'rgba(0,0,0,0.65)' }; + var filterItemStyle = { marginBottom: 12 }; + var filterControlStyle = { width: '100%' }; + var tableSingleLineStyle = '.movement-list-table .ant-table-thead th,.movement-list-table .ant-table-tbody td{white-space:nowrap;}'; + + var moveTypeOptions = useMemo(function () { + return [ + { value: '维修', label: '维修' }, + { value: '保养', label: '保养' }, + { value: '年审', label: '年审' }, + { value: '其他', label: '其他' } + ]; + }, []); + + var plateOptions = useMemo(function () { + return [ + { value: '粤A12345', label: '粤A12345' }, + { value: '粤B11111', label: '粤B11111' }, + { value: '浙A11111', label: '浙A11111' }, + { value: '浙B22222', label: '浙B22222' }, + { value: '沪A30003', label: '沪A30003' }, + { value: '苏E88888', label: '苏E88888' }, + { value: '京A66666', label: '京A66666' }, + { value: '渝A99999', label: '渝A99999' }, + { value: '川A77777', label: '川A77777' }, + { value: '鲁B55555', label: '鲁B55555' } + ]; + }, []); + + var draftState = useState({ + moveStartRange: null, + moveTypes: [], + plateNo: undefined + }); + var draft = draftState[0]; + var setDraft = draftState[1]; + + var appliedState = useState({ + moveStartRange: null, + moveTypes: [], + plateNo: undefined + }); + var applied = appliedState[0]; + var setApplied = appliedState[1]; + + var pageState = useState(1); + var page = pageState[0]; + var setPage = pageState[1]; + var pageSizeState = useState(20); + var pageSize = pageSizeState[0]; + var setPageSize = pageSizeState[1]; + + var requirementModalState = useState(false); + var requirementModalOpen = requirementModalState[0]; + var setRequirementModalOpen = requirementModalState[1]; + + var requirementDocContent = [ + '一个「数字化资产ONEOS运管平台」中的「异动管理」模块', + '#面包屑:运维管理-车辆业务-异动管理', + '', + '1.筛选;', + '1.1.异动开始日期:日期选择器,输入框支持双日历选择开始-结束时间;', + '1.2.异动类型:选择器,选项包括:维修、保养、年审、其他,支持多选;', + '1.3.车牌号:选择器,输入框支持模糊搜索下拉匹配结果;', + '1.4.右侧为查询、重置按钮;', + '', + '2.列表:', + '2.1.异动开始日期:显示车辆异动开始日期,格式为:YYYY-MM-DD HH:MM;', + '2.2.异动预计结束日期:显示车辆异动结束日期,格式为:YYYY-MM-DD HH:MM;', + '2.3.审批状态:分为:待提交、审批中、审批完成、驳回、撤回;', + '2.4.异动目的地:显示车辆异动目的地,选项包括:停车场、维修站、其他;', + '2.5.目的地名称:显示车辆异动目的地名称;', + '2.6.异动类型:显示车辆异动类型,选项包括:维修、保养、年审、其他;', + '2.7.预计异动里程(km):显示车辆预计异动里程;', + '2.8.车牌号:显示车牌号;', + '2.9.异动开始里程(km):显示车辆异动开始里程;', + '2.10.异动开始电量(kWh):显示车辆异动开始电量;', + '2.11.异动开始氢量;显示车辆异动开始氢量,带单位,单位根据型号参数表获取,分为%和MPa;', + '2.12.创建人:显示发起人姓名;', + '2.13.创建时间:显示发起时间,格式为:YYYY-MM-DD HH:MM;', + '2.14.操作:查看、编辑;', + ' 2.14.1.查看:点击跳转异动-查看页;', + ' 2.14.2.编辑:点击跳转异动-编辑页,只有审批状态为:待提交、驳回、撤回时显示编辑;', + '', + '3.列表右下方为分页功能,支持单页显示条数设置;' + ].join('\n'); + + var listState = useState(function () { + return [ + { + id: 'mv1', + moveStartAt: '2026-02-20 09:30', + moveEndExpectedAt: '2026-02-22 18:00', + approvalStatus: '待提交', + destination: '维修站', + destinationName: '天河氢能维修中心', + moveType: '维修', + expectedMileageKm: '45.5', + plateNo: '粤A12345', + startMileageKm: '15230.12', + startElectricKwh: '68.40', + startHydrogen: '28.30', + h2Unit: 'MPa', + creatorName: '张明', + createTime: '2026-02-20 08:10' + }, + { + id: 'mv2', + moveStartAt: '2026-02-21 14:00', + moveEndExpectedAt: '2026-02-21 17:30', + approvalStatus: '审批中', + destination: '停车场', + destinationName: '西湖景区停车场', + moveType: '保养', + expectedMileageKm: '12.0', + plateNo: '浙A11111', + startMileageKm: '12010.00', + startElectricKwh: '55.20', + startHydrogen: '60.00', + h2Unit: '%', + creatorName: '王芳', + createTime: '2026-02-21 13:20' + }, + { + id: 'mv3', + moveStartAt: '2026-02-24 08:15', + moveEndExpectedAt: '2026-02-24 12:00', + approvalStatus: '审批完成', + destination: '其他', + destinationName: '车管所检测线', + moveType: '年审', + expectedMileageKm: '8.2', + plateNo: '粤B11111', + startMileageKm: '8020.50', + startElectricKwh: '62.10', + startHydrogen: '55.00', + h2Unit: '%', + creatorName: '李华', + createTime: '2026-02-24 07:50' + }, + { + id: 'mv4', + moveStartAt: '2026-02-25 10:00', + moveEndExpectedAt: '2026-02-26 09:00', + approvalStatus: '驳回', + destination: '维修站', + destinationName: '张江服务站', + moveType: '其他', + expectedMileageKm: '30.0', + plateNo: '沪A30003', + startMileageKm: '9800.00', + startElectricKwh: '69.00', + startHydrogen: '26.00', + h2Unit: 'MPa', + creatorName: '赵强', + createTime: '2026-02-25 09:40' + }, + { + id: 'mv5', + moveStartAt: '2026-02-26 16:20', + moveEndExpectedAt: '2026-02-27 10:00', + approvalStatus: '撤回', + destination: '停车场', + destinationName: '宁波江北停车场', + moveType: '维修', + expectedMileageKm: '22.8', + plateNo: '浙B22222', + startMileageKm: '15010.00', + startElectricKwh: '58.00', + startHydrogen: '22.10', + h2Unit: 'MPa', + creatorName: '陈静', + createTime: '2026-02-26 15:55' + }, + { + id: 'mv6', + moveStartAt: '2026-02-27 07:45', + moveEndExpectedAt: '2026-02-27 19:00', + approvalStatus: '审批中', + destination: '维修站', + destinationName: '苏州园区快修站', + moveType: '保养', + expectedMileageKm: '18.6', + plateNo: '苏E88888', + startMileageKm: '23105.80', + startElectricKwh: '42.50', + startHydrogen: '45.20', + h2Unit: '%', + creatorName: '张明', + createTime: '2026-02-27 07:20' + }, + { + id: 'mv7', + moveStartAt: '2026-02-27 11:00', + moveEndExpectedAt: '2026-02-28 17:30', + approvalStatus: '审批完成', + destination: '其他', + destinationName: '顺义综合检测场', + moveType: '年审', + expectedMileageKm: '35.0', + plateNo: '京A66666', + startMileageKm: '8890.00', + startElectricKwh: '71.20', + startHydrogen: '31.50', + h2Unit: 'MPa', + creatorName: '王芳', + createTime: '2026-02-27 10:35' + }, + { + id: 'mv8', + moveStartAt: '2026-02-28 08:30', + moveEndExpectedAt: '2026-02-28 14:00', + approvalStatus: '待提交', + destination: '停车场', + destinationName: '两江新区枢纽停车场', + moveType: '其他', + expectedMileageKm: '6.5', + plateNo: '渝A99999', + startMileageKm: '17660.25', + startElectricKwh: '48.90', + startHydrogen: '58.00', + h2Unit: '%', + creatorName: '李华', + createTime: '2026-02-28 08:05' + }, + { + id: 'mv9', + moveStartAt: '2026-02-28 13:15', + moveEndExpectedAt: '2026-03-01 09:00', + approvalStatus: '驳回', + destination: '维修站', + destinationName: '成都高新氢能维保站', + moveType: '维修', + expectedMileageKm: '52.3', + plateNo: '川A77777', + startMileageKm: '34500.00', + startElectricKwh: '33.60', + startHydrogen: '24.80', + h2Unit: 'MPa', + creatorName: '赵强', + createTime: '2026-02-28 12:50' + }, + { + id: 'mv10', + moveStartAt: '2026-03-01 06:00', + moveEndExpectedAt: '2026-03-01 11:45', + approvalStatus: '审批完成', + destination: '其他', + destinationName: '青岛港务临时停放点', + moveType: '保养', + expectedMileageKm: '15.0', + plateNo: '鲁B55555', + startMileageKm: '11220.00', + startElectricKwh: '65.00', + startHydrogen: '62.50', + h2Unit: '%', + creatorName: '陈静', + createTime: '2026-03-01 05:40' + } + ]; + }); + var list = listState[0]; + + function matchRange(valStr, range) { + if (!range || !range[0] || !range[1]) return true; + var s = ''; + var e = ''; + if (range[0] && range[0].format) s = range[0].format('YYYY-MM-DD'); + if (range[1] && range[1].format) e = range[1].format('YYYY-MM-DD'); + if (!s && !e) return true; + var v = String(valStr || '').slice(0, 10); + if (s && v < s) return false; + if (e && v > e) return false; + return true; + } + + function applyFilters(rows) { + return (rows || []).filter(function (r) { + if (!matchRange(r.moveStartAt, applied.moveStartRange)) return false; + if (applied.plateNo && r.plateNo !== applied.plateNo) return false; + if (applied.moveTypes && applied.moveTypes.length > 0) { + if (applied.moveTypes.indexOf(r.moveType) < 0) return false; + } + return true; + }); + } + + var filtered = useMemo(function () { return applyFilters(list); }, [list, applied]); + + var paged = useMemo(function () { + var start = (page - 1) * pageSize; + return filtered.slice(start, start + pageSize); + }, [filtered, page, pageSize]); + + var handleQuery = useCallback(function () { + setApplied(Object.assign({}, draft)); + setPage(1); + }, [draft]); + + var handleReset = useCallback(function () { + var empty = { moveStartRange: null, moveTypes: [], plateNo: undefined }; + setDraft(empty); + setApplied(empty); + setPage(1); + }, []); + + var columns = useMemo(function () { + return [ + { title: '异动开始日期', dataIndex: 'moveStartAt', key: 'moveStartAt', width: 160, render: function (v) { return fmtYMDHM(v); } }, + { title: '异动预计结束日期', dataIndex: 'moveEndExpectedAt', key: 'moveEndExpectedAt', width: 170, render: function (v) { return fmtYMDHM(v); } }, + { title: '审批状态', dataIndex: 'approvalStatus', key: 'approvalStatus', width: 100 }, + { title: '异动目的地', dataIndex: 'destination', key: 'destination', width: 110 }, + { title: '目的地名称', dataIndex: 'destinationName', key: 'destinationName', width: 160, ellipsis: true }, + { title: '异动类型', dataIndex: 'moveType', key: 'moveType', width: 90 }, + { title: '预计异动里程(km)', dataIndex: 'expectedMileageKm', key: 'expectedMileageKm', width: 150 }, + { title: '车牌号', dataIndex: 'plateNo', key: 'plateNo', width: 110 }, + { title: '异动开始里程(km)', dataIndex: 'startMileageKm', key: 'startMileageKm', width: 160 }, + { title: '异动开始电量(kWh)', dataIndex: 'startElectricKwh', key: 'startElectricKwh', width: 160 }, + { + title: '异动开始氢量', + key: 'startHydrogen', + width: 130, + render: function (_, r) { + var u = r.h2Unit || ''; + return (r.startHydrogen != null && r.startHydrogen !== '') ? String(r.startHydrogen) + (u ? ' ' + u : '') : '-'; + } + }, + { title: '创建人', dataIndex: 'creatorName', key: 'creatorName', width: 100 }, + { title: '创建时间', dataIndex: 'createTime', key: 'createTime', width: 160, render: function (v) { return fmtYMDHM(v); } }, + { + title: '操作', + key: 'action', + width: 120, + fixed: 'right', + render: function (_, r) { + var nodes = [ + React.createElement(Button, { key: 'view', type: 'link', size: 'small', onClick: function () { message.info('跳转异动-查看页(原型)ID:' + r.id); } }, '查看') + ]; + if (canShowMovementEdit(r.approvalStatus)) { + nodes.push(React.createElement(Button, { key: 'edit', type: 'link', size: 'small', onClick: function () { message.info('跳转异动-编辑页(原型)ID:' + r.id); } }, '编辑')); + } + return React.createElement(React.Fragment, null, nodes); + } + } + ]; + }, []); + + return React.createElement(App, null, + React.createElement('div', { style: layoutStyle }, + React.createElement('div', { style: { display: 'flex', alignItems: 'center', justifyContent: 'space-between', marginBottom: 16, flexWrap: 'wrap', gap: 8 } }, + React.createElement(Breadcrumb, { items: [{ title: '运维管理' }, { title: '车辆业务' }, { title: '异动管理' }] }), + React.createElement(Button, { type: 'link', style: { padding: 0 }, onClick: function () { setRequirementModalOpen(true); } }, '查看需求说明') + ), + + React.createElement(Modal, { + title: '需求说明', + open: requirementModalOpen, + onCancel: function () { setRequirementModalOpen(false); }, + width: 720, + footer: React.createElement(Button, { onClick: function () { setRequirementModalOpen(false); } }, '关闭'), + bodyStyle: { maxHeight: '70vh', overflow: 'auto' } + }, React.createElement('div', { style: { whiteSpace: 'pre-wrap', fontSize: 13, lineHeight: 1.6, color: 'rgba(0,0,0,0.85)' } }, requirementDocContent)), + + React.createElement(Card, { style: { marginBottom: 16 } }, + React.createElement('div', { style: { display: 'grid', gridTemplateColumns: '1fr 1fr 1fr', gap: '16px 24px', alignItems: 'start' } }, + React.createElement('div', { style: filterItemStyle }, + React.createElement('div', { style: filterLabelStyle }, '异动开始日期'), + React.createElement(RangePicker, { + style: filterControlStyle, + value: draft.moveStartRange, + onChange: function (v) { setDraft(function (p) { return Object.assign({}, p, { moveStartRange: v }); }); }, + placeholder: ['开始日期', '结束日期'], + showTime: false + }) + ), + React.createElement('div', { style: filterItemStyle }, + React.createElement('div', { style: filterLabelStyle }, '异动类型'), + React.createElement(Select, { + mode: 'multiple', + placeholder: '请选择异动类型(可多选)', + style: filterControlStyle, + value: draft.moveTypes, + onChange: function (v) { setDraft(function (p) { return Object.assign({}, p, { moveTypes: v || [] }); }); }, + allowClear: true, + options: moveTypeOptions, + maxTagCount: 'responsive' + }) + ), + React.createElement('div', { style: filterItemStyle }, + React.createElement('div', { style: filterLabelStyle }, '车牌号'), + React.createElement(Select, { + placeholder: '请输入或选择车牌号', + style: filterControlStyle, + value: draft.plateNo, + onChange: function (v) { setDraft(function (p) { return Object.assign({}, p, { plateNo: v }); }); }, + allowClear: true, + showSearch: true, + options: plateOptions, + filterOption: filterOption + }) + ) + ), + React.createElement('div', { style: { display: 'flex', justifyContent: 'flex-end', gap: 8, marginTop: 16 } }, + React.createElement(Button, { onClick: handleReset }, '重置'), + React.createElement(Button, { type: 'primary', onClick: handleQuery }, '查询') + ) + ), + + React.createElement(Card, null, + React.createElement('style', null, tableSingleLineStyle), + React.createElement('div', { className: 'movement-list-table' }, + React.createElement(Table, { + rowKey: 'id', + columns: columns, + dataSource: paged, + scroll: { x: 2240 }, + size: 'small', + pagination: { + current: page, + pageSize: pageSize, + total: filtered.length, + showSizeChanger: true, + showQuickJumper: true, + showTotal: function (t) { return '共 ' + t + ' 条'; }, + onChange: function (pg, ps) { setPage(pg); if (ps) setPageSize(ps); } + } + }) + ) + ) + ) + ); +}; diff --git a/web端/运维管理/车辆业务/异动管理.新增.jsx b/web端/运维管理/车辆业务/异动管理.新增.jsx new file mode 100644 index 0000000..bb653d2 --- /dev/null +++ b/web端/运维管理/车辆业务/异动管理.新增.jsx @@ -0,0 +1,564 @@ +// 【重要】必须使用 const Component 作为组件变量名 +// 运维管理 - 车辆业务 - 异动管理 - 新增 + +const Component = function () { + var useState = React.useState; + var useMemo = React.useMemo; + var useCallback = React.useCallback; + + var antd = window.antd; + var App = antd.App; + var Breadcrumb = antd.Breadcrumb; + var Card = antd.Card; + var Button = antd.Button; + var Input = antd.Input; + var Select = antd.Select; + var DatePicker = antd.DatePicker; + var Table = antd.Table; + var Modal = antd.Modal; + var message = antd.message; + + function filterOption(input, option) { + var label = (option && (option.label || option.children)) || ''; + return String(label).toLowerCase().indexOf(String(input || '').toLowerCase()) >= 0; + } + + function toFixed2Input(v) { + var s = String(v === null || v === undefined ? '' : v); + s = s.replace(/[^\d.]/g, ''); + var firstDot = s.indexOf('.'); + if (firstDot >= 0) { + s = s.slice(0, firstDot + 1) + s.slice(firstDot + 1).replace(/\./g, ''); + } + if (firstDot >= 0) { + var a = s.split('.'); + s = a[0] + '.' + (a[1] || '').slice(0, 2); + } + return s; + } + + var layoutStyle = { padding: '16px 24px', background: '#f5f5f5', minHeight: '100vh' }; + var labelStyle = { marginBottom: 6, fontSize: 14, color: 'rgba(0,0,0,0.65)' }; + var formItemStyle = { marginBottom: 12 }; + var controlStyle = { width: '100%' }; + var reqStarStyle = { color: '#ff4d4f', marginRight: 4 }; + var reqStar = React.createElement('span', { style: reqStarStyle }, '*'); + + // 车辆表(用于车牌选择与反写) + var vehicleDb = useMemo(function () { + return [ + { plateNo: '粤A12345', vehicleType: '厢式货车', brand: '东风', model: 'DFH1180', departParking: '天河智慧停车场', h2Unit: 'MPa' }, + { plateNo: '粤B11111', vehicleType: '轿车', brand: '比亚迪', model: '汉', departParking: '南山科技园停车场', h2Unit: '%' }, + { plateNo: '浙A11111', vehicleType: 'SUV', brand: '小鹏', model: 'P7', departParking: '西湖景区停车场', h2Unit: '%' }, + { plateNo: '浙B22222', vehicleType: '轿车', brand: '蔚来', model: 'ET5', departParking: '宁波江北停车场', h2Unit: 'MPa' }, + { plateNo: '沪A30003', vehicleType: '厢式货车', brand: '福田', model: 'BJ1180', departParking: '张江园区停车场', h2Unit: 'MPa' } + ]; + }, []); + + var plateOptions = useMemo(function () { + return vehicleDb.map(function (v) { return { value: v.plateNo, label: v.plateNo }; }); + }, [vehicleDb]); + + var destinationTypeOptions = useMemo(function () { + return [ + { value: '停车场', label: '停车场' }, + { value: '维修站', label: '维修站' }, + { value: '其他', label: '其他' } + ]; + }, []); + + var destinationParkingOptions = useMemo(function () { + return [ + { value: '天河智慧停车场', label: '天河智慧停车场' }, + { value: '南山科技园停车场', label: '南山科技园停车场' }, + { value: '西湖景区停车场', label: '西湖景区停车场' }, + { value: '宁波江北停车场', label: '宁波江北停车场' }, + { value: '张江园区停车场', label: '张江园区停车场' } + ]; + }, []); + + var destinationRepairOptions = useMemo(function () { + return [ + { value: '杭州拱墅维修站', label: '杭州拱墅维修站' }, + { value: '广州天河维修站', label: '广州天河维修站' }, + { value: '上海浦东维修站', label: '上海浦东维修站' } + ]; + }, []); + + var changeTypeOptions = useMemo(function () { + return [ + { value: '维修', label: '维修' }, + { value: '保养', label: '保养' }, + { value: '年审', label: '年审' }, + { value: '其他', label: '其他' } + ]; + }, []); + + var requirementModalState = useState(false); + var requirementModalOpen = requirementModalState[0]; + var setRequirementModalOpen = requirementModalState[1]; + + var requirementDocContent = [ + '一个「数字化资产ONEOS运管平台」中的「异动管理」「新增」模块', + '#面包屑:运维管理-车辆业务-异动管理-新增', + '', + '1.异动情况;', + '1.1.异动开始日期:必填项,日期选择器,格式为:YYYY-MM-DD HH:MM;', + '1.2.异动预计结束日期:必填项,日期选择器,格式为:YYYY-MM-DD HH:MM;', + '1.3.异动目的地:必填项,选择器,选项为:停车场、维修站、其他;', + '2.4.目的地名称:必填项,如异动目的地为停车场,则此处为停车场(选择器),如异动目的地为维修站,则此处为维修站(选择器),如异动目的地为其他,则此处为输入框(自定义输入);', + '2.5.异动类型:必填项,选择器,选项为:维修、保养、年审、其他;', + '2.6.预计异动里程:输入框,支持2位小数输入,后缀为km;', + '2.7.备注:文本域,支持自定义输入;', + '', + '2.车辆信息:', + '2.1.车牌号:显示车牌号,支持输入框模糊搜索下拉匹配对应选项;', + '2.2.车辆类型:根据所选车辆类型自动反写,默认提示为请先选择车辆;', + '2.3.品牌:根据所选车辆品牌自动反写,默认提示为请先选择车辆;', + '2.4.型号:根据所选车辆型号自动反写,默认提示为请先选择车辆;', + '2.5.出发停车场:根据所选车辆出发时停车场自动反写,默认提示为请先选择车辆;', + '2.6.异动开始里程:必填项,输入框,精确至2位小数,后缀为km;', + '2.7.异动开始氢量:必填项,输入框,精确至2位小数,后缀为%或MPa,根据所选车辆型号中获取;', + '2.8.异动开始电量:必填项,输入框,精确至2位小数,后缀为kWh;', + '2.9.操作:删除;', + '2.10.新增一行:铺满整行;', + '', + '3.底部为提交审核、保存、取消;' + ].join('\n'); + + var formState = useState({ + startTime: null, + plannedEndTime: null, + destinationType: undefined, + destinationName: undefined, + destinationNameOther: '', + changeType: undefined, + plannedMileageKm: '', + remark: '' + }); + var form = formState[0]; + var setForm = formState[1]; + + var errorsState = useState({}); + var errors = errorsState[0]; + var setErrors = errorsState[1]; + + var rowIdRef = React.useRef(2); + var vehiclesState = useState([ + { + id: 1, + plateNo: undefined, + vehicleType: '', + brand: '', + model: '', + departParking: '', + h2Unit: '', + startMileageKm: '', + startHydrogen: '', + startElectricKwh: '' + } + ]); + var vehicles = vehiclesState[0]; + var setVehicles = vehiclesState[1]; + + var updateForm = useCallback(function (patch) { + setForm(function (p) { return Object.assign({}, p, patch); }); + }, []); + + var updateRow = useCallback(function (index, patch) { + setVehicles(function (prev) { + var list = prev.slice(); + var cur = list[index] || {}; + list[index] = Object.assign({}, cur, patch); + return list; + }); + }, []); + + var handlePlateChange = useCallback(function (index, plateNo) { + var v = vehicleDb.find(function (x) { return x.plateNo === plateNo; }); + updateRow(index, { + plateNo: plateNo, + vehicleType: v ? v.vehicleType : '', + brand: v ? v.brand : '', + model: v ? v.model : '', + departParking: v ? v.departParking : '', + h2Unit: v ? v.h2Unit : '' + }); + }, [vehicleDb, updateRow]); + + var addRow = useCallback(function () { + setVehicles(function (prev) { + return prev.concat([{ + id: rowIdRef.current++, + plateNo: undefined, + vehicleType: '', + brand: '', + model: '', + departParking: '', + h2Unit: '', + startMileageKm: '', + startHydrogen: '', + startElectricKwh: '' + }]); + }); + }, []); + + var removeRow = useCallback(function (index) { + setVehicles(function (prev) { + var list = prev.slice(); + list.splice(index, 1); + if (list.length === 0) { + return [{ + id: rowIdRef.current++, + plateNo: undefined, + vehicleType: '', + brand: '', + model: '', + departParking: '', + h2Unit: '', + startMileageKm: '', + startHydrogen: '', + startElectricKwh: '' + }]; + } + return list; + }); + }, []); + + function validate() { + var e = {}; + if (!form.startTime) e.startTime = '请选择异动开始日期'; + if (!form.plannedEndTime) e.plannedEndTime = '请选择异动预计结束日期'; + if (!form.destinationType) e.destinationType = '请选择异动目的地'; + if (form.destinationType === '其他') { + if (!String(form.destinationNameOther || '').trim()) e.destinationName = '请输入目的地名称'; + } else { + if (!form.destinationName) e.destinationName = '请选择目的地名称'; + } + if (!form.changeType) e.changeType = '请选择异动类型'; + + var effectiveRows = (vehicles || []).filter(function (r) { return r && String(r.plateNo || '').trim(); }); + if (effectiveRows.length === 0) e.vehicleList = '请至少选择一辆车'; + + for (var i = 0; i < (vehicles || []).length; i++) { + var r = vehicles[i] || {}; + if (!String(r.plateNo || '').trim()) continue; + if (!String(r.startMileageKm || '').trim()) e['row_' + i + '_startMileageKm'] = '请输入异动开始里程'; + if (!String(r.startHydrogen || '').trim()) e['row_' + i + '_startHydrogen'] = '请输入异动开始氢量'; + if (!String(r.startElectricKwh || '').trim()) e['row_' + i + '_startElectricKwh'] = '请输入异动开始电量'; + } + + setErrors(e); + return Object.keys(e).length === 0; + } + + var handleSubmitAudit = useCallback(function () { + if (!validate()) { + message.error('请完善必填项后再提交'); + return; + } + Modal.confirm({ + title: '确认提交审核?', + content: '提交后将进入审批流程(原型)。', + okText: '提交审核', + cancelText: '取消', + onOk: function () { + message.success('已提交审核(原型)'); + } + }); + }, [form, vehicles]); + + var handleSave = useCallback(function () { + message.info('已保存(原型,不做校验)'); + }, []); + + var handleCancel = useCallback(function () { + Modal.confirm({ + title: '是否确认取消', + content: '取消将会丢失所有已填写内容,是否确认?', + okText: '确认', + cancelText: '取消', + onOk: function () { + message.info('返回异动管理列表页(原型)'); + } + }); + }, []); + + // 目的地名称控件:随异动目的地变化 + var destinationNameLabel = form.destinationType === '维修站' ? '维修站' : (form.destinationType === '停车场' ? '停车场' : '目的地名称'); + var destinationNameNode = (function () { + if (form.destinationType === '其他') { + return React.createElement(Input, { + placeholder: '请输入目的地名称', + value: form.destinationNameOther, + onChange: function (e) { updateForm({ destinationNameOther: e.target.value }); }, + status: errors.destinationName ? 'error' : undefined + }); + } + var opts = form.destinationType === '维修站' ? destinationRepairOptions : destinationParkingOptions; + return React.createElement(Select, { + placeholder: '请选择' + destinationNameLabel, + style: controlStyle, + value: form.destinationName, + onChange: function (v) { updateForm({ destinationName: v }); }, + allowClear: true, + showSearch: true, + options: opts, + filterOption: filterOption, + status: errors.destinationName ? 'error' : undefined, + disabled: !form.destinationType + }); + })(); + + var vehicleColumns = useMemo(function () { + return [ + { + title: React.createElement('span', null, reqStar, '车牌号'), + key: 'plateNo', + width: 140, + render: function (_, r, index) { + return React.createElement(Select, { + placeholder: '请输入或选择车牌号', + style: { width: '100%' }, + value: r.plateNo, + onChange: function (v) { handlePlateChange(index, v); }, + allowClear: true, + showSearch: true, + options: plateOptions, + filterOption: filterOption, + status: errors.vehicleList ? 'error' : undefined + }); + } + }, + { + title: '车辆类型', + key: 'vehicleType', + width: 120, + render: function (_, r) { + return React.createElement(Input, { value: r.vehicleType ? r.vehicleType : '请先选择车辆', disabled: true }); + } + }, + { + title: '品牌', + key: 'brand', + width: 100, + render: function (_, r) { + return React.createElement(Input, { value: r.brand ? r.brand : '请先选择车辆', disabled: true }); + } + }, + { + title: '型号', + key: 'model', + width: 120, + render: function (_, r) { + return React.createElement(Input, { value: r.model ? r.model : '请先选择车辆', disabled: true }); + } + }, + { + title: '出发停车场', + key: 'departParking', + width: 160, + render: function (_, r) { + return React.createElement(Input, { value: r.departParking ? r.departParking : '请先选择车辆', disabled: true }); + } + }, + { + title: React.createElement('span', null, reqStar, '异动开始里程'), + key: 'startMileageKm', + width: 160, + render: function (_, r, index) { + var k = 'row_' + index + '_startMileageKm'; + return React.createElement(Input, { + value: r.startMileageKm, + onChange: function (e) { updateRow(index, { startMileageKm: toFixed2Input(e.target.value) }); }, + placeholder: '0.00', + addonAfter: 'km', + status: errors[k] ? 'error' : undefined + }); + } + }, + { + title: React.createElement('span', null, reqStar, '异动开始氢量'), + key: 'startHydrogen', + width: 150, + render: function (_, r, index) { + var k = 'row_' + index + '_startHydrogen'; + var unit = r.h2Unit || '%/MPa'; + return React.createElement(Input, { + value: r.startHydrogen, + onChange: function (e) { updateRow(index, { startHydrogen: toFixed2Input(e.target.value) }); }, + placeholder: '0.00', + addonAfter: unit, + status: errors[k] ? 'error' : undefined + }); + } + }, + { + title: React.createElement('span', null, reqStar, '异动开始电量'), + key: 'startElectricKwh', + width: 150, + render: function (_, r, index) { + var k = 'row_' + index + '_startElectricKwh'; + return React.createElement(Input, { + value: r.startElectricKwh, + onChange: function (e) { updateRow(index, { startElectricKwh: toFixed2Input(e.target.value) }); }, + placeholder: '0.00', + addonAfter: 'kWh', + status: errors[k] ? 'error' : undefined + }); + } + }, + { + title: '操作', + key: 'action', + width: 80, + fixed: 'right', + render: function (_, __, index) { + return React.createElement(Button, { type: 'link', danger: true, size: 'small', onClick: function () { removeRow(index); } }, '删除'); + } + } + ]; + }, [plateOptions, errors, handlePlateChange, updateRow, removeRow]); + + return React.createElement(App, null, + React.createElement('div', { style: layoutStyle }, + React.createElement('div', { style: { display: 'flex', alignItems: 'center', justifyContent: 'space-between', marginBottom: 16, flexWrap: 'wrap', gap: 8 } }, + React.createElement(Breadcrumb, { items: [{ title: '运维管理' }, { title: '车辆业务' }, { title: '异动管理' }, { title: '新增' }] }), + React.createElement(Button, { type: 'link', style: { padding: 0 }, onClick: function () { setRequirementModalOpen(true); } }, '查看需求说明') + ), + + React.createElement(Modal, { + title: '需求说明', + open: requirementModalOpen, + onCancel: function () { setRequirementModalOpen(false); }, + width: 720, + footer: React.createElement(Button, { onClick: function () { setRequirementModalOpen(false); } }, '关闭'), + bodyStyle: { maxHeight: '70vh', overflow: 'auto' } + }, React.createElement('div', { style: { whiteSpace: 'pre-wrap', fontSize: 13, lineHeight: 1.6, color: 'rgba(0,0,0,0.85)' } }, requirementDocContent)), + + React.createElement(Card, { title: '异动情况', style: { marginBottom: 16 } }, + React.createElement('div', { style: { display: 'grid', gridTemplateColumns: '1fr 1fr 1fr', gap: '16px 24px', alignItems: 'start' } }, + React.createElement('div', { style: formItemStyle }, + React.createElement('div', { style: labelStyle }, reqStar, '异动开始日期'), + React.createElement(DatePicker, { + style: controlStyle, + showTime: { format: 'HH:mm' }, + format: 'YYYY-MM-DD HH:mm', + placeholder: '请选择异动开始日期', + value: form.startTime, + onChange: function (v) { updateForm({ startTime: v }); }, + status: errors.startTime ? 'error' : undefined + }), + errors.startTime ? React.createElement('div', { style: { marginTop: 4, color: '#ff4d4f', fontSize: 12 } }, errors.startTime) : null + ), + React.createElement('div', { style: formItemStyle }, + React.createElement('div', { style: labelStyle }, reqStar, '异动预计结束日期'), + React.createElement(DatePicker, { + style: controlStyle, + showTime: { format: 'HH:mm' }, + format: 'YYYY-MM-DD HH:mm', + placeholder: '请选择异动预计结束日期', + value: form.plannedEndTime, + onChange: function (v) { updateForm({ plannedEndTime: v }); }, + status: errors.plannedEndTime ? 'error' : undefined + }), + errors.plannedEndTime ? React.createElement('div', { style: { marginTop: 4, color: '#ff4d4f', fontSize: 12 } }, errors.plannedEndTime) : null + ), + React.createElement('div', { style: formItemStyle }, + React.createElement('div', { style: labelStyle }, reqStar, '异动目的地'), + React.createElement(Select, { + placeholder: '请选择异动目的地', + style: controlStyle, + value: form.destinationType, + onChange: function (v) { + setForm(function (p) { + return Object.assign({}, p, { + destinationType: v, + destinationName: undefined, + destinationNameOther: '' + }); + }); + }, + allowClear: true, + options: destinationTypeOptions, + status: errors.destinationType ? 'error' : undefined + }), + errors.destinationType ? React.createElement('div', { style: { marginTop: 4, color: '#ff4d4f', fontSize: 12 } }, errors.destinationType) : null + ), + + React.createElement('div', { style: formItemStyle }, + React.createElement('div', { style: labelStyle }, reqStar, destinationNameLabel), + destinationNameNode, + errors.destinationName ? React.createElement('div', { style: { marginTop: 4, color: '#ff4d4f', fontSize: 12 } }, errors.destinationName) : null + ), + React.createElement('div', { style: formItemStyle }, + React.createElement('div', { style: labelStyle }, reqStar, '异动类型'), + React.createElement(Select, { + placeholder: '请选择异动类型', + style: controlStyle, + value: form.changeType, + onChange: function (v) { updateForm({ changeType: v }); }, + allowClear: true, + options: changeTypeOptions, + status: errors.changeType ? 'error' : undefined + }), + errors.changeType ? React.createElement('div', { style: { marginTop: 4, color: '#ff4d4f', fontSize: 12 } }, errors.changeType) : null + ), + React.createElement('div', { style: formItemStyle }, + React.createElement('div', { style: labelStyle }, '预计异动里程'), + React.createElement(Input, { + placeholder: '0.00', + value: form.plannedMileageKm, + onChange: function (e) { updateForm({ plannedMileageKm: toFixed2Input(e.target.value) }); }, + addonAfter: 'km' + }) + ), + + React.createElement('div', { style: Object.assign({}, formItemStyle, { gridColumn: 'span 3' }) }, + React.createElement('div', { style: labelStyle }, '备注'), + React.createElement(Input.TextArea, { + placeholder: '请输入备注', + value: form.remark, + onChange: function (e) { updateForm({ remark: e.target.value }); }, + autoSize: { minRows: 3, maxRows: 6 } + }) + ) + ) + ), + + React.createElement(Card, { title: '车辆信息', style: { marginBottom: 16 } }, + errors.vehicleList ? React.createElement('div', { style: { marginBottom: 12, color: '#ff4d4f', fontSize: 12 } }, errors.vehicleList) : null, + React.createElement(Table, { + rowKey: 'id', + columns: vehicleColumns, + dataSource: vehicles, + size: 'small', + pagination: false, + scroll: { x: 1250 } + }), + React.createElement(Button, { type: 'dashed', style: { marginTop: 12, width: '100%' }, onClick: addRow }, '新增一行') + ), + + React.createElement('div', { style: { height: 56 } }), + React.createElement('div', { + style: { + position: 'fixed', + left: 0, + right: 0, + bottom: 0, + padding: '12px 24px', + background: '#fff', + borderTop: '1px solid #f0f0f0', + display: 'flex', + gap: 8, + zIndex: 10 + } + }, + React.createElement(Button, { type: 'primary', onClick: handleSubmitAudit }, '提交审核'), + React.createElement(Button, { onClick: handleSave }, '保存'), + React.createElement(Button, { onClick: handleCancel }, '取消') + ) + ) + ); +}; + diff --git a/web端/运维管理/车辆业务/调拨管理-接收记录.jsx b/web端/运维管理/车辆业务/调拨管理-接收记录.jsx new file mode 100644 index 0000000..cddd334 --- /dev/null +++ b/web端/运维管理/车辆业务/调拨管理-接收记录.jsx @@ -0,0 +1,447 @@ +// 【重要】必须使用 const Component 作为组件变量名 +// 运维管理 - 车辆业务 - 调拨管理 - 接收记录 + +const Component = function () { + var useState = React.useState; + var useMemo = React.useMemo; + var useCallback = React.useCallback; + + var antd = window.antd; + var App = antd.App; + var Breadcrumb = antd.Breadcrumb; + var Card = antd.Card; + var Button = antd.Button; + var Input = antd.Input; + var Select = antd.Select; + var DatePicker = antd.DatePicker; + var Table = antd.Table; + var Modal = antd.Modal; + var message = antd.message; + + function filterOption(input, option) { + var label = (option && (option.label || option.children)) || ''; + return String(label).toLowerCase().indexOf(String(input || '').toLowerCase()) >= 0; + } + + function getInitialReceiveDate() { + return null; + } + + var layoutStyle = { padding: '16px 24px', background: '#f5f5f5', minHeight: '100vh' }; + var labelStyle = { marginBottom: 6, fontSize: 14, color: 'rgba(0,0,0,0.65)' }; + var formItemStyle = { marginBottom: 12 }; + var controlStyle = { width: '100%' }; + var reqStarStyle = { color: '#ff4d4f', marginRight: 4 }; + var reqStar = React.createElement('span', { style: reqStarStyle }, '*'); + + var vehicleDb = useMemo(function () { + return [ + { plateNo: '粤A12345', vehicleType: '厢式货车', brand: '东风', model: 'DFH1180', departParking: '天河智慧停车场', h2Unit: 'MPa' }, + { plateNo: '粤B11111', vehicleType: '轿车', brand: '比亚迪', model: '汉', departParking: '南山科技园停车场', h2Unit: '%' }, + { plateNo: '浙A11111', vehicleType: 'SUV', brand: '小鹏', model: 'P7', departParking: '西湖景区停车场', h2Unit: '%' }, + { plateNo: '浙B22222', vehicleType: '轿车', brand: '蔚来', model: 'ET5', departParking: '宁波江北停车场', h2Unit: 'MPa' }, + { plateNo: '沪A30003', vehicleType: '厢式货车', brand: '福田', model: 'BJ1180', departParking: '张江园区停车场', h2Unit: 'MPa' } + ]; + }, []); + + // 调拨单带出:按车牌匹配的出发读数(切换车牌时同步) + var departSnapshotByPlate = useMemo(function () { + return { + '粤A12345': { departMileageKm: '15230.12', departHydrogen: '28.30', h2Unit: 'MPa', departElectricKwh: '68.40' }, + '粤B11111': { departMileageKm: '8020.50', departHydrogen: '55.00', h2Unit: '%', departElectricKwh: '62.10' }, + '浙A11111': { departMileageKm: '12010.00', departHydrogen: '60.00', h2Unit: '%', departElectricKwh: '55.20' }, + '浙B22222': { departMileageKm: '15010.00', departHydrogen: '22.10', h2Unit: 'MPa', departElectricKwh: '58.00' }, + '沪A30003': { departMileageKm: '9800.00', departHydrogen: '26.00', h2Unit: 'MPa', departElectricKwh: '69.00' } + }; + }, []); + + var plateOptions = useMemo(function () { + return vehicleDb.map(function (v) { return { value: v.plateNo, label: v.plateNo }; }); + }, [vehicleDb]); + + var situationState = useState({ + transferDateStr: '2026-02-20', + departRegionText: '广东省-广州市', + receiveRegionText: '浙江省-杭州市', + receivePerson: '王芳', + method: '第三方运输', + reason: '场站资源调整,车辆调度至杭州项目点。', + carrierName: '顺丰同城运输', + carrierPhone: '400-123-4567', + receiveDate: getInitialReceiveDate() + }); + var situation = situationState[0]; + var setSituation = situationState[1]; + + var errorsState = useState({}); + var errors = errorsState[0]; + var setErrors = errorsState[1]; + + var requirementModalState = useState(false); + var requirementModalOpen = requirementModalState[0]; + var setRequirementModalOpen = requirementModalState[1]; + + var requirementDocContent = [ + '一个「数字化资产ONEOS运管平台」中的「调拨管理」「接收记录」模块', + '#面包屑:运维管理-车辆业务-调拨管理-接收记录', + '页面采用多个卡片的方式进行展示', + '1.调拨情况:', + '1.1.调拨日期:显示调拨日期,格式为:YYYY-MM-DD;', + '1.2.出发区域:显示出发区域,格式为省-市2级;', + '1.3.接收区域:显示接收区域,格式为省-市2级;', + '1.4.接收人:显示接收人姓名;', + '1.5.调拨方式:显示调拨方式,选项为:第三方运输、司机驾驶;', + '1.6.调拨原因:显示调拨原因;', + '1.7.运输方名称:显示运输方名称;', + '1.8.运输方联系方式:显示运输方联系方式;', + '1.9.接收日期:日期选择器,精确至天;', + '', + '2.调拨车辆清单;', + '#以列表方式展示:', + '2.1.车牌号:显示车牌号,支持输入框模糊搜索下拉匹配对应选项;', + '2.2.车辆类型:根据所选车辆类型自动反写,默认提示为请先选择车辆;', + '2.3.品牌:根据所选车辆品牌自动反写,默认提示为请先选择车辆;', + '2.4.型号:根据所选车辆型号自动反写,默认提示为请先选择车辆;', + '2.5.出发停车场:根据所选车辆出发时停车场自动反写,默认提示为请先选择车辆;', + '2.6.出发里程:显示出发里程,输入框,精确至2位小数,后缀为km;', + '2.7.接收里程:必填项,输入框,精确至2位小数,后缀为km;', + '2.8.出发氢量:显示出发氢量,输入框,精确至2位小数,后缀为%或MPa,根据所选车辆型号中获取;', + '2.9.接收氢量:必填项,输入框,精确至2位小数,后缀为%或MPa,根据所选车辆型号中获取;', + '2.10.出发电量:显示出发电量,输入框,精确至2位小数,后缀为kWh;', + '2.11.接收电量:必填项,输入框,精确至2位小数,后缀为kWh;', + '2.12.操作:无;' + ].join('\n'); + + var vehiclesState = useState([ + { + id: 1, + plateNo: '粤A12345', + vehicleType: '厢式货车', + brand: '东风', + model: 'DFH1180', + departParking: '天河智慧停车场', + departMileageKm: '15230.12', + departHydrogen: '28.30', + h2Unit: 'MPa', + departElectricKwh: '68.40', + receiveMileageKm: '', + receiveHydrogen: '', + receiveElectricKwh: '' + }, + { + id: 2, + plateNo: '浙A11111', + vehicleType: 'SUV', + brand: '小鹏', + model: 'P7', + departParking: '西湖景区停车场', + departMileageKm: '12010.00', + departHydrogen: '60.00', + h2Unit: '%', + departElectricKwh: '55.20', + receiveMileageKm: '', + receiveHydrogen: '', + receiveElectricKwh: '' + } + ]); + var vehicles = vehiclesState[0]; + var setVehicles = vehiclesState[1]; + + function toFixed2Input(v) { + var s = String(v === null || v === undefined ? '' : v); + s = s.replace(/[^\d.]/g, ''); + var firstDot = s.indexOf('.'); + if (firstDot >= 0) { + s = s.slice(0, firstDot + 1) + s.slice(firstDot + 1).replace(/\./g, ''); + } + if (firstDot >= 0) { + var a = s.split('.'); + s = a[0] + '.' + (a[1] || '').slice(0, 2); + } + return s; + } + + var updateRow = useCallback(function (index, patch) { + setVehicles(function (prev) { + var list = prev.slice(); + var cur = list[index] || {}; + list[index] = Object.assign({}, cur, patch); + return list; + }); + }, []); + + var handlePlateChange = useCallback(function (index, plateNo) { + var v = vehicleDb.find(function (x) { return x.plateNo === plateNo; }); + var snap = departSnapshotByPlate[plateNo] || {}; + updateRow(index, { + plateNo: plateNo, + vehicleType: v ? v.vehicleType : '', + brand: v ? v.brand : '', + model: v ? v.model : '', + departParking: v ? v.departParking : '', + h2Unit: v ? v.h2Unit : (snap.h2Unit || ''), + departMileageKm: snap.departMileageKm != null ? String(snap.departMileageKm) : '', + departHydrogen: snap.departHydrogen != null ? String(snap.departHydrogen) : '', + departElectricKwh: snap.departElectricKwh != null ? String(snap.departElectricKwh) : '' + }); + }, [vehicleDb, departSnapshotByPlate, updateRow]); + + function validate() { + var e = {}; + if (!situation.receiveDate) e.receiveDate = '请选择接收日期'; + + for (var i = 0; i < (vehicles || []).length; i++) { + var r = vehicles[i] || {}; + if (!String(r.plateNo || '').trim()) continue; + if (!String(r.receiveMileageKm || '').trim()) e['row_' + i + '_receiveMileageKm'] = '请输入接收里程'; + if (!String(r.receiveHydrogen || '').trim()) e['row_' + i + '_receiveHydrogen'] = '请输入接收氢量'; + if (!String(r.receiveElectricKwh || '').trim()) e['row_' + i + '_receiveElectricKwh'] = '请输入接收电量'; + } + + setErrors(e); + return Object.keys(e).length === 0; + } + + var handleSubmit = useCallback(function () { + if (!validate()) { + message.error('请完善接收日期及车辆接收信息'); + return; + } + Modal.confirm({ + title: '确认提交接收记录?', + content: '提交后接收数据将归档(原型)。', + okText: '确定', + cancelText: '取消', + onOk: function () { + message.success('接收记录已提交(原型)'); + } + }); + }, [situation, vehicles]); + + var handleBack = useCallback(function () { + message.info('返回调拨管理页(原型)'); + }, []); + + var vehicleColumns = useMemo(function () { + return [ + { + title: '车牌号', + key: 'plateNo', + width: 130, + render: function (_, r, index) { + return React.createElement(Select, { + placeholder: '请输入或选择车牌号', + style: { width: '100%' }, + value: r.plateNo, + onChange: function (v) { handlePlateChange(index, v); }, + allowClear: true, + showSearch: true, + options: plateOptions, + filterOption: filterOption + }); + } + }, + { + title: '车辆类型', + key: 'vehicleType', + width: 110, + render: function (_, r) { + return React.createElement(Input, { value: r.vehicleType ? r.vehicleType : '请先选择车辆', disabled: true }); + } + }, + { + title: '品牌', + key: 'brand', + width: 90, + render: function (_, r) { + return React.createElement(Input, { value: r.brand ? r.brand : '请先选择车辆', disabled: true }); + } + }, + { + title: '型号', + key: 'model', + width: 110, + render: function (_, r) { + return React.createElement(Input, { value: r.model ? r.model : '请先选择车辆', disabled: true }); + } + }, + { + title: '出发停车场', + key: 'departParking', + width: 140, + render: function (_, r) { + return React.createElement(Input, { value: r.departParking ? r.departParking : '请先选择车辆', disabled: true }); + } + }, + { + title: '出发里程', + key: 'departMileageKm', + width: 120, + render: function (_, r) { + return React.createElement(Input, { value: r.departMileageKm || '', disabled: true, addonAfter: 'km' }); + } + }, + { + title: React.createElement('span', null, reqStar, '接收里程'), + key: 'receiveMileageKm', + width: 120, + render: function (_, r, index) { + var k = 'row_' + index + '_receiveMileageKm'; + return React.createElement(Input, { + value: r.receiveMileageKm, + onChange: function (e) { updateRow(index, { receiveMileageKm: toFixed2Input(e.target.value) }); }, + placeholder: '0.00', + addonAfter: 'km', + status: errors[k] ? 'error' : undefined + }); + } + }, + { + title: '出发氢量', + key: 'departHydrogen', + width: 120, + render: function (_, r) { + var unit = r.h2Unit || ''; + return React.createElement(Input, { value: r.departHydrogen || '', disabled: true, addonAfter: unit || '-' }); + } + }, + { + title: React.createElement('span', null, reqStar, '接收氢量'), + key: 'receiveHydrogen', + width: 120, + render: function (_, r, index) { + var k = 'row_' + index + '_receiveHydrogen'; + var unit = r.h2Unit || '%/MPa'; + return React.createElement(Input, { + value: r.receiveHydrogen, + onChange: function (e) { updateRow(index, { receiveHydrogen: toFixed2Input(e.target.value) }); }, + placeholder: '0.00', + addonAfter: unit, + status: errors[k] ? 'error' : undefined + }); + } + }, + { + title: '出发电量', + key: 'departElectricKwh', + width: 120, + render: function (_, r) { + return React.createElement(Input, { value: r.departElectricKwh || '', disabled: true, addonAfter: 'kWh' }); + } + }, + { + title: React.createElement('span', null, reqStar, '接收电量'), + key: 'receiveElectricKwh', + width: 120, + render: function (_, r, index) { + var k = 'row_' + index + '_receiveElectricKwh'; + return React.createElement(Input, { + value: r.receiveElectricKwh, + onChange: function (e) { updateRow(index, { receiveElectricKwh: toFixed2Input(e.target.value) }); }, + placeholder: '0.00', + addonAfter: 'kWh', + status: errors[k] ? 'error' : undefined + }); + } + } + ]; + }, [plateOptions, errors, handlePlateChange, updateRow]); + + return React.createElement(App, null, + React.createElement('div', { style: layoutStyle }, + React.createElement('div', { style: { display: 'flex', alignItems: 'center', justifyContent: 'space-between', marginBottom: 16, flexWrap: 'wrap', gap: 8 } }, + React.createElement(Breadcrumb, { items: [{ title: '运维管理' }, { title: '车辆业务' }, { title: '调拨管理' }, { title: '接收记录' }] }), + React.createElement(Button, { type: 'link', style: { padding: 0 }, onClick: function () { setRequirementModalOpen(true); } }, '查看需求说明') + ), + + React.createElement(Modal, { + title: '需求说明', + open: requirementModalOpen, + onCancel: function () { setRequirementModalOpen(false); }, + width: 720, + footer: React.createElement(Button, { onClick: function () { setRequirementModalOpen(false); } }, '关闭'), + bodyStyle: { maxHeight: '70vh', overflow: 'auto' } + }, React.createElement('div', { style: { whiteSpace: 'pre-wrap', fontSize: 13, lineHeight: 1.6, color: 'rgba(0,0,0,0.85)' } }, requirementDocContent)), + + React.createElement(Card, { title: '调拨情况', style: { marginBottom: 16 } }, + React.createElement('div', { style: { display: 'grid', gridTemplateColumns: '1fr 1fr 1fr', gap: '16px 24px', alignItems: 'start' } }, + React.createElement('div', { style: formItemStyle }, + React.createElement('div', { style: labelStyle }, '调拨日期'), + React.createElement(Input, { value: situation.transferDateStr, disabled: true, style: controlStyle }) + ), + React.createElement('div', { style: formItemStyle }, + React.createElement('div', { style: labelStyle }, '出发区域'), + React.createElement(Input, { value: situation.departRegionText, disabled: true, style: controlStyle }) + ), + React.createElement('div', { style: formItemStyle }, + React.createElement('div', { style: labelStyle }, '接收区域'), + React.createElement(Input, { value: situation.receiveRegionText, disabled: true, style: controlStyle }) + ), + React.createElement('div', { style: formItemStyle }, + React.createElement('div', { style: labelStyle }, '接收人'), + React.createElement(Input, { value: situation.receivePerson, disabled: true, style: controlStyle }) + ), + React.createElement('div', { style: formItemStyle }, + React.createElement('div', { style: labelStyle }, '调拨方式'), + React.createElement(Input, { value: situation.method, disabled: true, style: controlStyle }) + ), + React.createElement('div', { style: formItemStyle }), + React.createElement('div', { style: Object.assign({}, formItemStyle, { gridColumn: 'span 3' }) }, + React.createElement('div', { style: labelStyle }, '调拨原因'), + React.createElement(Input.TextArea, { value: situation.reason, disabled: true, autoSize: { minRows: 2, maxRows: 4 } }) + ), + React.createElement('div', { style: formItemStyle }, + React.createElement('div', { style: labelStyle }, '运输方名称'), + React.createElement(Input, { value: situation.carrierName, disabled: true, style: controlStyle }) + ), + React.createElement('div', { style: formItemStyle }, + React.createElement('div', { style: labelStyle }, '运输方联系方式'), + React.createElement(Input, { value: situation.carrierPhone, disabled: true, style: controlStyle }) + ), + React.createElement('div', { style: formItemStyle }, + React.createElement('div', { style: labelStyle }, reqStar, '接收日期'), + React.createElement(DatePicker, { + style: controlStyle, + format: 'YYYY-MM-DD', + placeholder: '请选择接收日期', + value: situation.receiveDate, + onChange: function (v) { setSituation(function (p) { return Object.assign({}, p, { receiveDate: v }); }); }, + status: errors.receiveDate ? 'error' : undefined + }), + errors.receiveDate ? React.createElement('div', { style: { marginTop: 4, color: '#ff4d4f', fontSize: 12 } }, errors.receiveDate) : null + ) + ) + ), + + React.createElement(Card, { title: '调拨车辆清单', style: { marginBottom: 16 } }, + React.createElement(Table, { + rowKey: 'id', + columns: vehicleColumns, + dataSource: vehicles, + size: 'small', + pagination: false, + scroll: { x: 1400 } + }) + ), + + React.createElement('div', { style: { height: 56 } }), + React.createElement('div', { + style: { + position: 'fixed', + left: 0, + right: 0, + bottom: 0, + padding: '12px 24px', + background: '#fff', + borderTop: '1px solid #f0f0f0', + display: 'flex', + gap: 8, + zIndex: 10 + } + }, + React.createElement(Button, { type: 'primary', onClick: handleSubmit }, '提交'), + React.createElement(Button, { onClick: handleBack }, '返回') + ) + ) + ); +}; diff --git a/web端/运维管理/车辆业务/调拨管理-新增.jsx b/web端/运维管理/车辆业务/调拨管理-新增.jsx new file mode 100644 index 0000000..9d0e034 --- /dev/null +++ b/web端/运维管理/车辆业务/调拨管理-新增.jsx @@ -0,0 +1,552 @@ +// 【重要】必须使用 const Component 作为组件变量名 +// 运维管理 - 车辆业务 - 调拨管理 - 新增 + +const Component = function () { + var useState = React.useState; + var useMemo = React.useMemo; + var useCallback = React.useCallback; + + var antd = window.antd; + var App = antd.App; + var Breadcrumb = antd.Breadcrumb; + var Card = antd.Card; + var Button = antd.Button; + var Input = antd.Input; + var Select = antd.Select; + var DatePicker = antd.DatePicker; + var Cascader = antd.Cascader; + var Table = antd.Table; + var Modal = antd.Modal; + var message = antd.message; + + function filterOption(input, option) { + var label = (option && (option.label || option.children)) || ''; + return String(label).toLowerCase().indexOf(String(input || '').toLowerCase()) >= 0; + } + + var layoutStyle = { padding: '16px 24px', background: '#f5f5f5', minHeight: '100vh' }; + var labelStyle = { marginBottom: 6, fontSize: 14, color: 'rgba(0,0,0,0.65)' }; + var formItemStyle = { marginBottom: 12 }; + var controlStyle = { width: '100%' }; + var reqStarStyle = { color: '#ff4d4f', marginRight: 4 }; + var reqStar = React.createElement('span', { style: reqStarStyle }, '*'); + + var regionOptions = useMemo(function () { + return [ + { value: 'zhejiang', label: '浙江省', children: [{ value: 'hangzhou', label: '杭州市' }, { value: 'ningbo', label: '宁波市' }, { value: 'jiaxing', label: '嘉兴市' }] }, + { value: 'shanghai', label: '上海市', children: [{ value: 'shanghai', label: '上海市' }] }, + { value: 'guangdong', label: '广东省', children: [{ value: 'guangzhou', label: '广州市' }, { value: 'shenzhen', label: '深圳市' }, { value: 'dongguan', label: '东莞市' }] } + ]; + }, []); + + // 用户表(原型:全量用户) + var userOptions = useMemo(function () { + return [ + { value: '张明', label: '张明' }, + { value: '王芳', label: '王芳' }, + { value: '李华', label: '李华' }, + { value: '赵强', label: '赵强' }, + { value: '陈静', label: '陈静' } + ]; + }, []); + + var methodOptions = useMemo(function () { + return [ + { value: '第三方运输', label: '第三方运输' }, + { value: '司机驾驶', label: '司机驾驶' } + ]; + }, []); + + // 车辆表(用于车牌选择与反写) + var vehicleDb = useMemo(function () { + return [ + { plateNo: '粤A12345', vehicleType: '厢式货车', brand: '东风', model: 'DFH1180', departParking: '天河智慧停车场', h2Unit: 'MPa' }, + { plateNo: '粤B11111', vehicleType: '轿车', brand: '比亚迪', model: '汉', departParking: '南山科技园停车场', h2Unit: '%' }, + { plateNo: '浙A11111', vehicleType: 'SUV', brand: '小鹏', model: 'P7', departParking: '西湖景区停车场', h2Unit: '%' }, + { plateNo: '浙B22222', vehicleType: '轿车', brand: '蔚来', model: 'ET5', departParking: '宁波江北停车场', h2Unit: 'MPa' }, + { plateNo: '沪A30003', vehicleType: '厢式货车', brand: '福田', model: 'BJ1180', departParking: '张江园区停车场', h2Unit: 'MPa' } + ]; + }, []); + + var plateOptions = useMemo(function () { + return vehicleDb.map(function (v) { return { value: v.plateNo, label: v.plateNo }; }); + }, [vehicleDb]); + + var formState = useState({ + transferDate: null, + departRegion: undefined, + receiveRegion: undefined, + receivePerson: undefined, + method: undefined, + reason: '', + carrierName: '', + carrierPhone: '' + }); + var form = formState[0]; + var setForm = formState[1]; + + var errorsState = useState({}); + var errors = errorsState[0]; + var setErrors = errorsState[1]; + + var requirementModalState = useState(false); + var requirementModalOpen = requirementModalState[0]; + var setRequirementModalOpen = requirementModalState[1]; + + var requirementDocContent = [ + '一个「数字化资产ONEOS运管平台」中的「调拨管理」「新增」模块', + '#面包屑:运维管理-车辆业务-调拨管理-新增', + '页面采用多个卡片的方式进行展示', + '1.调拨情况:', + '1.1.调拨日期:必填项,日期选择器,精确至天,格式为:YYYY-MM-DD;', + '1.2.出发区域:必填项,地区选择器,支持省-市2级;', + '1.3.接收区域:必填项,地区选择器,支持省-市2级;', + '1.4.接收人:必填项,选择器,支持输入框模糊搜索下拉匹配对应选项,接收人取自用户表所有用户;', + '1.5.调拨方式:必填项,选择器,默认提示:请选择调拨方式,选项为:第三方运输、司机驾驶;', + '1.6.调拨原因:必填项,文本域,支持用户自定义输入;', + '1.7.运输方名称:必填项,输入框,默认提示:请输入运输方名称/司机姓名;', + '1.8.运输方联系方式:必填项,输入框,默认提示:请输入运输方/司机联系方式;', + '', + '2.调拨车辆清单;', + '#以列表方式展示:', + '2.1.车牌号:必填项,选择器,支持输入框模糊搜索下拉匹配对应选项;', + '2.2.车辆类型:根据所选车辆类型自动反写,默认提示为请先选择车辆;', + '2.3.品牌:根据所选车辆品牌自动反写,默认提示为请先选择车辆;', + '2.4.型号:根据所选车辆型号自动反写,默认提示为请先选择车辆;', + '2.5.出发停车场:根据所选车辆出发时停车场自动反写,默认提示为请先选择车辆;', + '2.6.出发里程:必填项,输入框,精确至2位小数,后缀为km;', + '2.7.出发氢量:必填项,输入框,精确至2位小数,后缀为%或MPa,根据所选车辆型号中获取;', + '2.8.出发电量:必填项,输入框,精确至2位小数,后缀为kWh;', + '2.9.操作:删除', + '2.10.底部为新增一行,铺满整行;', + '需要至少提交一辆车才能完成调拨,否则提交审核时提示:请选择调拨车辆;' + ].join('\n'); + + var rowIdRef = React.useRef(2); + var vehiclesState = useState([ + { + id: 1, + plateNo: undefined, + vehicleType: '', + brand: '', + model: '', + departParking: '', + departMileageKm: '', + departHydrogen: '', + h2Unit: '', + departElectricKwh: '' + } + ]); + var vehicles = vehiclesState[0]; + var setVehicles = vehiclesState[1]; + + function toFixed2Input(v) { + var s = String(v === null || v === undefined ? '' : v); + // 仅做简单清洗:保留数字与小数点 + s = s.replace(/[^\d.]/g, ''); + // 只保留第一个小数点 + var firstDot = s.indexOf('.'); + if (firstDot >= 0) { + s = s.slice(0, firstDot + 1) + s.slice(firstDot + 1).replace(/\./g, ''); + } + // 最多两位小数(输入态不强制补0) + if (firstDot >= 0) { + var a = s.split('.'); + s = a[0] + '.' + (a[1] || '').slice(0, 2); + } + return s; + } + + var updateForm = useCallback(function (patch) { + setForm(function (p) { return Object.assign({}, p, patch); }); + }, []); + + var updateRow = useCallback(function (index, patch) { + setVehicles(function (prev) { + var list = prev.slice(); + var cur = list[index] || {}; + list[index] = Object.assign({}, cur, patch); + return list; + }); + }, []); + + var handlePlateChange = useCallback(function (index, plateNo) { + var v = vehicleDb.find(function (x) { return x.plateNo === plateNo; }); + updateRow(index, { + plateNo: plateNo, + vehicleType: v ? v.vehicleType : '', + brand: v ? v.brand : '', + model: v ? v.model : '', + departParking: v ? v.departParking : '', + h2Unit: v ? v.h2Unit : '' + }); + }, [vehicleDb, updateRow]); + + var addRow = useCallback(function () { + setVehicles(function (prev) { + return prev.concat([{ + id: rowIdRef.current++, + plateNo: undefined, + vehicleType: '', + brand: '', + model: '', + departParking: '', + departMileageKm: '', + departHydrogen: '', + h2Unit: '', + departElectricKwh: '' + }]); + }); + }, []); + + var removeRow = useCallback(function (index) { + setVehicles(function (prev) { + var list = prev.slice(); + list.splice(index, 1); + if (list.length === 0) { + return [{ + id: rowIdRef.current++, + plateNo: undefined, + vehicleType: '', + brand: '', + model: '', + departParking: '', + departMileageKm: '', + departHydrogen: '', + h2Unit: '', + departElectricKwh: '' + }]; + } + return list; + }); + }, []); + + function validate() { + var e = {}; + if (!form.transferDate) e.transferDate = '请选择调拨日期'; + if (!form.departRegion || form.departRegion.length < 2) e.departRegion = '请选择出发区域'; + if (!form.receiveRegion || form.receiveRegion.length < 2) e.receiveRegion = '请选择接收区域'; + if (!form.receivePerson) e.receivePerson = '请选择接收人'; + if (!form.method) e.method = '请选择调拨方式'; + if (!String(form.reason || '').trim()) e.reason = '请输入调拨原因'; + if (!String(form.carrierName || '').trim()) e.carrierName = '请输入运输方名称/司机姓名'; + if (!String(form.carrierPhone || '').trim()) e.carrierPhone = '请输入运输方/司机联系方式'; + + var effectiveRows = (vehicles || []).filter(function (r) { return r && String(r.plateNo || '').trim(); }); + if (effectiveRows.length === 0) e.vehicleList = '请选择调拨车辆'; + + for (var i = 0; i < (vehicles || []).length; i++) { + var r = vehicles[i] || {}; + if (!String(r.plateNo || '').trim()) continue; + if (!String(r.departMileageKm || '').trim()) e['row_' + i + '_departMileageKm'] = '请输入出发里程'; + if (!String(r.departHydrogen || '').trim()) e['row_' + i + '_departHydrogen'] = '请输入出发氢量'; + if (!String(r.departElectricKwh || '').trim()) e['row_' + i + '_departElectricKwh'] = '请输入出发电量'; + } + + setErrors(e); + return Object.keys(e).length === 0; + } + + var handleSubmitAudit = useCallback(function () { + if (!validate()) { + if (errors && errors.vehicleList) message.error(errors.vehicleList); + else if (!form.transferDate) message.error('请完善必填项后再提交'); + else message.error('请完善必填项后再提交'); + return; + } + Modal.confirm({ + title: '确认提交审核?', + content: '提交后将进入审批流程(原型)。', + okText: '提交审核', + cancelText: '取消', + onOk: function () { + message.success('已提交审核(原型)'); + } + }); + }, [form, errors]); + + var handleSave = useCallback(function () { + message.info('已保存(原型,不做校验)'); + }, []); + + var handleCancel = useCallback(function () { + Modal.confirm({ + title: '是否确认取消', + content: '取消将会丢失所有已填写内容,是否确认?', + okText: '确认', + cancelText: '取消', + onOk: function () { + message.info('返回调拨管理页(原型)'); + } + }); + }, []); + + var vehicleColumns = useMemo(function () { + return [ + { + title: React.createElement('span', null, reqStar, '车牌号'), + key: 'plateNo', + width: 140, + render: function (_, r, index) { + return React.createElement(Select, { + placeholder: '请输入或选择车牌号', + style: { width: '100%' }, + value: r.plateNo, + onChange: function (v) { handlePlateChange(index, v); }, + allowClear: true, + showSearch: true, + options: plateOptions, + filterOption: filterOption, + status: errors.vehicleList ? 'error' : undefined + }); + } + }, + { + title: '车辆类型', + key: 'vehicleType', + width: 120, + render: function (_, r) { + return React.createElement(Input, { value: r.vehicleType ? r.vehicleType : '请先选择车辆', disabled: true }); + } + }, + { + title: '品牌', + key: 'brand', + width: 100, + render: function (_, r) { + return React.createElement(Input, { value: r.brand ? r.brand : '请先选择车辆', disabled: true }); + } + }, + { + title: '型号', + key: 'model', + width: 120, + render: function (_, r) { + return React.createElement(Input, { value: r.model ? r.model : '请先选择车辆', disabled: true }); + } + }, + { + title: '出发停车场', + key: 'departParking', + width: 160, + render: function (_, r) { + return React.createElement(Input, { value: r.departParking ? r.departParking : '请先选择车辆', disabled: true }); + } + }, + { + title: React.createElement('span', null, reqStar, '出发里程'), + key: 'departMileageKm', + width: 140, + render: function (_, r, index) { + var k = 'row_' + index + '_departMileageKm'; + return React.createElement(Input, { + value: r.departMileageKm, + onChange: function (e) { updateRow(index, { departMileageKm: toFixed2Input(e.target.value) }); }, + placeholder: '0.00', + addonAfter: 'km', + status: errors[k] ? 'error' : undefined + }); + } + }, + { + title: React.createElement('span', null, reqStar, '出发氢量'), + key: 'departHydrogen', + width: 140, + render: function (_, r, index) { + var k = 'row_' + index + '_departHydrogen'; + var unit = r.h2Unit || '%/MPa'; + return React.createElement(Input, { + value: r.departHydrogen, + onChange: function (e) { updateRow(index, { departHydrogen: toFixed2Input(e.target.value) }); }, + placeholder: '0.00', + addonAfter: unit, + status: errors[k] ? 'error' : undefined + }); + } + }, + { + title: React.createElement('span', null, reqStar, '出发电量'), + key: 'departElectricKwh', + width: 150, + render: function (_, r, index) { + var k = 'row_' + index + '_departElectricKwh'; + return React.createElement(Input, { + value: r.departElectricKwh, + onChange: function (e) { updateRow(index, { departElectricKwh: toFixed2Input(e.target.value) }); }, + placeholder: '0.00', + addonAfter: 'kWh', + status: errors[k] ? 'error' : undefined + }); + } + }, + { + title: '操作', + key: 'action', + width: 80, + fixed: 'right', + render: function (_, __, index) { + return React.createElement(Button, { type: 'link', danger: true, size: 'small', onClick: function () { removeRow(index); } }, '删除'); + } + } + ]; + }, [plateOptions, errors, handlePlateChange, updateRow, removeRow]); + + return React.createElement(App, null, + React.createElement('div', { style: layoutStyle }, + React.createElement('div', { style: { display: 'flex', alignItems: 'center', justifyContent: 'space-between', marginBottom: 16, flexWrap: 'wrap', gap: 8 } }, + React.createElement(Breadcrumb, { items: [{ title: '运维管理' }, { title: '车辆业务' }, { title: '调拨管理' }, { title: '新增' }] }), + React.createElement(Button, { type: 'link', style: { padding: 0 }, onClick: function () { setRequirementModalOpen(true); } }, '查看需求说明') + ), + + React.createElement(Modal, { + title: '需求说明', + open: requirementModalOpen, + onCancel: function () { setRequirementModalOpen(false); }, + width: 720, + footer: React.createElement(Button, { onClick: function () { setRequirementModalOpen(false); } }, '关闭'), + bodyStyle: { maxHeight: '70vh', overflow: 'auto' } + }, React.createElement('div', { style: { whiteSpace: 'pre-wrap', fontSize: 13, lineHeight: 1.6, color: 'rgba(0,0,0,0.85)' } }, requirementDocContent)), + + React.createElement(Card, { title: '调拨情况', style: { marginBottom: 16 } }, + React.createElement('div', { style: { display: 'grid', gridTemplateColumns: '1fr 1fr 1fr', gap: '16px 24px', alignItems: 'start' } }, + React.createElement('div', { style: formItemStyle }, + React.createElement('div', { style: labelStyle }, reqStar, '调拨日期'), + React.createElement(DatePicker, { + style: controlStyle, + format: 'YYYY-MM-DD', + placeholder: '请选择调拨日期', + value: form.transferDate, + onChange: function (v) { updateForm({ transferDate: v }); }, + status: errors.transferDate ? 'error' : undefined + }), + errors.transferDate ? React.createElement('div', { style: { marginTop: 4, color: '#ff4d4f', fontSize: 12 } }, errors.transferDate) : null + ), + React.createElement('div', { style: formItemStyle }, + React.createElement('div', { style: labelStyle }, reqStar, '出发区域'), + React.createElement(Cascader, { + style: controlStyle, + placeholder: '请选择出发区域', + options: regionOptions, + value: form.departRegion, + onChange: function (v) { updateForm({ departRegion: v }); }, + allowClear: true, + status: errors.departRegion ? 'error' : undefined + }), + errors.departRegion ? React.createElement('div', { style: { marginTop: 4, color: '#ff4d4f', fontSize: 12 } }, errors.departRegion) : null + ), + React.createElement('div', { style: formItemStyle }, + React.createElement('div', { style: labelStyle }, reqStar, '接收区域'), + React.createElement(Cascader, { + style: controlStyle, + placeholder: '请选择接收区域', + options: regionOptions, + value: form.receiveRegion, + onChange: function (v) { updateForm({ receiveRegion: v }); }, + allowClear: true, + status: errors.receiveRegion ? 'error' : undefined + }), + errors.receiveRegion ? React.createElement('div', { style: { marginTop: 4, color: '#ff4d4f', fontSize: 12 } }, errors.receiveRegion) : null + ), + + React.createElement('div', { style: formItemStyle }, + React.createElement('div', { style: labelStyle }, reqStar, '接收人'), + React.createElement(Select, { + placeholder: '请输入或选择接收人', + style: controlStyle, + value: form.receivePerson, + onChange: function (v) { updateForm({ receivePerson: v }); }, + allowClear: true, + showSearch: true, + options: userOptions, + filterOption: filterOption, + status: errors.receivePerson ? 'error' : undefined + }), + errors.receivePerson ? React.createElement('div', { style: { marginTop: 4, color: '#ff4d4f', fontSize: 12 } }, errors.receivePerson) : null + ), + React.createElement('div', { style: formItemStyle }, + React.createElement('div', { style: labelStyle }, reqStar, '调拨方式'), + React.createElement(Select, { + placeholder: '请选择调拨方式', + style: controlStyle, + value: form.method, + onChange: function (v) { updateForm({ method: v }); }, + allowClear: true, + options: methodOptions, + status: errors.method ? 'error' : undefined + }), + errors.method ? React.createElement('div', { style: { marginTop: 4, color: '#ff4d4f', fontSize: 12 } }, errors.method) : null + ), + React.createElement('div', { style: formItemStyle }), + + React.createElement('div', { style: Object.assign({}, formItemStyle, { gridColumn: 'span 3' }) }, + React.createElement('div', { style: labelStyle }, reqStar, '调拨原因'), + React.createElement(Input.TextArea, { + placeholder: '请输入调拨原因', + value: form.reason, + onChange: function (e) { updateForm({ reason: e.target.value }); }, + autoSize: { minRows: 3, maxRows: 6 }, + status: errors.reason ? 'error' : undefined + }), + errors.reason ? React.createElement('div', { style: { marginTop: 4, color: '#ff4d4f', fontSize: 12 } }, errors.reason) : null + ), + + React.createElement('div', { style: formItemStyle }, + React.createElement('div', { style: labelStyle }, reqStar, '运输方名称'), + React.createElement(Input, { + placeholder: '请输入运输方名称/司机姓名', + value: form.carrierName, + onChange: function (e) { updateForm({ carrierName: e.target.value }); }, + status: errors.carrierName ? 'error' : undefined + }), + errors.carrierName ? React.createElement('div', { style: { marginTop: 4, color: '#ff4d4f', fontSize: 12 } }, errors.carrierName) : null + ), + React.createElement('div', { style: formItemStyle }, + React.createElement('div', { style: labelStyle }, reqStar, '运输方联系方式'), + React.createElement(Input, { + placeholder: '请输入运输方/司机联系方式', + value: form.carrierPhone, + onChange: function (e) { updateForm({ carrierPhone: e.target.value }); }, + status: errors.carrierPhone ? 'error' : undefined + }), + errors.carrierPhone ? React.createElement('div', { style: { marginTop: 4, color: '#ff4d4f', fontSize: 12 } }, errors.carrierPhone) : null + ), + React.createElement('div', { style: formItemStyle }) + ) + ), + + React.createElement(Card, { title: '调拨车辆清单', style: { marginBottom: 16 } }, + errors.vehicleList ? React.createElement('div', { style: { marginBottom: 12, color: '#ff4d4f', fontSize: 12 } }, errors.vehicleList) : null, + React.createElement(Table, { + rowKey: 'id', + columns: vehicleColumns, + dataSource: vehicles, + size: 'small', + pagination: false, + scroll: { x: 1100 } + }), + React.createElement(Button, { type: 'dashed', style: { marginTop: 12, width: '100%' }, onClick: addRow }, '新增一行') + ), + + React.createElement('div', { style: { height: 56 } }), + React.createElement('div', { + style: { + position: 'fixed', + left: 0, + right: 0, + bottom: 0, + padding: '12px 24px', + background: '#fff', + borderTop: '1px solid #f0f0f0', + display: 'flex', + gap: 8, + zIndex: 10 + } + }, + React.createElement(Button, { type: 'primary', onClick: handleSubmitAudit }, '提交审核'), + React.createElement(Button, { onClick: handleSave }, '保存'), + React.createElement(Button, { onClick: handleCancel }, '取消') + ) + ) + ); +}; + diff --git a/web端/运维管理/车辆业务/调拨管理-查看.jsx b/web端/运维管理/车辆业务/调拨管理-查看.jsx new file mode 100644 index 0000000..9de7e1e --- /dev/null +++ b/web端/运维管理/车辆业务/调拨管理-查看.jsx @@ -0,0 +1,302 @@ +// 【重要】必须使用 const Component 作为组件变量名 +// 运维管理 - 车辆业务 - 调拨管理 - 查看(只读) + +const Component = function () { + var useState = React.useState; + var useMemo = React.useMemo; + + var antd = window.antd; + var App = antd.App; + var Breadcrumb = antd.Breadcrumb; + var Card = antd.Card; + var Button = antd.Button; + var Input = antd.Input; + var Select = antd.Select; + var DatePicker = antd.DatePicker; + var Cascader = antd.Cascader; + var Table = antd.Table; + var Modal = antd.Modal; + var message = antd.message; + + function getInitialTransferDate() { + try { + if (window.dayjs) return window.dayjs('2026-02-20'); + } catch (e1) {} + try { + if (window.moment) return window.moment('2026-02-20', 'YYYY-MM-DD'); + } catch (e2) {} + return null; + } + + var layoutStyle = { padding: '16px 24px', background: '#f5f5f5', minHeight: '100vh' }; + var labelStyle = { marginBottom: 6, fontSize: 14, color: 'rgba(0,0,0,0.65)' }; + var formItemStyle = { marginBottom: 12 }; + var controlStyle = { width: '100%' }; + + var regionOptions = useMemo(function () { + return [ + { value: 'zhejiang', label: '浙江省', children: [{ value: 'hangzhou', label: '杭州市' }, { value: 'ningbo', label: '宁波市' }, { value: 'jiaxing', label: '嘉兴市' }] }, + { value: 'shanghai', label: '上海市', children: [{ value: 'shanghai', label: '上海市' }] }, + { value: 'guangdong', label: '广东省', children: [{ value: 'guangzhou', label: '广州市' }, { value: 'shenzhen', label: '深圳市' }, { value: 'dongguan', label: '东莞市' }] } + ]; + }, []); + + var userOptions = useMemo(function () { + return [ + { value: '张明', label: '张明' }, + { value: '王芳', label: '王芳' }, + { value: '李华', label: '李华' }, + { value: '赵强', label: '赵强' }, + { value: '陈静', label: '陈静' } + ]; + }, []); + + var methodOptions = useMemo(function () { + return [ + { value: '第三方运输', label: '第三方运输' }, + { value: '司机驾驶', label: '司机驾驶' } + ]; + }, []); + + // 原型:从详情接口拉取的只读数据(与新增/编辑字段一致) + var form = { + transferDate: getInitialTransferDate(), + departRegion: ['guangdong', 'guangzhou'], + receiveRegion: ['zhejiang', 'hangzhou'], + receivePerson: '王芳', + method: '第三方运输', + reason: '场站资源调整,车辆需从广州仓库调度至杭州项目点,保障项目运力。', + carrierName: '顺丰同城运输', + carrierPhone: '400-123-4567' + }; + + var vehicles = [ + { + id: 1, + plateNo: '粤A12345', + vehicleType: '厢式货车', + brand: '东风', + model: 'DFH1180', + departParking: '天河智慧停车场', + departMileageKm: '15230.12', + departHydrogen: '28.30', + h2Unit: 'MPa', + departElectricKwh: '68.40' + }, + { + id: 2, + plateNo: '浙A11111', + vehicleType: 'SUV', + brand: '小鹏', + model: 'P7', + departParking: '西湖景区停车场', + departMileageKm: '12010.00', + departHydrogen: '60.00', + h2Unit: '%', + departElectricKwh: '55.20' + } + ]; + + var requirementModalState = useState(false); + var requirementModalOpen = requirementModalState[0]; + var setRequirementModalOpen = requirementModalState[1]; + + var requirementDocContent = [ + '一个「数字化资产ONEOS运管平台」中的「调拨管理」「查看」模块', + '#面包屑:运维管理-车辆业务-调拨管理-查看', + '页面布局与字段与「调拨管理-新增」一致,所有表单项均为只读,仅供查询展示。', + '', + '1.调拨情况:调拨日期、出发/接收区域、接收人、调拨方式、调拨原因、运输方名称、运输方联系方式 — 全部禁用不可编辑。', + '2.调拨车辆清单:车牌号、车辆类型、品牌、型号、出发停车场、出发里程、出发氢量、出发电量 — 全部禁用;不提供新增行与删除操作。', + '3.底部仅提供「返回」按钮,返回调拨管理列表(原型)。' + ].join('\n'); + + var vehicleColumns = useMemo(function () { + return [ + { + title: '车牌号', + key: 'plateNo', + width: 140, + render: function (_, r) { + return React.createElement(Input, { value: r.plateNo || '-', disabled: true }); + } + }, + { + title: '车辆类型', + key: 'vehicleType', + width: 120, + render: function (_, r) { + return React.createElement(Input, { value: r.vehicleType || '-', disabled: true }); + } + }, + { + title: '品牌', + key: 'brand', + width: 100, + render: function (_, r) { + return React.createElement(Input, { value: r.brand || '-', disabled: true }); + } + }, + { + title: '型号', + key: 'model', + width: 120, + render: function (_, r) { + return React.createElement(Input, { value: r.model || '-', disabled: true }); + } + }, + { + title: '出发停车场', + key: 'departParking', + width: 160, + render: function (_, r) { + return React.createElement(Input, { value: r.departParking || '-', disabled: true }); + } + }, + { + title: '出发里程', + key: 'departMileageKm', + width: 140, + render: function (_, r) { + return React.createElement(Input, { value: r.departMileageKm || '-', disabled: true, addonAfter: 'km' }); + } + }, + { + title: '出发氢量', + key: 'departHydrogen', + width: 140, + render: function (_, r) { + var unit = r.h2Unit || ''; + return React.createElement(Input, { value: r.departHydrogen || '-', disabled: true, addonAfter: unit || '-' }); + } + }, + { + title: '出发电量', + key: 'departElectricKwh', + width: 150, + render: function (_, r) { + return React.createElement(Input, { value: r.departElectricKwh || '-', disabled: true, addonAfter: 'kWh' }); + } + } + ]; + }, []); + + return React.createElement(App, null, + React.createElement('div', { style: layoutStyle }, + React.createElement('div', { style: { display: 'flex', alignItems: 'center', justifyContent: 'space-between', marginBottom: 16, flexWrap: 'wrap', gap: 8 } }, + React.createElement(Breadcrumb, { items: [{ title: '运维管理' }, { title: '车辆业务' }, { title: '调拨管理' }, { title: '查看' }] }), + React.createElement(Button, { type: 'link', style: { padding: 0 }, onClick: function () { setRequirementModalOpen(true); } }, '查看需求说明') + ), + + React.createElement(Modal, { + title: '需求说明', + open: requirementModalOpen, + onCancel: function () { setRequirementModalOpen(false); }, + width: 720, + footer: React.createElement(Button, { onClick: function () { setRequirementModalOpen(false); } }, '关闭'), + bodyStyle: { maxHeight: '70vh', overflow: 'auto' } + }, React.createElement('div', { style: { whiteSpace: 'pre-wrap', fontSize: 13, lineHeight: 1.6, color: 'rgba(0,0,0,0.85)' } }, requirementDocContent)), + + React.createElement(Card, { title: '调拨情况', style: { marginBottom: 16 } }, + React.createElement('div', { style: { display: 'grid', gridTemplateColumns: '1fr 1fr 1fr', gap: '16px 24px', alignItems: 'start' } }, + React.createElement('div', { style: formItemStyle }, + React.createElement('div', { style: labelStyle }, '调拨日期'), + React.createElement(DatePicker, { + style: controlStyle, + format: 'YYYY-MM-DD', + value: form.transferDate, + disabled: true, + inputReadOnly: true + }) + ), + React.createElement('div', { style: formItemStyle }, + React.createElement('div', { style: labelStyle }, '出发区域'), + React.createElement(Cascader, { + style: controlStyle, + options: regionOptions, + value: form.departRegion, + disabled: true + }) + ), + React.createElement('div', { style: formItemStyle }, + React.createElement('div', { style: labelStyle }, '接收区域'), + React.createElement(Cascader, { + style: controlStyle, + options: regionOptions, + value: form.receiveRegion, + disabled: true + }) + ), + + React.createElement('div', { style: formItemStyle }, + React.createElement('div', { style: labelStyle }, '接收人'), + React.createElement(Select, { + style: controlStyle, + value: form.receivePerson, + options: userOptions, + disabled: true + }) + ), + React.createElement('div', { style: formItemStyle }, + React.createElement('div', { style: labelStyle }, '调拨方式'), + React.createElement(Select, { + style: controlStyle, + value: form.method, + options: methodOptions, + disabled: true + }) + ), + React.createElement('div', { style: formItemStyle }), + + React.createElement('div', { style: Object.assign({}, formItemStyle, { gridColumn: 'span 3' }) }, + React.createElement('div', { style: labelStyle }, '调拨原因'), + React.createElement(Input.TextArea, { + value: form.reason, + disabled: true, + autoSize: { minRows: 3, maxRows: 6 } + }) + ), + + React.createElement('div', { style: formItemStyle }, + React.createElement('div', { style: labelStyle }, '运输方名称'), + React.createElement(Input, { value: form.carrierName, disabled: true }) + ), + React.createElement('div', { style: formItemStyle }, + React.createElement('div', { style: labelStyle }, '运输方联系方式'), + React.createElement(Input, { value: form.carrierPhone, disabled: true }) + ), + React.createElement('div', { style: formItemStyle }) + ) + ), + + React.createElement(Card, { title: '调拨车辆清单', style: { marginBottom: 16 } }, + React.createElement(Table, { + rowKey: 'id', + columns: vehicleColumns, + dataSource: vehicles, + size: 'small', + pagination: false, + scroll: { x: 1020 } + }) + ), + + React.createElement('div', { style: { height: 56 } }), + React.createElement('div', { + style: { + position: 'fixed', + left: 0, + right: 0, + bottom: 0, + padding: '12px 24px', + background: '#fff', + borderTop: '1px solid #f0f0f0', + display: 'flex', + gap: 8, + zIndex: 10 + } + }, + React.createElement(Button, { onClick: function () { message.info('返回调拨管理页(原型)'); } }, '返回') + ) + ) + ); +}; diff --git a/web端/运维管理/车辆业务/调拨管理-编辑.jsx b/web端/运维管理/车辆业务/调拨管理-编辑.jsx new file mode 100644 index 0000000..1556b50 --- /dev/null +++ b/web端/运维管理/车辆业务/调拨管理-编辑.jsx @@ -0,0 +1,547 @@ +// 【重要】必须使用 const Component 作为组件变量名 +// 运维管理 - 车辆业务 - 调拨管理 - 编辑(样例:所有字段已填写) + +const Component = function () { + var useState = React.useState; + var useMemo = React.useMemo; + var useCallback = React.useCallback; + + var antd = window.antd; + var App = antd.App; + var Breadcrumb = antd.Breadcrumb; + var Card = antd.Card; + var Button = antd.Button; + var Input = antd.Input; + var Select = antd.Select; + var DatePicker = antd.DatePicker; + var Cascader = antd.Cascader; + var Table = antd.Table; + var Modal = antd.Modal; + var message = antd.message; + + function filterOption(input, option) { + var label = (option && (option.label || option.children)) || ''; + return String(label).toLowerCase().indexOf(String(input || '').toLowerCase()) >= 0; + } + + function getInitialTransferDate() { + try { + if (window.dayjs) return window.dayjs('2026-02-20'); + } catch (e1) {} + try { + if (window.moment) return window.moment('2026-02-20', 'YYYY-MM-DD'); + } catch (e2) {} + return null; + } + + var layoutStyle = { padding: '16px 24px', background: '#f5f5f5', minHeight: '100vh' }; + var labelStyle = { marginBottom: 6, fontSize: 14, color: 'rgba(0,0,0,0.65)' }; + var formItemStyle = { marginBottom: 12 }; + var controlStyle = { width: '100%' }; + var reqStarStyle = { color: '#ff4d4f', marginRight: 4 }; + var reqStar = React.createElement('span', { style: reqStarStyle }, '*'); + + var regionOptions = useMemo(function () { + return [ + { value: 'zhejiang', label: '浙江省', children: [{ value: 'hangzhou', label: '杭州市' }, { value: 'ningbo', label: '宁波市' }, { value: 'jiaxing', label: '嘉兴市' }] }, + { value: 'shanghai', label: '上海市', children: [{ value: 'shanghai', label: '上海市' }] }, + { value: 'guangdong', label: '广东省', children: [{ value: 'guangzhou', label: '广州市' }, { value: 'shenzhen', label: '深圳市' }, { value: 'dongguan', label: '东莞市' }] } + ]; + }, []); + + var userOptions = useMemo(function () { + return [ + { value: '张明', label: '张明' }, + { value: '王芳', label: '王芳' }, + { value: '李华', label: '李华' }, + { value: '赵强', label: '赵强' }, + { value: '陈静', label: '陈静' } + ]; + }, []); + + var methodOptions = useMemo(function () { + return [ + { value: '第三方运输', label: '第三方运输' }, + { value: '司机驾驶', label: '司机驾驶' } + ]; + }, []); + + var vehicleDb = useMemo(function () { + return [ + { plateNo: '粤A12345', vehicleType: '厢式货车', brand: '东风', model: 'DFH1180', departParking: '天河智慧停车场', h2Unit: 'MPa' }, + { plateNo: '粤B11111', vehicleType: '轿车', brand: '比亚迪', model: '汉', departParking: '南山科技园停车场', h2Unit: '%' }, + { plateNo: '浙A11111', vehicleType: 'SUV', brand: '小鹏', model: 'P7', departParking: '西湖景区停车场', h2Unit: '%' }, + { plateNo: '浙B22222', vehicleType: '轿车', brand: '蔚来', model: 'ET5', departParking: '宁波江北停车场', h2Unit: 'MPa' }, + { plateNo: '沪A30003', vehicleType: '厢式货车', brand: '福田', model: 'BJ1180', departParking: '张江园区停车场', h2Unit: 'MPa' } + ]; + }, []); + + var plateOptions = useMemo(function () { + return vehicleDb.map(function (v) { return { value: v.plateNo, label: v.plateNo }; }); + }, [vehicleDb]); + + // 编辑页:从服务端拉取的已填写数据(原型用例) + var formState = useState({ + transferDate: getInitialTransferDate(), + departRegion: ['guangdong', 'guangzhou'], + receiveRegion: ['zhejiang', 'hangzhou'], + receivePerson: '王芳', + method: '第三方运输', + reason: '场站资源调整,车辆需从广州仓库调度至杭州项目点,保障项目运力。', + carrierName: '顺丰同城运输', + carrierPhone: '400-123-4567' + }); + var form = formState[0]; + var setForm = formState[1]; + + var errorsState = useState({}); + var errors = errorsState[0]; + var setErrors = errorsState[1]; + + var requirementModalState = useState(false); + var requirementModalOpen = requirementModalState[0]; + var setRequirementModalOpen = requirementModalState[1]; + + var requirementDocContent = [ + '一个「数字化资产ONEOS运管平台」中的「调拨管理」「编辑」模块', + '#面包屑:运维管理-车辆业务-调拨管理-编辑', + '页面布局、字段与「调拨管理-新增」一致;进入页面时从调拨单加载已保存数据,支持修改后提交审核或保存。', + '', + '1.调拨情况:同新增页(调拨日期、出发/接收区域、接收人、调拨方式、调拨原因、运输方名称、运输方联系方式)。', + '2.调拨车辆清单:同新增页;至少保留一辆有效车辆方可提交审核。' + ].join('\n'); + + var rowIdRef = React.useRef(3); + var vehiclesState = useState([ + { + id: 1, + plateNo: '粤A12345', + vehicleType: '厢式货车', + brand: '东风', + model: 'DFH1180', + departParking: '天河智慧停车场', + departMileageKm: '15230.12', + departHydrogen: '28.30', + h2Unit: 'MPa', + departElectricKwh: '68.40' + }, + { + id: 2, + plateNo: '浙A11111', + vehicleType: 'SUV', + brand: '小鹏', + model: 'P7', + departParking: '西湖景区停车场', + departMileageKm: '12010.00', + departHydrogen: '60.00', + h2Unit: '%', + departElectricKwh: '55.20' + } + ]); + var vehicles = vehiclesState[0]; + var setVehicles = vehiclesState[1]; + + function toFixed2Input(v) { + var s = String(v === null || v === undefined ? '' : v); + s = s.replace(/[^\d.]/g, ''); + var firstDot = s.indexOf('.'); + if (firstDot >= 0) { + s = s.slice(0, firstDot + 1) + s.slice(firstDot + 1).replace(/\./g, ''); + } + if (firstDot >= 0) { + var a = s.split('.'); + s = a[0] + '.' + (a[1] || '').slice(0, 2); + } + return s; + } + + var updateForm = useCallback(function (patch) { + setForm(function (p) { return Object.assign({}, p, patch); }); + }, []); + + var updateRow = useCallback(function (index, patch) { + setVehicles(function (prev) { + var list = prev.slice(); + var cur = list[index] || {}; + list[index] = Object.assign({}, cur, patch); + return list; + }); + }, []); + + var handlePlateChange = useCallback(function (index, plateNo) { + var v = vehicleDb.find(function (x) { return x.plateNo === plateNo; }); + updateRow(index, { + plateNo: plateNo, + vehicleType: v ? v.vehicleType : '', + brand: v ? v.brand : '', + model: v ? v.model : '', + departParking: v ? v.departParking : '', + h2Unit: v ? v.h2Unit : '' + }); + }, [vehicleDb, updateRow]); + + var addRow = useCallback(function () { + setVehicles(function (prev) { + return prev.concat([{ + id: rowIdRef.current++, + plateNo: undefined, + vehicleType: '', + brand: '', + model: '', + departParking: '', + departMileageKm: '', + departHydrogen: '', + h2Unit: '', + departElectricKwh: '' + }]); + }); + }, []); + + var removeRow = useCallback(function (index) { + setVehicles(function (prev) { + var list = prev.slice(); + list.splice(index, 1); + if (list.length === 0) { + return [{ + id: rowIdRef.current++, + plateNo: undefined, + vehicleType: '', + brand: '', + model: '', + departParking: '', + departMileageKm: '', + departHydrogen: '', + h2Unit: '', + departElectricKwh: '' + }]; + } + return list; + }); + }, []); + + function validate() { + var e = {}; + if (!form.transferDate) e.transferDate = '请选择调拨日期'; + if (!form.departRegion || form.departRegion.length < 2) e.departRegion = '请选择出发区域'; + if (!form.receiveRegion || form.receiveRegion.length < 2) e.receiveRegion = '请选择接收区域'; + if (!form.receivePerson) e.receivePerson = '请选择接收人'; + if (!form.method) e.method = '请选择调拨方式'; + if (!String(form.reason || '').trim()) e.reason = '请输入调拨原因'; + if (!String(form.carrierName || '').trim()) e.carrierName = '请输入运输方名称/司机姓名'; + if (!String(form.carrierPhone || '').trim()) e.carrierPhone = '请输入运输方/司机联系方式'; + + var effectiveRows = (vehicles || []).filter(function (r) { return r && String(r.plateNo || '').trim(); }); + if (effectiveRows.length === 0) e.vehicleList = '请选择调拨车辆'; + + for (var i = 0; i < (vehicles || []).length; i++) { + var r = vehicles[i] || {}; + if (!String(r.plateNo || '').trim()) continue; + if (!String(r.departMileageKm || '').trim()) e['row_' + i + '_departMileageKm'] = '请输入出发里程'; + if (!String(r.departHydrogen || '').trim()) e['row_' + i + '_departHydrogen'] = '请输入出发氢量'; + if (!String(r.departElectricKwh || '').trim()) e['row_' + i + '_departElectricKwh'] = '请输入出发电量'; + } + + setErrors(e); + return Object.keys(e).length === 0; + } + + var handleSubmitAudit = useCallback(function () { + if (!validate()) { + message.error('请完善必填项后再提交'); + return; + } + Modal.confirm({ + title: '确认提交审核?', + content: '提交后将进入审批流程(原型)。', + okText: '提交审核', + cancelText: '取消', + onOk: function () { + message.success('已提交审核(原型)'); + } + }); + }, [form, vehicles]); + + var handleSave = useCallback(function () { + message.info('已保存(原型,不做校验)'); + }, []); + + var handleCancel = useCallback(function () { + Modal.confirm({ + title: '是否确认取消', + content: '取消将返回列表,未保存的修改将丢失(原型)。是否确认?', + okText: '确认', + cancelText: '取消', + onOk: function () { + message.info('返回调拨管理页(原型)'); + } + }); + }, []); + + var vehicleColumns = useMemo(function () { + return [ + { + title: React.createElement('span', null, reqStar, '车牌号'), + key: 'plateNo', + width: 140, + render: function (_, r, index) { + return React.createElement(Select, { + placeholder: '请输入或选择车牌号', + style: { width: '100%' }, + value: r.plateNo, + onChange: function (v) { handlePlateChange(index, v); }, + allowClear: true, + showSearch: true, + options: plateOptions, + filterOption: filterOption, + status: errors.vehicleList ? 'error' : undefined + }); + } + }, + { + title: '车辆类型', + key: 'vehicleType', + width: 120, + render: function (_, r) { + return React.createElement(Input, { value: r.vehicleType ? r.vehicleType : '请先选择车辆', disabled: true }); + } + }, + { + title: '品牌', + key: 'brand', + width: 100, + render: function (_, r) { + return React.createElement(Input, { value: r.brand ? r.brand : '请先选择车辆', disabled: true }); + } + }, + { + title: '型号', + key: 'model', + width: 120, + render: function (_, r) { + return React.createElement(Input, { value: r.model ? r.model : '请先选择车辆', disabled: true }); + } + }, + { + title: '出发停车场', + key: 'departParking', + width: 160, + render: function (_, r) { + return React.createElement(Input, { value: r.departParking ? r.departParking : '请先选择车辆', disabled: true }); + } + }, + { + title: React.createElement('span', null, reqStar, '出发里程'), + key: 'departMileageKm', + width: 140, + render: function (_, r, index) { + var k = 'row_' + index + '_departMileageKm'; + return React.createElement(Input, { + value: r.departMileageKm, + onChange: function (e) { updateRow(index, { departMileageKm: toFixed2Input(e.target.value) }); }, + placeholder: '0.00', + addonAfter: 'km', + status: errors[k] ? 'error' : undefined + }); + } + }, + { + title: React.createElement('span', null, reqStar, '出发氢量'), + key: 'departHydrogen', + width: 140, + render: function (_, r, index) { + var k = 'row_' + index + '_departHydrogen'; + var unit = r.h2Unit || '%/MPa'; + return React.createElement(Input, { + value: r.departHydrogen, + onChange: function (e) { updateRow(index, { departHydrogen: toFixed2Input(e.target.value) }); }, + placeholder: '0.00', + addonAfter: unit, + status: errors[k] ? 'error' : undefined + }); + } + }, + { + title: React.createElement('span', null, reqStar, '出发电量'), + key: 'departElectricKwh', + width: 150, + render: function (_, r, index) { + var k = 'row_' + index + '_departElectricKwh'; + return React.createElement(Input, { + value: r.departElectricKwh, + onChange: function (e) { updateRow(index, { departElectricKwh: toFixed2Input(e.target.value) }); }, + placeholder: '0.00', + addonAfter: 'kWh', + status: errors[k] ? 'error' : undefined + }); + } + }, + { + title: '操作', + key: 'action', + width: 80, + fixed: 'right', + render: function (_, __, index) { + return React.createElement(Button, { type: 'link', danger: true, size: 'small', onClick: function () { removeRow(index); } }, '删除'); + } + } + ]; + }, [plateOptions, errors, handlePlateChange, updateRow, removeRow]); + + return React.createElement(App, null, + React.createElement('div', { style: layoutStyle }, + React.createElement('div', { style: { display: 'flex', alignItems: 'center', justifyContent: 'space-between', marginBottom: 16, flexWrap: 'wrap', gap: 8 } }, + React.createElement(Breadcrumb, { items: [{ title: '运维管理' }, { title: '车辆业务' }, { title: '调拨管理' }, { title: '编辑' }] }), + React.createElement(Button, { type: 'link', style: { padding: 0 }, onClick: function () { setRequirementModalOpen(true); } }, '查看需求说明') + ), + + React.createElement(Modal, { + title: '需求说明', + open: requirementModalOpen, + onCancel: function () { setRequirementModalOpen(false); }, + width: 720, + footer: React.createElement(Button, { onClick: function () { setRequirementModalOpen(false); } }, '关闭'), + bodyStyle: { maxHeight: '70vh', overflow: 'auto' } + }, React.createElement('div', { style: { whiteSpace: 'pre-wrap', fontSize: 13, lineHeight: 1.6, color: 'rgba(0,0,0,0.85)' } }, requirementDocContent)), + + React.createElement(Card, { title: '调拨情况', style: { marginBottom: 16 } }, + React.createElement('div', { style: { display: 'grid', gridTemplateColumns: '1fr 1fr 1fr', gap: '16px 24px', alignItems: 'start' } }, + React.createElement('div', { style: formItemStyle }, + React.createElement('div', { style: labelStyle }, reqStar, '调拨日期'), + React.createElement(DatePicker, { + style: controlStyle, + format: 'YYYY-MM-DD', + placeholder: '请选择调拨日期', + value: form.transferDate, + onChange: function (v) { updateForm({ transferDate: v }); }, + status: errors.transferDate ? 'error' : undefined + }), + errors.transferDate ? React.createElement('div', { style: { marginTop: 4, color: '#ff4d4f', fontSize: 12 } }, errors.transferDate) : null + ), + React.createElement('div', { style: formItemStyle }, + React.createElement('div', { style: labelStyle }, reqStar, '出发区域'), + React.createElement(Cascader, { + style: controlStyle, + placeholder: '请选择出发区域', + options: regionOptions, + value: form.departRegion, + onChange: function (v) { updateForm({ departRegion: v }); }, + allowClear: true, + status: errors.departRegion ? 'error' : undefined + }), + errors.departRegion ? React.createElement('div', { style: { marginTop: 4, color: '#ff4d4f', fontSize: 12 } }, errors.departRegion) : null + ), + React.createElement('div', { style: formItemStyle }, + React.createElement('div', { style: labelStyle }, reqStar, '接收区域'), + React.createElement(Cascader, { + style: controlStyle, + placeholder: '请选择接收区域', + options: regionOptions, + value: form.receiveRegion, + onChange: function (v) { updateForm({ receiveRegion: v }); }, + allowClear: true, + status: errors.receiveRegion ? 'error' : undefined + }), + errors.receiveRegion ? React.createElement('div', { style: { marginTop: 4, color: '#ff4d4f', fontSize: 12 } }, errors.receiveRegion) : null + ), + + React.createElement('div', { style: formItemStyle }, + React.createElement('div', { style: labelStyle }, reqStar, '接收人'), + React.createElement(Select, { + placeholder: '请输入或选择接收人', + style: controlStyle, + value: form.receivePerson, + onChange: function (v) { updateForm({ receivePerson: v }); }, + allowClear: true, + showSearch: true, + options: userOptions, + filterOption: filterOption, + status: errors.receivePerson ? 'error' : undefined + }), + errors.receivePerson ? React.createElement('div', { style: { marginTop: 4, color: '#ff4d4f', fontSize: 12 } }, errors.receivePerson) : null + ), + React.createElement('div', { style: formItemStyle }, + React.createElement('div', { style: labelStyle }, reqStar, '调拨方式'), + React.createElement(Select, { + placeholder: '请选择调拨方式', + style: controlStyle, + value: form.method, + onChange: function (v) { updateForm({ method: v }); }, + allowClear: true, + options: methodOptions, + status: errors.method ? 'error' : undefined + }), + errors.method ? React.createElement('div', { style: { marginTop: 4, color: '#ff4d4f', fontSize: 12 } }, errors.method) : null + ), + React.createElement('div', { style: formItemStyle }), + + React.createElement('div', { style: Object.assign({}, formItemStyle, { gridColumn: 'span 3' }) }, + React.createElement('div', { style: labelStyle }, reqStar, '调拨原因'), + React.createElement(Input.TextArea, { + placeholder: '请输入调拨原因', + value: form.reason, + onChange: function (e) { updateForm({ reason: e.target.value }); }, + autoSize: { minRows: 3, maxRows: 6 }, + status: errors.reason ? 'error' : undefined + }), + errors.reason ? React.createElement('div', { style: { marginTop: 4, color: '#ff4d4f', fontSize: 12 } }, errors.reason) : null + ), + + React.createElement('div', { style: formItemStyle }, + React.createElement('div', { style: labelStyle }, reqStar, '运输方名称'), + React.createElement(Input, { + placeholder: '请输入运输方名称/司机姓名', + value: form.carrierName, + onChange: function (e) { updateForm({ carrierName: e.target.value }); }, + status: errors.carrierName ? 'error' : undefined + }), + errors.carrierName ? React.createElement('div', { style: { marginTop: 4, color: '#ff4d4f', fontSize: 12 } }, errors.carrierName) : null + ), + React.createElement('div', { style: formItemStyle }, + React.createElement('div', { style: labelStyle }, reqStar, '运输方联系方式'), + React.createElement(Input, { + placeholder: '请输入运输方/司机联系方式', + value: form.carrierPhone, + onChange: function (e) { updateForm({ carrierPhone: e.target.value }); }, + status: errors.carrierPhone ? 'error' : undefined + }), + errors.carrierPhone ? React.createElement('div', { style: { marginTop: 4, color: '#ff4d4f', fontSize: 12 } }, errors.carrierPhone) : null + ), + React.createElement('div', { style: formItemStyle }) + ) + ), + + React.createElement(Card, { title: '调拨车辆清单', style: { marginBottom: 16 } }, + errors.vehicleList ? React.createElement('div', { style: { marginBottom: 12, color: '#ff4d4f', fontSize: 12 } }, errors.vehicleList) : null, + React.createElement(Table, { + rowKey: 'id', + columns: vehicleColumns, + dataSource: vehicles, + size: 'small', + pagination: false, + scroll: { x: 1100 } + }), + React.createElement(Button, { type: 'dashed', style: { marginTop: 12, width: '100%' }, onClick: addRow }, '新增一行') + ), + + React.createElement('div', { style: { height: 56 } }), + React.createElement('div', { + style: { + position: 'fixed', + left: 0, + right: 0, + bottom: 0, + padding: '12px 24px', + background: '#fff', + borderTop: '1px solid #f0f0f0', + display: 'flex', + gap: 8, + zIndex: 10 + } + }, + React.createElement(Button, { type: 'primary', onClick: handleSubmitAudit }, '提交审核'), + React.createElement(Button, { onClick: handleSave }, '保存'), + React.createElement(Button, { onClick: handleCancel }, '取消') + ) + ) + ); +}; diff --git a/web端/运维管理/车辆业务/调拨管理.jsx b/web端/运维管理/车辆业务/调拨管理.jsx index 2293371..55db836 100644 --- a/web端/运维管理/车辆业务/调拨管理.jsx +++ b/web端/运维管理/车辆业务/调拨管理.jsx @@ -1,2240 +1,1013 @@ -// 【重要】必须使用 const Component 作为组件变量名 -// 调拨管理 - 车辆资产管理后台模块 -// 设计变量参考 Arco Design Token: https://arco.design/react/docs/token -var ARCO_TOKEN = { - primary: '#165DFF', - primaryHover: '#4080FF', - primaryActive: '#0E42D2', - danger: '#F53F3F', - success: '#00B42A', - warning: '#FF7D00', - link: '#165DFF', - neutral1: '#FFFFFF', - neutral2: '#F7F8FA', - neutral3: '#F2F3F5', - neutral4: '#E5E6EB', - neutral5: '#C9CDD4', - neutral6: '#86909C', - neutral7: '#4E5969', - neutral8: '#1D2129', - border: '#E5E6EB', - borderSecondary: '#C9CDD4', - fill: '#F2F3F5', - fillSecondary: '#F7F8FA', - shadowLight: '0 1px 2px rgba(0,0,0,0.05)', - shadowMedium: '0 2px 8px rgba(0,0,0,0.08)', - radiusSmall: '2px', - radiusMedium: '4px', - radiusLarge: '8px', - spacing4: '4px', - spacing8: '8px', - spacing12: '12px', - spacing16: '16px', - spacing24: '24px', - fontSize14: '14px', - fontSize16: '16px', - fontFamily: '"PingFang SC", "苹方-简", -apple-system, BlinkMacSystemFont, "Helvetica Neue", Arial, sans-serif' -}; - -var APPROVAL_STATUS = [ - { value: 'pending_submit', label: '待提交' }, - { value: 'pending_approval', label: '待审批' }, - { value: 'approving', label: '审批中' }, - { value: 'completed', label: '审批完成' }, - { value: 'rejected', label: '审批驳回' }, - { value: 'withdrawn', label: '撤回' } -]; - -var TRANSFER_METHODS = [ - { value: 'third_party', label: '第三方运输' }, - { value: 'driver', label: '司机驾驶' } -]; - -var provinceList = [ - { code: 'gd', name: '广东省' }, - { code: 'zj', name: '浙江省' }, - { code: 'bj', name: '北京市' } -]; -var cityMap = { - gd: [{ code: 'gz', name: '广州市' }, { code: 'sz', name: '深圳市' }], - zj: [{ code: 'hz', name: '杭州市' }, { code: 'nb', name: '宁波市' }], - bj: [{ code: 'bj', name: '北京市' }] -}; - -// 运维部用户(操作人、创建人来源) -var mockOpsUsers = [ - { id: 'u1', name: '张明', dept: '运维部' }, - { id: 'u2', name: '王芳', dept: '运维部' }, - { id: 'u3', name: '李华', dept: '运维部' }, - { id: 'u4', name: '赵强', dept: '运维部' }, - { id: 'u5', name: '陈静', dept: '运维部' } -]; - -// 库存车辆(含车辆类型、品牌、型号、停车场、氢量单位等,用于反写) -var mockStockVehicles = [ - { id: 'v1', plateNo: '粤A12345', status: '库存', vehicleType: '轿车', brand: '比亚迪', model: '秦', departParking: '天河智慧停车场', h2Unit: '%' }, - { id: 'v2', plateNo: '粤A67890', status: '库存', vehicleType: '轿车', brand: '特斯拉', model: 'Model 3', departParking: '南山科技园停车场', h2Unit: 'MPa' }, - { id: 'v3', plateNo: '浙A11111', status: '库存', vehicleType: 'SUV', brand: '小鹏', model: 'P7', departParking: '西湖景区停车场', h2Unit: 'KG' }, - { id: 'v4', plateNo: '浙B22222', status: '库存', vehicleType: '轿车', brand: '蔚来', model: 'ET5', departParking: '宁波江北停车场', h2Unit: '%' }, - { id: 'v5', plateNo: '京A88888', status: '库存', vehicleType: 'MPV', brand: '理想', model: 'L9', departParking: '朝阳区停车场', h2Unit: 'MPa' }, - { id: 'v6', plateNo: '粤B11111', status: '库存', vehicleType: '轿车', brand: '比亚迪', model: '汉', departParking: '福田停车场', h2Unit: 'KG' } -]; - -// 审批节点(查看时步骤条) -var mockApprovalSteps = [ - { key: 'node1', name: '区域负责人审批' }, - { key: 'node2', name: '运营负责人审批' }, - { key: 'node3', name: '财务确认' } -]; - -const Component = function () { - // 视图:list | add | edit | view - var _sv = React.useState('list'); - var currentView = _sv[0]; - var setCurrentView = _sv[1]; - - // Tab:in_progress | history - var _tab = React.useState('in_progress'); - var listTab = _tab[0]; - var setListTab = _tab[1]; - - // 筛选 - var _fd = React.useState(''); - var filterDateStart = _fd[0]; - var setFilterDateStart = _fd[1]; - var _fe = React.useState(''); - var filterDateEnd = _fe[0]; - var setFilterDateEnd = _fe[1]; - var _fo = React.useState(''); - var filterOperator = _fo[0]; - var setFilterOperator = _fo[1]; - var _frdStart = React.useState(''); - var filterReceiveDateStart = _frdStart[0]; - var setFilterReceiveDateStart = _frdStart[1]; - var _frdEnd = React.useState(''); - var filterReceiveDateEnd = _frdEnd[0]; - var setFilterReceiveDateEnd = _frdEnd[1]; - var _frc = React.useState(''); - var filterReceiver = _frc[0]; - var setFilterReceiver = _frc[1]; - var _fpl = React.useState(''); - var filterPlateNo = _fpl[0]; - var setFilterPlateNo = _fpl[1]; - var _fdp = React.useState(''); - var filterDepartProvince = _fdp[0]; - var setFilterDepartProvince = _fdp[1]; - var _fdc = React.useState(''); - var filterDepartCity = _fdc[0]; - var setFilterDepartCity = _fdc[1]; - var _ftp = React.useState(''); - var filterTransferProvince = _ftp[0]; - var setFilterTransferProvince = _ftp[1]; - var _ftc = React.useState(''); - var filterTransferCity = _ftc[0]; - var setFilterTransferCity = _ftc[1]; - var _fm = React.useState(''); - var filterMethod = _fm[0]; - var setFilterMethod = _fm[1]; - var _fas = React.useState(''); - var filterApprovalStatus = _fas[0]; - var setFilterApprovalStatus = _fas[1]; - - // 已应用的筛选条件(仅点击查询后更新,列表按此筛选) - var _applied = React.useState({}); - var appliedFilters = _applied[0]; - var setAppliedFilters = _applied[1]; - - // 筛选下拉展开 - var _ao = React.useState(false); - var filterOperatorOpen = _ao[0]; - var setFilterOperatorOpen = _ao[1]; - var _arc = React.useState(false); - var filterReceiverOpen = _arc[0]; - var setFilterReceiverOpen = _arc[1]; - var _ap = React.useState(false); - var filterPlateOpen = _ap[0]; - var setFilterPlateOpen = _ap[1]; - var _cd = React.useState(false); - var filterCascaderDepartOpen = _cd[0]; - var setFilterCascaderDepartOpen = _cd[1]; - var _ct = React.useState(false); - var filterCascaderTransferOpen = _ct[0]; - var setFilterCascaderTransferOpen = _ct[1]; - var _drOpen = React.useState(false); - var filterDateRangeOpen = _drOpen[0]; - var setFilterDateRangeOpen = _drOpen[1]; - var _drRecOpen = React.useState(false); - var filterReceiveDateRangeOpen = _drRecOpen[0]; - var setFilterReceiveDateRangeOpen = _drRecOpen[1]; - function getInitialViewMonth(valueStr) { - if (valueStr && /^\d{4}-\d{2}-\d{2}$/.test(valueStr)) return valueStr.substring(0, 7); - var d = new Date(); - return d.getFullYear() + '-' + String(d.getMonth() + 1).padStart(2, '0'); - } - var _drViewL = React.useState(''); - var filterDateRangeViewLeft = _drViewL[0]; - var setFilterDateRangeViewLeft = _drViewL[1]; - var _drViewR = React.useState(''); - var filterDateRangeViewRight = _drViewR[0]; - var setFilterDateRangeViewRight = _drViewR[1]; - var _drRecViewL = React.useState(''); - var filterReceiveDateRangeViewLeft = _drRecViewL[0]; - var setFilterReceiveDateRangeViewLeft = _drRecViewL[1]; - var _drRecViewR = React.useState(''); - var filterReceiveDateRangeViewRight = _drRecViewR[0]; - var setFilterReceiveDateRangeViewRight = _drRecViewR[1]; - - // 分页 - var _cp = React.useState(1); - var currentPage = _cp[0]; - var setCurrentPage = _cp[1]; - var _ps = React.useState(20); - var pageSize = _ps[0]; - var setPageSize = _ps[1]; - - // 调拨记录列表:每条主记录含 lines(按车牌号展开,每车牌一行),hasReceiveRecord 表示是否已补充接收 - // 进行中 10 条(20 行),默认每页 20 条,第一页同时展示「接收记录」「编辑」「撤回」供开发参考 - var _mockList = React.useState((function () { - var regions = [ - { p: 'gd', c: 'gz', label: '广东省-广州市' }, - { p: 'gd', c: 'sz', label: '广东省-深圳市' }, - { p: 'zj', c: 'hz', label: '浙江省-杭州市' }, - { p: 'zj', c: 'nb', label: '浙江省-宁波市' }, - { p: 'bj', c: 'bj', label: '北京市-北京市' } - ]; - var users = [{ id: 'u1', name: '张明' }, { id: 'u2', name: '王芳' }, { id: 'u3', name: '李华' }, { id: 'u4', name: '赵强' }, { id: 'u5', name: '陈静' }]; - var vehicles = [ - { plateNo: '粤A12345', vehicleType: '轿车', brand: '比亚迪', model: '秦', departParking: '天河智慧停车场', h2Unit: '%' }, - { plateNo: '粤A67890', vehicleType: '轿车', brand: '特斯拉', model: 'Model 3', departParking: '南山科技园停车场', h2Unit: 'MPa' }, - { plateNo: '浙A11111', vehicleType: 'SUV', brand: '小鹏', model: 'P7', departParking: '西湖景区停车场', h2Unit: 'KG' }, - { plateNo: '浙B22222', vehicleType: '轿车', brand: '蔚来', model: 'ET5', departParking: '宁波江北停车场', h2Unit: '%' }, - { plateNo: '京A88888', vehicleType: 'MPV', brand: '理想', model: 'L9', departParking: '朝阳区停车场', h2Unit: 'MPa' }, - { plateNo: '粤B11111', vehicleType: '轿车', brand: '比亚迪', model: '汉', departParking: '福田停车场', h2Unit: 'KG' } - ]; - var reasons = ['区域调配需求', '司机驾驶调拨', '维修后回调', '新车投放', '租赁到期回调']; - var carriers = [{ name: '顺丰物流', contact: '400-111-2222' }, { name: '德邦物流', contact: '95353' }]; - var list = []; - var tid = 1; - function makeTransfer(inProgress, hasReceive, count) { - for (var c = 0; c < count; c++) { - var status = inProgress ? ['pending_submit', 'pending_approval', 'approving', 'rejected', 'withdrawn'][tid % 5] : 'completed'; - var hasRec = inProgress ? false : hasReceive; - var dep = regions[tid % regions.length]; - var trans = regions[(tid + 1) % regions.length]; - var u = users[tid % users.length]; - var d = '2025-' + String((tid % 12) + 1).padStart(2, '0') + '-' + String((tid % 20) + 1).padStart(2, '0'); - var createTime = d + ' ' + String(9 + (tid % 8)).padStart(2, '0') + ':' + (tid % 2 ? '15' : '30'); - var lineCount = 2; - var lines = []; - for (var L = 0; L < lineCount; L++) { - var v = vehicles[(tid + L) % vehicles.length]; - lines.push({ - plateNo: v.plateNo, - vehicleType: v.vehicleType, - brand: v.brand, - model: v.model, - departParking: v.departParking, - departMileage: 1000 + tid * 100 + L * 50, - departH2: (60 + tid + L) + (v.h2Unit === 'KG' ? '' : v.h2Unit), - departH2Unit: v.h2Unit, - departElec: 80 + tid + L, - receiveMileage: hasRec ? 1100 + tid * 100 + L * 50 : null, - receiveH2: hasRec ? (65 + tid + L) + v.h2Unit : null, - receiveElec: hasRec ? 85 + tid + L : null, - receiveParking: hasRec ? '抵达停车场' + tid : null, - receiverName: hasRec ? users[(tid + 1) % users.length].name : null - }); - } - list.push({ - id: 't' + tid, - transferDate: d, - departProvince: dep.p, - departCity: dep.c, - departLabel: dep.label, - operatorId: u.id, - operatorName: u.name, - transferProvince: trans.p, - transferCity: trans.c, - transferLabel: trans.label, - transferMethod: tid % 2 ? 'third_party' : 'driver', - transferReason: reasons[tid % reasons.length], - carrierName: carriers[tid % 2].name, - carrierContact: carriers[tid % 2].contact, - approvalStatus: status, - hasReceiveRecord: hasRec, - receiveDate: hasRec ? '2025-' + String((tid % 12) + 1).padStart(2, '0') + '-' + String((tid % 15) + 10).padStart(2, '0') : '', - receiverId: hasRec ? users[(tid + 1) % users.length].id : '', - receiverName: hasRec ? users[(tid + 1) % users.length].name : '', - createTime: createTime, - lines: lines - }); - tid++; - } - } - makeTransfer(false, false, 2); // 进行中:审批完成但未补充接收(2 条,排在最前) - makeTransfer(true, false, 18); // 进行中:待提交/待审批/审批中/驳回/撤回(共 20 条进行中) - makeTransfer(false, true, 20); // 历史记录:审批完成且已补充接收(20 条) - return list; - }())); - var mockTransferList = _mockList[0]; - var setMockTransferList = _mockList[1]; - - // 新增/编辑表单(编辑、查看、接收仍用 formData) - var defaultForm = { - transferDate: '', - receiveDate: '', - operatorId: '', - operatorName: '', - selectedVehicleIds: [], - transferMethod: '', - transferReason: '', - departProvince: '', - departCity: '', - transferProvince: '', - transferCity: '', - carrierName: '', - carrierContact: '' - }; - var _form = React.useState(defaultForm); - var formData = _form[0]; - var setFormData = _form[1]; - - // 新增页专用:上方 7 项 + 下方可编辑行表 - var defaultAddForm = { - transferDate: '', - departProvince: '', - departCity: '', - transferProvince: '', - transferCity: '', - transferMethod: '', - transferReason: '', - carrierName: '', - carrierContact: '' - }; - var _addForm = React.useState(defaultAddForm); - var addFormData = _addForm[0]; - var setAddFormData = _addForm[1]; - var addFormLineIdRef = React.useRef(0); - function createEmptyAddLine() { - addFormLineIdRef.current = (addFormLineIdRef.current || 0) + 1; - return { - rowId: 'addRow-' + addFormLineIdRef.current, - vehicleId: '', - plateNo: '', - vehicleType: '', - brand: '', - model: '', - departParking: '', - departMileage: '', - departH2: '', - departH2Unit: '', - departElec: '' - }; - } - var _addLines = React.useState(function () { return [{ rowId: 'addRow-1', vehicleId: '', plateNo: '', vehicleType: '', brand: '', model: '', departParking: '', departMileage: '', departH2: '', departH2Unit: '', departElec: '' }]; }); - var addFormLines = _addLines[0]; - var setAddFormLines = _addLines[1]; - var _plateOpen = React.useState(null); - var plateSelectOpenRowId = _plateOpen[0]; - var setPlateSelectOpenRowId = _plateOpen[1]; - var _plateKw = React.useState(''); - var plateSearchKeyword = _plateKw[0]; - var setPlateSearchKeyword = _plateKw[1]; - var _addDepartCascader = React.useState(false); - var addDepartCascaderOpen = _addDepartCascader[0]; - var setAddDepartCascaderOpen = _addDepartCascader[1]; - var _addAcceptCascader = React.useState(false); - var addAcceptCascaderOpen = _addAcceptCascader[0]; - var setAddAcceptCascaderOpen = _addAcceptCascader[1]; - - // 编辑页专用:行表 + 车牌选择展开态(与新增页结构一致) - var editFormLineIdRef = React.useRef(0); - function createEmptyEditLine() { - editFormLineIdRef.current = editFormLineIdRef.current + 1; - return { - rowId: 'editRow-' + editFormLineIdRef.current, - vehicleId: '', - plateNo: '', - vehicleType: '', - brand: '', - model: '', - departParking: '', - departMileage: '', - departH2: '', - departH2Unit: '', - departElec: '', - receiveMileage: '', - receiveH2: '', - receiveElec: '' - }; - } - function buildEditFormLinesFromRecord(transfer) { - if (!transfer || !transfer.lines || !transfer.lines.length) return [createEmptyEditLine()]; - editFormLineIdRef.current = Math.max(editFormLineIdRef.current || 0, transfer.lines.length); - return transfer.lines.map(function (line, idx) { - var v = mockStockVehicles.find(function (x) { return x.plateNo === line.plateNo; }); - return { - rowId: 'editRow-' + (idx + 1), - vehicleId: v ? v.id : (line.vehicleId || ''), - plateNo: line.plateNo || '', - vehicleType: line.vehicleType || (v && v.vehicleType) || '', - brand: line.brand || (v && v.brand) || '', - model: line.model || (v && v.model) || '', - departParking: line.departParking || (v && v.departParking) || '', - departMileage: line.departMileage != null && line.departMileage !== '' ? line.departMileage : '', - departH2: line.departH2 != null && line.departH2 !== '' ? line.departH2 : '', - departH2Unit: (line.departH2Unit || (v && v.h2Unit) || ''), - departElec: line.departElec != null && line.departElec !== '' ? line.departElec : '', - receiveMileage: line.receiveMileage != null && line.receiveMileage !== '' ? line.receiveMileage : '', - receiveH2: line.receiveH2 != null && line.receiveH2 !== '' ? line.receiveH2 : '', - receiveElec: line.receiveElec != null && line.receiveElec !== '' ? line.receiveElec : '' - }; - }); - } - var _editFormLines = React.useState([]); - var editFormLines = _editFormLines[0]; - var setEditFormLines = _editFormLines[1]; - var _editPlateOpen = React.useState(null); - var editPlateSelectOpenRowId = _editPlateOpen[0]; - var setEditPlateSelectOpenRowId = _editPlateOpen[1]; - var _editPlateKw = React.useState(''); - var editPlateSearchKeyword = _editPlateKw[0]; - var setEditPlateSearchKeyword = _editPlateKw[1]; - - function updateEditLine(rowId, updates) { - setEditFormLines(function (prev) { - return prev.map(function (l) { - if (l.rowId !== rowId) return l; - var next = {}; - for (var k in l) next[k] = l[k]; - for (var k in updates) next[k] = updates[k]; - return next; - }); - }); - } - function getEditPagePlateOptions(rowId) { - var usedElsewhere = function (v) { - return editFormLines.some(function (l) { return l.rowId !== rowId && l.vehicleId === v.id; }); - }; - var list = mockStockVehicles.filter(function (v) { return !usedElsewhere(v); }); - var kw = (editPlateSearchKeyword || '').trim(); - if (kw) list = list.filter(function (v) { return (v.plateNo || '').indexOf(kw) >= 0; }); - return list; - } - - // 编辑/查看 当前记录 - var _edit = React.useState(null); - var editRecord = _edit[0]; - var setEditRecord = _edit[1]; - var _view = React.useState(null); - var viewRecord = _view[0]; - var setViewRecord = _view[1]; - - // 新增页级联/穿梭框等 UI 状态 - var _formDp = React.useState(false); - var formDepartCascaderOpen = _formDp[0]; - var setFormDepartCascaderOpen = _formDp[1]; - var _formTp = React.useState(false); - var formTransferCascaderOpen = _formTp[0]; - var setFormTransferCascaderOpen = _formTp[1]; - var _formOp = React.useState(false); - var formOperatorOpen = _formOp[0]; - var setFormOperatorOpen = _formOp[1]; - // 穿梭框:左侧/右侧选中的 id 列表(用于多选后点击添加/移除) - var _leftSel = React.useState([]); - var leftSelectedIds = _leftSel[0]; - var setLeftSelectedIds = _leftSel[1]; - var _rightSel = React.useState([]); - var rightSelectedIds = _rightSel[0]; - var setRightSelectedIds = _rightSel[1]; - - var _toast = React.useState(''); - var toastMessage = _toast[0]; - var setToastMessage = _toast[1]; - var _reqModal = React.useState(false); - var showRequirementModal = _reqModal[0]; - var setShowRequirementModal = _reqModal[1]; - var _withdrawConfirm = React.useState(null); - var withdrawConfirmRecord = _withdrawConfirm[0]; - var setWithdrawConfirmRecord = _withdrawConfirm[1]; - var _selectedRows = React.useState([]); - var selectedRowIds = _selectedRows[0]; - var setSelectedRowIds = _selectedRows[1]; - var _receiveForm = React.useState({ receiveDate: '', receiverName: '张明', lines: [] }); - var receiveFormData = _receiveForm[0]; - var setReceiveFormData = _receiveForm[1]; - - function getStatusLabel(value) { - var s = APPROVAL_STATUS.find(function (x) { return x.value === value; }); - return s ? s.label : value; - } - function getMethodLabel(value) { - var m = TRANSFER_METHODS.find(function (x) { return x.value === value; }); - return m ? m.label : value; - } - // 氢量只显示一次单位:若值已带 %/MPa/KG 则不追加单位 - function formatH2(val, unit) { - if (val == null || val === '') return '-'; - var s = String(val); - if (s.match(/%|MPa|KG$/)) return s; - return s + (unit || ''); - } - - // 将主记录按 lines 展开为行(每车牌一行),并进行中/历史记录 tab 筛选 - function getFlattenedRows() { - var rows = []; - mockTransferList.forEach(function (t) { - var inProgress = ['pending_submit', 'pending_approval', 'approving', 'rejected', 'withdrawn'].indexOf(t.approvalStatus) >= 0 || (t.approvalStatus === 'completed' && !t.hasReceiveRecord); - var inHistory = t.approvalStatus === 'completed' && t.hasReceiveRecord; - if (listTab === 'in_progress' && !inProgress) return; - if (listTab === 'history' && !inHistory) return; - (t.lines || []).forEach(function (line) { - rows.push({ transfer: t, line: line, rowId: t.id + '-' + (line.plateNo || '') }); - }); - }); - return rows; - } - - function getFilteredList() { - var list = getFlattenedRows(); - var a = appliedFilters; - list = list.filter(function (row) { - var t = row.transfer; - var line = row.line; - if (a.filterDateStart && t.transferDate < a.filterDateStart) return false; - if (a.filterDateEnd && t.transferDate > a.filterDateEnd) return false; - if (a.filterOperator && (!t.operatorName || t.operatorName.indexOf(a.filterOperator) < 0)) return false; - if (a.filterReceiveDateStart && t.receiveDate && t.receiveDate < a.filterReceiveDateStart) return false; - if (a.filterReceiveDateEnd && t.receiveDate && t.receiveDate > a.filterReceiveDateEnd) return false; - if (a.filterReceiver && (!t.receiverName || t.receiverName.indexOf(a.filterReceiver) < 0)) return false; - if (a.filterPlateNo && (!line.plateNo || line.plateNo.indexOf(a.filterPlateNo) < 0)) return false; - if (a.filterDepartProvince && t.departProvince !== a.filterDepartProvince) return false; - if (a.filterDepartCity && t.departCity !== a.filterDepartCity) return false; - if (a.filterTransferProvince && t.transferProvince !== a.filterTransferProvince) return false; - if (a.filterTransferCity && t.transferCity !== a.filterTransferCity) return false; - if (a.filterMethod && t.transferMethod !== a.filterMethod) return false; - if (a.filterApprovalStatus && t.approvalStatus !== a.filterApprovalStatus) return false; - return true; - }); - return list; - } - - var filteredList = getFilteredList(); - var totalItems = filteredList.length; - var totalPages = Math.ceil(totalItems / pageSize) || 1; - var validPage = currentPage > totalPages && totalPages > 0 ? 1 : (currentPage < 1 ? 1 : currentPage); - if (validPage !== currentPage && totalPages > 0) { - setCurrentPage(1); - validPage = 1; - } - var startIndex = (validPage - 1) * pageSize; - var endIndex = startIndex + pageSize; - var paginatedList = filteredList.slice(startIndex, endIndex); - - function handleFormChange(field, value) { - var next = {}; - for (var k in formData) { next[k] = formData[k]; } - next[field] = value; - setFormData(next); - } - - function handleAddFormChange(field, value) { - var next = {}; - for (var k in addFormData) { next[k] = addFormData[k]; } - next[field] = value; - setAddFormData(next); - } - - function validateAddForm(submitForApproval) { - if (!addFormData.transferDate) { - setToastMessage('请选择调拨日期'); - setTimeout(function () { setToastMessage(''); }, 2000); - return false; - } - if (!addFormData.departProvince || !addFormData.departCity) { - setToastMessage('请选择出发区域'); - setTimeout(function () { setToastMessage(''); }, 2000); - return false; - } - if (!addFormData.transferProvince || !addFormData.transferCity) { - setToastMessage('请选择接收区域'); - setTimeout(function () { setToastMessage(''); }, 2000); - return false; - } - if (!addFormData.transferMethod) { - setToastMessage('请选择调拨方式'); - setTimeout(function () { setToastMessage(''); }, 2000); - return false; - } - if (!addFormData.transferReason || !addFormData.transferReason.trim()) { - setToastMessage('请填写调拨原因'); - setTimeout(function () { setToastMessage(''); }, 2000); - return false; - } - if (!addFormData.carrierName || !addFormData.carrierName.trim()) { - setToastMessage('请填写运输方名称'); - setTimeout(function () { setToastMessage(''); }, 2000); - return false; - } - if (!addFormData.carrierContact || !addFormData.carrierContact.trim()) { - setToastMessage('请填写运输方联系方式'); - setTimeout(function () { setToastMessage(''); }, 2000); - return false; - } - var validLines = addFormLines.filter(function (row) { return row.vehicleId && row.plateNo; }); - if (validLines.length === 0) { - setToastMessage('请至少添加一行并选择车牌号'); - setTimeout(function () { setToastMessage(''); }, 2000); - return false; - } - for (var i = 0; i < addFormLines.length; i++) { - var row = addFormLines[i]; - if (!row.plateNo) continue; - var rowNum = i + 1; - if (row.departMileage === '' || row.departMileage === undefined || row.departMileage === null) { - setToastMessage('请填写第' + rowNum + '行出发里程(KM)'); - setTimeout(function () { setToastMessage(''); }, 2000); - return false; - } - if (row.departH2 === '' || row.departH2 === undefined || row.departH2 === null) { - setToastMessage('请填写第' + rowNum + '行出发氢量'); - setTimeout(function () { setToastMessage(''); }, 2000); - return false; - } - if (row.departElec === '' || row.departElec === undefined || row.departElec === null) { - setToastMessage('请填写第' + rowNum + '行出发电量'); - setTimeout(function () { setToastMessage(''); }, 2000); - return false; - } - } - return true; - } - - function buildAddRecord(approvalStatus) { - var dp = provinceList.find(function (x) { return x.code === addFormData.departProvince; }); - var dc = (cityMap[addFormData.departProvince] || []).find(function (x) { return x.code === addFormData.departCity; }); - var tp = provinceList.find(function (x) { return x.code === addFormData.transferProvince; }); - var tc = (cityMap[addFormData.transferProvince] || []).find(function (x) { return x.code === addFormData.transferCity; }); - var newId = 't' + (mockTransferList.length + 1); - var now = new Date(); - var createTimeStr = now.getFullYear() + '-' + String(now.getMonth() + 1).padStart(2, '0') + '-' + String(now.getDate()).padStart(2, '0') + ' ' + String(now.getHours()).padStart(2, '0') + ':' + String(now.getMinutes()).padStart(2, '0'); - var validLines = addFormLines.filter(function (row) { return row.vehicleId && row.plateNo; }); - var lines = validLines.map(function (row) { - return { - plateNo: row.plateNo, - vehicleType: row.vehicleType || '-', - brand: row.brand || '-', - model: row.model || '-', - departParking: row.departParking || '-', - departMileage: row.departMileage != null && row.departMileage !== '' ? Number(row.departMileage) : null, - departH2: row.departH2 != null && row.departH2 !== '' ? row.departH2 : '', - departH2Unit: row.departH2Unit || '', - departElec: row.departElec != null && row.departElec !== '' ? Number(row.departElec) : null, - receiveMileage: null, - receiveH2: null, - receiveElec: null, - receiveParking: null, - receiverName: null - }; - }); - return { - id: newId, - transferDate: addFormData.transferDate, - operatorId: 'u1', - operatorName: '张明', - departProvince: addFormData.departProvince, - departCity: addFormData.departCity, - departLabel: (dp ? dp.name : '') + '-' + (dc ? dc.name : ''), - transferProvince: addFormData.transferProvince, - transferCity: addFormData.transferCity, - transferLabel: (tp ? tp.name : '') + '-' + (tc ? tc.name : ''), - transferMethod: addFormData.transferMethod, - transferReason: addFormData.transferReason || '', - carrierName: addFormData.carrierName || '', - carrierContact: addFormData.carrierContact || '', - approvalStatus: approvalStatus, - hasReceiveRecord: false, - receiveDate: '', - receiverId: '', - receiverName: '', - createTime: createTimeStr, - lines: lines - }; - } - - function handleAddSave() { - if (!validateAddForm(false)) return; - var newRecord = buildAddRecord('pending_submit'); - setMockTransferList(mockTransferList.concat([newRecord])); - setToastMessage('保存成功'); - setTimeout(function () { setToastMessage(''); }, 2000); - setCurrentView('list'); - setAddFormData(defaultAddForm); - setAddFormLines([createEmptyAddLine()]); - setPlateSelectOpenRowId(null); - } - - function handleAddSubmit() { - if (!validateAddForm(true)) return; - var newRecord = buildAddRecord('pending_approval'); - setMockTransferList(mockTransferList.concat([newRecord])); - setToastMessage('已提交审核'); - setTimeout(function () { setToastMessage(''); }, 2000); - setCurrentView('list'); - setAddFormData(defaultAddForm); - setAddFormLines([createEmptyAddLine()]); - setPlateSelectOpenRowId(null); - } - - function handleAddCancel() { - setCurrentView('list'); - setAddFormData(defaultAddForm); - setAddFormLines([createEmptyAddLine()]); - setPlateSelectOpenRowId(null); - } - - function updateAddLine(rowId, updates) { - setAddFormLines(function (prev) { - return prev.map(function (l) { - if (l.rowId !== rowId) return l; - var next = {}; - for (var k in l) next[k] = l[k]; - for (var k in updates) next[k] = updates[k]; - return next; - }); - }); - } - - function getAddPagePlateOptions(rowId) { - var usedElsewhere = function (v) { - return addFormLines.some(function (l) { return l.rowId !== rowId && l.vehicleId === v.id; }); - }; - var list = mockStockVehicles.filter(function (v) { return !usedElsewhere(v); }); - var kw = (plateSearchKeyword || '').trim(); - if (kw) list = list.filter(function (v) { return (v.plateNo || '').indexOf(kw) >= 0; }); - return list; - } - - function renderAddPage() { - var grid = styles.formGrid; - return React.createElement('div', {}, - React.createElement('div', { style: Object.assign({}, styles.card, { marginBottom: t.spacing16 }) }, - React.createElement('div', { style: grid }, - React.createElement('div', { style: styles.formRow }, - React.createElement('label', { style: styles.formLabel }, '调拨日期', React.createElement('span', { style: styles.formLabelReq }, '*')), - React.createElement('input', { style: styles.input, type: 'date', value: addFormData.transferDate, onChange: function (e) { handleAddFormChange('transferDate', e.target.value); } }) - ), - React.createElement('div', { style: styles.formRow }, - React.createElement('label', { style: styles.formLabel }, '出发区域', React.createElement('span', { style: styles.formLabelReq }, '*')), - renderCascader(addFormData.departProvince, addFormData.departCity, function (v) { setAddFormData(function (prev) { var n = {}; for (var k in prev) n[k] = prev[k]; n.departProvince = v; n.departCity = ''; return n; }); }, function (v) { setAddFormData(function (prev) { var n = {}; for (var k in prev) n[k] = prev[k]; n.departCity = v; return n; }); }, addDepartCascaderOpen, setAddDepartCascaderOpen) - ), - React.createElement('div', { style: styles.formRow }, - React.createElement('label', { style: styles.formLabel }, '接收区域', React.createElement('span', { style: styles.formLabelReq }, '*')), - renderCascader(addFormData.transferProvince, addFormData.transferCity, function (v) { setAddFormData(function (prev) { var n = {}; for (var k in prev) n[k] = prev[k]; n.transferProvince = v; n.transferCity = ''; return n; }); }, function (v) { setAddFormData(function (prev) { var n = {}; for (var k in prev) n[k] = prev[k]; n.transferCity = v; return n; }); }, addAcceptCascaderOpen, setAddAcceptCascaderOpen) - ), - React.createElement('div', { style: styles.formRow }, - React.createElement('label', { style: styles.formLabel }, '调拨方式', React.createElement('span', { style: styles.formLabelReq }, '*')), - React.createElement('div', { style: styles.btnGroup }, - React.createElement('button', { type: 'button', style: Object.assign({}, styles.btnGroupItem, addFormData.transferMethod === 'third_party' ? styles.btnGroupItemActive : {}), onClick: function () { handleAddFormChange('transferMethod', 'third_party'); } }, '第三方运输'), - React.createElement('button', { type: 'button', style: Object.assign({}, styles.btnGroupItem, styles.btnGroupItemLast, addFormData.transferMethod === 'driver' ? styles.btnGroupItemActive : {}), onClick: function () { handleAddFormChange('transferMethod', 'driver'); } }, '司机驾驶') - ) - ), - React.createElement('div', { style: Object.assign({}, styles.formRow, styles.formGridFull) }, - React.createElement('label', { style: styles.formLabel }, '调拨原因', React.createElement('span', { style: styles.formLabelReq }, '*')), - React.createElement('textarea', { style: styles.textarea, value: addFormData.transferReason, onChange: function (e) { handleAddFormChange('transferReason', e.target.value); }, placeholder: '请输入调拨原因' }) - ), - React.createElement('div', { style: styles.formRow }, - React.createElement('label', { style: styles.formLabel }, '运输方名称', React.createElement('span', { style: styles.formLabelReq }, '*')), - React.createElement('input', { style: styles.input, value: addFormData.carrierName, onChange: function (e) { handleAddFormChange('carrierName', e.target.value); }, placeholder: '请输入运输方名称或司机姓名' }) - ), - React.createElement('div', { style: styles.formRow }, - React.createElement('label', { style: styles.formLabel }, '运输方联系方式', React.createElement('span', { style: styles.formLabelReq }, '*')), - React.createElement('input', { style: styles.input, value: addFormData.carrierContact, onChange: function (e) { handleAddFormChange('carrierContact', e.target.value); }, placeholder: '请输入运输方联系方式' }) - ) - ) - ), - React.createElement('div', { style: styles.card }, - React.createElement('div', { style: styles.tableWrapAddPage }, - React.createElement('table', { style: styles.table }, - React.createElement('thead', {}, - React.createElement('tr', {}, - React.createElement('th', { style: Object.assign({}, styles.th, styles.thNowrap) }, '车牌号', React.createElement('span', { style: styles.formLabelReq }, '*')), - React.createElement('th', { style: Object.assign({}, styles.th, styles.thNowrap) }, '车辆类型'), - React.createElement('th', { style: Object.assign({}, styles.th, styles.thNowrap) }, '品牌'), - React.createElement('th', { style: Object.assign({}, styles.th, styles.thNowrap) }, '型号'), - React.createElement('th', { style: Object.assign({}, styles.th, styles.thNowrap) }, '出发停车场'), - React.createElement('th', { style: Object.assign({}, styles.th, styles.thNowrap) }, '出发里程(KM)', React.createElement('span', { style: styles.formLabelReq }, '*')), - React.createElement('th', { style: Object.assign({}, styles.th, styles.thNowrap) }, '出发氢量', React.createElement('span', { style: styles.formLabelReq }, '*')), - React.createElement('th', { style: Object.assign({}, styles.th, styles.thNowrap) }, '出发电量', React.createElement('span', { style: styles.formLabelReq }, '*')), - React.createElement('th', { style: Object.assign({}, styles.th, styles.thNowrap) }, '操作') - ) - ), - React.createElement('tbody', {}, - addFormLines.map(function (row, rowIndex) { - var isPlateOpen = plateSelectOpenRowId === row.rowId; - var plateOptions = getAddPagePlateOptions(row.rowId); - var isEvenRow = rowIndex % 2 === 1; - return React.createElement('tr', { key: row.rowId, style: isEvenRow ? styles.trStripe : styles.trOdd }, - React.createElement('td', { style: Object.assign({}, styles.td, styles.tdNowrap) }, - React.createElement('div', { style: styles.autocompleteWrap }, - React.createElement('input', { - style: Object.assign({}, styles.input, { minWidth: '120px' }), - placeholder: '请选择', - value: isPlateOpen ? plateSearchKeyword : (row.plateNo || ''), - onChange: function (e) { setPlateSearchKeyword(e.target.value); setPlateSelectOpenRowId(row.rowId); }, - onFocus: function () { setPlateSelectOpenRowId(row.rowId); setPlateSearchKeyword(row.plateNo || ''); }, - onBlur: function () { setTimeout(function () { setPlateSelectOpenRowId(null); }, 200); } - }), - isPlateOpen && React.createElement(React.Fragment, {}, - React.createElement('div', { style: { position: 'fixed', left: 0, top: 0, right: 0, bottom: 0, zIndex: 1049 }, onClick: function () { setPlateSelectOpenRowId(null); } }), - React.createElement('div', { style: Object.assign({}, styles.autocompletePanel, styles.autocompletePanelOverflow), onClick: function (e) { e.stopPropagation(); } }, - plateOptions.length === 0 - ? React.createElement('div', { style: { padding: '8px 12px', fontSize: t.fontSize14, color: t.neutral6 } }, '无匹配的库存车辆') - : plateOptions.map(function (v) { - return React.createElement('div', { - key: v.id, - style: styles.autocompleteOption, - onMouseDown: function (e) { e.preventDefault(); }, - onClick: function () { - updateAddLine(row.rowId, { vehicleId: v.id, plateNo: v.plateNo, vehicleType: v.vehicleType || '', brand: v.brand || '', model: v.model || '', departParking: v.departParking || '', departH2Unit: v.h2Unit || '' }); - setPlateSelectOpenRowId(null); - setPlateSearchKeyword(''); - } - }, v.plateNo); - }) - ) - ) - ) - ), - React.createElement('td', { style: Object.assign({}, styles.td, styles.tdNowrap) }, row.vehicleType || '-'), - React.createElement('td', { style: Object.assign({}, styles.td, styles.tdNowrap) }, row.brand || '-'), - React.createElement('td', { style: Object.assign({}, styles.td, styles.tdNowrap) }, row.model || '-'), - React.createElement('td', { style: Object.assign({}, styles.td, styles.tdNowrap) }, row.departParking || '-'), - React.createElement('td', { style: Object.assign({}, styles.td, styles.tdNowrap) }, - React.createElement('input', { style: Object.assign({}, styles.input, { width: '80px' }), type: 'number', value: row.departMileage, onChange: function (e) { updateAddLine(row.rowId, { departMileage: e.target.value }); }, placeholder: '' }) - ), - React.createElement('td', { style: Object.assign({}, styles.td, styles.tdNowrap) }, - React.createElement('span', { style: { display: 'inline-flex', alignItems: 'center' } }, - React.createElement('input', { style: Object.assign({}, styles.input, { width: '80px' }), value: row.departH2, onChange: function (e) { updateAddLine(row.rowId, { departH2: e.target.value }); }, placeholder: '' }), - row.departH2Unit ? React.createElement('span', { style: { marginLeft: '4px', color: t.neutral6, fontSize: t.fontSize14 } }, row.departH2Unit) : null - ) - ), - React.createElement('td', { style: Object.assign({}, styles.td, styles.tdNowrap) }, - React.createElement('span', { style: { display: 'inline-flex', alignItems: 'center' } }, - React.createElement('input', { style: Object.assign({}, styles.input, { width: '80px' }), value: row.departElec, onChange: function (e) { updateAddLine(row.rowId, { departElec: e.target.value }); }, placeholder: '' }), - React.createElement('span', { style: { marginLeft: '4px', color: t.neutral6, fontSize: t.fontSize14 } }, 'kWh') - ) - ), - React.createElement('td', { style: Object.assign({}, styles.td, styles.tdNowrap) }, - React.createElement('a', { href: '#', style: styles.actionLink, onClick: function (e) { - e.preventDefault(); - if (addFormLines.length <= 1) { setToastMessage('至少保留一行'); setTimeout(function () { setToastMessage(''); }, 2000); return; } - setAddFormLines(addFormLines.filter(function (l) { return l.rowId !== row.rowId; })); - } }, '删除') - ) - ); - }) - ) - ) - ), - React.createElement('div', { style: { marginTop: t.spacing12 } }, - React.createElement('button', { type: 'button', style: Object.assign({}, styles.btn, styles.btnDefault), onClick: function () { setAddFormLines(addFormLines.concat([createEmptyAddLine()])); } }, '新增一行') - ), - React.createElement('div', { style: styles.modalFooter }, - React.createElement('button', { style: Object.assign({}, styles.btn, styles.btnDefault), onClick: handleAddCancel }, '取消'), - React.createElement('button', { style: Object.assign({}, styles.btn, styles.btnDefault), onClick: handleAddSave }, '保存'), - React.createElement('button', { style: Object.assign({}, styles.btn, styles.btnPrimary), onClick: handleAddSubmit }, '提交审核') - ) - ) - ); - } - - function renderEditPage() { - var grid = styles.formGrid; - return React.createElement('div', {}, - React.createElement('div', { style: Object.assign({}, styles.card, { marginBottom: t.spacing16 }) }, - React.createElement('div', { style: grid }, - React.createElement('div', { style: styles.formRow }, - React.createElement('label', { style: styles.formLabel }, '调拨日期', React.createElement('span', { style: styles.formLabelReq }, '*')), - React.createElement('input', { style: styles.input, type: 'date', value: formData.transferDate, onChange: function (e) { handleFormChange('transferDate', e.target.value); } }) - ), - React.createElement('div', { style: styles.formRow }, - React.createElement('label', { style: styles.formLabel }, '出发区域', React.createElement('span', { style: styles.formLabelReq }, '*')), - renderCascader(formData.departProvince, formData.departCity, function (v) { setFormData(function (prev) { var n = {}; for (var k in prev) n[k] = prev[k]; n.departProvince = v; n.departCity = ''; return n; }); }, function (v) { setFormData(function (prev) { var n = {}; for (var k in prev) n[k] = prev[k]; n.departCity = v; return n; }); }, formDepartCascaderOpen, setFormDepartCascaderOpen) - ), - React.createElement('div', { style: styles.formRow }, - React.createElement('label', { style: styles.formLabel }, '接收区域', React.createElement('span', { style: styles.formLabelReq }, '*')), - renderCascader(formData.transferProvince, formData.transferCity, function (v) { setFormData(function (prev) { var n = {}; for (var k in prev) n[k] = prev[k]; n.transferProvince = v; n.transferCity = ''; return n; }); }, function (v) { setFormData(function (prev) { var n = {}; for (var k in prev) n[k] = prev[k]; n.transferCity = v; return n; }); }, formTransferCascaderOpen, setFormTransferCascaderOpen) - ), - React.createElement('div', { style: styles.formRow }, - React.createElement('label', { style: styles.formLabel }, '调拨方式', React.createElement('span', { style: styles.formLabelReq }, '*')), - React.createElement('div', { style: styles.btnGroup }, - React.createElement('button', { type: 'button', style: Object.assign({}, styles.btnGroupItem, formData.transferMethod === 'third_party' ? styles.btnGroupItemActive : {}), onClick: function () { handleFormChange('transferMethod', 'third_party'); } }, '第三方运输'), - React.createElement('button', { type: 'button', style: Object.assign({}, styles.btnGroupItem, styles.btnGroupItemLast, formData.transferMethod === 'driver' ? styles.btnGroupItemActive : {}), onClick: function () { handleFormChange('transferMethod', 'driver'); } }, '司机驾驶') - ) - ), - React.createElement('div', { style: Object.assign({}, styles.formRow, styles.formGridFull) }, - React.createElement('label', { style: styles.formLabel }, '调拨原因', React.createElement('span', { style: styles.formLabelReq }, '*')), - React.createElement('textarea', { style: styles.textarea, value: formData.transferReason, onChange: function (e) { handleFormChange('transferReason', e.target.value); }, placeholder: '请输入调拨原因' }) - ), - React.createElement('div', { style: styles.formRow }, - React.createElement('label', { style: styles.formLabel }, '运输方名称', React.createElement('span', { style: styles.formLabelReq }, '*')), - React.createElement('input', { style: styles.input, value: formData.carrierName, onChange: function (e) { handleFormChange('carrierName', e.target.value); }, placeholder: '请输入运输方名称或司机姓名' }) - ), - React.createElement('div', { style: styles.formRow }, - React.createElement('label', { style: styles.formLabel }, '运输方联系方式', React.createElement('span', { style: styles.formLabelReq }, '*')), - React.createElement('input', { style: styles.input, value: formData.carrierContact, onChange: function (e) { handleFormChange('carrierContact', e.target.value); }, placeholder: '请输入运输方联系方式' }) - ), - React.createElement('div', { style: styles.formRow }, - React.createElement('label', { style: styles.formLabel }, '接收日期', React.createElement('span', { style: styles.formLabelReq }, '*')), - React.createElement('input', { style: styles.input, type: 'date', value: formData.receiveDate, onChange: function (e) { handleFormChange('receiveDate', e.target.value); } }) - ) - ) - ), - React.createElement('div', { style: styles.card }, - React.createElement('div', { style: styles.tableWrapAddPage }, - React.createElement('table', { style: styles.table }, - React.createElement('thead', {}, - React.createElement('tr', {}, - React.createElement('th', { style: Object.assign({}, styles.th, styles.thNowrap) }, '车牌号', React.createElement('span', { style: styles.formLabelReq }, '*')), - React.createElement('th', { style: Object.assign({}, styles.th, styles.thNowrap) }, '车辆类型'), - React.createElement('th', { style: Object.assign({}, styles.th, styles.thNowrap) }, '品牌'), - React.createElement('th', { style: Object.assign({}, styles.th, styles.thNowrap) }, '型号'), - React.createElement('th', { style: Object.assign({}, styles.th, styles.thNowrap) }, '出发停车场'), - React.createElement('th', { style: Object.assign({}, styles.th, styles.thNowrap) }, '出发里程(KM)', React.createElement('span', { style: styles.formLabelReq }, '*')), - React.createElement('th', { style: Object.assign({}, styles.th, styles.thNowrap) }, '接收里程(KM)'), - React.createElement('th', { style: Object.assign({}, styles.th, styles.thNowrap) }, '出发氢量', React.createElement('span', { style: styles.formLabelReq }, '*')), - React.createElement('th', { style: Object.assign({}, styles.th, styles.thNowrap) }, '接收氢量', React.createElement('span', { style: styles.formLabelReq }, '*')), - React.createElement('th', { style: Object.assign({}, styles.th, styles.thNowrap) }, '出发电量', React.createElement('span', { style: styles.formLabelReq }, '*')), - React.createElement('th', { style: Object.assign({}, styles.th, styles.thNowrap) }, '接收电量', React.createElement('span', { style: styles.formLabelReq }, '*')), - React.createElement('th', { style: Object.assign({}, styles.th, styles.thNowrap) }, '操作') - ) - ), - React.createElement('tbody', {}, - editFormLines.map(function (row, rowIndex) { - var isPlateOpen = editPlateSelectOpenRowId === row.rowId; - var plateOptions = getEditPagePlateOptions(row.rowId); - var isEvenRow = rowIndex % 2 === 1; - return React.createElement('tr', { key: row.rowId, style: isEvenRow ? styles.trStripe : styles.trOdd }, - React.createElement('td', { style: Object.assign({}, styles.td, styles.tdNowrap) }, - React.createElement('div', { style: styles.autocompleteWrap }, - React.createElement('input', { - style: Object.assign({}, styles.input, { minWidth: '120px' }), - placeholder: '请选择', - value: isPlateOpen ? editPlateSearchKeyword : (row.plateNo || ''), - onChange: function (e) { setEditPlateSearchKeyword(e.target.value); setEditPlateSelectOpenRowId(row.rowId); }, - onFocus: function () { setEditPlateSelectOpenRowId(row.rowId); setEditPlateSearchKeyword(row.plateNo || ''); }, - onBlur: function () { setTimeout(function () { setEditPlateSelectOpenRowId(null); }, 200); } - }), - isPlateOpen && React.createElement(React.Fragment, {}, - React.createElement('div', { style: { position: 'fixed', left: 0, top: 0, right: 0, bottom: 0, zIndex: 1049 }, onClick: function () { setEditPlateSelectOpenRowId(null); } }), - React.createElement('div', { style: Object.assign({}, styles.autocompletePanel, styles.autocompletePanelOverflow), onClick: function (e) { e.stopPropagation(); } }, - plateOptions.length === 0 - ? React.createElement('div', { style: { padding: '8px 12px', fontSize: t.fontSize14, color: t.neutral6 } }, '无匹配的库存车辆') - : plateOptions.map(function (v) { - return React.createElement('div', { - key: v.id, - style: styles.autocompleteOption, - onMouseDown: function (e) { e.preventDefault(); }, - onClick: function () { - updateEditLine(row.rowId, { vehicleId: v.id, plateNo: v.plateNo, vehicleType: v.vehicleType || '', brand: v.brand || '', model: v.model || '', departParking: v.departParking || '', departH2Unit: v.h2Unit || '' }); - setEditPlateSelectOpenRowId(null); - setEditPlateSearchKeyword(''); - } - }, v.plateNo); - }) - ) - ) - ) - ), - React.createElement('td', { style: Object.assign({}, styles.td, styles.tdNowrap) }, row.vehicleType || '-'), - React.createElement('td', { style: Object.assign({}, styles.td, styles.tdNowrap) }, row.brand || '-'), - React.createElement('td', { style: Object.assign({}, styles.td, styles.tdNowrap) }, row.model || '-'), - React.createElement('td', { style: Object.assign({}, styles.td, styles.tdNowrap) }, row.departParking || '-'), - React.createElement('td', { style: Object.assign({}, styles.td, styles.tdNowrap) }, - React.createElement('input', { style: Object.assign({}, styles.input, { width: '80px' }), type: 'number', value: row.departMileage, onChange: function (e) { updateEditLine(row.rowId, { departMileage: e.target.value }); }, placeholder: '' }) - ), - React.createElement('td', { style: Object.assign({}, styles.td, styles.tdNowrap) }, - React.createElement('input', { style: Object.assign({}, styles.input, { width: '80px' }), type: 'number', value: row.receiveMileage, onChange: function (e) { updateEditLine(row.rowId, { receiveMileage: e.target.value }); }, placeholder: '' }) - ), - React.createElement('td', { style: Object.assign({}, styles.td, styles.tdNowrap) }, - React.createElement('span', { style: { display: 'inline-flex', alignItems: 'center' } }, - React.createElement('input', { style: Object.assign({}, styles.input, { width: '80px' }), value: row.departH2, onChange: function (e) { updateEditLine(row.rowId, { departH2: e.target.value }); }, placeholder: '' }), - row.departH2Unit ? React.createElement('span', { style: { marginLeft: '4px', color: t.neutral6, fontSize: t.fontSize14 } }, row.departH2Unit) : null - ) - ), - React.createElement('td', { style: Object.assign({}, styles.td, styles.tdNowrap) }, - React.createElement('span', { style: { display: 'inline-flex', alignItems: 'center' } }, - React.createElement('input', { style: Object.assign({}, styles.input, { width: '80px' }), value: row.receiveH2, onChange: function (e) { updateEditLine(row.rowId, { receiveH2: e.target.value }); }, placeholder: '' }), - row.departH2Unit ? React.createElement('span', { style: { marginLeft: '4px', color: t.neutral6, fontSize: t.fontSize14 } }, row.departH2Unit) : null - ) - ), - React.createElement('td', { style: Object.assign({}, styles.td, styles.tdNowrap) }, - React.createElement('span', { style: { display: 'inline-flex', alignItems: 'center' } }, - React.createElement('input', { style: Object.assign({}, styles.input, { width: '80px' }), value: row.departElec, onChange: function (e) { updateEditLine(row.rowId, { departElec: e.target.value }); }, placeholder: '' }), - React.createElement('span', { style: { marginLeft: '4px', color: t.neutral6, fontSize: t.fontSize14 } }, 'kWh') - ) - ), - React.createElement('td', { style: Object.assign({}, styles.td, styles.tdNowrap) }, - React.createElement('input', { style: Object.assign({}, styles.input, { width: '80px' }), type: 'number', value: row.receiveElec, onChange: function (e) { updateEditLine(row.rowId, { receiveElec: e.target.value }); }, placeholder: '' }) - ), - React.createElement('td', { style: Object.assign({}, styles.td, styles.tdNowrap) }, - React.createElement('a', { href: '#', style: styles.actionLink, onClick: function (e) { - e.preventDefault(); - if (editFormLines.length <= 1) { setToastMessage('至少保留一行'); setTimeout(function () { setToastMessage(''); }, 2000); return; } - setEditFormLines(editFormLines.filter(function (l) { return l.rowId !== row.rowId; })); - } }, '删除') - ) - ); - }) - ) - ) - ), - React.createElement('div', { style: { marginTop: t.spacing12 } }, - React.createElement('button', { type: 'button', style: Object.assign({}, styles.btn, styles.btnDefault), onClick: function () { setEditFormLines(editFormLines.concat([createEmptyEditLine()])); } }, '新增一行') - ), - React.createElement('div', { style: styles.modalFooter }, - React.createElement('button', { style: Object.assign({}, styles.btn, styles.btnDefault), onClick: function () { setCurrentView('list'); setEditRecord(null); setFormData(defaultForm); setEditFormLines([]); setEditPlateSelectOpenRowId(null); setEditPlateSearchKeyword(''); } }, '取消'), - React.createElement('button', { style: Object.assign({}, styles.btn, styles.btnDefault), onClick: handleEditSave }, '保存'), - React.createElement('button', { style: Object.assign({}, styles.btn, styles.btnPrimary), onClick: function () { handleEditSave(); } }, '提交') - ) - ) - ); - } - - // 查看页:与接收记录页布局、字段一致,全部只读禁用(调拨信息 + 接收日期 + 明细表) - function renderViewPage(record) { - if (!record) return null; - var lines = record.lines || []; - return React.createElement('div', { style: styles.card }, - React.createElement('div', { style: styles.modalTitle }, '查看调拨'), - renderFormContent(true, true), - React.createElement('div', { style: styles.formRow }, - React.createElement('label', { style: styles.formLabel }, '接收日期'), - React.createElement('span', { style: { fontSize: t.fontSize14, color: t.neutral8 } }, record.receiveDate || '-') - ), - React.createElement('div', { style: Object.assign({}, styles.formRow, { marginTop: t.spacing24 }) }, - React.createElement('div', { style: styles.tableWrap }, - React.createElement('table', { style: styles.table }, - React.createElement('thead', {}, - React.createElement('tr', {}, - React.createElement('th', { style: styles.th }, '车牌号'), - React.createElement('th', { style: styles.th }, '车辆类型'), - React.createElement('th', { style: styles.th }, '品牌'), - React.createElement('th', { style: styles.th }, '型号'), - React.createElement('th', { style: styles.th }, '出发停车场'), - React.createElement('th', { style: styles.th }, '出发里程(KM)'), - React.createElement('th', { style: styles.th }, '接收里程(KM)'), - React.createElement('th', { style: styles.th }, '出发氢量'), - React.createElement('th', { style: styles.th }, '接收氢量'), - React.createElement('th', { style: styles.th }, '出发电量'), - React.createElement('th', { style: styles.th }, '接收电量(kWh)') - ) - ), - React.createElement('tbody', {}, - lines.map(function (line, idx) { - var isEvenRow = idx % 2 === 1; - return React.createElement('tr', { key: idx, style: isEvenRow ? styles.trStripe : styles.trOdd }, - React.createElement('td', { style: styles.td }, line.plateNo || '-'), - React.createElement('td', { style: styles.td }, line.vehicleType || '-'), - React.createElement('td', { style: styles.td }, line.brand || '-'), - React.createElement('td', { style: styles.td }, line.model || '-'), - React.createElement('td', { style: styles.td }, line.departParking || '-'), - React.createElement('td', { style: styles.td }, line.departMileage != null ? line.departMileage : '-'), - React.createElement('td', { style: styles.td }, line.receiveMileage != null ? line.receiveMileage : '-'), - React.createElement('td', { style: styles.td }, formatH2(line.departH2, line.departH2Unit)), - React.createElement('td', { style: styles.td }, formatH2(line.receiveH2, line.departH2Unit)), - React.createElement('td', { style: styles.td }, line.departElec != null ? line.departElec + ' kWh' : '-'), - React.createElement('td', { style: styles.td }, line.receiveElec != null ? line.receiveElec + ' kWh' : '-') - ); - }) - ) - ) - ) - ), - React.createElement('div', { style: styles.modalFooter }, - React.createElement('button', { style: Object.assign({}, styles.btn, styles.btnDefault), onClick: function () { setViewRecord(null); setCurrentView('list'); } }, '返回') - ) - ); - } - - function validateEditForm() { - if (!formData.transferDate) { - setToastMessage('请选择调拨日期'); - setTimeout(function () { setToastMessage(''); }, 2000); - return false; - } - if (!formData.departProvince || !formData.departCity) { - setToastMessage('请选择出发区域'); - setTimeout(function () { setToastMessage(''); }, 2000); - return false; - } - if (!formData.transferProvince || !formData.transferCity) { - setToastMessage('请选择接收区域'); - setTimeout(function () { setToastMessage(''); }, 2000); - return false; - } - if (!formData.transferMethod) { - setToastMessage('请选择调拨方式'); - setTimeout(function () { setToastMessage(''); }, 2000); - return false; - } - if (!formData.transferReason || !formData.transferReason.trim()) { - setToastMessage('请填写调拨原因'); - setTimeout(function () { setToastMessage(''); }, 2000); - return false; - } - if (!formData.carrierName || !formData.carrierName.trim()) { - setToastMessage('请填写运输方名称'); - setTimeout(function () { setToastMessage(''); }, 2000); - return false; - } - if (!formData.carrierContact || !formData.carrierContact.trim()) { - setToastMessage('请填写运输方联系方式'); - setTimeout(function () { setToastMessage(''); }, 2000); - return false; - } - if (!formData.receiveDate) { - setToastMessage('请选择接收日期'); - setTimeout(function () { setToastMessage(''); }, 2000); - return false; - } - var validLines = editFormLines.filter(function (row) { return row.plateNo; }); - if (validLines.length === 0) { - setToastMessage('请至少保留一行并选择车牌号'); - setTimeout(function () { setToastMessage(''); }, 2000); - return false; - } - for (var i = 0; i < editFormLines.length; i++) { - var row = editFormLines[i]; - if (!row.plateNo) continue; - var rowNum = i + 1; - if (row.departMileage === '' || row.departMileage === undefined || row.departMileage === null) { - setToastMessage('请填写第' + rowNum + '行出发里程(KM)'); - setTimeout(function () { setToastMessage(''); }, 2000); - return false; - } - if (row.departH2 === '' || row.departH2 === undefined || row.departH2 === null) { - setToastMessage('请填写第' + rowNum + '行出发氢量'); - setTimeout(function () { setToastMessage(''); }, 2000); - return false; - } - if (row.departElec === '' || row.departElec === undefined || row.departElec === null) { - setToastMessage('请填写第' + rowNum + '行出发电量'); - setTimeout(function () { setToastMessage(''); }, 2000); - return false; - } - if (row.receiveH2 === '' || row.receiveH2 === undefined || row.receiveH2 === null) { - setToastMessage('请填写第' + rowNum + '行接收氢量'); - setTimeout(function () { setToastMessage(''); }, 2000); - return false; - } - if (row.receiveElec === '' || row.receiveElec === undefined || row.receiveElec === null) { - setToastMessage('请填写第' + rowNum + '行接收电量'); - setTimeout(function () { setToastMessage(''); }, 2000); - return false; - } - } - return true; - } - - function handleEditSave() { - if (!editRecord) return; - if (!validateEditForm()) return; - var dp = provinceList.find(function (x) { return x.code === formData.departProvince; }); - var dc = (cityMap[formData.departProvince] || []).find(function (x) { return x.code === formData.departCity; }); - var tp = provinceList.find(function (x) { return x.code === formData.transferProvince; }); - var tc = (cityMap[formData.transferProvince] || []).find(function (x) { return x.code === formData.transferCity; }); - var validRows = editFormLines.filter(function (row) { return row.plateNo; }); - var lines = validRows.map(function (row) { - var existing = (editRecord.lines || []).find(function (l) { return l.plateNo === row.plateNo; }); - return { - plateNo: row.plateNo, - vehicleType: row.vehicleType || '-', - brand: row.brand || '-', - model: row.model || '-', - departParking: row.departParking || '-', - departMileage: row.departMileage != null && row.departMileage !== '' ? Number(row.departMileage) : null, - departH2: row.departH2 != null && row.departH2 !== '' ? row.departH2 : '', - departH2Unit: row.departH2Unit || '', - departElec: row.departElec != null && row.departElec !== '' ? Number(row.departElec) : null, - receiveMileage: row.receiveMileage !== '' && row.receiveMileage !== undefined ? Number(row.receiveMileage) : (existing && existing.receiveMileage), - receiveH2: row.receiveH2 != null && row.receiveH2 !== '' ? row.receiveH2 : (existing && existing.receiveH2), - receiveElec: row.receiveElec !== '' && row.receiveElec !== undefined ? Number(row.receiveElec) : (existing && existing.receiveElec), - receiveParking: existing && existing.receiveParking, - receiverName: existing && existing.receiverName - }; - }); - var updated = { - id: editRecord.id, - transferDate: formData.transferDate, - operatorId: editRecord.operatorId, - operatorName: editRecord.operatorName, - departProvince: formData.departProvince, - departCity: formData.departCity, - departLabel: (dp ? dp.name : '') + '-' + (dc ? dc.name : ''), - transferProvince: formData.transferProvince, - transferCity: formData.transferCity, - transferLabel: (tp ? tp.name : '') + '-' + (tc ? tc.name : ''), - transferMethod: formData.transferMethod, - transferReason: formData.transferReason || '', - carrierName: formData.carrierName || '', - carrierContact: formData.carrierContact || '', - approvalStatus: editRecord.approvalStatus, - hasReceiveRecord: editRecord.hasReceiveRecord, - receiveDate: formData.receiveDate, - receiverId: editRecord.receiverId, - receiverName: editRecord.receiverName, - createTime: editRecord.createTime, - lines: lines - }; - setMockTransferList(mockTransferList.map(function (r) { return r.id === editRecord.id ? updated : r; })); - setToastMessage('保存成功'); - setTimeout(function () { setToastMessage(''); }, 2000); - setEditRecord(null); - setCurrentView('list'); - setFormData(defaultForm); - setEditFormLines([]); - setEditPlateSelectOpenRowId(null); - setEditPlateSearchKeyword(''); - } - - function handleWithdraw(transfer) { - if (!transfer) return; - setMockTransferList(mockTransferList.map(function (r) { - if (r.id === transfer.id) { - var next = {}; - for (var k in r) next[k] = r[k]; - next.approvalStatus = 'withdrawn'; - return next; - } - return r; - })); - setWithdrawConfirmRecord(null); - setToastMessage('撤回成功'); - setTimeout(function () { setToastMessage(''); }, 2000); - } - - function setFormDataFromTransfer(transfer) { - if (!transfer || !transfer.lines) return; - var plateNos = transfer.lines.map(function (l) { return l.plateNo; }); - var selectedIds = mockStockVehicles.filter(function (v) { return plateNos.indexOf(v.plateNo) >= 0; }).map(function (v) { return v.id; }); - setFormData({ - transferDate: transfer.transferDate, - operatorId: transfer.operatorId, - operatorName: transfer.operatorName, - selectedVehicleIds: selectedIds, - transferMethod: transfer.transferMethod, - transferReason: transfer.transferReason || '', - departProvince: transfer.departProvince || '', - departCity: transfer.departCity || '', - transferProvince: transfer.transferProvince || '', - transferCity: transfer.transferCity || '', - carrierName: transfer.carrierName || '', - carrierContact: transfer.carrierContact || '' - }); - } - - function openEdit(transfer) { - if (!transfer || !transfer.lines) return; - setEditRecord(transfer); - setFormData({ - transferDate: transfer.transferDate, - receiveDate: transfer.receiveDate || '', - operatorId: transfer.operatorId, - operatorName: transfer.operatorName, - selectedVehicleIds: [], - transferMethod: transfer.transferMethod, - transferReason: transfer.transferReason || '', - departProvince: transfer.departProvince || '', - departCity: transfer.departCity || '', - transferProvince: transfer.transferProvince || '', - transferCity: transfer.transferCity || '', - carrierName: transfer.carrierName || '', - carrierContact: transfer.carrierContact || '' - }); - setEditFormLines(buildEditFormLinesFromRecord(transfer)); - setEditPlateSelectOpenRowId(null); - setEditPlateSearchKeyword(''); - setCurrentView('edit'); - } - - var t = ARCO_TOKEN; - var styles = { - page: { padding: t.spacing24, fontFamily: t.fontFamily, backgroundColor: t.fill, minHeight: '100vh' }, - breadcrumb: { marginBottom: t.spacing16, fontSize: t.fontSize14, color: t.neutral6, display: 'flex', alignItems: 'center', justifyContent: 'space-between' }, - breadcrumbLeft: { display: 'flex', alignItems: 'center' }, - breadcrumbLink: { color: t.link, textDecoration: 'none', marginRight: t.spacing8 }, - breadcrumbCurrent: { color: t.neutral8 }, - breadcrumbRight: { display: 'flex', alignItems: 'center' }, - requirementLink: { color: t.link, textDecoration: 'none', fontSize: t.fontSize14, cursor: 'pointer' }, - modalCloseBtn: { position: 'absolute', right: t.spacing16, top: t.spacing16, width: '24px', height: '24px', display: 'flex', alignItems: 'center', justifyContent: 'center', cursor: 'pointer', borderRadius: t.radiusMedium, backgroundColor: 'transparent', border: 'none', color: t.neutral6, fontSize: '18px', lineHeight: '1', padding: 0 }, - requirementSection: { marginBottom: t.spacing16 }, - requirementSectionTitle: { fontSize: t.fontSize16, fontWeight: 600, color: t.neutral8, marginBottom: t.spacing8 }, - requirementItem: { marginBottom: t.spacing8, paddingLeft: t.spacing16, fontSize: t.fontSize14, color: t.neutral7 }, - requirementSubItem: { marginBottom: t.spacing4, paddingLeft: t.spacing24, fontSize: t.fontSize14, color: t.neutral7 }, - card: { backgroundColor: t.neutral1, borderRadius: t.radiusLarge, boxShadow: t.shadowLight, marginBottom: t.spacing16, padding: t.spacing24 + ' 20px' }, - searchPanel: { paddingBottom: t.spacing24, marginBottom: t.spacing24, borderBottom: '1px solid ' + t.neutral4 }, - searchPanelInner: { display: 'flex', alignItems: 'flex-start', gap: t.spacing16 }, - searchGridWrap: { flex: 1, minWidth: 0 }, - searchGrid: { display: 'grid', gridTemplateColumns: 'repeat(2, 1fr)', gap: t.spacing16 + ' ' + t.spacing24 }, - searchField: { display: 'flex', flexDirection: 'row', alignItems: 'center', gap: '20px', minWidth: 0 }, - searchFieldControl: { flex: 1, minWidth: 0, overflow: 'hidden' }, - searchFieldLabel: { fontSize: t.fontSize14, color: t.neutral8, whiteSpace: 'nowrap', flexShrink: 0 }, - searchDivider: { width: '1px', backgroundColor: t.neutral4, alignSelf: 'stretch', flexShrink: 0 }, - searchActions: { display: 'flex', flexDirection: 'column', gap: t.spacing8, justifyContent: 'center', flexShrink: 0 }, - filterGrid: { display: 'grid', gridTemplateColumns: '1fr 1fr 1fr', gap: t.spacing16 }, - filterItem: { display: 'flex', alignItems: 'center', gap: t.spacing8, flexWrap: 'wrap' }, - filterItemFull: { gridColumn: '1 / -1', display: 'flex', justifyContent: 'flex-end', gap: t.spacing8 }, - label: { marginRight: t.spacing8, fontSize: t.fontSize14, color: t.neutral8, whiteSpace: 'nowrap' }, - filterLabel: { marginRight: t.spacing8, fontSize: t.fontSize14, color: t.neutral8, whiteSpace: 'nowrap', minWidth: '80px', textAlign: 'right' }, - input: { padding: '0 10px', height: '32px', width: '100%', minWidth: '140px', borderRadius: '2px', border: '1px solid ' + t.border, fontSize: t.fontSize14, fontFamily: t.fontFamily, boxSizing: 'border-box', outline: 'none', transition: 'border-color 0.2s, box-shadow 0.2s', textAlign: 'left' }, - select: { padding: '0 32px 0 12px', height: '32px', minWidth: '120px', borderRadius: '2px', border: '1px solid ' + t.border, fontSize: t.fontSize14, fontFamily: t.fontFamily, color: t.neutral8, backgroundColor: t.neutral1, cursor: 'pointer', outline: 'none', appearance: 'none', WebkitAppearance: 'none', backgroundImage: 'url("data:image/svg+xml,%3Csvg xmlns=\'http://www.w3.org/2000/svg\' width=\'12\' height=\'12\' viewBox=\'0 0 48 48\'%3E%3Cpath fill=\'%2386909C\' d=\'M24 32l-12-12h24z\'/%3E%3C/svg%3E")', backgroundRepeat: 'no-repeat', backgroundPosition: 'right 20px center', transition: 'border-color 0.2s, box-shadow 0.2s', textAlign: 'left' }, - btn: { padding: t.spacing8 + ' ' + t.spacing16, borderRadius: t.radiusMedium, cursor: 'pointer', fontSize: t.fontSize14, display: 'inline-flex', alignItems: 'center', justifyContent: 'center', gap: '6px' }, - btnFixed: { height: '32px', padding: '0 16px' }, - btnPrimary: { backgroundColor: t.primary, color: t.neutral1, border: 'none' }, - btnDefault: { backgroundColor: t.neutral1, color: t.neutral8, border: '1px solid ' + t.border }, - btnOutline: { backgroundColor: t.neutral1, color: t.primary, border: '1px solid ' + t.primary }, - toolbar: { display: 'flex', justifyContent: 'flex-end', marginBottom: t.spacing16 }, - tabs: { display: 'flex', borderBottom: '1px solid ' + t.border, marginBottom: t.spacing16 }, - tab: { padding: '10px 16px', cursor: 'pointer', fontSize: t.fontSize14, color: t.neutral7 }, - tabActive: { color: t.primary, borderBottom: '2px solid ' + t.primary, marginBottom: '-1px' }, - tableWrap: { overflowX: 'auto', border: '1px solid ' + t.neutral4, borderRadius: t.radiusMedium }, - tableWrapAddPage: { overflow: 'visible', border: '1px solid ' + t.neutral4, borderRadius: t.radiusMedium }, - table: { width: '100%', borderCollapse: 'collapse', fontSize: t.fontSize14 }, - th: { textAlign: 'left', padding: '0 16px', height: '40px', boxSizing: 'border-box', backgroundColor: t.fillSecondary, borderBottom: '1px solid ' + t.neutral4, fontWeight: 600, color: t.neutral8, verticalAlign: 'middle' }, - thNowrap: { whiteSpace: 'nowrap' }, - thStickyRight: { position: 'sticky', right: 0, backgroundColor: t.fillSecondary, boxShadow: '-2px 0 4px rgba(0,0,0,0.06)', zIndex: 1 }, - tdStickyRight: { position: 'sticky', right: 0, backgroundColor: t.neutral1, boxShadow: '-2px 0 4px rgba(0,0,0,0.06)', zIndex: 1 }, - tdStickyRightStripe: { position: 'sticky', right: 0, backgroundColor: t.fillSecondary, boxShadow: '-2px 0 4px rgba(0,0,0,0.06)', zIndex: 1 }, - td: { padding: '0 16px', height: '42px', boxSizing: 'border-box', borderBottom: '1px solid ' + t.neutral4, color: t.neutral8, verticalAlign: 'middle' }, - tdNowrap: { whiteSpace: 'nowrap' }, - trStripe: { backgroundColor: t.fillSecondary }, - trOdd: { backgroundColor: t.neutral1 }, - actionLink: { color: t.link, cursor: 'pointer', marginRight: t.spacing12, fontSize: t.fontSize14 }, - pagination: { display: 'flex', alignItems: 'center', justifyContent: 'space-between', padding: '16px', borderTop: '1px solid ' + t.neutral4 }, - paginationLeft: { display: 'flex', alignItems: 'center', gap: '8px', fontSize: t.fontSize14, color: t.neutral7 }, - paginationRight: { display: 'flex', alignItems: 'center', gap: '8px' }, - paginationSelect: { padding: '4px 8px', height: '28px', borderRadius: '2px', border: '1px solid ' + t.border, fontSize: t.fontSize14, fontFamily: t.fontFamily }, - paginationBtn: { minWidth: '28px', height: '28px', padding: '0 8px', borderRadius: '2px', border: '1px solid ' + t.border, backgroundColor: t.neutral1, cursor: 'pointer', fontSize: t.fontSize14 }, - paginationBtnActive: { backgroundColor: t.primary, color: t.neutral1, borderColor: t.primary }, - paginationBtnDisabled: { opacity: 0.5, cursor: 'not-allowed' }, - cascaderWrap: { position: 'relative', width: '100%', minWidth: 0 }, - cascaderInput: { display: 'flex', alignItems: 'center', justifyContent: 'flex-start', width: '100%', height: '32px', padding: '0 32px 0 12px', borderRadius: '2px', border: '1px solid ' + t.border, cursor: 'pointer', fontSize: t.fontSize14, fontFamily: t.fontFamily, color: t.neutral8, backgroundColor: t.neutral1, outline: 'none', transition: 'border-color 0.2s, box-shadow 0.2s', boxSizing: 'border-box', textAlign: 'left', backgroundImage: 'url("data:image/svg+xml,%3Csvg xmlns=\'http://www.w3.org/2000/svg\' width=\'12\' height=\'12\' viewBox=\'0 0 48 48\'%3E%3Cpath fill=\'%2386909C\' d=\'M24 32l-12-12h24z\'/%3E%3C/svg%3E")', backgroundRepeat: 'no-repeat', backgroundPosition: 'right 20px center' }, - cascaderPanel: { position: 'absolute', left: 0, top: '100%', marginTop: '4px', backgroundColor: t.neutral1, border: '1px solid ' + t.border, borderRadius: '2px', boxShadow: '0 4px 10px rgba(0,0,0,0.08)', zIndex: 1050, display: 'flex', minWidth: '240px', maxHeight: '256px' }, - cascaderColumn: { minWidth: '100px', maxHeight: '256px', overflowY: 'auto', borderRight: '1px solid ' + t.neutral4 }, - cascaderColumnLast: { borderRight: 'none' }, - cascaderOption: { padding: '8px 12px', fontSize: t.fontSize14, fontFamily: t.fontFamily, color: t.neutral8, cursor: 'pointer', transition: 'background-color 0.1s' }, - cascaderOptionHover: { backgroundColor: t.neutral2 }, - autocompleteWrap: { position: 'relative', minWidth: '140px' }, - autocompleteWrapFull: { width: '100%', minWidth: 0, maxWidth: '100%' }, - autocompleteTrigger: { padding: '0 32px 0 12px', height: '32px', minWidth: '140px', borderRadius: '2px', border: '1px solid ' + t.border, fontSize: t.fontSize14, fontFamily: t.fontFamily, color: t.neutral8, backgroundColor: t.neutral1, boxSizing: 'border-box', outline: 'none', transition: 'border-color 0.2s, box-shadow 0.2s', textAlign: 'left', backgroundImage: 'url("data:image/svg+xml,%3Csvg xmlns=\'http://www.w3.org/2000/svg\' width=\'12\' height=\'12\' viewBox=\'0 0 48 48\'%3E%3Cpath fill=\'%2386909C\' d=\'M24 32l-12-12h24z\'/%3E%3C/svg%3E")', backgroundRepeat: 'no-repeat', backgroundPosition: 'right 20px center' }, - autocompleteTriggerFull: { width: '100%', minWidth: 0, maxWidth: '100%' }, - autocompletePanel: { position: 'absolute', left: 0, top: '100%', marginTop: '4px', backgroundColor: t.neutral1, border: '1px solid ' + t.border, borderRadius: '2px', boxShadow: '0 4px 10px rgba(0,0,0,0.08)', zIndex: 100, minWidth: '100%', maxHeight: '256px', overflowY: 'auto', padding: '4px 0' }, - autocompletePanelOverflow: { zIndex: 1050 }, - autocompleteOption: { padding: '8px 12px', fontSize: t.fontSize14, fontFamily: t.fontFamily, color: t.neutral8, cursor: 'pointer', transition: 'background-color 0.1s' }, - dateRangeWrap: { position: 'relative', width: '100%' }, - dateRangeTrigger: { display: 'flex', alignItems: 'center', justifyContent: 'space-between', width: '100%', height: '32px', padding: '0 10px 0 12px', borderRadius: '2px', border: '1px solid ' + t.border, fontSize: t.fontSize14, fontFamily: t.fontFamily, color: t.neutral8, backgroundColor: t.neutral1, cursor: 'pointer', outline: 'none', transition: 'border-color 0.2s, box-shadow 0.2s', boxSizing: 'border-box', textAlign: 'left' }, - dateRangeTriggerFocus: { borderColor: t.primary, boxShadow: '0 0 0 2px rgba(22,93,255,0.2)' }, - dateRangeDropdown: { position: 'absolute', left: 0, top: '100%', marginTop: '4px', backgroundColor: t.neutral1, border: '1px solid ' + t.border, borderRadius: '4px', boxShadow: '0 4px 10px rgba(0,0,0,0.12)', zIndex: 1050, padding: '12px 16px', minWidth: '480px' }, - dateRangeCalendars: { display: 'flex', gap: '24px' }, - dateRangeCalendar: { minWidth: '200px' }, - dateRangeCalendarHeader: { display: 'flex', alignItems: 'center', justifyContent: 'space-between', marginBottom: '12px' }, - dateRangeCalendarNav: { display: 'flex', alignItems: 'center', gap: '4px' }, - dateRangeCalendarNavBtn: { width: '28px', height: '28px', display: 'flex', alignItems: 'center', justifyContent: 'center', border: 'none', borderRadius: '2px', backgroundColor: 'transparent', color: t.neutral7, cursor: 'pointer', fontSize: '14px' }, - dateRangeCalendarTitle: { fontSize: t.fontSize14, fontWeight: 600, color: t.neutral8 }, - dateRangeCalendarWeekdays: { display: 'grid', gridTemplateColumns: 'repeat(7, 1fr)', gap: '2px', marginBottom: '4px', fontSize: '12px', color: t.neutral6 }, - dateRangeCalendarGrid: { display: 'grid', gridTemplateColumns: 'repeat(7, 1fr)', gap: '2px' }, - dateRangeDay: { width: '28px', height: '28px', display: 'flex', alignItems: 'center', justifyContent: 'center', fontSize: '13px', color: t.neutral8, cursor: 'pointer', borderRadius: '2px' }, - dateRangeDayOther: { color: t.neutral5 }, - dateRangeDaySelected: { backgroundColor: t.primary, color: t.neutral1 }, - dateRangeDayInRange: { backgroundColor: 'rgba(22,93,255,0.15)', color: t.primary }, - dateRangeDayToday: { position: 'relative', fontWeight: 600 }, - formRow: { marginBottom: t.spacing16 }, - formLabel: { display: 'block', marginBottom: '6px', fontSize: t.fontSize14, color: t.neutral8 }, - formLabelReq: { color: t.danger, marginLeft: '2px' }, - formGrid: { display: 'grid', gridTemplateColumns: '1fr 1fr 1fr', gap: t.spacing24, maxWidth: '100%' }, - formGridFull: { gridColumn: '1 / -1' }, - textarea: { width: '100%', minHeight: '80px', padding: '8px 10px', borderRadius: '2px', border: '1px solid ' + t.border, fontSize: t.fontSize14, fontFamily: t.fontFamily, resize: 'vertical', boxSizing: 'border-box' }, - radioGroup: { display: 'flex', gap: t.spacing16, alignItems: 'center' }, - radioItem: { display: 'flex', alignItems: 'center', cursor: 'pointer' }, - btnGroup: { display: 'inline-flex', border: '1px solid ' + t.border, borderRadius: t.radiusMedium, overflow: 'hidden' }, - btnGroupItem: { padding: '0 16px', height: '32px', border: 'none', borderRight: '1px solid ' + t.border, cursor: 'pointer', fontSize: t.fontSize14, backgroundColor: t.neutral1, color: t.neutral7 }, - btnGroupItemLast: { borderRight: 'none' }, - btnGroupItemActive: { backgroundColor: t.primary, color: t.neutral1 }, - transferBox: { display: 'flex', alignItems: 'stretch', gap: t.spacing12, minHeight: '240px', border: '1px solid ' + t.border, borderRadius: t.radiusMedium, padding: t.spacing12 }, - transferColumn: { flex: 1, border: '1px solid ' + t.neutral4, borderRadius: t.radiusSmall, overflow: 'hidden', display: 'flex', flexDirection: 'column' }, - transferColumnHead: { padding: '8px 12px', backgroundColor: t.fillSecondary, fontSize: t.fontSize14, fontWeight: 600 }, - transferColumnList: { flex: 1, overflowY: 'auto', padding: '4px' }, - transferItem: { padding: '8px 12px', fontSize: t.fontSize14, cursor: 'pointer', borderRadius: t.radiusSmall }, - transferItemSelected: { backgroundColor: t.primary, color: t.neutral1 }, - transferBtns: { display: 'flex', flexDirection: 'column', justifyContent: 'center', gap: t.spacing8 }, - stepBar: { display: 'flex', alignItems: 'center', marginBottom: t.spacing24, padding: t.spacing16, backgroundColor: t.fillSecondary, borderRadius: t.radiusMedium }, - stepItem: { display: 'flex', alignItems: 'center', flex: 1 }, - stepDot: { width: '24px', height: '24px', borderRadius: '50%', display: 'flex', alignItems: 'center', justifyContent: 'center', fontSize: '12px', marginRight: '8px' }, - stepDotDone: { backgroundColor: t.success, color: t.neutral1 }, - stepDotCurrent: { backgroundColor: t.primary, color: t.neutral1 }, - stepDotPending: { backgroundColor: t.neutral4, color: t.neutral6 }, - modalMask: { position: 'fixed', left: 0, top: 0, right: 0, bottom: 0, backgroundColor: 'rgba(0,0,0,0.45)', zIndex: 1000, display: 'flex', alignItems: 'center', justifyContent: 'center' }, - modalBox: { backgroundColor: t.neutral1, borderRadius: t.radiusLarge, maxWidth: '90%', maxHeight: '90%', overflow: 'auto', padding: t.spacing24, minWidth: '600px', position: 'relative' }, - modalTitle: { fontSize: t.fontSize16, fontWeight: 600, marginBottom: t.spacing16 }, - modalFooter: { marginTop: t.spacing24, display: 'flex', justifyContent: 'flex-end', gap: t.spacing8 }, - toast: { position: 'fixed', top: t.spacing24, left: '50%', transform: 'translateX(-50%)', backgroundColor: 'rgba(0,0,0,0.75)', color: t.neutral1, padding: '10px 20px', borderRadius: t.radiusMedium, zIndex: 2000, fontSize: t.fontSize14 } - }; - - // 列表运输方名称、运输方联系方式列样式(支持长文本换行) - var carrierInfoTdStyle = Object.assign({}, styles.td, { whiteSpace: 'normal', verticalAlign: 'middle', minWidth: '100px', wordBreak: 'break-word', overflowWrap: 'break-word' }); - - // 穿梭框:左侧可选车辆 = 库存中未在 formData.selectedVehicleIds 的 - var leftVehicles = mockStockVehicles.filter(function (v) { return formData.selectedVehicleIds.indexOf(v.id) < 0; }); - var rightVehicles = mockStockVehicles.filter(function (v) { return formData.selectedVehicleIds.indexOf(v.id) >= 0; }); - - function renderFilterSelect(options, value, onChange, open, setOpen, placeholder, filterFn, fullWidth) { - var list = filterFn ? options.filter(filterFn) : options; - var wrapStyle = fullWidth ? Object.assign({}, styles.autocompleteWrap, styles.autocompleteWrapFull) : styles.autocompleteWrap; - var triggerBase = fullWidth ? Object.assign({}, styles.autocompleteTrigger, styles.autocompleteTriggerFull) : styles.autocompleteTrigger; - var triggerStyle = Object.assign({}, triggerBase, open ? { borderColor: t.primary, boxShadow: '0 0 0 2px rgba(22,93,255,0.2)' } : {}); - return React.createElement('div', { style: wrapStyle }, - React.createElement('input', { - style: triggerStyle, - className: 'arco-select-trigger', - placeholder: placeholder, - value: value, - onChange: function (e) { onChange(e.target.value); }, - onFocus: function () { setOpen(true); }, - onBlur: function () { setTimeout(function () { setOpen(false); }, 200); } - }), - open && list.length > 0 && React.createElement(React.Fragment, {}, - React.createElement('div', { style: { position: 'fixed', left: 0, top: 0, right: 0, bottom: 0, zIndex: 99 }, onClick: function () { setOpen(false); } }), - React.createElement('div', { style: styles.autocompletePanel, onClick: function (e) { e.stopPropagation(); } }, - list.map(function (opt) { - var label = typeof opt === 'string' ? opt : (opt.label || opt.name || opt.plateNo); - var val = typeof opt === 'string' ? opt : (opt.value || opt.id || opt.plateNo); - return React.createElement('div', { - key: val, - style: styles.autocompleteOption, - className: 'arco-select-option', - onMouseDown: function (e) { e.preventDefault(); }, - onMouseEnter: function (e) { e.currentTarget.style.backgroundColor = t.neutral2; }, - onMouseLeave: function (e) { e.currentTarget.style.backgroundColor = 'transparent'; }, - onClick: function () { onChange(typeof opt === 'string' ? opt : (opt.name || opt.plateNo || val)); setOpen(false); } - }, label); - }) - ) - ) - ); - } - - function getCalendarWeeks(year, month) { - var d = new Date(year, month - 1, 1); - var firstDay = d.getDay(); - var daysInMonth = new Date(year, month, 0).getDate(); - var weeks = []; - var week = []; - for (var i = 0; i < firstDay; i++) { - var prev = new Date(year, month - 1, -firstDay + i + 1); - week.push({ date: prev.getDate(), yyyymmdd: prev.getFullYear() + '-' + String(prev.getMonth() + 1).padStart(2, '0') + '-' + String(prev.getDate()).padStart(2, '0'), isCurrentMonth: false }); - } - for (var j = 1; j <= daysInMonth; j++) { - week.push({ date: j, yyyymmdd: year + '-' + String(month).padStart(2, '0') + '-' + String(j).padStart(2, '0'), isCurrentMonth: true }); - if (week.length === 7) { weeks.push(week); week = []; } - } - if (week.length) { - var nextMonth = month === 12 ? 1 : month + 1; - var nextYear = month === 12 ? year + 1 : year; - for (var k = week.length; k < 7; k++) { - var dayNum = k - week.length + 1; - week.push({ date: dayNum, yyyymmdd: nextYear + '-' + String(nextMonth).padStart(2, '0') + '-' + String(dayNum).padStart(2, '0'), isCurrentMonth: false }); - } - weeks.push(week); - } - return weeks; - } - function renderDateRangePicker(startValue, endValue, setStart, setEnd, open, setOpen, viewLeft, viewRight, setViewLeft, setViewRight) { - var displayText = (startValue && endValue) ? (startValue + ' - ' + endValue) : (startValue ? (startValue + ' - 结束日期') : '开始日期 - 结束日期'); - var triggerStyle = Object.assign({}, styles.dateRangeTrigger, open ? styles.dateRangeTriggerFocus : {}); - var today = new Date(); - var todayStr = today.getFullYear() + '-' + String(today.getMonth() + 1).padStart(2, '0') + '-' + String(today.getDate()).padStart(2, '0'); - var leftYM = viewLeft || getInitialViewMonth(startValue); - var rightYM = viewRight || (function () { - var p = leftYM.split('-'); - var y = parseInt(p[0], 10); - var m = parseInt(p[1], 10); - if (m === 12) return (y + 1) + '-01'; - return y + '-' + String(m + 1).padStart(2, '0'); - }()); - var leftParts = leftYM.split('-'); - var rightParts = rightYM.split('-'); - var leftWeeks = getCalendarWeeks(parseInt(leftParts[0], 10), parseInt(leftParts[1], 10)); - var rightWeeks = getCalendarWeeks(parseInt(rightParts[0], 10), parseInt(rightParts[1], 10)); - function goPrevMonth(isLeftCalendar) { - var ym = isLeftCalendar ? leftYM : rightYM; - var p = ym.split('-'); - var y = parseInt(p[0], 10); - var m = parseInt(p[1], 10); - if (m === 1) { y--; m = 12; } else m--; - var next = y + '-' + String(m).padStart(2, '0'); - if (isLeftCalendar) { setViewLeft(next); setViewRight(m === 12 ? (y + 1) + '-01' : y + '-' + String(m + 1).padStart(2, '0')); } - else { setViewRight(next); setViewLeft(m === 1 ? (y - 1) + '-12' : y + '-' + String(m - 1).padStart(2, '0')); } - } - function goNextMonth(isLeftCalendar) { - var ym = isLeftCalendar ? leftYM : rightYM; - var p = ym.split('-'); - var y = parseInt(p[0], 10); - var m = parseInt(p[1], 10); - if (m === 12) { y++; m = 1; } else m++; - var next = y + '-' + String(m).padStart(2, '0'); - if (isLeftCalendar) { setViewLeft(next); setViewRight(m === 12 ? (y + 1) + '-01' : y + '-' + String(m + 1).padStart(2, '0')); } - else { setViewRight(next); setViewLeft(m === 1 ? (y - 1) + '-12' : y + '-' + String(m - 1).padStart(2, '0')); } - } - function onSelectDate(yyyymmdd) { - if (!startValue || (startValue && endValue)) { - setStart(yyyymmdd); - setEnd(''); - } else { - if (yyyymmdd < startValue) { setEnd(startValue); setStart(yyyymmdd); } - else setEnd(yyyymmdd); - } - } - function renderOneCalendar(weeks, isLeft) { - return React.createElement('div', { style: styles.dateRangeCalendar }, - React.createElement('div', { style: styles.dateRangeCalendarHeader }, - React.createElement('div', { style: styles.dateRangeCalendarNav }, - React.createElement('button', { type: 'button', style: styles.dateRangeCalendarNavBtn, onClick: function () { goPrevMonth(isLeft); } }, '\u00AB'), - React.createElement('button', { type: 'button', style: styles.dateRangeCalendarNavBtn, onClick: function () { goPrevMonth(isLeft); } }, '\u2039') - ), - React.createElement('span', { style: styles.dateRangeCalendarTitle }, (isLeft ? leftYM : rightYM).replace('-', '\u5E74') + '\u6708'), - React.createElement('div', { style: styles.dateRangeCalendarNav }, - React.createElement('button', { type: 'button', style: styles.dateRangeCalendarNavBtn, onClick: function () { goNextMonth(isLeft); } }, '\u203A'), - React.createElement('button', { type: 'button', style: styles.dateRangeCalendarNavBtn, onClick: function () { goNextMonth(isLeft); } }, '\u00BB') - ) - ), - React.createElement('div', { style: styles.dateRangeCalendarWeekdays }, ['日', '一', '二', '三', '四', '五', '六'].map(function (w) { return React.createElement('div', { key: w }, w); })), - React.createElement('div', { style: styles.dateRangeCalendarGrid }, - weeks.map(function (week, wi) { - return week.map(function (day, di) { - var isSelected = day.yyyymmdd === startValue || day.yyyymmdd === endValue; - var isInRange = startValue && endValue && day.yyyymmdd >= startValue && day.yyyymmdd <= endValue; - var isToday = day.yyyymmdd === todayStr; - var dayStyle = Object.assign({}, styles.dateRangeDay, !day.isCurrentMonth ? styles.dateRangeDayOther : {}, isSelected ? styles.dateRangeDaySelected : {}, isInRange && !isSelected ? styles.dateRangeDayInRange : {}, isToday ? styles.dateRangeDayToday : {}); - return React.createElement('div', { - key: wi + '-' + di, - style: dayStyle, - onClick: function () { onSelectDate(day.yyyymmdd); } - }, day.date); - }); - }) - ) - ); - } - return React.createElement('div', { style: styles.dateRangeWrap }, - React.createElement('div', { - style: triggerStyle, - onClick: function () { - if (!open) { - setViewLeft(getInitialViewMonth(startValue)); - var l = getInitialViewMonth(startValue); - var p = l.split('-'); - var y = parseInt(p[0], 10); - var m = parseInt(p[1], 10); - setViewRight(m === 12 ? (y + 1) + '-01' : y + '-' + String(m + 1).padStart(2, '0')); - } - setOpen(!open); - } - }, React.createElement('span', { style: { color: (startValue || endValue) ? t.neutral8 : t.neutral6 } }, displayText), React.createElement('span', { style: { width: '16px', height: '16px', flexShrink: 0, marginLeft: '8px', display: 'inline-flex', alignItems: 'center', justifyContent: 'center', color: t.neutral6 } }, React.createElement('svg', { width: 16, height: 16, viewBox: '0 0 24 24', fill: 'none', stroke: 'currentColor', strokeWidth: 2 }, React.createElement('rect', { x: 3, y: 4, width: 18, height: 18, rx: 2 }), React.createElement('line', { x1: 16, y1: 2, x2: 16, y2: 6 }), React.createElement('line', { x1: 8, y1: 2, x2: 8, y2: 6 }), React.createElement('line', { x1: 3, y1: 10, x2: 21, y2: 10 })))), - open && React.createElement(React.Fragment, {}, - React.createElement('div', { style: { position: 'fixed', left: 0, top: 0, right: 0, bottom: 0, zIndex: 1049 }, onClick: function () { setOpen(false); } }), - React.createElement('div', { style: styles.dateRangeDropdown, onClick: function (e) { e.stopPropagation(); } }, - React.createElement('div', { style: styles.dateRangeCalendars }, - renderOneCalendar(leftWeeks, true), - renderOneCalendar(rightWeeks, false) - ) - ) - ) - ); - } - - function renderCascader(provinceCode, cityCode, setProvince, setCity, open, setOpen) { - var p = provinceList.find(function (x) { return x.code === provinceCode; }); - var c = (cityMap[provinceCode] || []).find(function (x) { return x.code === cityCode; }); - var display = (p ? p.name : '') + (p && c ? ' - ' : '') + (c ? c.name : ''); - var cascaderTriggerStyle = Object.assign({}, styles.cascaderInput, open ? { borderColor: t.primary, boxShadow: '0 0 0 2px rgba(22,93,255,0.2)' } : {}); - return React.createElement('div', { style: styles.cascaderWrap }, - React.createElement('div', { - style: cascaderTriggerStyle, - className: 'arco-select-trigger', - onClick: function () { setOpen(!open); } - }, React.createElement('span', { style: { color: (provinceCode && cityCode) ? t.neutral8 : t.neutral6, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' } }, display || '请选择省-市')), - open && React.createElement(React.Fragment, {}, - React.createElement('div', { style: { position: 'fixed', left: 0, top: 0, right: 0, bottom: 0, zIndex: 1049 }, onClick: function () { setOpen(false); } }), - React.createElement('div', { style: styles.cascaderPanel, onClick: function (e) { e.stopPropagation(); } }, - React.createElement('div', { style: styles.cascaderColumn }, - provinceList.map(function (pr) { - return React.createElement('div', { - key: pr.code, - style: styles.cascaderOption, - className: 'arco-select-option', - onMouseEnter: function (e) { e.currentTarget.style.backgroundColor = t.neutral2; }, - onMouseLeave: function (e) { e.currentTarget.style.backgroundColor = 'transparent'; }, - onClick: function () { setProvince(pr.code); setCity(''); } - }, pr.name); - }) - ), - React.createElement('div', { style: Object.assign({}, styles.cascaderColumn, styles.cascaderColumnLast) }, - (cityMap[provinceCode] || []).map(function (ci) { - return React.createElement('div', { - key: ci.code, - style: styles.cascaderOption, - className: 'arco-select-option', - onMouseEnter: function (e) { e.currentTarget.style.backgroundColor = t.neutral2; }, - onMouseLeave: function (e) { e.currentTarget.style.backgroundColor = 'transparent'; }, - onClick: function () { setCity(ci.code); setOpen(false); } - }, ci.name); - }) - ) - ) - ) - ); - } - - function renderFormContent(readonly, isView) { - var disabled = readonly === true; - var grid = styles.formGrid; - return React.createElement('div', { style: grid }, - React.createElement('div', { style: styles.formRow }, - React.createElement('label', { style: styles.formLabel }, '调拨日期', !disabled && React.createElement('span', { style: styles.formLabelReq }, '*')), - disabled ? React.createElement('span', {}, formData.transferDate) : React.createElement('input', { style: styles.input, type: 'date', value: formData.transferDate, onChange: function (e) { handleFormChange('transferDate', e.target.value); } }) - ), - React.createElement('div', { style: styles.formRow }, - React.createElement('label', { style: styles.formLabel }, '操作人', !disabled && React.createElement('span', { style: styles.formLabelReq }, '*')), - disabled ? React.createElement('span', {}, formData.operatorName) : renderFilterSelect(mockOpsUsers, formData.operatorName, function (v) { handleFormChange('operatorName', v); var u = mockOpsUsers.find(function (x) { return x.name === v; }); if (u) handleFormChange('operatorId', u.id); }, formOperatorOpen, setFormOperatorOpen, '支持模糊搜索', function (u) { return !formData.operatorName || (u.name && u.name.indexOf(formData.operatorName) >= 0); }) - ), - React.createElement('div', { style: Object.assign({}, styles.formRow, styles.formGridFull) }, - React.createElement('label', { style: styles.formLabel }, '车牌号', !disabled && React.createElement('span', { style: styles.formLabelReq }, '*')), - disabled ? React.createElement('span', {}, (formData.selectedVehicleIds && mockStockVehicles.filter(function (v) { return formData.selectedVehicleIds.indexOf(v.id) >= 0; }).map(function (v) { return v.plateNo; }).join('、')) || '-') : React.createElement('div', { style: styles.transferBox }, - React.createElement('div', { style: styles.transferColumn }, - React.createElement('div', { style: styles.transferColumnHead }, '库存车辆'), - React.createElement('div', { style: styles.transferColumnList }, - leftVehicles.map(function (v) { - var selected = leftSelectedIds.indexOf(v.id) >= 0; - return React.createElement('div', { - key: v.id, - style: Object.assign({}, styles.transferItem, selected ? styles.transferItemSelected : {}), - onClick: function () { - if (selected) setLeftSelectedIds(leftSelectedIds.filter(function (id) { return id !== v.id; })); - else setLeftSelectedIds(leftSelectedIds.concat([v.id])); - } - }, v.plateNo); - }) - ) - ), - React.createElement('div', { style: styles.transferBtns }, - React.createElement('button', { style: Object.assign({}, styles.btn, styles.btnDefault), title: '添加', onClick: function () { - handleFormChange('selectedVehicleIds', (formData.selectedVehicleIds || []).concat(leftSelectedIds)); - setLeftSelectedIds([]); - } }, '→'), - React.createElement('button', { style: Object.assign({}, styles.btn, styles.btnDefault), title: '移除', onClick: function () { - handleFormChange('selectedVehicleIds', (formData.selectedVehicleIds || []).filter(function (id) { return rightSelectedIds.indexOf(id) < 0; })); - setRightSelectedIds([]); - } }, '←') - ), - React.createElement('div', { style: styles.transferColumn }, - React.createElement('div', { style: styles.transferColumnHead }, '已选车辆'), - React.createElement('div', { style: styles.transferColumnList }, - rightVehicles.map(function (v) { - var selected = rightSelectedIds.indexOf(v.id) >= 0; - return React.createElement('div', { - key: v.id, - style: Object.assign({}, styles.transferItem, selected ? styles.transferItemSelected : {}), - onClick: function () { - if (selected) setRightSelectedIds(rightSelectedIds.filter(function (id) { return id !== v.id; })); - else setRightSelectedIds(rightSelectedIds.concat([v.id])); - } - }, v.plateNo); - }) - ) - ) - ) - ), - React.createElement('div', { style: styles.formRow }, - React.createElement('label', { style: styles.formLabel }, '调拨方式', !disabled && React.createElement('span', { style: styles.formLabelReq }, '*')), - disabled ? React.createElement('span', {}, getMethodLabel(formData.transferMethod)) : React.createElement('div', { style: styles.radioGroup }, - TRANSFER_METHODS.map(function (m) { - return React.createElement('label', { key: m.value, style: styles.radioItem }, - React.createElement('input', { type: 'radio', name: 'transferMethod', value: m.value, checked: formData.transferMethod === m.value, onChange: function () { handleFormChange('transferMethod', m.value); } }), - React.createElement('span', { style: { marginLeft: '6px' } }, m.label) - ); - }) - ) - ), - React.createElement('div', { style: Object.assign({}, styles.formRow, styles.formGridFull) }, - React.createElement('label', { style: styles.formLabel }, '调拨原因', !disabled && React.createElement('span', { style: styles.formLabelReq }, '*')), - disabled ? React.createElement('span', {}, formData.transferReason || '-') : React.createElement('textarea', { style: styles.textarea, value: formData.transferReason, onChange: function (e) { handleFormChange('transferReason', e.target.value); }, placeholder: '请输入' }) - ), - React.createElement('div', { style: styles.formRow }, - React.createElement('label', { style: styles.formLabel }, '出发区域', !disabled && React.createElement('span', { style: styles.formLabelReq }, '*')), - disabled ? React.createElement('span', {}, (function () { - var r = viewRecord || editRecord; - if (r && r.departLabel) return r.departLabel; - if (formData.departProvince && formData.departCity) { - var p = provinceList.find(function (x) { return x.code === formData.departProvince; }); - var c = (cityMap[formData.departProvince] || []).find(function (x) { return x.code === formData.departCity; }); - return (p ? p.name : '') + '-' + (c ? c.name : ''); - } - return '-'; - }()) ) : renderCascader(formData.departProvince, formData.departCity, function (v) { setFormData(function (prev) { var n = {}; for (var k in prev) n[k] = prev[k]; n.departProvince = v; n.departCity = ''; return n; }); }, function (v) { setFormData(function (prev) { var n = {}; for (var k in prev) n[k] = prev[k]; n.departCity = v; return n; }); }, formDepartCascaderOpen, setFormDepartCascaderOpen) - ), - React.createElement('div', { style: styles.formRow }, - React.createElement('label', { style: styles.formLabel }, '接收区域', !disabled && React.createElement('span', { style: styles.formLabelReq }, '*')), - disabled ? React.createElement('span', {}, (function () { - var r = viewRecord || editRecord; - if (r && r.transferLabel) return r.transferLabel; - if (formData.transferProvince && formData.transferCity) { - var p = provinceList.find(function (x) { return x.code === formData.transferProvince; }); - var c = (cityMap[formData.transferProvince] || []).find(function (x) { return x.code === formData.transferCity; }); - return (p ? p.name : '') + '-' + (c ? c.name : ''); - } - return '-'; - }()) ) : renderCascader(formData.transferProvince, formData.transferCity, function (v) { setFormData(function (prev) { var n = {}; for (var k in prev) n[k] = prev[k]; n.transferProvince = v; n.transferCity = ''; return n; }); }, function (v) { setFormData(function (prev) { var n = {}; for (var k in prev) n[k] = prev[k]; n.transferCity = v; return n; }); }, formTransferCascaderOpen, setFormTransferCascaderOpen) - ), - React.createElement('div', { style: styles.formRow }, - React.createElement('label', { style: styles.formLabel }, '运输方名称', !disabled && React.createElement('span', { style: styles.formLabelReq }, '*')), - disabled ? React.createElement('span', {}, (viewRecord || editRecord || formData).carrierName || '-') : React.createElement('input', { style: styles.input, value: formData.carrierName, onChange: function (e) { handleFormChange('carrierName', e.target.value); }, placeholder: '请输入' }) - ), - React.createElement('div', { style: styles.formRow }, - React.createElement('label', { style: styles.formLabel }, '运输方联系方式', !disabled && React.createElement('span', { style: styles.formLabelReq }, '*')), - disabled ? React.createElement('span', {}, (viewRecord || editRecord || formData).carrierContact || '-') : React.createElement('input', { style: styles.input, value: formData.carrierContact, onChange: function (e) { handleFormChange('carrierContact', e.target.value); }, placeholder: '请输入' }) - ) - ); - } - - return ( - React.createElement('div', { style: styles.page }, - React.createElement('style', { - dangerouslySetInnerHTML: { - __html: '.arco-select-trigger:hover{border-color:#C9CDD4 !important;}' - + 'select:hover{border-color:#C9CDD4 !important;}' - + 'select:focus{border-color:#165DFF !important;box-shadow:0 0 0 2px rgba(22,93,255,0.2) !important;}' - + '.arco-select-option:hover{background-color:#F7F8FA !important;}' - } - }), - React.createElement('div', { style: styles.breadcrumb }, - React.createElement('div', { style: styles.breadcrumbLeft }, - React.createElement('a', { href: '#', style: styles.breadcrumbLink, onClick: function (e) { e.preventDefault(); } }, '运维管理'), - React.createElement('span', { style: { marginRight: '8px' } }, '/'), - React.createElement('a', { href: '#', style: styles.breadcrumbLink, onClick: function (e) { e.preventDefault(); } }, '车辆业务'), - React.createElement('span', { style: { marginRight: '8px' } }, '/'), - React.createElement('span', { style: styles.breadcrumbCurrent }, '调拨管理') - ), - React.createElement('div', { style: styles.breadcrumbRight }, - React.createElement('a', { href: '#', style: styles.requirementLink, onClick: function (e) { e.preventDefault(); setShowRequirementModal(true); } }, '查看需求说明') - ) - ), - - currentView === 'list' && React.createElement(React.Fragment, {}, - React.createElement('div', { style: styles.card }, - React.createElement('div', { style: styles.searchPanel }, - React.createElement('div', { style: styles.searchPanelInner }, - React.createElement('div', { style: styles.searchGridWrap }, - React.createElement('div', { style: styles.searchGrid }, - React.createElement('div', { style: styles.searchField }, - React.createElement('span', { style: styles.searchFieldLabel }, '调拨日期'), - React.createElement('div', { style: styles.searchFieldControl }, renderDateRangePicker(filterDateStart, filterDateEnd, setFilterDateStart, setFilterDateEnd, filterDateRangeOpen, setFilterDateRangeOpen, filterDateRangeViewLeft, filterDateRangeViewRight, setFilterDateRangeViewLeft, setFilterDateRangeViewRight)) - ), - React.createElement('div', { style: styles.searchField }, - React.createElement('span', { style: styles.searchFieldLabel }, '调拨人'), - React.createElement('div', { style: styles.searchFieldControl }, renderFilterSelect(mockOpsUsers.map(function (u) { return u.name; }), filterOperator, setFilterOperator, filterOperatorOpen, setFilterOperatorOpen, '模糊搜索', function (n) { return !filterOperator || n.indexOf(filterOperator) >= 0; }, true)) - ), - React.createElement('div', { style: styles.searchField }, - React.createElement('span', { style: styles.searchFieldLabel }, '接收日期'), - React.createElement('div', { style: styles.searchFieldControl }, renderDateRangePicker(filterReceiveDateStart, filterReceiveDateEnd, setFilterReceiveDateStart, setFilterReceiveDateEnd, filterReceiveDateRangeOpen, setFilterReceiveDateRangeOpen, filterReceiveDateRangeViewLeft, filterReceiveDateRangeViewRight, setFilterReceiveDateRangeViewLeft, setFilterReceiveDateRangeViewRight)) - ), - React.createElement('div', { style: styles.searchField }, - React.createElement('span', { style: styles.searchFieldLabel }, '接收人'), - React.createElement('div', { style: styles.searchFieldControl }, renderFilterSelect(mockOpsUsers.map(function (u) { return u.name; }), filterReceiver, setFilterReceiver, filterReceiverOpen, setFilterReceiverOpen, '模糊搜索', function (n) { return !filterReceiver || n.indexOf(filterReceiver) >= 0; }, true)) - ), - React.createElement('div', { style: styles.searchField }, - React.createElement('span', { style: styles.searchFieldLabel }, '车牌号'), - React.createElement('div', { style: styles.searchFieldControl }, renderFilterSelect(mockStockVehicles.map(function (v) { return v.plateNo; }), filterPlateNo, setFilterPlateNo, filterPlateOpen, setFilterPlateOpen, '模糊搜索', function (p) { return !filterPlateNo || p.indexOf(filterPlateNo) >= 0; }, true)) - ), - React.createElement('div', { style: styles.searchField }, - React.createElement('span', { style: styles.searchFieldLabel }, '出发区域'), - React.createElement('div', { style: styles.searchFieldControl }, renderCascader(filterDepartProvince, filterDepartCity, setFilterDepartProvince, setFilterDepartCity, filterCascaderDepartOpen, setFilterCascaderDepartOpen)) - ), - React.createElement('div', { style: styles.searchField }, - React.createElement('span', { style: styles.searchFieldLabel }, '调拨区域'), - React.createElement('div', { style: styles.searchFieldControl }, renderCascader(filterTransferProvince, filterTransferCity, setFilterTransferProvince, setFilterTransferCity, filterCascaderTransferOpen, setFilterCascaderTransferOpen)) - ), - React.createElement('div', { style: styles.searchField }, - React.createElement('span', { style: styles.searchFieldLabel }, '调拨方式'), - React.createElement('div', { style: styles.searchFieldControl }, - React.createElement('select', { - style: Object.assign({}, styles.select, { width: '100%', minWidth: 0 }), - value: filterMethod, - onChange: function (e) { setFilterMethod(e.target.value); } - }, React.createElement('option', { value: '' }, '全部'), TRANSFER_METHODS.map(function (m) { return React.createElement('option', { key: m.value, value: m.value }, m.label); })) - ) - ), - React.createElement('div', { style: styles.searchField }, - React.createElement('span', { style: styles.searchFieldLabel }, '审批状态'), - React.createElement('div', { style: styles.searchFieldControl }, - React.createElement('select', { - style: Object.assign({}, styles.select, { width: '100%', minWidth: 0 }), - value: filterApprovalStatus, - onChange: function (e) { setFilterApprovalStatus(e.target.value); } - }, React.createElement('option', { value: '' }, '全部'), APPROVAL_STATUS.map(function (s) { return React.createElement('option', { key: s.value, value: s.value }, s.label); })) - ) - ) - ) - ), - React.createElement('div', { style: styles.searchDivider }), - React.createElement('div', { style: styles.searchActions }, - React.createElement('button', { - style: Object.assign({}, styles.btn, styles.btnPrimary, styles.btnFixed), - onClick: function () { - setAppliedFilters({ - filterDateStart: filterDateStart, - filterDateEnd: filterDateEnd, - filterOperator: filterOperator, - filterReceiveDateStart: filterReceiveDateStart, - filterReceiveDateEnd: filterReceiveDateEnd, - filterReceiver: filterReceiver, - filterPlateNo: filterPlateNo, - filterDepartProvince: filterDepartProvince, - filterDepartCity: filterDepartCity, - filterTransferProvince: filterTransferProvince, - filterTransferCity: filterTransferCity, - filterMethod: filterMethod, - filterApprovalStatus: filterApprovalStatus - }); - setCurrentPage(1); - setToastMessage('查询成功'); - setTimeout(function () { setToastMessage(''); }, 1500); - } - }, '查询'), - React.createElement('button', { - style: Object.assign({}, styles.btn, styles.btnDefault, styles.btnFixed), - onClick: function () { - setFilterDateStart(''); setFilterDateEnd(''); setFilterReceiveDateStart(''); setFilterReceiveDateEnd(''); setFilterOperator(''); setFilterReceiver(''); setFilterPlateNo(''); - setFilterDepartProvince(''); setFilterDepartCity(''); setFilterTransferProvince(''); setFilterTransferCity(''); - setFilterMethod(''); setFilterApprovalStatus(''); - setAppliedFilters({}); - setCurrentPage(1); - } - }, '重置') - ) - ) - ), - React.createElement('div', { style: styles.tabs }, - React.createElement('div', { style: Object.assign({}, styles.tab, listTab === 'in_progress' ? styles.tabActive : {}), onClick: function () { setListTab('in_progress'); setCurrentPage(1); setSelectedRowIds([]); } }, '进行中'), - React.createElement('div', { style: Object.assign({}, styles.tab, listTab === 'history' ? styles.tabActive : {}), onClick: function () { setListTab('history'); setCurrentPage(1); setSelectedRowIds([]); } }, '历史记录') - ), - React.createElement('div', { style: styles.toolbar }, - listTab === 'in_progress' && React.createElement('button', { style: Object.assign({}, styles.btn, styles.btnPrimary, styles.btnFixed), onClick: function () { setAddFormData(defaultAddForm); setAddFormLines([createEmptyAddLine()]); setCurrentView('add'); } }, '新增'), - React.createElement('button', { style: Object.assign({}, styles.btn, styles.btnDefault, styles.btnFixed), onClick: function () { setToastMessage(selectedRowIds.length ? '导出' + selectedRowIds.length + '条' : '请先勾选要导出的数据'); setTimeout(function () { setToastMessage(''); }, 2000); } }, '导出') - ), - React.createElement('div', { style: styles.tableWrap }, - React.createElement('table', { style: styles.table }, - React.createElement('thead', {}, - React.createElement('tr', {}, - listTab === 'in_progress' ? React.createElement(React.Fragment, {}, - React.createElement('th', { style: Object.assign({}, styles.th, styles.thNowrap, { width: '32px' }) }, React.createElement('input', { type: 'checkbox', checked: paginatedList.length > 0 && selectedRowIds.length === paginatedList.length, onChange: function (e) { setSelectedRowIds(e.target.checked ? paginatedList.map(function (r) { return r.rowId; }) : []); } })), - React.createElement('th', { style: Object.assign({}, styles.th, styles.thNowrap) }, '调拨日期'), - React.createElement('th', { style: Object.assign({}, styles.th, styles.thNowrap) }, '出发区域'), - React.createElement('th', { style: Object.assign({}, styles.th, styles.thNowrap) }, '调拨人'), - React.createElement('th', { style: Object.assign({}, styles.th, styles.thNowrap) }, '接收区域'), - React.createElement('th', { style: Object.assign({}, styles.th, styles.thNowrap) }, '调拨方式'), - React.createElement('th', { style: Object.assign({}, styles.th, styles.thNowrap) }, '调拨原因'), - React.createElement('th', { style: Object.assign({}, styles.th, styles.thNowrap) }, '车牌号'), - React.createElement('th', { style: Object.assign({}, styles.th, styles.thNowrap) }, '车辆类型'), - React.createElement('th', { style: Object.assign({}, styles.th, styles.thNowrap) }, '品牌'), - React.createElement('th', { style: Object.assign({}, styles.th, styles.thNowrap) }, '型号'), - React.createElement('th', { style: Object.assign({}, styles.th, styles.thNowrap) }, '运输方名称'), - React.createElement('th', { style: Object.assign({}, styles.th, styles.thNowrap) }, '运输方联系方式'), - React.createElement('th', { style: Object.assign({}, styles.th, styles.thNowrap) }, '出发里程(KM)'), - React.createElement('th', { style: Object.assign({}, styles.th, styles.thNowrap) }, '出发氢量'), - React.createElement('th', { style: Object.assign({}, styles.th, styles.thNowrap) }, '出发电量'), - React.createElement('th', { style: Object.assign({}, styles.th, styles.thNowrap) }, '出发停车场'), - React.createElement('th', { style: Object.assign({}, styles.th, styles.thNowrap) }, '创建日期'), - React.createElement('th', { style: Object.assign({}, styles.th, styles.thNowrap, styles.thStickyRight) }, '操作') - ) : React.createElement(React.Fragment, {}, - React.createElement('th', { style: Object.assign({}, styles.th, styles.thNowrap, { width: '32px' }) }, React.createElement('input', { type: 'checkbox', checked: paginatedList.length > 0 && selectedRowIds.length === paginatedList.length, onChange: function (e) { setSelectedRowIds(e.target.checked ? paginatedList.map(function (r) { return r.rowId; }) : []); } })), - React.createElement('th', { style: Object.assign({}, styles.th, styles.thNowrap) }, '调拨日期'), - React.createElement('th', { style: Object.assign({}, styles.th, styles.thNowrap) }, '出发区域'), - React.createElement('th', { style: Object.assign({}, styles.th, styles.thNowrap) }, '调拨人'), - React.createElement('th', { style: Object.assign({}, styles.th, styles.thNowrap) }, '接收日期'), - React.createElement('th', { style: Object.assign({}, styles.th, styles.thNowrap) }, '接收区域'), - React.createElement('th', { style: Object.assign({}, styles.th, styles.thNowrap) }, '调拨方式'), - React.createElement('th', { style: Object.assign({}, styles.th, styles.thNowrap) }, '调拨原因'), - React.createElement('th', { style: Object.assign({}, styles.th, styles.thNowrap) }, '接收人'), - React.createElement('th', { style: Object.assign({}, styles.th, styles.thNowrap) }, '车牌号'), - React.createElement('th', { style: Object.assign({}, styles.th, styles.thNowrap) }, '车辆类型'), - React.createElement('th', { style: Object.assign({}, styles.th, styles.thNowrap) }, '品牌'), - React.createElement('th', { style: Object.assign({}, styles.th, styles.thNowrap) }, '型号'), - React.createElement('th', { style: Object.assign({}, styles.th, styles.thNowrap) }, '运输方名称'), - React.createElement('th', { style: Object.assign({}, styles.th, styles.thNowrap) }, '运输方联系方式'), - React.createElement('th', { style: Object.assign({}, styles.th, styles.thNowrap) }, '出发里程(KM)'), - React.createElement('th', { style: Object.assign({}, styles.th, styles.thNowrap) }, '接收里程(KM)'), - React.createElement('th', { style: Object.assign({}, styles.th, styles.thNowrap) }, '出发氢量'), - React.createElement('th', { style: Object.assign({}, styles.th, styles.thNowrap) }, '接收氢量'), - React.createElement('th', { style: Object.assign({}, styles.th, styles.thNowrap) }, '出发电量'), - React.createElement('th', { style: Object.assign({}, styles.th, styles.thNowrap) }, '接收电量'), - React.createElement('th', { style: Object.assign({}, styles.th, styles.thNowrap) }, '出发停车场'), - React.createElement('th', { style: Object.assign({}, styles.th, styles.thNowrap) }, '接收停车场'), - React.createElement('th', { style: Object.assign({}, styles.th, styles.thNowrap) }, '创建日期'), - React.createElement('th', { style: Object.assign({}, styles.th, styles.thNowrap, styles.thStickyRight) }, '操作') - ) - ) - ), - React.createElement('tbody', {}, - paginatedList.length === 0 - ? React.createElement('tr', {}, React.createElement('td', { colSpan: listTab === 'in_progress' ? 19 : 25, style: Object.assign({}, styles.td, { textAlign: 'center', color: t.neutral6 }) }, '暂无数据')) - : paginatedList.map(function (row, rowIndex) { - var tr = row.transfer; - var line = row.line; - var canReceive = tr.approvalStatus === 'completed' && !tr.hasReceiveRecord; - var canEdit = ['pending_submit', 'rejected', 'withdrawn'].indexOf(tr.approvalStatus) >= 0; - var canWithdraw = tr.approvalStatus === 'approving'; - var checked = selectedRowIds.indexOf(row.rowId) >= 0; - var isEvenRow = rowIndex % 2 === 1; - var tdOneLine = Object.assign({}, styles.td, styles.tdNowrap); - return React.createElement('tr', { key: row.rowId, style: isEvenRow ? styles.trStripe : styles.trOdd }, - React.createElement('td', { style: tdOneLine }, React.createElement('input', { type: 'checkbox', checked: checked, onChange: function (e) { setSelectedRowIds(e.target.checked ? selectedRowIds.concat([row.rowId]) : selectedRowIds.filter(function (id) { return id !== row.rowId; })); } })), - listTab === 'in_progress' ? React.createElement(React.Fragment, {}, - React.createElement('td', { style: tdOneLine }, tr.transferDate), - React.createElement('td', { style: tdOneLine }, tr.departLabel || '-'), - React.createElement('td', { style: tdOneLine }, tr.operatorName), - React.createElement('td', { style: tdOneLine }, tr.transferLabel || '-'), - React.createElement('td', { style: tdOneLine }, getMethodLabel(tr.transferMethod)), - React.createElement('td', { style: tdOneLine }, tr.transferReason || '-'), - React.createElement('td', { style: tdOneLine }, line.plateNo || '-'), - React.createElement('td', { style: tdOneLine }, line.vehicleType || '-'), - React.createElement('td', { style: tdOneLine }, line.brand || '-'), - React.createElement('td', { style: tdOneLine }, line.model || '-'), - React.createElement('td', { style: carrierInfoTdStyle }, tr.carrierName || '-'), - React.createElement('td', { style: carrierInfoTdStyle }, tr.carrierContact || '-'), - React.createElement('td', { style: tdOneLine }, line.departMileage != null ? line.departMileage : '-'), - React.createElement('td', { style: tdOneLine }, formatH2(line.departH2, line.departH2Unit)), - React.createElement('td', { style: tdOneLine }, line.departElec != null ? line.departElec + ' kWh' : '-'), - React.createElement('td', { style: tdOneLine }, line.departParking || '-'), - React.createElement('td', { style: tdOneLine }, tr.createTime), - React.createElement('td', { style: Object.assign({}, tdOneLine, isEvenRow ? styles.tdStickyRightStripe : styles.tdStickyRight) }, - canReceive && React.createElement('a', { style: styles.actionLink, onClick: function (e) { - e.preventDefault(); - setViewRecord(tr); - setFormDataFromTransfer(tr); - setReceiveFormData({ - receiveDate: '', - receiverName: '张明', - lines: (tr.lines || []).map(function (l) { - return { - plateNo: l.plateNo, - vehicleType: l.vehicleType, - brand: l.brand, - model: l.model, - departParking: l.departParking, - departMileage: l.departMileage, - departH2: l.departH2, - departH2Unit: l.departH2Unit, - departElec: l.departElec, - receiveMileage: l.receiveMileage != null ? l.receiveMileage : '', - receiveH2: l.receiveH2 != null ? l.receiveH2 : '', - receiveElec: l.receiveElec != null ? l.receiveElec : '' - }; - }) - }); - setCurrentView('receive'); - } }, '接收记录'), - canEdit && React.createElement('a', { style: styles.actionLink, onClick: function (e) { e.preventDefault(); openEdit(tr); } }, '编辑'), - canWithdraw && React.createElement('a', { style: styles.actionLink, onClick: function (e) { e.preventDefault(); setWithdrawConfirmRecord(tr); } }, '撤回') - ) - ) : React.createElement(React.Fragment, {}, - React.createElement('td', { style: tdOneLine }, tr.transferDate), - React.createElement('td', { style: tdOneLine }, tr.departLabel || '-'), - React.createElement('td', { style: tdOneLine }, tr.operatorName), - React.createElement('td', { style: tdOneLine }, tr.receiveDate || '-'), - React.createElement('td', { style: tdOneLine }, tr.transferLabel || '-'), - React.createElement('td', { style: tdOneLine }, getMethodLabel(tr.transferMethod)), - React.createElement('td', { style: tdOneLine }, tr.transferReason || '-'), - React.createElement('td', { style: tdOneLine }, tr.receiverName || '-'), - React.createElement('td', { style: tdOneLine }, line.plateNo || '-'), - React.createElement('td', { style: tdOneLine }, line.vehicleType || '-'), - React.createElement('td', { style: tdOneLine }, line.brand || '-'), - React.createElement('td', { style: tdOneLine }, line.model || '-'), - React.createElement('td', { style: carrierInfoTdStyle }, tr.carrierName || '-'), - React.createElement('td', { style: carrierInfoTdStyle }, tr.carrierContact || '-'), - React.createElement('td', { style: tdOneLine }, line.departMileage != null ? line.departMileage : '-'), - React.createElement('td', { style: tdOneLine }, line.receiveMileage != null ? line.receiveMileage : '-'), - React.createElement('td', { style: tdOneLine }, formatH2(line.departH2, line.departH2Unit)), - React.createElement('td', { style: tdOneLine }, formatH2(line.receiveH2, line.departH2Unit)), - React.createElement('td', { style: tdOneLine }, line.departElec != null ? line.departElec + ' kWh' : '-'), - React.createElement('td', { style: tdOneLine }, line.receiveElec != null ? line.receiveElec + ' kWh' : '-'), - React.createElement('td', { style: tdOneLine }, line.departParking || '-'), - React.createElement('td', { style: tdOneLine }, line.receiveParking || '-'), - React.createElement('td', { style: tdOneLine }, tr.createTime), - React.createElement('td', { style: Object.assign({}, tdOneLine, isEvenRow ? styles.tdStickyRightStripe : styles.tdStickyRight) }, React.createElement('a', { style: styles.actionLink, onClick: function (e) { e.preventDefault(); setViewRecord(tr); setFormDataFromTransfer(tr); setCurrentView('view'); } }, '查看')) - ) - ); - }) - ) - ) - ), - totalItems > 0 && React.createElement('div', { style: styles.pagination }, - React.createElement('div', { style: styles.paginationLeft }, - React.createElement('span', {}, '共 ' + totalItems + ' 条'), - React.createElement('span', { style: { marginLeft: '16px' } }, '每页'), - React.createElement('select', { style: styles.paginationSelect, value: pageSize, onChange: function (e) { setPageSize(Number(e.target.value)); setCurrentPage(1); } }, - React.createElement('option', { value: 10 }, '10'), - React.createElement('option', { value: 20 }, '20'), - React.createElement('option', { value: 50 }, '50'), - React.createElement('option', { value: 100 }, '100') - ), - React.createElement('span', {}, '条') - ), - React.createElement('div', { style: styles.paginationRight }, - React.createElement('button', { style: Object.assign({}, styles.paginationBtn, currentPage <= 1 ? styles.paginationBtnDisabled : {}), disabled: currentPage <= 1, onClick: function () { if (currentPage > 1) setCurrentPage(currentPage - 1); } }, '上一页'), - React.createElement('span', { style: { margin: '0 8px' } }, currentPage + ' / ' + totalPages), - React.createElement('button', { style: Object.assign({}, styles.paginationBtn, currentPage >= totalPages ? styles.paginationBtnDisabled : {}), disabled: currentPage >= totalPages, onClick: function () { if (currentPage < totalPages) setCurrentPage(currentPage + 1); } }, '下一页') - ) - ) - ) - ), - - currentView === 'add' && React.createElement(React.Fragment, {}, - React.createElement('div', { style: { marginBottom: t.spacing16, fontSize: t.fontSize16, fontWeight: 600, color: t.neutral8 } }, '新增调拨'), - renderAddPage() - ), - currentView === 'edit' && React.createElement(React.Fragment, {}, - React.createElement('div', { style: { marginBottom: t.spacing16, fontSize: t.fontSize16, fontWeight: 600, color: t.neutral8 } }, '编辑调拨'), - renderEditPage() - ), - - withdrawConfirmRecord && React.createElement('div', { style: styles.modalMask, onClick: function () { setWithdrawConfirmRecord(null); } }, - React.createElement('div', { style: Object.assign({}, styles.modalBox, { minWidth: '360px' }), onClick: function (e) { e.stopPropagation(); } }, - React.createElement('div', { style: styles.modalTitle }, '确认撤回'), - React.createElement('p', { style: { margin: '0 0 16px', fontSize: t.fontSize14 } }, '是否确认撤回该调拨记录?'), - React.createElement('div', { style: styles.modalFooter }, - React.createElement('button', { style: Object.assign({}, styles.btn, styles.btnDefault), onClick: function () { setWithdrawConfirmRecord(null); } }, '取消'), - React.createElement('button', { style: Object.assign({}, styles.btn, styles.btnPrimary), onClick: function () { handleWithdraw(withdrawConfirmRecord); } }, '确认') - ) - ) - ), - - currentView === 'view' && viewRecord && renderViewPage(viewRecord), - - currentView === 'receive' && viewRecord && React.createElement('div', { style: styles.card }, - React.createElement('div', { style: styles.modalTitle }, '接收记录'), - renderFormContent(true, true), - React.createElement('div', { style: styles.formRow }, - React.createElement('label', { style: styles.formLabel }, '接收日期', React.createElement('span', { style: styles.formLabelReq }, '*')), - React.createElement('input', { style: styles.input, type: 'date', value: receiveFormData.receiveDate, onChange: function (e) { setReceiveFormData(Object.assign({}, receiveFormData, { receiveDate: e.target.value })); } }) - ), - React.createElement('div', { style: Object.assign({}, styles.formRow, { marginTop: t.spacing24 }) }, - React.createElement('div', { style: styles.tableWrap }, - React.createElement('table', { style: styles.table }, - React.createElement('thead', {}, - React.createElement('tr', {}, - React.createElement('th', { style: styles.th }, '车牌号'), - React.createElement('th', { style: styles.th }, '车辆类型'), - React.createElement('th', { style: styles.th }, '品牌'), - React.createElement('th', { style: styles.th }, '型号'), - React.createElement('th', { style: styles.th }, '出发停车场'), - React.createElement('th', { style: styles.th }, '出发里程(KM)'), - React.createElement('th', { style: styles.th }, '接收里程(KM)', React.createElement('span', { style: styles.formLabelReq }, '*')), - React.createElement('th', { style: styles.th }, '出发氢量'), - React.createElement('th', { style: styles.th }, '接收氢量', React.createElement('span', { style: styles.formLabelReq }, '*')), - React.createElement('th', { style: styles.th }, '出发电量'), - React.createElement('th', { style: styles.th }, '接收电量', React.createElement('span', { style: styles.formLabelReq }, '*')) - ) - ), - React.createElement('tbody', {}, - (receiveFormData.lines || []).map(function (line, idx) { - var isEvenRow = idx % 2 === 1; - return React.createElement('tr', { key: idx, style: isEvenRow ? styles.trStripe : styles.trOdd }, - React.createElement('td', { style: styles.td }, line.plateNo), - React.createElement('td', { style: styles.td }, line.vehicleType), - React.createElement('td', { style: styles.td }, line.brand), - React.createElement('td', { style: styles.td }, line.model), - React.createElement('td', { style: styles.td }, line.departParking), - React.createElement('td', { style: styles.td }, line.departMileage != null ? line.departMileage : '-'), - React.createElement('td', { style: styles.td }, React.createElement('input', { style: Object.assign({}, styles.input, { width: '80px' }), type: 'number', value: line.receiveMileage, onChange: function (e) { var next = receiveFormData.lines.slice(); next[idx] = Object.assign({}, next[idx], { receiveMileage: e.target.value }); setReceiveFormData(Object.assign({}, receiveFormData, { lines: next })); } })), - React.createElement('td', { style: styles.td }, formatH2(line.departH2, line.departH2Unit)), - React.createElement('td', { style: styles.td }, React.createElement(React.Fragment, {}, React.createElement('input', { style: Object.assign({}, styles.input, { width: '80px' }), value: line.receiveH2, onChange: function (e) { var next = receiveFormData.lines.slice(); next[idx] = Object.assign({}, next[idx], { receiveH2: e.target.value }); setReceiveFormData(Object.assign({}, receiveFormData, { lines: next })); } }), React.createElement('span', { style: { marginLeft: '4px' } }, (line.departH2Unit && !String(line.receiveH2 || '').match(/%|MPa|KG$/)) ? line.departH2Unit : ''))), - React.createElement('td', { style: styles.td }, (line.departElec != null ? line.departElec : '-') + ' kWh'), - React.createElement('td', { style: styles.td }, React.createElement('input', { style: Object.assign({}, styles.input, { width: '80px' }), type: 'number', value: line.receiveElec, onChange: function (e) { var next = receiveFormData.lines.slice(); next[idx] = Object.assign({}, next[idx], { receiveElec: e.target.value }); setReceiveFormData(Object.assign({}, receiveFormData, { lines: next })); } })) - ); - }) - ) - ) - ) - ), - React.createElement('div', { style: styles.modalFooter }, - React.createElement('button', { style: Object.assign({}, styles.btn, styles.btnDefault), onClick: function () { setViewRecord(null); setCurrentView('list'); } }, '取消'), - React.createElement('button', { style: Object.assign({}, styles.btn, styles.btnDefault), onClick: function () { - if (!receiveFormData.receiveDate) { setToastMessage('请选择接收日期'); setTimeout(function () { setToastMessage(''); }, 2000); return; } - var recLines = receiveFormData.lines || []; - for (var ri = 0; ri < recLines.length; ri++) { - var fl = recLines[ri]; - var rn = ri + 1; - if (fl.receiveMileage === '' || fl.receiveMileage === undefined || fl.receiveMileage === null) { setToastMessage('请填写第' + rn + '行接收里程(KM)'); setTimeout(function () { setToastMessage(''); }, 2000); return; } - if (fl.receiveH2 === '' || fl.receiveH2 === undefined || fl.receiveH2 === null) { setToastMessage('请填写第' + rn + '行接收氢量'); setTimeout(function () { setToastMessage(''); }, 2000); return; } - if (fl.receiveElec === '' || fl.receiveElec === undefined || fl.receiveElec === null) { setToastMessage('请填写第' + rn + '行接收电量'); setTimeout(function () { setToastMessage(''); }, 2000); return; } - } - var updatedLines = (viewRecord.lines || []).map(function (l, i) { - var formLine = (receiveFormData.lines || [])[i] || {}; - var next = {}; - for (var k in l) next[k] = l[k]; - next.receiveMileage = formLine.receiveMileage !== '' && formLine.receiveMileage !== undefined ? Number(formLine.receiveMileage) : null; - next.receiveH2 = formLine.receiveH2 !== '' && formLine.receiveH2 !== undefined ? formLine.receiveH2 : null; - next.receiveElec = formLine.receiveElec !== '' && formLine.receiveElec !== undefined ? Number(formLine.receiveElec) : null; - next.receiveParking = '抵达停车场'; - next.receiverName = receiveFormData.receiverName; - return next; - }); - var updated = {}; - for (var k in viewRecord) updated[k] = viewRecord[k]; - updated.hasReceiveRecord = true; - updated.receiveDate = receiveFormData.receiveDate; - updated.receiverId = 'u1'; - updated.receiverName = receiveFormData.receiverName; - updated.lines = updatedLines; - setMockTransferList(mockTransferList.map(function (r) { return r.id === viewRecord.id ? updated : r; })); - setViewRecord(updated); - setToastMessage('保存成功'); - setTimeout(function () { setToastMessage(''); }, 2000); - } }, '保存'), - React.createElement('button', { style: Object.assign({}, styles.btn, styles.btnPrimary), onClick: function () { - if (!receiveFormData.receiveDate) { setToastMessage('请选择接收日期'); setTimeout(function () { setToastMessage(''); }, 2000); return; } - var recLines2 = receiveFormData.lines || []; - for (var ri2 = 0; ri2 < recLines2.length; ri2++) { - var fl2 = recLines2[ri2]; - var rn2 = ri2 + 1; - if (fl2.receiveMileage === '' || fl2.receiveMileage === undefined || fl2.receiveMileage === null) { setToastMessage('请填写第' + rn2 + '行接收里程(KM)'); setTimeout(function () { setToastMessage(''); }, 2000); return; } - if (fl2.receiveH2 === '' || fl2.receiveH2 === undefined || fl2.receiveH2 === null) { setToastMessage('请填写第' + rn2 + '行接收氢量'); setTimeout(function () { setToastMessage(''); }, 2000); return; } - if (fl2.receiveElec === '' || fl2.receiveElec === undefined || fl2.receiveElec === null) { setToastMessage('请填写第' + rn2 + '行接收电量'); setTimeout(function () { setToastMessage(''); }, 2000); return; } - } - var updatedLines = (viewRecord.lines || []).map(function (l, i) { - var formLine = (receiveFormData.lines || [])[i] || {}; - var next = {}; - for (var k in l) next[k] = l[k]; - next.receiveMileage = formLine.receiveMileage !== '' && formLine.receiveMileage !== undefined ? Number(formLine.receiveMileage) : null; - next.receiveH2 = formLine.receiveH2 !== '' && formLine.receiveH2 !== undefined ? formLine.receiveH2 : null; - next.receiveElec = formLine.receiveElec !== '' && formLine.receiveElec !== undefined ? Number(formLine.receiveElec) : null; - next.receiveParking = '抵达停车场'; - next.receiverName = receiveFormData.receiverName; - return next; - }); - var updated = {}; - for (var k in viewRecord) updated[k] = viewRecord[k]; - updated.hasReceiveRecord = true; - updated.receiveDate = receiveFormData.receiveDate; - updated.receiverId = 'u1'; - updated.receiverName = receiveFormData.receiverName; - updated.lines = updatedLines; - setMockTransferList(mockTransferList.map(function (r) { return r.id === viewRecord.id ? updated : r; })); - setToastMessage('保存成功'); - setTimeout(function () { setToastMessage(''); }, 2000); - setViewRecord(null); - setCurrentView('list'); - } }, '提交') - ) - ), - - showRequirementModal && React.createElement('div', { - style: styles.modalMask, - onClick: function () { setShowRequirementModal(false); } - }, React.createElement('div', { - style: Object.assign({}, styles.modalBox, { minWidth: '640px', maxWidth: '800px' }), - onClick: function (e) { e.stopPropagation(); } - }, - React.createElement('button', { - style: styles.modalCloseBtn, - onClick: function () { setShowRequirementModal(false); }, - title: '关闭' - }, '×'), - React.createElement('div', { style: { paddingRight: '32px', paddingBottom: t.spacing24, lineHeight: '1.65', maxHeight: '85vh', overflowY: 'auto', fontSize: t.fontSize14, color: t.neutral7 } }, - React.createElement('div', { style: Object.assign({}, styles.requirementSection, { marginTop: 0 }) }, - React.createElement('div', { style: styles.requirementSectionTitle }, '面包屑'), - React.createElement('div', { style: styles.requirementItem }, '运维管理-车辆业务-调拨管理') - ), - React.createElement('div', { style: styles.requirementSection }, - React.createElement('div', { style: styles.requirementSectionTitle }, '筛选'), - React.createElement('div', { style: styles.requirementItem }, '1.调拨日期:日期选择器,支持选择开始-结束时间'), - React.createElement('div', { style: styles.requirementItem }, '2.调拨人:选择器,支持从输入框输入内容模糊搜索'), - React.createElement('div', { style: styles.requirementItem }, '3.接收日期:日期选择器,支持选择开始-结束时间'), - React.createElement('div', { style: styles.requirementItem }, '4.接收人:选择器,支持从输入框输入内容模糊搜索'), - React.createElement('div', { style: styles.requirementItem }, '5.车牌号:选择器,支持从输入框输入内容模糊搜索'), - React.createElement('div', { style: styles.requirementItem }, '6.出发区域:级联选择,支持省市二级级联'), - React.createElement('div', { style: styles.requirementItem }, '7.调拨区域:级联选择,支持省市二级级联'), - React.createElement('div', { style: styles.requirementItem }, '8.调拨方式:选择器,状态分为:第三方运输、司机驾驶'), - React.createElement('div', { style: styles.requirementItem }, '9.审批状态:选择器,状态分为:待提交、待审批、审批中、审批完成、审批驳回、撤回'), - React.createElement('div', { style: Object.assign({}, styles.requirementItem, { marginTop: t.spacing8, marginBottom: t.spacing4 }) }, '审批状态说明(该说明只做需求说明,AI无需分析):'), - React.createElement('div', { style: Object.assign({}, styles.requirementSubItem, { paddingLeft: t.spacing24 }) }, - React.createElement('div', { style: { marginBottom: '2px' } }, 'a.待提交:新增完成后选择保存,但未提交审核;'), - React.createElement('div', { style: { marginBottom: '2px' } }, 'b.待审批:已提交审核,但未通过第一个流程节点审核;'), - React.createElement('div', { style: { marginBottom: '2px' } }, 'c.审批中:已提交审核,至少完成1个以上节点审核,但未完成最终节点审核;'), - React.createElement('div', { style: { marginBottom: '2px' } }, 'd.审批完成:已提交审核,并完成最终节点审核;'), - React.createElement('div', { style: { marginBottom: '2px' } }, 'e.审批驳回:已提交审核,但任意节点审核未通过,审批驳回的记录支持修改后重新提交审核;'), - React.createElement('div', {}, 'f.撤回:已提交审核,但完成最终审核前主动撤回,撤回的记录支持修改后重新提交审核;') - ) - ), - React.createElement('div', { style: styles.requirementSection }, - React.createElement('div', { style: styles.requirementSectionTitle }, '列表'), - React.createElement('div', { style: styles.requirementItem }, '列表由两个tab页组成,分别为:进行中、历史记录;'), - React.createElement('div', { style: Object.assign({}, styles.requirementItem, { marginTop: t.spacing12, marginBottom: t.spacing4 }) }, 'a.进行中tab:显示审批状态为待提交、待审批、审批完成、审核驳回、撤回的记录以及未补充接收记录的数据:'), - React.createElement('div', { style: Object.assign({}, styles.requirementSubItem, { paddingLeft: t.spacing24, marginBottom: t.spacing8 }) }, '列表上方右侧为新增、导出(支持多选)按钮,下方为分页功能,支持选择单页显示多少条数据记录,显示字段按以下顺序'), - [ '1.调拨日期:新建调拨记录时填写的调拨日期,格式为YYYY-MM-DD', '2.出发区域:显示该车辆出发时区域', '3.调拨人:新建调拨记录的操作人', '4.接收区域:新建调拨记录时填写的接收区域', '5.调拨方式:新建调拨记录时选择的状态', '6.调拨原因:新建调拨记录时输入的调拨原因', '7.运输方名称:新建调拨记录时输入的运输方名称', '8.运输方联系方式:新建调拨记录时输入的运输方联系方式', '9.车牌号:新建调拨记录时填写的车牌号,每个车牌号形成一条单独记录;', '10.车辆类型:根据车牌号自动反写车辆类型', '11.品牌:根据车牌号自动反写品牌', '12.型号:根据车牌号自动反写型号', '13.运输方信息:新建调拨记录时手动输入的运输方名称及联系方式,在列表中显示为两行,上方为运输方名称,下方为联系方式', '14.出发里程(KM):新建调拨记录时填写的出发里程', '15.出发氢量:新建调拨记录时填写的出发氢量,单位根据车辆型号对应氢气计量单位自动匹配,分为%、MPa、KG,分别给出一些样例', '16.出发电量:新建调拨记录时填写的出发电量,单位为kWh', '17.出发停车场:新建调拨记录时该车辆出发时的停车场', '18.创建日期:显示该记录创建日期', '19.操作:接收记录、编辑、撤回;操作记录说明如下' ].map(function (txt, i) { return React.createElement('div', { key: i, style: Object.assign({}, styles.requirementSubItem, { paddingLeft: t.spacing24, marginBottom: '2px' }) }, txt); }), - React.createElement('div', { style: Object.assign({}, styles.requirementSubItem, { paddingLeft: t.spacing24 }) }, - React.createElement('div', { style: { marginBottom: '2px' } }, 'a.接收记录:点击后与新增页样式和字段相同,但只有接收日期、抵达里程(KM)、抵达氢量、抵达电量、接收停车场等字段可以操作,仅审核状态为审核完成时显示该功能'), - React.createElement('div', { style: { marginBottom: '2px' } }, 'b.编辑:审核状态为待提交、审批驳回、撤回的数据可进行编辑,其他审核状态不显示编辑,点击编辑后页面与新增页样式相同所有字段可编辑;'), - React.createElement('div', {}, 'c.撤回:点击弹出框进行二次确认,点击弹出框确认按钮toast提示撤回成功,点击弹出框取消按钮,关闭弹出框;仅在审批状态为审批中可撤回,如审批状态为已完成则不显示撤回;') - ), - React.createElement('div', { style: Object.assign({}, styles.requirementItem, { marginTop: t.spacing16, marginBottom: t.spacing4 }) }, 'b.历史记录tab:'), - React.createElement('div', { style: Object.assign({}, styles.requirementSubItem, { paddingLeft: t.spacing24, marginBottom: t.spacing8 }) }, '显示审批状态为审核完成以及完成补充接收记录的数据:列表上方右侧为导出(支持多选)按钮,下方为分页功能,支持选择单页显示多少条数据记录'), - [ '1.调拨日期:新建调拨记录时填写的调拨日期,格式为YYYY-MM-DD', '2.出发区域:显示该车辆出发时区域', '3.调拨人:新建调拨记录的操作人', '4.接收日期:补充接收记录时填写的接收日期,格式为YYYY-MM-DD', '5.接收区域:新建调拨记录时填写的接收区域', '6.调拨方式:新建调拨记录时选择的状态', '7.调拨原因:新建调拨记录时输入的调拨原因', '8.运输方名称:新建调拨记录时输入的运输方名称', '9.运输方联系方式:新建调拨记录时输入的运输方联系方式', '10.接收人:补充接收记录时的操作人', '11.车牌号:新建调拨记录时填写的车牌号,每个车牌号形成一条单独记录;', '12.车辆类型:根据车牌号自动反写车辆类型', '13.品牌:根据车牌号自动反写品牌', '14.型号:根据车牌号自动反写型号', '15.运输方信息:新建调拨记录时手动输入的运输方名称及联系方式,在列表中显示为两行,上方为运输方名称,下方为联系方式', '16.出发里程(KM):新建调拨记录时填写的出发里程', '17.接收里程(KM):补充接收记录时填写的抵达里程', '18.出发氢量:新建调拨记录时填写的出发氢量,单位根据车辆型号对应氢气计量单位自动匹配,分为%、MPa、KG,分别给出一些样例', '19.接收氢量:补充接收记录时填写的抵达氢量,单位根据车辆型号对应氢气计量单位自动匹配,分为%、MPa、KG,分别给出一些样例', '20.出发电量:新建调拨记录时填写的出发电量,单位为kWh', '21.接收电量:补充接收记录时填写的抵达电量,单位为kWh', '22.出发停车场:新建调拨记录时该车辆出发时的停车场', '23.接收停车场:补充接收记录时该车辆抵达场', '24.创建日期:显示该记录创建日期', '25.操作:查看;操作记录说明如下' ].map(function (txt, i) { return React.createElement('div', { key: i, style: Object.assign({}, styles.requirementSubItem, { paddingLeft: t.spacing24, marginBottom: '2px' }) }, txt); }), - React.createElement('div', { style: Object.assign({}, styles.requirementSubItem, { paddingLeft: t.spacing24 }) }, 'a.查看:与接收记录页所有字段和布局相同,但所有字段控件均为禁用状态;') - ), - React.createElement('div', { style: styles.requirementSection }, - React.createElement('div', { style: styles.requirementSectionTitle }, '新增'), - React.createElement('div', { style: styles.requirementItem }, '点击新增按钮以打开新页面的方式进行操作。'), - React.createElement('div', { style: styles.requirementItem }, '页面分为上下两部分组成,上方以3列布局,显示以下字段:'), - [ '1.调拨日期:必填项,日期选择器,格式为YYYY-MM-DD', '2.出发区域:必填项,级联选择器,显示格式为:省-市', '3.接受区域:必填项,级联选择器,显示格式为:省-市', '4.调拨方式:必填项,按钮式选择器,选项分别为第三方运输、司机驾驶', '5.调拨原因:必填项,文本域', '6.运输方名称:必填项,输入框,输入框提示信息为请输入运输方名称或司机姓名', '7.运输方联系方式:必填项,输入框,输入框提示信息为请输入运输方联系方式' ].map(function (txt, i) { return React.createElement('div', { key: i, style: Object.assign({}, styles.requirementSubItem, { paddingLeft: t.spacing24 }) }, txt); }), - React.createElement('div', { style: Object.assign({}, styles.requirementItem, { marginTop: t.spacing8 }) }, '页面下方以可编辑列表方式显示以下字段,默认显示一行数据,列表下方为新增一行按钮,点击新增一行数据'), - [ '1.车牌号:选择器,输入框支持模糊搜索,只能选择状态为库存的车辆', '2.车辆类型:直接显示内容,根据车牌号自动反写车辆类型', '3.品牌:直接显示内容,根据车牌号自动反写品牌', '4.型号:直接显示内容,根据车牌号自动反写型号', '5.出发停车场:直接显示内容,根据车牌号当前停车场自动反写', '6.出发里程(KM):输入框', '7.出发氢量:输入框,后缀为单位,单位根据该车辆型号参数内氢系统仪表盘单位字段自动反写单位,如未设置则不显示后缀单位', '8.出发电量:输入框,后缀为单位,单位为kWh', '9.操作:删除,点击后删除该行数据' ].map(function (txt, i) { return React.createElement('div', { key: i, style: Object.assign({}, styles.requirementSubItem, { paddingLeft: t.spacing24 }) }, txt); }), - React.createElement('div', { style: Object.assign({}, styles.requirementItem, { marginTop: t.spacing8 }) }, '页面最下方为提交审核、保存、取消按钮'), - React.createElement('div', { style: Object.assign({}, styles.requirementSubItem, { paddingLeft: t.spacing24 }) }, '点击提交审核提交并转入调拨审核流程;点击保存,保存数据但不提交审核;点击取消,跳转回调拨列表页') - ), - React.createElement('div', { style: styles.requirementSection }, - React.createElement('div', { style: styles.requirementSectionTitle }, '接收记录'), - React.createElement('div', { style: styles.requirementItem }, '上方显示新增页所有字段和布局,但所有组件为禁用状态,除此外新增一个可编辑字段'), - React.createElement('div', { style: Object.assign({}, styles.requirementSubItem, { paddingLeft: t.spacing24 }) }, '1.接收日期:必填项,日期选择器,格式为YYYY-MM-DD'), - React.createElement('div', { style: Object.assign({}, styles.requirementItem, { marginTop: t.spacing8 }) }, '页面下方以可编辑列表方式显示以下字段'), - [ '2.车牌号:文字方式显示新增时记录的车牌号', '3.车辆类型:文字方式显示新增时记录的车牌号对应车辆类型', '4.品牌:文字方式显示新增时记录的车牌号对应品牌', '5.型号:文字方式显示新增时记录的车牌号对应型号', '6.出发停车场:文字方式显示新增时记录的车牌号对应停车场', '7.出发里程(KM):文字方式显示新增时记录的出发里程', '8.接收里程(KM):输入框', '9.出发氢量:文字显示新增时记录的车牌号对应出发氢量,并显示单位', '10.接收氢量:输入框,后缀为单位,单位根据车辆型号对应氢气计量单位自动匹配,分为%、MPa、KG', '11.出发电量:文字显示新增时记录的车牌号对应出发电量,单位为kWh', '12.接收电量:输入框,后缀为单位,单位为kWh' ].map(function (txt, i) { return React.createElement('div', { key: i, style: Object.assign({}, styles.requirementSubItem, { paddingLeft: t.spacing24 }) }, txt); }) - ), - React.createElement('div', { style: styles.requirementSection }, - React.createElement('div', { style: styles.requirementSectionTitle }, '导出'), - React.createElement('div', { style: styles.requirementItem }, '支持选择器选择对应数据进行导出') - ) - ) - )), - - toastMessage && React.createElement('div', { style: styles.toast }, toastMessage) - ) - ); -}; - -if (typeof window !== 'undefined') { - window.Component = Component; - function mount() { - var rootEl = document.getElementById('root'); - if (rootEl && window.ReactDOM && window.React) { - var root = ReactDOM.createRoot(rootEl); - root.render(React.createElement(Component)); - } - } - if (document.readyState === 'loading') { - document.addEventListener('DOMContentLoaded', mount); - } else { - setTimeout(mount, 0); - } -} +// 【重要】必须使用 const Component 作为组件变量名 +// 运维管理 - 车辆业务 - 调拨管理(列表页) + +const Component = function () { + var useState = React.useState; + var useMemo = React.useMemo; + var useCallback = React.useCallback; + + var antd = window.antd; + var App = antd.App; + var Breadcrumb = antd.Breadcrumb; + var Card = antd.Card; + var Button = antd.Button; + var Table = antd.Table; + var Tabs = antd.Tabs; + var Select = antd.Select; + var DatePicker = antd.DatePicker; + var Cascader = antd.Cascader; + var message = antd.message; + var Modal = antd.Modal; + + var RangePicker = DatePicker.RangePicker; + + function filterOption(input, option) { + var label = (option && (option.label || option.children)) || ''; + return String(label).toLowerCase().indexOf(String(input || '').toLowerCase()) >= 0; + } + + function fmtYMDHM(v) { + if (v === null || v === undefined) return '-'; + var s = String(v).trim(); + if (!s) return '-'; + if (/^\\d{4}-\\d{2}-\\d{2}\\s+\\d{2}:\\d{2}/.test(s)) return s.slice(0, 16); + if (/^\\d{4}-\\d{2}-\\d{2}$/.test(s)) return s + ' 00:00'; + try { + var d = new Date(s.replace(/-/g, '/')); + if (isNaN(d.getTime())) return s; + var p2 = function (n) { return n < 10 ? '0' + n : '' + n; }; + return d.getFullYear() + '-' + p2(d.getMonth() + 1) + '-' + p2(d.getDate()) + ' ' + p2(d.getHours()) + ':' + p2(d.getMinutes()); + } catch (e) { + return s; + } + } + + var layoutStyle = { padding: '16px 24px', background: '#f5f5f5', minHeight: '100vh' }; + var filterLabelStyle = { marginBottom: 6, fontSize: 14, color: 'rgba(0,0,0,0.65)' }; + var filterItemStyle = { marginBottom: 12 }; + var filterControlStyle = { width: '100%' }; + var tableSingleLineStyle = '.transfer-list-table .ant-table-thead th,.transfer-list-table .ant-table-tbody td{white-space:nowrap;}'; + + var regionOptions = useMemo(function () { + return [ + { value: 'zhejiang', label: '浙江省', children: [{ value: 'hangzhou', label: '杭州市' }, { value: 'ningbo', label: '宁波市' }, { value: 'jiaxing', label: '嘉兴市' }] }, + { value: 'shanghai', label: '上海市', children: [{ value: 'shanghai', label: '上海市' }] }, + { value: 'guangdong', label: '广东省', children: [{ value: 'guangzhou', label: '广州市' }, { value: 'shenzhen', label: '深圳市' }, { value: 'dongguan', label: '东莞市' }] } + ]; + }, []); + + var userOptions = useMemo(function () { + return [ + { value: '张明', label: '张明' }, + { value: '王芳', label: '王芳' }, + { value: '李华', label: '李华' }, + { value: '赵强', label: '赵强' }, + { value: '陈静', label: '陈静' } + ]; + }, []); + + var plateOptions = useMemo(function () { + return [ + { value: '粤A12345', label: '粤A12345' }, + { value: '粤B11111', label: '粤B11111' }, + { value: '浙A11111', label: '浙A11111' }, + { value: '浙B22222', label: '浙B22222' }, + { value: '沪A30003', label: '沪A30003' } + ]; + }, []); + + var methodOptions = useMemo(function () { + return [ + { value: '第三方运输', label: '第三方运输' }, + { value: '司机驾驶', label: '司机驾驶' } + ]; + }, []); + + var approvalOptions = useMemo(function () { + return [ + { value: '待提交', label: '待提交' }, + { value: '审批中', label: '审批中' }, + { value: '审批完成', label: '审批完成' }, + { value: '审批驳回', label: '审批驳回' }, + { value: '撤回', label: '撤回' } + ]; + }, []); + + var filterExpandedState = useState(false); + var filterExpanded = filterExpandedState[0]; + var setFilterExpanded = filterExpandedState[1]; + + var draftState = useState({ + transferDateRange: null, + transferPerson: undefined, + receiveDateRange: null, + receivePerson: undefined, + plateNo: undefined, + departRegion: undefined, + transferRegion: undefined, + method: undefined, + approvalStatus: undefined + }); + var draft = draftState[0]; + var setDraft = draftState[1]; + + var appliedState = useState({ + transferDateRange: null, + transferPerson: undefined, + receiveDateRange: null, + receivePerson: undefined, + plateNo: undefined, + departRegion: undefined, + transferRegion: undefined, + method: undefined, + approvalStatus: undefined + }); + var applied = appliedState[0]; + var setApplied = appliedState[1]; + + var tabState = useState('in_progress'); + var tab = tabState[0]; + var setTab = tabState[1]; + + var pageState = useState(1); + var page = pageState[0]; + var setPage = pageState[1]; + var pageSizeState = useState(20); + var pageSize = pageSizeState[0]; + var setPageSize = pageSizeState[1]; + + var requirementModalState = useState(false); + var requirementModalOpen = requirementModalState[0]; + var setRequirementModalOpen = requirementModalState[1]; + + var requirementDocContent = [ + '一个「数字化资产ONEOS运管平台」中的「调拨管理」模块', + '#面包屑:运维管理-车辆业务-调拨管理', + '1.筛选:', + '1.1.调拨日期:日期选择器,支持单输入框双日历进行开始-结束时间搜索;', + '1.2.调拨人:选择器,支持输入框输入内容模糊搜索下拉选择对应调拨人,调拨人来自用户表;', + '1.3.接收日期:日期选择器,支持单输入框双日历进行开始-结束时间搜索;', + '1.4.接收人:选择器,支持输入框输入内容模糊搜索下拉选择对应接收人,接收人来自用户表;', + '1.5.车牌号:选择器,支持输入框输入内容模糊搜索下拉选择车牌号;', + '1.6.出发区域:级联地区选择器,省-市2级;', + '1.7.调拨区域:级联地区选择器,省-市2级;', + '1.8.调拨方式:选择器,选项为:第三方运输、司机驾驶;', + '1.9.审批状态:选择器,选项为:待提交、审批中、审批完成、审批驳回、撤回;', + '', + '2.列表:分为进行中、历史记录2个tab;tab最右侧为新增、导出;', + '2.1.进行中:', + '2.1.1.调拨日期:显示调拨日期,格式为:YYYY-MM-DD HH:MM;', + '2.1.2.出发区域:显示出发省-市,根据车辆出发时停车场区域获取;', + '2.1.3.调拨人:显示调拨人姓名;', + '2.1.4.接收区域:显示接受省-市;', + '2.1.5.接收人:显示接收人姓名;', + '2.1.6.审批状态:待提交、审批中、审批完成、驳回、撤回;', + '2.1.7.调拨方式:显示调拨方式,分为第三方运输、司机驾驶;', + '2.1.8.调拨原因:显示调拨原因;', + '2.1.9.车牌号:显示调拨车牌号;', + '2.1.10.车辆类型:显示调拨车辆对应类型;', + '2.1.11.品牌:显示调拨车辆对应品牌;', + '2.1.12.型号:显示调拨车辆对应型号;', + '2.1.13.运输方名称:显示调拨车辆对应运输方信息;', + '2.1.14.出发里程(km):显示调拨车辆对应出发里程;', + '2.1.15.出发氢量:显示调拨车辆对应出发氢量,带单位(单位根据该型号型号参数下仪表盘单位)', + '2.1.16.出发电量(kWh):显示调拨车辆对应出发电量;', + '2.1.17.出发停车场:显示调拨车辆出发停车场名称;', + '2.1.18.创建日期:显示调拨申请创建日期,格式为:YYYY-MM-DD HH:MM;', + '2.1.19.操作:查看、编辑、接收记录、撤回;', + ' 2.1.19.1.查看:点击跳转调拨管理-查看页;', + ' 2.1.19.2.编辑:点击跳转调拨管理-编辑页,只有待提交、审批驳回、撤回状态才显示编辑;', + ' 2.1.19.3.接收记录:点击跳转调拨管理-接收记录页,只有审批状态为审批完成时才显示接收记录;', + ' 2.1.19.4.撤回:点击进行二次确认,确认后审批状态修改为撤回,只有审批状态为审批中时才显示撤回;', + '', + '2.2.历史记录:', + '2.2.1.调拨日期:显示调拨日期,格式为:YYYY-MM-DD HH:MM;', + '2.2.2.出发区域:显示出发省-市,根据车辆出发时停车场区域获取;', + '2.2.3.调拨人:显示调拨人姓名;', + '2.2.4.接收日期:显示接收日期,格式为:YYYY-MM-DD HH:MM;', + '2.2.5.接收区域:显示接受省-市;', + '2.2.6.接收人:显示接收人姓名;', + '2.2.7.审批状态:审核完成;', + '2.2.8.调拨方式:显示调拨方式,分为第三方运输、司机驾驶;', + '2.2.9.调拨原因:显示调拨原因;', + '2.2.10.车牌号:显示调拨车牌号;', + '2.2.11.车辆类型:显示调拨车辆对应类型;', + '2.2.12.品牌:显示调拨车辆对应品牌;', + '2.2.13.型号:显示调拨车辆对应型号;', + '2.2.14.运输方名称:显示调拨车辆对应运输方信息;', + '2.2.15.出发里程(km):显示调拨车辆对应出发里程;', + '2.2.16.接收里程(km):显示调拨车辆对应接收里程;', + '2.2.17.出发氢量:显示调拨车辆对应出发氢量,带单位(单位根据该型号型号参数下仪表盘单位);', + '2.2.18.接收氢量:显示调拨车辆对应接收氢量,带单位(单位根据该型号型号参数下仪表盘单位);', + '2.2.19.出发电量(kWh):显示调拨车辆对应出发电量;', + '2.2.20.接收电量(kWh):显示调拨车辆对应接收电量;', + '2.2.21.出发停车场:显示调拨车辆出发停车场名称;', + '2.2.22.创建日期:显示调拨申请创建日期,格式为:YYYY-MM-DD HH:MM;', + '2.2.23.操作:查看;', + ' 2.1.17.1.查看:点击跳转调拨管理-查看页;' + ].join('\n'); + + var listInProgressState = useState(function () { + return [ + { + id: 'tp1', + transferDate: '2026-02-20 09:30', + departRegionText: '广东省-广州市', + transferPerson: '张明', + receiveRegionText: '浙江省-嘉兴市', + receivePerson: '王芳', + approvalStatus: '待提交', + method: '第三方运输', + reason: '场站资源调整', + plateNo: '粤A12345', + vehicleType: '厢式货车', + brand: '东风', + model: 'DFH1180', + carrierName: '顺丰同城运输', + departMileageKm: '15230.12', + departHydrogen: '28.30', + h2Unit: 'MPa', + departElectricKwh: '68.40', + departParking: '天河智慧停车场', + createDate: '2026-02-20 08:10' + }, + { + id: 'tp2', + transferDate: '2026-02-22 14:10', + departRegionText: '浙江省-杭州市', + transferPerson: '李华', + receiveRegionText: '上海市-上海市', + receivePerson: '赵强', + approvalStatus: '审批完成', + method: '司机驾驶', + reason: '项目调度需要', + plateNo: '浙A11111', + vehicleType: 'SUV', + brand: '小鹏', + model: 'P7', + carrierName: '-', + departMileageKm: '12010.00', + departHydrogen: '60.00', + h2Unit: '%', + departElectricKwh: '55.20', + departParking: '西湖景区停车场', + createDate: '2026-02-22 12:40' + }, + { + id: 'tp3', + transferDate: '2026-02-24 11:05', + departRegionText: '广东省-深圳市', + transferPerson: '王芳', + receiveRegionText: '浙江省-宁波市', + receivePerson: '陈静', + approvalStatus: '审批完成', + method: '第三方运输', + reason: '维修站资源调整', + plateNo: '粤B11111', + vehicleType: '轿车', + brand: '比亚迪', + model: '汉', + carrierName: '德邦物流', + departMileageKm: '8020.50', + departHydrogen: '55.00', + h2Unit: '%', + departElectricKwh: '62.10', + departParking: '南山科技园停车场', + createDate: '2026-02-24 10:20' + }, + { + id: 'tp4', + transferDate: '2026-02-25 16:40', + departRegionText: '浙江省-嘉兴市', + transferPerson: '赵强', + receiveRegionText: '上海市-上海市', + receivePerson: '李华', + approvalStatus: '待提交', + method: '司机驾驶', + reason: '项目调度需要', + plateNo: '浙B22222', + vehicleType: '轿车', + brand: '蔚来', + model: 'ET5', + carrierName: '-', + departMileageKm: '15010.00', + departHydrogen: '22.10', + h2Unit: 'MPa', + departElectricKwh: '58.00', + departParking: '宁波江北停车场', + createDate: '2026-02-25 15:55' + }, + { + id: 'tp5', + transferDate: '2026-02-26 09:15', + departRegionText: '上海市-上海市', + transferPerson: '陈静', + receiveRegionText: '广东省-广州市', + receivePerson: '张明', + approvalStatus: '审批驳回', + method: '第三方运输', + reason: '车辆调拨申请驳回样例', + plateNo: '沪A30003', + vehicleType: '厢式货车', + brand: '福田', + model: 'BJ1180', + carrierName: '顺丰同城运输', + departMileageKm: '9800.00', + departHydrogen: '26.00', + h2Unit: 'MPa', + departElectricKwh: '69.00', + departParking: '张江园区停车场', + createDate: '2026-02-26 08:30' + }, + { + id: 'tp6', + transferDate: '2026-02-27 13:30', + departRegionText: '浙江省-杭州市', + transferPerson: '张明', + receiveRegionText: '浙江省-嘉兴市', + receivePerson: '王芳', + approvalStatus: '撤回', + method: '司机驾驶', + reason: '计划变更,撤回申请', + plateNo: '浙A11111', + vehicleType: 'SUV', + brand: '小鹏', + model: 'P7', + carrierName: '-', + departMileageKm: '12100.20', + departHydrogen: '58.00', + h2Unit: '%', + departElectricKwh: '54.80', + departParking: '西湖景区停车场', + createDate: '2026-02-27 12:45' + }, + { + id: 'tp7', + transferDate: '2026-02-28 08:50', + departRegionText: '广东省-东莞市', + transferPerson: '李华', + receiveRegionText: '广东省-深圳市', + receivePerson: '赵强', + approvalStatus: '审批中', + method: '第三方运输', + reason: '跨区域调拨', + plateNo: '粤A12345', + vehicleType: '厢式货车', + brand: '东风', + model: 'DFH1180', + carrierName: '中外运', + departMileageKm: '15310.00', + departHydrogen: '27.50', + h2Unit: 'MPa', + departElectricKwh: '67.20', + departParking: '松山湖停车场', + createDate: '2026-02-28 08:05' + }, + { + id: 'tp8', + transferDate: '2026-03-01 10:10', + departRegionText: '浙江省-宁波市', + transferPerson: '王芳', + receiveRegionText: '上海市-上海市', + receivePerson: '陈静', + approvalStatus: '待提交', + method: '司机驾驶', + reason: '项目新增点位支持', + plateNo: '浙B22222', + vehicleType: '轿车', + brand: '蔚来', + model: 'ET5', + carrierName: '-', + departMileageKm: '15120.00', + departHydrogen: '21.80', + h2Unit: 'MPa', + departElectricKwh: '57.50', + departParking: '宁波江北停车场', + createDate: '2026-03-01 09:30' + }, + { + id: 'tp9', + transferDate: '2026-03-02 15:25', + departRegionText: '上海市-上海市', + transferPerson: '赵强', + receiveRegionText: '浙江省-杭州市', + receivePerson: '李华', + approvalStatus: '审批中', + method: '第三方运输', + reason: '场站容量调整', + plateNo: '沪A30003', + vehicleType: '厢式货车', + brand: '福田', + model: 'BJ1180', + carrierName: '德邦物流', + departMileageKm: '9850.00', + departHydrogen: '24.20', + h2Unit: 'MPa', + departElectricKwh: '68.30', + departParking: '张江园区停车场', + createDate: '2026-03-02 14:40' + }, + { + id: 'tp10', + transferDate: '2026-03-03 09:05', + departRegionText: '浙江省-嘉兴市', + transferPerson: '陈静', + receiveRegionText: '广东省-广州市', + receivePerson: '张明', + approvalStatus: '待提交', + method: '第三方运输', + reason: '车辆调拨支持新项目', + plateNo: '浙A11111', + vehicleType: 'SUV', + brand: '小鹏', + model: 'P7', + carrierName: '顺丰同城运输', + departMileageKm: '12220.00', + departHydrogen: '56.00', + h2Unit: '%', + departElectricKwh: '53.90', + departParking: '嘉兴南湖停车场', + createDate: '2026-03-03 08:20' + } + ]; + }); + var listInProgress = listInProgressState[0]; + var setListInProgress = listInProgressState[1]; + + var listHistory = useMemo(function () { + return [ + { + id: 'th1', + transferDate: '2026-01-10 10:00', + departRegionText: '上海市-上海市', + transferPerson: '张明', + receiveDate: '2026-01-12 18:20', + receiveRegionText: '广东省-深圳市', + receivePerson: '陈静', + approvalStatus: '审批完成', + method: '第三方运输', + reason: '场站资源调整', + plateNo: '沪A30003', + vehicleType: '厢式货车', + brand: '福田', + model: 'BJ1180', + carrierName: '德邦物流', + departMileageKm: '9800.00', + receiveMileageKm: '10120.00', + departHydrogen: '25.50', + receiveHydrogen: '22.10', + h2Unit: 'MPa', + departElectricKwh: '70.00', + receiveElectricKwh: '62.30', + departParking: '张江园区停车场', + createDate: '2026-01-09 16:45' + }, + { + id: 'th2', + transferDate: '2026-01-15 09:30', + departRegionText: '广东省-广州市', + transferPerson: '王芳', + receiveDate: '2026-01-17 14:10', + receiveRegionText: '浙江省-杭州市', + receivePerson: '赵强', + approvalStatus: '审批完成', + method: '司机驾驶', + reason: '项目调度需要', + plateNo: '粤A12345', + vehicleType: '厢式货车', + brand: '东风', + model: 'DFH1180', + carrierName: '-', + departMileageKm: '14500.00', + receiveMileageKm: '14920.00', + departHydrogen: '30.00', + receiveHydrogen: '27.10', + h2Unit: 'MPa', + departElectricKwh: '66.00', + receiveElectricKwh: '59.20', + departParking: '天河智慧停车场', + createDate: '2026-01-14 18:00' + }, + { + id: 'th3', + transferDate: '2026-01-20 16:05', + departRegionText: '浙江省-宁波市', + transferPerson: '李华', + receiveDate: '2026-01-22 10:30', + receiveRegionText: '广东省-深圳市', + receivePerson: '陈静', + approvalStatus: '审批完成', + method: '第三方运输', + reason: '场站资源调整', + plateNo: '浙B22222', + vehicleType: '轿车', + brand: '蔚来', + model: 'ET5', + carrierName: '中外运', + departMileageKm: '15080.00', + receiveMileageKm: '15410.00', + departHydrogen: '24.00', + receiveHydrogen: '21.50', + h2Unit: 'MPa', + departElectricKwh: '58.60', + receiveElectricKwh: '52.10', + departParking: '宁波江北停车场', + createDate: '2026-01-20 15:15' + }, + { + id: 'th4', + transferDate: '2026-01-25 11:20', + departRegionText: '上海市-上海市', + transferPerson: '张明', + receiveDate: '2026-01-27 19:45', + receiveRegionText: '广东省-东莞市', + receivePerson: '王芳', + approvalStatus: '审批完成', + method: '第三方运输', + reason: '跨区域调拨', + plateNo: '沪A30003', + vehicleType: '厢式货车', + brand: '福田', + model: 'BJ1180', + carrierName: '德邦物流', + departMileageKm: '9900.00', + receiveMileageKm: '10320.00', + departHydrogen: '26.80', + receiveHydrogen: '23.60', + h2Unit: 'MPa', + departElectricKwh: '71.20', + receiveElectricKwh: '64.00', + departParking: '张江园区停车场', + createDate: '2026-01-25 10:40' + }, + { + id: 'th5', + transferDate: '2026-01-28 08:50', + departRegionText: '广东省-深圳市', + transferPerson: '陈静', + receiveDate: '2026-01-30 16:10', + receiveRegionText: '浙江省-嘉兴市', + receivePerson: '李华', + approvalStatus: '审批完成', + method: '司机驾驶', + reason: '项目新增点位支持', + plateNo: '粤B11111', + vehicleType: '轿车', + brand: '比亚迪', + model: '汉', + carrierName: '-', + departMileageKm: '8100.00', + receiveMileageKm: '8460.00', + departHydrogen: '58.00', + receiveHydrogen: '52.00', + h2Unit: '%', + departElectricKwh: '61.00', + receiveElectricKwh: '55.00', + departParking: '南山科技园停车场', + createDate: '2026-01-28 08:05' + }, + { + id: 'th6', + transferDate: '2026-02-02 14:30', + departRegionText: '浙江省-杭州市', + transferPerson: '赵强', + receiveDate: '2026-02-04 09:20', + receiveRegionText: '上海市-上海市', + receivePerson: '张明', + approvalStatus: '审批完成', + method: '第三方运输', + reason: '场站容量调整', + plateNo: '浙A11111', + vehicleType: 'SUV', + brand: '小鹏', + model: 'P7', + carrierName: '顺丰同城运输', + departMileageKm: '11880.00', + receiveMileageKm: '12110.00', + departHydrogen: '62.00', + receiveHydrogen: '58.00', + h2Unit: '%', + departElectricKwh: '56.00', + receiveElectricKwh: '52.30', + departParking: '西湖景区停车场', + createDate: '2026-02-02 13:45' + }, + { + id: 'th7', + transferDate: '2026-02-05 10:10', + departRegionText: '广东省-东莞市', + transferPerson: '李华', + receiveDate: '2026-02-07 18:30', + receiveRegionText: '广东省-深圳市', + receivePerson: '陈静', + approvalStatus: '审批完成', + method: '司机驾驶', + reason: '场站资源调整', + plateNo: '粤A12345', + vehicleType: '厢式货车', + brand: '东风', + model: 'DFH1180', + carrierName: '-', + departMileageKm: '14850.00', + receiveMileageKm: '15120.00', + departHydrogen: '29.00', + receiveHydrogen: '26.50', + h2Unit: 'MPa', + departElectricKwh: '65.00', + receiveElectricKwh: '60.00', + departParking: '松山湖停车场', + createDate: '2026-02-05 09:20' + }, + { + id: 'th8', + transferDate: '2026-02-08 15:40', + departRegionText: '上海市-上海市', + transferPerson: '张明', + receiveDate: '2026-02-10 11:15', + receiveRegionText: '浙江省-宁波市', + receivePerson: '王芳', + approvalStatus: '审批完成', + method: '第三方运输', + reason: '项目调度需要', + plateNo: '沪A30003', + vehicleType: '厢式货车', + brand: '福田', + model: 'BJ1180', + carrierName: '德邦物流', + departMileageKm: '10050.00', + receiveMileageKm: '10460.00', + departHydrogen: '25.20', + receiveHydrogen: '22.80', + h2Unit: 'MPa', + departElectricKwh: '72.00', + receiveElectricKwh: '66.00', + departParking: '张江园区停车场', + createDate: '2026-02-08 14:50' + }, + { + id: 'th9', + transferDate: '2026-02-12 09:00', + departRegionText: '浙江省-嘉兴市', + transferPerson: '陈静', + receiveDate: '2026-02-14 17:20', + receiveRegionText: '广东省-广州市', + receivePerson: '赵强', + approvalStatus: '审批完成', + method: '第三方运输', + reason: '车辆调拨支持新项目', + plateNo: '浙A11111', + vehicleType: 'SUV', + brand: '小鹏', + model: 'P7', + carrierName: '顺丰同城运输', + departMileageKm: '11980.00', + receiveMileageKm: '12420.00', + departHydrogen: '60.00', + receiveHydrogen: '55.00', + h2Unit: '%', + departElectricKwh: '55.00', + receiveElectricKwh: '49.80', + departParking: '嘉兴南湖停车场', + createDate: '2026-02-12 08:15' + }, + { + id: 'th10', + transferDate: '2026-02-16 13:10', + departRegionText: '广东省-深圳市', + transferPerson: '王芳', + receiveDate: '2026-02-18 09:40', + receiveRegionText: '上海市-上海市', + receivePerson: '李华', + approvalStatus: '审批完成', + method: '司机驾驶', + reason: '项目调度需要', + plateNo: '粤B11111', + vehicleType: '轿车', + brand: '比亚迪', + model: '汉', + carrierName: '-', + departMileageKm: '8200.00', + receiveMileageKm: '8560.00', + departHydrogen: '57.00', + receiveHydrogen: '50.00', + h2Unit: '%', + departElectricKwh: '60.00', + receiveElectricKwh: '54.00', + departParking: '南山科技园停车场', + createDate: '2026-02-16 12:20' + } + ]; + }, []); + + function matchRange(valStr, range) { + if (!range || !range[0] || !range[1]) return true; + var s = ''; + var e = ''; + if (range[0] && range[0].format) s = range[0].format('YYYY-MM-DD'); + if (range[1] && range[1].format) e = range[1].format('YYYY-MM-DD'); + if (!s && !e) return true; + var v = String(valStr || '').slice(0, 10); + if (s && v < s) return false; + if (e && v > e) return false; + return true; + } + + function matchRegionText(text, cascaderVal) { + if (!cascaderVal || cascaderVal.length < 2) return true; + var map = { + zhejiang: '浙江省', shanghai: '上海市', guangdong: '广东省', + hangzhou: '杭州市', ningbo: '宁波市', jiaxing: '嘉兴市', + guangzhou: '广州市', shenzhen: '深圳市', dongguan: '东莞市' + }; + var pt = map[cascaderVal[0]] || ''; + var ct = map[cascaderVal[1]] || ''; + return String(text || '').indexOf(pt + '-' + ct) >= 0; + } + + function applyFilters(list, isHistory) { + return (list || []).filter(function (r) { + if (applied.transferPerson && r.transferPerson !== applied.transferPerson) return false; + if (applied.receivePerson && r.receivePerson !== applied.receivePerson) return false; + if (applied.plateNo && r.plateNo !== applied.plateNo) return false; + if (applied.method && r.method !== applied.method) return false; + if (applied.approvalStatus && r.approvalStatus !== applied.approvalStatus) return false; + if (!matchRange(r.transferDate, applied.transferDateRange)) return false; + if (isHistory) { + if (!matchRange(r.receiveDate, applied.receiveDateRange)) return false; + } + if (!matchRegionText(r.departRegionText, applied.departRegion)) return false; + if (!matchRegionText(r.receiveRegionText, applied.transferRegion)) return false; + return true; + }); + } + + var filteredInProgress = useMemo(function () { return applyFilters(listInProgress, false); }, [listInProgress, applied]); + var filteredHistory = useMemo(function () { return applyFilters(listHistory, true); }, [listHistory, applied]); + + var pagedInProgress = useMemo(function () { + var start = (page - 1) * pageSize; + return filteredInProgress.slice(start, start + pageSize); + }, [filteredInProgress, page, pageSize]); + + var pagedHistory = useMemo(function () { + var start = (page - 1) * pageSize; + return filteredHistory.slice(start, start + pageSize); + }, [filteredHistory, page, pageSize]); + + var handleQuery = useCallback(function () { + setApplied(Object.assign({}, draft)); + setPage(1); + }, [draft]); + + var handleReset = useCallback(function () { + var empty = { + transferDateRange: null, + transferPerson: undefined, + receiveDateRange: null, + receivePerson: undefined, + plateNo: undefined, + departRegion: undefined, + transferRegion: undefined, + method: undefined, + approvalStatus: undefined + }; + setDraft(empty); + setApplied(empty); + setPage(1); + }, []); + + var handleAdd = useCallback(function () { message.info('跳转调拨管理-新增(原型)'); }, []); + var handleExport = useCallback(function () { message.success('导出(原型)'); }, []); + + var columnsInProgress = useMemo(function () { + return [ + { title: '调拨日期', dataIndex: 'transferDate', key: 'transferDate', width: 160, render: function (v) { return fmtYMDHM(v); } }, + { title: '出发区域', dataIndex: 'departRegionText', key: 'departRegionText', width: 130 }, + { title: '调拨人', dataIndex: 'transferPerson', key: 'transferPerson', width: 100 }, + { title: '接收区域', dataIndex: 'receiveRegionText', key: 'receiveRegionText', width: 130 }, + { title: '接收人', dataIndex: 'receivePerson', key: 'receivePerson', width: 100 }, + { title: '审批状态', dataIndex: 'approvalStatus', key: 'approvalStatus', width: 100 }, + { title: '调拨方式', dataIndex: 'method', key: 'method', width: 110 }, + { title: '调拨原因', dataIndex: 'reason', key: 'reason', width: 140, ellipsis: true }, + { title: '车牌号', dataIndex: 'plateNo', key: 'plateNo', width: 110 }, + { title: '车辆类型', dataIndex: 'vehicleType', key: 'vehicleType', width: 120, ellipsis: true }, + { title: '品牌', dataIndex: 'brand', key: 'brand', width: 90 }, + { title: '型号', dataIndex: 'model', key: 'model', width: 120, ellipsis: true }, + { title: '运输方名称', dataIndex: 'carrierName', key: 'carrierName', width: 140, ellipsis: true }, + { title: '出发里程(km)', dataIndex: 'departMileageKm', key: 'departMileageKm', width: 130 }, + { title: '出发氢量', key: 'departHydrogen', width: 110, render: function (_, r) { return (r.departHydrogen || '-') + (r.h2Unit ? r.h2Unit : ''); } }, + { title: '出发电量(kWh)', dataIndex: 'departElectricKwh', key: 'departElectricKwh', width: 130 }, + { title: '出发停车场', dataIndex: 'departParking', key: 'departParking', width: 140, ellipsis: true }, + { title: '创建日期', dataIndex: 'createDate', key: 'createDate', width: 160, render: function (v) { return fmtYMDHM(v); } }, + { + title: '操作', + key: 'action', + width: 280, + fixed: 'right', + render: function (_, r) { + var st = String(r && r.approvalStatus ? r.approvalStatus : ''); + var canEdit = st === '待提交' || st === '审批驳回' || st === '撤回'; + var canReceiveRecord = st === '审批完成'; + var canRevoke = st === '审批中'; + var rowId = r && r.id; + return React.createElement('span', { style: { display: 'inline-flex', flexWrap: 'wrap', gap: 8, alignItems: 'center' } }, + React.createElement(Button, { type: 'link', size: 'small', onClick: function () { message.info('跳转调拨管理-查看页(原型)ID:' + rowId); } }, '查看'), + canEdit ? React.createElement(Button, { type: 'link', size: 'small', onClick: function () { message.info('跳转调拨管理-编辑页(原型)ID:' + rowId); } }, '编辑') : null, + canReceiveRecord ? React.createElement(Button, { type: 'link', size: 'small', onClick: function () { message.info('跳转调拨管理-接收记录页(原型)ID:' + rowId); } }, '接收记录') : null, + canRevoke ? React.createElement(Button, { + type: 'link', + size: 'small', + danger: true, + onClick: function () { + Modal.confirm({ + title: '是否确认撤回?', + content: '确认后该调拨单审批状态将变更为「撤回」。', + okText: '确认', + cancelText: '取消', + onOk: function () { + setListInProgress(function (prev) { + return (prev || []).map(function (row) { + if (row && row.id === rowId) return Object.assign({}, row, { approvalStatus: '撤回' }); + return row; + }); + }); + message.success('已撤回,审批状态已更新为撤回'); + } + }); + } + }, '撤回') : null + ); + } + } + ]; + }, [setListInProgress]); + + var columnsHistory = useMemo(function () { + return [ + { title: '调拨日期', dataIndex: 'transferDate', key: 'transferDate', width: 160, render: function (v) { return fmtYMDHM(v); } }, + { title: '出发区域', dataIndex: 'departRegionText', key: 'departRegionText', width: 130 }, + { title: '调拨人', dataIndex: 'transferPerson', key: 'transferPerson', width: 100 }, + { title: '接收日期', dataIndex: 'receiveDate', key: 'receiveDate', width: 160, render: function (v) { return fmtYMDHM(v); } }, + { title: '接收区域', dataIndex: 'receiveRegionText', key: 'receiveRegionText', width: 130 }, + { title: '接收人', dataIndex: 'receivePerson', key: 'receivePerson', width: 100 }, + { title: '审批状态', dataIndex: 'approvalStatus', key: 'approvalStatus', width: 100 }, + { title: '调拨方式', dataIndex: 'method', key: 'method', width: 110 }, + { title: '调拨原因', dataIndex: 'reason', key: 'reason', width: 140, ellipsis: true }, + { title: '车牌号', dataIndex: 'plateNo', key: 'plateNo', width: 110 }, + { title: '车辆类型', dataIndex: 'vehicleType', key: 'vehicleType', width: 120, ellipsis: true }, + { title: '品牌', dataIndex: 'brand', key: 'brand', width: 90 }, + { title: '型号', dataIndex: 'model', key: 'model', width: 120, ellipsis: true }, + { title: '运输方名称', dataIndex: 'carrierName', key: 'carrierName', width: 140, ellipsis: true }, + { title: '出发里程(km)', dataIndex: 'departMileageKm', key: 'departMileageKm', width: 130 }, + { title: '接收里程(km)', dataIndex: 'receiveMileageKm', key: 'receiveMileageKm', width: 130 }, + { title: '出发氢量', key: 'departHydrogen', width: 110, render: function (_, r) { return (r.departHydrogen || '-') + (r.h2Unit ? r.h2Unit : ''); } }, + { title: '接收氢量', key: 'receiveHydrogen', width: 110, render: function (_, r) { return (r.receiveHydrogen || '-') + (r.h2Unit ? r.h2Unit : ''); } }, + { title: '出发电量(kWh)', dataIndex: 'departElectricKwh', key: 'departElectricKwh', width: 130 }, + { title: '接收电量(kWh)', dataIndex: 'receiveElectricKwh', key: 'receiveElectricKwh', width: 130 }, + { title: '出发停车场', dataIndex: 'departParking', key: 'departParking', width: 140, ellipsis: true }, + { title: '创建日期', dataIndex: 'createDate', key: 'createDate', width: 160, render: function (v) { return fmtYMDHM(v); } }, + { + title: '操作', + key: 'action', + width: 100, + fixed: 'right', + render: function (_, r) { + return React.createElement(Button, { type: 'link', size: 'small', onClick: function () { message.info('跳转调拨管理-查看页(原型)ID:' + r.id); } }, '查看'); + } + } + ]; + }, []); + + var filterItems = [ + React.createElement('div', { key: 'transferDate', style: filterItemStyle }, + React.createElement('div', { style: filterLabelStyle }, '调拨日期'), + React.createElement(RangePicker, { style: filterControlStyle, value: draft.transferDateRange, onChange: function (v) { setDraft(function (p) { return Object.assign({}, p, { transferDateRange: v }); }); }, placeholder: ['开始日期', '结束日期'] }) + ), + React.createElement('div', { key: 'transferPerson', style: filterItemStyle }, + React.createElement('div', { style: filterLabelStyle }, '调拨人'), + React.createElement(Select, { placeholder: '请输入或选择调拨人', style: filterControlStyle, value: draft.transferPerson, onChange: function (v) { setDraft(function (p) { return Object.assign({}, p, { transferPerson: v }); }); }, allowClear: true, showSearch: true, options: userOptions, filterOption: filterOption }) + ), + React.createElement('div', { key: 'receiveDate', style: filterItemStyle }, + React.createElement('div', { style: filterLabelStyle }, '接收日期'), + React.createElement(RangePicker, { style: filterControlStyle, value: draft.receiveDateRange, onChange: function (v) { setDraft(function (p) { return Object.assign({}, p, { receiveDateRange: v }); }); }, placeholder: ['开始日期', '结束日期'] }) + ), + React.createElement('div', { key: 'receivePerson', style: filterItemStyle }, + React.createElement('div', { style: filterLabelStyle }, '接收人'), + React.createElement(Select, { placeholder: '请输入或选择接收人', style: filterControlStyle, value: draft.receivePerson, onChange: function (v) { setDraft(function (p) { return Object.assign({}, p, { receivePerson: v }); }); }, allowClear: true, showSearch: true, options: userOptions, filterOption: filterOption }) + ), + React.createElement('div', { key: 'plateNo', style: filterItemStyle }, + React.createElement('div', { style: filterLabelStyle }, '车牌号'), + React.createElement(Select, { placeholder: '请输入或选择车牌号', style: filterControlStyle, value: draft.plateNo, onChange: function (v) { setDraft(function (p) { return Object.assign({}, p, { plateNo: v }); }); }, allowClear: true, showSearch: true, options: plateOptions, filterOption: filterOption }) + ), + React.createElement('div', { key: 'departRegion', style: filterItemStyle }, + React.createElement('div', { style: filterLabelStyle }, '出发区域'), + React.createElement(Cascader, { placeholder: '请选择出发区域', style: filterControlStyle, options: regionOptions, value: draft.departRegion, onChange: function (v) { setDraft(function (p) { return Object.assign({}, p, { departRegion: v }); }); }, allowClear: true }) + ), + React.createElement('div', { key: 'transferRegion', style: filterItemStyle }, + React.createElement('div', { style: filterLabelStyle }, '调拨区域'), + React.createElement(Cascader, { placeholder: '请选择调拨区域', style: filterControlStyle, options: regionOptions, value: draft.transferRegion, onChange: function (v) { setDraft(function (p) { return Object.assign({}, p, { transferRegion: v }); }); }, allowClear: true }) + ), + React.createElement('div', { key: 'method', style: filterItemStyle }, + React.createElement('div', { style: filterLabelStyle }, '调拨方式'), + React.createElement(Select, { placeholder: '请选择调拨方式', style: filterControlStyle, value: draft.method, onChange: function (v) { setDraft(function (p) { return Object.assign({}, p, { method: v }); }); }, allowClear: true, options: methodOptions }) + ), + React.createElement('div', { key: 'approvalStatus', style: filterItemStyle }, + React.createElement('div', { style: filterLabelStyle }, '审批状态'), + React.createElement(Select, { placeholder: '请选择审批状态', style: filterControlStyle, value: draft.approvalStatus, onChange: function (v) { setDraft(function (p) { return Object.assign({}, p, { approvalStatus: v }); }); }, allowClear: true, options: approvalOptions }) + ) + ]; + + var filterCount = filterExpanded ? 9 : 3; + var filterNodes = []; + for (var i = 0; i < filterCount && i < filterItems.length; i++) filterNodes.push(filterItems[i]); + + var tabItems = useMemo(function () { + return [ + { + key: 'in_progress', + label: '进行中', + children: React.createElement(Table, { + rowKey: 'id', + columns: columnsInProgress, + dataSource: pagedInProgress, + scroll: { x: 2300 }, + size: 'small', + pagination: { + current: page, + pageSize: pageSize, + total: filteredInProgress.length, + showSizeChanger: true, + showQuickJumper: true, + showTotal: function (t) { return '共 ' + t + ' 条'; }, + onChange: function (pg, ps) { setPage(pg); if (ps) setPageSize(ps); } + } + }) + }, + { + key: 'history', + label: '历史记录', + children: React.createElement(Table, { + rowKey: 'id', + columns: columnsHistory, + dataSource: pagedHistory, + scroll: { x: 2600 }, + size: 'small', + pagination: { + current: page, + pageSize: pageSize, + total: filteredHistory.length, + showSizeChanger: true, + showQuickJumper: true, + showTotal: function (t) { return '共 ' + t + ' 条'; }, + onChange: function (pg, ps) { setPage(pg); if (ps) setPageSize(ps); } + } + }) + } + ]; + }, [columnsInProgress, columnsHistory, pagedInProgress, pagedHistory, page, pageSize, filteredInProgress.length, filteredHistory.length]); + + return React.createElement(App, null, + React.createElement('div', { style: layoutStyle }, + React.createElement('div', { style: { display: 'flex', alignItems: 'center', justifyContent: 'space-between', marginBottom: 16, flexWrap: 'wrap', gap: 8 } }, + React.createElement(Breadcrumb, { items: [{ title: '运维管理' }, { title: '车辆业务' }, { title: '调拨管理' }] }), + React.createElement(Button, { type: 'link', style: { padding: 0 }, onClick: function () { setRequirementModalOpen(true); } }, '查看需求说明') + ), + + React.createElement(Modal, { + title: '需求说明', + open: requirementModalOpen, + onCancel: function () { setRequirementModalOpen(false); }, + width: 720, + footer: React.createElement(Button, { onClick: function () { setRequirementModalOpen(false); } }, '关闭'), + bodyStyle: { maxHeight: '70vh', overflow: 'auto' } + }, React.createElement('div', { style: { whiteSpace: 'pre-wrap', fontSize: 13, lineHeight: 1.6, color: 'rgba(0,0,0,0.85)' } }, requirementDocContent)), + + React.createElement(Card, { style: { marginBottom: 16 } }, + React.createElement('div', { style: { display: 'grid', gridTemplateColumns: '1fr 1fr 1fr', gap: '16px 24px', alignItems: 'start', flex: 1, minWidth: 0 } }, filterNodes), + React.createElement('div', { style: { display: 'flex', justifyContent: 'flex-end', gap: 8, marginTop: 16 } }, + React.createElement(Button, { onClick: handleReset }, '重置'), + React.createElement(Button, { type: 'primary', onClick: handleQuery }, '查询'), + React.createElement(Button, { type: 'link', size: 'small', onClick: function () { setFilterExpanded(!filterExpanded); } }, filterExpanded ? '收起' : '展开') + ) + ), + + React.createElement(Card, null, + React.createElement(React.Fragment, null, + React.createElement('style', null, tableSingleLineStyle), + React.createElement('div', { className: 'transfer-list-table' }, + React.createElement(Tabs, { + activeKey: tab, + onChange: function (k) { setTab(k); setPage(1); }, + tabBarExtraContent: React.createElement('div', { style: { display: 'flex', gap: 8 } }, + React.createElement(Button, { type: 'primary', onClick: handleAdd }, '新增'), + React.createElement(Button, { onClick: handleExport }, '导出') + ), + items: tabItems + }) + ) + ) + ) + ) + ); +}; + diff --git a/web端/运维管理/车辆管理-查看.jsx b/web端/运维管理/车辆管理-查看.jsx index a071e1b..b2d03cb 100644 --- a/web端/运维管理/车辆管理-查看.jsx +++ b/web端/运维管理/车辆管理-查看.jsx @@ -12,6 +12,11 @@ const Component = function () { var Tag = antd.Tag; var Button = antd.Button; var Tooltip = antd.Tooltip; + var Select = antd.Select; + var DatePicker = antd.DatePicker; + var RangePicker = DatePicker.RangePicker; + var message = antd.message; + var Image = antd.Image; // 顶部概览 mock 数据(与图片一致) var overview = { @@ -72,6 +77,21 @@ const Component = function () { coldMachineVendor: 'xxxxxxxx企业', stackVendor: 'XXXXXXXX企业' }; + + // 证照管理 Tab:证件照片占位(可替换为真实 URL,支持 Image 预览) + var licensePhotoPlaceholder = 'data:image/svg+xml,' + encodeURIComponent('行驶证/证照示意图'); + var certificateDetail = { + drivingLicense: { img: licensePhotoPlaceholder, regDate: '2025-07-01', scrapDate: '2038-12-31', inspectExpire: '2027-07-31' }, + operationPermit: { img: licensePhotoPlaceholder, permitNo: '营330482001234', regDate: '2025-07-15', inspectExpire: '2026-07-14', certExpire: '2030-07-14' }, + passPermit: { img: licensePhotoPlaceholder, code: 'TX-ZJ-2025-0088', area: '浙江省嘉兴市平湖市行政辖区', expire: '2026-12-31' }, + registrationCert: { img: licensePhotoPlaceholder }, + h2Permit: { img: licensePhotoPlaceholder, permitCode: 'JQZ-2025-F069001', cardCode: 'JK-88A901256', inspectDate: '2025-06-15' }, + h2Card: { img: licensePhotoPlaceholder, stationName: '嘉兴港区某某加氢站' }, + safetyValve: { img: licensePhotoPlaceholder, inspectDate: '2025-05-10', cycle: '12个月', validUntil: '2026-05-09' }, + pressureGauge: { img: licensePhotoPlaceholder, inspectDate: '2025-05-10', cycle: '12个月', gaugeValidUntil: '2026-05-09' }, + h2Cylinder: { img: licensePhotoPlaceholder, vendor: '某某高压气瓶制造有限公司', inspectDate: '2025-04-01', cycle: '36个月', cylinderValidUntil: '2028-03-31' } + }; + var maintenanceList = [ { key: '1', item: '变速器油', kmCycle: '60000', monthCycle: '24', laborCost: '0', materialCost: '571', total: '571', lastKm: '' }, { key: '2', item: '变速器油', kmCycle: '60000', monthCycle: '24', laborCost: '0', materialCost: '571', total: '571', lastKm: '' }, @@ -81,6 +101,371 @@ const Component = function () { ]; var activeTab = useState('model'); + var rearFilterDraft = useState({ installRange: null, deviceType: undefined }); + var rearFilterApplied = useState({ installRange: null, deviceType: undefined }); + var leaseFilterDraft = useState({ contractCode: undefined, projectName: undefined, customerName: undefined }); + var leaseFilterApplied = useState({ contractCode: undefined, projectName: undefined, customerName: undefined }); + var accidentFilterDraft = useState({ accidentTimeRange: null, customerName: undefined }); + var accidentFilterApplied = useState({ accidentTimeRange: null, customerName: undefined }); + var violationFilterDraft = useState({ violationTimeRange: null, payStatus: undefined, violationCustomer: undefined }); + var violationFilterApplied = useState({ violationTimeRange: null, payStatus: undefined, violationCustomer: undefined }); + var moveRecordFilterDraft = useState({ moveStartRange: null, destination: undefined, moveType: undefined }); + var moveRecordFilterApplied = useState({ moveStartRange: null, destination: undefined, moveType: undefined }); + var transferRecordFilterDraft = useState({ transferDateRange: null, transferPerson: undefined, receivePerson: undefined }); + var transferRecordFilterApplied = useState({ transferDateRange: null, transferPerson: undefined, receivePerson: undefined }); + + var rearDeviceTypeOptions = [ + { value: 'GPS', label: 'GPS' }, + { value: '尾板', label: '尾板' }, + { value: '车身广告', label: '车身广告' }, + { value: 'G7安全套件', label: 'G7安全套件' }, + { value: 'G7普通设备', label: 'G7普通设备' }, + { value: 'G7温控设备', label: 'G7温控设备' }, + { value: '备胎', label: '备胎' } + ]; + var rearDeviceMockData = [ + { key: 'rd1', deviceType: 'GPS', supplier: '深圳某某物联科技', actionType: '安装', actionTime: '2024-06-10 09:30', operator: '张三' }, + { key: 'rd2', deviceType: '尾板', supplier: '上海凯卓液压设备', actionType: '安装', actionTime: '2024-07-02 14:15', operator: '李四' }, + { key: 'rd3', deviceType: '车身广告', supplier: '广州传媒广告', actionType: '拆卸', actionTime: '2024-08-18 11:00', operator: '王五' }, + { key: 'rd4', deviceType: 'G7安全套件', supplier: 'G7易流科技', actionType: '安装', actionTime: '2024-09-05 16:40', operator: '赵六' }, + { key: 'rd5', deviceType: 'G7普通设备', supplier: 'G7易流科技', actionType: '拆卸', actionTime: '2024-10-12 08:20', operator: '张三' }, + { key: 'rd6', deviceType: 'G7温控设备', supplier: 'G7易流科技', actionType: '安装', actionTime: '2024-11-01 13:45', operator: '陈静' }, + { key: 'rd7', deviceType: '备胎', supplier: '某某汽配供应链', actionType: '安装', actionTime: '2024-11-20 10:00', operator: '李四' }, + { key: 'rd8', deviceType: 'GPS', supplier: '深圳某某物联科技', actionType: '拆卸', actionTime: '2025-01-08 15:30', operator: '王五' } + ]; + + function matchRearInstallRange(valStr, range) { + if (!range || !range[0] || !range[1]) return true; + var s = ''; + var e = ''; + if (range[0] && range[0].format) s = range[0].format('YYYY-MM-DD'); + if (range[1] && range[1].format) e = range[1].format('YYYY-MM-DD'); + if (!s && !e) return true; + var v = String(valStr || '').slice(0, 10); + if (s && v < s) return false; + if (e && v > e) return false; + return true; + } + function fmtRearActionTime(v) { + if (v === null || v === undefined) return '-'; + var str = String(v).trim(); + if (!str) return '-'; + if (/^\d{4}-\d{2}-\d{2}\s+\d{2}:\d{2}/.test(str)) return str.slice(0, 16); + if (/^\d{4}-\d{2}-\d{2}$/.test(str)) return str + ' 00:00'; + return str; + } + function filterOption(input, option) { + var label = (option && (option.label || option.children)) || ''; + return String(label).toLowerCase().indexOf(String(input || '').toLowerCase()) >= 0; + } + function fmtDateYMD(v) { + if (v === null || v === undefined) return '-'; + var s = String(v).trim(); + if (!s || s === '-') return '-'; + if (/^\d{4}-\d{2}-\d{2}/.test(s)) return s.slice(0, 10); + try { + var d = new Date(s.replace(/-/g, '/')); + if (isNaN(d.getTime())) return s; + var p2 = function (n) { return n < 10 ? '0' + n : '' + n; }; + return d.getFullYear() + '-' + p2(d.getMonth() + 1) + '-' + p2(d.getDate()); + } catch (e) { + return s; + } + } + + var rearDraft = rearFilterDraft[0]; + var setRearDraft = rearFilterDraft[1]; + var rearApplied = rearFilterApplied[0]; + var setRearApplied = rearFilterApplied[1]; + var rearFiltered = rearDeviceMockData.filter(function (row) { + if (!matchRearInstallRange(row.actionTime, rearApplied.installRange)) return false; + if (rearApplied.deviceType && row.deviceType !== rearApplied.deviceType) return false; + return true; + }); + + var leaseMockData = [ + { key: 'ls1', contractCode: 'LNZLHTSH2023071301', projectName: '嘉兴冷链城配A线', customerName: '上海迅杰物流有限公司', deliveryDate: '2024-03-15', deliveryPerson: '金可鹏', returnDate: '2024-09-10', returnPerson: '王明' }, + { key: 'ls2', contractCode: 'HT-2024-009', projectName: '平湖氢能示范运营', customerName: '上海迅杰物流有限公司', deliveryDate: '2025-01-08', deliveryPerson: '李华', returnDate: '-', returnPerson: '-' }, + { key: 'ls3', contractCode: 'ZL-SH-2023-066', projectName: '上海港短驳项目', customerName: '江苏某某供应链有限公司', deliveryDate: '2023-11-20', deliveryPerson: '赵强', returnDate: '2024-05-30', returnPerson: '陈静' }, + { key: 'ls4', contractCode: 'LNZLHTSH2023071301', projectName: '沪浙干线运输', customerName: '浙江某某快运', deliveryDate: '2022-08-01', deliveryPerson: '张三', returnDate: '2023-07-14', returnPerson: '李四' }, + { key: 'ls5', contractCode: 'HT-2024-112', projectName: '长三角城配网络', customerName: '上海迅杰物流有限公司', deliveryDate: '2024-11-01', deliveryPerson: '周伟', returnDate: '2025-02-20', returnPerson: '吴芳' } + ]; + function leaseUniqOptions(rows, field) { + var seen = {}; + var out = []; + for (var i = 0; i < rows.length; i++) { + var v = rows[i][field]; + if (v && v !== '-' && !seen[v]) { + seen[v] = true; + out.push({ value: v, label: v }); + } + } + return out; + } + var leaseContractOptions = leaseUniqOptions(leaseMockData, 'contractCode'); + var leaseProjectOptions = leaseUniqOptions(leaseMockData, 'projectName'); + var leaseCustomerOptions = leaseUniqOptions(leaseMockData, 'customerName'); + var leaseDraft = leaseFilterDraft[0]; + var setLeaseDraft = leaseFilterDraft[1]; + var leaseApplied = leaseFilterApplied[0]; + var setLeaseApplied = leaseFilterApplied[1]; + var leaseFiltered = leaseMockData.filter(function (row) { + if (leaseApplied.contractCode && row.contractCode !== leaseApplied.contractCode) return false; + if (leaseApplied.projectName && row.projectName !== leaseApplied.projectName) return false; + if (leaseApplied.customerName && row.customerName !== leaseApplied.customerName) return false; + return true; + }); + + function matchAccidentDateRange(valStr, range) { + if (!range || !range[0] || !range[1]) return true; + var s = ''; + var e = ''; + if (range[0] && range[0].format) s = range[0].format('YYYY-MM-DD'); + if (range[1] && range[1].format) e = range[1].format('YYYY-MM-DD'); + if (!s && !e) return true; + var v = String(valStr || '').slice(0, 10); + if (s && v < s) return false; + if (e && v > e) return false; + return true; + } + function cellOrDash(v) { + if (v === null || v === undefined) return '-'; + var s = String(v).trim(); + return s ? s : '-'; + } + + var accidentMockData = [ + { + key: 'ac1', + accidentCode: 'SG202508250001', + accidentTime: '2025-08-25', + location: '北京市大兴区京开高速辅路K12段', + accidentType: '撞固定物', + customerName: '北京海龙运输有限公司', + ourLossAmount: '', + otherLossAmount: '', + liability: '全责', + status: '未结案', + closeTime: '', + otherFee: '', + remark: '' + }, + { + key: 'ac2', + accidentCode: 'SG202504180012', + accidentTime: '2025-04-18', + location: '上海市浦东新区外环高速出口匝道', + accidentType: '追尾', + customerName: '上海迅杰物流有限公司', + ourLossAmount: '12800.00', + otherLossAmount: '5600.00', + liability: '主责', + status: '已结案', + closeTime: '2025-05-30', + otherFee: '800.00', + remark: '对方车辆已理赔完毕' + }, + { + key: 'ac3', + accidentCode: 'SG202502030088', + accidentTime: '2025-02-03', + location: '浙江省嘉兴市平湖市乍兴公路与平廊线交叉口', + accidentType: '剐蹭', + customerName: '上海迅杰物流有限公司', + ourLossAmount: '2100.00', + otherLossAmount: '', + liability: '同责', + status: '未结案', + closeTime: '', + otherFee: '', + remark: '' + }, + { + key: 'ac4', + accidentCode: 'SG202411120156', + accidentTime: '2024-11-12', + location: '广东省深圳市南山区南海大道与东滨路交汇处', + accidentType: '侧翻', + customerName: '江苏某某供应链有限公司', + ourLossAmount: '', + otherLossAmount: '32000.00', + liability: '次责', + status: '已结案', + closeTime: '2024-12-20', + otherFee: '1200.50', + remark: '货物转运产生费用' + }, + { + key: 'ac5', + accidentCode: 'SG202409051203', + accidentTime: '2024-09-05', + location: '杭州市余杭区文一西路隧道内', + accidentType: '撞固定物', + customerName: '浙江某某快运有限公司', + ourLossAmount: '8600.00', + otherLossAmount: '', + liability: '全责', + status: '未结案', + closeTime: '', + otherFee: '', + remark: '待交警责任认定书' + } + ]; + var accidentCustomerOptions = leaseUniqOptions(accidentMockData, 'customerName'); + var accidentDraft = accidentFilterDraft[0]; + var setAccidentDraft = accidentFilterDraft[1]; + var accidentApplied = accidentFilterApplied[0]; + var setAccidentApplied = accidentFilterApplied[1]; + var accidentFiltered = accidentMockData.filter(function (row) { + if (!matchAccidentDateRange(row.accidentTime, accidentApplied.accidentTimeRange)) return false; + if (accidentApplied.customerName && row.customerName !== accidentApplied.customerName) return false; + return true; + }); + + var violationPayStatusOptions = [ + { value: '未缴费', label: '未缴费' }, + { value: '已缴费', label: '已缴费' } + ]; + var violationMockData = [ + { + key: 'vz1', + violationCode: 'WZ202602010001', + violationBehavior: '闯红灯', + violationTime: '2026-02-01', + fineAmount: '100.00', + payStatus: '未缴费', + points: '6', + processed: '未处理', + violationCustomer: '上海馨想事成物流有限公司', + photo: '', + remark: '' + }, + { + key: 'vz2', + violationCode: 'WZ202511200088', + violationBehavior: '超速20%以下', + violationTime: '2025-11-20', + fineAmount: '200.00', + payStatus: '已缴费', + points: '3', + processed: '已处理', + violationCustomer: '上海迅杰物流有限公司', + photo: 'mock-url', + remark: '线上已缴清' + }, + { + key: 'vz3', + violationCode: 'WZ202508150045', + violationBehavior: '违法停车', + violationTime: '2025-08-15', + fineAmount: '150.00', + payStatus: '未缴费', + points: '0', + processed: '未处理', + violationCustomer: '北京海龙运输有限公司', + photo: '', + remark: '' + }, + { + key: 'vz4', + violationCode: 'WZ202506030112', + violationBehavior: '不按导向车道行驶', + violationTime: '2025-06-03', + fineAmount: '100.00', + payStatus: '已缴费', + points: '2', + processed: '已处理', + violationCustomer: '江苏某某供应链有限公司', + photo: '', + remark: '' + }, + { + key: 'vz5', + violationCode: 'WZ202503221956', + violationBehavior: '闯禁令标志', + violationTime: '2025-03-22', + fineAmount: '100.00', + payStatus: '未缴费', + points: '3', + processed: '未处理', + violationCustomer: '上海馨想事成物流有限公司', + photo: '', + remark: '复议中' + } + ]; + var violationCustomerOptions = leaseUniqOptions(violationMockData, 'violationCustomer'); + var violationDraft = violationFilterDraft[0]; + var setViolationDraft = violationFilterDraft[1]; + var violationApplied = violationFilterApplied[0]; + var setViolationApplied = violationFilterApplied[1]; + var violationFiltered = violationMockData.filter(function (row) { + if (!matchAccidentDateRange(row.violationTime, violationApplied.violationTimeRange)) return false; + if (violationApplied.payStatus && row.payStatus !== violationApplied.payStatus) return false; + if (violationApplied.violationCustomer && row.violationCustomer !== violationApplied.violationCustomer) return false; + return true; + }); + + var moveDestinationOptions = [ + { value: '维修站', label: '维修站' }, + { value: '停车场', label: '停车场' }, + { value: '其他', label: '其他' } + ]; + var moveTypeFilterOptions = [ + { value: '维修', label: '维修' }, + { value: '保养', label: '保养' }, + { value: '年审', label: '年审' }, + { value: '其他', label: '其他' } + ]; + var moveRecordMockData = [ + { key: 'mv1', moveStartAt: '2026-02-20 09:30', moveEndExpectedAt: '2026-02-22 18:00', approvalStatus: '待提交', destination: '维修站', destinationName: '天河氢能维修中心', moveType: '维修', expectedMileageKm: '45.5', startMileageKm: '15230.12', startElectricKwh: '68.40', startHydrogen: '28.30', h2Unit: 'MPa', creatorName: '张明', createTime: '2026-02-20 08:10' }, + { key: 'mv2', moveStartAt: '2026-02-21 14:00', moveEndExpectedAt: '2026-02-21 17:30', approvalStatus: '审批中', destination: '停车场', destinationName: '西湖景区停车场', moveType: '保养', expectedMileageKm: '12.0', startMileageKm: '12010.00', startElectricKwh: '55.20', startHydrogen: '60.00', h2Unit: '%', creatorName: '王芳', createTime: '2026-02-21 13:20' }, + { key: 'mv3', moveStartAt: '2026-02-24 08:15', moveEndExpectedAt: '2026-02-24 12:00', approvalStatus: '审批完成', destination: '其他', destinationName: '车管所检测线', moveType: '年审', expectedMileageKm: '8.2', startMileageKm: '8020.50', startElectricKwh: '62.10', startHydrogen: '55.00', h2Unit: '%', creatorName: '李华', createTime: '2026-02-24 07:50' }, + { key: 'mv4', moveStartAt: '2026-02-25 10:00', moveEndExpectedAt: '2026-02-26 09:00', approvalStatus: '驳回', destination: '维修站', destinationName: '张江服务站', moveType: '其他', expectedMileageKm: '30.0', startMileageKm: '9800.00', startElectricKwh: '69.00', startHydrogen: '26.00', h2Unit: 'MPa', creatorName: '赵强', createTime: '2026-02-25 09:40' }, + { key: 'mv5', moveStartAt: '2026-02-26 16:20', moveEndExpectedAt: '2026-02-27 10:00', approvalStatus: '撤回', destination: '停车场', destinationName: '宁波江北停车场', moveType: '维修', expectedMileageKm: '22.8', startMileageKm: '15010.00', startElectricKwh: '58.00', startHydrogen: '22.10', h2Unit: 'MPa', creatorName: '陈静', createTime: '2026-02-26 15:55' }, + { key: 'mv6', moveStartAt: '2026-02-27 07:45', moveEndExpectedAt: '2026-02-27 19:00', approvalStatus: '审批中', destination: '维修站', destinationName: '苏州园区快修站', moveType: '保养', expectedMileageKm: '18.6', startMileageKm: '23105.80', startElectricKwh: '42.50', startHydrogen: '45.20', h2Unit: '%', creatorName: '张明', createTime: '2026-02-27 07:20' }, + { key: 'mv7', moveStartAt: '2026-02-27 11:00', moveEndExpectedAt: '2026-02-28 17:30', approvalStatus: '审批完成', destination: '其他', destinationName: '顺义综合检测场', moveType: '年审', expectedMileageKm: '35.0', startMileageKm: '8890.00', startElectricKwh: '71.20', startHydrogen: '31.50', h2Unit: 'MPa', creatorName: '王芳', createTime: '2026-02-27 10:35' }, + { key: 'mv8', moveStartAt: '2026-02-28 08:30', moveEndExpectedAt: '2026-02-28 14:00', approvalStatus: '待提交', destination: '停车场', destinationName: '两江新区枢纽停车场', moveType: '其他', expectedMileageKm: '6.5', startMileageKm: '17660.25', startElectricKwh: '48.90', startHydrogen: '58.00', h2Unit: '%', creatorName: '李华', createTime: '2026-02-28 08:05' }, + { key: 'mv9', moveStartAt: '2026-02-28 13:15', moveEndExpectedAt: '2026-03-01 09:00', approvalStatus: '驳回', destination: '维修站', destinationName: '成都高新氢能维保站', moveType: '维修', expectedMileageKm: '52.3', startMileageKm: '34500.00', startElectricKwh: '33.60', startHydrogen: '24.80', h2Unit: 'MPa', creatorName: '赵强', createTime: '2026-02-28 12:50' }, + { key: 'mv10', moveStartAt: '2026-03-01 06:00', moveEndExpectedAt: '2026-03-01 11:45', approvalStatus: '审批完成', destination: '其他', destinationName: '青岛港务临时停放点', moveType: '保养', expectedMileageKm: '15.0', startMileageKm: '11220.00', startElectricKwh: '65.00', startHydrogen: '62.50', h2Unit: '%', creatorName: '陈静', createTime: '2026-03-01 05:40' } + ]; + var moveRecordDraft = moveRecordFilterDraft[0]; + var setMoveRecordDraft = moveRecordFilterDraft[1]; + var moveRecordApplied = moveRecordFilterApplied[0]; + var setMoveRecordApplied = moveRecordFilterApplied[1]; + var moveRecordFiltered = moveRecordMockData.filter(function (row) { + if (!matchAccidentDateRange(row.moveStartAt, moveRecordApplied.moveStartRange)) return false; + if (moveRecordApplied.destination && row.destination !== moveRecordApplied.destination) return false; + if (moveRecordApplied.moveType && row.moveType !== moveRecordApplied.moveType) return false; + return true; + }); + + var transferMockData = [ + { key: 'tp1', transferDate: '2026-02-20 09:30', departRegionText: '广东省-广州市', transferPerson: '张明', receiveRegionText: '浙江省-嘉兴市', receivePerson: '王芳', approvalStatus: '待提交', method: '第三方运输', reason: '场站资源调整', vehicleType: '厢式货车', brand: '东风', model: 'DFH1180', carrierName: '顺丰同城运输', departMileageKm: '15230.12', departHydrogen: '28.30', h2Unit: 'MPa', departElectricKwh: '68.40', departParking: '天河智慧停车场', createDate: '2026-02-20 08:10' }, + { key: 'tp2', transferDate: '2026-02-22 14:10', departRegionText: '浙江省-杭州市', transferPerson: '李华', receiveRegionText: '上海市-上海市', receivePerson: '赵强', approvalStatus: '审批完成', method: '司机驾驶', reason: '项目调度需要', vehicleType: 'SUV', brand: '小鹏', model: 'P7', carrierName: '-', departMileageKm: '12010.00', departHydrogen: '60.00', h2Unit: '%', departElectricKwh: '55.20', departParking: '西湖景区停车场', createDate: '2026-02-22 12:40' }, + { key: 'tp3', transferDate: '2026-02-24 11:05', departRegionText: '广东省-深圳市', transferPerson: '王芳', receiveRegionText: '浙江省-宁波市', receivePerson: '陈静', approvalStatus: '审批完成', method: '第三方运输', reason: '维修站资源调整', vehicleType: '轿车', brand: '比亚迪', model: '汉', carrierName: '德邦物流', departMileageKm: '8020.50', departHydrogen: '55.00', h2Unit: '%', departElectricKwh: '62.10', departParking: '南山科技园停车场', createDate: '2026-02-24 10:20' }, + { key: 'tp4', transferDate: '2026-02-25 16:40', departRegionText: '浙江省-嘉兴市', transferPerson: '赵强', receiveRegionText: '上海市-上海市', receivePerson: '李华', approvalStatus: '待提交', method: '司机驾驶', reason: '项目调度需要', vehicleType: '轿车', brand: '蔚来', model: 'ET5', carrierName: '-', departMileageKm: '15010.00', departHydrogen: '22.10', h2Unit: 'MPa', departElectricKwh: '58.00', departParking: '宁波江北停车场', createDate: '2026-02-25 15:55' }, + { key: 'tp5', transferDate: '2026-02-26 09:15', departRegionText: '上海市-上海市', transferPerson: '陈静', receiveRegionText: '广东省-广州市', receivePerson: '张明', approvalStatus: '审批驳回', method: '第三方运输', reason: '车辆调拨申请驳回样例', vehicleType: '厢式货车', brand: '福田', model: 'BJ1180', carrierName: '顺丰同城运输', departMileageKm: '9800.00', departHydrogen: '26.00', h2Unit: 'MPa', departElectricKwh: '69.00', departParking: '张江园区停车场', createDate: '2026-02-26 08:30' }, + { key: 'tp6', transferDate: '2026-02-27 13:30', departRegionText: '浙江省-杭州市', transferPerson: '张明', receiveRegionText: '浙江省-嘉兴市', receivePerson: '王芳', approvalStatus: '撤回', method: '司机驾驶', reason: '计划变更,撤回申请', vehicleType: 'SUV', brand: '小鹏', model: 'P7', carrierName: '-', departMileageKm: '12100.20', departHydrogen: '58.00', h2Unit: '%', departElectricKwh: '54.80', departParking: '西湖景区停车场', createDate: '2026-02-27 12:45' }, + { key: 'tp7', transferDate: '2026-02-28 08:50', departRegionText: '广东省-东莞市', transferPerson: '李华', receiveRegionText: '广东省-深圳市', receivePerson: '赵强', approvalStatus: '审批中', method: '第三方运输', reason: '跨区域调拨', vehicleType: '厢式货车', brand: '东风', model: 'DFH1180', carrierName: '中外运', departMileageKm: '15310.00', departHydrogen: '27.50', h2Unit: 'MPa', departElectricKwh: '67.20', departParking: '松山湖停车场', createDate: '2026-02-28 08:05' }, + { key: 'tp8', transferDate: '2026-03-01 10:10', departRegionText: '浙江省-宁波市', transferPerson: '王芳', receiveRegionText: '上海市-上海市', receivePerson: '陈静', approvalStatus: '待提交', method: '司机驾驶', reason: '项目新增点位支持', vehicleType: '轿车', brand: '蔚来', model: 'ET5', carrierName: '-', departMileageKm: '15120.00', departHydrogen: '21.80', h2Unit: 'MPa', departElectricKwh: '57.50', departParking: '宁波江北停车场', createDate: '2026-03-01 09:30' }, + { key: 'tp9', transferDate: '2026-03-02 15:25', departRegionText: '上海市-上海市', transferPerson: '赵强', receiveRegionText: '浙江省-杭州市', receivePerson: '李华', approvalStatus: '审批中', method: '第三方运输', reason: '场站容量调整', vehicleType: '厢式货车', brand: '福田', model: 'BJ1180', carrierName: '德邦物流', departMileageKm: '9850.00', departHydrogen: '24.20', h2Unit: 'MPa', departElectricKwh: '68.30', departParking: '张江园区停车场', createDate: '2026-03-02 14:40' }, + { key: 'tp10', transferDate: '2026-03-03 09:05', departRegionText: '浙江省-嘉兴市', transferPerson: '陈静', receiveRegionText: '广东省-广州市', receivePerson: '张明', approvalStatus: '待提交', method: '第三方运输', reason: '车辆调拨支持新项目', vehicleType: 'SUV', brand: '小鹏', model: 'P7', carrierName: '顺丰同城运输', departMileageKm: '12220.00', departHydrogen: '56.00', h2Unit: '%', departElectricKwh: '53.90', departParking: '嘉兴南湖停车场', createDate: '2026-03-03 08:20' } + ]; + var transferPersonOptions = leaseUniqOptions(transferMockData, 'transferPerson'); + var transferReceivePersonOptions = leaseUniqOptions(transferMockData, 'receivePerson'); + var transferDraft = transferRecordFilterDraft[0]; + var setTransferDraft = transferRecordFilterDraft[1]; + var transferApplied = transferRecordFilterApplied[0]; + var setTransferApplied = transferRecordFilterApplied[1]; + var transferFiltered = transferMockData.filter(function (row) { + if (!matchAccidentDateRange(row.transferDate, transferApplied.transferDateRange)) return false; + if (transferApplied.transferPerson && row.transferPerson !== transferApplied.transferPerson) return false; + if (transferApplied.receivePerson && row.receivePerson !== transferApplied.receivePerson) return false; + return true; + }); + + var filterLabelStyle = { marginBottom: 6, fontSize: 14, color: 'rgba(0,0,0,0.65)' }; + var filterItemStyle = { marginBottom: 12 }; var styles = { page: { padding: '16px 24px 40px', backgroundColor: '#f5f5f5', minHeight: '100vh', fontSize: 14 }, @@ -124,6 +509,88 @@ const Component = function () { ); } + function CertFieldRow(label, value) { + var show = value != null && String(value).trim() !== ''; + return React.createElement('div', { style: { display: 'flex', gap: 8, marginBottom: 10, fontSize: 14, lineHeight: '22px' } }, + React.createElement('span', { style: { color: 'rgba(0,0,0,0.45)', width: 168, flexShrink: 0 } }, label + ':'), + React.createElement('span', { style: { color: 'rgba(0,0,0,0.85)' } }, show ? value : '—') + ); + } + function CertSectionCard(title, imageSrc, fieldNodes) { + var right = fieldNodes && fieldNodes.length + ? React.createElement('div', { + style: { + flex: 1, + minWidth: 260, + display: 'flex', + alignItems: 'center', + alignSelf: 'stretch' + } + }, React.createElement('div', { style: { width: '100%' } }, fieldNodes)) + : null; + return React.createElement(Card, { key: title, size: 'small', style: { marginBottom: 16 }, title: title }, + React.createElement('div', { style: { display: 'flex', gap: 24, flexWrap: 'wrap', alignItems: 'stretch' } }, + React.createElement('div', { style: { flexShrink: 0, display: 'flex', flexDirection: 'column' } }, + React.createElement('div', { style: { marginBottom: 8, color: 'rgba(0,0,0,0.45)', fontSize: 13 } }, '证件照片'), + React.createElement(Image, { + width: 168, + height: 112, + style: { objectFit: 'cover', borderRadius: 4, border: '1px solid #f0f0f0', background: '#fafafa' }, + src: imageSrc, + alt: title, + preview: true + }) + ), + right + ) + ); + } + + var cd = certificateDetail; + var licenseManagementTabContent = React.createElement('div', { style: { padding: '0 4px' } }, + CertSectionCard('行驶证', cd.drivingLicense.img, [ + CertFieldRow('注册日期', cd.drivingLicense.regDate), + CertFieldRow('强制报废日期', cd.drivingLicense.scrapDate), + CertFieldRow('审验有效期', cd.drivingLicense.inspectExpire) + ]), + CertSectionCard('营运证', cd.operationPermit.img, [ + CertFieldRow('营运证编号', cd.operationPermit.permitNo), + CertFieldRow('注册日期', cd.operationPermit.regDate), + CertFieldRow('审验有效期', cd.operationPermit.inspectExpire), + CertFieldRow('证件有效期', cd.operationPermit.certExpire) + ]), + CertSectionCard('通行证', cd.passPermit.img, [ + CertFieldRow('通行证编码', cd.passPermit.code), + CertFieldRow('通行区域', cd.passPermit.area), + CertFieldRow('有效期', cd.passPermit.expire) + ]), + CertSectionCard('登记证', cd.registrationCert.img, null), + CertSectionCard('加氢证', cd.h2Permit.img, [ + CertFieldRow('加氢证编码', cd.h2Permit.permitCode), + CertFieldRow('加氢卡编码', cd.h2Permit.cardCode), + CertFieldRow('检验日期', cd.h2Permit.inspectDate) + ]), + CertSectionCard('加氢卡', cd.h2Card.img, [ + CertFieldRow('加氢卡对应加氢站', cd.h2Card.stationName) + ]), + CertSectionCard('安全阀', cd.safetyValve.img, [ + CertFieldRow('检验日期', cd.safetyValve.inspectDate), + CertFieldRow('检验周期', cd.safetyValve.cycle), + CertFieldRow('安全阀检测有效期', cd.safetyValve.validUntil) + ]), + CertSectionCard('压力表', cd.pressureGauge.img, [ + CertFieldRow('检验日期', cd.pressureGauge.inspectDate), + CertFieldRow('检验周期', cd.pressureGauge.cycle), + CertFieldRow('压力表检测有效期', cd.pressureGauge.gaugeValidUntil) + ]), + CertSectionCard('氢气瓶', cd.h2Cylinder.img, [ + CertFieldRow('气瓶厂家', cd.h2Cylinder.vendor), + CertFieldRow('检验日期', cd.h2Cylinder.inspectDate), + CertFieldRow('检验周期', cd.h2Cylinder.cycle), + CertFieldRow('氢瓶检测有效期', cd.h2Cylinder.cylinderValidUntil) + ]) + ); + var tabItems = [ { key: 'model', @@ -193,19 +660,478 @@ const Component = function () { ) ) }, - { key: 'equip', label: '后装设备', children: React.createElement('div', { style: { padding: 24, color: '#999' } }, '暂无数据') }, - { key: 'license', label: '证照信息', children: React.createElement('div', { style: { padding: 24, color: '#999' } }, '暂无数据') }, - { key: 'lease', label: '租赁记录', children: React.createElement('div', { style: { padding: 24, color: '#999' } }, '暂无数据') }, + { + key: 'equip', + label: '后装设备', + children: React.createElement('div', { style: { padding: '0 4px' } }, + React.createElement(Card, { size: 'small', style: { marginBottom: 16 } }, + React.createElement('div', { style: { display: 'grid', gridTemplateColumns: 'repeat(2, 1fr)', gap: '16px 24px', maxWidth: 900, alignItems: 'start' } }, + React.createElement('div', { style: filterItemStyle }, + React.createElement('div', { style: filterLabelStyle }, '安装时间'), + React.createElement(RangePicker, { + style: { width: '100%' }, + value: rearDraft.installRange, + onChange: function (v) { setRearDraft(function (p) { return Object.assign({}, p, { installRange: v }); }); }, + placeholder: ['开始日期', '结束日期'] + }) + ), + React.createElement('div', { style: filterItemStyle }, + React.createElement('div', { style: filterLabelStyle }, '设备类型'), + React.createElement(Select, { + placeholder: '请选择设备类型', + style: { width: '100%' }, + value: rearDraft.deviceType, + onChange: function (v) { setRearDraft(function (p) { return Object.assign({}, p, { deviceType: v }); }); }, + allowClear: true, + options: rearDeviceTypeOptions + }) + ) + ), + React.createElement('div', { style: { display: 'flex', justifyContent: 'flex-end', gap: 8 } }, + React.createElement(Button, { onClick: function () { + var empty = { installRange: null, deviceType: undefined }; + setRearDraft(empty); + setRearApplied(empty); + } }, '重置'), + React.createElement(Button, { type: 'primary', onClick: function () { setRearApplied(Object.assign({}, rearDraft)); } }, '查询') + ) + ), + React.createElement(Table, { + size: 'small', + rowKey: 'key', + bordered: true, + dataSource: rearFiltered, + columns: [ + { title: '设备类型', dataIndex: 'deviceType', key: 'deviceType', width: 140 }, + { title: '供应商', dataIndex: 'supplier', key: 'supplier', width: 200, ellipsis: true }, + { title: '类型', dataIndex: 'actionType', key: 'actionType', width: 90 }, + { title: '安装/拆卸时间', dataIndex: 'actionTime', key: 'actionTime', width: 170, render: function (tv) { return fmtRearActionTime(tv); } }, + { title: '操作人', dataIndex: 'operator', key: 'operator', width: 100 } + ], + scroll: { x: 800 }, + pagination: { + pageSize: 10, + showSizeChanger: true, + showQuickJumper: true, + showTotal: function (t) { return '共 ' + t + ' 条'; } + } + }) + ) + }, + { key: 'license', label: '证照管理', children: licenseManagementTabContent }, + { + key: 'lease', + label: '租赁记录', + children: React.createElement('div', { style: { padding: '0 4px' } }, + React.createElement(Card, { size: 'small', style: { marginBottom: 16 } }, + React.createElement('div', { style: { display: 'grid', gridTemplateColumns: 'repeat(3, 1fr)', gap: '16px 24px', alignItems: 'start' } }, + React.createElement('div', { style: filterItemStyle }, + React.createElement('div', { style: filterLabelStyle }, '合同编码'), + React.createElement(Select, { + placeholder: '请输入或选择合同编码', + style: { width: '100%' }, + value: leaseDraft.contractCode, + onChange: function (v) { setLeaseDraft(function (p) { return Object.assign({}, p, { contractCode: v }); }); }, + allowClear: true, + showSearch: true, + options: leaseContractOptions, + filterOption: filterOption + }) + ), + React.createElement('div', { style: filterItemStyle }, + React.createElement('div', { style: filterLabelStyle }, '项目名称'), + React.createElement(Select, { + placeholder: '请输入或选择项目名称', + style: { width: '100%' }, + value: leaseDraft.projectName, + onChange: function (v) { setLeaseDraft(function (p) { return Object.assign({}, p, { projectName: v }); }); }, + allowClear: true, + showSearch: true, + options: leaseProjectOptions, + filterOption: filterOption + }) + ), + React.createElement('div', { style: filterItemStyle }, + React.createElement('div', { style: filterLabelStyle }, '客户名称'), + React.createElement(Select, { + placeholder: '请输入或选择客户名称', + style: { width: '100%' }, + value: leaseDraft.customerName, + onChange: function (v) { setLeaseDraft(function (p) { return Object.assign({}, p, { customerName: v }); }); }, + allowClear: true, + showSearch: true, + options: leaseCustomerOptions, + filterOption: filterOption + }) + ) + ), + React.createElement('div', { style: { display: 'flex', justifyContent: 'flex-end', gap: 8 } }, + React.createElement(Button, { onClick: function () { + var empty = { contractCode: undefined, projectName: undefined, customerName: undefined }; + setLeaseDraft(empty); + setLeaseApplied(empty); + } }, '重置'), + React.createElement(Button, { type: 'primary', onClick: function () { setLeaseApplied(Object.assign({}, leaseDraft)); } }, '查询') + ) + ), + React.createElement(Table, { + size: 'small', + rowKey: 'key', + bordered: true, + dataSource: leaseFiltered, + columns: [ + { title: '合同编码', dataIndex: 'contractCode', key: 'contractCode', width: 180, ellipsis: true }, + { title: '项目名称', dataIndex: 'projectName', key: 'projectName', width: 160, ellipsis: true }, + { title: '客户名称', dataIndex: 'customerName', key: 'customerName', width: 200, ellipsis: true }, + { title: '交车日期', dataIndex: 'deliveryDate', key: 'deliveryDate', width: 120, render: function (tv) { return fmtDateYMD(tv); } }, + { title: '交车人', dataIndex: 'deliveryPerson', key: 'deliveryPerson', width: 100 }, + { title: '还车日期', dataIndex: 'returnDate', key: 'returnDate', width: 120, render: function (tv) { return fmtDateYMD(tv); } }, + { title: '还车人', dataIndex: 'returnPerson', key: 'returnPerson', width: 100, render: function (tv) { return (tv && String(tv) !== '-') ? tv : '-'; } } + ], + scroll: { x: 1100 }, + pagination: { + pageSize: 10, + showSizeChanger: true, + showQuickJumper: true, + showTotal: function (t) { return '共 ' + t + ' 条'; } + } + }) + ) + }, { key: 'insurance', label: '保险记录', children: React.createElement('div', { style: { padding: 24, color: '#999' } }, '暂无数据') }, { key: 'repair', label: '维修记录', children: React.createElement('div', { style: { padding: 24, color: '#999' } }, '暂无数据') }, { key: 'maintain', label: '保养记录', children: React.createElement('div', { style: { padding: 24, color: '#999' } }, '暂无数据') }, - { key: 'accident', label: '事故记录', children: React.createElement('div', { style: { padding: 24, color: '#999' } }, '暂无数据') }, + { + key: 'accident', + label: '事故记录', + children: React.createElement('div', { style: { padding: '0 4px' } }, + React.createElement(Card, { size: 'small', style: { marginBottom: 16 } }, + React.createElement('div', { style: { display: 'grid', gridTemplateColumns: 'repeat(2, 1fr)', gap: '16px 24px', maxWidth: 900, alignItems: 'start' } }, + React.createElement('div', { style: filterItemStyle }, + React.createElement('div', { style: filterLabelStyle }, '事故时间'), + React.createElement(RangePicker, { + style: { width: '100%' }, + value: accidentDraft.accidentTimeRange, + onChange: function (v) { setAccidentDraft(function (p) { return Object.assign({}, p, { accidentTimeRange: v }); }); }, + placeholder: ['开始日期', '结束日期'] + }) + ), + React.createElement('div', { style: filterItemStyle }, + React.createElement('div', { style: filterLabelStyle }, '客户名称'), + React.createElement(Select, { + placeholder: '请输入或选择客户名称', + style: { width: '100%' }, + value: accidentDraft.customerName, + onChange: function (v) { setAccidentDraft(function (p) { return Object.assign({}, p, { customerName: v }); }); }, + allowClear: true, + showSearch: true, + options: accidentCustomerOptions, + filterOption: filterOption + }) + ) + ), + React.createElement('div', { style: { display: 'flex', justifyContent: 'flex-end', gap: 8 } }, + React.createElement(Button, { onClick: function () { + var empty = { accidentTimeRange: null, customerName: undefined }; + setAccidentDraft(empty); + setAccidentApplied(empty); + } }, '重置'), + React.createElement(Button, { type: 'primary', onClick: function () { setAccidentApplied(Object.assign({}, accidentDraft)); } }, '查询') + ) + ), + React.createElement(Table, { + size: 'small', + rowKey: 'key', + bordered: true, + dataSource: accidentFiltered, + columns: [ + { title: '事故编码', dataIndex: 'accidentCode', key: 'accidentCode', width: 150, ellipsis: true }, + { title: '事故时间', dataIndex: 'accidentTime', key: 'accidentTime', width: 110, render: function (tv) { return fmtDateYMD(tv); } }, + { title: '事故地点', dataIndex: 'location', key: 'location', width: 220, ellipsis: true }, + { title: '事故类型', dataIndex: 'accidentType', key: 'accidentType', width: 100 }, + { title: '客户名称', dataIndex: 'customerName', key: 'customerName', width: 200, ellipsis: true }, + { title: '我方定损金额', dataIndex: 'ourLossAmount', key: 'ourLossAmount', width: 120, render: function (tv) { return cellOrDash(tv); } }, + { title: '对方定损金额', dataIndex: 'otherLossAmount', key: 'otherLossAmount', width: 120, render: function (tv) { return cellOrDash(tv); } }, + { title: '责任划分', dataIndex: 'liability', key: 'liability', width: 90 }, + { title: '事故状态', dataIndex: 'status', key: 'status', width: 90 }, + { title: '结案时间', dataIndex: 'closeTime', key: 'closeTime', width: 110, render: function (tv) { return fmtDateYMD(tv); } }, + { title: '其他费用', dataIndex: 'otherFee', key: 'otherFee', width: 100, render: function (tv) { return cellOrDash(tv); } }, + { title: '备注', dataIndex: 'remark', key: 'remark', width: 160, ellipsis: true, render: function (tv) { return cellOrDash(tv); } } + ], + scroll: { x: 1800 }, + pagination: { + pageSize: 10, + showSizeChanger: true, + showQuickJumper: true, + showTotal: function (t) { return '共 ' + t + ' 条'; } + } + }) + ) + }, { key: 'fault', label: '故障记录', children: React.createElement('div', { style: { padding: 24, color: '#999' } }, '暂无数据') }, - { key: 'violation', label: '违章记录', children: React.createElement('div', { style: { padding: 24, color: '#999' } }, '暂无数据') }, - { key: 'change', label: '异动记录', children: React.createElement('div', { style: { padding: 24, color: '#999' } }, '暂无数据') }, - { key: 'transfer', label: '调拨记录', children: React.createElement('div', { style: { padding: 24, color: '#999' } }, '暂无数据') }, - { key: 'prep', label: '整备记录', children: React.createElement('div', { style: { padding: 24, color: '#999' } }, '暂无数据') }, - { key: 'inspect', label: '抽检记录', children: React.createElement('div', { style: { padding: 24, color: '#999' } }, '暂无数据') } + { + key: 'violation', + label: '违章记录', + children: React.createElement('div', { style: { padding: '0 4px' } }, + React.createElement(Card, { size: 'small', style: { marginBottom: 16 } }, + React.createElement('div', { style: { display: 'grid', gridTemplateColumns: 'repeat(3, 1fr)', gap: '16px 24px', alignItems: 'start' } }, + React.createElement('div', { style: filterItemStyle }, + React.createElement('div', { style: filterLabelStyle }, '违法时间'), + React.createElement(RangePicker, { + style: { width: '100%' }, + value: violationDraft.violationTimeRange, + onChange: function (v) { setViolationDraft(function (p) { return Object.assign({}, p, { violationTimeRange: v }); }); }, + placeholder: ['开始日期', '结束日期'] + }) + ), + React.createElement('div', { style: filterItemStyle }, + React.createElement('div', { style: filterLabelStyle }, '缴费状态'), + React.createElement(Select, { + placeholder: '请选择缴费状态', + style: { width: '100%' }, + value: violationDraft.payStatus, + onChange: function (v) { setViolationDraft(function (p) { return Object.assign({}, p, { payStatus: v }); }); }, + allowClear: true, + options: violationPayStatusOptions + }) + ), + React.createElement('div', { style: filterItemStyle }, + React.createElement('div', { style: filterLabelStyle }, '违章客户'), + React.createElement(Select, { + placeholder: '请输入或选择违章客户', + style: { width: '100%' }, + value: violationDraft.violationCustomer, + onChange: function (v) { setViolationDraft(function (p) { return Object.assign({}, p, { violationCustomer: v }); }); }, + allowClear: true, + showSearch: true, + options: violationCustomerOptions, + filterOption: filterOption + }) + ) + ), + React.createElement('div', { style: { display: 'flex', justifyContent: 'flex-end', gap: 8 } }, + React.createElement(Button, { onClick: function () { + var empty = { violationTimeRange: null, payStatus: undefined, violationCustomer: undefined }; + setViolationDraft(empty); + setViolationApplied(empty); + } }, '重置'), + React.createElement(Button, { type: 'primary', onClick: function () { setViolationApplied(Object.assign({}, violationDraft)); } }, '查询') + ) + ), + React.createElement(Table, { + size: 'small', + rowKey: 'key', + bordered: true, + dataSource: violationFiltered, + columns: [ + { title: '违章编码', dataIndex: 'violationCode', key: 'violationCode', width: 150, ellipsis: true }, + { title: '违法行为', dataIndex: 'violationBehavior', key: 'violationBehavior', width: 140, ellipsis: true }, + { title: '违法时间', dataIndex: 'violationTime', key: 'violationTime', width: 110, render: function (tv) { return fmtDateYMD(tv); } }, + { title: '罚款金额', dataIndex: 'fineAmount', key: 'fineAmount', width: 100, render: function (tv) { return cellOrDash(tv); } }, + { title: '缴费状态', dataIndex: 'payStatus', key: 'payStatus', width: 90 }, + { title: '计分值', dataIndex: 'points', key: 'points', width: 80 }, + { title: '是否处理', dataIndex: 'processed', key: 'processed', width: 90 }, + { title: '违章客户', dataIndex: 'violationCustomer', key: 'violationCustomer', width: 220, ellipsis: true }, + { + title: '违章照片', + key: 'photo', + width: 100, + render: function (_, r) { + if (r.photo) { + return React.createElement(Button, { type: 'link', size: 'small', onClick: function () { message.info('预览违章照片(原型)'); } }, '查看'); + } + return '-'; + } + }, + { title: '备注', dataIndex: 'remark', key: 'remark', width: 140, ellipsis: true, render: function (tv) { return cellOrDash(tv); } } + ], + scroll: { x: 1500 }, + pagination: { + pageSize: 10, + showSizeChanger: true, + showQuickJumper: true, + showTotal: function (t) { return '共 ' + t + ' 条'; } + } + }) + ) + }, + { + key: 'change', + label: '异动记录', + children: React.createElement('div', { style: { padding: '0 4px' } }, + React.createElement(Card, { size: 'small', style: { marginBottom: 16 } }, + React.createElement('div', { style: { display: 'grid', gridTemplateColumns: 'repeat(3, 1fr)', gap: '16px 24px', alignItems: 'start' } }, + React.createElement('div', { style: filterItemStyle }, + React.createElement('div', { style: filterLabelStyle }, '异动开始日期'), + React.createElement(RangePicker, { + style: { width: '100%' }, + value: moveRecordDraft.moveStartRange, + onChange: function (v) { setMoveRecordDraft(function (p) { return Object.assign({}, p, { moveStartRange: v }); }); }, + placeholder: ['开始日期', '结束日期'] + }) + ), + React.createElement('div', { style: filterItemStyle }, + React.createElement('div', { style: filterLabelStyle }, '异动目的地'), + React.createElement(Select, { + placeholder: '请选择异动目的地', + style: { width: '100%' }, + value: moveRecordDraft.destination, + onChange: function (v) { setMoveRecordDraft(function (p) { return Object.assign({}, p, { destination: v }); }); }, + allowClear: true, + options: moveDestinationOptions + }) + ), + React.createElement('div', { style: filterItemStyle }, + React.createElement('div', { style: filterLabelStyle }, '异动类型'), + React.createElement(Select, { + placeholder: '请选择异动类型', + style: { width: '100%' }, + value: moveRecordDraft.moveType, + onChange: function (v) { setMoveRecordDraft(function (p) { return Object.assign({}, p, { moveType: v }); }); }, + allowClear: true, + options: moveTypeFilterOptions + }) + ) + ), + React.createElement('div', { style: { display: 'flex', justifyContent: 'flex-end', gap: 8 } }, + React.createElement(Button, { onClick: function () { + var empty = { moveStartRange: null, destination: undefined, moveType: undefined }; + setMoveRecordDraft(empty); + setMoveRecordApplied(empty); + } }, '重置'), + React.createElement(Button, { type: 'primary', onClick: function () { setMoveRecordApplied(Object.assign({}, moveRecordDraft)); } }, '查询') + ) + ), + React.createElement(Table, { + size: 'small', + rowKey: 'key', + bordered: true, + dataSource: moveRecordFiltered, + columns: [ + { title: '异动开始日期', dataIndex: 'moveStartAt', key: 'moveStartAt', width: 160, render: function (tv) { return fmtRearActionTime(tv); } }, + { title: '异动预计结束日期', dataIndex: 'moveEndExpectedAt', key: 'moveEndExpectedAt', width: 170, render: function (tv) { return fmtRearActionTime(tv); } }, + { title: '审批状态', dataIndex: 'approvalStatus', key: 'approvalStatus', width: 100 }, + { title: '异动目的地', dataIndex: 'destination', key: 'destination', width: 100 }, + { title: '目的地名称', dataIndex: 'destinationName', key: 'destinationName', width: 180, ellipsis: true }, + { title: '异动类型', dataIndex: 'moveType', key: 'moveType', width: 90 }, + { title: '预计异动里程(km)', dataIndex: 'expectedMileageKm', key: 'expectedMileageKm', width: 150 }, + { title: '异动开始里程(km)', dataIndex: 'startMileageKm', key: 'startMileageKm', width: 150 }, + { title: '异动开始电量(kWh)', dataIndex: 'startElectricKwh', key: 'startElectricKwh', width: 150 }, + { + title: '异动开始氢量', + key: 'startHydrogen', + width: 130, + render: function (_, r) { + var u = r.h2Unit || ''; + return (r.startHydrogen != null && r.startHydrogen !== '') ? String(r.startHydrogen) + (u ? ' ' + u : '') : '-'; + } + }, + { title: '创建人', dataIndex: 'creatorName', key: 'creatorName', width: 100 }, + { title: '创建时间', dataIndex: 'createTime', key: 'createTime', width: 160, render: function (tv) { return fmtRearActionTime(tv); } } + ], + scroll: { x: 2000 }, + pagination: { + pageSize: 10, + showSizeChanger: true, + showQuickJumper: true, + showTotal: function (t) { return '共 ' + t + ' 条'; } + } + }) + ) + }, + { + key: 'transfer', + label: '调拨记录', + children: React.createElement('div', { style: { padding: '0 4px' } }, + React.createElement(Card, { size: 'small', style: { marginBottom: 16 } }, + React.createElement('div', { style: { display: 'grid', gridTemplateColumns: 'repeat(3, 1fr)', gap: '16px 24px', alignItems: 'start' } }, + React.createElement('div', { style: filterItemStyle }, + React.createElement('div', { style: filterLabelStyle }, '调拨日期'), + React.createElement(RangePicker, { + style: { width: '100%' }, + value: transferDraft.transferDateRange, + onChange: function (v) { setTransferDraft(function (p) { return Object.assign({}, p, { transferDateRange: v }); }); }, + placeholder: ['开始日期', '结束日期'] + }) + ), + React.createElement('div', { style: filterItemStyle }, + React.createElement('div', { style: filterLabelStyle }, '调拨人'), + React.createElement(Select, { + placeholder: '请输入或选择调拨人', + style: { width: '100%' }, + value: transferDraft.transferPerson, + onChange: function (v) { setTransferDraft(function (p) { return Object.assign({}, p, { transferPerson: v }); }); }, + allowClear: true, + showSearch: true, + options: transferPersonOptions, + filterOption: filterOption + }) + ), + React.createElement('div', { style: filterItemStyle }, + React.createElement('div', { style: filterLabelStyle }, '接收人'), + React.createElement(Select, { + placeholder: '请输入或选择接收人', + style: { width: '100%' }, + value: transferDraft.receivePerson, + onChange: function (v) { setTransferDraft(function (p) { return Object.assign({}, p, { receivePerson: v }); }); }, + allowClear: true, + showSearch: true, + options: transferReceivePersonOptions, + filterOption: filterOption + }) + ) + ), + React.createElement('div', { style: { display: 'flex', justifyContent: 'flex-end', gap: 8 } }, + React.createElement(Button, { onClick: function () { + var empty = { transferDateRange: null, transferPerson: undefined, receivePerson: undefined }; + setTransferDraft(empty); + setTransferApplied(empty); + } }, '重置'), + React.createElement(Button, { type: 'primary', onClick: function () { setTransferApplied(Object.assign({}, transferDraft)); } }, '查询') + ) + ), + React.createElement(Table, { + size: 'small', + rowKey: 'key', + bordered: true, + dataSource: transferFiltered, + columns: [ + { title: '调拨日期', dataIndex: 'transferDate', key: 'transferDate', width: 160, render: function (tv) { return fmtRearActionTime(tv); } }, + { title: '出发区域', dataIndex: 'departRegionText', key: 'departRegionText', width: 130 }, + { title: '调拨人', dataIndex: 'transferPerson', key: 'transferPerson', width: 90 }, + { title: '接收区域', dataIndex: 'receiveRegionText', key: 'receiveRegionText', width: 130 }, + { title: '接收人', dataIndex: 'receivePerson', key: 'receivePerson', width: 90 }, + { title: '审批状态', dataIndex: 'approvalStatus', key: 'approvalStatus', width: 100 }, + { title: '调拨方式', dataIndex: 'method', key: 'method', width: 110 }, + { title: '调拨原因', dataIndex: 'reason', key: 'reason', width: 160, ellipsis: true }, + { title: '车辆类型', dataIndex: 'vehicleType', key: 'vehicleType', width: 100 }, + { title: '品牌', dataIndex: 'brand', key: 'brand', width: 90 }, + { title: '型号', dataIndex: 'model', key: 'model', width: 100, ellipsis: true }, + { title: '运输方名称', dataIndex: 'carrierName', key: 'carrierName', width: 140, ellipsis: true, render: function (tv) { return (tv && String(tv) !== '-') ? tv : '—'; } }, + { title: '出发里程(km)', dataIndex: 'departMileageKm', key: 'departMileageKm', width: 130 }, + { + title: '出发氢量', + key: 'departHydrogen', + width: 110, + render: function (_, r) { + var u = r.h2Unit || ''; + return (r.departHydrogen != null && r.departHydrogen !== '') ? String(r.departHydrogen) + (u ? u : '') : '—'; + } + }, + { title: '出发电量(kWh)', dataIndex: 'departElectricKwh', key: 'departElectricKwh', width: 130 }, + { title: '出发停车场', dataIndex: 'departParking', key: 'departParking', width: 150, ellipsis: true }, + { title: '创建日期', dataIndex: 'createDate', key: 'createDate', width: 160, render: function (tv) { return fmtRearActionTime(tv); } } + ], + scroll: { x: 2400 }, + pagination: { + pageSize: 10, + showSizeChanger: true, + showQuickJumper: true, + showTotal: function (t) { return '共 ' + t + ' 条'; } + } + }) + ) + } ]; var breadcrumbNodes = [ diff --git a/web端/需求说明/运维管理-车务管理/异动-新增 b/web端/需求说明/运维管理-车务管理/异动-新增 new file mode 100644 index 0000000..96c6512 --- /dev/null +++ b/web端/需求说明/运维管理-车务管理/异动-新增 @@ -0,0 +1,25 @@ +一个「数字化资产ONEOS运管平台」中的「异动管理」「新增」模块 +#面包屑:运维管理-车辆业务-异动管理-新增 + +1.异动情况; +1.1.异动开始日期:必填项,日期选择器,格式为:YYYY-MM-DD HH:MM; +1.2.异动预计结束日期:必填项,日期选择器,格式为:YYYY-MM-DD HH:MM; +1.3.异动目的地:必填项,选择器,选项为:停车场、维修站、其他; +2.4.目的地名称:必填项,如异动目的地为停车场,则此处为停车场(选择器),如异动目的地为维修站,则此处为维修站(选择器),如异动目的地为其他,则此处为输入框(自定义输入); +2.5.异动类型:必填项,选择器,选项为:维修、保养、年审、其他; +2.6.预计异动里程:输入框,支持2位小数输入,后缀为km; +2.7.备注:文本域,支持自定义输入; + +2.车辆信息: +2.1.车牌号:显示车牌号,支持输入框模糊搜索下拉匹配对应选项; +2.2.车辆类型:根据所选车辆类型自动反写,默认提示为请先选择车辆; +2.3.品牌:根据所选车辆品牌自动反写,默认提示为请先选择车辆; +2.4.型号:根据所选车辆型号自动反写,默认提示为请先选择车辆; +2.5.出发停车场:根据所选车辆出发时停车场自动反写,默认提示为请先选择车辆; +2.6.异动开始里程:必填项,输入框,精确至2位小数,后缀为km; +2.7.异动开始氢量:必填项,输入框,精确至2位小数,后缀为%或MPa,根据所选车辆型号中获取; +2.8.异动开始电量:必填项,输入框,精确至2位小数,后缀为kWh; +2.9.操作:删除; +2.10.新增一行:铺满整行; + +3.底部为提交审核、保存、取消; \ No newline at end of file diff --git a/web端/需求说明/运维管理-车务管理/异动管理 b/web端/需求说明/运维管理-车务管理/异动管理 new file mode 100644 index 0000000..5a50f4b --- /dev/null +++ b/web端/需求说明/运维管理-车务管理/异动管理 @@ -0,0 +1,28 @@ +一个「数字化资产ONEOS运管平台」中的「异动管理」模块 +#面包屑:运维管理-车辆业务-异动管理 + +1.筛选; +1.1.异动开始日期:日期选择器,输入框支持双日历选择开始-结束时间; +1.2.异动类型:选择器,选项包括:维修、保养、年审、其他,支持多选; +1.3.车牌号:选择器,输入框支持模糊搜索下拉匹配结果; +1.4.右侧为查询、重置按钮; + +2.列表: +2.1.异动开始日期:显示车辆异动开始日期,格式为:YYYY-MM-DD HH:MM; +2.2.异动预计结束日期:显示车辆异动结束日期,格式为:YYYY-MM-DD HH:MM; +2.3.审批状态:分为:待提交、审批中、审批完成、驳回、撤回; +2.4.异动目的地:显示车辆异动目的地,选项包括:停车场、维修站、其他; +2.5.目的地名称:显示车辆异动目的地名称; +2.6.异动类型:显示车辆异动类型,选项包括:维修、保养、年审、其他; +2.7.预计异动里程(km):显示车辆预计异动里程; +2.8.车牌号:显示车牌号; +2.9.异动开始里程(km):显示车辆异动开始里程; +2.10.异动开始电量(kWh):显示车辆异动开始电量; +2.11.异动开始氢量;显示车辆异动开始氢量,带单位,单位根据型号参数表获取,分为%和MPa; +2.12.创建人:显示发起人姓名; +2.13.创建时间:显示发起时间,格式为:YYYY-MM-DD HH:MM; +2.14.操作:查看、编辑; + 2.14.1.查看:点击跳转异动-查看页; + 2.14.2.编辑:点击跳转异动-编辑页,只有审批状态为:待提交、驳回、撤回时显示编辑; + +3.列表右下方为分页功能,支持单页显示条数设置; \ No newline at end of file diff --git a/web端/需求说明/运维管理-车务管理/调拨管理 b/web端/需求说明/运维管理-车务管理/调拨管理 new file mode 100644 index 0000000..5d0577a --- /dev/null +++ b/web端/需求说明/运维管理-车务管理/调拨管理 @@ -0,0 +1,64 @@ +一个「数字化资产ONEOS运管平台」中的「调拨管理」模块 +#面包屑:运维管理-车辆业务-调拨管理 +1.筛选: +1.1.调拨日期:日期选择器,支持单输入框双日历进行开始-结束时间搜索; +1.2.调拨人:选择器,支持输入框输入内容模糊搜索下拉选择对应调拨人,调拨人来自用户表; +1.3.接收日期:日期选择器,支持单输入框双日历进行开始-结束时间搜索; +1.4.接收人:选择器,支持输入框输入内容模糊搜索下拉选择对应接收人,接收人来自用户表; +1.5.车牌号:选择器,支持输入框输入内容模糊搜索下拉选择车牌号; +1.6.出发区域:级联地区选择器,省-市2级; +1.7.调拨区域:级联地区选择器,省-市2级; +1.8.调拨方式:选择器,选项为:第三方运输、司机驾驶; +1.9.审批状态:选择器,选项为:待提交、审批中、审批完成、审批驳回、撤回; + +2.列表:分为进行中、历史记录2个tab;tab最右侧为新增、导出; +2.1.进行中: +2.1.1.调拨日期:显示调拨日期,格式为:YYYY-MM-DD HH:MM; +2.1.2.出发区域:显示出发省-市,根据车辆出发时停车场区域获取; +2.1.3.调拨人:显示调拨人姓名; +2.1.4.接收区域:显示接受省-市; +2.1.5.接收人:显示接收人姓名; +2.1.6.审批状态:待提交、审批中、审批完成、驳回、撤回; +2.1.7.调拨方式:显示调拨方式,分为第三方运输、司机驾驶; +2.1.8.调拨原因:显示调拨原因; +2.1.9.车牌号:显示调拨车牌号; +2.1.10.车辆类型:显示调拨车辆对应类型; +2.1.11.品牌:显示调拨车辆对应品牌; +2.1.12.型号:显示调拨车辆对应型号; +2.1.13.运输方名称:显示调拨车辆对应运输方信息; +2.1.14.出发里程(km):显示调拨车辆对应出发里程; +2.1.15.出发氢量:显示调拨车辆对应出发氢量,带单位(单位根据该型号型号参数下仪表盘单位) +2.1.16.出发电量(kWh):显示调拨车辆对应出发电量; +2.1.17.出发停车场:显示调拨车辆出发停车场名称; +2.1.18.创建日期:显示调拨申请创建日期,格式为:YYYY-MM-DD HH:MM; +2.1.19.操作:查看、编辑、接收记录、撤回; + 2.1.19.1.查看:点击跳转调拨管理-查看页; + 2.1.19.2.编辑:点击跳转调拨管理-编辑页,只有待提交、审批驳回、撤回状态才显示编辑; + 2.1.19.3.接收记录:点击跳转调拨管理-接收记录页,只有审批状态为审批完成时才显示接收记录; + 2.1.19.4.撤回:点击进行二次确认,确认后审批状态修改为撤回,只有审批状态为审批中时才显示撤回; + +2.2.历史记录: +2.2.1.调拨日期:显示调拨日期,格式为:YYYY-MM-DD HH:MM; +2.2.2.出发区域:显示出发省-市,根据车辆出发时停车场区域获取; +2.2.3.调拨人:显示调拨人姓名; +2.2.4.接收日期:显示接收日期,格式为:YYYY-MM-DD HH:MM; +2.2.5.接收区域:显示接受省-市; +2.2.6.接收人:显示接收人姓名; +2.2.7.审批状态:审核完成; +2.2.8.调拨方式:显示调拨方式,分为第三方运输、司机驾驶; +2.2.9.调拨原因:显示调拨原因; +2.2.10.车牌号:显示调拨车牌号; +2.2.11.车辆类型:显示调拨车辆对应类型; +2.2.12.品牌:显示调拨车辆对应品牌; +2.2.13.型号:显示调拨车辆对应型号; +2.2.14.运输方名称:显示调拨车辆对应运输方信息; +2.2.15.出发里程(km):显示调拨车辆对应出发里程; +2.2.16.接收里程(km):显示调拨车辆对应接收里程; +2.2.17.出发氢量:显示调拨车辆对应出发氢量,带单位(单位根据该型号型号参数下仪表盘单位); +2.2.18.接收氢量:显示调拨车辆对应接收氢量,带单位(单位根据该型号型号参数下仪表盘单位); +2.2.19.出发电量(kWh):显示调拨车辆对应出发电量; +2.2.20.接收电量(kWh):显示调拨车辆对应接收电量; +2.2.21.出发停车场:显示调拨车辆出发停车场名称; +2.2.22.创建日期:显示调拨申请创建日期,格式为:YYYY-MM-DD HH:MM; +2.2.23.操作:查看; + 2.1.17.1.查看:点击跳转调拨管理-查看页; \ No newline at end of file diff --git a/web端/需求说明/运维管理-车务管理/调拨管理-接收记录 b/web端/需求说明/运维管理-车务管理/调拨管理-接收记录 new file mode 100644 index 0000000..e805b2a --- /dev/null +++ b/web端/需求说明/运维管理-车务管理/调拨管理-接收记录 @@ -0,0 +1,28 @@ +一个「数字化资产ONEOS运管平台」中的「调拨管理」「接收记录」模块 +#面包屑:运维管理-车辆业务-调拨管理-接收记录 +页面采用多个卡片的方式进行展示 +1.调拨情况: +1.1.调拨日期:显示调拨日期,格式为:YYYY-MM-DD; +1.2.出发区域:显示出发区域,格式为省-市2级; +1.3.接收区域:显示接收区域,格式为省-市2级; +1.4.接收人:显示接收人姓名; +1.5.调拨方式:显示调拨方式,选项为:第三方运输、司机驾驶; +1.6.调拨原因:显示调拨原因; +1.7.运输方名称:显示运输方名称; +1.8.运输方联系方式:显示运输方联系方式; +1.9.接收日期:日期选择器,精确至天; + +2.调拨车辆清单; +#以列表方式展示: +2.1.车牌号:显示车牌号,支持输入框模糊搜索下拉匹配对应选项; +2.2.车辆类型:根据所选车辆类型自动反写,默认提示为请先选择车辆; +2.3.品牌:根据所选车辆品牌自动反写,默认提示为请先选择车辆; +2.4.型号:根据所选车辆型号自动反写,默认提示为请先选择车辆; +2.5.出发停车场:根据所选车辆出发时停车场自动反写,默认提示为请先选择车辆; +2.6.出发里程:显示出发里程,输入框,精确至2位小数,后缀为km; +2.7.接收里程:必填项,输入框,精确至2位小数,后缀为km; +2.8.出发氢量:显示出发氢量,输入框,精确至2位小数,后缀为%或MPa,根据所选车辆型号中获取; +2.9.接收氢量:必填项,输入框,精确至2位小数,后缀为%或MPa,根据所选车辆型号中获取; +2.10.出发电量:显示出发电量,输入框,精确至2位小数,后缀为kWh; +2.11.接收电量:必填项,输入框,精确至2位小数,后缀为kWh; +2.12.操作:无; \ No newline at end of file diff --git a/web端/需求说明/运维管理-车务管理/调拨管理-新增 b/web端/需求说明/运维管理-车务管理/调拨管理-新增 new file mode 100644 index 0000000..a05e63b --- /dev/null +++ b/web端/需求说明/运维管理-车务管理/调拨管理-新增 @@ -0,0 +1,26 @@ +一个「数字化资产ONEOS运管平台」中的「调拨管理」「新增」模块 +#面包屑:运维管理-车辆业务-调拨管理-新增 +页面采用多个卡片的方式进行展示 +1.调拨情况: +1.1.调拨日期:必填项,日期选择器,精确至天,格式为:YYYY-MM-DD; +1.2.出发区域:必填项,地区选择器,支持省-市2级; +1.3.接收区域:必填项,地区选择器,支持省-市2级; +1.4.接收人:必填项,选择器,支持输入框模糊搜索下拉匹配对应选项,接收人取自用户表所有用户; +1.5.调拨方式:必填项,选择器,默认提示:请选择调拨方式,选项为:第三方运输、司机驾驶; +1.6.调拨原因:必填项,文本域,支持用户自定义输入; +1.7.运输方名称:必填项,输入框,默认提示:请输入运输方名称/司机姓名; +1.8.运输方联系方式:必填项,输入框,默认提示:请输入运输方/司机联系方式; + +2.调拨车辆清单; +#以列表方式展示: +2.1.车牌号:必填项,选择器,支持输入框模糊搜索下拉匹配对应选项; +2.2.车辆类型:根据所选车辆类型自动反写,默认提示为请先选择车辆; +2.3.品牌:根据所选车辆品牌自动反写,默认提示为请先选择车辆; +2.4.型号:根据所选车辆型号自动反写,默认提示为请先选择车辆; +2.5.出发停车场:根据所选车辆出发时停车场自动反写,默认提示为请先选择车辆; +2.6.出发里程:必填项,输入框,精确至2位小数,后缀为km; +2.7.出发氢量:必填项,输入框,精确至2位小数,后缀为%或MPa,根据所选车辆型号中获取; +2.8.出发电量:必填项,输入框,精确至2位小数,后缀为kWh; +2.9.操作:删除 +2.10.底部为新增一行,铺满整行; +需要至少提交一辆车才能完成调拨,否则提交审核时提示:请选择调拨车辆; \ No newline at end of file diff --git a/web端/需求说明/运维管理-车务管理/还车管理 b/web端/需求说明/运维管理-车务管理/还车管理 new file mode 100644 index 0000000..bdb583f --- /dev/null +++ b/web端/需求说明/运维管理-车务管理/还车管理 @@ -0,0 +1,51 @@ +一个「数字化资产ONEOS运管平台」中的「还车管理」模块 +1.面包屑: +1.1.运维管理-车辆业务-还车管理 + +2.筛选: +2.1.合同编码:选择器,默认为所有合同;提示信息为:请输入或选择合同编码,支持从输入框输入内容进行模糊搜索,下拉显示结果; +2.2.项目名称:选择器,默认为所有项目;提示信息为:请输入或选择项目名称,支持从输入框输入内容进行模糊搜索,下拉显示结果; +2.3.客户名称:选择器,默认为所有客户;提示信息为:请输入或选择客户名称,支持从输入框输入内容进行模糊搜索,下拉显示结果; +2.4.车牌号:选择器,支持输入框输入车牌号模糊搜索下拉框匹配结果; +2.5.车辆类型:选择器,显示所有车辆类型,支持多选; +2.6.品牌:选择器,显示所有品牌,支持多选; +2.7.型号:选择器,支持输入框输入型号模糊搜索下拉框匹配结果; +2.7.查询:点击查询,根据单个或多个筛选条件(且)联动表格进行查询; +2.8.重置:点击清空查询条件至默认; + +#列表:分为2个tab:待处理、历史记录;,右侧为导出; +3.待处理: +3.1.交车时间:显示该车辆交车时间,格式为:YYYY-MM-DD HH:MM; +3.2.交车人:显示该车辆交车人姓名; +3.3.车牌号:显示该车辆车牌号; +3.4.车辆类型:显示该车辆车辆类型; +3.5.品牌:显示该车辆品牌; +3.6.型号:显示该车辆型号; +3.7.车辆识别代码:显示该车辆对应车辆识别代码; +3.8.合同编码:显示该车辆对应合同编码; +3.9.客户名称:显示该车辆对应合同中客户名称; +3.10.项目名称:显示该车辆对应合同中项目名称; +3.11.业务部门:显示该车辆对应合同中业务部门; +3.12.业务负责人:显示该车辆对应合同中业务负责人姓名; +3.13.操作:车辆到达、还车; + 3.13.1.车辆到达:点击车辆到达后进行二次确认,提示为:请确认车辆是否到达,点击确认后该按钮变更为还车; + 3.13.2.还车:点击跳转还车管理-还车页; + +4.历史记录: +4.1.交车时间:显示该车辆交车时间,格式为:YYYY-MM-DD HH:MM; +4.2.交车人:显示该车辆交车人姓名; +4.3.还车时间:显示该车辆还车时间,格式为:YYYY-MM-DD HH:MM; +4.4.还车人:显示该车辆交车人姓名; +4.5.车牌号:显示该车辆车牌号; +4.6.车辆类型:显示该车辆车辆类型; +4.7.品牌:显示该车辆品牌; +4.8.型号:显示该车辆型号; +4.9.车辆识别代码:显示该车辆对应车辆识别代码; +4.10.合同编码:显示该车辆对应合同编码; +4.11.客户名称:显示该车辆对应合同中客户名称; +4.12.项目名称:显示该车辆对应合同中项目名称; +4.13.业务部门:显示该车辆对应合同中业务部门; +4.14.业务负责人:显示该车辆对应合同中业务负责人姓名; +4.15.操作:查看; + 4.15.1.查看:点击跳转还车管理-查看; +5.右下方为分页符,支持选择单页显示数据条数; \ No newline at end of file diff --git a/web端/需求说明/运维管理-车务管理/还车管理-查看 b/web端/需求说明/运维管理-车务管理/还车管理-查看 new file mode 100644 index 0000000..90d1a04 --- /dev/null +++ b/web端/需求说明/运维管理-车务管理/还车管理-查看 @@ -0,0 +1,46 @@ +一个「数字化资产ONEOS运管平台」中的「还车管理」「还车」模块 +1.面包屑: +1.1.运维管理-车辆业务-还车管理-还车 + +2.合同信息: +2.1.合同编码:显示该车辆对应合同编码; +2.2.项目名称:显示该车辆对应项目名称; +2.3.客户名称:显示该车辆对应客户名称; +2.4.业务部门:显示该车辆合同对应业务部门; +2.5.业务负责人:显示该车辆合同对应业务负责人; + +3.车辆信息: +3.1.车牌号:显示该车辆车牌号; +3.2.车辆型号:显示该车辆型号; +3.3.品牌:显示该车辆品牌; +3.4.型号:显示该车辆型号; +3.5.交车时间:显示该车辆交车时间,格式为:YYYY-MM-DD HH:MM; +3.6.交车地点:显示该车辆交车地点,格式为:省-市; + +4.还车明细: +4.1.还车人:必填项,输入框,默认显示交车时司机姓名(从OCR自动识别身份证); +4.2.还车人电话:必填项,输入框,默认显示交车时司机手机号(从司机扫码培训时验证的手机号); +4.3.还车人身份证:必填项,输入框,默认显示还车时司机身份证号(从OCR自动识别身份证); +4.4.还车地点:必填项,选择器,选项为停车场、维修站,默认提示:请选择还车地点; +4.5.停车场/维修站:必填项,选择器,选择停车场或维修站;当还车地点为停车场时,字段名称为停车场,当还车地点为维修站时,字段名称为维修站; +4.6.到达时间:必填项,日期选择器,输入框单日历,支持选择年月日,精确到分钟,格式为:YYYY-MM-DD HH:MM; +4.7.备胎照片:左侧为交车时备胎照片(仅查看,支持点击预览),右侧为图片上传按钮,支持单张照片上传,上传后按钮变为图片,支持点击图片预览和右上角删除,图片上传后提示识别中,然后弹出卡片,左侧为图片,右侧为胎纹深度:输入框(自动反写胎纹深度),后缀为mm; +4.8.交车时备胎胎纹深度:输入框(禁用),显示交车时胎纹深度,后缀为mm; +4.9.还车时备胎胎纹深度:输入框,默认提示为请输入备胎胎纹深度,如上传备胎照片并确认后则自动反写OCR识别结果; +4.10.交车里程:输入框(禁用),显示交车时交车里程,后缀为km; +4.11.还车里程:必填项,输入框,支持2位小数输入,后缀为km; +4.12.交车电量:输入框(禁用),显示交车时交车电量,后缀为kWh; +4.13.还车电量:必填项,输入框,支持2位小数输入,后缀为kWh; +4.14.交车氢量:输入框(禁用),显示交车时交车氢量,后缀为MPa或%(根据车辆型号参数列表中仪表盘显示单位显示); +4.15.还车氢量:必填项,输入框,支持2位小数输入,后缀为MPa或%(根据车辆型号参数列表中仪表盘显示单位显示); +4.16.接车服务费:输入框,支持2位小数输入,后缀为元; +4.17.还车检查单:点击弹出抽屉,抽屉显示还车检查项(默认为交车时状态),下方为提交和返回按钮,参照交车管理-交车单-编辑中交车检查单; + +5.还车照片:参照交车管理-交车单-编辑中交车照片,只是所有上传按钮左侧增加交车照片显示(仅查看,支持点击预览); + +所有交车时照片下方增加文字提示:交车时照片 + +4.底部为提交、取消按钮; + 4.1.提交:点击进行二次确认,点击确认完成该车辆还车,并将该记录加入历史记录; + 4.2.保存:点击暂存还车单(不做校验); + 4.2.取消:点击返回还车管理页; \ No newline at end of file