Initial commit: ONE-OS project
Made-with: Cursor
This commit is contained in:
BIN
web端/运维管理/.DS_Store
vendored
Normal file
BIN
web端/运维管理/.DS_Store
vendored
Normal file
Binary file not shown.
1319
web端/运维管理/基本数据维护/停车场管理.jsx
Normal file
1319
web端/运维管理/基本数据维护/停车场管理.jsx
Normal file
File diff suppressed because it is too large
Load Diff
938
web端/运维管理/车辆业务/上牌管理.jsx
Executable file
938
web端/运维管理/车辆业务/上牌管理.jsx
Executable file
@@ -0,0 +1,938 @@
|
||||
// 【重要】必须使用 const Component 作为组件变量名
|
||||
// 车辆上牌管理 - 车辆资产管理后台模块
|
||||
var ARCO_TOKEN = {
|
||||
primary: '#165DFF',
|
||||
primaryHover: '#4080FF',
|
||||
danger: '#F53F3F',
|
||||
success: '#00B42A',
|
||||
neutral1: '#FFFFFF',
|
||||
neutral2: '#F7F8FA',
|
||||
neutral3: '#F2F3F5',
|
||||
neutral4: '#E5E6EB',
|
||||
neutral5: '#C9CDD4',
|
||||
neutral6: '#86909C',
|
||||
neutral7: '#4E5969',
|
||||
neutral8: '#1D2129',
|
||||
border: '#E5E6EB',
|
||||
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',
|
||||
spacing8: '8px',
|
||||
spacing12: '12px',
|
||||
spacing16: '16px',
|
||||
spacing24: '24px',
|
||||
fontSize14: '14px',
|
||||
fontSize16: '16px',
|
||||
fontFamily: '-apple-system, BlinkMacSystemFont, "PingFang SC", "Helvetica Neue", Arial, sans-serif',
|
||||
link: '#165DFF'
|
||||
};
|
||||
|
||||
const Component = function () {
|
||||
var antd = window.antd;
|
||||
var Input = antd.Input;
|
||||
var Select = antd.Select;
|
||||
var Button = antd.Button;
|
||||
var DatePicker = antd.DatePicker;
|
||||
var Table = antd.Table;
|
||||
var Modal = antd.Modal;
|
||||
var message = antd.message;
|
||||
var Option = Select.Option;
|
||||
var Spin = antd.Spin;
|
||||
|
||||
var _useState = React.useState('');
|
||||
var filterDateStart = _useState[0];
|
||||
var setFilterDateStart = _useState[1];
|
||||
|
||||
var _useState2 = React.useState('');
|
||||
var filterDateEnd = _useState2[0];
|
||||
var setFilterDateEnd = _useState2[1];
|
||||
|
||||
var _useState3 = React.useState('');
|
||||
var filterOperator = _useState3[0];
|
||||
var setFilterOperator = _useState3[1];
|
||||
|
||||
var _useState4 = React.useState('');
|
||||
var filterPlateNo = _useState4[0];
|
||||
var setFilterPlateNo = _useState4[1];
|
||||
|
||||
var _useState5 = React.useState('');
|
||||
var filterVin = _useState5[0];
|
||||
var setFilterVin = _useState5[1];
|
||||
|
||||
var _useState5h = React.useState('');
|
||||
var appliedDateStart = _useState5h[0];
|
||||
var setAppliedDateStart = _useState5h[1];
|
||||
var _useState5i = React.useState('');
|
||||
var appliedDateEnd = _useState5i[0];
|
||||
var setAppliedDateEnd = _useState5i[1];
|
||||
var _useState5j = React.useState('');
|
||||
var appliedOperator = _useState5j[0];
|
||||
var setAppliedOperator = _useState5j[1];
|
||||
var _useState5k = React.useState('');
|
||||
var appliedPlateNo = _useState5k[0];
|
||||
var setAppliedPlateNo = _useState5k[1];
|
||||
var _useState5l = React.useState('');
|
||||
var appliedVin = _useState5l[0];
|
||||
var setAppliedVin = _useState5l[1];
|
||||
|
||||
var _useState6 = React.useState(1);
|
||||
var currentPage = _useState6[0];
|
||||
var setCurrentPage = _useState6[1];
|
||||
|
||||
var _useState7 = React.useState(10);
|
||||
var pageSize = _useState7[0];
|
||||
var setPageSize = _useState7[1];
|
||||
|
||||
var _useState9 = React.useState(null);
|
||||
var viewPhotoRecord = _useState9[0];
|
||||
var setViewPhotoRecord = _useState9[1];
|
||||
|
||||
var _useState10 = React.useState(false);
|
||||
var ocrModalVisible = _useState10[0];
|
||||
var setOcrModalVisible = _useState10[1];
|
||||
|
||||
var _useState11 = React.useState(false);
|
||||
var confirmModalVisible = _useState11[0];
|
||||
var setConfirmModalVisible = _useState11[1];
|
||||
|
||||
var _useState12 = React.useState(null);
|
||||
var confirmData = _useState12[0];
|
||||
var setConfirmData = _useState12[1];
|
||||
|
||||
var _useState13 = React.useState([]);
|
||||
var batchConfirmList = _useState13[0];
|
||||
var setBatchConfirmList = _useState13[1];
|
||||
|
||||
var _useState14 = React.useState(0);
|
||||
var batchConfirmIndex = _useState14[0];
|
||||
var setBatchConfirmIndex = _useState14[1];
|
||||
|
||||
var _useState15 = React.useState(false);
|
||||
var isBatchMode = _useState15[0];
|
||||
var setIsBatchMode = _useState15[1];
|
||||
|
||||
var _useState15b = React.useState(0);
|
||||
var batchTotalCount = _useState15b[0];
|
||||
var setBatchTotalCount = _useState15b[1];
|
||||
|
||||
var _useState16 = React.useState('');
|
||||
var confirmVin = _useState16[0];
|
||||
var setConfirmVin = _useState16[1];
|
||||
|
||||
var _useState17 = React.useState('');
|
||||
var confirmPlateNo = _useState17[0];
|
||||
var setConfirmPlateNo = _useState17[1];
|
||||
|
||||
var _useState17a = React.useState('');
|
||||
var confirmScrapDate = _useState17a[0];
|
||||
var setConfirmScrapDate = _useState17a[1];
|
||||
|
||||
var _useState17b = React.useState('');
|
||||
var confirmInspectionExpiry = _useState17b[0];
|
||||
var setConfirmInspectionExpiry = _useState17b[1];
|
||||
|
||||
var _useState18b = React.useState(false);
|
||||
var showRequirementModal = _useState18b[0];
|
||||
var setShowRequirementModal = _useState18b[1];
|
||||
|
||||
var _useState18c = React.useState(false);
|
||||
var batchTaskCardVisible = _useState18c[0];
|
||||
var setBatchTaskCardVisible = _useState18c[1];
|
||||
|
||||
var fileInputRef = React.useRef(null);
|
||||
var batchFullListRef = React.useRef(null);
|
||||
var batchUploadFromCardRef = React.useRef(false);
|
||||
var batchFileInputRef = React.useRef(null);
|
||||
|
||||
var _useState18e = React.useState([]);
|
||||
var batchTaskList = _useState18e[0];
|
||||
var setBatchTaskList = _useState18e[1];
|
||||
|
||||
var mockVehicleList = [
|
||||
{ id: 'v001', frameNo: 'LGW123456', brand: '比亚迪', model: '秦', vehicleType: '轿车' },
|
||||
{ id: 'v002', frameNo: 'LGW789012', brand: '特斯拉', model: 'Model 3', vehicleType: '轿车' },
|
||||
{ id: 'v003', frameNo: 'HZ111222', brand: '小鹏', model: 'P7', vehicleType: '轿车' }
|
||||
];
|
||||
|
||||
var initialRecordList = [
|
||||
{
|
||||
id: 'r001',
|
||||
plateDate: '2025-02-01',
|
||||
operator: '张明',
|
||||
plateNo: '粤A12345',
|
||||
vin: 'LGW123456',
|
||||
vehicleType: '轿车',
|
||||
brand: '比亚迪',
|
||||
model: '秦',
|
||||
photoUrl: 'https://picsum.photos/300/200?random=1'
|
||||
},
|
||||
{
|
||||
id: 'r002',
|
||||
plateDate: '2025-02-03',
|
||||
operator: '王芳',
|
||||
plateNo: '粤A67890',
|
||||
vin: 'LGW789012',
|
||||
vehicleType: '轿车',
|
||||
brand: '特斯拉',
|
||||
model: 'Model 3',
|
||||
photoUrl: 'https://picsum.photos/300/200?random=2'
|
||||
}
|
||||
];
|
||||
|
||||
// 近5条批量上牌任务(时间、照片数量、完成进度);进度100%时有 items 用于「识别」进入确认界面
|
||||
var getInitialBatchTaskList = function () {
|
||||
return [
|
||||
{ id: 'bt1', createTime: '2025-02-12 10:30', photoCount: 3, progress: 100, items: [
|
||||
{ photoUrl: 'https://picsum.photos/300/200?random=b1', vin: 'LGW123456', plateNo: '粤A11111', vehicle: mockVehicleList[0] },
|
||||
{ photoUrl: 'https://picsum.photos/300/200?random=b2', vin: 'LGW789012', plateNo: '粤A22222', vehicle: mockVehicleList[1] },
|
||||
{ photoUrl: 'https://picsum.photos/300/200?random=b3', vin: 'HZ111222', plateNo: '粤A33333', vehicle: mockVehicleList[2] }
|
||||
]},
|
||||
{ id: 'bt2', createTime: '2025-02-12 09:15', photoCount: 5, progress: 100, items: [
|
||||
{ photoUrl: 'https://picsum.photos/300/200?random=b4', vin: 'LGW123456', plateNo: '粤A44444', vehicle: mockVehicleList[0] },
|
||||
{ photoUrl: 'https://picsum.photos/300/200?random=b5', vin: 'LGW789012', plateNo: '粤A55555', vehicle: mockVehicleList[1] }
|
||||
]},
|
||||
{ id: 'bt3', createTime: '2025-02-11 16:20', photoCount: 4, progress: 80, items: null },
|
||||
{ id: 'bt4', createTime: '2025-02-11 14:00', photoCount: 2, progress: 50, items: null },
|
||||
{ id: 'bt5', createTime: '2025-02-10 11:30', photoCount: 6, progress: 30, items: null }
|
||||
];
|
||||
};
|
||||
|
||||
React.useEffect(function () {
|
||||
setBatchTaskList(function (prev) {
|
||||
if (prev.length === 0) return getInitialBatchTaskList();
|
||||
return prev;
|
||||
});
|
||||
}, []);
|
||||
|
||||
var _useState18 = React.useState(initialRecordList);
|
||||
var recordList = _useState18[0];
|
||||
var setRecordList = _useState18[1];
|
||||
|
||||
var getUniqueOperators = function () {
|
||||
var seen = {};
|
||||
var list = [];
|
||||
recordList.forEach(function (r) {
|
||||
if (r.operator && !seen[r.operator]) {
|
||||
seen[r.operator] = true;
|
||||
list.push(r.operator);
|
||||
}
|
||||
});
|
||||
return list.sort();
|
||||
};
|
||||
|
||||
var getUniquePlateNos = function () {
|
||||
var seen = {};
|
||||
var list = [];
|
||||
recordList.forEach(function (r) {
|
||||
if (r.plateNo && !seen[r.plateNo]) {
|
||||
seen[r.plateNo] = true;
|
||||
list.push(r.plateNo);
|
||||
}
|
||||
});
|
||||
return list.sort();
|
||||
};
|
||||
|
||||
var getUniqueVins = function () {
|
||||
var seen = {};
|
||||
var list = [];
|
||||
recordList.forEach(function (r) {
|
||||
if (r.vin && !seen[r.vin]) {
|
||||
seen[r.vin] = true;
|
||||
list.push(r.vin);
|
||||
}
|
||||
});
|
||||
mockVehicleList.forEach(function (v) {
|
||||
if (v.frameNo && !seen[v.frameNo]) {
|
||||
seen[v.frameNo] = true;
|
||||
list.push(v.frameNo);
|
||||
}
|
||||
});
|
||||
return list.sort();
|
||||
};
|
||||
|
||||
var allOperators = getUniqueOperators();
|
||||
var allPlateNos = getUniquePlateNos();
|
||||
var allVins = getUniqueVins();
|
||||
|
||||
var getFilteredList = function () {
|
||||
var list = recordList;
|
||||
if (appliedDateStart) {
|
||||
list = list.filter(function (r) { return r.plateDate >= appliedDateStart; });
|
||||
}
|
||||
if (appliedDateEnd) {
|
||||
list = list.filter(function (r) { return r.plateDate <= appliedDateEnd; });
|
||||
}
|
||||
if (appliedOperator) {
|
||||
list = list.filter(function (r) {
|
||||
return r.operator && r.operator.indexOf(appliedOperator) >= 0;
|
||||
});
|
||||
}
|
||||
if (appliedPlateNo) {
|
||||
list = list.filter(function (r) {
|
||||
return r.plateNo && r.plateNo.indexOf(appliedPlateNo) >= 0;
|
||||
});
|
||||
}
|
||||
if (appliedVin) {
|
||||
list = list.filter(function (r) {
|
||||
return r.vin && r.vin.indexOf(appliedVin) >= 0;
|
||||
});
|
||||
}
|
||||
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);
|
||||
var startIndex = (validPage - 1) * pageSize;
|
||||
var endIndex = startIndex + pageSize;
|
||||
var paginatedList = filteredList.slice(startIndex, endIndex);
|
||||
|
||||
var findVehicleByVin = function (vin) {
|
||||
return mockVehicleList.find(function (v) { return v.frameNo === vin; });
|
||||
};
|
||||
|
||||
var todayStr = function () {
|
||||
var d = new Date();
|
||||
var y = d.getFullYear();
|
||||
var m = (d.getMonth() + 1).toString();
|
||||
var day = d.getDate().toString();
|
||||
if (m.length === 1) { m = '0' + m; }
|
||||
if (day.length === 1) { day = '0' + day; }
|
||||
return y + '-' + m + '-' + day;
|
||||
};
|
||||
|
||||
var sampleScrapDates = ['2035-12-31', '2030-06-15', '2028-03-20'];
|
||||
var sampleInspectionExpiries = ['2026-06', '2025-12', '2027-03'];
|
||||
var getSampleScrapDate = function () { return sampleScrapDates[Math.floor(Math.random() * sampleScrapDates.length)]; };
|
||||
var getSampleInspectionExpiry = function () { return sampleInspectionExpiries[Math.floor(Math.random() * sampleInspectionExpiries.length)]; };
|
||||
|
||||
var processFileAndGetItem = function (file, callback) {
|
||||
var reader = new FileReader();
|
||||
reader.onload = function () {
|
||||
var photoUrl = reader.result;
|
||||
var mockVin = mockVehicleList[0].frameNo;
|
||||
var mockPlate = '粤A' + Math.floor(Math.random() * 90000 + 10000).toString();
|
||||
var vehicle = findVehicleByVin(mockVin);
|
||||
var item = {
|
||||
photoUrl: photoUrl,
|
||||
vin: mockVin,
|
||||
plateNo: mockPlate,
|
||||
vehicle: vehicle
|
||||
};
|
||||
callback(item);
|
||||
};
|
||||
reader.readAsDataURL(file);
|
||||
};
|
||||
|
||||
var simulateOcrAndConfirm = function (items, isMulti) {
|
||||
setOcrModalVisible(false);
|
||||
if (isMulti && items.length > 1) {
|
||||
batchFullListRef.current = items.slice();
|
||||
setBatchConfirmList(items);
|
||||
setBatchConfirmIndex(0);
|
||||
setBatchTotalCount(items.length);
|
||||
setConfirmData(items[0]);
|
||||
setConfirmVin(items[0].vin);
|
||||
setConfirmPlateNo(items[0].plateNo);
|
||||
setConfirmScrapDate(getSampleScrapDate());
|
||||
setConfirmInspectionExpiry(getSampleInspectionExpiry());
|
||||
setConfirmModalVisible(true);
|
||||
setIsBatchMode(true);
|
||||
} else if (items.length > 0) {
|
||||
setConfirmData(items[0]);
|
||||
setConfirmVin(items[0].vin);
|
||||
setConfirmPlateNo(items[0].plateNo);
|
||||
setConfirmScrapDate(getSampleScrapDate());
|
||||
setConfirmInspectionExpiry(getSampleInspectionExpiry());
|
||||
setConfirmModalVisible(true);
|
||||
setIsBatchMode(false);
|
||||
}
|
||||
};
|
||||
|
||||
var handleUpload = function (e, isBatch) {
|
||||
var files = e.target.files;
|
||||
if (!files || files.length === 0) return;
|
||||
// 从批量上传弹框内「上传车牌」触发:不进入识别/确认页,只在弹框中新增一条识别任务
|
||||
if (batchUploadFromCardRef.current) {
|
||||
batchUploadFromCardRef.current = false;
|
||||
var fileCount = files.length;
|
||||
var collected = [];
|
||||
var processed = 0;
|
||||
var checkDone = function () {
|
||||
processed = processed + 1;
|
||||
if (processed === fileCount) {
|
||||
var now = new Date();
|
||||
var timeStr = 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');
|
||||
setBatchTaskList(function (prev) {
|
||||
var next = [{ id: 'bt' + Date.now(), createTime: timeStr, photoCount: collected.length, progress: 100, items: collected }].concat(prev);
|
||||
return next.slice(0, 5);
|
||||
});
|
||||
}
|
||||
};
|
||||
for (var i = 0; i < fileCount; i++) {
|
||||
(function (idx) {
|
||||
processFileAndGetItem(files[idx], function (item) {
|
||||
collected.push(item);
|
||||
checkDone();
|
||||
});
|
||||
})(i);
|
||||
}
|
||||
e.target.value = '';
|
||||
return;
|
||||
}
|
||||
setOcrModalVisible(true);
|
||||
var fileCount = files.length;
|
||||
var collected = [];
|
||||
var processed = 0;
|
||||
var checkDone = function () {
|
||||
processed = processed + 1;
|
||||
if (processed === fileCount) {
|
||||
setTimeout(function () {
|
||||
simulateOcrAndConfirm(collected, isBatch && collected.length > 1);
|
||||
}, 1500);
|
||||
}
|
||||
};
|
||||
for (var i = 0; i < fileCount; i++) {
|
||||
(function (idx) {
|
||||
processFileAndGetItem(files[idx], function (item) {
|
||||
collected.push(item);
|
||||
checkDone();
|
||||
});
|
||||
})(i);
|
||||
}
|
||||
e.target.value = '';
|
||||
};
|
||||
|
||||
var handleConfirmSubmit = function () {
|
||||
var vehicle = confirmData && confirmData.vehicle;
|
||||
var newRecord = {
|
||||
id: 'r' + Date.now(),
|
||||
plateDate: todayStr(),
|
||||
operator: '当前用户',
|
||||
plateNo: confirmPlateNo,
|
||||
vin: confirmVin,
|
||||
vehicleType: vehicle ? vehicle.vehicleType : '轿车',
|
||||
brand: vehicle ? vehicle.brand : '-',
|
||||
model: vehicle ? vehicle.model : '-',
|
||||
photoUrl: confirmData && confirmData.photoUrl ? confirmData.photoUrl : 'https://picsum.photos/300/200?random=' + Date.now()
|
||||
};
|
||||
var nextList = recordList.slice();
|
||||
nextList.unshift(newRecord);
|
||||
setRecordList(nextList);
|
||||
message.success('车辆上牌成功');
|
||||
if (isBatchMode && batchConfirmList.length > 1) {
|
||||
var nextBatch = batchConfirmList.slice(1);
|
||||
var nextItem = nextBatch[0];
|
||||
setBatchConfirmList(nextBatch);
|
||||
setBatchConfirmIndex(batchConfirmIndex + 1);
|
||||
if (nextItem) {
|
||||
setConfirmData(nextItem);
|
||||
setConfirmVin(nextItem.vin);
|
||||
setConfirmPlateNo(nextItem.plateNo);
|
||||
setConfirmScrapDate(getSampleScrapDate());
|
||||
setConfirmInspectionExpiry(getSampleInspectionExpiry());
|
||||
} else {
|
||||
var fullList = batchFullListRef.current;
|
||||
if (fullList && fullList.length > 0) {
|
||||
var now = new Date();
|
||||
var timeStr = 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');
|
||||
setBatchTaskList(function (prev) {
|
||||
var next = [{ id: 'bt' + Date.now(), createTime: timeStr, photoCount: fullList.length, progress: 100, items: fullList }].concat(prev);
|
||||
return next.slice(0, 5);
|
||||
});
|
||||
batchFullListRef.current = null;
|
||||
}
|
||||
setConfirmModalVisible(false);
|
||||
setConfirmData(null);
|
||||
setConfirmVin('');
|
||||
setConfirmPlateNo('');
|
||||
setConfirmScrapDate('');
|
||||
setConfirmInspectionExpiry('');
|
||||
setBatchConfirmList([]);
|
||||
setBatchTotalCount(0);
|
||||
setIsBatchMode(false);
|
||||
}
|
||||
} else {
|
||||
setConfirmModalVisible(false);
|
||||
setConfirmData(null);
|
||||
setConfirmVin('');
|
||||
setConfirmPlateNo('');
|
||||
setConfirmScrapDate('');
|
||||
setConfirmInspectionExpiry('');
|
||||
setBatchConfirmList([]);
|
||||
setBatchTotalCount(0);
|
||||
setIsBatchMode(false);
|
||||
}
|
||||
};
|
||||
|
||||
var handleConfirmCancel = function () {
|
||||
setConfirmModalVisible(false);
|
||||
setConfirmData(null);
|
||||
setConfirmVin('');
|
||||
setConfirmPlateNo('');
|
||||
setConfirmScrapDate('');
|
||||
setConfirmInspectionExpiry('');
|
||||
setBatchConfirmList([]);
|
||||
setBatchConfirmIndex(0);
|
||||
setBatchTotalCount(0);
|
||||
setIsBatchMode(false);
|
||||
};
|
||||
|
||||
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' },
|
||||
card: { backgroundColor: t.neutral1, borderRadius: t.radiusLarge, boxShadow: t.shadowLight, marginBottom: t.spacing16, padding: t.spacing16 },
|
||||
filterRow: { display: 'flex', flexWrap: 'wrap', alignItems: 'center', gap: t.spacing12 },
|
||||
filterRowRight: { display: 'flex', alignItems: 'center', gap: t.spacing8, marginLeft: 'auto' },
|
||||
label: { marginRight: t.spacing8, fontSize: t.fontSize14, color: t.neutral8, whiteSpace: 'nowrap' },
|
||||
input: { padding: '0 10px', height: '32px', width: '180px', borderRadius: '2px', border: '1px solid ' + t.border, fontSize: t.fontSize14, boxSizing: 'border-box' },
|
||||
btn: { padding: t.spacing8 + ' ' + t.spacing16, borderRadius: t.radiusMedium, cursor: 'pointer', fontSize: t.fontSize14, display: 'inline-flex', alignItems: 'center', justifyContent: 'center', gap: '6px', boxSizing: 'border-box' },
|
||||
btnFixed: { width: '82px', height: '32px', padding: 0, borderRadius: '2px', lineHeight: '1' },
|
||||
btnIcon: { width: '14px', height: '14px', flexShrink: 0, display: 'block' },
|
||||
btnFillBlue: { backgroundColor: t.primary, color: t.neutral1, border: 'none' },
|
||||
btnOutlineBlue: { backgroundColor: t.neutral1, color: t.primary, border: '1px solid ' + t.primary },
|
||||
btnDefault: { backgroundColor: t.neutral1, color: t.neutral8, border: '1px solid ' + t.border },
|
||||
btnSize82: { width: '82px', height: '32px', padding: 0, lineHeight: '1', boxSizing: 'border-box' },
|
||||
toolbar: { display: 'flex', alignItems: 'center', justifyContent: 'flex-end', gap: t.spacing12, marginBottom: t.spacing16 },
|
||||
tableWrap: { overflowX: 'auto', backgroundColor: t.neutral1, borderRadius: t.radiusMedium, border: '1px solid ' + t.neutral4 },
|
||||
table: { width: '100%', borderCollapse: 'separate', borderSpacing: 0, fontSize: t.fontSize14 },
|
||||
th: { textAlign: 'left', padding: '12px 16px', backgroundColor: t.fillSecondary, borderBottom: '1px solid ' + t.neutral4, fontWeight: 600, color: t.neutral8, fontSize: t.fontSize14, whiteSpace: 'nowrap' },
|
||||
td: { padding: '12px 16px', borderBottom: '1px solid ' + t.neutral4, color: t.neutral8, fontSize: t.fontSize14 },
|
||||
pagination: { display: 'flex', alignItems: 'center', justifyContent: 'space-between', padding: '16px', borderTop: '1px solid ' + t.neutral4, backgroundColor: t.neutral1 },
|
||||
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, backgroundColor: t.neutral1 },
|
||||
paginationBtn: { minWidth: '28px', height: '28px', padding: '0 8px', borderRadius: '2px', border: '1px solid ' + t.border, backgroundColor: t.neutral1, color: t.neutral8, cursor: 'pointer', fontSize: t.fontSize14, display: 'inline-flex', alignItems: 'center', justifyContent: 'center' },
|
||||
paginationBtnActive: { backgroundColor: t.primary, color: t.neutral1, borderColor: t.primary },
|
||||
paginationBtnDisabled: { opacity: 0.5, cursor: 'not-allowed' },
|
||||
paginationInput: { width: '50px', height: '28px', padding: '0 8px', borderRadius: '2px', border: '1px solid ' + t.border, fontSize: t.fontSize14, textAlign: 'center' },
|
||||
actionLink: { color: t.link, cursor: 'pointer', marginRight: t.spacing12, fontSize: t.fontSize14 },
|
||||
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: '500px', position: 'relative' },
|
||||
modalTitle: { fontSize: t.fontSize16, fontWeight: 600, marginBottom: t.spacing16, color: t.neutral8 },
|
||||
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 },
|
||||
autocompleteWrap: { position: 'relative', width: '180px', display: 'inline-block' },
|
||||
autocompletePanel: { position: 'absolute', left: 0, top: '100%', marginTop: '4px', backgroundColor: t.neutral1, borderRadius: t.radiusMedium, border: '1px solid ' + t.border, boxShadow: t.shadowMedium, zIndex: 100, minWidth: '100%', maxHeight: '200px', overflowY: 'auto' },
|
||||
autocompleteOption: { padding: '8px 12px', fontSize: t.fontSize14, color: t.neutral8, cursor: 'pointer' },
|
||||
autocompleteOptionHover: { backgroundColor: t.fill },
|
||||
confirmCard: { display: 'flex', gap: t.spacing24, marginTop: t.spacing16 },
|
||||
confirmPhoto: { flex: '0 0 300px', height: '200px', borderRadius: t.radiusMedium, overflow: 'hidden', backgroundColor: t.neutral3 },
|
||||
confirmPhotoImg: { width: '100%', height: '100%', objectFit: 'cover' },
|
||||
confirmForm: { flex: 1, display: 'flex', flexDirection: 'column', gap: t.spacing16 },
|
||||
formLabel: { display: 'block', marginBottom: '6px', fontSize: t.fontSize14, color: t.neutral8 },
|
||||
formInput: { padding: '8px 12px', height: '36px', borderRadius: t.radiusMedium, border: '1px solid ' + t.border, fontSize: t.fontSize14, width: '100%', boxSizing: 'border-box' },
|
||||
photoViewModal: { maxWidth: '800px', textAlign: 'center' },
|
||||
photoViewImg: { maxWidth: '100%', maxHeight: '70vh', borderRadius: t.radiusMedium },
|
||||
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 },
|
||||
modalContent: { fontSize: t.fontSize14, color: t.neutral8, lineHeight: '1.6' },
|
||||
requirementSection: { marginBottom: t.spacing16 },
|
||||
requirementSectionTitle: { fontSize: t.fontSize16, fontWeight: 600, color: t.neutral8, marginBottom: t.spacing8 },
|
||||
flowWrap: { marginTop: t.spacing8, marginBottom: t.spacing16 },
|
||||
flowCol: { display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 0 },
|
||||
flowArrow: { width: '2px', height: '20px', backgroundColor: t.neutral5 },
|
||||
flowNodeOval: { padding: '8px 20px', borderRadius: '20px', border: '1px solid ' + t.neutral5, backgroundColor: t.neutral2, fontSize: t.fontSize14, color: t.neutral8 },
|
||||
flowNodeRect: { padding: '8px 20px', border: '1px solid ' + t.neutral5, backgroundColor: t.neutral1, fontSize: t.fontSize14, color: t.neutral8 },
|
||||
flowNodeDiamond: { padding: '10px 16px', border: '1px solid ' + t.neutral5, backgroundColor: t.fillSecondary, fontSize: t.fontSize14, color: t.neutral8, transform: 'rotate(0deg)', width: '140px', textAlign: 'center', boxSizing: 'border-box', clipPath: 'polygon(50% 0%, 100% 50%, 50% 100%, 0% 50%)' },
|
||||
flowNodeDiamondWrap: { padding: '8px 16px', border: '1px solid ' + t.neutral5, backgroundColor: t.fillSecondary, fontSize: t.fontSize14, color: t.neutral8, minWidth: '120px', textAlign: 'center' },
|
||||
flowNodeToast: { padding: '8px 16px', borderRadius: '8px', border: '1px solid ' + t.neutral4, backgroundColor: t.neutral2, fontSize: t.fontSize14, color: t.neutral7 },
|
||||
flowRow: { display: 'flex', alignItems: 'flex-start', justifyContent: 'center', gap: '24px', flexWrap: 'wrap' },
|
||||
flowBranch: { display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 0 },
|
||||
requirementItem: { marginBottom: t.spacing8, paddingLeft: t.spacing16 },
|
||||
requirementSubItem: { marginBottom: t.spacing4, paddingLeft: t.spacing16, fontSize: t.fontSize14, color: t.neutral7 },
|
||||
batchTaskCardHeader: { display: 'flex', alignItems: 'center', justifyContent: 'space-between', marginBottom: t.spacing16 },
|
||||
batchTaskTable: { width: '100%', borderCollapse: 'collapse', fontSize: t.fontSize14 },
|
||||
batchTaskTh: { textAlign: 'left', padding: '10px 12px', borderBottom: '1px solid ' + t.neutral4, color: t.neutral7, fontWeight: 500 },
|
||||
batchTaskTd: { padding: '10px 12px', borderBottom: '1px solid ' + t.neutral4, color: t.neutral8 },
|
||||
progressWrap: { width: '120px', height: '8px', backgroundColor: t.neutral4, borderRadius: '4px', overflow: 'hidden' },
|
||||
progressBar: { height: '100%', backgroundColor: t.primary, borderRadius: '4px', transition: 'width 0.2s' },
|
||||
recognizeLink: { color: t.link, cursor: 'pointer', fontSize: t.fontSize14 },
|
||||
dateRangeWrap: { position: 'relative', display: 'inline-block' },
|
||||
dateRangeTrigger: { display: 'flex', alignItems: 'center', height: '32px', padding: '0 12px', border: '1px solid ' + t.border, borderRadius: '2px', backgroundColor: t.neutral1, cursor: 'pointer', minWidth: '280px', boxSizing: 'border-box' },
|
||||
dateRangeTriggerFocused: { borderColor: t.primary, outline: 'none' },
|
||||
dateRangeLabel: { display: 'flex', alignItems: 'center', gap: '6px', padding: '0 8px', height: '100%', fontSize: t.fontSize14, color: t.neutral8 },
|
||||
dateRangeLabelActive: { backgroundColor: 'rgba(22,93,255,0.1)', color: t.primary, borderBottom: '2px solid ' + t.primary },
|
||||
dateRangeLabelText: { whiteSpace: 'nowrap' },
|
||||
dateRangeDash: { color: t.neutral5, margin: '0 4px', fontSize: t.fontSize14 },
|
||||
dateRangeIcon: { marginLeft: 'auto', width: '16px', height: '16px', color: t.neutral6, flexShrink: 0 },
|
||||
dateRangePanel: { position: 'absolute', left: 0, top: '100%', marginTop: '4px', backgroundColor: t.neutral1, borderRadius: t.radiusMedium, border: '1px solid ' + t.border, boxShadow: t.shadowMedium, zIndex: 100, padding: '16px', display: 'flex', gap: '24px' },
|
||||
dateRangeCalendar: { width: '280px' },
|
||||
dateRangeCalendarHeader: { display: 'flex', alignItems: 'center', justifyContent: 'space-between', marginBottom: '12px', padding: '0 4px' },
|
||||
dateRangeCalendarTitle: { fontSize: t.fontSize14, fontWeight: 500, color: t.neutral8 },
|
||||
dateRangeCalendarNav: { display: 'flex', alignItems: 'center', gap: '4px' },
|
||||
dateRangeNavBtn: { width: '28px', height: '28px', display: 'flex', alignItems: 'center', justifyContent: 'center', border: 'none', backgroundColor: 'transparent', color: t.neutral6, cursor: 'pointer', borderRadius: t.radiusSmall },
|
||||
dateRangeNavBtnHover: { color: t.primary, backgroundColor: t.fill },
|
||||
dateRangeWeekRow: { display: 'flex', marginBottom: '4px' },
|
||||
dateRangeWeekCell: { width: '36px', height: '28px', display: 'flex', alignItems: 'center', justifyContent: 'center', fontSize: '12px', color: t.neutral6 },
|
||||
dateRangeDayRow: { display: 'flex' },
|
||||
dateRangeDayCell: { width: '36px', height: '36px', display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center', fontSize: t.fontSize14, cursor: 'pointer', borderRadius: t.radiusSmall, color: t.neutral8 },
|
||||
dateRangeDayCellOther: { color: t.neutral5 },
|
||||
dateRangeDayCellSelected: { color: t.primary },
|
||||
dateRangeDayCellInRange: { backgroundColor: 'rgba(22,93,255,0.08)', color: t.primary },
|
||||
dateRangeDayDot: { width: '4px', height: '4px', borderRadius: '50%', backgroundColor: t.primary, marginTop: '2px' }
|
||||
};
|
||||
|
||||
var renderFilterSelect = function (value, setValue, options, placeholder) {
|
||||
var opts = (options || []).map(function (o) { return React.createElement(Option, { key: o, value: o }, o); });
|
||||
return React.createElement(Select, {
|
||||
placeholder: placeholder || '请选择或输入搜索',
|
||||
style: { width: 180 },
|
||||
value: value || undefined,
|
||||
onChange: function (v) { setValue(v || ''); },
|
||||
showSearch: true,
|
||||
allowClear: true,
|
||||
filterOption: function (input, opt) {
|
||||
var c = opt && opt.children;
|
||||
return c && String(c).toLowerCase().indexOf((input || '').toLowerCase()) >= 0;
|
||||
}
|
||||
}, opts);
|
||||
};
|
||||
|
||||
return React.createElement(
|
||||
'div',
|
||||
{ style: styles.page },
|
||||
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); } }, '查看需求说明')
|
||||
)
|
||||
),
|
||||
React.createElement(
|
||||
'div',
|
||||
{ style: styles.card },
|
||||
React.createElement(
|
||||
'div',
|
||||
{ style: styles.filterRow },
|
||||
React.createElement('span', { style: styles.label }, '上牌日期:'),
|
||||
React.createElement(DatePicker, {
|
||||
style: { width: 180 },
|
||||
format: 'YYYY-MM-DD',
|
||||
placeholder: '开始日期',
|
||||
value: filterDateStart && window.moment ? window.moment(filterDateStart, 'YYYY-MM-DD') : null,
|
||||
onChange: function (d, dateStr) { setFilterDateStart(dateStr || ''); }
|
||||
}),
|
||||
React.createElement('span', { style: { color: t.neutral6, margin: '0 4px' } }, '至'),
|
||||
React.createElement(DatePicker, {
|
||||
style: { width: 180 },
|
||||
format: 'YYYY-MM-DD',
|
||||
placeholder: '结束日期',
|
||||
value: filterDateEnd && window.moment ? window.moment(filterDateEnd, 'YYYY-MM-DD') : null,
|
||||
onChange: function (d, dateStr) { setFilterDateEnd(dateStr || ''); }
|
||||
}),
|
||||
React.createElement('span', { style: styles.label }, '操作人:'),
|
||||
renderFilterSelect(filterOperator, setFilterOperator, allOperators, '请选择操作人'),
|
||||
React.createElement('span', { style: styles.label }, '车牌号:'),
|
||||
renderFilterSelect(filterPlateNo, setFilterPlateNo, allPlateNos, '请选择车牌号'),
|
||||
React.createElement('span', { style: styles.label }, '车辆识别代码:'),
|
||||
renderFilterSelect(filterVin, setFilterVin, allVins, '请选择车辆识别代码'),
|
||||
React.createElement(
|
||||
'div',
|
||||
{ style: styles.filterRowRight },
|
||||
React.createElement(Button, {
|
||||
type: 'primary',
|
||||
onClick: function () {
|
||||
setAppliedDateStart(filterDateStart);
|
||||
setAppliedDateEnd(filterDateEnd);
|
||||
setAppliedOperator(filterOperator);
|
||||
setAppliedPlateNo(filterPlateNo);
|
||||
setAppliedVin(filterVin);
|
||||
setCurrentPage(1);
|
||||
message.success('查询成功');
|
||||
}
|
||||
}, '查询'),
|
||||
React.createElement(Button, {
|
||||
onClick: function () {
|
||||
setFilterDateStart('');
|
||||
setFilterDateEnd('');
|
||||
setAppliedDateStart('');
|
||||
setAppliedDateEnd('');
|
||||
setFilterOperator('');
|
||||
setFilterPlateNo('');
|
||||
setFilterVin('');
|
||||
setAppliedOperator('');
|
||||
setAppliedPlateNo('');
|
||||
setAppliedVin('');
|
||||
setCurrentPage(1);
|
||||
}
|
||||
}, '重置')
|
||||
)
|
||||
)
|
||||
),
|
||||
React.createElement(
|
||||
'div',
|
||||
{ style: styles.card },
|
||||
React.createElement(
|
||||
'div',
|
||||
{ style: styles.toolbar },
|
||||
React.createElement('input', {
|
||||
type: 'file',
|
||||
ref: fileInputRef,
|
||||
accept: 'image/*',
|
||||
style: { display: 'none' },
|
||||
onChange: function (e) { handleUpload(e, false); }
|
||||
}),
|
||||
React.createElement('input', {
|
||||
type: 'file',
|
||||
ref: batchFileInputRef,
|
||||
accept: 'image/*',
|
||||
multiple: true,
|
||||
style: { display: 'none' },
|
||||
onChange: function (e) { handleUpload(e, true); }
|
||||
}),
|
||||
React.createElement(Button, {
|
||||
type: 'primary',
|
||||
onClick: function () { if (fileInputRef.current) fileInputRef.current.click(); }
|
||||
}, '新增'),
|
||||
React.createElement(Button, {
|
||||
onClick: function () { setBatchTaskCardVisible(true); }
|
||||
}, '批量上传')
|
||||
),
|
||||
React.createElement(Table, {
|
||||
rowKey: 'id',
|
||||
size: 'small',
|
||||
columns: [
|
||||
{ title: '上牌日期', dataIndex: 'plateDate', key: 'plateDate', width: 120 },
|
||||
{ title: '操作人', dataIndex: 'operator', key: 'operator', width: 100 },
|
||||
{ title: '车牌号', dataIndex: 'plateNo', key: 'plateNo', width: 120 },
|
||||
{ title: '车辆识别代码', dataIndex: 'vin', key: 'vin', width: 140 },
|
||||
{ title: '车辆类型', dataIndex: 'vehicleType', key: 'vehicleType', width: 100 },
|
||||
{ title: '品牌', dataIndex: 'brand', key: 'brand', width: 100 },
|
||||
{ title: '型号', dataIndex: 'model', key: 'model', width: 120 },
|
||||
{ title: '操作', key: 'action', width: 80, render: function (_, row) { return React.createElement(Button, { type: 'link', size: 'small', onClick: function () { setViewPhotoRecord(row); } }, '查看'); } }
|
||||
],
|
||||
dataSource: paginatedList,
|
||||
pagination: {
|
||||
current: validPage,
|
||||
pageSize: pageSize,
|
||||
total: totalItems,
|
||||
showSizeChanger: true,
|
||||
showQuickJumper: true,
|
||||
pageSizeOptions: ['10', '20', '50', '100'],
|
||||
showTotal: function (total) { return '共 ' + total + ' 条'; },
|
||||
onChange: function (page, size) {
|
||||
setCurrentPage(page);
|
||||
if (size !== pageSize) setPageSize(size);
|
||||
}
|
||||
}
|
||||
})
|
||||
),
|
||||
React.createElement(Modal, {
|
||||
title: '识别中,请勿关闭页面',
|
||||
visible: ocrModalVisible,
|
||||
footer: null,
|
||||
closable: false,
|
||||
maskClosable: false,
|
||||
children: React.createElement('div', { style: { padding: '24px 0', textAlign: 'center' } },
|
||||
React.createElement(Spin, { size: 'large' }),
|
||||
React.createElement('p', { style: { marginTop: 12, color: t.neutral6 } }, '正在识别行驶证信息...')
|
||||
)
|
||||
}),
|
||||
React.createElement(Modal, {
|
||||
title: isBatchMode && batchTotalCount > 1 ? '确认上牌信息(' + (batchTotalCount - batchConfirmList.length + 1) + '/' + batchTotalCount + ')' : '确认上牌信息',
|
||||
visible: confirmModalVisible && !!confirmData,
|
||||
onCancel: handleConfirmCancel,
|
||||
onOk: handleConfirmSubmit,
|
||||
okText: '确认',
|
||||
cancelText: '取消',
|
||||
width: 560,
|
||||
children: confirmData ? React.createElement(
|
||||
'div',
|
||||
{ style: styles.confirmCard },
|
||||
React.createElement('div', { style: styles.confirmPhoto },
|
||||
React.createElement('img', { src: confirmData.photoUrl, alt: '行驶证', style: styles.confirmPhotoImg })
|
||||
),
|
||||
React.createElement('div', { style: styles.confirmForm },
|
||||
React.createElement('div', { style: { marginBottom: 16 } },
|
||||
React.createElement('label', { style: styles.formLabel }, '车辆识别代号'),
|
||||
React.createElement(Input, {
|
||||
style: { width: '100%' },
|
||||
value: confirmVin,
|
||||
onChange: function (e) { setConfirmVin(e.target.value); }
|
||||
})
|
||||
),
|
||||
React.createElement('div', { style: { marginBottom: 16 } },
|
||||
React.createElement('label', { style: styles.formLabel }, '车牌号'),
|
||||
React.createElement(Input, {
|
||||
style: { width: '100%' },
|
||||
value: confirmPlateNo,
|
||||
onChange: function (e) { setConfirmPlateNo(e.target.value); }
|
||||
})
|
||||
),
|
||||
React.createElement('div', { style: { marginBottom: 16 } },
|
||||
React.createElement('label', { style: styles.formLabel }, '强制报废日期'),
|
||||
React.createElement(Input, {
|
||||
style: { width: '100%' },
|
||||
placeholder: 'YYYY-MM-DD',
|
||||
value: confirmScrapDate,
|
||||
onChange: function (e) { setConfirmScrapDate(e.target.value); }
|
||||
})
|
||||
),
|
||||
React.createElement('div', null,
|
||||
React.createElement('label', { style: styles.formLabel }, '检验有效期'),
|
||||
React.createElement(Input, {
|
||||
style: { width: '100%' },
|
||||
placeholder: 'YYYY-MM',
|
||||
value: confirmInspectionExpiry,
|
||||
onChange: function (e) { setConfirmInspectionExpiry(e.target.value); }
|
||||
})
|
||||
)
|
||||
)
|
||||
) : null
|
||||
}),
|
||||
React.createElement(Modal, {
|
||||
title: '行驶证照片',
|
||||
visible: !!viewPhotoRecord,
|
||||
footer: React.createElement(Button, { onClick: function () { setViewPhotoRecord(null); } }, '关闭'),
|
||||
onCancel: function () { setViewPhotoRecord(null); },
|
||||
width: 640,
|
||||
children: viewPhotoRecord ? React.createElement('img', { src: viewPhotoRecord.photoUrl, alt: '行驶证', style: Object.assign({}, styles.photoViewImg, { width: '100%' }) }) : null
|
||||
}),
|
||||
React.createElement(Modal, {
|
||||
title: '批量上牌任务',
|
||||
visible: batchTaskCardVisible,
|
||||
onCancel: function () { setBatchTaskCardVisible(false); },
|
||||
footer: React.createElement(Button, { onClick: function () { setBatchTaskCardVisible(false); } }, '关闭'),
|
||||
width: 560,
|
||||
children: React.createElement(React.Fragment, null,
|
||||
React.createElement('div', { style: Object.assign({}, styles.batchTaskCardHeader, { marginBottom: 16 }) },
|
||||
React.createElement(Button, {
|
||||
type: 'primary',
|
||||
onClick: function () {
|
||||
batchUploadFromCardRef.current = true;
|
||||
if (batchFileInputRef.current) batchFileInputRef.current.click();
|
||||
}
|
||||
}, '批量上传')
|
||||
),
|
||||
React.createElement(Table, {
|
||||
rowKey: 'id',
|
||||
size: 'small',
|
||||
columns: [
|
||||
{ title: '任务时间', dataIndex: 'createTime', key: 'createTime', width: 160 },
|
||||
{ title: '照片数量', dataIndex: 'photoCount', key: 'photoCount', width: 100, render: function (c) { return c + ' 张'; } },
|
||||
{ title: '完成进度', key: 'progress', width: 160, render: function (_, task) {
|
||||
return React.createElement('div', { style: { display: 'flex', alignItems: 'center', gap: 8 } },
|
||||
React.createElement('div', { style: styles.progressWrap },
|
||||
React.createElement('div', { style: Object.assign({}, styles.progressBar, { width: (task.progress || 0) + '%' }) })
|
||||
),
|
||||
React.createElement('span', { style: { fontSize: t.fontSize14, color: t.neutral7, minWidth: 36 } }, (task.progress || 0) + '%')
|
||||
);
|
||||
} },
|
||||
{ title: '操作', key: 'action', width: 80, render: function (_, task) {
|
||||
return task.progress === 100 && task.items && task.items.length > 0
|
||||
? React.createElement(Button, { type: 'link', size: 'small', onClick: function () {
|
||||
setBatchConfirmList(task.items);
|
||||
setBatchConfirmIndex(0);
|
||||
setBatchTotalCount(task.items.length);
|
||||
setConfirmData(task.items[0]);
|
||||
setConfirmVin(task.items[0].vin);
|
||||
setConfirmPlateNo(task.items[0].plateNo);
|
||||
setConfirmScrapDate(getSampleScrapDate());
|
||||
setConfirmInspectionExpiry(getSampleInspectionExpiry());
|
||||
setConfirmModalVisible(true);
|
||||
setIsBatchMode(true);
|
||||
setBatchTaskCardVisible(false);
|
||||
} }, '识别')
|
||||
: React.createElement('span', { style: { color: t.neutral5, fontSize: t.fontSize14 } }, '-');
|
||||
} }
|
||||
],
|
||||
dataSource: batchTaskList.slice(0, 5),
|
||||
pagination: false
|
||||
})
|
||||
)
|
||||
}),
|
||||
React.createElement(Modal, {
|
||||
title: '需求说明',
|
||||
visible: showRequirementModal,
|
||||
onCancel: function () { setShowRequirementModal(false); },
|
||||
footer: React.createElement(Button, { onClick: function () { setShowRequirementModal(false); } }, '关闭'),
|
||||
width: 720,
|
||||
children: React.createElement('div', { style: styles.modalContent },
|
||||
React.createElement('div', { style: Object.assign({}, styles.requirementSection, { marginBottom: t.spacing24 }) },
|
||||
React.createElement('div', { style: Object.assign({}, styles.requirementSectionTitle, { fontSize: '18px', marginBottom: t.spacing12 }) }, '上牌管理'),
|
||||
React.createElement('div', { style: Object.assign({}, styles.requirementItem, { marginTop: 0, color: t.neutral7 }) }, '用以识别行驶证正反面,识别车架号、车牌号、强制报废日期(YYYY-MM-DD)、检验有效期(YYYY-MM)')
|
||||
),
|
||||
React.createElement('div', { style: styles.requirementSection },
|
||||
React.createElement('div', { style: styles.requirementSectionTitle }, '1.面包屑:'),
|
||||
React.createElement('div', { style: styles.requirementItem }, '运维管理-车辆业务-上牌管理')
|
||||
),
|
||||
React.createElement('div', { style: styles.requirementSection },
|
||||
React.createElement('div', { style: styles.requirementSectionTitle }, '2.筛选:'),
|
||||
React.createElement('div', { style: styles.requirementSubItem }, '2.1.上牌日期:双日历日期选择器,支持选择开始-结束时间,支持手动修改日期,但检验格式及判断结束日期不得早于开始日期;'),
|
||||
React.createElement('div', { style: styles.requirementSubItem }, '2.2.操作人:选择器,支持从输入框输入内容模糊搜索,默认提示内容为:请选择操作人;'),
|
||||
React.createElement('div', { style: styles.requirementSubItem }, '2.3.车牌号:选择器,支持从输入框输入内容模糊搜索,默认提示内容为:请选择车牌号;'),
|
||||
React.createElement('div', { style: styles.requirementSubItem }, '2.4.车辆识别代码:选择器,支持从输入框输入内容模糊搜索,默认提示内容为:请选择车辆识别代码;')
|
||||
),
|
||||
React.createElement('div', { style: styles.requirementSection },
|
||||
React.createElement('div', { style: styles.requirementSectionTitle }, '3.列表:'),
|
||||
React.createElement('div', { style: styles.requirementItem }, '列表右侧按钮为新增、批量上传,字段依次为上牌日期、操作人、车牌号、车辆识别代码、车辆类型、品牌、型号、操作;'),
|
||||
React.createElement('div', { style: styles.requirementSubItem }, '3.1.上牌日期:车辆上牌操作完成日期,格式为YYYY-MM-DD'),
|
||||
React.createElement('div', { style: styles.requirementSubItem }, '3.2.操作人:车辆上牌记录操作用户姓名;'),
|
||||
React.createElement('div', { style: styles.requirementSubItem }, '3.3.车牌号:显示上牌车牌号;通过新增按钮上传行驶证照片后,通过OCR识别技术,自动识别出该车辆识别代号对应车牌号,确认无误提交后自动反写'),
|
||||
React.createElement('div', { style: styles.requirementSubItem }, '3.4.车辆识别代码:显示上牌车辆车辆识别代码;'),
|
||||
React.createElement('div', { style: styles.requirementSubItem }, '3.5.车辆类型:显示该车辆识别代码对应车辆类型;'),
|
||||
React.createElement('div', { style: styles.requirementSubItem }, '3.6.品牌:显示该车辆识别代码对应品牌;'),
|
||||
React.createElement('div', { style: styles.requirementSubItem }, '3.7.型号:显示该车辆识别代码对应型号;'),
|
||||
React.createElement('div', { style: styles.requirementSubItem }, '3.8.操作:行驶证,点击放大预览行驶证照片;'),
|
||||
React.createElement('div', { style: styles.requirementItem }, '下方增加分页功能,支持选择单页数据条数;')
|
||||
),
|
||||
React.createElement('div', { style: styles.requirementSection },
|
||||
React.createElement('div', { style: styles.requirementSectionTitle }, '4.新增:'),
|
||||
React.createElement('div', { style: styles.requirementSubItem }, '4.1.点击新增按钮,上传行驶证照片附件,上传后OCR识别过程中弹出卡片提示:识别中,请勿关闭页面;如果照片识别失败,则提示:识别失败,请重新尝试;'),
|
||||
React.createElement('div', { style: styles.requirementSubItem }, '4.2.上传成功后确认卡片中显示照片、车辆识别代码、车牌号、强制报废日期、检验有效期,可通过二次编辑进行校正;'),
|
||||
React.createElement('div', { style: styles.requirementSubItem }, '4.3.点击卡片页面底部"确认"按钮,确认根据车辆识别代码判断是否存在该车辆,如果是则toast提示"上牌成功",并在列表中生成操作,如果否则toast提示:该车辆不存在。')
|
||||
),
|
||||
React.createElement('div', { style: styles.requirementSection },
|
||||
React.createElement('div', { style: styles.requirementSectionTitle }, '5.批量上传:'),
|
||||
React.createElement('div', { style: styles.requirementItem }, '5.1.点击批量上牌按钮,弹出批量上牌任务卡片,再点击右上角上传车牌,上传多张行驶证照片附件,上传后弹出批量上牌任务卡片:卡片中记录最近5条批量上牌任务,任务字段为任务时间、照片数量、识别错误、完成进度、操作;'),
|
||||
React.createElement('div', { style: styles.requirementSubItem }, '5.1.1.任务时间:上传批量照片的时间,精确至分钟,格式为YYYY-MM-DD HH:MM;'),
|
||||
React.createElement('div', { style: styles.requirementSubItem }, '5.1.2.照片数量:显示这一批照片总数;'),
|
||||
React.createElement('div', { style: styles.requirementSubItem }, '5.1.3.识别错误:显示识别失败的照片总数,hover时气泡卡片显示识别失败的照片名称,以;分隔;'),
|
||||
React.createElement('div', { style: styles.requirementSubItem }, '5.1.4.完成进度:显示ocr识别进度条和已完成百分比;'),
|
||||
React.createElement('div', { style: styles.requirementSubItem }, '5.1.5.操作:已完成任务操作栏显示识别,未完成任务操作栏显示-;'),
|
||||
React.createElement('div', { style: styles.requirementItem }, '5.2.识别:点击识别确认卡片中当前张数、显示照片、车辆识别代码、车牌号、强制报废日期、检验有效期,可通过二次编辑进行校正;当前张数显示在确认上牌信息标题右侧,格式为(当前/总计),依次操作直到完成所有记录提交完成,全部完成后toast提示:批量上传成功;'),
|
||||
React.createElement('div', { style: styles.requirementItem }, '5.3.在识别确认卡片中点击确认后将立刻上传该照片,可再次通过点击批量上传拉取上传任务框的方式,自动跳转至最后一条上传记录进行操作;'),
|
||||
React.createElement('div', { style: styles.requirementItem }, '5.4.批量上传任务中照片全部识别完成后,不再显示识别按钮;'),
|
||||
React.createElement('div', { style: styles.requirementItem }, '5.5.具体识别流程请参考axure菜单目录中上牌管理下的流程图;')
|
||||
)
|
||||
)
|
||||
})
|
||||
);
|
||||
};
|
||||
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);
|
||||
}
|
||||
}
|
||||
538
web端/运维管理/车辆业务/交车管理.jsx
Normal file
538
web端/运维管理/车辆业务/交车管理.jsx
Normal file
@@ -0,0 +1,538 @@
|
||||
// 【重要】必须使用 const Component 作为组件变量名
|
||||
// 车辆业务 - 交车管理(ONEOS运管平台,布局参照新增租赁合同)
|
||||
|
||||
const Component = function () {
|
||||
var useState = React.useState;
|
||||
var useCallback = React.useCallback;
|
||||
var useMemo = React.useMemo;
|
||||
|
||||
var antd = window.antd;
|
||||
var Breadcrumb = antd.Breadcrumb;
|
||||
var Card = antd.Card;
|
||||
var DatePicker = antd.DatePicker;
|
||||
var Select = antd.Select;
|
||||
var Button = antd.Button;
|
||||
var Tabs = antd.Tabs;
|
||||
var Table = antd.Table;
|
||||
var Popover = antd.Popover;
|
||||
var Cascader = antd.Cascader;
|
||||
var Modal = antd.Modal;
|
||||
var message = antd.message;
|
||||
|
||||
var RangePicker = DatePicker.RangePicker;
|
||||
|
||||
var filterState = useState({
|
||||
contractCode: undefined,
|
||||
projectName: undefined,
|
||||
customerName: undefined,
|
||||
deliveryRegion: undefined,
|
||||
dateStart: '',
|
||||
dateEnd: '',
|
||||
deliveryPerson: undefined
|
||||
});
|
||||
var filters = filterState[0];
|
||||
var setFilters = filterState[1];
|
||||
var appliedFilterState = useState({
|
||||
contractCode: undefined,
|
||||
projectName: undefined,
|
||||
customerName: undefined,
|
||||
deliveryRegion: undefined,
|
||||
dateStart: '',
|
||||
dateEnd: '',
|
||||
deliveryPerson: undefined
|
||||
});
|
||||
var appliedFilters = appliedFilterState[0];
|
||||
var setAppliedFilters = appliedFilterState[1];
|
||||
|
||||
var activeTabState = useState('pending');
|
||||
var activeTab = activeTabState[0];
|
||||
var setActiveTab = activeTabState[1];
|
||||
var pageState = useState(1);
|
||||
var pageSizeState = useState(10);
|
||||
var requirementModalOpen = useState(false);
|
||||
var setRequirementModalOpen = requirementModalOpen[1];
|
||||
|
||||
var requirementDocContent = '交车管理\n\n1.面包屑:\n1.1.运维管理-车辆业务-交车管理\n\n2.筛选:\n2.1.合同编码:选择器,默认为所有合同;提示信息为:请输入或选择合同编码,支持从输入框输入内容进行模糊搜索,下拉显示结果;\n2.2.项目名称:选择器,默认为所有项目;提示信息为:请输入或选择项目名称,支持从输入框输入内容进行模糊搜索,下拉显示结果;\n3.3.客户名称:选择器,默认为所有客户;提示信息为:请输入或选择客户名称,支持从输入框输入内容进行模糊搜索,下拉显示结果;\n3.4.交车区域:地区选择器,支持省-市2级筛选;\n3.5.交车时间:日期选择器,默认提示信息为:请选择交车开始时间 请选择交车结束时间,单输入框,双日历,支持时间段选择,精确至天,格式为:YYYY-MM-DD - YYYY-MM-DD;\n3.6.交车人:选择器,默认为所有交车人;提示信息为:请输入或选择交车人姓名,支持从输入框输入内容进行模糊搜索,下拉显示结果;\n3.7.查询:点击查询,根据单个或多个筛选条件(且)联动表格进行查询;\n3.8.重置:点击清空查询条件至默认;\n\n3.列表:\n分为两个tab:待处理、历史记录\n3.1.待处理:显示以下字段:\n3.1.1.预计交车时间:支持单日及开始-结束日期两种方式,格式为:YYYY-MM-DD及YYYY-MM-DD至YYYY-MM-DD,取自对应交车任务中预计交车时间;\n3.1.2.任务发布时间:显示交车任务单生成时间,格式为:YYYY-MM-DD HH:MM;\n3.1.3.合同编码:显示租赁/自营合同编码;\n3.1.4.项目名称:显示租赁/自营合同项目名称;\n3.1.5.客户名称:显示租赁/自营合同客户名称;\n3.1.6.交车数量:显示交车数量,重点色显示,点击弹出气泡卡片,列表显示:车辆类型、品牌、型号、车牌号;\n 3.1.6.1.车辆类型:显示车辆类型;\n 3.1.6.2.品牌:显示车辆品牌;\n 3.1.6.3.型号:显示车辆型号;\n 3.1.6.4.车牌号:显示交车车辆车牌号,如果该车还未交车则显示为-;\n3.1.7.交车区域:显示交车区域,交车区域来自车辆租赁合同-交车区域,格式为省-市;\n3.1.8.交车地点:显示交车地点,交车地点来自车辆租赁合同-交车地点,显示详细地址;\n3.1.9.操作:查看、交车;\n 3.1.8.1.交车:点击跳转交车单页面;\n\n3.2.历史记录:显示以下字段:\n3.2.1.预计交车时间:支持单日及开始-结束日期两种方式,格式为:YYYY-MM-DD及YYYY-MM-DD至YYYY-MM-DD,取自对应交车任务中预计交车时间;\n3.2.2.任务发布时间:显示交车任务单生成时间,格式为:YYYY-MM-DD HH:MM;\n3.2.3.交车完成时间:显示交车单完成时间,格式为:YYYY-MM-DD HH:MM;\n3.2.4.交车人:显示交车单最终提交用户;\n3.2.5.合同编码:显示租赁/自营合同编码;\n3.2.6.项目名称:显示租赁/自营合同项目名称;\n3.2.7.客户名称:显示租赁/自营合同客户名称;\n3.2.8.交车数量:显示交车数,重点色显示,点击弹出气泡卡片,列表显示:车辆类型、品牌、型号、车牌号、实际交车日期、交车人;\n 3.2.8.1.车辆类型:显示车辆类型;\n 3.2.8.2.品牌:显示车辆品牌;\n 3.2.8.3.型号:显示车辆型号;\n 3.2.8.4.车牌号:显示交车车辆车牌号,如果该车还未交车则显示为-;\n 3.2.8.5.实际交车日期:显示实际交车日期,格式为YYYY-MM-DD,如该车还未交车则显示为-;\n 3.2.8.6.交车人:显示实际交车人用户姓名,如该车还未还车则显示为-;\n3.2.9.交车区域:显示交车区域,交车区域来自车辆租赁合同-交车区域,格式为省-市;\n3.2.10.交车地点:显示交车地点,交车地点来自车辆租赁合同-交车地点,显示详细地址;\n3.2.11.操作:查看;\n 3.2.11.1.查看:点击跳转查看交车单页面;';
|
||||
|
||||
// 交车区域:省-市 二级
|
||||
var regionOptions = [
|
||||
{ value: 'zhejiang', label: '浙江省', children: [{ value: 'hangzhou', label: '杭州市' }, { value: 'jiaxing', label: '嘉兴市' }, { value: 'ningbo', label: '宁波市' }] },
|
||||
{ value: 'shanghai', label: '上海市', children: [{ value: 'shanghai', label: '上海市' }] },
|
||||
{ value: 'guangdong', label: '广东省', children: [{ value: 'guangzhou', label: '广州市' }, { value: 'shenzhen', label: '深圳市' }] }
|
||||
];
|
||||
|
||||
var contractCodeOptions = [
|
||||
{ value: 'HT-ZL-2025-001', label: 'HT-ZL-2025-001' },
|
||||
{ value: 'HT-ZL-2025-002', label: 'HT-ZL-2025-002' },
|
||||
{ value: 'HT-ZL-2025-003', label: 'HT-ZL-2025-003' }
|
||||
];
|
||||
var projectNameOptions = [
|
||||
{ value: 'p1', label: '嘉兴氢能示范项目' },
|
||||
{ value: 'p2', label: '上海物流租赁项目' },
|
||||
{ value: 'p3', label: '杭州城配租赁项目' }
|
||||
];
|
||||
var customerNameOptions = [
|
||||
{ value: 'c1', label: '嘉兴某某物流有限公司' },
|
||||
{ value: 'c2', label: '上海某某运输公司' },
|
||||
{ value: 'c3', label: '杭州某某租赁有限公司' }
|
||||
];
|
||||
var deliveryPersonOptions = [
|
||||
{ value: '张三', label: '张三' },
|
||||
{ value: '李四', label: '李四' },
|
||||
{ value: '王五', label: '王五' }
|
||||
];
|
||||
|
||||
// 待处理 mock(10条样例)
|
||||
var pendingListState = useState([
|
||||
{ id: 'd1', expectedDate: '2025-02-28', taskPublishTime: '2025-02-20 09:00', contractCode: 'HT-ZL-2025-001', projectName: '嘉兴氢能示范项目', customerName: '嘉兴某某物流有限公司', deliveryCount: 2, vehicleList: [{ vehicleType: '厢式货车', brand: '东风', model: 'DFH1180', plateNo: '京A12345' }, { vehicleType: '平板货车', brand: '福田', model: 'BJ1180', plateNo: '-' }], deliveryRegion: '浙江省-嘉兴市', deliveryAddress: '嘉兴市南湖区科技大道1号' },
|
||||
{ id: 'd2', expectedDate: '2025-03-01 至 2025-03-05', taskPublishTime: '2025-02-21 10:30', contractCode: 'HT-ZL-2025-002', projectName: '上海物流租赁项目', customerName: '上海某某运输公司', deliveryCount: 1, vehicleList: [{ vehicleType: '厢式货车', brand: '江淮', model: 'HFC1180', plateNo: '-' }], deliveryRegion: '上海市-上海市', deliveryAddress: '浦东新区张江高科技园区' },
|
||||
{ id: 'd3', expectedDate: '2025-02-25', taskPublishTime: '2025-02-18 14:00', contractCode: 'HT-ZL-2025-003', projectName: '杭州城配租赁项目', customerName: '杭州某某租赁有限公司', deliveryCount: 3, vehicleList: [{ vehicleType: '栏板货车', brand: '重汽', model: 'ZZ1180', plateNo: '浙A10001' }, { vehicleType: '厢式货车', brand: '东风', model: 'DFH1190', plateNo: '-' }, { vehicleType: '平板货车', brand: '福田', model: 'BJ1190', plateNo: '-' }], deliveryRegion: '浙江省-杭州市', deliveryAddress: '余杭区未来科技城' },
|
||||
{ id: 'd4', expectedDate: '2025-03-08', taskPublishTime: '2025-02-25 08:15', contractCode: 'HT-ZL-2025-004', projectName: '嘉兴氢能示范项目', customerName: '嘉兴某某物流有限公司', deliveryCount: 1, vehicleList: [{ vehicleType: '厢式货车', brand: '重汽', model: 'ZZ1160', plateNo: '-' }], deliveryRegion: '浙江省-嘉兴市', deliveryAddress: '嘉兴市秀洲区洪兴西路288号' },
|
||||
{ id: 'd5', expectedDate: '2025-03-10 至 2025-03-12', taskPublishTime: '2025-02-26 11:20', contractCode: 'HT-ZL-2025-005', projectName: '上海物流租赁项目', customerName: '上海某某运输公司', deliveryCount: 2, vehicleList: [{ vehicleType: '平板货车', brand: '福田', model: 'BJ1180', plateNo: '-' }, { vehicleType: '栏板货车', brand: '东风', model: 'DFH1160', plateNo: '-' }], deliveryRegion: '上海市-上海市', deliveryAddress: '闵行区莘庄工业区申富路669号' },
|
||||
{ id: 'd6', expectedDate: '2025-03-15', taskPublishTime: '2025-03-01 09:30', contractCode: 'HT-ZL-2025-006', projectName: '杭州城配租赁项目', customerName: '杭州某某租赁有限公司', deliveryCount: 4, vehicleList: [{ vehicleType: '厢式货车', brand: '江淮', model: 'HFC1180', plateNo: '-' }, { vehicleType: '厢式货车', brand: '东风', model: 'DFH1180', plateNo: '-' }, { vehicleType: '平板货车', brand: '福田', model: 'BJ1190', plateNo: '-' }, { vehicleType: '栏板货车', brand: '重汽', model: 'ZZ1180', plateNo: '-' }], deliveryRegion: '浙江省-杭州市', deliveryAddress: '萧山区市心北路108号' },
|
||||
{ id: 'd7', expectedDate: '2025-03-18', taskPublishTime: '2025-03-03 14:00', contractCode: 'HT-ZL-2025-007', projectName: '嘉兴氢能示范项目', customerName: '嘉兴某某物流有限公司', deliveryCount: 1, vehicleList: [{ vehicleType: '平板货车', brand: '福田', model: 'BJ1180', plateNo: '浙F80088' }], deliveryRegion: '浙江省-嘉兴市', deliveryAddress: '嘉兴市经开区昌盛路1号' },
|
||||
{ id: 'd8', expectedDate: '2025-03-20 至 2025-03-22', taskPublishTime: '2025-03-05 10:00', contractCode: 'HT-ZL-2025-008', projectName: '上海物流租赁项目', customerName: '上海某某运输公司', deliveryCount: 3, vehicleList: [{ vehicleType: '厢式货车', brand: '江淮', model: 'HFC1190', plateNo: '-' }, { vehicleType: '栏板货车', brand: '重汽', model: 'ZZ1190', plateNo: '-' }, { vehicleType: '厢式货车', brand: '东风', model: 'DFH1190', plateNo: '-' }], deliveryRegion: '上海市-上海市', deliveryAddress: '宝山区沪太路5008号' },
|
||||
{ id: 'd9', expectedDate: '2025-03-25', taskPublishTime: '2025-03-08 08:45', contractCode: 'HT-ZL-2025-009', projectName: '杭州城配租赁项目', customerName: '杭州某某租赁有限公司', deliveryCount: 2, vehicleList: [{ vehicleType: '栏板货车', brand: '东风', model: 'DFH1160', plateNo: '-' }, { vehicleType: '平板货车', brand: '福田', model: 'BJ1180', plateNo: '浙A20002' }], deliveryRegion: '浙江省-杭州市', deliveryAddress: '滨江区网商路699号' },
|
||||
{ id: 'd10', expectedDate: '2025-03-28', taskPublishTime: '2025-03-10 16:20', contractCode: 'HT-ZL-2025-010', projectName: '嘉兴氢能示范项目', customerName: '嘉兴某某物流有限公司', deliveryCount: 1, vehicleList: [{ vehicleType: '厢式货车', brand: '重汽', model: 'ZZ1180', plateNo: '-' }], deliveryRegion: '浙江省-嘉兴市', deliveryAddress: '嘉兴市南湖区广益路与由拳路交叉口' }
|
||||
]);
|
||||
var pendingList = pendingListState[0];
|
||||
|
||||
// 历史记录 mock(10条样例,含交车完成时间、交车人,vehicleList 含实际交车日期、交车人)
|
||||
var historyListState = useState([
|
||||
{ id: 'h1', expectedDate: '2025-02-15', taskPublishTime: '2025-02-10 09:00', completeTime: '2025-02-15 14:30', deliveryPerson: '张三', contractCode: 'HT-ZL-2024-001', projectName: '嘉兴氢能示范项目', customerName: '嘉兴某某物流有限公司', deliveryCount: 2, vehicleList: [{ vehicleType: '厢式货车', brand: '东风', model: 'DFH1180', plateNo: '京A12345', actualDate: '2025-02-15', deliveryPerson: '张三' }, { vehicleType: '平板货车', brand: '福田', model: 'BJ1180', plateNo: '京C11111', actualDate: '2025-02-15', deliveryPerson: '李四' }], deliveryRegion: '浙江省-嘉兴市', deliveryAddress: '嘉兴市南湖区科技大道1号' },
|
||||
{ id: 'h2', expectedDate: '2025-02-10 至 2025-02-12', taskPublishTime: '2025-02-05 10:00', completeTime: '2025-02-12 11:00', deliveryPerson: '王五', contractCode: 'HT-ZL-2024-002', projectName: '上海物流租赁项目', customerName: '上海某某运输公司', deliveryCount: 1, vehicleList: [{ vehicleType: '厢式货车', brand: '江淮', model: 'HFC1180', plateNo: '沪A20002', actualDate: '2025-02-11', deliveryPerson: '王五' }], deliveryRegion: '上海市-上海市', deliveryAddress: '浦东新区张江路100号' },
|
||||
{ id: 'h3', expectedDate: '2025-02-18', taskPublishTime: '2025-02-12 08:30', completeTime: '2025-02-18 15:00', deliveryPerson: '张三', contractCode: 'HT-ZL-2024-003', projectName: '杭州城配租赁项目', customerName: '杭州某某租赁有限公司', deliveryCount: 3, vehicleList: [{ vehicleType: '栏板货车', brand: '重汽', model: 'ZZ1180', plateNo: '浙A10001', actualDate: '2025-02-18', deliveryPerson: '张三' }, { vehicleType: '厢式货车', brand: '东风', model: 'DFH1190', plateNo: '浙A10002', actualDate: '2025-02-18', deliveryPerson: '李四' }, { vehicleType: '平板货车', brand: '福田', model: 'BJ1190', plateNo: '浙A10003', actualDate: '2025-02-18', deliveryPerson: '王五' }], deliveryRegion: '浙江省-杭州市', deliveryAddress: '余杭区未来科技城' },
|
||||
{ id: 'h4', expectedDate: '2025-02-20', taskPublishTime: '2025-02-14 11:00', completeTime: '2025-02-20 10:15', deliveryPerson: '李四', contractCode: 'HT-ZL-2024-004', projectName: '嘉兴氢能示范项目', customerName: '嘉兴某某物流有限公司', deliveryCount: 1, vehicleList: [{ vehicleType: '厢式货车', brand: '江淮', model: 'HFC1180', plateNo: '浙F60001', actualDate: '2025-02-20', deliveryPerson: '李四' }], deliveryRegion: '浙江省-嘉兴市', deliveryAddress: '嘉兴市秀洲区洪兴西路288号' },
|
||||
{ id: 'h5', expectedDate: '2025-02-22 至 2025-02-24', taskPublishTime: '2025-02-16 09:45', completeTime: '2025-02-24 16:30', deliveryPerson: '王五', contractCode: 'HT-ZL-2024-005', projectName: '上海物流租赁项目', customerName: '上海某某运输公司', deliveryCount: 2, vehicleList: [{ vehicleType: '平板货车', brand: '福田', model: 'BJ1180', plateNo: '沪B30001', actualDate: '2025-02-23', deliveryPerson: '王五' }, { vehicleType: '栏板货车', brand: '东风', model: 'DFH1160', plateNo: '沪B30002', actualDate: '2025-02-24', deliveryPerson: '张三' }], deliveryRegion: '上海市-上海市', deliveryAddress: '闵行区莘庄工业区申富路669号' },
|
||||
{ id: 'h6', expectedDate: '2025-02-25', taskPublishTime: '2025-02-18 14:20', completeTime: '2025-02-25 11:00', deliveryPerson: '张三', contractCode: 'HT-ZL-2024-006', projectName: '杭州城配租赁项目', customerName: '杭州某某租赁有限公司', deliveryCount: 1, vehicleList: [{ vehicleType: '厢式货车', brand: '重汽', model: 'ZZ1160', plateNo: '浙A40001', actualDate: '2025-02-25', deliveryPerson: '张三' }], deliveryRegion: '浙江省-杭州市', deliveryAddress: '萧山区市心北路108号' },
|
||||
{ id: 'h7', expectedDate: '2025-02-28', taskPublishTime: '2025-02-20 10:10', completeTime: '2025-02-28 14:45', deliveryPerson: '李四', contractCode: 'HT-ZL-2024-007', projectName: '嘉兴氢能示范项目', customerName: '嘉兴某某物流有限公司', deliveryCount: 2, vehicleList: [{ vehicleType: '厢式货车', brand: '东风', model: 'DFH1180', plateNo: '浙F70001', actualDate: '2025-02-28', deliveryPerson: '李四' }, { vehicleType: '平板货车', brand: '福田', model: 'BJ1180', plateNo: '浙F70002', actualDate: '2025-02-28', deliveryPerson: '王五' }], deliveryRegion: '浙江省-嘉兴市', deliveryAddress: '嘉兴市经开区昌盛路1号' },
|
||||
{ id: 'h8', expectedDate: '2025-03-02', taskPublishTime: '2025-02-22 08:00', completeTime: '2025-03-02 09:30', deliveryPerson: '王五', contractCode: 'HT-ZL-2024-008', projectName: '上海物流租赁项目', customerName: '上海某某运输公司', deliveryCount: 1, vehicleList: [{ vehicleType: '栏板货车', brand: '江淮', model: 'HFC1160', plateNo: '沪A50001', actualDate: '2025-03-02', deliveryPerson: '王五' }], deliveryRegion: '上海市-上海市', deliveryAddress: '宝山区沪太路5008号' },
|
||||
{ id: 'h9', expectedDate: '2025-03-05 至 2025-03-07', taskPublishTime: '2025-02-25 15:30', completeTime: '2025-03-07 13:20', deliveryPerson: '张三', contractCode: 'HT-ZL-2024-009', projectName: '杭州城配租赁项目', customerName: '杭州某某租赁有限公司', deliveryCount: 2, vehicleList: [{ vehicleType: '厢式货车', brand: '江淮', model: 'HFC1190', plateNo: '浙A60001', actualDate: '2025-03-06', deliveryPerson: '张三' }, { vehicleType: '栏板货车', brand: '重汽', model: 'ZZ1190', plateNo: '浙A60002', actualDate: '2025-03-07', deliveryPerson: '李四' }], deliveryRegion: '浙江省-杭州市', deliveryAddress: '滨江区网商路699号' },
|
||||
{ id: 'h10', expectedDate: '2025-03-10', taskPublishTime: '2025-03-01 11:00', completeTime: '2025-03-10 10:00', deliveryPerson: '李四', contractCode: 'HT-ZL-2024-010', projectName: '嘉兴氢能示范项目', customerName: '嘉兴某某物流有限公司', deliveryCount: 1, vehicleList: [{ vehicleType: '平板货车', brand: '福田', model: 'BJ1190', plateNo: '浙F90001', actualDate: '2025-03-10', deliveryPerson: '李四' }], deliveryRegion: '浙江省-嘉兴市', deliveryAddress: '嘉兴市南湖区广益路与由拳路交叉口' }
|
||||
]);
|
||||
var historyList = historyListState[0];
|
||||
|
||||
var filteredPending = useMemo(function () {
|
||||
var list = pendingList.slice();
|
||||
if (appliedFilters.contractCode) list = list.filter(function (r) { return (r.contractCode || '').indexOf(appliedFilters.contractCode) !== -1; });
|
||||
if (appliedFilters.projectName) list = list.filter(function (r) { return r.projectName === appliedFilters.projectName; });
|
||||
if (appliedFilters.customerName) list = list.filter(function (r) { return r.customerName === appliedFilters.customerName; });
|
||||
if (appliedFilters.deliveryRegion) list = list.filter(function (r) { return (r.deliveryRegion || '').indexOf(appliedFilters.deliveryRegion) !== -1; });
|
||||
if (appliedFilters.dateStart) list = list.filter(function (r) { var d = (r.expectedDate || '').slice(0, 10); return d >= appliedFilters.dateStart; });
|
||||
if (appliedFilters.dateEnd) list = list.filter(function (r) { var d = (r.expectedDate || '').slice(0, 10); return d <= appliedFilters.dateEnd; });
|
||||
return list;
|
||||
}, [pendingList, appliedFilters]);
|
||||
|
||||
var filteredHistory = useMemo(function () {
|
||||
var list = historyList.slice();
|
||||
if (appliedFilters.contractCode) list = list.filter(function (r) { return (r.contractCode || '').indexOf(appliedFilters.contractCode) !== -1; });
|
||||
if (appliedFilters.projectName) list = list.filter(function (r) { return r.projectName === appliedFilters.projectName; });
|
||||
if (appliedFilters.customerName) list = list.filter(function (r) { return r.customerName === appliedFilters.customerName; });
|
||||
if (appliedFilters.deliveryRegion) list = list.filter(function (r) { return (r.deliveryRegion || '').indexOf(appliedFilters.deliveryRegion) !== -1; });
|
||||
if (appliedFilters.dateStart) list = list.filter(function (r) { var d = (r.completeTime || '').slice(0, 10); return d >= appliedFilters.dateStart; });
|
||||
if (appliedFilters.dateEnd) list = list.filter(function (r) { var d = (r.completeTime || '').slice(0, 10); return d <= appliedFilters.dateEnd; });
|
||||
if (appliedFilters.deliveryPerson) list = list.filter(function (r) { return (r.deliveryPerson || '').indexOf(appliedFilters.deliveryPerson) !== -1; });
|
||||
return list;
|
||||
}, [historyList, appliedFilters]);
|
||||
|
||||
var page = pageState[0];
|
||||
var setPage = pageState[1];
|
||||
var pageSize = pageSizeState[0];
|
||||
var setPageSize = pageSizeState[1];
|
||||
var totalCount = activeTab === 'pending' ? filteredPending.length : filteredHistory.length;
|
||||
var displayPending = useMemo(function () {
|
||||
var start = (page - 1) * pageSize;
|
||||
return filteredPending.slice(start, start + pageSize);
|
||||
}, [filteredPending, page, pageSize]);
|
||||
var displayHistory = useMemo(function () {
|
||||
var start = (page - 1) * pageSize;
|
||||
return filteredHistory.slice(start, start + pageSize);
|
||||
}, [filteredHistory, page, pageSize]);
|
||||
|
||||
var handleQuery = useCallback(function () {
|
||||
var regionVal = filters.deliveryRegion;
|
||||
if (Array.isArray(regionVal) && regionVal.length >= 2) {
|
||||
var prov = regionOptions.find(function (r) { return r.value === regionVal[0]; });
|
||||
var city = prov && prov.children && prov.children.find(function (c) { return c.value === regionVal[1]; });
|
||||
regionVal = prov && city ? prov.label + '-' + city.label : undefined;
|
||||
} else if (Array.isArray(regionVal) && regionVal.length === 1) {
|
||||
var p = regionOptions.find(function (r) { return r.value === regionVal[0]; });
|
||||
regionVal = p ? p.label : undefined;
|
||||
}
|
||||
setAppliedFilters({
|
||||
contractCode: filters.contractCode,
|
||||
projectName: filters.projectName,
|
||||
customerName: filters.customerName,
|
||||
deliveryRegion: regionVal,
|
||||
dateStart: filters.dateStart,
|
||||
dateEnd: filters.dateEnd,
|
||||
deliveryPerson: filters.deliveryPerson
|
||||
});
|
||||
setPage(1);
|
||||
}, [filters]);
|
||||
|
||||
var handleReset = useCallback(function () {
|
||||
var empty = { contractCode: undefined, projectName: undefined, customerName: undefined, deliveryRegion: undefined, dateStart: '', dateEnd: '', deliveryPerson: undefined };
|
||||
setFilters(empty);
|
||||
setAppliedFilters(empty);
|
||||
setPage(1);
|
||||
}, []);
|
||||
|
||||
var handleExport = useCallback(function () {
|
||||
var rows = activeTab === 'pending' ? filteredPending : filteredHistory;
|
||||
if (!rows || rows.length === 0) {
|
||||
message.warning('当前无数据可导出');
|
||||
return;
|
||||
}
|
||||
var escapeCsv = function (v) {
|
||||
var s = v == null ? '' : String(v);
|
||||
if (s.indexOf(',') !== -1 || s.indexOf('"') !== -1 || s.indexOf('\n') !== -1) return '"' + s.replace(/"/g, '""') + '"';
|
||||
return s;
|
||||
};
|
||||
var headers;
|
||||
var rowToCells = function (r) {
|
||||
if (activeTab === 'pending') {
|
||||
return [r.expectedDate, r.taskPublishTime, r.contractCode, r.projectName, r.customerName, r.deliveryCount, r.deliveryRegion, r.deliveryAddress];
|
||||
}
|
||||
return [r.expectedDate, r.taskPublishTime, r.completeTime, r.deliveryPerson, r.contractCode, r.projectName, r.customerName, r.deliveryCount, r.deliveryRegion, r.deliveryAddress];
|
||||
};
|
||||
if (activeTab === 'pending') {
|
||||
headers = ['预计交车时间', '任务发布时间', '合同编码', '项目名称', '客户名称', '交车数量', '交车区域', '交车地点'];
|
||||
} else {
|
||||
headers = ['预计交车时间', '任务发布时间', '交车完成时间', '交车人', '合同编码', '项目名称', '客户名称', '交车数量', '交车区域', '交车地点'];
|
||||
}
|
||||
var csv = headers.map(escapeCsv).join(',') + '\n';
|
||||
rows.forEach(function (r) {
|
||||
csv += rowToCells(r).map(escapeCsv).join(',') + '\n';
|
||||
});
|
||||
var blob = new Blob(['\ufeff' + csv], { type: 'text/csv;charset=utf-8' });
|
||||
var url = URL.createObjectURL(blob);
|
||||
var a = document.createElement('a');
|
||||
a.href = url;
|
||||
a.download = '交车管理_' + (activeTab === 'pending' ? '待处理' : '历史记录') + '_' + new Date().getTime() + '.csv';
|
||||
a.click();
|
||||
URL.revokeObjectURL(url);
|
||||
message.success('导出成功');
|
||||
}, [activeTab, filteredPending, filteredHistory]);
|
||||
|
||||
var dateRangeValue = useMemo(function () {
|
||||
if (!filters.dateStart && !filters.dateEnd) return null;
|
||||
try {
|
||||
if (typeof window !== 'undefined' && window.dayjs && filters.dateStart && filters.dateEnd) {
|
||||
return [window.dayjs(filters.dateStart), window.dayjs(filters.dateEnd)];
|
||||
}
|
||||
} catch (e) {}
|
||||
return null;
|
||||
}, [filters.dateStart, filters.dateEnd]);
|
||||
|
||||
var onDateRangeChange = useCallback(function (dates, dateStrings) {
|
||||
setFilters(function (f) {
|
||||
var g = {}; for (var k in f) g[k] = f[k];
|
||||
g.dateStart = (dateStrings && dateStrings[0]) || '';
|
||||
g.dateEnd = (dateStrings && dateStrings[1]) || '';
|
||||
return g;
|
||||
});
|
||||
}, []);
|
||||
|
||||
// 交车区域 Cascader 的 value:用 appliedFilters 反推或存 value 数组。筛选用字符串比较,表单用 Cascader 选省-市
|
||||
var deliveryRegionValue = useMemo(function () {
|
||||
var s = filters.deliveryRegion;
|
||||
if (!s || typeof s !== 'string') return undefined;
|
||||
var parts = s.split('-');
|
||||
if (parts.length < 2) return undefined;
|
||||
for (var i = 0; i < regionOptions.length; i++) {
|
||||
var prov = regionOptions[i];
|
||||
if (prov.label !== parts[0]) continue;
|
||||
for (var j = 0; j < (prov.children || []).length; j++) {
|
||||
if (prov.children[j].label === parts[1]) return [prov.value, prov.children[j].value];
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
}, [filters.deliveryRegion]);
|
||||
|
||||
// 列表列:待处理
|
||||
var popoverTableStyle = { width: '100%', borderCollapse: 'collapse', fontSize: 12 };
|
||||
var popoverThStyle = { padding: '6px 8px', textAlign: 'left', borderBottom: '1px solid #f0f0f0', backgroundColor: '#fafafa', fontWeight: 600 };
|
||||
var popoverTdStyle = { padding: '6px 8px', borderBottom: '1px solid #f0f0f0' };
|
||||
|
||||
function renderPendingQuantity(record) {
|
||||
var list = record.vehicleList || [];
|
||||
var content = React.createElement('div', { style: { padding: 8, minWidth: 320 } },
|
||||
React.createElement('div', { style: { marginBottom: 8, fontWeight: 600 } }, '车辆明细'),
|
||||
React.createElement('table', { style: popoverTableStyle },
|
||||
React.createElement('thead', null,
|
||||
React.createElement('tr', null,
|
||||
React.createElement('th', { style: popoverThStyle }, '车辆类型'),
|
||||
React.createElement('th', { style: popoverThStyle }, '品牌'),
|
||||
React.createElement('th', { style: popoverThStyle }, '型号'),
|
||||
React.createElement('th', { style: popoverThStyle }, '车牌号')
|
||||
)
|
||||
),
|
||||
React.createElement('tbody', null,
|
||||
list.map(function (v, i) {
|
||||
return React.createElement('tr', { key: i },
|
||||
React.createElement('td', { style: popoverTdStyle }, v.vehicleType || '-'),
|
||||
React.createElement('td', { style: popoverTdStyle }, v.brand || '-'),
|
||||
React.createElement('td', { style: popoverTdStyle }, v.model || '-'),
|
||||
React.createElement('td', { style: popoverTdStyle }, v.plateNo || '-')
|
||||
);
|
||||
})
|
||||
)
|
||||
)
|
||||
);
|
||||
return React.createElement(Popover, { content: content, title: null },
|
||||
React.createElement('span', { style: { color: '#1890ff', cursor: 'pointer', fontWeight: 600 } }, record.deliveryCount + ' 辆')
|
||||
);
|
||||
}
|
||||
|
||||
function renderHistoryQuantity(record) {
|
||||
var list = record.vehicleList || [];
|
||||
var content = React.createElement('div', { style: { padding: 8, minWidth: 420 } },
|
||||
React.createElement('div', { style: { marginBottom: 8, fontWeight: 600 } }, '车辆明细'),
|
||||
React.createElement('table', { style: popoverTableStyle },
|
||||
React.createElement('thead', null,
|
||||
React.createElement('tr', null,
|
||||
React.createElement('th', { style: popoverThStyle }, '车辆类型'),
|
||||
React.createElement('th', { style: popoverThStyle }, '品牌'),
|
||||
React.createElement('th', { style: popoverThStyle }, '型号'),
|
||||
React.createElement('th', { style: popoverThStyle }, '车牌号'),
|
||||
React.createElement('th', { style: popoverThStyle }, '实际交车日期'),
|
||||
React.createElement('th', { style: popoverThStyle }, '交车人')
|
||||
)
|
||||
),
|
||||
React.createElement('tbody', null,
|
||||
list.map(function (v, i) {
|
||||
return React.createElement('tr', { key: i },
|
||||
React.createElement('td', { style: popoverTdStyle }, v.vehicleType || '-'),
|
||||
React.createElement('td', { style: popoverTdStyle }, v.brand || '-'),
|
||||
React.createElement('td', { style: popoverTdStyle }, v.model || '-'),
|
||||
React.createElement('td', { style: popoverTdStyle }, v.plateNo || '-'),
|
||||
React.createElement('td', { style: popoverTdStyle }, v.actualDate || '-'),
|
||||
React.createElement('td', { style: popoverTdStyle }, v.deliveryPerson || '-')
|
||||
);
|
||||
})
|
||||
)
|
||||
)
|
||||
);
|
||||
return React.createElement(Popover, { content: content, title: null },
|
||||
React.createElement('span', { style: { color: '#1890ff', cursor: 'pointer', fontWeight: 600 } }, record.deliveryCount + ' 辆')
|
||||
);
|
||||
}
|
||||
|
||||
var pendingColumns = [
|
||||
{ title: '预计交车时间', dataIndex: 'expectedDate', key: 'expectedDate', width: 260, ellipsis: true },
|
||||
{ title: '任务发布时间', dataIndex: 'taskPublishTime', key: 'taskPublishTime', width: 160, ellipsis: true },
|
||||
{ title: '合同编码', dataIndex: 'contractCode', key: 'contractCode', width: 160, ellipsis: true },
|
||||
{ title: '项目名称', dataIndex: 'projectName', key: 'projectName', width: 160, ellipsis: true },
|
||||
{ title: '客户名称', dataIndex: 'customerName', key: 'customerName', width: 180, ellipsis: true },
|
||||
{ title: '交车数量', key: 'deliveryCount', width: 100, render: function (_, r) { return renderPendingQuantity(r); } },
|
||||
{ title: '交车区域', dataIndex: 'deliveryRegion', key: 'deliveryRegion', width: 130, ellipsis: true },
|
||||
{ title: '交车地点', dataIndex: 'deliveryAddress', key: 'deliveryAddress', width: 220, ellipsis: true },
|
||||
{ title: '操作', key: 'action', width: 80, fixed: 'right', render: function (_, r) {
|
||||
return React.createElement(Button, { type: 'link', size: 'small', onClick: function () { message.info('跳转查看交车单'); } }, '查看');
|
||||
} }
|
||||
];
|
||||
|
||||
var historyColumns = [
|
||||
{ title: '预计交车时间', dataIndex: 'expectedDate', key: 'expectedDate', width: 260, ellipsis: true },
|
||||
{ title: '任务发布时间', dataIndex: 'taskPublishTime', key: 'taskPublishTime', width: 160, ellipsis: true },
|
||||
{ title: '交车完成时间', dataIndex: 'completeTime', key: 'completeTime', width: 160, ellipsis: true },
|
||||
{ title: '交车人', dataIndex: 'deliveryPerson', key: 'deliveryPerson', width: 100, ellipsis: true },
|
||||
{ title: '合同编码', dataIndex: 'contractCode', key: 'contractCode', width: 160, ellipsis: true },
|
||||
{ title: '项目名称', dataIndex: 'projectName', key: 'projectName', width: 160, ellipsis: true },
|
||||
{ title: '客户名称', dataIndex: 'customerName', key: 'customerName', width: 180, ellipsis: true },
|
||||
{ title: '交车数量', key: 'deliveryCount', width: 100, render: function (_, r) { return renderHistoryQuantity(r); } },
|
||||
{ title: '交车区域', dataIndex: 'deliveryRegion', key: 'deliveryRegion', width: 130, ellipsis: true },
|
||||
{ title: '交车地点', dataIndex: 'deliveryAddress', key: 'deliveryAddress', width: 220, ellipsis: true },
|
||||
{ title: '操作', key: 'action', width: 80, fixed: 'right', render: function () {
|
||||
return React.createElement(Button, { type: 'link', size: 'small', onClick: function () { message.info('跳转查看交车单页面'); } }, '查看');
|
||||
} }
|
||||
];
|
||||
|
||||
var tablePagination = useMemo(function () {
|
||||
return {
|
||||
current: page,
|
||||
pageSize: pageSize,
|
||||
total: totalCount,
|
||||
showSizeChanger: true,
|
||||
showTotal: function (t) { return '共 ' + t + ' 条'; },
|
||||
pageSizeOptions: ['10', '20', '50'],
|
||||
onChange: function (p, size) { setPage(p); if (size !== pageSize) setPageSize(size); }
|
||||
};
|
||||
}, [page, pageSize, totalCount]);
|
||||
|
||||
var styles = {
|
||||
page: { padding: '16px 24px 48px', backgroundColor: '#f5f5f5', minHeight: '100vh', fontSize: 14 },
|
||||
breadcrumb: { marginBottom: 16, color: '#666' },
|
||||
breadcrumbSep: { margin: '0 8px', color: '#999' },
|
||||
card: { backgroundColor: '#fff', borderRadius: 8, marginBottom: 16, boxShadow: '0 1px 2px rgba(0,0,0,0.05)', overflow: 'hidden' },
|
||||
cardBody: { padding: '20px 24px' },
|
||||
formRow: { display: 'grid', gridTemplateColumns: '1fr 1fr 1fr', gap: '16px 24px', alignItems: 'start' },
|
||||
formItem: { marginBottom: 4 },
|
||||
formLabel: { display: 'block', marginBottom: 4, color: '#333' }
|
||||
};
|
||||
|
||||
var breadcrumbItems = [
|
||||
{ title: '运维管理' },
|
||||
{ title: '车辆业务' },
|
||||
{ title: '交车管理' }
|
||||
];
|
||||
|
||||
return React.createElement('div', { style: styles.page },
|
||||
React.createElement('div', { style: { display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 16 } },
|
||||
React.createElement(Breadcrumb, { items: breadcrumbItems }),
|
||||
React.createElement(Button, { type: 'link', onClick: function () { setRequirementModalOpen(true); } }, '查看需求说明')
|
||||
),
|
||||
React.createElement(Card, { style: { marginBottom: 16 } },
|
||||
React.createElement('div', { style: styles.cardBody },
|
||||
React.createElement('div', { style: styles.formRow },
|
||||
React.createElement('div', null,
|
||||
React.createElement('div', { style: styles.formLabel }, '合同编码'),
|
||||
React.createElement(Select, {
|
||||
placeholder: '请输入或选择合同编码',
|
||||
allowClear: true,
|
||||
showSearch: true,
|
||||
optionFilterProp: 'label',
|
||||
value: filters.contractCode,
|
||||
onChange: function (v) { setFilters(function (f) { var g = {}; for (var k in f) g[k] = f[k]; g.contractCode = v; return g; }); },
|
||||
style: { width: '100%' },
|
||||
options: contractCodeOptions
|
||||
})
|
||||
),
|
||||
React.createElement('div', null,
|
||||
React.createElement('div', { style: styles.formLabel }, '项目名称'),
|
||||
React.createElement(Select, {
|
||||
placeholder: '请输入或选择项目名称',
|
||||
allowClear: true,
|
||||
showSearch: true,
|
||||
optionFilterProp: 'label',
|
||||
value: filters.projectName,
|
||||
onChange: function (v) { setFilters(function (f) { var g = {}; for (var k in f) g[k] = f[k]; g.projectName = v; return g; }); },
|
||||
style: { width: '100%' },
|
||||
options: projectNameOptions
|
||||
})
|
||||
),
|
||||
React.createElement('div', null,
|
||||
React.createElement('div', { style: styles.formLabel }, '客户名称'),
|
||||
React.createElement(Select, {
|
||||
placeholder: '请输入或选择客户名称',
|
||||
allowClear: true,
|
||||
showSearch: true,
|
||||
optionFilterProp: 'label',
|
||||
value: filters.customerName,
|
||||
onChange: function (v) { setFilters(function (f) { var g = {}; for (var k in f) g[k] = f[k]; g.customerName = v; return g; }); },
|
||||
style: { width: '100%' },
|
||||
options: customerNameOptions
|
||||
})
|
||||
),
|
||||
React.createElement('div', null,
|
||||
React.createElement('div', { style: styles.formLabel }, '交车区域'),
|
||||
React.createElement(Cascader, {
|
||||
options: regionOptions,
|
||||
placeholder: '请选择省-市',
|
||||
allowClear: true,
|
||||
style: { width: '100%' },
|
||||
value: deliveryRegionValue,
|
||||
onChange: function (value) {
|
||||
var s;
|
||||
if (value && value.length >= 2) {
|
||||
var prov = regionOptions.find(function (r) { return r.value === value[0]; });
|
||||
var city = prov && prov.children && prov.children.find(function (c) { return c.value === value[1]; });
|
||||
s = prov && city ? prov.label + '-' + city.label : undefined;
|
||||
} else { s = undefined; }
|
||||
setFilters(function (f) { var g = {}; for (var k in f) g[k] = f[k]; g.deliveryRegion = s; return g; });
|
||||
},
|
||||
displayRender: function (labels) { return labels && labels.length ? labels.join(' / ') : ''; }
|
||||
})
|
||||
),
|
||||
React.createElement('div', null,
|
||||
React.createElement('div', { style: styles.formLabel }, '交车时间'),
|
||||
React.createElement(RangePicker, {
|
||||
style: { width: '100%' },
|
||||
placeholder: ['请选择交车开始时间', '请选择交车结束时间'],
|
||||
value: dateRangeValue,
|
||||
onChange: onDateRangeChange
|
||||
})
|
||||
),
|
||||
React.createElement('div', null,
|
||||
React.createElement('div', { style: styles.formLabel }, '交车人'),
|
||||
React.createElement(Select, {
|
||||
placeholder: '请输入或选择交车人姓名',
|
||||
allowClear: true,
|
||||
showSearch: true,
|
||||
optionFilterProp: 'label',
|
||||
value: filters.deliveryPerson,
|
||||
onChange: function (v) { setFilters(function (f) { var g = {}; for (var k in f) g[k] = f[k]; g.deliveryPerson = v; return g; }); },
|
||||
style: { width: '100%' },
|
||||
options: deliveryPersonOptions
|
||||
})
|
||||
)
|
||||
),
|
||||
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(Tabs, {
|
||||
activeKey: activeTab,
|
||||
onChange: function (k) { setActiveTab(k); setPage(1); },
|
||||
tabBarExtraContent: React.createElement(Button, { onClick: handleExport }, '导出'),
|
||||
items: [
|
||||
{
|
||||
key: 'pending',
|
||||
label: '待处理',
|
||||
children: React.createElement(Table, {
|
||||
columns: pendingColumns,
|
||||
dataSource: displayPending,
|
||||
rowKey: 'id',
|
||||
pagination: tablePagination,
|
||||
scroll: { x: 1490 },
|
||||
size: 'middle'
|
||||
})
|
||||
},
|
||||
{
|
||||
key: 'history',
|
||||
label: '历史记录',
|
||||
children: React.createElement(Table, {
|
||||
columns: historyColumns,
|
||||
dataSource: displayHistory,
|
||||
rowKey: 'id',
|
||||
pagination: tablePagination,
|
||||
scroll: { x: 1650 },
|
||||
size: 'middle'
|
||||
})
|
||||
}
|
||||
]
|
||||
})
|
||||
),
|
||||
React.createElement(Modal, {
|
||||
title: '需求说明',
|
||||
open: requirementModalOpen[0],
|
||||
onCancel: function () { setRequirementModalOpen(false); },
|
||||
footer: React.createElement(Button, { onClick: function () { setRequirementModalOpen(false); } }, '关闭'),
|
||||
width: 640,
|
||||
destroyOnClose: true
|
||||
}, React.createElement('div', { style: { maxHeight: 560, overflowY: 'auto', whiteSpace: 'pre-wrap', lineHeight: 1.6, fontSize: 13 } }, requirementDocContent))
|
||||
);
|
||||
};
|
||||
|
||||
if (typeof window !== 'undefined') {
|
||||
window.Component = Component;
|
||||
if (document.readyState === 'loading') {
|
||||
document.addEventListener('DOMContentLoaded', function () {
|
||||
var rootEl = document.getElementById('root');
|
||||
if (rootEl && window.ReactDOM && window.React) {
|
||||
var root = ReactDOM.createRoot(rootEl);
|
||||
root.render(React.createElement(Component));
|
||||
}
|
||||
});
|
||||
} else {
|
||||
var rootEl = document.getElementById('root');
|
||||
if (rootEl && window.ReactDOM && window.React) {
|
||||
var root = ReactDOM.createRoot(rootEl);
|
||||
root.render(React.createElement(Component));
|
||||
}
|
||||
}
|
||||
}
|
||||
481
web端/运维管理/车辆业务/后装设备.jsx
Normal file
481
web端/运维管理/车辆业务/后装设备.jsx
Normal file
@@ -0,0 +1,481 @@
|
||||
// 【重要】必须使用 const Component 作为组件变量名
|
||||
// 后装设备 - 运维管理-车辆业务
|
||||
var ARCO_TOKEN = {
|
||||
primary: '#165DFF',
|
||||
primaryHover: '#4080FF',
|
||||
danger: '#F53F3F',
|
||||
success: '#00B42A',
|
||||
neutral1: '#FFFFFF',
|
||||
neutral2: '#F7F8FA',
|
||||
neutral3: '#F2F3F5',
|
||||
neutral4: '#E5E6EB',
|
||||
neutral5: '#C9CDD4',
|
||||
neutral6: '#86909C',
|
||||
neutral7: '#4E5969',
|
||||
neutral8: '#1D2129',
|
||||
border: '#E5E6EB',
|
||||
fill: '#F2F3F5',
|
||||
fillSecondary: '#F7F8FA',
|
||||
shadowLight: '0 1px 2px rgba(0,0,0,0.05)',
|
||||
radiusMedium: '4px',
|
||||
radiusLarge: '8px',
|
||||
spacing8: '8px',
|
||||
spacing12: '12px',
|
||||
spacing16: '16px',
|
||||
spacing24: '24px',
|
||||
fontSize14: '14px',
|
||||
fontSize16: '16px',
|
||||
fontFamily: '-apple-system, BlinkMacSystemFont, "PingFang SC", "Helvetica Neue", Arial, sans-serif',
|
||||
link: '#165DFF'
|
||||
};
|
||||
|
||||
var DEVICE_TYPES = ['GPS', '尾板', '车身广告', 'G7安全套件', 'G7普通设备', 'G7温控设备', '备胎'];
|
||||
|
||||
var MOCK_VEHICLE_OPTIONS = ['粤A12345', '粤A67890', '粤B11111', '粤B22222', '粤C33333', '京A88888'];
|
||||
|
||||
var MOCK_LIST = [
|
||||
{ id: '1', deviceType: 'GPS', plateNo: '粤A12345', supplier: '深圳智联', lastOpType: '安装', createTime: '2025-02-20 10:30', removeTime: '', createOperator: '张明', removeOperator: '' },
|
||||
{ id: '2', deviceType: '尾板', plateNo: '粤A67890', supplier: '广州机械', lastOpType: '拆除', createTime: '2025-02-01 09:00', removeTime: '2025-02-18 14:20', createOperator: '李强', removeOperator: '王芳' },
|
||||
{ id: '3', deviceType: '车身广告', plateNo: '粤B11111', supplier: '东莞广告', lastOpType: '安装', createTime: '2025-02-15 09:00', removeTime: '', createOperator: '李强', removeOperator: '' },
|
||||
{ id: '4', deviceType: 'G7安全套件', plateNo: '粤A12345', supplier: 'G7科技', lastOpType: '安装', createTime: '2025-02-10 16:45', removeTime: '', createOperator: '张明', removeOperator: '' },
|
||||
{ id: '5', deviceType: '备胎', plateNo: '粤C33333', supplier: '华南轮胎', lastOpType: '拆除', createTime: '2025-01-20 08:00', removeTime: '2025-02-08 11:20', createOperator: '赵六', removeOperator: '赵六' }
|
||||
];
|
||||
|
||||
const Component = function () {
|
||||
var antd = window.antd;
|
||||
var Select = antd.Select;
|
||||
var Button = antd.Button;
|
||||
var DatePicker = antd.DatePicker;
|
||||
var Table = antd.Table;
|
||||
var Modal = antd.Modal;
|
||||
var Input = antd.Input;
|
||||
var message = antd.message;
|
||||
var Option = Select.Option;
|
||||
var RangePicker = DatePicker.RangePicker;
|
||||
var Tabs = antd.Tabs;
|
||||
|
||||
var _useStateTab = React.useState('installed');
|
||||
var activeTab = _useStateTab[0];
|
||||
var setActiveTab = _useStateTab[1];
|
||||
|
||||
var _useState = React.useState('');
|
||||
var filterDeviceType = _useState[0];
|
||||
var setFilterDeviceType = _useState[1];
|
||||
|
||||
var _useState2 = React.useState('');
|
||||
var filterVehicle = _useState2[0];
|
||||
var setFilterVehicle = _useState2[1];
|
||||
|
||||
var _useState3 = React.useState([]);
|
||||
var filterDateRange = _useState3[0];
|
||||
var setFilterDateRange = _useState3[1];
|
||||
|
||||
var _useState4 = React.useState({ deviceType: '', vehicle: '', dateStart: '', dateEnd: '' });
|
||||
var appliedFilter = _useState4[0];
|
||||
var setAppliedFilter = _useState4[1];
|
||||
|
||||
var _useState5 = React.useState(1);
|
||||
var currentPage = _useState5[0];
|
||||
var setCurrentPage = _useState5[1];
|
||||
|
||||
var _useState6 = React.useState(10);
|
||||
var pageSize = _useState6[0];
|
||||
var setPageSize = _useState6[1];
|
||||
|
||||
var _useState7 = React.useState(MOCK_LIST);
|
||||
var dataList = _useState7[0];
|
||||
var setDataList = _useState7[1];
|
||||
|
||||
var _useState8 = React.useState(null);
|
||||
var viewRecord = _useState8[0];
|
||||
var setViewRecord = _useState8[1];
|
||||
|
||||
var _useState9 = React.useState(null);
|
||||
var editRecord = _useState9[0];
|
||||
var setEditRecord = _useState9[1];
|
||||
|
||||
var _useState10 = React.useState(null);
|
||||
var removeConfirmRecord = _useState10[0];
|
||||
var setRemoveConfirmRecord = _useState10[1];
|
||||
|
||||
var _useState11 = React.useState(false);
|
||||
var addModalVisible = _useState11[0];
|
||||
var setAddModalVisible = _useState11[1];
|
||||
|
||||
var _useState12 = React.useState(false);
|
||||
var showRequirementModal = _useState12[0];
|
||||
var setShowRequirementModal = _useState12[1];
|
||||
|
||||
var applyBaseFilter = function (list) {
|
||||
if (appliedFilter.deviceType) {
|
||||
list = list.filter(function (r) { return r.deviceType === appliedFilter.deviceType; });
|
||||
}
|
||||
if (appliedFilter.vehicle) {
|
||||
list = list.filter(function (r) { return r.plateNo && r.plateNo.indexOf(appliedFilter.vehicle) >= 0; });
|
||||
}
|
||||
return list;
|
||||
};
|
||||
|
||||
var installedList = dataList.filter(function (r) { return !r.removeTime || r.removeTime === ''; });
|
||||
var removedList = dataList.filter(function (r) { return r.removeTime && r.removeTime !== ''; });
|
||||
|
||||
var installedFiltered = applyBaseFilter(installedList).filter(function (r) {
|
||||
if (appliedFilter.dateStart && r.createTime) { if (r.createTime.slice(0, 10) < appliedFilter.dateStart) return false; }
|
||||
if (appliedFilter.dateEnd && r.createTime) { if (r.createTime.slice(0, 10) > appliedFilter.dateEnd) return false; }
|
||||
return true;
|
||||
});
|
||||
var removedFiltered = applyBaseFilter(removedList).filter(function (r) {
|
||||
if (appliedFilter.dateStart && r.removeTime) { if (r.removeTime.slice(0, 10) < appliedFilter.dateStart) return false; }
|
||||
if (appliedFilter.dateEnd && r.removeTime) { if (r.removeTime.slice(0, 10) > appliedFilter.dateEnd) return false; }
|
||||
return true;
|
||||
});
|
||||
|
||||
var filteredList = activeTab === 'installed' ? installedFiltered : removedFiltered;
|
||||
var totalItems = filteredList.length;
|
||||
var totalPages = Math.ceil(totalItems / pageSize) || 1;
|
||||
var validPage = currentPage > totalPages && totalPages > 0 ? 1 : (currentPage < 1 ? 1 : currentPage);
|
||||
var startIndex = (validPage - 1) * pageSize;
|
||||
var paginatedList = filteredList.slice(startIndex, startIndex + pageSize);
|
||||
|
||||
var handleQuery = function () {
|
||||
var dateStart = '';
|
||||
var dateEnd = '';
|
||||
if (filterDateRange && filterDateRange.length >= 2 && filterDateRange[0] && filterDateRange[1]) {
|
||||
if (filterDateRange[0].format) {
|
||||
dateStart = filterDateRange[0].format('YYYY-MM-DD');
|
||||
dateEnd = filterDateRange[1].format('YYYY-MM-DD');
|
||||
} else if (window.dayjs) {
|
||||
dateStart = window.dayjs(filterDateRange[0]).format('YYYY-MM-DD');
|
||||
dateEnd = window.dayjs(filterDateRange[1]).format('YYYY-MM-DD');
|
||||
}
|
||||
}
|
||||
setAppliedFilter({
|
||||
deviceType: filterDeviceType,
|
||||
vehicle: filterVehicle,
|
||||
dateStart: dateStart,
|
||||
dateEnd: dateEnd
|
||||
});
|
||||
setCurrentPage(1);
|
||||
message.success('查询成功');
|
||||
};
|
||||
|
||||
var handleReset = function () {
|
||||
setFilterDeviceType('');
|
||||
setFilterVehicle('');
|
||||
setFilterDateRange([]);
|
||||
setAppliedFilter({ deviceType: '', vehicle: '', dateStart: '', dateEnd: '' });
|
||||
setCurrentPage(1);
|
||||
};
|
||||
|
||||
var handleRemoveConfirm = function (row) {
|
||||
var nowStr = '2025-02-24 15:00';
|
||||
if (window.dayjs) { nowStr = window.dayjs().format('YYYY-MM-DD HH:mm'); }
|
||||
setDataList(dataList.map(function (r) {
|
||||
if (r.id === row.id) {
|
||||
return { id: r.id, deviceType: r.deviceType, plateNo: r.plateNo, supplier: r.supplier, lastOpType: '拆除', createTime: r.createTime, removeTime: nowStr, createOperator: r.createOperator, removeOperator: '当前用户' };
|
||||
}
|
||||
return r;
|
||||
}));
|
||||
setRemoveConfirmRecord(null);
|
||||
message.success('拆除成功');
|
||||
};
|
||||
|
||||
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: '8px' },
|
||||
breadcrumbCurrent: { color: t.neutral8 },
|
||||
requirementLink: { color: t.link, textDecoration: 'none', fontSize: t.fontSize14, cursor: 'pointer' },
|
||||
modalContent: { fontSize: t.fontSize14, color: t.neutral8, lineHeight: 1.6 },
|
||||
requirementSection: { marginBottom: t.spacing16 },
|
||||
requirementSectionTitle: { fontSize: t.fontSize16, fontWeight: 600, color: t.neutral8, marginBottom: 8 },
|
||||
requirementItem: { marginBottom: 8, paddingLeft: 16 },
|
||||
requirementSubItem: { marginBottom: 4, paddingLeft: 16, color: t.neutral7 },
|
||||
card: { backgroundColor: t.neutral1, borderRadius: t.radiusLarge, boxShadow: t.shadowLight, marginBottom: t.spacing16, padding: t.spacing16 },
|
||||
filterRow: { display: 'flex', flexWrap: 'wrap', alignItems: 'center', gap: t.spacing12 },
|
||||
label: { marginRight: t.spacing8, fontSize: t.fontSize14, color: t.neutral8, whiteSpace: 'nowrap' },
|
||||
filterRight: { marginLeft: 'auto', display: 'flex', gap: t.spacing8 },
|
||||
toolbar: { display: 'flex', justifyContent: 'flex-end', gap: t.spacing12, marginBottom: t.spacing8 }
|
||||
};
|
||||
|
||||
var deviceTypeOptions = DEVICE_TYPES.map(function (type) {
|
||||
return React.createElement(Option, { key: type, value: type }, type);
|
||||
});
|
||||
|
||||
var vehicleOptions = MOCK_VEHICLE_OPTIONS.map(function (v) {
|
||||
return React.createElement(Option, { key: v, value: v }, v);
|
||||
});
|
||||
|
||||
return React.createElement(
|
||||
'div',
|
||||
{ style: styles.page },
|
||||
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('a', { href: '#', style: styles.requirementLink, onClick: function (e) { e.preventDefault(); setShowRequirementModal(true); } }, '查看需求说明')
|
||||
),
|
||||
React.createElement(
|
||||
'div',
|
||||
{ style: styles.card },
|
||||
React.createElement(
|
||||
'div',
|
||||
{ style: styles.filterRow },
|
||||
React.createElement('span', { style: styles.label }, '设备类型:'),
|
||||
React.createElement(Select, {
|
||||
placeholder: '请选择设备类型',
|
||||
style: { width: 160 },
|
||||
value: filterDeviceType || undefined,
|
||||
onChange: function (v) { setFilterDeviceType(v || ''); },
|
||||
allowClear: true
|
||||
}, deviceTypeOptions),
|
||||
React.createElement('span', { style: styles.label }, '使用车辆:'),
|
||||
React.createElement(Select, {
|
||||
placeholder: '请选择或输入搜索',
|
||||
style: { width: 180 },
|
||||
value: filterVehicle || undefined,
|
||||
onChange: function (v) { setFilterVehicle(v || ''); },
|
||||
showSearch: true,
|
||||
allowClear: true,
|
||||
filterOption: function (input, opt) {
|
||||
var c = opt && opt.children;
|
||||
return c && String(c).toLowerCase().indexOf((input || '').toLowerCase()) >= 0;
|
||||
}
|
||||
}, vehicleOptions),
|
||||
React.createElement('span', { style: styles.label }, '安装时间:'),
|
||||
React.createElement(RangePicker, {
|
||||
style: { width: 260 },
|
||||
format: 'YYYY-MM-DD',
|
||||
placeholder: ['开始日期', '结束日期'],
|
||||
value: filterDateRange,
|
||||
onChange: function (dates) { setFilterDateRange(dates || []); }
|
||||
}),
|
||||
React.createElement('div', { style: styles.filterRight },
|
||||
React.createElement(Button, { type: 'primary', onClick: handleQuery }, '查询'),
|
||||
React.createElement(Button, { onClick: handleReset }, '重置')
|
||||
)
|
||||
)
|
||||
),
|
||||
React.createElement(
|
||||
'div',
|
||||
{ style: styles.card },
|
||||
React.createElement(
|
||||
'div',
|
||||
{ style: styles.toolbar },
|
||||
activeTab === 'installed' && React.createElement(Button, { type: 'primary', onClick: function () { message.info('请查看运维管理-车辆业务-后装设备-新增后装设备'); } }, '新增'),
|
||||
React.createElement(Button, { onClick: function () { message.info('根据筛选条件导出excel'); } }, '导出')
|
||||
),
|
||||
React.createElement(Tabs, {
|
||||
activeKey: activeTab,
|
||||
onChange: function (key) { setActiveTab(key); setCurrentPage(1); },
|
||||
items: [
|
||||
{
|
||||
key: 'installed',
|
||||
label: '已安装',
|
||||
children: React.createElement(Table, {
|
||||
rowKey: 'id',
|
||||
size: 'small',
|
||||
columns: [
|
||||
{ title: '设备类型', dataIndex: 'deviceType', key: 'deviceType', width: 120 },
|
||||
{ title: '车牌号', dataIndex: 'plateNo', key: 'plateNo', width: 120 },
|
||||
{ title: '供应商', dataIndex: 'supplier', key: 'supplier', width: 120 },
|
||||
{ title: '安装时间', dataIndex: 'createTime', key: 'createTime', width: 160 },
|
||||
{ title: '安装人', dataIndex: 'createOperator', key: 'createOperator', width: 100 },
|
||||
{
|
||||
title: '操作',
|
||||
key: 'action',
|
||||
width: 160,
|
||||
render: function (_, row) {
|
||||
return React.createElement(React.Fragment, null,
|
||||
React.createElement(Button, { type: 'link', size: 'small', onClick: function () { message.info('请查看运维管理-车辆业务-后装设备-查看'); } }, '查看'),
|
||||
React.createElement(Button, { type: 'link', size: 'small', onClick: function () { message.info('请查看运维管理-车辆业务-后装设备-编辑'); } }, '编辑'),
|
||||
React.createElement(Button, { type: 'link', size: 'small', danger: true, onClick: function () { setRemoveConfirmRecord(row); } }, '拆除')
|
||||
);
|
||||
}
|
||||
}
|
||||
],
|
||||
dataSource: paginatedList,
|
||||
pagination: {
|
||||
current: validPage,
|
||||
pageSize: pageSize,
|
||||
total: totalItems,
|
||||
showSizeChanger: true,
|
||||
showQuickJumper: true,
|
||||
pageSizeOptions: ['10', '20', '50', '100'],
|
||||
showTotal: function (total) { return '共 ' + total + ' 条'; },
|
||||
onChange: function (page, size) {
|
||||
setCurrentPage(page);
|
||||
if (size !== pageSize) setPageSize(size);
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
{
|
||||
key: 'removed',
|
||||
label: '拆除记录',
|
||||
children: React.createElement(Table, {
|
||||
rowKey: 'id',
|
||||
size: 'small',
|
||||
columns: [
|
||||
{ title: '设备类型', dataIndex: 'deviceType', key: 'deviceType', width: 120 },
|
||||
{ title: '车牌号', dataIndex: 'plateNo', key: 'plateNo', width: 120 },
|
||||
{ title: '供应商', dataIndex: 'supplier', key: 'supplier', width: 120 },
|
||||
{ title: '拆除时间', dataIndex: 'removeTime', key: 'removeTime', width: 160 },
|
||||
{ title: '拆除人', dataIndex: 'removeOperator', key: 'removeOperator', width: 100 },
|
||||
{
|
||||
title: '操作',
|
||||
key: 'action',
|
||||
width: 80,
|
||||
render: function (_, row) {
|
||||
return React.createElement(Button, { type: 'link', size: 'small', onClick: function () { message.info('请查看运维管理-车辆业务-后装设备-查看'); } }, '查看');
|
||||
}
|
||||
}
|
||||
],
|
||||
dataSource: paginatedList,
|
||||
pagination: {
|
||||
current: validPage,
|
||||
pageSize: pageSize,
|
||||
total: totalItems,
|
||||
showSizeChanger: true,
|
||||
showQuickJumper: true,
|
||||
pageSizeOptions: ['10', '20', '50', '100'],
|
||||
showTotal: function (total) { return '共 ' + total + ' 条'; },
|
||||
onChange: function (page, size) {
|
||||
setCurrentPage(page);
|
||||
if (size !== pageSize) setPageSize(size);
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
]
|
||||
})
|
||||
),
|
||||
viewRecord && React.createElement(Modal, {
|
||||
title: '查看后装设备',
|
||||
open: !!viewRecord,
|
||||
onCancel: function () { setViewRecord(null); },
|
||||
footer: React.createElement(Button, { onClick: function () { setViewRecord(null); } }, '关闭'),
|
||||
width: 520,
|
||||
children: viewRecord ? React.createElement('div', { style: { lineHeight: '2' } },
|
||||
React.createElement('div', null, '设备类型:', viewRecord.deviceType),
|
||||
React.createElement('div', null, '车牌号:', viewRecord.plateNo),
|
||||
React.createElement('div', null, '供应商:', viewRecord.supplier),
|
||||
React.createElement('div', null, '安装时间:', viewRecord.createTime || '-'),
|
||||
React.createElement('div', null, '安装人:', viewRecord.createOperator || '-'),
|
||||
React.createElement('div', null, '拆除时间:', viewRecord.removeTime || '-'),
|
||||
React.createElement('div', null, '拆除人:', viewRecord.removeOperator || '-')
|
||||
) : null
|
||||
}),
|
||||
editRecord && React.createElement(Modal, {
|
||||
title: '编辑后装设备',
|
||||
open: !!editRecord,
|
||||
onCancel: function () { setEditRecord(null); },
|
||||
onOk: function () {
|
||||
setEditRecord(null);
|
||||
message.success('保存成功');
|
||||
},
|
||||
okText: '保存',
|
||||
cancelText: '取消',
|
||||
width: 520,
|
||||
children: editRecord ? React.createElement('div', { style: { display: 'flex', flexDirection: 'column', gap: 16 } },
|
||||
React.createElement('div', null, React.createElement('span', { style: styles.label }, '设备类型'), React.createElement(Select, { style: { width: '100%' }, value: editRecord.deviceType, options: DEVICE_TYPES.map(function (d) { return { label: d, value: d }; }) })),
|
||||
React.createElement('div', null, React.createElement('span', { style: styles.label }, '车牌号'), React.createElement(Input, { style: { width: '100%' }, value: editRecord.plateNo, readOnly: true })),
|
||||
React.createElement('div', null, React.createElement('span', { style: styles.label }, '供应商'), React.createElement(Input, { style: { width: '100%' }, defaultValue: editRecord.supplier }))
|
||||
) : null
|
||||
}),
|
||||
removeConfirmRecord && React.createElement(Modal, {
|
||||
title: '确认拆除',
|
||||
open: !!removeConfirmRecord,
|
||||
onCancel: function () { setRemoveConfirmRecord(null); },
|
||||
onOk: function () { handleRemoveConfirm(removeConfirmRecord); },
|
||||
okText: '确认拆除',
|
||||
cancelText: '取消',
|
||||
okButtonProps: { danger: true },
|
||||
children: removeConfirmRecord ? React.createElement('div', null, '确定要拆除该车辆「', removeConfirmRecord.deviceType, '」后装设备吗?') : null
|
||||
}),
|
||||
React.createElement(Modal, {
|
||||
title: '需求说明',
|
||||
open: showRequirementModal,
|
||||
onCancel: function () { setShowRequirementModal(false); },
|
||||
footer: React.createElement(Button, { onClick: function () { setShowRequirementModal(false); } }, '关闭'),
|
||||
width: 720,
|
||||
children: React.createElement('div', { style: styles.modalContent },
|
||||
React.createElement('div', { style: styles.requirementSection },
|
||||
React.createElement('div', { style: styles.requirementSectionTitle }, '1. 面包屑:'),
|
||||
React.createElement('div', { style: styles.requirementItem }, '1.1. 运维管理-车辆业务-后装设备')
|
||||
),
|
||||
React.createElement('div', { style: styles.requirementSection },
|
||||
React.createElement('div', { style: styles.requirementSectionTitle }, '2. 筛选:'),
|
||||
React.createElement('div', { style: styles.requirementItem }, '2.1. 支持通过设备类型、使用车辆、安装日期进行管理,点击查询后,筛选条件与列表内容联动。点击重置会回到默认筛选条件并在列表展示结果:'),
|
||||
React.createElement('div', { style: styles.requirementSubItem }, '2.1.1. 设备类型:选择器,包括GPS、尾板、车身广告、G7安全套件、G7普通设备、G7温控设备、备胎;'),
|
||||
React.createElement('div', { style: styles.requirementSubItem }, '2.1.2. 使用车辆:选择器,支持通过输入框对输入内容模糊搜索,并下拉对应选项;'),
|
||||
React.createElement('div', { style: styles.requirementSubItem }, '2.1.3. 安装时间:日期选择器,支持单输入框内双日历选择开始-结束时间;')
|
||||
),
|
||||
React.createElement('div', { style: styles.requirementSection },
|
||||
React.createElement('div', { style: styles.requirementSectionTitle }, '3. 列表:'),
|
||||
React.createElement('div', { style: styles.requirementItem }, '列表分为2个tab,已安装/拆除记录;'),
|
||||
React.createElement('div', { style: styles.requirementItem }, '当已安装列表对应车辆存在车身广告/尾板时,在备车时会自动拉取车身广告/尾板为有的状态;'),
|
||||
React.createElement('div', { style: styles.requirementItem }, '当已安装列表不存在车身广告/尾板时,在备车时车身广告/尾板为无的状态;'),
|
||||
React.createElement('div', { style: styles.requirementItem }, '如果在备车/交车时手动取消或勾选车身广告尾板,并完成提交,后装设备列表也会新增一条该车辆的车身广告/尾板安装数据;'),
|
||||
React.createElement('div', { style: styles.requirementSectionTitle }, '3.1. 已安装:'),
|
||||
React.createElement('div', { style: styles.requirementSubItem }, '3.1.1. 列表展示所有后装设备信息,字段依次为:设备类型、车牌号、供应商、安装时间、安装人、操作;列表右上角为新增、导出;'),
|
||||
React.createElement('div', { style: styles.requirementSubItem }, '3.1.1.1. 设备类型:显示后装设备类型,包括:GPS、尾板、车身广告、G7安全套件、G7普通设备、G7温控设备、备胎;'),
|
||||
React.createElement('div', { style: styles.requirementSubItem }, '3.1.1.2. 车牌号:显示后装设备对应车牌号信息;'),
|
||||
React.createElement('div', { style: styles.requirementSubItem }, '3.1.1.3. 供应商:显示后装设备供应商信息;'),
|
||||
React.createElement('div', { style: styles.requirementSubItem }, '3.1.1.4. 安装时间:显示后装设备安装时间,格式为YYYY-MM-DD HH:MM;'),
|
||||
React.createElement('div', { style: styles.requirementSubItem }, '3.1.1.5. 安装人:显示后装设备安装用户名称;'),
|
||||
React.createElement('div', { style: styles.requirementSubItem }, '3.1.1.6. 操作:支持查看、编辑、拆除;'),
|
||||
React.createElement('div', { style: styles.requirementSectionTitle }, '3.2. 拆除记录:'),
|
||||
React.createElement('div', { style: styles.requirementSubItem }, '3.2.1. 列表展示所有后装设备拆除记录,字段依次为:设备类型、车牌号、供应商、拆除时间、拆除人、操作;列表右上角为新增、导出;'),
|
||||
React.createElement('div', { style: styles.requirementSubItem }, '3.2.1.1. 设备类型:显示后装设备类型,包括:GPS、尾板、车身广告、G7安全套件、G7普通设备、G7温控设备、备胎;'),
|
||||
React.createElement('div', { style: styles.requirementSubItem }, '3.2.1.2. 车牌号:显示后装设备对应车牌号信息;'),
|
||||
React.createElement('div', { style: styles.requirementSubItem }, '3.2.1.3. 供应商:显示后装设备供应商信息;'),
|
||||
React.createElement('div', { style: styles.requirementSubItem }, '3.2.1.4. 拆除时间:显示后装设备拆除时间,格式为YYYY-MM-DD HH:MM;'),
|
||||
React.createElement('div', { style: styles.requirementSubItem }, '3.2.1.5. 拆除人:显示后装设备拆除用户名称;'),
|
||||
React.createElement('div', { style: styles.requirementSubItem }, '3.2.1.6. 操作:支持查看;')
|
||||
)
|
||||
)
|
||||
}),
|
||||
addModalVisible && React.createElement(Modal, {
|
||||
title: '新增后装设备',
|
||||
open: addModalVisible,
|
||||
onCancel: function () { setAddModalVisible(false); },
|
||||
onOk: function () {
|
||||
setDataList([{ id: String(Date.now()), deviceType: 'GPS', plateNo: '粤A12345', supplier: '新供应商', lastOpType: '安装', createTime: '2025-02-24 12:00', removeTime: '', createOperator: '当前用户', removeOperator: '' }].concat(dataList));
|
||||
setAddModalVisible(false);
|
||||
message.success('新增成功');
|
||||
},
|
||||
okText: '确定',
|
||||
cancelText: '取消',
|
||||
width: 520,
|
||||
children: React.createElement('div', { style: { display: 'flex', flexDirection: 'column', gap: 16 } },
|
||||
React.createElement('div', null, React.createElement('span', { style: styles.label }, '设备类型'), React.createElement(Select, { style: { width: '100%' }, placeholder: '请选择', options: DEVICE_TYPES.map(function (d) { return { label: d, value: d }; }) })),
|
||||
React.createElement('div', null, React.createElement('span', { style: styles.label }, '使用车辆'), React.createElement(Select, { style: { width: '100%' }, placeholder: '请选择或搜索', showSearch: true, options: MOCK_VEHICLE_OPTIONS.map(function (v) { return { label: v, value: v }; }) })),
|
||||
React.createElement('div', null, React.createElement('span', { style: styles.label }, '供应商'), React.createElement(Input, { style: { width: '100%' }, placeholder: '请输入供应商' }))
|
||||
)
|
||||
})
|
||||
);
|
||||
};
|
||||
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);
|
||||
}
|
||||
}
|
||||
652
web端/运维管理/车辆业务/备车管理.jsx
Executable file
652
web端/运维管理/车辆业务/备车管理.jsx
Executable file
@@ -0,0 +1,652 @@
|
||||
// 【重要】必须使用 const Component 作为组件变量名
|
||||
// 备车管理 - 车辆资产管理后台(按 antd 规范)
|
||||
|
||||
const Component = function () {
|
||||
var useState = React.useState;
|
||||
var useCallback = React.useCallback;
|
||||
var useMemo = React.useMemo;
|
||||
|
||||
var antd = window.antd;
|
||||
var Breadcrumb = antd.Breadcrumb;
|
||||
var Card = antd.Card;
|
||||
var DatePicker = antd.DatePicker;
|
||||
var Select = antd.Select;
|
||||
var Button = antd.Button;
|
||||
var Tabs = antd.Tabs;
|
||||
var Table = antd.Table;
|
||||
var Modal = antd.Modal;
|
||||
var Steps = antd.Steps;
|
||||
var Input = antd.Input;
|
||||
var Radio = antd.Radio;
|
||||
var Space = antd.Space;
|
||||
var Row = antd.Row;
|
||||
var Col = antd.Col;
|
||||
var message = antd.message;
|
||||
|
||||
var RangePicker = DatePicker.RangePicker;
|
||||
|
||||
// 当前视图:'list' | 'add'
|
||||
var viewState = useState('list');
|
||||
var currentView = viewState[0];
|
||||
var setCurrentView = viewState[1];
|
||||
|
||||
var filterState = useState({
|
||||
dateStart: '',
|
||||
dateEnd: '',
|
||||
operator: undefined,
|
||||
plateNo: undefined,
|
||||
vehicleType: undefined,
|
||||
parkingLot: undefined
|
||||
});
|
||||
var filters = filterState[0];
|
||||
var setFilters = filterState[1];
|
||||
// 实际参与列表筛选的条件(点击查询后与 filters 同步)
|
||||
var appliedFilterState = useState({
|
||||
dateStart: '',
|
||||
dateEnd: '',
|
||||
operator: undefined,
|
||||
plateNo: undefined,
|
||||
vehicleType: undefined,
|
||||
parkingLot: undefined
|
||||
});
|
||||
var appliedFilters = appliedFilterState[0];
|
||||
var setAppliedFilters = appliedFilterState[1];
|
||||
|
||||
var activeTabState = useState('completed');
|
||||
var activeTab = activeTabState[0];
|
||||
var setActiveTab = activeTabState[1];
|
||||
|
||||
var defaultInspection = [{ checkType: '灯光', checkItem: '前大灯', result: '正常', treadDepth: '', remark: '' }, { checkType: '灯光', checkItem: '尾灯', result: '正常', treadDepth: '', remark: '' }, { checkType: '轮胎', checkItem: '前左胎', result: '正常', treadDepth: '5.2mm', remark: '' }, { checkType: '车身', checkItem: '车身外观', result: '正常', treadDepth: '', remark: '' }];
|
||||
var completedListState = useState([
|
||||
{ id: '1', completeDate: '2025-02-10 09:30', operator: '张三', vehicleType: '厢式货车', plateNo: '京A12345', brand: '东风', model: 'DFH1180', vin: 'LGHXCAE28M1234567', parkingLot: '朝阳停车场', bodyAd: '有', adPhotoCount: 3, adPhotos: ['https://picsum.photos/200/150?random=1', 'https://picsum.photos/200/150?random=2', 'https://picsum.photos/200/150?random=3'], tailboard: '有', hasTrailer: '有', trailerPlate: '京B67890', flawPhotoCount: 2, flawPhotos: ['https://picsum.photos/200/150?random=4', 'https://picsum.photos/200/150?random=5'], inspectionList: [{ checkType: '灯光', checkItem: '前大灯', result: '正常', treadDepth: '', remark: '' }, { checkType: '灯光', checkItem: '尾灯', result: '正常', treadDepth: '', remark: '' }, { checkType: '轮胎', checkItem: '前左胎', result: '正常', treadDepth: '5.2mm', remark: '' }, { checkType: '车身', checkItem: '车身外观', result: '异常', treadDepth: '', remark: '有划痕' }] },
|
||||
{ id: '2', completeDate: '2025-02-09 10:15', operator: '李四', vehicleType: '平板货车', plateNo: '京C11111', brand: '福田', model: 'BJ1180', vin: 'LGHXCAE28M7654321', parkingLot: '海淀停车场', bodyAd: '无', adPhotoCount: 0, adPhotos: [], tailboard: '无', hasTrailer: '无', trailerPlate: '', flawPhotoCount: 1, flawPhotos: ['https://picsum.photos/200/150?random=6'], inspectionList: [{ checkType: '灯光', checkItem: '前大灯', result: '正常', treadDepth: '', remark: '' }, { checkType: '轮胎', checkItem: '前左胎', result: '异常', treadDepth: '3.1mm', remark: '需更换' }] },
|
||||
{ id: '3', completeDate: '2025-02-08 11:00', operator: '王五', vehicleType: '厢式货车', plateNo: '京D22222', brand: '江淮', model: 'HFC1180', vin: 'LGHXCAE28M8888888', parkingLot: '丰台停车场', bodyAd: '有', adPhotoCount: 2, adPhotos: ['https://picsum.photos/200/150?random=7', 'https://picsum.photos/200/150?random=8'], tailboard: '有', hasTrailer: '无', trailerPlate: '', flawPhotoCount: 0, flawPhotos: [], inspectionList: defaultInspection },
|
||||
{ id: '4', completeDate: '2025-02-07 13:45', operator: '赵六', vehicleType: '栏板货车', plateNo: '京E33333', brand: '重汽', model: 'ZZ1180', vin: 'LGHXCAE28M7777777', parkingLot: '西城停车场', bodyAd: '无', adPhotoCount: 0, adPhotos: [], tailboard: '无', hasTrailer: '有', trailerPlate: '京E33334', flawPhotoCount: 1, flawPhotos: ['https://picsum.photos/200/150?random=9'], inspectionList: defaultInspection },
|
||||
{ id: '5', completeDate: '2025-02-06 08:20', operator: '张三', vehicleType: '平板货车', plateNo: '京A23456', brand: '东风', model: 'DFH1190', vin: 'LGHXCAE28M6666666', parkingLot: '朝阳停车场', bodyAd: '有', adPhotoCount: 1, adPhotos: ['https://picsum.photos/200/150?random=10'], tailboard: '有', hasTrailer: '无', trailerPlate: '', flawPhotoCount: 0, flawPhotos: [], inspectionList: defaultInspection },
|
||||
{ id: '6', completeDate: '2025-02-05 14:30', operator: '李四', vehicleType: '厢式货车', plateNo: '京B34567', brand: '福田', model: 'BJ1190', vin: 'LGHXCAE28M5555555', parkingLot: '海淀停车场', bodyAd: '无', adPhotoCount: 0, adPhotos: [], tailboard: '无', hasTrailer: '无', trailerPlate: '', flawPhotoCount: 2, flawPhotos: ['https://picsum.photos/200/150?random=11', 'https://picsum.photos/200/150?random=12'], inspectionList: defaultInspection },
|
||||
{ id: '7', completeDate: '2025-02-04 16:00', operator: '王五', vehicleType: '栏板货车', plateNo: '京C45678', brand: '江淮', model: 'HFC1190', vin: 'LGHXCAE28M4444444', parkingLot: '丰台停车场', bodyAd: '有', adPhotoCount: 2, adPhotos: ['https://picsum.photos/200/150?random=13', 'https://picsum.photos/200/150?random=14'], tailboard: '有', hasTrailer: '有', trailerPlate: '京C45679', flawPhotoCount: 0, flawPhotos: [], inspectionList: defaultInspection },
|
||||
{ id: '8', completeDate: '2025-02-03 09:00', operator: '赵六', vehicleType: '厢式货车', plateNo: '京D56789', brand: '重汽', model: 'ZZ1190', vin: 'LGHXCAE28M3333333', parkingLot: '西城停车场', bodyAd: '无', adPhotoCount: 0, adPhotos: [], tailboard: '有', hasTrailer: '无', trailerPlate: '', flawPhotoCount: 1, flawPhotos: ['https://picsum.photos/200/150?random=15'], inspectionList: defaultInspection },
|
||||
{ id: '9', completeDate: '2025-02-02 10:30', operator: '张三', vehicleType: '平板货车', plateNo: '京E67890', brand: '东风', model: 'DFH1200', vin: 'LGHXCAE28M2222222', parkingLot: '朝阳停车场', bodyAd: '有', adPhotoCount: 3, adPhotos: ['https://picsum.photos/200/150?random=16', 'https://picsum.photos/200/150?random=17', 'https://picsum.photos/200/150?random=18'], tailboard: '无', hasTrailer: '无', trailerPlate: '', flawPhotoCount: 0, flawPhotos: [], inspectionList: defaultInspection },
|
||||
{ id: '10', completeDate: '2025-02-01 15:45', operator: '李四', vehicleType: '厢式货车', plateNo: '京A78901', brand: '福田', model: 'BJ1200', vin: 'LGHXCAE28M1111111', parkingLot: '海淀停车场', bodyAd: '无', adPhotoCount: 0, adPhotos: [], tailboard: '有', hasTrailer: '有', trailerPlate: '京A78902', flawPhotoCount: 0, flawPhotos: [], inspectionList: defaultInspection }
|
||||
]);
|
||||
var completedList = completedListState[0];
|
||||
var setCompletedList = completedListState[1];
|
||||
|
||||
var pendingListState = useState([
|
||||
{ id: 'p1', operateDate: '2025-02-10 14:30', operator: '王五', vehicleType: '厢式货车', plateNo: '京F10001', brand: '江淮', model: 'HFC1180', vin: 'LGHXCAE28M9990001', parkingLot: '丰台停车场', bodyAd: '有', adPhotoCount: 2, adPhotos: ['https://picsum.photos/200/150?random=19', 'https://picsum.photos/200/150?random=20'], tailboard: '有', hasTrailer: '无', trailerPlate: '', flawPhotoCount: 0, flawPhotos: [] },
|
||||
{ id: 'p2', operateDate: '2025-02-09 09:15', operator: '赵六', vehicleType: '平板货车', plateNo: '京F10002', brand: '重汽', model: 'ZZ1180', vin: 'LGHXCAE28M9990002', parkingLot: '西城停车场', bodyAd: '无', adPhotoCount: 0, adPhotos: [], tailboard: '无', hasTrailer: '无', trailerPlate: '', flawPhotoCount: 1, flawPhotos: ['https://picsum.photos/200/150?random=21'] },
|
||||
{ id: 'p3', operateDate: '2025-02-08 11:45', operator: '张三', vehicleType: '栏板货车', plateNo: '京F10003', brand: '东风', model: 'DFH1180', vin: 'LGHXCAE28M9990003', parkingLot: '朝阳停车场', bodyAd: '有', adPhotoCount: 1, adPhotos: ['https://picsum.photos/200/150?random=22'], tailboard: '有', hasTrailer: '有', trailerPlate: '京F10004', flawPhotoCount: 0, flawPhotos: [] },
|
||||
{ id: 'p4', operateDate: '2025-02-07 08:00', operator: '李四', vehicleType: '厢式货车', plateNo: '京F10005', brand: '福田', model: 'BJ1180', vin: 'LGHXCAE28M9990004', parkingLot: '海淀停车场', bodyAd: '无', adPhotoCount: 0, adPhotos: [], tailboard: '无', hasTrailer: '无', trailerPlate: '', flawPhotoCount: 0, flawPhotos: [] },
|
||||
{ id: 'p5', operateDate: '2025-02-06 13:20', operator: '王五', vehicleType: '厢式货车', plateNo: '京F10006', brand: '江淮', model: 'HFC1190', vin: 'LGHXCAE28M9990005', parkingLot: '丰台停车场', bodyAd: '有', adPhotoCount: 3, adPhotos: ['https://picsum.photos/200/150?random=23', 'https://picsum.photos/200/150?random=24', 'https://picsum.photos/200/150?random=25'], tailboard: '有', hasTrailer: '无', trailerPlate: '', flawPhotoCount: 2, flawPhotos: ['https://picsum.photos/200/150?random=26', 'https://picsum.photos/200/150?random=27'] },
|
||||
{ id: 'p6', operateDate: '2025-02-05 15:30', operator: '赵六', vehicleType: '平板货车', plateNo: '京F10007', brand: '重汽', model: 'ZZ1190', vin: 'LGHXCAE28M9990006', parkingLot: '西城停车场', bodyAd: '无', adPhotoCount: 0, adPhotos: [], tailboard: '无', hasTrailer: '有', trailerPlate: '京F10008', flawPhotoCount: 0, flawPhotos: [] },
|
||||
{ id: 'p7', operateDate: '2025-02-04 10:00', operator: '张三', vehicleType: '厢式货车', plateNo: '京F10009', brand: '东风', model: 'DFH1190', vin: 'LGHXCAE28M9990007', parkingLot: '朝阳停车场', bodyAd: '有', adPhotoCount: 2, adPhotos: ['https://picsum.photos/200/150?random=28', 'https://picsum.photos/200/150?random=29'], tailboard: '有', hasTrailer: '无', trailerPlate: '', flawPhotoCount: 0, flawPhotos: [] },
|
||||
{ id: 'p8', operateDate: '2025-02-03 16:45', operator: '李四', vehicleType: '栏板货车', plateNo: '京F10010', brand: '福田', model: 'BJ1190', vin: 'LGHXCAE28M9990008', parkingLot: '海淀停车场', bodyAd: '无', adPhotoCount: 0, adPhotos: [], tailboard: '无', hasTrailer: '无', trailerPlate: '', flawPhotoCount: 1, flawPhotos: ['https://picsum.photos/200/150?random=30'] },
|
||||
{ id: 'p9', operateDate: '2025-02-02 09:30', operator: '王五', vehicleType: '厢式货车', plateNo: '京F10011', brand: '江淮', model: 'HFC1200', vin: 'LGHXCAE28M9990009', parkingLot: '丰台停车场', bodyAd: '有', adPhotoCount: 1, adPhotos: ['https://picsum.photos/200/150?random=31'], tailboard: '有', hasTrailer: '有', trailerPlate: '京F10012', flawPhotoCount: 0, flawPhotos: [] },
|
||||
{ id: 'p10', operateDate: '2025-02-01 14:00', operator: '赵六', vehicleType: '平板货车', plateNo: '京F10013', brand: '重汽', model: 'ZZ1200', vin: 'LGHXCAE28M9990010', parkingLot: '西城停车场', bodyAd: '无', adPhotoCount: 0, adPhotos: [], tailboard: '无', hasTrailer: '无', trailerPlate: '', flawPhotoCount: 0, flawPhotos: [] }
|
||||
]);
|
||||
var pendingList = pendingListState[0];
|
||||
var setPendingList = pendingListState[1];
|
||||
|
||||
var pageState = useState(1);
|
||||
var page = pageState[0];
|
||||
var setPage = pageState[1];
|
||||
var pageSizeState = useState(10);
|
||||
var pageSize = pageSizeState[0];
|
||||
var setPageSize = pageSizeState[1];
|
||||
|
||||
var operatorOptions = useMemo(function () { return [{ value: '张三', label: '张三' }, { value: '李四', label: '李四' }, { value: '王五', label: '王五' }, { value: '赵六', label: '赵六' }]; }, []);
|
||||
var plateOptions = useMemo(function () { return [{ value: '京A12345', label: '京A12345' }, { value: '京C11111', label: '京C11111' }, { value: '京D22222', label: '京D22222' }, { value: '京E33333', label: '京E33333' }]; }, []);
|
||||
var vehicleTypeOptions = useMemo(function () { return [{ value: '厢式货车', label: '厢式货车' }, { value: '平板货车', label: '平板货车' }, { value: '栏板货车', label: '栏板货车' }]; }, []);
|
||||
var parkingOptions = useMemo(function () { return [{ value: '朝阳停车场', label: '朝阳停车场' }, { value: '海淀停车场', label: '海淀停车场' }, { value: '丰台停车场', label: '丰台停车场' }, { value: '西城停车场', label: '西城停车场' }]; }, []);
|
||||
|
||||
var reqDocOpenState = useState(false);
|
||||
var photoModalState = useState({ open: false, photos: [], currentIndex: 0 });
|
||||
|
||||
var addStepState = useState(1);
|
||||
var addFormState = useState({
|
||||
plateNo: '',
|
||||
vehicleType: '',
|
||||
brand: '',
|
||||
vin: '',
|
||||
bodyAd: '无',
|
||||
adPhotos: [],
|
||||
tailboard: '无',
|
||||
hasTrailer: '',
|
||||
trailerPlate: '',
|
||||
flawPhotos: [],
|
||||
inspectionList: [
|
||||
{ checkType: '灯光', checkItem: '前大灯', result: '正常', treadDepth: '', remark: '' },
|
||||
{ checkType: '灯光', checkItem: '尾灯', result: '正常', treadDepth: '', remark: '' },
|
||||
{ checkType: '轮胎', checkItem: '前左胎', result: '正常', treadDepth: '', remark: '' },
|
||||
{ checkType: '车身', checkItem: '车身外观', result: '正常', treadDepth: '', remark: '' }
|
||||
]
|
||||
});
|
||||
|
||||
var filteredCompleted = useMemo(function () {
|
||||
var list = completedList.slice();
|
||||
if (appliedFilters.operator) list = list.filter(function (r) { return r.operator.indexOf(appliedFilters.operator) !== -1; });
|
||||
if (appliedFilters.plateNo) list = list.filter(function (r) { return r.plateNo.indexOf(appliedFilters.plateNo) !== -1; });
|
||||
if (appliedFilters.vehicleType) list = list.filter(function (r) { return r.vehicleType.indexOf(appliedFilters.vehicleType) !== -1; });
|
||||
if (appliedFilters.parkingLot) list = list.filter(function (r) { return r.parkingLot.indexOf(appliedFilters.parkingLot) !== -1; });
|
||||
if (appliedFilters.dateStart) list = list.filter(function (r) { var d = (r.completeDate || '').slice(0, 10); return d >= appliedFilters.dateStart; });
|
||||
if (appliedFilters.dateEnd) list = list.filter(function (r) { var d = (r.completeDate || '').slice(0, 10); return d <= appliedFilters.dateEnd; });
|
||||
return list.sort(function (a, b) { return (b.completeDate || '').localeCompare(a.completeDate || ''); });
|
||||
}, [completedList, appliedFilters]);
|
||||
|
||||
var filteredPending = useMemo(function () {
|
||||
var list = pendingList.slice();
|
||||
if (appliedFilters.operator) list = list.filter(function (r) { return r.operator.indexOf(appliedFilters.operator) !== -1; });
|
||||
if (appliedFilters.plateNo) list = list.filter(function (r) { return r.plateNo.indexOf(appliedFilters.plateNo) !== -1; });
|
||||
if (appliedFilters.vehicleType) list = list.filter(function (r) { return r.vehicleType.indexOf(appliedFilters.vehicleType) !== -1; });
|
||||
if (appliedFilters.parkingLot) list = list.filter(function (r) { return r.parkingLot.indexOf(appliedFilters.parkingLot) !== -1; });
|
||||
if (appliedFilters.dateStart) list = list.filter(function (r) { var d = (r.operateDate || '').slice(0, 10); return d >= appliedFilters.dateStart; });
|
||||
if (appliedFilters.dateEnd) list = list.filter(function (r) { var d = (r.operateDate || '').slice(0, 10); return d <= appliedFilters.dateEnd; });
|
||||
return list.sort(function (a, b) { return (b.operateDate || '').localeCompare(a.operateDate || ''); });
|
||||
}, [pendingList, appliedFilters]);
|
||||
|
||||
var displayCompleted = useMemo(function () {
|
||||
var start = (page - 1) * pageSize;
|
||||
return filteredCompleted.slice(start, start + pageSize);
|
||||
}, [filteredCompleted, page, pageSize]);
|
||||
|
||||
var displayPending = useMemo(function () {
|
||||
var start = (page - 1) * pageSize;
|
||||
return filteredPending.slice(start, start + pageSize);
|
||||
}, [filteredPending, page, pageSize]);
|
||||
|
||||
var totalCompleted = filteredCompleted.length;
|
||||
var totalPending = filteredPending.length;
|
||||
var totalCount = activeTab === 'completed' ? totalCompleted : totalPending;
|
||||
|
||||
var handleQuery = useCallback(function () {
|
||||
setAppliedFilters({ dateStart: filters.dateStart, dateEnd: filters.dateEnd, operator: filters.operator, plateNo: filters.plateNo, vehicleType: filters.vehicleType, parkingLot: filters.parkingLot });
|
||||
setPage(1);
|
||||
}, [filters.dateStart, filters.dateEnd, filters.operator, filters.plateNo, filters.vehicleType, filters.parkingLot]);
|
||||
var handleReset = useCallback(function () {
|
||||
var empty = { dateStart: '', dateEnd: '', operator: undefined, plateNo: undefined, vehicleType: undefined, parkingLot: undefined };
|
||||
setFilters(empty);
|
||||
setAppliedFilters(empty);
|
||||
setPage(1);
|
||||
}, []);
|
||||
|
||||
var handleExport = useCallback(function () {
|
||||
if (activeTab !== 'completed') {
|
||||
message.warning('请在「已完成」Tab 下导出');
|
||||
return;
|
||||
}
|
||||
var rows = filteredCompleted;
|
||||
var headers = ['备车时间', '备车人', '车辆类型', '车牌号', '品牌', '型号', '车辆识别代码', '停车场', '车身广告', '广告照片', '尾板', '是否有挂', '挂车牌号', '瑕疵照片'];
|
||||
var csv = headers.join(',') + '\n';
|
||||
rows.forEach(function (r) {
|
||||
csv += [r.completeDate, r.operator, r.vehicleType, r.plateNo, r.brand, r.model, r.vin, r.parkingLot, r.bodyAd, (r.adPhotoCount || 0) + '张', r.tailboard, r.hasTrailer, r.trailerPlate || '', (r.flawPhotoCount || 0) + '张'].join(',') + '\n';
|
||||
});
|
||||
var blob = new Blob(['\ufeff' + csv], { type: 'text/csv;charset=utf-8' });
|
||||
var url = URL.createObjectURL(blob);
|
||||
var a = document.createElement('a');
|
||||
a.href = url;
|
||||
a.download = '备车管理导出_' + new Date().getTime() + '.csv';
|
||||
a.click();
|
||||
URL.revokeObjectURL(url);
|
||||
message.success('导出成功');
|
||||
}, [activeTab, filteredCompleted]);
|
||||
|
||||
var openPhotoModal = useCallback(function (photos, index) {
|
||||
if (!photos || photos.length === 0) return;
|
||||
photoModalState[1]({ open: true, photos: photos, currentIndex: index || 0 });
|
||||
}, []);
|
||||
|
||||
var addForm = addFormState[0];
|
||||
var setAddForm = addFormState[1];
|
||||
var addStep = addStepState[0];
|
||||
var setAddStep = addStepState[1];
|
||||
|
||||
var handleAddSave = useCallback(function () {
|
||||
var d = new Date();
|
||||
var pad = function (n) { return String(n).padStart(2, '0'); };
|
||||
var dateTimeStr = d.getFullYear() + '-' + pad(d.getMonth() + 1) + '-' + pad(d.getDate()) + ' ' + pad(d.getHours()) + ':' + pad(d.getMinutes());
|
||||
var item = {
|
||||
id: 'p' + Date.now(),
|
||||
operateDate: dateTimeStr,
|
||||
operator: '当前用户',
|
||||
vehicleType: addForm.vehicleType || '厢式货车',
|
||||
plateNo: addForm.plateNo,
|
||||
brand: addForm.brand || '-',
|
||||
model: addForm.model || '-',
|
||||
vin: addForm.vin,
|
||||
parkingLot: addForm.parkingLot || '朝阳停车场',
|
||||
bodyAd: addForm.bodyAd,
|
||||
adPhotoCount: (addForm.adPhotos && addForm.adPhotos.length) || 0,
|
||||
adPhotos: addForm.adPhotos || [],
|
||||
tailboard: addForm.tailboard,
|
||||
hasTrailer: addForm.trailerPlate ? '有' : '无',
|
||||
trailerPlate: addForm.trailerPlate || '',
|
||||
flawPhotoCount: (addForm.flawPhotos && addForm.flawPhotos.length) || 0,
|
||||
flawPhotos: addForm.flawPhotos || []
|
||||
};
|
||||
setPendingList(pendingList.concat([item]));
|
||||
setCurrentView('list');
|
||||
setActiveTab('pending');
|
||||
setAddForm({ plateNo: '', vehicleType: '', brand: '', vin: '', bodyAd: '无', adPhotos: [], tailboard: '无', hasTrailer: '', trailerPlate: '', flawPhotos: [], inspectionList: addForm.inspectionList });
|
||||
setAddStep(1);
|
||||
message.success('已保存至待提交列表');
|
||||
}, [addForm, pendingList]);
|
||||
|
||||
var handleAddNext = useCallback(function () {
|
||||
if (!addForm.plateNo) {
|
||||
message.warning('请选择车牌号');
|
||||
return;
|
||||
}
|
||||
setAddStep(2);
|
||||
}, [addForm.plateNo]);
|
||||
|
||||
var handleAddSubmit = useCallback(function () {
|
||||
var d = new Date();
|
||||
var pad = function (n) { return String(n).padStart(2, '0'); };
|
||||
var dateTimeStr = d.getFullYear() + '-' + pad(d.getMonth() + 1) + '-' + pad(d.getDate()) + ' ' + pad(d.getHours()) + ':' + pad(d.getMinutes());
|
||||
var item = {
|
||||
id: String(Date.now()),
|
||||
completeDate: dateTimeStr,
|
||||
operator: '当前用户',
|
||||
vehicleType: addForm.vehicleType || '厢式货车',
|
||||
plateNo: addForm.plateNo,
|
||||
brand: addForm.brand || '-',
|
||||
model: addForm.model || '-',
|
||||
vin: addForm.vin,
|
||||
parkingLot: addForm.parkingLot || '朝阳停车场',
|
||||
bodyAd: addForm.bodyAd,
|
||||
adPhotoCount: (addForm.adPhotos && addForm.adPhotos.length) || 0,
|
||||
adPhotos: addForm.adPhotos || [],
|
||||
tailboard: addForm.tailboard,
|
||||
hasTrailer: addForm.trailerPlate ? '有' : '无',
|
||||
trailerPlate: addForm.trailerPlate || '',
|
||||
flawPhotoCount: (addForm.flawPhotos && addForm.flawPhotos.length) || 0,
|
||||
flawPhotos: addForm.flawPhotos || [],
|
||||
inspectionList: addForm.inspectionList || []
|
||||
};
|
||||
setCompletedList(completedList.concat([item]));
|
||||
setCurrentView('list');
|
||||
setActiveTab('completed');
|
||||
setAddForm({ plateNo: '', vehicleType: '', brand: '', vin: '', bodyAd: '无', adPhotos: [], tailboard: '无', hasTrailer: '', trailerPlate: '', flawPhotos: [], inspectionList: addForm.inspectionList });
|
||||
setAddStep(1);
|
||||
message.success('提交成功');
|
||||
}, [addForm, completedList]);
|
||||
|
||||
var onPlateSelect = useCallback(function (plateNo) {
|
||||
setAddForm(function (prev) {
|
||||
var next = {};
|
||||
for (var k in prev) next[k] = prev[k];
|
||||
next.plateNo = plateNo;
|
||||
next.vehicleType = '厢式货车';
|
||||
next.brand = '东风';
|
||||
next.vin = 'LGHXCAE28M' + Math.floor(Math.random() * 10000000);
|
||||
return next;
|
||||
});
|
||||
}, []);
|
||||
|
||||
var requirementDocContent = '#.面包屑:运维管理-车辆业务-备车管理,支持点击对应模块跳转\n\n#筛选:支持通过备车日期、备车人、车牌号、车辆类型、停车场等方式进行筛选;\n1.备车日期:日期选择器,点击显示两个日历控件,支持选择开始和结束时间,时间格式为YYYY-MM-DD;\n2.备车人:选择器,支持从输入框输入内容模糊搜索展示对应选项;\n3.车牌号:选择器,支持从输入框输入内容模糊搜索展示对应选项;\n4.车辆类型:选择器,支持从输入框输入内容模糊搜索展示对应选项;\n5.停车场:选择器,支持从输入框输入内容模糊搜索展示对应选项;\n6.右侧显示查询、重置按钮,点击查询按钮按筛选条件显示列表内容,点击重置清除筛选条件并按默认条件显示列表内容;\n\n#列表:\n列表分为两个tab,分别为:已完成、待检查;已完成列表右侧包含新增、导出按钮,下方增加分页功能,支持选择单页显示数据记录条数;\n1.已完成tab显示完成车辆记录及备车检查两个步骤表单并点击提交的记录;\n2.待检查tab显示新增备车时只点击保存,但未提交的记录;\n3.点击新增按钮,打开新页面进行新增表单页;\n4.导出需全选/多选对应数据记录,再点击导出下载csv;\n5.列表以区域进行数据权限划分,用户表中对应区域的用户只能查询自己区域的数据;';
|
||||
|
||||
// 日期范围变化(antd RangePicker 返回 dayjs 或 [string, string] 依项目而定,此处用字符串存)
|
||||
function onDateRangeChange(dates, dateStrings) {
|
||||
setFilters(function (f) {
|
||||
var g = {};
|
||||
for (var k in f) g[k] = f[k];
|
||||
g.dateStart = (dateStrings && dateStrings[0]) || '';
|
||||
g.dateEnd = (dateStrings && dateStrings[1]) || '';
|
||||
return g;
|
||||
});
|
||||
}
|
||||
|
||||
var dateRangeValue = useMemo(function () {
|
||||
if (!filters.dateStart && !filters.dateEnd) return null;
|
||||
try {
|
||||
if (typeof window.dayjs === 'function' && filters.dateStart && filters.dateEnd) {
|
||||
return [window.dayjs(filters.dateStart), window.dayjs(filters.dateEnd)];
|
||||
}
|
||||
} catch (e) {}
|
||||
return null;
|
||||
}, [filters.dateStart, filters.dateEnd]);
|
||||
|
||||
// 已完成表格列(含多选、照片链接、操作列查看按钮,点击不打开新页面)
|
||||
function getCompletedColumns(openPhoto) {
|
||||
return [
|
||||
{ title: '备车时间', dataIndex: 'completeDate', key: 'completeDate', width: 160 },
|
||||
{ title: '备车人', dataIndex: 'operator', key: 'operator', width: 90 },
|
||||
{ title: '车辆类型', dataIndex: 'vehicleType', key: 'vehicleType', width: 100 },
|
||||
{ title: '品牌', dataIndex: 'brand', key: 'brand', width: 80 },
|
||||
{ title: '型号', dataIndex: 'model', key: 'model', width: 100 },
|
||||
{ title: '车牌号', dataIndex: 'plateNo', key: 'plateNo', width: 100 },
|
||||
{ title: '车辆识别代码', dataIndex: 'vin', key: 'vin', width: 180 },
|
||||
{ title: '停车场', dataIndex: 'parkingLot', key: 'parkingLot', width: 110 },
|
||||
{ title: '车身广告', dataIndex: 'bodyAd', key: 'bodyAd', width: 90 },
|
||||
{ title: '广告照片', key: 'adPhotos', width: 90, render: function (_, r) {
|
||||
var photos = r.adPhotos && r.adPhotos.length > 0 ? r.adPhotos : [];
|
||||
return photos.length > 0 ? React.createElement(Button, { type: 'link', size: 'small', onClick: function (e) { if (e) { e.preventDefault(); e.stopPropagation(); } openPhoto(photos, 0); } }, photos.length + '张') : '-';
|
||||
}},
|
||||
{ title: '尾板', dataIndex: 'tailboard', key: 'tailboard', width: 70 },
|
||||
{ title: '是否有挂', dataIndex: 'hasTrailer', key: 'hasTrailer', width: 90 },
|
||||
{ title: '挂车牌号', dataIndex: 'trailerPlate', key: 'trailerPlate', width: 100, render: function (v) { return v || '-'; } },
|
||||
{ title: '瑕疵照片', key: 'flawPhotos', width: 90, render: function (_, r) {
|
||||
var photos = r.flawPhotos && r.flawPhotos.length > 0 ? r.flawPhotos : [];
|
||||
return photos.length > 0 ? React.createElement(Button, { type: 'link', size: 'small', onClick: function (e) { if (e) { e.preventDefault(); e.stopPropagation(); } openPhoto(photos, 0); } }, photos.length + '张') : '-';
|
||||
}},
|
||||
{ title: '操作', key: 'action', width: 80, fixed: 'right', render: function (_, r) {
|
||||
return React.createElement(Button, { type: 'link', size: 'small', onClick: function () {} }, '查看');
|
||||
}}
|
||||
];
|
||||
}
|
||||
|
||||
function getPendingColumns(openPhoto, onEdit) {
|
||||
return [
|
||||
{ title: '创建时间', dataIndex: 'operateDate', key: 'operateDate', width: 160 },
|
||||
{ title: '备车人', dataIndex: 'operator', key: 'operator', width: 90 },
|
||||
{ title: '车辆类型', dataIndex: 'vehicleType', key: 'vehicleType', width: 100 },
|
||||
{ title: '品牌', dataIndex: 'brand', key: 'brand', width: 80 },
|
||||
{ title: '型号', dataIndex: 'model', key: 'model', width: 100 },
|
||||
{ title: '车牌号', dataIndex: 'plateNo', key: 'plateNo', width: 100 },
|
||||
{ title: '车辆识别代码', dataIndex: 'vin', key: 'vin', width: 180 },
|
||||
{ title: '停车场', dataIndex: 'parkingLot', key: 'parkingLot', width: 110 },
|
||||
{ title: '车身广告', dataIndex: 'bodyAd', key: 'bodyAd', width: 90 },
|
||||
{ title: '广告照片', key: 'adPhotos', width: 90, render: function (_, r) {
|
||||
var photos = (r.adPhotos && r.adPhotos.length > 0) ? r.adPhotos : [];
|
||||
return photos.length > 0 ? React.createElement(Button, { type: 'link', size: 'small', onClick: function (e) { if (e) { e.preventDefault(); e.stopPropagation(); } openPhoto(photos, 0); } }, photos.length + '张') : '-';
|
||||
}},
|
||||
{ title: '尾板', dataIndex: 'tailboard', key: 'tailboard', width: 70 },
|
||||
{ title: '是否有挂', dataIndex: 'hasTrailer', key: 'hasTrailer', width: 90 },
|
||||
{ title: '挂车牌号', dataIndex: 'trailerPlate', key: 'trailerPlate', width: 100, render: function (v) { return v || '-'; } },
|
||||
{ title: '瑕疵照片', key: 'flawPhotos', width: 90, render: function (_, r) {
|
||||
var photos = (r.flawPhotos && r.flawPhotos.length > 0) ? r.flawPhotos : [];
|
||||
return photos.length > 0 ? React.createElement(Button, { type: 'link', size: 'small', onClick: function (e) { if (e) { e.preventDefault(); e.stopPropagation(); } openPhoto(photos, 0); } }, photos.length + '张') : '-';
|
||||
}},
|
||||
{ title: '操作', key: 'action', width: 80, fixed: 'right', render: function (_, r) {
|
||||
return React.createElement(Button, { type: 'link', size: 'small', onClick: function () {
|
||||
setAddForm(function (prev) {
|
||||
var n = {};
|
||||
for (var k in prev) n[k] = prev[k];
|
||||
n.plateNo = r.plateNo; n.vehicleType = r.vehicleType; n.brand = r.brand; n.vin = r.vin;
|
||||
n.bodyAd = r.bodyAd; n.adPhotos = r.adPhotos || []; n.tailboard = r.tailboard;
|
||||
n.trailerPlate = r.trailerPlate || ''; n.flawPhotos = r.flawPhotos || [];
|
||||
return n;
|
||||
});
|
||||
setAddStep(1);
|
||||
setCurrentView('add');
|
||||
} }, '编辑');
|
||||
}}
|
||||
];
|
||||
}
|
||||
|
||||
var tablePagination = useMemo(function () {
|
||||
return {
|
||||
current: page,
|
||||
pageSize: pageSize,
|
||||
total: totalCount,
|
||||
showSizeChanger: true,
|
||||
showTotal: function (t) { return '共 ' + t + ' 条'; },
|
||||
pageSizeOptions: ['10', '20', '50'],
|
||||
onChange: function (p, size) {
|
||||
setPage(p);
|
||||
if (size !== pageSize) setPageSize(size);
|
||||
}
|
||||
};
|
||||
}, [page, pageSize, totalCount]);
|
||||
|
||||
// —————— 列表页 ——————
|
||||
function ListView() {
|
||||
var breadcrumbItems = [
|
||||
{ title: '运维管理' },
|
||||
{ title: '车辆业务' },
|
||||
{ title: '备车管理' }
|
||||
];
|
||||
return React.createElement('div', { style: { padding: 24, background: '#f5f5f5', minHeight: '100vh' } },
|
||||
React.createElement('div', { style: { display: 'flex', alignItems: 'center', justifyContent: 'space-between', marginBottom: 16 } },
|
||||
React.createElement(Breadcrumb, { items: breadcrumbItems }),
|
||||
React.createElement(Button, { type: 'link', style: { padding: 0 }, onClick: function () { reqDocOpenState[1](true); } }, '查看需求说明')
|
||||
),
|
||||
React.createElement(Modal, {
|
||||
title: '需求说明',
|
||||
open: reqDocOpenState[0],
|
||||
onCancel: function () { reqDocOpenState[1](false); },
|
||||
footer: null,
|
||||
width: 720,
|
||||
styles: { body: { maxHeight: '70vh', overflow: 'auto', whiteSpace: 'pre-wrap', fontSize: 14 } }
|
||||
}, requirementDocContent.split('\n').map(function (line, idx) {
|
||||
var trimmed = line;
|
||||
if (trimmed.indexOf('#') === 0) {
|
||||
return React.createElement('div', { key: idx, style: { fontWeight: 'bold', marginTop: idx === 0 ? 0 : 16, marginBottom: 8, paddingBottom: 4, borderBottom: '1px solid #f0f0f0' } }, trimmed.replace(/^#\.?/, '').trim());
|
||||
}
|
||||
if (/^\d+\./.test(trimmed)) return React.createElement('div', { key: idx, style: { marginLeft: 12, marginBottom: 4 } }, trimmed);
|
||||
if (trimmed === '') return React.createElement('div', { key: idx, style: { height: 12 } });
|
||||
return React.createElement('div', { key: idx, style: { marginBottom: 8 } }, trimmed);
|
||||
})),
|
||||
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
|
||||
}
|
||||
},
|
||||
React.createElement('div', null,
|
||||
React.createElement('div', { style: { marginBottom: 4 } }, '备车日期'),
|
||||
React.createElement(RangePicker, {
|
||||
value: dateRangeValue,
|
||||
onChange: onDateRangeChange,
|
||||
style: { width: '100%' },
|
||||
placeholder: ['开始日期', '结束日期']
|
||||
})
|
||||
),
|
||||
React.createElement('div', null,
|
||||
React.createElement('div', { style: { marginBottom: 4 } }, '备车人'),
|
||||
React.createElement(Select, {
|
||||
placeholder: '请选择备车人',
|
||||
allowClear: true,
|
||||
showSearch: true,
|
||||
optionFilterProp: 'label',
|
||||
value: filters.operator,
|
||||
onChange: function (v) { setFilters(function (f) { var g = {}; for (var k in f) g[k] = f[k]; g.operator = v; return g; }); },
|
||||
style: { width: '100%' },
|
||||
options: operatorOptions
|
||||
})
|
||||
),
|
||||
React.createElement('div', null,
|
||||
React.createElement('div', { style: { marginBottom: 4 } }, '车牌号'),
|
||||
React.createElement(Select, {
|
||||
placeholder: '请选择车牌号',
|
||||
allowClear: true,
|
||||
showSearch: true,
|
||||
optionFilterProp: 'label',
|
||||
value: filters.plateNo,
|
||||
onChange: function (v) { setFilters(function (f) { var g = {}; for (var k in f) g[k] = f[k]; g.plateNo = v; return g; }); },
|
||||
style: { width: '100%' },
|
||||
options: plateOptions
|
||||
})
|
||||
),
|
||||
React.createElement('div', null,
|
||||
React.createElement('div', { style: { marginBottom: 4 } }, '车辆类型'),
|
||||
React.createElement(Select, {
|
||||
placeholder: '请选择车辆类型',
|
||||
allowClear: true,
|
||||
showSearch: true,
|
||||
optionFilterProp: 'label',
|
||||
value: filters.vehicleType,
|
||||
onChange: function (v) { setFilters(function (f) { var g = {}; for (var k in f) g[k] = f[k]; g.vehicleType = v; return g; }); },
|
||||
style: { width: '100%' },
|
||||
options: vehicleTypeOptions
|
||||
})
|
||||
),
|
||||
React.createElement('div', null,
|
||||
React.createElement('div', { style: { marginBottom: 4 } }, '停车场'),
|
||||
React.createElement(Select, {
|
||||
placeholder: '请选择停车场',
|
||||
allowClear: true,
|
||||
showSearch: true,
|
||||
optionFilterProp: 'label',
|
||||
value: filters.parkingLot,
|
||||
onChange: function (v) { setFilters(function (f) { var g = {}; for (var k in f) g[k] = f[k]; g.parkingLot = v; return g; }); },
|
||||
style: { width: '100%' },
|
||||
options: parkingOptions
|
||||
})
|
||||
)
|
||||
),
|
||||
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(Tabs, {
|
||||
activeKey: activeTab,
|
||||
onChange: function (k) { setActiveTab(k); setPage(1); },
|
||||
tabBarExtraContent: React.createElement('div', { style: { display: 'flex', gap: 8 } },
|
||||
React.createElement(Button, { type: 'primary', onClick: function () {} }, '新增'),
|
||||
activeTab === 'completed' ? React.createElement(Button, { onClick: handleExport }, '导出') : null
|
||||
),
|
||||
items: [
|
||||
{
|
||||
key: 'completed',
|
||||
label: '已完成',
|
||||
children: React.createElement(Table, {
|
||||
columns: getCompletedColumns(openPhotoModal),
|
||||
dataSource: displayCompleted,
|
||||
rowKey: 'id',
|
||||
pagination: tablePagination,
|
||||
scroll: { x: 1400 },
|
||||
size: 'middle'
|
||||
})
|
||||
},
|
||||
{
|
||||
key: 'pending',
|
||||
label: '待提交',
|
||||
children: React.createElement(Table, {
|
||||
columns: getPendingColumns(openPhotoModal),
|
||||
dataSource: displayPending,
|
||||
rowKey: 'id',
|
||||
pagination: tablePagination,
|
||||
scroll: { x: 1400 },
|
||||
size: 'middle'
|
||||
})
|
||||
}
|
||||
]
|
||||
})
|
||||
),
|
||||
// 照片预览:全屏遮罩 + 放大图片,点击遮罩关闭
|
||||
photoModalState[0].open && photoModalState[0].photos && photoModalState[0].photos.length > 0 ? React.createElement('div', {
|
||||
style: {
|
||||
position: 'fixed',
|
||||
top: 0,
|
||||
left: 0,
|
||||
right: 0,
|
||||
bottom: 0,
|
||||
backgroundColor: 'rgba(0,0,0,0.75)',
|
||||
zIndex: 1000,
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
cursor: 'pointer'
|
||||
},
|
||||
onClick: function () { photoModalState[1]({ open: false, photos: [], currentIndex: 0 }); }
|
||||
}, React.createElement('div', {
|
||||
style: { position: 'relative', display: 'flex', flexDirection: 'column', alignItems: 'center', cursor: 'default', maxWidth: '100%', maxHeight: '100%' },
|
||||
onClick: function (e) { if (e) e.stopPropagation(); }
|
||||
},
|
||||
React.createElement('img', {
|
||||
src: photoModalState[0].photos[photoModalState[0].currentIndex] || photoModalState[0].photos[0],
|
||||
alt: '',
|
||||
style: { maxWidth: '90vw', maxHeight: '85vh', objectFit: 'contain' }
|
||||
}),
|
||||
photoModalState[0].photos.length > 1 ? React.createElement('div', { style: { marginTop: 16, display: 'flex', alignItems: 'center', gap: 16 } },
|
||||
React.createElement(Button, {
|
||||
disabled: photoModalState[0].currentIndex === 0,
|
||||
onClick: function (e) { e.stopPropagation(); photoModalState[1]({ open: true, photos: photoModalState[0].photos, currentIndex: Math.max(0, photoModalState[0].currentIndex - 1) }); }
|
||||
}, '上一张'),
|
||||
React.createElement('span', { style: { color: '#fff' } }, (photoModalState[0].currentIndex + 1) + ' / ' + photoModalState[0].photos.length),
|
||||
React.createElement(Button, {
|
||||
disabled: photoModalState[0].currentIndex >= photoModalState[0].photos.length - 1,
|
||||
onClick: function (e) { e.stopPropagation(); photoModalState[1]({ open: true, photos: photoModalState[0].photos, currentIndex: Math.min(photoModalState[0].photos.length - 1, photoModalState[0].currentIndex + 1) }); }
|
||||
}, '下一张')
|
||||
) : null
|
||||
)) : null
|
||||
);
|
||||
}
|
||||
|
||||
// —————— 新增页 ——————
|
||||
function AddView() {
|
||||
var form = addFormState[0];
|
||||
var setForm = addFormState[1];
|
||||
var step = addStepState[0];
|
||||
var addBreadcrumbItems = [
|
||||
{ title: '运维管理' },
|
||||
{ title: '车辆业务' },
|
||||
{ title: '备车管理' },
|
||||
{ title: '新增备车' }
|
||||
];
|
||||
return React.createElement('div', { style: { padding: 24, background: '#f5f5f5', minHeight: '100vh' } },
|
||||
React.createElement(Breadcrumb, { items: addBreadcrumbItems, style: { marginBottom: 16 } }),
|
||||
React.createElement(Card, null,
|
||||
React.createElement(Steps, { current: step - 1, style: { marginBottom: 24 }, items: [
|
||||
{ title: '步骤1 车辆记录' },
|
||||
{ title: '步骤2 备车检查' }
|
||||
] }),
|
||||
step === 1 ? React.createElement(Row, { gutter: [16, 16] },
|
||||
React.createElement(Col, { span: 24 }, React.createElement('span', { style: { color: '#666', marginRight: 8 } }, '车牌号 *'), React.createElement(Select, { placeholder: '请选择车牌号(仅库存车辆)', allowClear: true, showSearch: true, optionFilterProp: 'label', value: form.plateNo || undefined, onChange: onPlateSelect, style: { width: 200 }, options: plateOptions })),
|
||||
React.createElement(Col, { span: 24 }, React.createElement('span', { style: { color: '#666', marginRight: 8 } }, '车辆类型'), React.createElement(Input, { value: form.vehicleType, readOnly: true, style: { width: 200, background: '#f5f5f5' } })),
|
||||
React.createElement(Col, { span: 24 }, React.createElement('span', { style: { color: '#666', marginRight: 8 } }, '品牌'), React.createElement(Input, { value: form.brand, readOnly: true, style: { width: 200, background: '#f5f5f5' } })),
|
||||
React.createElement(Col, { span: 24 }, React.createElement('span', { style: { color: '#666', marginRight: 8 } }, '车架号'), React.createElement(Input, { value: form.vin, readOnly: true, style: { width: 200, background: '#f5f5f5' } })),
|
||||
React.createElement(Col, { span: 24 }, React.createElement('span', { style: { color: '#666', marginRight: 8 } }, '车身广告 *'), React.createElement(Radio.Group, { value: form.bodyAd, onChange: function (e) { setForm(function (p) { var n = {}; for (var k in p) n[k] = p[k]; n.bodyAd = e.target.value; return n; }); }, options: [{ value: '无', label: '无' }, { value: '有', label: '有' }] })),
|
||||
form.bodyAd === '有' ? React.createElement(Col, { span: 24 }, React.createElement('span', { style: { color: '#666', marginRight: 8 } }, '广告照片(最多5张)'), React.createElement(Space, null, (form.adPhotos || []).slice(0, 5).map(function (url, i) { return React.createElement('img', { key: i, src: url, alt: '', style: { width: 60, height: 60, objectFit: 'cover', borderRadius: 4 } }); }), (form.adPhotos || []).length < 5 ? React.createElement(Button, { onClick: function () { setForm(function (p) { var n = {}; for (var k in p) n[k] = p[k]; n.adPhotos = (p.adPhotos || []).concat(['https://picsum.photos/200/150?r=' + Date.now()]); return n; }); } }, '上传') : null)) : null,
|
||||
React.createElement(Col, { span: 24 }, React.createElement('span', { style: { color: '#666', marginRight: 8 } }, '尾板 *'), React.createElement(Radio.Group, { value: form.tailboard, onChange: function (e) { setForm(function (p) { var n = {}; for (var k in p) n[k] = p[k]; n.tailboard = e.target.value; return n; }); }, options: [{ value: '无', label: '无' }, { value: '有', label: '有' }] })),
|
||||
React.createElement(Col, { span: 24 }, React.createElement('span', { style: { color: '#666', marginRight: 8 } }, '挂车牌号(有挂时填写)'), React.createElement(Input, { value: form.trailerPlate, onChange: function (e) { setForm(function (p) { var n = {}; for (var k in p) n[k] = p[k]; n.trailerPlate = e.target.value; return n; }); }, placeholder: '不填视为无挂', style: { width: 200 } })),
|
||||
React.createElement(Col, { span: 24 }, React.createElement('span', { style: { color: '#666', marginRight: 8 } }, '瑕疵照片(最多5张)'), React.createElement(Space, null, (form.flawPhotos || []).slice(0, 5).map(function (url, i) { return React.createElement('img', { key: i, src: url, alt: '', style: { width: 60, height: 60, objectFit: 'cover', borderRadius: 4 } }); }), (form.flawPhotos || []).length < 5 ? React.createElement(Button, { onClick: function () { setForm(function (p) { var n = {}; for (var k in p) n[k] = p[k]; n.flawPhotos = (p.flawPhotos || []).concat(['https://picsum.photos/200/150?f=' + Date.now()]); return n; }); } }, '上传') : null)),
|
||||
React.createElement(Col, { span: 24 }, React.createElement(Space, null, React.createElement(Button, { type: 'primary', onClick: handleAddNext }, '下一步'), React.createElement(Button, { onClick: handleAddSave }, '保存'), React.createElement(Button, { onClick: function () { setCurrentView('list'); } }, '取消')))
|
||||
) : React.createElement('div', null,
|
||||
React.createElement('div', { style: { marginBottom: 16, fontWeight: 600 } }, '备车检查'),
|
||||
React.createElement(Table, {
|
||||
dataSource: form.inspectionList || [],
|
||||
rowKey: function (_, i) { return i; },
|
||||
pagination: false,
|
||||
columns: [
|
||||
{ title: '检查类型', dataIndex: 'checkType', width: 100 },
|
||||
{ title: '检查项', dataIndex: 'checkItem', width: 120 },
|
||||
{ title: '检查项结果', dataIndex: 'result', width: 120, render: function (val, record, i) {
|
||||
return React.createElement(Select, { value: val, onChange: function (v) { setForm(function (p) { var n = {}; for (var k in p) n[k] = p[k]; var list = (p.inspectionList || []).slice(); list[i] = Object.assign({}, list[i], { result: v }); n.inspectionList = list; return n; }); }, style: { width: '100%' }, options: [{ value: '正常', label: '正常' }, { value: '异常', label: '异常' }] });
|
||||
}},
|
||||
{ title: '胎纹深度(轮胎时)', key: 'treadDepth', width: 140, render: function (_, record, i) {
|
||||
if (record.checkItem && record.checkItem.indexOf('胎') !== -1) {
|
||||
return React.createElement(Input, { value: record.treadDepth, onChange: function (e) { setForm(function (p) { var n = {}; for (var k in p) n[k] = p[k]; var list = (p.inspectionList || []).slice(); list[i] = Object.assign({}, list[i], { treadDepth: e.target.value }); n.inspectionList = list; return n; }); }, placeholder: '胎纹深度' });
|
||||
}
|
||||
return '-';
|
||||
}},
|
||||
{ title: '备注', dataIndex: 'remark', render: function (val, record, i) {
|
||||
return React.createElement(Input, { value: val, onChange: function (e) { setForm(function (p) { var n = {}; for (var k in p) n[k] = p[k]; var list = (p.inspectionList || []).slice(); list[i] = Object.assign({}, list[i], { remark: e.target.value }); n.inspectionList = list; return n; }); }, placeholder: '备注' });
|
||||
}}
|
||||
]
|
||||
}),
|
||||
React.createElement('div', { style: { marginTop: 16 } }, React.createElement(Space, null, React.createElement(Button, { type: 'primary', onClick: handleAddSubmit }, '提交'), React.createElement(Button, { onClick: handleAddSave }, '保存'), React.createElement(Button, { onClick: function () { setCurrentView('list'); } }, '取消')))
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
return ListView();
|
||||
};
|
||||
|
||||
if (typeof window !== 'undefined') {
|
||||
window.Component = Component;
|
||||
if (document.readyState === 'loading') {
|
||||
document.addEventListener('DOMContentLoaded', function () {
|
||||
var rootEl = document.getElementById('root');
|
||||
if (rootEl && window.ReactDOM && window.React) {
|
||||
var root = ReactDOM.createRoot(rootEl);
|
||||
root.render(React.createElement(Component));
|
||||
}
|
||||
});
|
||||
} else {
|
||||
var rootEl = document.getElementById('root');
|
||||
if (rootEl && window.ReactDOM && window.React) {
|
||||
var root = ReactDOM.createRoot(rootEl);
|
||||
root.render(React.createElement(Component));
|
||||
}
|
||||
}
|
||||
}
|
||||
143
web端/运维管理/车辆业务/新增后装设备.jsx
Normal file
143
web端/运维管理/车辆业务/新增后装设备.jsx
Normal file
@@ -0,0 +1,143 @@
|
||||
// 【重要】必须使用 const Component 作为组件变量名
|
||||
// 新增后装设备 - 运维管理-车辆业务
|
||||
var ARCO_TOKEN = {
|
||||
primary: '#165DFF',
|
||||
primaryHover: '#4080FF',
|
||||
neutral1: '#FFFFFF',
|
||||
neutral4: '#E5E6EB',
|
||||
neutral6: '#86909C',
|
||||
neutral8: '#1D2129',
|
||||
border: '#E5E6EB',
|
||||
fill: '#F2F3F5',
|
||||
shadowLight: '0 1px 2px rgba(0,0,0,0.05)',
|
||||
radiusLarge: '8px',
|
||||
spacing16: '16px',
|
||||
spacing24: '24px',
|
||||
fontSize14: '14px',
|
||||
fontSize16: '16px',
|
||||
fontFamily: '-apple-system, BlinkMacSystemFont, "PingFang SC", "Helvetica Neue", Arial, sans-serif',
|
||||
link: '#165DFF'
|
||||
};
|
||||
|
||||
var DEVICE_TYPES = ['GPS', '尾板', '车身广告', 'G7安全套件', 'G7普通设备', 'G7温控设备', '备胎'];
|
||||
|
||||
var MOCK_VEHICLE_OPTIONS = ['粤A12345', '粤A67890', '粤B11111', '粤B22222', '粤C33333', '京A88888'];
|
||||
|
||||
const Component = function () {
|
||||
var antd = window.antd;
|
||||
var Select = antd.Select;
|
||||
var Button = antd.Button;
|
||||
var Input = antd.Input;
|
||||
var message = antd.message;
|
||||
var Option = Select.Option;
|
||||
|
||||
var _useState = React.useState('');
|
||||
var deviceType = _useState[0];
|
||||
var setDeviceType = _useState[1];
|
||||
|
||||
var _useState2 = React.useState('');
|
||||
var vehicle = _useState2[0];
|
||||
var setVehicle = _useState2[1];
|
||||
|
||||
var _useState3 = React.useState('');
|
||||
var supplier = _useState3[0];
|
||||
var setSupplier = _useState3[1];
|
||||
|
||||
var handleSubmit = function () {
|
||||
message.success('新增成功');
|
||||
setDeviceType('');
|
||||
setVehicle('');
|
||||
setSupplier('');
|
||||
};
|
||||
|
||||
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' },
|
||||
breadcrumbLink: { color: t.link, textDecoration: 'none', marginRight: '8px' },
|
||||
breadcrumbCurrent: { color: t.neutral8 },
|
||||
card: { backgroundColor: t.neutral1, borderRadius: t.radiusLarge, boxShadow: t.shadowLight, marginBottom: t.spacing16, padding: t.spacing24, maxWidth: 560 },
|
||||
label: { display: 'block', marginBottom: 8, fontSize: t.fontSize14, color: t.neutral8 },
|
||||
row: { marginBottom: t.spacing16 },
|
||||
actions: { marginTop: t.spacing24, display: 'flex', gap: 12 }
|
||||
};
|
||||
|
||||
var deviceTypeOptions = DEVICE_TYPES.map(function (type) {
|
||||
return React.createElement(Option, { key: type, value: type }, type);
|
||||
});
|
||||
|
||||
var vehicleOptions = MOCK_VEHICLE_OPTIONS.map(function (v) {
|
||||
return React.createElement(Option, { key: v, value: v }, v);
|
||||
});
|
||||
|
||||
return React.createElement(
|
||||
'div',
|
||||
{ style: styles.page },
|
||||
React.createElement(
|
||||
'div',
|
||||
{ style: styles.breadcrumb },
|
||||
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.card },
|
||||
React.createElement('div', { style: { fontSize: t.fontSize16, fontWeight: 600, marginBottom: t.spacing24, color: t.neutral8 } }, '新增后装设备'),
|
||||
React.createElement('div', { style: styles.row },
|
||||
React.createElement('label', { style: styles.label }, '设备类型'),
|
||||
React.createElement(Select, {
|
||||
placeholder: '请选择设备类型',
|
||||
style: { width: '100%' },
|
||||
value: deviceType || undefined,
|
||||
onChange: function (v) { setDeviceType(v || ''); },
|
||||
allowClear: true
|
||||
}, deviceTypeOptions)
|
||||
),
|
||||
React.createElement('div', { style: styles.row },
|
||||
React.createElement('label', { style: styles.label }, '使用车辆'),
|
||||
React.createElement(Select, {
|
||||
placeholder: '请选择或输入搜索',
|
||||
style: { width: '100%' },
|
||||
value: vehicle || undefined,
|
||||
onChange: function (v) { setVehicle(v || ''); },
|
||||
showSearch: true,
|
||||
allowClear: true,
|
||||
filterOption: function (input, opt) {
|
||||
var c = opt && opt.children;
|
||||
return c && String(c).toLowerCase().indexOf((input || '').toLowerCase()) >= 0;
|
||||
}
|
||||
}, vehicleOptions)
|
||||
),
|
||||
React.createElement('div', { style: styles.row },
|
||||
React.createElement('label', { style: styles.label }, '供应商'),
|
||||
React.createElement(Input, {
|
||||
placeholder: '请输入供应商',
|
||||
value: supplier,
|
||||
onChange: function (e) { setSupplier(e.target.value); }
|
||||
})
|
||||
),
|
||||
React.createElement('div', { style: styles.actions },
|
||||
React.createElement(Button, { type: 'primary', onClick: handleSubmit }, '提交'),
|
||||
React.createElement(Button, { onClick: function () { setDeviceType(''); setVehicle(''); setSupplier(''); } }, '重置')
|
||||
)
|
||||
)
|
||||
);
|
||||
};
|
||||
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);
|
||||
}
|
||||
}
|
||||
472
web端/运维管理/车辆业务/新增备车.jsx
Normal file
472
web端/运维管理/车辆业务/新增备车.jsx
Normal file
@@ -0,0 +1,472 @@
|
||||
// 【重要】必须使用 const Component 作为组件变量名
|
||||
// 车辆业务 - 新增备车(ONEOS运管平台,布局参照新增租赁合同)
|
||||
|
||||
const Component = function () {
|
||||
var useState = React.useState;
|
||||
var useCallback = React.useCallback;
|
||||
var useMemo = React.useMemo;
|
||||
var useRef = React.useRef;
|
||||
|
||||
var antd = window.antd;
|
||||
var Breadcrumb = antd.Breadcrumb;
|
||||
var Card = antd.Card;
|
||||
var Select = antd.Select;
|
||||
var Input = antd.Input;
|
||||
var Button = antd.Button;
|
||||
var Switch = antd.Switch;
|
||||
var Drawer = antd.Drawer;
|
||||
var Table = antd.Table;
|
||||
var message = antd.message;
|
||||
var Modal = antd.Modal;
|
||||
var Space = antd.Space;
|
||||
|
||||
// 车牌管理 mock:车牌号及对应车辆信息、后装设备(车身广告、尾板)
|
||||
var plateManageList = [
|
||||
{ plateNo: '京A12345', vehicleType: '厢式货车', brand: '东风', model: 'DFH1180', vin: 'LGHXCAE28M1234567', bodyAd: true, tailboard: true },
|
||||
{ plateNo: '京C11111', vehicleType: '平板货车', brand: '福田', model: 'BJ1180', vin: 'LGHXCAE28M7654321', bodyAd: false, tailboard: false },
|
||||
{ plateNo: '京D22222', vehicleType: '厢式货车', brand: '江淮', model: 'HFC1180', vin: 'LGHXCAE28M8888888', bodyAd: true, tailboard: false },
|
||||
{ plateNo: '京E33333', vehicleType: '栏板货车', brand: '重汽', model: 'ZZ1180', vin: 'LGHXCAE28M7777777', bodyAd: false, tailboard: true },
|
||||
{ plateNo: '京F10001', vehicleType: '厢式货车', brand: '江淮', model: 'HFC1180', vin: 'LGHXCAE28M9990001', bodyAd: true, tailboard: true }
|
||||
];
|
||||
|
||||
// 备车检查单:类别 -> 检查项目列表
|
||||
var inspectionCategoryItems = {
|
||||
'车灯': ['大灯', '转向灯', '小灯', '示廓灯', '刹车灯', '倒车灯', '牌照灯', '防雾灯', '室内灯'],
|
||||
'仪表盘': ['氢系统指示', '电控系统指示', '数值清晰准确', '故障报警灯'],
|
||||
'驾驶室': ['点烟器', '车窗升降', '按键开关', '雨刮器', '内后视镜是否正常', '内/外门把手', '安全带', '空调冷暖风', '仪表盘', '门锁功能', '手刹', '车钥匙功能是否正常', '喇叭', '音响功能', '遮阳板', '主副驾座椅', '方向盘', '内饰干净整洁'],
|
||||
'轮胎': ['前左胎', '前右胎', '后左胎', '后右胎'],
|
||||
'液位检查': ['冷却液', '制动液', '玻璃水'],
|
||||
'外观检查': ['车身外观', '漆面', '玻璃'],
|
||||
'车辆外观': ['整车外观'],
|
||||
'其他': ['其他检查项'],
|
||||
'随车工具': ['三角牌', '灭火器', '反光背心'],
|
||||
'随车证件': ['行驶证', '营运证', '保险单'],
|
||||
'整车': ['整车状态'],
|
||||
'燃料电池系统': ['氢系统', '储氢瓶'],
|
||||
'冷机': ['冷机运行'],
|
||||
'制动系统': ['制动踏板', '驻车制动']
|
||||
};
|
||||
|
||||
function buildInspectionList() {
|
||||
var list = [];
|
||||
var categories = Object.keys(inspectionCategoryItems);
|
||||
for (var i = 0; i < categories.length; i++) {
|
||||
var cat = categories[i];
|
||||
var items = inspectionCategoryItems[cat];
|
||||
for (var j = 0; j < items.length; j++) {
|
||||
list.push({ category: cat, checkItem: items[j], checked: true, remark: '' });
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
var formState = useState({
|
||||
plateNo: '',
|
||||
vehicleType: '',
|
||||
brand: '',
|
||||
model: '',
|
||||
vin: '',
|
||||
bodyAd: true,
|
||||
adPhotos: [],
|
||||
tailboard: false,
|
||||
trailerPlate: '',
|
||||
flawPhotos: [],
|
||||
inspectionList: buildInspectionList()
|
||||
});
|
||||
var form = formState[0];
|
||||
var setForm = formState[1];
|
||||
|
||||
var drawerOpenState = useState(false);
|
||||
var photoPreviewState = useState({ open: false, url: null });
|
||||
var reqDocOpenState = useState(false);
|
||||
var adPhotoInputRef = useRef(null);
|
||||
var flawPhotoInputRef = useRef(null);
|
||||
var plateOptions = useMemo(function () {
|
||||
return plateManageList.map(function (p) { return { value: p.plateNo, label: p.plateNo }; });
|
||||
}, []);
|
||||
|
||||
var onPlateSelect = useCallback(function (plateNo) {
|
||||
var vehicle = plateManageList.find(function (p) { return p.plateNo === plateNo; });
|
||||
if (!vehicle) return;
|
||||
setForm(function (prev) {
|
||||
var next = {};
|
||||
for (var k in prev) next[k] = prev[k];
|
||||
next.plateNo = vehicle.plateNo;
|
||||
next.vehicleType = vehicle.vehicleType || '';
|
||||
next.brand = vehicle.brand || '';
|
||||
next.model = vehicle.model || '';
|
||||
next.vin = vehicle.vin || '';
|
||||
next.bodyAd = !!vehicle.bodyAd;
|
||||
next.tailboard = !!vehicle.tailboard;
|
||||
return next;
|
||||
});
|
||||
}, []);
|
||||
|
||||
var updateInspection = useCallback(function (index, field, value) {
|
||||
setForm(function (prev) {
|
||||
var n = {};
|
||||
for (var k in prev) n[k] = prev[k];
|
||||
var list = (prev.inspectionList || []).slice();
|
||||
var row = list[index] || {};
|
||||
list[index] = Object.assign({}, row, { [field]: value });
|
||||
n.inspectionList = list;
|
||||
return n;
|
||||
});
|
||||
}, []);
|
||||
|
||||
var addAdPhoto = useCallback(function () {
|
||||
if ((form.adPhotos || []).length >= 4) { message.warning('最多上传4张'); return; }
|
||||
if (adPhotoInputRef.current) adPhotoInputRef.current.click();
|
||||
}, [form.adPhotos]);
|
||||
var onAdPhotoFileChange = useCallback(function (e) {
|
||||
var files = e.target.files;
|
||||
if (!files || files.length === 0) return;
|
||||
setForm(function (p) {
|
||||
var current = p.adPhotos || [];
|
||||
var remain = 4 - current.length;
|
||||
if (remain <= 0) return p;
|
||||
var urls = [];
|
||||
for (var i = 0; i < files.length && urls.length < remain; i++) {
|
||||
if (files[i].type.indexOf('image') !== -1) urls.push(URL.createObjectURL(files[i]));
|
||||
}
|
||||
if (urls.length === 0) return p;
|
||||
var n = {}; for (var k in p) n[k] = p[k]; n.adPhotos = current.concat(urls); return n;
|
||||
});
|
||||
e.target.value = '';
|
||||
}, []);
|
||||
var removeAdPhoto = useCallback(function (idx) {
|
||||
setForm(function (p) {
|
||||
var n = {};
|
||||
for (var k in p) n[k] = p[k];
|
||||
var arr = (p.adPhotos || []).slice();
|
||||
var url = arr[idx];
|
||||
if (url && url.indexOf('blob:') === 0) URL.revokeObjectURL(url);
|
||||
arr.splice(idx, 1);
|
||||
n.adPhotos = arr;
|
||||
return n;
|
||||
});
|
||||
}, []);
|
||||
var addFlawPhoto = useCallback(function () {
|
||||
if ((form.flawPhotos || []).length >= 4) { message.warning('最多上传4张'); return; }
|
||||
if (flawPhotoInputRef.current) flawPhotoInputRef.current.click();
|
||||
}, [form.flawPhotos]);
|
||||
var onFlawPhotoFileChange = useCallback(function (e) {
|
||||
var files = e.target.files;
|
||||
if (!files || files.length === 0) return;
|
||||
setForm(function (p) {
|
||||
var current = p.flawPhotos || [];
|
||||
var remain = 4 - current.length;
|
||||
if (remain <= 0) return p;
|
||||
var urls = [];
|
||||
for (var i = 0; i < files.length && urls.length < remain; i++) {
|
||||
if (files[i].type.indexOf('image') !== -1) urls.push(URL.createObjectURL(files[i]));
|
||||
}
|
||||
if (urls.length === 0) return p;
|
||||
var n = {}; for (var k in p) n[k] = p[k]; n.flawPhotos = current.concat(urls); return n;
|
||||
});
|
||||
e.target.value = '';
|
||||
}, []);
|
||||
var removeFlawPhoto = useCallback(function (idx) {
|
||||
setForm(function (p) {
|
||||
var n = {};
|
||||
for (var k in p) n[k] = p[k];
|
||||
var arr = (p.flawPhotos || []).slice();
|
||||
var url = arr[idx];
|
||||
if (url && url.indexOf('blob:') === 0) URL.revokeObjectURL(url);
|
||||
arr.splice(idx, 1);
|
||||
n.flawPhotos = arr;
|
||||
return n;
|
||||
});
|
||||
}, []);
|
||||
|
||||
var handleSubmit = useCallback(function () {
|
||||
if (!form.plateNo) { message.warning('请选择车牌号'); return; }
|
||||
message.success('备车成功');
|
||||
// 保存数据并跳转至备车管理-已完成(实际项目接路由)
|
||||
if (typeof window !== 'undefined' && window.history) window.history.back();
|
||||
}, [form.plateNo]);
|
||||
var handleSave = useCallback(function () {
|
||||
if (!form.plateNo) { message.warning('请选择车牌号'); return; }
|
||||
message.success('暂存成功');
|
||||
// 保存数据并跳转至备车管理-待提交
|
||||
if (typeof window !== 'undefined' && window.history) window.history.back();
|
||||
}, [form.plateNo]);
|
||||
|
||||
// 布局样式(参照新增租赁合同)
|
||||
var styles = {
|
||||
page: { padding: '16px 24px 80px', backgroundColor: '#f5f5f5', minHeight: '100vh', fontSize: 14 },
|
||||
breadcrumb: { marginBottom: 16, color: '#666' },
|
||||
breadcrumbSep: { margin: '0 8px', color: '#999' },
|
||||
card: { backgroundColor: '#fff', borderRadius: 8, marginBottom: 16, boxShadow: '0 1px 2px rgba(0,0,0,0.05)', overflow: 'hidden' },
|
||||
cardBody: { padding: '20px 24px' },
|
||||
formRow: { display: 'flex', flexWrap: 'wrap', marginBottom: 16 },
|
||||
formCol: { flex: '0 0 33.33%', minWidth: 200, paddingRight: 16, marginBottom: 8, boxSizing: 'border-box' },
|
||||
formColFull: { flex: '0 0 100%', marginBottom: 8, boxSizing: 'border-box' },
|
||||
label: { display: 'block', marginBottom: 6, color: '#333' },
|
||||
labelRequired: { color: '#ff4d4f', marginRight: 4 },
|
||||
footer: { position: 'fixed', bottom: 0, left: 0, right: 0, padding: '12px 24px', backgroundColor: '#fff', borderTop: '1px solid #e8e8e8', display: 'flex', gap: 12, zIndex: 99 }
|
||||
};
|
||||
|
||||
var FormItem = function (props) {
|
||||
var colStyle = props.fullWidth ? styles.formColFull : styles.formCol;
|
||||
return React.createElement('div', { style: colStyle },
|
||||
React.createElement('label', { style: styles.label },
|
||||
props.required ? React.createElement('span', { style: styles.labelRequired }, '*') : null,
|
||||
props.label
|
||||
),
|
||||
props.children
|
||||
);
|
||||
};
|
||||
|
||||
var inspectionList = form.inspectionList || [];
|
||||
var categoryRowSpans = useMemo(function () {
|
||||
var list = inspectionList;
|
||||
var spans = [];
|
||||
var i = 0;
|
||||
while (i < list.length) {
|
||||
var cat = list[i].category;
|
||||
var start = i;
|
||||
while (i < list.length && list[i].category === cat) i++;
|
||||
spans[start] = i - start;
|
||||
for (var j = start + 1; j < i; j++) spans[j] = 0;
|
||||
}
|
||||
return spans;
|
||||
}, [form.inspectionList]);
|
||||
|
||||
var inspectionColumns = [
|
||||
{
|
||||
title: '类别',
|
||||
dataIndex: 'category',
|
||||
key: 'category',
|
||||
width: 120,
|
||||
onCell: function (_, index) { return { rowSpan: categoryRowSpans[index] !== undefined ? categoryRowSpans[index] : 1 }; }
|
||||
},
|
||||
{ title: '检查项目', dataIndex: 'checkItem', key: 'checkItem', width: 180 },
|
||||
{
|
||||
title: '检查情况',
|
||||
key: 'checked',
|
||||
width: 100,
|
||||
render: function (_, record, index) {
|
||||
return React.createElement(Switch, {
|
||||
checked: record.checked !== false,
|
||||
onChange: function (checked) { updateInspection(index, 'checked', checked); }
|
||||
});
|
||||
}
|
||||
},
|
||||
{
|
||||
title: '备注',
|
||||
dataIndex: 'remark',
|
||||
key: 'remark',
|
||||
render: function (val, record, index) {
|
||||
return React.createElement(Input, {
|
||||
value: val,
|
||||
onChange: function (e) { updateInspection(index, 'remark', e.target.value); },
|
||||
placeholder: '备注'
|
||||
});
|
||||
}
|
||||
}
|
||||
];
|
||||
|
||||
// 方形拍照图标(广告照片与瑕疵共用)
|
||||
var cameraIconBox = function (onClick) {
|
||||
return React.createElement('div', {
|
||||
role: 'button',
|
||||
tabIndex: 0,
|
||||
onClick: onClick,
|
||||
style: { width: 64, height: 64, border: '1px dashed #d9d9d9', borderRadius: 4, display: 'flex', alignItems: 'center', justifyContent: 'center', cursor: 'pointer', background: '#fafafa', boxSizing: 'border-box' }
|
||||
}, React.createElement('svg', { width: 28, height: 28, viewBox: '0 0 24 24', fill: 'none', stroke: '#999', strokeWidth: 2 },
|
||||
React.createElement('path', { d: 'M23 19a2 2 0 0 1-2 2H3a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h4l2-3h6l2 3h4a2 2 0 0 1 2 2z' }),
|
||||
React.createElement('circle', { cx: 12, cy: 13, r: 4 })
|
||||
));
|
||||
};
|
||||
|
||||
var requirementDocContent = '新增备车\n\n1.面包屑:\n1.1.运维管理-车辆业务-备车管理-新增备车\n\n2.表单:\n2.1.车牌号:必选项,选择器,支持从输入框内输入内容进行模糊搜索,默认拉取「车牌管理」中所有「车牌号」;\n2.2.车辆类型:输入框禁用,选择车牌号后自动拉取该车牌号对应「车辆类型」;\n2.3.品牌:输入框禁用,选择车牌号后自动拉取该车牌号对应「品牌」;\n2.4.型号:输入框禁用,选择车牌号后自动拉取该车牌号对应「型号」\n2.5.车辆识别代码:输入框禁用,选择车牌号后自动拉取该车牌号「车辆识别代码」;\n2.6.车身广告:开关,选择车辆后拉取该车辆「后装设备」「车身广告」,如果该车辆有「车身广告」则勾选为开,如果无则勾选为无。同时如果手动进行操作,会同步到「后装设备」「车身广告」中,安装时间以该条备车记录提交成功为准;\n2.7.广告照片:图片上传,最多支持上传4张图片,支持主流照片格式。上传后,上传按钮后方横排显示已上传图片缩略图,支持点击预览和删除;\n2.8.尾板:开关,选择车辆后拉取该车辆「后装设备」「尾板」,如果该车辆有「尾板」则勾选为开,如果无则勾选为无。同时如果手动进行操作,会同步到「后装设备」「尾板」中,安装时间以该条备车记录提交成功为准;\n2.9.是否有挂:输入框,提示信息为:请输入挂车牌号,不输入为无挂;\n2.10.瑕疵:图片上传,最多支持上传4张图片,支持主流照片格式。上传后,上传按钮后方横排显示已上传图片缩略图,支持点击预览和删除;\n2.11.车辆检查:按钮,文字为备车检查单,点击右侧展开抽屉,抽屉内显示列表,字段为类别、检查项目、选择、备注;\n 2.11.1.类别:分为车灯、仪表盘、驾驶室、轮胎、液位检查、外观检查、车辆外观、其他、随车工具、随车证件、整车、燃料电池系统、冷机、制动系统;\n 2.11.2.检查项目:车灯类别对应(大灯、转向灯、小灯、示廓灯、刹车灯、倒车灯、牌照灯、防雾灯、室内灯)、仪表盘对应(氢系统指示、电控系统指示、数值清晰准确、故障报警灯)、驾驶室对应(点烟器、车窗升降、按键开关、雨刮器、内后视镜是否正常、内/外门把手、安全带、空调冷暖风、仪表盘、门锁功能、手刹、车钥匙功能是否正常、喇叭、音响功能、遮阳板、主副驾座椅、方向盘、内饰干净整洁)\n 2.11.3.检查情况:开关,在检查项目每项后方显示,默认为开,可手动进行关闭;\n 2.11.4.备注:输入框;\n2.12.下方为提交和保存;\n 2.12.1.提交:点击提交,toast提示:备车成功,同时保存该条数据并跳转至「备车管理」「已完成」;\n 2.12.2.保存:点击保存,toast提示:暂存成功,同时保存该条数据并跳转至「备车管理」「待提交」;';
|
||||
|
||||
var breadcrumbNodes = [
|
||||
React.createElement('span', { key: '1' }, '运维管理'),
|
||||
React.createElement('span', { key: '2', style: styles.breadcrumbSep }, ' / '),
|
||||
React.createElement('span', { key: '3' }, '车辆业务'),
|
||||
React.createElement('span', { key: '4', style: styles.breadcrumbSep }, ' / '),
|
||||
React.createElement('span', { key: '5' }, '备车管理'),
|
||||
React.createElement('span', { key: '6', style: styles.breadcrumbSep }, ' / '),
|
||||
React.createElement('span', { key: '7', style: { color: '#1890ff' } }, '新增备车')
|
||||
];
|
||||
|
||||
return React.createElement('div', { style: styles.page },
|
||||
React.createElement('div', { style: { display: 'flex', alignItems: 'center', justifyContent: 'space-between', marginBottom: 16 } },
|
||||
React.createElement('div', { style: styles.breadcrumb }, breadcrumbNodes),
|
||||
React.createElement(Button, { type: 'link', style: { padding: 0 }, onClick: function () { reqDocOpenState[1](true); } }, '查看需求说明')
|
||||
),
|
||||
React.createElement('div', { style: styles.card },
|
||||
React.createElement('div', { style: styles.cardBody },
|
||||
React.createElement('div', { style: styles.formRow },
|
||||
React.createElement(FormItem, { label: '车牌号', required: true },
|
||||
React.createElement(Select, {
|
||||
placeholder: '请选择车牌号',
|
||||
style: { width: '100%' },
|
||||
value: form.plateNo || undefined,
|
||||
onChange: onPlateSelect,
|
||||
showSearch: true,
|
||||
allowClear: true,
|
||||
optionFilterProp: 'label',
|
||||
filterOption: function (input, opt) {
|
||||
return (opt && opt.label && String(opt.label).toLowerCase().indexOf((input || '').toLowerCase()) >= 0);
|
||||
},
|
||||
options: plateOptions
|
||||
})
|
||||
),
|
||||
React.createElement(FormItem, { label: '车辆类型' },
|
||||
React.createElement(Input, { value: form.vehicleType, disabled: true, style: { width: '100%', background: '#f5f5f5' } })
|
||||
),
|
||||
React.createElement(FormItem, { label: '品牌' },
|
||||
React.createElement(Input, { value: form.brand, disabled: true, style: { width: '100%', background: '#f5f5f5' } })
|
||||
),
|
||||
React.createElement(FormItem, { label: '型号' },
|
||||
React.createElement(Input, { value: form.model, disabled: true, style: { width: '100%', background: '#f5f5f5' } })
|
||||
),
|
||||
React.createElement(FormItem, { label: '车辆识别代码' },
|
||||
React.createElement(Input, { value: form.vin, disabled: true, style: { width: '100%', background: '#f5f5f5' } })
|
||||
),
|
||||
React.createElement('div', { style: styles.formCol, key: 'ph0' }),
|
||||
React.createElement(FormItem, { label: '车身广告' },
|
||||
React.createElement(Switch, {
|
||||
checked: form.bodyAd,
|
||||
checkedChildren: '开',
|
||||
unCheckedChildren: '关',
|
||||
onChange: function (checked) {
|
||||
setForm(function (p) { var n = {}; for (var k in p) n[k] = p[k]; n.bodyAd = checked; return n; });
|
||||
}
|
||||
})
|
||||
),
|
||||
React.createElement('div', { style: styles.formCol, key: 'ph1' }),
|
||||
React.createElement('div', { style: styles.formCol, key: 'ph2' }),
|
||||
React.createElement(FormItem, { label: '尾板' },
|
||||
React.createElement(Switch, {
|
||||
checked: form.tailboard,
|
||||
checkedChildren: '开',
|
||||
unCheckedChildren: '关',
|
||||
onChange: function (checked) {
|
||||
setForm(function (p) { var n = {}; for (var k in p) n[k] = p[k]; n.tailboard = checked; return n; });
|
||||
}
|
||||
})
|
||||
),
|
||||
React.createElement(FormItem, { label: '广告照片', fullWidth: true },
|
||||
React.createElement('div', { style: { display: 'flex', flexWrap: 'wrap', alignItems: 'center', gap: 8 } },
|
||||
React.createElement('input', { type: 'file', ref: adPhotoInputRef, accept: 'image/*', multiple: true, style: { display: 'none' }, onChange: onAdPhotoFileChange }),
|
||||
(form.adPhotos || []).length < 4 ? cameraIconBox(addAdPhoto) : null,
|
||||
(form.adPhotos || []).map(function (url, i) {
|
||||
return React.createElement('span', { key: i, style: { position: 'relative', display: 'inline-block' } },
|
||||
React.createElement('img', {
|
||||
src: url,
|
||||
alt: '',
|
||||
style: { width: 64, height: 64, objectFit: 'cover', borderRadius: 4, cursor: 'pointer' },
|
||||
onClick: function () { photoPreviewState[1]({ open: true, url: url }); }
|
||||
}),
|
||||
React.createElement('span', {
|
||||
style: { position: 'absolute', top: -6, right: -6, width: 20, height: 20, borderRadius: '50%', background: '#ff4d4f', color: '#fff', fontSize: 12, display: 'flex', alignItems: 'center', justifyContent: 'center', cursor: 'pointer' },
|
||||
onClick: function () { removeAdPhoto(i); }
|
||||
}, '×')
|
||||
);
|
||||
})
|
||||
)
|
||||
),
|
||||
React.createElement(FormItem, { label: '是否有挂' },
|
||||
React.createElement(Input, {
|
||||
placeholder: '请输入挂车牌号,不输入为无挂',
|
||||
value: form.trailerPlate,
|
||||
onChange: function (e) {
|
||||
setForm(function (p) { var n = {}; for (var k in p) n[k] = p[k]; n.trailerPlate = e.target.value; return n; });
|
||||
},
|
||||
style: { width: '100%', maxWidth: 320 }
|
||||
})
|
||||
),
|
||||
React.createElement(FormItem, { label: '瑕疵', fullWidth: true },
|
||||
React.createElement('div', { style: { display: 'flex', flexWrap: 'wrap', alignItems: 'center', gap: 8 } },
|
||||
React.createElement('input', { type: 'file', ref: flawPhotoInputRef, accept: 'image/*', multiple: true, style: { display: 'none' }, onChange: onFlawPhotoFileChange }),
|
||||
(form.flawPhotos || []).length < 4 ? cameraIconBox(addFlawPhoto) : null,
|
||||
(form.flawPhotos || []).map(function (url, i) {
|
||||
return React.createElement('span', { key: i, style: { position: 'relative', display: 'inline-block' } },
|
||||
React.createElement('img', {
|
||||
src: url,
|
||||
alt: '',
|
||||
style: { width: 64, height: 64, objectFit: 'cover', borderRadius: 4, cursor: 'pointer' },
|
||||
onClick: function () { photoPreviewState[1]({ open: true, url: url }); }
|
||||
}),
|
||||
React.createElement('span', {
|
||||
style: { position: 'absolute', top: -6, right: -6, width: 20, height: 20, borderRadius: '50%', background: '#ff4d4f', color: '#fff', fontSize: 12, display: 'flex', alignItems: 'center', justifyContent: 'center', cursor: 'pointer' },
|
||||
onClick: function () { removeFlawPhoto(i); }
|
||||
}, '×')
|
||||
);
|
||||
})
|
||||
)
|
||||
),
|
||||
React.createElement(FormItem, { label: '车辆检查', fullWidth: true },
|
||||
React.createElement(Button, { type: 'default', onClick: function () { drawerOpenState[1](true); } }, '备车检查单')
|
||||
)
|
||||
)
|
||||
)
|
||||
),
|
||||
React.createElement('div', { style: styles.footer },
|
||||
React.createElement(Button, { type: 'primary', onClick: handleSubmit }, '提交'),
|
||||
React.createElement(Button, { onClick: handleSave }, '保存'),
|
||||
React.createElement(Button, { onClick: function () { if (typeof window !== 'undefined' && window.history) window.history.back(); } }, '取消')
|
||||
),
|
||||
React.createElement(Drawer, {
|
||||
title: '备车检查单',
|
||||
placement: 'right',
|
||||
width: 640,
|
||||
open: drawerOpenState[0],
|
||||
onClose: function () { drawerOpenState[1](false); },
|
||||
styles: { body: { display: 'flex', flexDirection: 'column', height: '100%', overflow: 'hidden', paddingBottom: 0 } },
|
||||
footer: React.createElement('div', { style: { display: 'flex', justifyContent: 'flex-end', gap: 8 } },
|
||||
React.createElement(Button, { onClick: function () { drawerOpenState[1](false); } }, '返回'),
|
||||
React.createElement(Button, { type: 'primary', onClick: function () { drawerOpenState[1](false); message.success('检查单已保存'); } }, '提交')
|
||||
)
|
||||
},
|
||||
React.createElement('div', { style: { flex: 1, minHeight: 0, overflow: 'auto' } },
|
||||
React.createElement(Table, {
|
||||
columns: inspectionColumns,
|
||||
dataSource: form.inspectionList || [],
|
||||
rowKey: function (_, i) { return i; },
|
||||
pagination: false,
|
||||
size: 'small'
|
||||
})
|
||||
)
|
||||
),
|
||||
React.createElement(Modal, {
|
||||
title: '需求说明',
|
||||
open: reqDocOpenState[0],
|
||||
onCancel: function () { reqDocOpenState[1](false); },
|
||||
footer: null,
|
||||
width: 720,
|
||||
styles: { body: { maxHeight: '70vh', overflow: 'auto', whiteSpace: 'pre-wrap', fontSize: 14, lineHeight: 1.8 } }
|
||||
}, requirementDocContent),
|
||||
photoPreviewState[0].open && photoPreviewState[0].url
|
||||
? React.createElement(Modal, {
|
||||
title: '预览',
|
||||
open: true,
|
||||
footer: null,
|
||||
onCancel: function () { photoPreviewState[1]({ open: false, url: null }); }
|
||||
}, React.createElement('img', { src: photoPreviewState[0].url, alt: '', style: { width: '100%' } }))
|
||||
: null
|
||||
);
|
||||
};
|
||||
|
||||
if (typeof window !== 'undefined') {
|
||||
window.Component = Component;
|
||||
if (document.readyState === 'loading') {
|
||||
document.addEventListener('DOMContentLoaded', function () {
|
||||
var rootEl = document.getElementById('root');
|
||||
if (rootEl && window.ReactDOM && window.React) {
|
||||
var root = ReactDOM.createRoot(rootEl);
|
||||
root.render(React.createElement(Component));
|
||||
}
|
||||
});
|
||||
} else {
|
||||
var rootEl = document.getElementById('root');
|
||||
if (rootEl && window.ReactDOM && window.React) {
|
||||
var root = ReactDOM.createRoot(rootEl);
|
||||
root.render(React.createElement(Component));
|
||||
}
|
||||
}
|
||||
}
|
||||
275
web端/运维管理/车辆业务/查看备车.jsx
Normal file
275
web端/运维管理/车辆业务/查看备车.jsx
Normal file
@@ -0,0 +1,275 @@
|
||||
// 【重要】必须使用 const Component 作为组件变量名
|
||||
// 车辆业务 - 查看备车(与新增备车相同布局,全部只读)
|
||||
|
||||
const Component = function () {
|
||||
var useState = React.useState;
|
||||
var useMemo = React.useMemo;
|
||||
|
||||
var antd = window.antd;
|
||||
var Breadcrumb = antd.Breadcrumb;
|
||||
var Card = antd.Card;
|
||||
var Input = antd.Input;
|
||||
var Button = antd.Button;
|
||||
var Drawer = antd.Drawer;
|
||||
var Table = antd.Table;
|
||||
var Modal = antd.Modal;
|
||||
|
||||
var plateManageList = [
|
||||
{ plateNo: '京A12345', vehicleType: '厢式货车', brand: '东风', model: 'DFH1180', vin: 'LGHXCAE28M1234567', bodyAd: true, tailboard: true },
|
||||
{ plateNo: '京C11111', vehicleType: '平板货车', brand: '福田', model: 'BJ1180', vin: 'LGHXCAE28M7654321', bodyAd: false, tailboard: false },
|
||||
{ plateNo: '京D22222', vehicleType: '厢式货车', brand: '江淮', model: 'HFC1180', vin: 'LGHXCAE28M8888888', bodyAd: true, tailboard: false },
|
||||
{ plateNo: '京E33333', vehicleType: '栏板货车', brand: '重汽', model: 'ZZ1180', vin: 'LGHXCAE28M7777777', bodyAd: false, tailboard: true },
|
||||
{ plateNo: '京F10001', vehicleType: '厢式货车', brand: '江淮', model: 'HFC1180', vin: 'LGHXCAE28M9990001', bodyAd: true, tailboard: true }
|
||||
];
|
||||
|
||||
var inspectionCategoryItems = {
|
||||
'车灯': ['大灯', '转向灯', '小灯', '示廓灯', '刹车灯', '倒车灯', '牌照灯', '防雾灯', '室内灯'],
|
||||
'仪表盘': ['氢系统指示', '电控系统指示', '数值清晰准确', '故障报警灯'],
|
||||
'驾驶室': ['点烟器', '车窗升降', '按键开关', '雨刮器', '内后视镜是否正常', '内/外门把手', '安全带', '空调冷暖风', '仪表盘', '门锁功能', '手刹', '车钥匙功能是否正常', '喇叭', '音响功能', '遮阳板', '主副驾座椅', '方向盘', '内饰干净整洁'],
|
||||
'轮胎': ['前左胎', '前右胎', '后左胎', '后右胎'],
|
||||
'液位检查': ['冷却液', '制动液', '玻璃水'],
|
||||
'外观检查': ['车身外观', '漆面', '玻璃'],
|
||||
'车辆外观': ['整车外观'],
|
||||
'其他': ['其他检查项'],
|
||||
'随车工具': ['三角牌', '灭火器', '反光背心'],
|
||||
'随车证件': ['行驶证', '营运证', '保险单'],
|
||||
'整车': ['整车状态'],
|
||||
'燃料电池系统': ['氢系统', '储氢瓶'],
|
||||
'冷机': ['冷机运行'],
|
||||
'制动系统': ['制动踏板', '驻车制动']
|
||||
};
|
||||
|
||||
function buildInspectionList() {
|
||||
var list = [];
|
||||
var categories = Object.keys(inspectionCategoryItems);
|
||||
for (var i = 0; i < categories.length; i++) {
|
||||
var cat = categories[i];
|
||||
var items = inspectionCategoryItems[cat];
|
||||
for (var j = 0; j < items.length; j++) {
|
||||
list.push({ category: cat, checkItem: items[j], checked: true, remark: '' });
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
// 只读:一条已填写的备车记录(不可编辑)
|
||||
var form = useMemo(function () {
|
||||
return {
|
||||
plateNo: '京A12345',
|
||||
vehicleType: '厢式货车',
|
||||
brand: '东风',
|
||||
model: 'DFH1180',
|
||||
vin: 'LGHXCAE28M1234567',
|
||||
bodyAd: true,
|
||||
adPhotos: ['https://picsum.photos/200/150?r=1', 'https://picsum.photos/200/150?r=2'],
|
||||
tailboard: true,
|
||||
trailerPlate: '京B67890',
|
||||
flawPhotos: ['https://picsum.photos/200/150?f=1'],
|
||||
inspectionList: buildInspectionList()
|
||||
};
|
||||
}, []);
|
||||
|
||||
var drawerOpenState = useState(false);
|
||||
var photoPreviewState = useState({ open: false, url: null });
|
||||
var reqDocOpenState = useState(false);
|
||||
|
||||
var styles = {
|
||||
page: { padding: '16px 24px 80px', backgroundColor: '#f5f5f5', minHeight: '100vh', fontSize: 14 },
|
||||
breadcrumb: { marginBottom: 16, color: '#666' },
|
||||
breadcrumbSep: { margin: '0 8px', color: '#999' },
|
||||
card: { backgroundColor: '#fff', borderRadius: 8, marginBottom: 16, boxShadow: '0 1px 2px rgba(0,0,0,0.05)', overflow: 'hidden' },
|
||||
cardBody: { padding: '20px 24px' },
|
||||
formRow: { display: 'flex', flexWrap: 'wrap', marginBottom: 16 },
|
||||
formCol: { flex: '0 0 33.33%', minWidth: 200, paddingRight: 16, marginBottom: 8, boxSizing: 'border-box' },
|
||||
formColFull: { flex: '0 0 100%', marginBottom: 8, boxSizing: 'border-box' },
|
||||
label: { display: 'block', marginBottom: 6, color: '#333' },
|
||||
labelRequired: { color: '#ff4d4f', marginRight: 4 },
|
||||
footer: { position: 'fixed', bottom: 0, left: 0, right: 0, padding: '12px 24px', backgroundColor: '#fff', borderTop: '1px solid #e8e8e8', display: 'flex', gap: 12, zIndex: 99 }
|
||||
};
|
||||
|
||||
var FormItem = function (props) {
|
||||
var colStyle = props.fullWidth ? styles.formColFull : styles.formCol;
|
||||
return React.createElement('div', { style: colStyle },
|
||||
React.createElement('label', { style: styles.label },
|
||||
props.required ? React.createElement('span', { style: styles.labelRequired }, '*') : null,
|
||||
props.label
|
||||
),
|
||||
props.children
|
||||
);
|
||||
};
|
||||
|
||||
var inspectionList = form.inspectionList || [];
|
||||
var categoryRowSpans = useMemo(function () {
|
||||
var list = inspectionList;
|
||||
var spans = [];
|
||||
var i = 0;
|
||||
while (i < list.length) {
|
||||
var cat = list[i].category;
|
||||
var start = i;
|
||||
while (i < list.length && list[i].category === cat) i++;
|
||||
spans[start] = i - start;
|
||||
for (var j = start + 1; j < i; j++) spans[j] = 0;
|
||||
}
|
||||
return spans;
|
||||
}, [form.inspectionList]);
|
||||
|
||||
var inspectionColumns = [
|
||||
{
|
||||
title: '类别',
|
||||
dataIndex: 'category',
|
||||
key: 'category',
|
||||
width: 120,
|
||||
onCell: function (_, index) { return { rowSpan: categoryRowSpans[index] !== undefined ? categoryRowSpans[index] : 1 }; }
|
||||
},
|
||||
{ title: '检查项目', dataIndex: 'checkItem', key: 'checkItem', width: 180 },
|
||||
{
|
||||
title: '检查情况',
|
||||
key: 'checked',
|
||||
width: 100,
|
||||
render: function (_, record) { return record.checked !== false ? '开' : '关'; }
|
||||
},
|
||||
{ title: '备注', dataIndex: 'remark', key: 'remark', render: function (val) { return val || '-'; } }
|
||||
];
|
||||
|
||||
var requirementDocContent = '新增备车\n\n1.面包屑:\n1.1.运维管理-车辆业务-备车管理-新增备车\n\n2.表单:\n2.1.车牌号:必选项,选择器,支持从输入框内输入内容进行模糊搜索,默认拉取「车牌管理」中所有「车牌号」;\n2.2.车辆类型:输入框禁用,选择车牌号后自动拉取该车牌号对应「车辆类型」;\n2.3.品牌:输入框禁用,选择车牌号后自动拉取该车牌号对应「品牌」;\n2.4.型号:输入框禁用,选择车牌号后自动拉取该车牌号对应「型号」\n2.5.车辆识别代码:输入框禁用,选择车牌号后自动拉取该车牌号「车辆识别代码」;\n2.6.车身广告:开关,选择车辆后拉取该车辆「后装设备」「车身广告」,如果该车辆有「车身广告」则勾选为开,如果无则勾选为无。同时如果手动进行操作,会同步到「后装设备」「车身广告」中,安装时间以该条备车记录提交成功为准;\n2.7.广告照片:图片上传,最多支持上传4张图片,支持主流照片格式。上传后,上传按钮后方横排显示已上传图片缩略图,支持点击预览和删除;\n2.8.尾板:开关,选择车辆后拉取该车辆「后装设备」「尾板」,如果该车辆有「尾板」则勾选为开,如果无则勾选为无。同时如果手动进行操作,会同步到「后装设备」「尾板」中,安装时间以该条备车记录提交成功为准;\n2.9.是否有挂:输入框,提示信息为:请输入挂车牌号,不输入为无挂;\n2.10.瑕疵:图片上传,最多支持上传4张图片,支持主流照片格式。上传后,上传按钮后方横排显示已上传图片缩略图,支持点击预览和删除;\n2.11.车辆检查:按钮,文字为备车检查单,点击右侧展开抽屉,抽屉内显示列表,字段为类别、检查项目、选择、备注;\n 2.11.1.类别:分为车灯、仪表盘、驾驶室、轮胎、液位检查、外观检查、车辆外观、其他、随车工具、随车证件、整车、燃料电池系统、冷机、制动系统;\n 2.11.2.检查项目:车灯类别对应(大灯、转向灯、小灯、示廓灯、刹车灯、倒车灯、牌照灯、防雾灯、室内灯)、仪表盘对应(氢系统指示、电控系统指示、数值清晰准确、故障报警灯)、驾驶室对应(点烟器、车窗升降、按键开关、雨刮器、内后视镜是否正常、内/外门把手、安全带、空调冷暖风、仪表盘、门锁功能、手刹、车钥匙功能是否正常、喇叭、音响功能、遮阳板、主副驾座椅、方向盘、内饰干净整洁)\n 2.11.3.检查情况:开关,在检查项目每项后方显示,默认为开,可手动进行关闭;\n 2.11.4.备注:输入框;\n2.12.下方为提交和保存;\n 2.12.1.提交:点击提交,toast提示:备车成功,同时保存该条数据并跳转至「备车管理」「已完成」;\n 2.12.2.保存:点击保存,toast提示:暂存成功,同时保存该条数据并跳转至「备车管理」「待提交」;';
|
||||
|
||||
var breadcrumbNodes = [
|
||||
React.createElement('span', { key: '1' }, '运维管理'),
|
||||
React.createElement('span', { key: '2', style: styles.breadcrumbSep }, ' / '),
|
||||
React.createElement('span', { key: '3' }, '车辆业务'),
|
||||
React.createElement('span', { key: '4', style: styles.breadcrumbSep }, ' / '),
|
||||
React.createElement('span', { key: '5' }, '备车管理'),
|
||||
React.createElement('span', { key: '6', style: styles.breadcrumbSep }, ' / '),
|
||||
React.createElement('span', { key: '7', style: { color: '#1890ff' } }, '查看备车')
|
||||
];
|
||||
|
||||
return React.createElement('div', { style: styles.page },
|
||||
React.createElement('div', { style: { display: 'flex', alignItems: 'center', justifyContent: 'space-between', marginBottom: 16 } },
|
||||
React.createElement('div', { style: styles.breadcrumb }, breadcrumbNodes),
|
||||
React.createElement(Button, { type: 'link', style: { padding: 0 }, onClick: function () { reqDocOpenState[1](true); } }, '查看需求说明')
|
||||
),
|
||||
React.createElement('div', { style: styles.card },
|
||||
React.createElement('div', { style: styles.cardBody },
|
||||
React.createElement('div', { style: styles.formRow },
|
||||
React.createElement(FormItem, { label: '车牌号', required: true },
|
||||
React.createElement(Input, { value: form.plateNo, disabled: true, style: { width: '100%', background: '#f5f5f5' } })
|
||||
),
|
||||
React.createElement(FormItem, { label: '车辆类型' },
|
||||
React.createElement(Input, { value: form.vehicleType, disabled: true, style: { width: '100%', background: '#f5f5f5' } })
|
||||
),
|
||||
React.createElement(FormItem, { label: '品牌' },
|
||||
React.createElement(Input, { value: form.brand, disabled: true, style: { width: '100%', background: '#f5f5f5' } })
|
||||
),
|
||||
React.createElement(FormItem, { label: '型号' },
|
||||
React.createElement(Input, { value: form.model, disabled: true, style: { width: '100%', background: '#f5f5f5' } })
|
||||
),
|
||||
React.createElement(FormItem, { label: '车辆识别代码' },
|
||||
React.createElement(Input, { value: form.vin, disabled: true, style: { width: '100%', background: '#f5f5f5' } })
|
||||
),
|
||||
React.createElement('div', { style: styles.formCol, key: 'ph0' }),
|
||||
React.createElement(FormItem, { label: '车身广告' },
|
||||
React.createElement(Input, { value: form.bodyAd ? '开' : '关', disabled: true, style: { width: '100%', background: '#f5f5f5' } })
|
||||
),
|
||||
React.createElement('div', { style: styles.formCol, key: 'ph1' }),
|
||||
React.createElement('div', { style: styles.formCol, key: 'ph2' }),
|
||||
React.createElement(FormItem, { label: '尾板' },
|
||||
React.createElement(Input, { value: form.tailboard ? '开' : '关', disabled: true, style: { width: '100%', background: '#f5f5f5' } })
|
||||
),
|
||||
React.createElement(FormItem, { label: '广告照片', fullWidth: true },
|
||||
React.createElement('div', { style: { display: 'flex', flexWrap: 'wrap', alignItems: 'center', gap: 8 } },
|
||||
(form.adPhotos || []).map(function (url, i) {
|
||||
return React.createElement('img', {
|
||||
key: i,
|
||||
src: url,
|
||||
alt: '',
|
||||
style: { width: 64, height: 64, objectFit: 'cover', borderRadius: 4, cursor: 'pointer' },
|
||||
onClick: function () { photoPreviewState[1]({ open: true, url: url }); }
|
||||
});
|
||||
}),
|
||||
(form.adPhotos || []).length === 0 ? React.createElement('span', { style: { color: '#999' } }, '无') : null
|
||||
)
|
||||
),
|
||||
React.createElement(FormItem, { label: '是否有挂' },
|
||||
React.createElement(Input, { value: form.trailerPlate || '无', disabled: true, style: { width: '100%', maxWidth: 320, background: '#f5f5f5' } })
|
||||
),
|
||||
React.createElement(FormItem, { label: '瑕疵', fullWidth: true },
|
||||
React.createElement('div', { style: { display: 'flex', flexWrap: 'wrap', alignItems: 'center', gap: 8 } },
|
||||
(form.flawPhotos || []).map(function (url, i) {
|
||||
return React.createElement('img', {
|
||||
key: i,
|
||||
src: url,
|
||||
alt: '',
|
||||
style: { width: 64, height: 64, objectFit: 'cover', borderRadius: 4, cursor: 'pointer' },
|
||||
onClick: function () { photoPreviewState[1]({ open: true, url: url }); }
|
||||
});
|
||||
}),
|
||||
(form.flawPhotos || []).length === 0 ? React.createElement('span', { style: { color: '#999' } }, '无') : null
|
||||
)
|
||||
),
|
||||
React.createElement(FormItem, { label: '车辆检查', fullWidth: true },
|
||||
React.createElement(Button, { type: 'default', onClick: function () { drawerOpenState[1](true); } }, '备车检查单')
|
||||
)
|
||||
)
|
||||
)
|
||||
),
|
||||
React.createElement('div', { style: styles.footer },
|
||||
React.createElement(Button, { onClick: function () { if (typeof window !== 'undefined' && window.history) window.history.back(); } }, '返回')
|
||||
),
|
||||
React.createElement(Drawer, {
|
||||
title: '备车检查单',
|
||||
placement: 'right',
|
||||
width: 640,
|
||||
open: drawerOpenState[0],
|
||||
onClose: function () { drawerOpenState[1](false); },
|
||||
styles: { body: { display: 'flex', flexDirection: 'column', height: '100%', overflow: 'hidden', paddingBottom: 0 } },
|
||||
footer: React.createElement('div', { style: { display: 'flex', justifyContent: 'flex-end' } },
|
||||
React.createElement(Button, { onClick: function () { drawerOpenState[1](false); } }, '返回')
|
||||
)
|
||||
},
|
||||
React.createElement('div', { style: { flex: 1, minHeight: 0, overflow: 'auto' } },
|
||||
React.createElement(Table, {
|
||||
columns: inspectionColumns,
|
||||
dataSource: form.inspectionList || [],
|
||||
rowKey: function (_, i) { return i; },
|
||||
pagination: false,
|
||||
size: 'small'
|
||||
})
|
||||
)
|
||||
),
|
||||
React.createElement(Modal, {
|
||||
title: '需求说明',
|
||||
open: reqDocOpenState[0],
|
||||
onCancel: function () { reqDocOpenState[1](false); },
|
||||
footer: null,
|
||||
width: 720,
|
||||
styles: { body: { maxHeight: '70vh', overflow: 'auto', whiteSpace: 'pre-wrap', fontSize: 14, lineHeight: 1.8 } }
|
||||
}, requirementDocContent),
|
||||
photoPreviewState[0].open && photoPreviewState[0].url
|
||||
? React.createElement(Modal, {
|
||||
title: '预览',
|
||||
open: true,
|
||||
footer: null,
|
||||
onCancel: function () { photoPreviewState[1]({ open: false, url: null }); }
|
||||
}, React.createElement('img', { src: photoPreviewState[0].url, alt: '', style: { width: '100%' } }))
|
||||
: null
|
||||
);
|
||||
};
|
||||
|
||||
if (typeof window !== 'undefined') {
|
||||
window.Component = Component;
|
||||
if (document.readyState === 'loading') {
|
||||
document.addEventListener('DOMContentLoaded', function () {
|
||||
var rootEl = document.getElementById('root');
|
||||
if (rootEl && window.ReactDOM && window.React) {
|
||||
var root = ReactDOM.createRoot(rootEl);
|
||||
root.render(React.createElement(Component));
|
||||
}
|
||||
});
|
||||
} else {
|
||||
var rootEl = document.getElementById('root');
|
||||
if (rootEl && window.ReactDOM && window.React) {
|
||||
var root = ReactDOM.createRoot(rootEl);
|
||||
root.render(React.createElement(Component));
|
||||
}
|
||||
}
|
||||
}
|
||||
2240
web端/运维管理/车辆业务/调拨管理.jsx
Normal file
2240
web端/运维管理/车辆业务/调拨管理.jsx
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user