Files
ONE-OS/web端/运维管理/备件管理/备件库存.jsx

1219 lines
52 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// 【重要】必须使用 const Component 作为组件变量名
// 数字化资产 ONEOS 运管平台 - 运维管理 - 备件库 - 备件库存(原型)
const Component = function () {
var useState = React.useState;
var useMemo = React.useMemo;
var useCallback = React.useCallback;
var antd = window.antd;
var Breadcrumb = antd.Breadcrumb;
var Card = antd.Card;
var Button = antd.Button;
var Table = antd.Table;
var Select = antd.Select;
var Modal = antd.Modal;
var Drawer = antd.Drawer;
var Form = antd.Form;
var Input = antd.Input;
var InputNumber = antd.InputNumber;
var DatePicker = antd.DatePicker;
var message = antd.message;
var Space = antd.Space;
var Descriptions = antd.Descriptions;
var Upload = antd.Upload;
var Image = antd.Image;
var dayjs = window.dayjs;
function normUploadFileList(e) {
if (Array.isArray(e)) return e;
return e && e.fileList ? e.fileList : [];
}
function filterOption(input, option) {
var label = (option && (option.label || option.children)) || '';
return String(label).toLowerCase().indexOf(String(input || '').toLowerCase()) >= 0;
}
function todayDayjs() {
if (dayjs) return dayjs().startOf('day');
return null;
}
function todayYMD() {
if (dayjs) return dayjs().format('YYYY-MM-DD');
var d = new Date();
return d.getFullYear() + '-' + String(d.getMonth() + 1).padStart(2, '0') + '-' + String(d.getDate()).padStart(2, '0');
}
function csvEscape(s) {
var x = String(s == null ? '' : s);
if (/[",\n\r]/.test(x)) return '"' + x.replace(/"/g, '""') + '"';
return x;
}
function downloadCsv(filename, headers, rows) {
var lines = [headers.map(csvEscape).join(',')].concat(
rows.map(function (r) { return r.map(csvEscape).join(','); })
);
var blob = new Blob(['\uFEFF' + lines.join('\n')], { type: 'text/csv;charset=utf-8;' });
var a = document.createElement('a');
a.href = URL.createObjectURL(blob);
a.download = filename;
a.click();
URL.revokeObjectURL(a.href);
}
var layoutStyle = { padding: '16px 24px', background: '#f5f5f5', minHeight: '100vh' };
var filterLabelStyle = { marginBottom: 6, fontSize: 14, color: 'rgba(0,0,0,0.65)' };
var filterItemStyle = { marginBottom: 12 };
var filterControlStyle = { width: '100%' };
var tableStyle = '.spare-stock-table .ant-table-thead th,.spare-stock-table .ant-table-tbody td{white-space:nowrap;}' +
'.spare-stock-table .col-stock-qty{text-align:left !important;}' +
'.spare-stock-table th.col-stock-qty{text-align:left !important;}';
// 与「仓库管理」一致的仓库名称选项(入库/领用出库)
var warehouseManageNames = useMemo(function () {
return [
'天河备件库', '西湖服务备件库', '上海浦东备件仓', '深圳南山备件仓',
'成都高新备件库', '宁波江北备件库', '北京朝阳备件仓', '重庆两江备件库'
];
}, []);
var vehicleModelSpecMap = {
'飞驰49t': '海格牌KLQ5180XYKFCEV',
'宇通49t': 'KLQ6129',
'现代4.5t': 'BJ5180',
'跃进4.5t': '帅铃Q6',
'苏龙18t': '海格牌KLQ5180XYKFCEV'
};
var allVehicleModelOptions = useMemo(function () {
return [
{ value: '飞驰49t', label: '飞驰49t' },
{ value: '宇通49t', label: '宇通49t' },
{ value: '现代4.5t', label: '现代4.5t' },
{ value: '跃进4.5t', label: '跃进4.5t' },
{ value: '苏龙18t', label: '苏龙18t' }
];
}, []);
var addDrawerVehicleOptions = useMemo(function () {
return allVehicleModelOptions.map(function (opt) {
var spec = vehicleModelSpecMap[opt.value];
return {
value: opt.value,
label: spec ? opt.value + '(型号:' + spec + '' : opt.label
};
});
}, [allVehicleModelOptions]);
function buildInitialStockRows() {
var XJ = '新件库';
var XJCode = 'WH-XJK';
var YS = '易损件库';
var YSCode = 'WH-YSK';
return [
{ id: 'ss-xj-01', warehouseCode: XJCode, warehouseName: XJ, spareCode: 'FC49t-XJ-0001', spareName: '去离子柱(飞驰49t-新件)', vehicleModels: ['飞驰49t'], stockQty: 34, totalInbound: 42, totalOutbound: 8 },
{ id: 'ss-xj-02', warehouseCode: XJCode, warehouseName: XJ, spareCode: 'FC49t-XJ-0002', spareName: '燃料电池空气滤芯(飞驰49t-新件)', vehicleModels: ['飞驰49t'], stockQty: 28, totalInbound: 55, totalOutbound: 27 },
{ id: 'ss-xj-03', warehouseCode: XJCode, warehouseName: XJ, spareCode: 'YT49t-XJ-0001', spareName: '去离子柱(宇通49t-新件)', vehicleModels: ['宇通49t'], stockQty: 20, totalInbound: 28, totalOutbound: 8 },
{ id: 'ss-xj-04', warehouseCode: XJCode, warehouseName: XJ, spareCode: 'YT49t-XJ-0002', spareName: '燃料电池空气滤芯(宇通49t-新件)', vehicleModels: ['宇通49t'], stockQty: 12, totalInbound: 18, totalOutbound: 6 },
{ id: 'ss-xj-05', warehouseCode: XJCode, warehouseName: XJ, spareCode: 'YT49t-XJ-0005', spareName: '燃料电池去离子水(宇通49t-新件)', vehicleModels: ['宇通49t'], stockQty: 5, totalInbound: 5, totalOutbound: 0 },
{ id: 'ss-xj-06', warehouseCode: XJCode, warehouseName: XJ, spareCode: 'YT49t-XJ-0029', spareName: '小循环滤网(宇通49t-新件)', vehicleModels: ['宇通49t'], stockQty: 11, totalInbound: 13, totalOutbound: 2 },
{ id: 'ss-xj-07', warehouseCode: XJCode, warehouseName: XJ, spareCode: 'YT49t-XJ-0030', spareName: '大循环滤网(宇通49t-新件)', vehicleModels: ['宇通49t'], stockQty: 10, totalInbound: 10, totalOutbound: 0 },
{ id: 'ss-xj-08', warehouseCode: XJCode, warehouseName: XJ, spareCode: 'XD4.5t-XJ-0008', spareName: '后尾灯(现代4.5t-新件)', vehicleModels: ['现代4.5t'], stockQty: 18, totalInbound: 40, totalOutbound: 22 },
{ id: 'ss-xj-09', warehouseCode: XJCode, warehouseName: XJ, spareCode: 'YJ4.5t-XJ-0035', spareName: '12V蓄电池(跃进4.5t-新件)', vehicleModels: ['跃进4.5t'], stockQty: 23, totalInbound: 26, totalOutbound: 3 },
{ id: 'ss-xj-10', warehouseCode: XJCode, warehouseName: XJ, spareCode: 'SL18t-XJ-0001', spareName: '去离子柱(苏龙18t-新件)', vehicleModels: ['苏龙18t'], stockQty: 11, totalInbound: 12, totalOutbound: 1 },
{ id: 'ss-xj-11', warehouseCode: XJCode, warehouseName: XJ, spareCode: 'SL18t-XJ-0002', spareName: '燃料电池空气滤芯(苏龙18t-新件)', vehicleModels: ['苏龙18t'], stockQty: 16, totalInbound: 16, totalOutbound: 0 },
{ id: 'ss-ys-01', warehouseCode: YSCode, warehouseName: YS, spareCode: 'TY-YS-0001', spareName: 'H1灯泡-易损件', vehicleModels: [], stockQty: 55, totalInbound: 55, totalOutbound: 0 },
{ id: 'ss-ys-02', warehouseCode: YSCode, warehouseName: YS, spareCode: 'TY-YS-0002', spareName: 'H3灯泡-易损件', vehicleModels: [], stockQty: 50, totalInbound: 50, totalOutbound: 0 },
{ id: 'ss-ys-03', warehouseCode: YSCode, warehouseName: YS, spareCode: 'TY-YS-0003', spareName: 'H7灯泡-易损件', vehicleModels: [], stockQty: 53, totalInbound: 53, totalOutbound: 0 },
{ id: 'ss-ys-04', warehouseCode: YSCode, warehouseName: YS, spareCode: 'TY-YS-0004', spareName: '小灯泡-易损件', vehicleModels: [], stockQty: 52, totalInbound: 52, totalOutbound: 0 },
{ id: 'ss-ys-05', warehouseCode: YSCode, warehouseName: YS, spareCode: 'TY-YS-0005', spareName: '2405灯泡-易损件', vehicleModels: [], stockQty: 110, totalInbound: 110, totalOutbound: 0 }
];
}
function buildSpareCatalogFromRows(rows) {
var map = {};
(rows || []).forEach(function (r) {
if (!r || !r.spareCode || map[r.spareCode]) return;
var isBulb = /灯泡/.test(r.spareName || '');
map[r.spareCode] = {
spareCode: r.spareCode,
spareName: r.spareName,
unit: isBulb ? '个' : '件',
vehicleModels: (r.vehicleModels || []).slice(),
alertThreshold: isBulb ? 20 : 8
};
});
return map;
}
var listState = useState(buildInitialStockRows);
var list = listState[0];
var spareCatalogState = useState(function () {
return buildSpareCatalogFromRows(buildInitialStockRows());
});
var spareCatalog = spareCatalogState[0];
var setSpareCatalog = spareCatalogState[1];
function getCatalogEntry(spareCode) {
return spareCatalog[spareCode] || null;
}
function getUnitForCode(spareCode) {
var c = getCatalogEntry(spareCode);
return (c && c.unit) || '件';
}
var inboundRecordsState = useState(function () {
var ph1 = 'https://via.placeholder.com/160x120.png?text=Inbound+1';
var ph2 = 'https://via.placeholder.com/160x120.png?text=Inbound+2';
return [
{ id: 'in-001', warehouseName: '新件库', spareCode: 'FC49t-XJ-0001', spareName: '去离子柱(飞驰49t-新件)', inboundType: '采购', qty: 4, inboundDate: '2025-02-27', operator: '张三', unitPrice: 128.5, remark: '季度补货', photoUrls: [ph1] },
{ id: 'in-002', warehouseName: '新件库', spareCode: 'YT49t-XJ-0002', spareName: '燃料电池空气滤芯(宇通49t-新件)', inboundType: '采购', qty: 6, inboundDate: '2025-02-26', operator: '李四', unitPrice: 86, remark: '', photoUrls: [ph1, ph2] },
{ id: 'in-003', warehouseName: '易损件库', spareCode: 'TY-YS-0001', spareName: 'H1灯泡-易损件', inboundType: '其他', qty: 20, inboundDate: '2025-02-25', operator: '王五', unitPrice: 3.5, remark: '调拨转入', photoUrls: [] },
{ id: 'in-004', warehouseName: '新件库', spareCode: 'SL18t-XJ-0002', spareName: '燃料电池空气滤芯(苏龙18t-新件)', inboundType: '采购', qty: 8, inboundDate: '2025-02-24', operator: '张三', unitPrice: 92.8, remark: '', photoUrls: [ph2] },
{ id: 'in-005', warehouseName: '新件库', spareCode: 'FC49t-XJ-0001', spareName: '去离子柱(飞驰49t-新件)', inboundType: '其他', qty: 2, inboundDate: '2025-02-20', operator: '赵六', unitPrice: 0, remark: '盘盈', photoUrls: [] }
];
});
var inboundRecords = inboundRecordsState[0];
var outboundRecordsState = useState(function () {
return [
{ id: 'out-001', warehouseName: '新件库', spareCode: 'FC49t-XJ-0002', spareName: '燃料电池空气滤芯(飞驰49t-新件)', outboundType: '维修', qty: 2, outboundDate: '2025-02-27', operator: '周强', remark: '车辆粤A12345' },
{ id: 'out-002', warehouseName: '新件库', spareCode: 'XD4.5t-XJ-0008', spareName: '后尾灯(现代4.5t-新件)', outboundType: '保养', qty: 1, outboundDate: '2025-02-26', operator: '钱敏', remark: '' },
{ id: 'out-003', warehouseName: '易损件库', spareCode: 'TY-YS-0003', spareName: 'H7灯泡-易损件', outboundType: '其他', qty: 5, outboundDate: '2025-02-25', operator: '孙亮', remark: '场站备用' },
{ id: 'out-004', warehouseName: '新件库', spareCode: 'YJ4.5t-XJ-0035', spareName: '12V蓄电池(跃进4.5t-新件)', outboundType: '维修', qty: 1, outboundDate: '2025-02-24', operator: '周强', remark: '' },
{ id: 'out-005', warehouseName: '新件库', spareCode: 'FC49t-XJ-0001', spareName: '去离子柱(飞驰49t-新件)', outboundType: '保养', qty: 1, outboundDate: '2025-02-23', operator: '钱敏', remark: '定期更换' },
{ id: 'out-006', warehouseName: '新件库', spareCode: 'FC49t-XJ-0002', spareName: '燃料电池空气滤芯(飞驰49t-新件)', outboundType: '维修', qty: 1, outboundDate: '2025-02-22', operator: '周强', remark: '粤B88888 进站' },
{ id: 'out-007', warehouseName: '新件库', spareCode: 'YT49t-XJ-0001', spareName: '去离子柱(宇通49t-新件)', outboundType: '维修', qty: 2, outboundDate: '2025-02-21', operator: '吴刚', remark: '' },
{ id: 'out-008', warehouseName: '新件库', spareCode: 'YT49t-XJ-0002', spareName: '燃料电池空气滤芯(宇通49t-新件)', outboundType: '保养', qty: 3, outboundDate: '2025-02-20', operator: '钱敏', remark: '车队批量保养' },
{ id: 'out-009', warehouseName: '新件库', spareCode: 'YT49t-XJ-0029', spareName: '小循环滤网(宇通49t-新件)', outboundType: '维修', qty: 1, outboundDate: '2025-02-19', operator: '郑华', remark: '泄漏检修更换' },
{ id: 'out-010', warehouseName: '新件库', spareCode: 'SL18t-XJ-0001', spareName: '去离子柱(苏龙18t-新件)', outboundType: '其他', qty: 1, outboundDate: '2025-02-18', operator: '孙亮', remark: '调拨至华东服务站' },
{ id: 'out-011', warehouseName: '新件库', spareCode: 'SL18t-XJ-0002', spareName: '燃料电池空气滤芯(苏龙18t-新件)', outboundType: '维修', qty: 2, outboundDate: '2025-02-17', operator: '周强', remark: '' },
{ id: 'out-012', warehouseName: '易损件库', spareCode: 'TY-YS-0001', spareName: 'H1灯泡-易损件', outboundType: '维修', qty: 8, outboundDate: '2025-02-16', operator: '赵磊', remark: '夜间抢修多车' },
{ id: 'out-013', warehouseName: '易损件库', spareCode: 'TY-YS-0001', spareName: 'H1灯泡-易损件', outboundType: '其他', qty: 4, outboundDate: '2025-02-15', operator: '孙亮', remark: '场站灯箱维护' },
{ id: 'out-014', warehouseName: '易损件库', spareCode: 'TY-YS-0002', spareName: 'H3灯泡-易损件', outboundType: '保养', qty: 6, outboundDate: '2025-02-14', operator: '钱敏', remark: '' },
{ id: 'out-015', warehouseName: '易损件库', spareCode: 'TY-YS-0004', spareName: '小灯泡-易损件', outboundType: '其他', qty: 10, outboundDate: '2025-02-13', operator: '吴刚', remark: '库存盘点出库' },
{ id: 'out-016', warehouseName: '易损件库', spareCode: 'TY-YS-0005', spareName: '2405灯泡-易损件', outboundType: '维修', qty: 12, outboundDate: '2025-02-12', operator: '郑华', remark: '批量更换老化灯泡' },
{ id: 'out-017', warehouseName: '新件库', spareCode: 'YT49t-XJ-0030', spareName: '大循环滤网(宇通49t-新件)', outboundType: '保养', qty: 2, outboundDate: '2025-02-11', operator: '钱敏', remark: '粤C22334' },
{ id: 'out-018', warehouseName: '新件库', spareCode: 'YT49t-XJ-0005', spareName: '燃料电池去离子水(宇通49t-新件)', outboundType: '其他', qty: 1, outboundDate: '2025-02-10', operator: '孙亮', remark: '试验用料' },
{ id: 'out-019', warehouseName: '新件库', spareCode: 'FC49t-XJ-0001', spareName: '去离子柱(飞驰49t-新件)', outboundType: '维修', qty: 3, outboundDate: '2025-02-09', operator: '周强', remark: '质保期内更换' },
{ id: 'out-020', warehouseName: '新件库', spareCode: 'XD4.5t-XJ-0008', spareName: '后尾灯(现代4.5t-新件)', outboundType: '维修', qty: 2, outboundDate: '2025-02-08', operator: '赵磊', remark: '追尾事故修复' }
];
});
var outboundRecords = outboundRecordsState[0];
var defaultDraft = {
warehouseName: undefined,
spareCode: undefined,
spareName: undefined,
vehicleModels: []
};
var draftState = useState(Object.assign({}, defaultDraft));
var draft = draftState[0];
var setDraft = draftState[1];
var appliedState = useState(Object.assign({}, defaultDraft));
var applied = appliedState[0];
var setApplied = appliedState[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 requirementModalState = useState(false);
var requirementModalOpen = requirementModalState[0];
var setRequirementModalOpen = requirementModalState[1];
var addDrawerState = useState(false);
var addDrawerOpen = addDrawerState[0];
var setAddDrawerOpen = addDrawerState[1];
var inboundDrawerState = useState(false);
var inboundDrawerOpen = inboundDrawerState[0];
var setInboundDrawerOpen = inboundDrawerState[1];
var outboundDrawerState = useState(false);
var outboundDrawerOpen = outboundDrawerState[0];
var setOutboundDrawerOpen = outboundDrawerState[1];
var detailRowState = useState(null);
var detailRow = detailRowState[0];
var setDetailRow = detailRowState[1];
var inboundHistRowState = useState(null);
var inboundHistRow = inboundHistRowState[0];
var setInboundHistRow = inboundHistRowState[1];
var outboundHistRowState = useState(null);
var outboundHistRow = outboundHistRowState[0];
var setOutboundHistRow = outboundHistRowState[1];
var histInboundPageState = useState(1);
var histInboundPage = histInboundPageState[0];
var setHistInboundPage = histInboundPageState[1];
var histInboundPageSizeState = useState(10);
var histInboundPageSize = histInboundPageSizeState[0];
var setHistInboundPageSize = histInboundPageSizeState[1];
var histOutboundPageState = useState(1);
var histOutboundPage = histOutboundPageState[0];
var setHistOutboundPage = histOutboundPageState[1];
var histOutboundPageSizeState = useState(10);
var histOutboundPageSize = histOutboundPageSizeState[0];
var setHistOutboundPageSize = histOutboundPageSizeState[1];
var addForm = Form.useForm()[0];
var inboundForm = Form.useForm()[0];
var outboundForm = Form.useForm()[0];
var requirementDocContent = [
'一个「数字化资产ONEOS运管平台」中的「备件库存」模块',
'#面包屑:运维管理-备件库-备件库存',
'',
'1.筛选:',
'1.1.仓库名称:选择器,支持输入框内输入模糊搜索,下拉匹配正确项;',
'1.2.备件编码:选择器,支持输入框内输入模糊搜索,下拉匹配正确项;',
'1.3.备件名称:选择器,支持输入框内输入模糊搜索,下拉匹配正确项;',
'1.4.适配车型:选择器,支持多选,显示所有型号;',
'',
'2.列表;右侧为新增备件信息、入库、领用出库、批量导入、导出按钮',
'#列表:',
'2.1.序号1.2.3.以此类推;',
'2.2.仓库编码:显示仓库编码;',
'2.3.仓库名称:显示仓库名称;',
'2.4.备件编码:显示备件编码;',
'2.5.备件名称:显示备件名称;',
'2.6.适配车型:显示适配车型,一个备件可能有多个车型,非必填;',
'2.7.库存数量:显示库存数量;',
'2.8.累积入库数量:显示该备件入库数量总和;',
'2.9.累积出库数量:显示该备件出库数量总和;',
'2.10.操作:备件明细、入库记录、出库记录;',
' 2.10.1.备件明细:点击弹出抽屉,字段为:',
' 2.10.1.1.备件编码:显示备件编码;',
' 2.10.1.2.备件名称:显示备件名称;',
' 2.10.1.3.计算单位:显示备件计算单位;',
' 2.10.1.4.适配车型:显示备件适配车型;',
' 2.10.1.5.告警阈值:显示备件告警阈值;',
' 2.10.2.入库记录点击弹出抽屉显示列表支持导出csv列表字段为',
' 2.10.2.1.备件编码:显示备件编码;',
' 2.10.2.2.备件名称:显示备件名称;',
' 2.10.2.3.入库类型:显示入库类型,分为采购、其他;',
' 2.10.2.4.入库数量显示入库数量单位根据备件明细单位显示格式为xx单位',
' 2.10.2.5.入库日期显示入库日期YYYY-MM-DD',
' 2.10.2.6.入库人员:显示入库人员姓名;',
' 2.10.2.7.单价显示入库单价格式为xx.xx元',
' 2.10.2.8.入库照片:显示入库照片,点击可放大预览;',
' 2.10.2.9.备注:显示备注信息;',
' 2.10.3.出库记录点击弹出抽屉显示列表支持导出csv字段为',
' 2.10.3.1.备件编码:显示备件编码;',
' 2.10.3.2.备件名称:显示备件名称;',
' 2.10.3.3.出库类型:显示出库类型;',
' 2.10.3.4.出库数量显示出库数量单位根据备件明细单位显示格式为xx单位',
' 2.10.3.5.出库日期显示出库日期YYYY-MM-DD',
' 2.10.3.6.出库人员:显示出库人员姓名;',
' 2.10.3.7.备注:显示备注信息;',
'2.11.右下角为分页功能,支持选择单页显示数据条数;',
'',
'3.新增备件信息',
'点击弹出抽屉,字段为:',
'3.1.备件编码:输入框,默认提示为请输入备件编码;',
'3.2.备件名称:输入框,默认提示为请输入备件名称;',
'3.3.计算单位:输入框,默认提示为请输入计量单位;',
'3.4.适配车型:非必填,选择器,支持多选,选项来自型号表,默认提示:请选择车型;',
'3.5.告警阈值:输入框,支持正数整数输入,支持输入框上下按钮调整数量,默认提示为请设置备件告警阈值;',
'',
'4.入库:',
'点击弹出抽屉,字段为:',
'4.1.仓库名称:选择器,选项来自于仓库管理;',
'4.2.备件名称:选择器,选项来自于备件管理;',
'4.3.入库类型:选择器,选项为:采购、其他;',
'4.4.入库数量:输入框,支持正数整数输入;支持点击增加减少变动数量;',
'4.5.入库日期:日期选择器,精确至天,默认为当日;',
'4.6.单价输入框支持2位小数输入后缀为元',
'4.7.入库照片:照片上传按钮,点击上传本地文件,上传后,支持预览和点击右上角删除按钮删除;',
'4.8.备注:文本域,支持自定义输入;',
'',
'5.领用出库:',
'点击弹出抽屉,字段为:',
'5.1.仓库名称:选择器,选项来自于仓库管理;',
'5.2.备件名称:选择器,选项来自于备件管理;',
'5.3.出库类型:选择器,选项为:维修、保养、其他;',
'5.4.出库数量:输入框,支持正数整数输入;支持点击增加减少变动数量;',
'5.5.出库日期:日期选择器,精确至天,默认为当天;',
'5.6.备注:文本域,支持自定义输入;',
'',
'6.批量导入:',
'根据入库字段生成csv模板',
'',
'7.导出根据筛选条件自动导出csv文件'
].join('\n');
var warehouseNameOptions = useMemo(function () {
var set = new Set();
warehouseManageNames.forEach(function (w) { set.add(w); });
(list || []).forEach(function (r) { if (r && r.warehouseName) set.add(r.warehouseName); });
return Array.from(set).map(function (v) { return { value: v, label: v }; });
}, [list, warehouseManageNames]);
var warehouseOptionsForForm = useMemo(function () {
return warehouseManageNames.map(function (w) { return { value: w, label: w }; });
}, [warehouseManageNames]);
var spareCodeOptions = useMemo(function () {
var set = new Set();
(list || []).forEach(function (r) { if (r && r.spareCode) set.add(r.spareCode); });
Object.keys(spareCatalog).forEach(function (k) { set.add(k); });
return Array.from(set).map(function (v) { return { value: v, label: v }; });
}, [list, spareCatalog]);
var spareNameOptions = useMemo(function () {
var set = new Set();
(list || []).forEach(function (r) { if (r && r.spareName) set.add(r.spareName); });
Object.keys(spareCatalog).forEach(function (k) {
var c = spareCatalog[k];
if (c && c.spareName) set.add(c.spareName);
});
return Array.from(set).map(function (v) { return { value: v, label: v }; });
}, [list, spareCatalog]);
var spareSelectByNameOptions = useMemo(function () {
var byCode = {};
Object.keys(spareCatalog).forEach(function (code) {
var c = spareCatalog[code];
if (c) byCode[code] = { value: code, label: c.spareName + '' + code + '' };
});
(list || []).forEach(function (r) {
if (r && r.spareCode && !byCode[r.spareCode]) {
byCode[r.spareCode] = { value: r.spareCode, label: r.spareName + '' + r.spareCode + '' };
}
});
return Object.keys(byCode).map(function (k) { return byCode[k]; });
}, [list, spareCatalog]);
function rowMatchesVehicleModels(row, selected) {
if (!selected || selected.length === 0) return true;
var models = row.vehicleModels || [];
for (var i = 0; i < selected.length; i++) {
if (models.indexOf(selected[i]) >= 0) return true;
}
return false;
}
var filtered = useMemo(function () {
return (list || []).filter(function (r) {
if (applied.warehouseName && r.warehouseName !== applied.warehouseName) return false;
if (applied.spareCode && r.spareCode !== applied.spareCode) return false;
if (applied.spareName && r.spareName !== applied.spareName) return false;
if (!rowMatchesVehicleModels(r, applied.vehicleModels)) return false;
return true;
});
}, [list, applied]);
var paged = useMemo(function () {
var start = (page - 1) * pageSize;
return filtered.slice(start, start + pageSize);
}, [filtered, page, pageSize]);
var serialStart = (page - 1) * pageSize;
var handleQuery = useCallback(function () {
setApplied({
warehouseName: draft.warehouseName,
spareCode: draft.spareCode,
spareName: draft.spareName,
vehicleModels: draft.vehicleModels ? draft.vehicleModels.slice() : []
});
setPage(1);
}, [draft]);
var handleReset = useCallback(function () {
setDraft(Object.assign({}, defaultDraft));
setApplied(Object.assign({}, defaultDraft));
setPage(1);
}, []);
var handleAdd = useCallback(function () {
addForm.resetFields();
setAddDrawerOpen(true);
}, [addForm]);
var handleAddDrawerClose = useCallback(function () {
setAddDrawerOpen(false);
addForm.resetFields();
}, [addForm]);
var handleAddDrawerSubmit = useCallback(function () {
addForm.validateFields().then(function (vals) {
setSpareCatalog(function (prev) {
var next = Object.assign({}, prev);
next[vals.spareCode] = {
spareCode: vals.spareCode,
spareName: vals.spareName,
unit: vals.unit,
vehicleModels: vals.vehicleModels || [],
alertThreshold: vals.alertThreshold
};
return next;
});
message.success('已保存(原型,联调时对接建档接口)');
setAddDrawerOpen(false);
addForm.resetFields();
}).catch(function () {});
}, [addForm, setSpareCatalog]);
var handleOpenInboundForm = useCallback(function () {
inboundForm.resetFields();
inboundForm.setFieldsValue({
inboundDate: todayDayjs() || undefined,
qty: 1,
inboundType: '采购',
unitPrice: undefined,
remark: '',
inboundPhotos: []
});
setInboundDrawerOpen(true);
}, [inboundForm]);
var handleInboundFormClose = useCallback(function () {
var fl = inboundForm.getFieldValue('inboundPhotos') || [];
fl.forEach(function (f) {
var u = f.url || f.thumbUrl;
if (u && String(u).indexOf('blob:') === 0) {
try { URL.revokeObjectURL(u); } catch (e) {}
}
});
setInboundDrawerOpen(false);
inboundForm.resetFields();
}, [inboundForm]);
var handleInboundFormSubmit = useCallback(function () {
inboundForm.validateFields().then(function () {
message.success('入库已提交(原型,联调对接接口)');
setInboundDrawerOpen(false);
inboundForm.resetFields();
}).catch(function () {});
}, [inboundForm]);
var handleOpenOutboundForm = useCallback(function () {
outboundForm.resetFields();
outboundForm.setFieldsValue({
outboundDate: todayDayjs() || undefined,
qty: 1,
outboundType: '维修',
remark: ''
});
setOutboundDrawerOpen(true);
}, [outboundForm]);
var handleOutboundFormClose = useCallback(function () {
setOutboundDrawerOpen(false);
outboundForm.resetFields();
}, [outboundForm]);
var handleOutboundFormSubmit = useCallback(function () {
outboundForm.validateFields().then(function () {
message.success('领用出库已提交(原型,联调对接接口)');
setOutboundDrawerOpen(false);
outboundForm.resetFields();
}).catch(function () {});
}, [outboundForm]);
var handleDownloadImportTemplate = useCallback(function () {
var headers = ['仓库名称', '备件名称', '入库类型', '入库数量', '入库日期', '单价', '入库照片', '备注'];
var sample = [
['天河备件库', '示例备件名称', '采购', '10', todayYMD(), '99.99', '图片文件名或URL可留空', '模板示例行,可删除']
];
downloadCsv('备件入库导入模板.csv', headers, sample);
message.success('已下载 CSV 模板');
}, []);
var handleExportList = useCallback(function () {
var headers = ['序号', '仓库编码', '仓库名称', '备件编码', '备件名称', '适配车型', '库存数量', '累积入库数量', '累积出库数量'];
var rows = filtered.map(function (r, i) {
var vm = (r.vehicleModels || []).length ? r.vehicleModels.join('、') : '-';
return [
String(i + 1),
r.warehouseCode,
r.warehouseName,
r.spareCode,
r.spareName,
vm,
r.stockQty,
r.totalInbound,
r.totalOutbound
];
});
downloadCsv('备件库存导出_' + todayYMD() + '.csv', headers, rows);
message.success('已按当前筛选条件导出 ' + rows.length + ' 条');
}, [filtered]);
var openDetail = useCallback(function (row) {
setDetailRow(row);
}, []);
var openInboundHist = useCallback(function (row) {
setInboundHistRow(row);
setHistInboundPage(1);
}, []);
var openOutboundHist = useCallback(function (row) {
setOutboundHistRow(row);
setHistOutboundPage(1);
}, []);
var filteredInboundHist = useMemo(function () {
if (!inboundHistRow) return [];
return (inboundRecords || []).filter(function (r) {
return r.warehouseName === inboundHistRow.warehouseName && r.spareCode === inboundHistRow.spareCode;
});
}, [inboundRecords, inboundHistRow]);
var filteredOutboundHist = useMemo(function () {
if (!outboundHistRow) return [];
return (outboundRecords || []).filter(function (r) {
return r.warehouseName === outboundHistRow.warehouseName && r.spareCode === outboundHistRow.spareCode;
});
}, [outboundRecords, outboundHistRow]);
var exportInboundHistCsv = useCallback(function () {
if (!inboundHistRow) return;
var unit = getUnitForCode(inboundHistRow.spareCode);
var headers = ['备件编码', '备件名称', '入库类型', '入库数量', '入库日期', '入库人员', '单价', '入库照片', '备注'];
var rows = filteredInboundHist.map(function (r) {
var pics = (r.photoUrls && r.photoUrls.length) ? r.photoUrls.join('') : '无';
return [
r.spareCode,
r.spareName,
r.inboundType,
String(r.qty) + '' + unit + '',
r.inboundDate,
r.operator,
(Number(r.unitPrice).toFixed(2)) + '元',
pics,
r.remark || ''
];
});
downloadCsv('入库记录_' + inboundHistRow.spareCode + '_' + todayYMD() + '.csv', headers, rows);
message.success('已导出 ' + rows.length + ' 条');
}, [filteredInboundHist, inboundHistRow, spareCatalog]);
var exportOutboundHistCsv = useCallback(function () {
if (!outboundHistRow) return;
var unit = getUnitForCode(outboundHistRow.spareCode);
var headers = ['备件编码', '备件名称', '出库类型', '出库数量', '出库日期', '出库人员', '备注'];
var rows = filteredOutboundHist.map(function (r) {
return [
r.spareCode,
r.spareName,
r.outboundType,
String(r.qty) + '' + unit + '',
r.outboundDate,
r.operator,
r.remark || ''
];
});
downloadCsv('出库记录_' + outboundHistRow.spareCode + '_' + todayYMD() + '.csv', headers, rows);
message.success('已导出 ' + rows.length + ' 条');
}, [filteredOutboundHist, outboundHistRow, spareCatalog]);
var columns = useMemo(function () {
return [
{
title: '序号',
key: 'serial',
width: 64,
fixed: 'left',
render: function (_, r, idx) {
return serialStart + idx + 1;
}
},
{ title: '仓库编码', dataIndex: 'warehouseCode', key: 'warehouseCode', width: 112, fixed: 'left' },
{ title: '仓库名称', dataIndex: 'warehouseName', key: 'warehouseName', width: 140, ellipsis: true },
{ title: '备件编码', dataIndex: 'spareCode', key: 'spareCode', width: 130 },
{ title: '备件名称', dataIndex: 'spareName', key: 'spareName', width: 240, ellipsis: true },
{
title: '适配车型',
key: 'vehicleModels',
width: 200,
ellipsis: true,
render: function (_, r) {
var arr = r.vehicleModels || [];
return arr.length ? arr.join('、') : '-';
}
},
{
title: '库存数量',
dataIndex: 'stockQty',
key: 'stockQty',
width: 96,
align: 'left',
className: 'col-stock-qty',
onHeaderCell: function () { return { className: 'col-stock-qty' }; },
render: function (v) {
if (v == null) return '-';
return React.createElement('span', {
style: {
color: 'var(--ant-color-primary, #1677ff)',
fontWeight: 600,
fontSize: 15
}
}, v);
}
},
{
title: '累积入库数量',
dataIndex: 'totalInbound',
key: 'totalInbound',
width: 120,
render: function (v) { return v != null ? v : '-'; }
},
{
title: '累积出库数量',
dataIndex: 'totalOutbound',
key: 'totalOutbound',
width: 120,
render: function (v) { return v != null ? v : '-'; }
},
{
title: '操作',
key: 'actions',
width: 220,
fixed: 'right',
render: function (_, row) {
return React.createElement(Space, { size: 'small', wrap: true },
React.createElement(Button, { type: 'link', size: 'small', style: { padding: 0 }, onClick: function () { openDetail(row); } }, '备件明细'),
React.createElement(Button, { type: 'link', size: 'small', style: { padding: 0 }, onClick: function () { openInboundHist(row); } }, '入库记录'),
React.createElement(Button, { type: 'link', size: 'small', style: { padding: 0 }, onClick: function () { openOutboundHist(row); } }, '出库记录')
);
}
}
];
}, [serialStart, openDetail, openInboundHist, openOutboundHist]);
var histInboundSerial = (histInboundPage - 1) * histInboundPageSize;
var histInboundPaged = useMemo(function () {
var s = (histInboundPage - 1) * histInboundPageSize;
return filteredInboundHist.slice(s, s + histInboundPageSize);
}, [filteredInboundHist, histInboundPage, histInboundPageSize]);
var histOutboundSerial = (histOutboundPage - 1) * histOutboundPageSize;
var histOutboundPaged = useMemo(function () {
var s = (histOutboundPage - 1) * histOutboundPageSize;
return filteredOutboundHist.slice(s, s + histOutboundPageSize);
}, [filteredOutboundHist, histOutboundPage, histOutboundPageSize]);
var inboundHistColumns = useMemo(function () {
function renderInboundPhotos(_, r) {
var urls = r.photoUrls || [];
if (!urls.length) return '-';
if (Image && Image.PreviewGroup) {
return React.createElement(
Image.PreviewGroup,
null,
urls.map(function (u, i) {
return React.createElement(Image, {
key: i,
width: 52,
height: 52,
style: { objectFit: 'cover', borderRadius: 4, marginRight: 4, cursor: 'pointer', verticalAlign: 'middle' },
src: u,
alt: '入库照片'
});
})
);
}
return React.createElement(Space, { size: 4, wrap: true },
urls.map(function (u, i) {
return React.createElement('img', {
key: i,
src: u,
alt: '',
style: { width: 52, height: 52, objectFit: 'cover', borderRadius: 4, cursor: 'pointer' },
onClick: function () { window.open(u, '_blank'); }
});
})
);
}
return [
{ title: '序号', key: 's', width: 60, render: function (_, r, i) { return histInboundSerial + i + 1; } },
{ title: '备件编码', dataIndex: 'spareCode', key: 'spareCode', width: 130 },
{ title: '备件名称', dataIndex: 'spareName', key: 'spareName', ellipsis: true },
{ title: '入库类型', dataIndex: 'inboundType', key: 'inboundType', width: 88 },
{
title: '入库数量',
key: 'qtyDisp',
width: 110,
render: function (_, r) {
var u = getUnitForCode(r.spareCode);
return r.qty + '' + u + '';
}
},
{ title: '入库日期', dataIndex: 'inboundDate', key: 'inboundDate', width: 112 },
{ title: '入库人员', dataIndex: 'operator', key: 'operator', width: 96 },
{
title: '单价',
key: 'price',
width: 100,
render: function (_, r) {
return Number(r.unitPrice).toFixed(2) + '元';
}
},
{ title: '入库照片', key: 'photos', width: 200, render: renderInboundPhotos },
{ title: '备注', dataIndex: 'remark', key: 'remark', ellipsis: true }
];
}, [histInboundSerial, spareCatalog]);
var outboundHistColumns = useMemo(function () {
return [
{ title: '序号', key: 's', width: 60, render: function (_, r, i) { return histOutboundSerial + i + 1; } },
{ title: '备件编码', dataIndex: 'spareCode', key: 'spareCode', width: 130 },
{ title: '备件名称', dataIndex: 'spareName', key: 'spareName', ellipsis: true },
{ title: '出库类型', dataIndex: 'outboundType', key: 'outboundType', width: 88 },
{
title: '出库数量',
key: 'qtyDisp',
width: 110,
render: function (_, r) {
var u = getUnitForCode(r.spareCode);
return r.qty + '' + u + '';
}
},
{ title: '出库日期', dataIndex: 'outboundDate', key: 'outboundDate', width: 112 },
{ title: '出库人员', dataIndex: 'operator', key: 'operator', width: 96 },
{ title: '备注', dataIndex: 'remark', key: 'remark', ellipsis: true }
];
}, [histOutboundSerial, spareCatalog]);
var detailDescItems = useMemo(function () {
if (!detailRow) return [];
var cat = getCatalogEntry(detailRow.spareCode);
var vm = (detailRow.vehicleModels || []).length
? detailRow.vehicleModels.join('、')
: (cat && cat.vehicleModels && cat.vehicleModels.length ? cat.vehicleModels.join('、') : '-');
return [
{ key: 'c', label: '备件编码', children: detailRow.spareCode },
{ key: 'n', label: '备件名称', children: detailRow.spareName },
{ key: 'u', label: '计算单位', children: (cat && cat.unit) || '-' },
{ key: 'v', label: '适配车型', children: vm },
{ key: 'a', label: '告警阈值', children: cat && cat.alertThreshold != null ? String(cat.alertThreshold) : '-' }
];
}, [detailRow, spareCatalog]);
return React.createElement('div', { style: layoutStyle },
React.createElement('div', { style: { display: 'flex', alignItems: 'center', justifyContent: 'space-between', marginBottom: 16, flexWrap: 'wrap', gap: 8 } },
React.createElement(Breadcrumb, { items: [{ title: '运维管理' }, { title: '备件库' }, { title: '备件库存' }] }),
React.createElement(Button, { type: 'link', style: { padding: 0 }, onClick: function () { setRequirementModalOpen(true); } }, '查看需求说明')
),
React.createElement(Modal, {
title: '需求说明',
open: requirementModalOpen,
onCancel: function () { setRequirementModalOpen(false); },
width: 820,
footer: React.createElement(Button, { onClick: function () { setRequirementModalOpen(false); } }, '关闭'),
bodyStyle: { paddingTop: 12, maxHeight: '78vh', overflow: 'auto' }
},
React.createElement(Card, {
size: 'small',
bordered: true,
style: { borderRadius: 8 },
bodyStyle: { padding: '16px 18px' }
},
React.createElement('div', { style: { whiteSpace: 'pre-wrap', fontSize: 13, lineHeight: 1.65, color: 'rgba(0,0,0,0.85)' } }, requirementDocContent)
)
),
React.createElement(Drawer, {
title: '备件明细',
placement: 'right',
width: 440,
open: !!detailRow,
onClose: function () { setDetailRow(null); },
destroyOnClose: true
},
detailRow ? React.createElement(Descriptions, { column: 1, bordered: true, size: 'small' },
detailDescItems.map(function (it) {
return React.createElement(Descriptions.Item, { key: it.key, label: it.label }, it.children);
})
) : null
),
React.createElement(Drawer, {
title: inboundHistRow ? '入库记录 · ' + inboundHistRow.spareName : '入库记录',
placement: 'right',
width: 1120,
open: !!inboundHistRow,
onClose: function () { setInboundHistRow(null); },
destroyOnClose: true,
extra: React.createElement(Button, { type: 'primary', size: 'small', onClick: exportInboundHistCsv, disabled: !filteredInboundHist.length }, '导出 CSV')
},
React.createElement(Table, {
rowKey: 'id',
size: 'small',
columns: inboundHistColumns,
dataSource: histInboundPaged,
scroll: { x: 1180 },
pagination: {
current: histInboundPage,
pageSize: histInboundPageSize,
total: filteredInboundHist.length,
showSizeChanger: true,
showTotal: function (t) { return '共 ' + t + ' 条'; },
onChange: function (pg, ps) { setHistInboundPage(pg); if (ps) setHistInboundPageSize(ps); }
}
})
),
React.createElement(Drawer, {
title: outboundHistRow ? '出库记录 · ' + outboundHistRow.spareName : '出库记录',
placement: 'right',
width: 880,
open: !!outboundHistRow,
onClose: function () { setOutboundHistRow(null); },
destroyOnClose: true,
extra: React.createElement(Button, { type: 'primary', size: 'small', onClick: exportOutboundHistCsv, disabled: !filteredOutboundHist.length }, '导出 CSV')
},
React.createElement(Table, {
rowKey: 'id',
size: 'small',
columns: outboundHistColumns,
dataSource: histOutboundPaged,
scroll: { x: 860 },
pagination: {
current: histOutboundPage,
pageSize: histOutboundPageSize,
total: filteredOutboundHist.length,
showSizeChanger: true,
showTotal: function (t) { return '共 ' + t + ' 条'; },
onChange: function (pg, ps) { setHistOutboundPage(pg); if (ps) setHistOutboundPageSize(ps); }
}
})
),
React.createElement(Drawer, {
title: '新增备件信息',
placement: 'right',
width: 440,
open: addDrawerOpen,
onClose: handleAddDrawerClose,
destroyOnClose: true,
footer: React.createElement('div', { style: { textAlign: 'right' } },
React.createElement(Button, { onClick: handleAddDrawerClose, style: { marginRight: 8 } }, '取消'),
React.createElement(Button, { type: 'primary', onClick: handleAddDrawerSubmit }, '确定')
)
},
React.createElement(Form, { form: addForm, layout: 'vertical', preserve: false },
React.createElement(Form.Item, {
name: 'spareCode',
label: '备件编码',
rules: [{ required: true, message: '请输入备件编码' }]
}, React.createElement(Input, { placeholder: '请输入备件编码', allowClear: true })),
React.createElement(Form.Item, {
name: 'spareName',
label: '备件名称',
rules: [{ required: true, message: '请输入备件名称' }]
}, React.createElement(Input, { placeholder: '请输入备件名称', allowClear: true })),
React.createElement(Form.Item, {
name: 'unit',
label: '计算单位',
rules: [{ required: true, message: '请输入计量单位' }]
}, React.createElement(Input, { placeholder: '请输入计量单位', allowClear: true })),
React.createElement(Form.Item, {
name: 'vehicleModels',
label: '适配车型'
}, React.createElement(Select, {
mode: 'multiple',
placeholder: '请选择车型',
allowClear: true,
options: addDrawerVehicleOptions,
showSearch: true,
filterOption: filterOption,
maxTagCount: 'responsive'
})),
React.createElement(Form.Item, {
name: 'alertThreshold',
label: '告警阈值',
rules: [{ required: true, message: '请设置备件告警阈值' }]
}, React.createElement(InputNumber, {
placeholder: '请设置备件告警阈值',
style: { width: '100%' },
min: 1,
precision: 0,
step: 1
}))
)
),
React.createElement(Drawer, {
title: '入库',
placement: 'right',
width: 480,
open: inboundDrawerOpen,
onClose: handleInboundFormClose,
destroyOnClose: true,
footer: React.createElement('div', { style: { textAlign: 'right' } },
React.createElement(Button, { onClick: handleInboundFormClose, style: { marginRight: 8 } }, '取消'),
React.createElement(Button, { type: 'primary', onClick: handleInboundFormSubmit }, '确定')
)
},
React.createElement(Form, { form: inboundForm, layout: 'vertical', preserve: false },
React.createElement(Form.Item, {
name: 'warehouseName',
label: '仓库名称',
rules: [{ required: true, message: '请选择仓库名称' }]
}, React.createElement(Select, {
placeholder: '请选择仓库',
allowClear: true,
showSearch: true,
options: warehouseOptionsForForm,
filterOption: filterOption
})),
React.createElement(Form.Item, {
name: 'spareCode',
label: '备件名称',
rules: [{ required: true, message: '请选择备件' }]
}, React.createElement(Select, {
placeholder: '请选择备件',
allowClear: true,
showSearch: true,
options: spareSelectByNameOptions,
filterOption: filterOption
})),
React.createElement(Form.Item, {
name: 'inboundType',
label: '入库类型',
rules: [{ required: true, message: '请选择入库类型' }]
}, React.createElement(Select, {
placeholder: '请选择',
options: [{ value: '采购', label: '采购' }, { value: '其他', label: '其他' }]
})),
React.createElement(Form.Item, {
name: 'qty',
label: '入库数量',
rules: [{ required: true, message: '请输入入库数量' }]
}, React.createElement(InputNumber, {
style: { width: '100%' },
min: 1,
precision: 0,
step: 1
})),
React.createElement(Form.Item, {
name: 'inboundDate',
label: '入库日期',
rules: [{ required: true, message: '请选择入库日期' }]
}, React.createElement(DatePicker, { style: { width: '100%' }, format: 'YYYY-MM-DD' })),
React.createElement(Form.Item, { label: '单价' },
React.createElement(Input.Group, { compact: true, style: { display: 'flex', width: '100%' } },
React.createElement(Form.Item, {
name: 'unitPrice',
noStyle: true,
rules: [{ required: true, message: '请输入单价' }]
}, React.createElement(InputNumber, {
style: { width: 'calc(100% - 40px)' },
min: 0,
precision: 2,
step: 0.01,
placeholder: '支持两位小数'
})),
React.createElement(Input, {
style: { width: 40, textAlign: 'center', padding: '0 4px' },
disabled: true,
value: '元'
})
)
),
React.createElement(Form.Item, {
name: 'inboundPhotos',
label: '入库照片',
valuePropName: 'fileList',
getValueFromEvent: normUploadFileList,
extra: React.createElement('span', { style: { fontSize: 12, color: 'rgba(0,0,0,0.45)' } }, '本地选择图片,点击缩略图可放大预览;卡片右上角可删除')
}, React.createElement(Upload, {
listType: 'picture-card',
accept: 'image/*',
beforeUpload: function () { return false; },
maxCount: 9,
multiple: true
}, React.createElement('div', null,
React.createElement('div', { style: { fontSize: 22, lineHeight: 1 } }, '+'),
React.createElement('div', { style: { marginTop: 6, fontSize: 12, color: 'rgba(0,0,0,0.65)' } }, '上传照片')
))),
React.createElement(Form.Item, { name: 'remark', label: '备注' },
React.createElement(Input.TextArea, { rows: 3, placeholder: '请输入备注', allowClear: true }))
)
),
React.createElement(Drawer, {
title: '领用出库',
placement: 'right',
width: 440,
open: outboundDrawerOpen,
onClose: handleOutboundFormClose,
destroyOnClose: true,
footer: React.createElement('div', { style: { textAlign: 'right' } },
React.createElement(Button, { onClick: handleOutboundFormClose, style: { marginRight: 8 } }, '取消'),
React.createElement(Button, { type: 'primary', onClick: handleOutboundFormSubmit }, '确定')
)
},
React.createElement(Form, { form: outboundForm, layout: 'vertical', preserve: false },
React.createElement(Form.Item, {
name: 'warehouseName',
label: '仓库名称',
rules: [{ required: true, message: '请选择仓库名称' }]
}, React.createElement(Select, {
placeholder: '请选择仓库',
allowClear: true,
showSearch: true,
options: warehouseOptionsForForm,
filterOption: filterOption
})),
React.createElement(Form.Item, {
name: 'spareCode',
label: '备件名称',
rules: [{ required: true, message: '请选择备件' }]
}, React.createElement(Select, {
placeholder: '请选择备件',
allowClear: true,
showSearch: true,
options: spareSelectByNameOptions,
filterOption: filterOption
})),
React.createElement(Form.Item, {
name: 'outboundType',
label: '出库类型',
rules: [{ required: true, message: '请选择出库类型' }]
}, React.createElement(Select, {
placeholder: '请选择',
options: [
{ value: '维修', label: '维修' },
{ value: '保养', label: '保养' },
{ value: '其他', label: '其他' }
]
})),
React.createElement(Form.Item, {
name: 'qty',
label: '出库数量',
rules: [{ required: true, message: '请输入出库数量' }]
}, React.createElement(InputNumber, {
style: { width: '100%' },
min: 1,
precision: 0,
step: 1
})),
React.createElement(Form.Item, {
name: 'outboundDate',
label: '出库日期',
rules: [{ required: true, message: '请选择出库日期' }]
}, React.createElement(DatePicker, { style: { width: '100%' }, format: 'YYYY-MM-DD' })),
React.createElement(Form.Item, { name: 'remark', label: '备注' },
React.createElement(Input.TextArea, { rows: 3, placeholder: '请输入备注', allowClear: true }))
)
),
React.createElement(Card, { style: { marginBottom: 16 } },
React.createElement('div', { style: { display: 'grid', gridTemplateColumns: 'repeat(4, 1fr)', gap: '16px 24px', alignItems: 'start' } },
React.createElement('div', { style: filterItemStyle },
React.createElement('div', { style: filterLabelStyle }, '仓库名称'),
React.createElement(Select, {
placeholder: '请输入或选择仓库名称',
style: filterControlStyle,
value: draft.warehouseName,
onChange: function (v) { setDraft(function (p) { return Object.assign({}, p, { warehouseName: v }); }); },
allowClear: true,
showSearch: true,
options: warehouseNameOptions,
filterOption: filterOption
})
),
React.createElement('div', { style: filterItemStyle },
React.createElement('div', { style: filterLabelStyle }, '备件编码'),
React.createElement(Select, {
placeholder: '请输入或选择备件编码',
style: filterControlStyle,
value: draft.spareCode,
onChange: function (v) { setDraft(function (p) { return Object.assign({}, p, { spareCode: v }); }); },
allowClear: true,
showSearch: true,
options: spareCodeOptions,
filterOption: filterOption
})
),
React.createElement('div', { style: filterItemStyle },
React.createElement('div', { style: filterLabelStyle }, '备件名称'),
React.createElement(Select, {
placeholder: '请输入或选择备件名称',
style: filterControlStyle,
value: draft.spareName,
onChange: function (v) { setDraft(function (p) { return Object.assign({}, p, { spareName: v }); }); },
allowClear: true,
showSearch: true,
options: spareNameOptions,
filterOption: filterOption
})
),
React.createElement('div', { style: filterItemStyle },
React.createElement('div', { style: filterLabelStyle }, '适配车型'),
React.createElement(Select, {
mode: 'multiple',
placeholder: '请选择型号(可多选)',
style: filterControlStyle,
value: draft.vehicleModels,
onChange: function (v) { setDraft(function (p) { return Object.assign({}, p, { vehicleModels: v || [] }); }); },
allowClear: true,
showSearch: true,
filterOption: filterOption,
options: allVehicleModelOptions,
maxTagCount: 'responsive'
})
)
),
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, {
title: '列表',
bordered: false,
style: { borderRadius: 8 },
extra: React.createElement(Space, { wrap: true },
React.createElement(Button, { type: 'primary', onClick: handleAdd }, '新增备件信息'),
React.createElement(Button, { onClick: handleOpenInboundForm }, '入库'),
React.createElement(Button, { onClick: handleOpenOutboundForm }, '领用出库'),
React.createElement(Button, { onClick: handleDownloadImportTemplate }, '批量导入'),
React.createElement(Button, { onClick: handleExportList }, '导出')
)
},
React.createElement('style', null, tableStyle),
React.createElement('div', { className: 'spare-stock-table' },
React.createElement(Table, {
rowKey: 'id',
columns: columns,
dataSource: paged,
scroll: { x: 1680 },
size: 'small',
pagination: {
current: page,
pageSize: pageSize,
total: filtered.length,
showSizeChanger: true,
showQuickJumper: true,
pageSizeOptions: ['10', '20', '50', '100'],
showTotal: function (t) { return '共 ' + t + ' 条'; },
onChange: function (pg, ps) { setPage(pg); if (ps) setPageSize(ps); }
}
})
)
)
);
};