// 导入 h 函数 const { createApp, ref, reactive, onMounted, onUnmounted,nextTick, watch, h, computed } = Vue; const { ElMessage, ElMessageBox, ElTableV2, ElCheckbox,ElLoading } = ElementPlus; // 获取 URL 参数中的 BJDID function getUrlParameter(name) { const urlParams = new URLSearchParams(window.location.search); return urlParams.get(name) || ''; } function getControlValue(controlId) { const exact = document.getElementById(controlId); if (exact && typeof exact.value !== 'undefined') { return exact.value || ''; } const bySuffix = document.querySelector(`[id$="${controlId}"]`); if (bySuffix && typeof bySuffix.value !== 'undefined') { return bySuffix.value || ''; } return ''; } // 获取 BJDID,优先从 URL 参数,其次从输入框 function getBJDID() { // 优先从 URL 参数获取 const urlBJDID = getUrlParameter('BJDID'); if (urlBJDID) { return urlBJDID; } // 如果 URL 中没有,则从输入框获取 return getControlValue('txtBJDID'); } const BJDID = getBJDID(); function logMappingDebug(stage, payload) { try { console.log(`[BJCPJXDR][MappingDebug][${stage}]`, payload); } catch (e) {} } function getDefaultPasteFieldOrder() { const defaultOrder = ['包号', '报价产品', '技术规范书ID', '计量单位', '数量']; const validFields = new Set(['包号', '报价产品', '技术规范书ID', '计量单位', '数量', '不导入']); let rawValue = getControlValue('txtBJU059').trim(); if (!rawValue) return defaultOrder; const parsed = rawValue .replace(/,/g, ',') .split(',') .map(item => item.trim()) .filter(item => item !== ''); if (parsed.length === 0) return defaultOrder; const normalized = parsed.map(item => (validFields.has(item) ? item : '不导入')); while (normalized.length < defaultOrder.length) normalized.push('不导入'); const finalOrder = normalized.slice(0, defaultOrder.length); logMappingDebug('getDefaultPasteFieldOrder', { protocol: window.location.protocol, rawValue, parsed, finalOrder }); return finalOrder; } function applyDefaultColumnMapping(columnFieldMapping, detectedColumnCount) { logMappingDebug('applyDefaultColumnMapping.before', { detectedColumnCount, mapping: JSON.parse(JSON.stringify(columnFieldMapping)) }); Object.keys(columnFieldMapping).forEach(key => delete columnFieldMapping[key]); const fields = getDefaultPasteFieldOrder(); for (let i = 0; i < Math.min(detectedColumnCount, fields.length); i++) { columnFieldMapping[i + 1] = fields[i] === '不导入' ? '' : fields[i]; } logMappingDebug('applyDefaultColumnMapping.after', { fields, mapping: JSON.parse(JSON.stringify(columnFieldMapping)) }); } function forceApplyDefaultColumnMapping(columnFieldMapping, detectedColumnCount) { logMappingDebug('forceApplyDefaultColumnMapping.start', { detectedColumnCount, mapping: JSON.parse(JSON.stringify(columnFieldMapping)) }); const applyOnce = () => { const fields = getDefaultPasteFieldOrder(); const maxCount = Math.min(detectedColumnCount, fields.length); for (let i = 1; i <= maxCount; i++) { const fieldName = fields[i - 1] === '不导入' ? '' : fields[i - 1]; columnFieldMapping[i] = fieldName; columnFieldMapping[i.toString()] = fieldName; } logMappingDebug('forceApplyDefaultColumnMapping.applyOnce', { fields, maxCount, mapping: JSON.parse(JSON.stringify(columnFieldMapping)) }); }; applyOnce(); setTimeout(applyOnce, 0); setTimeout(applyOnce, 60); } const app = createApp({ setup() { //进度条 const showCenterProgress = ref(false); const centerProgressPercentage = ref(0); const centerProgressStatus = ref(''); const centerProgressText = ref(''); let progressTimer = null; // 手动粘贴对话框相关变量 const manualPasteDialogVisible = ref(false); const manualPasteText = ref(''); // 列映射相关变量 const pasteStep = ref('input'); const detectedColumnCount = ref(0); const detectedPreviewRows = ref([]); const columnFieldMapping = reactive({}); const pasteFieldOptions = [ { value: '', label: '不导入' }, { value: '包号', label: '包号' }, { value: '报价产品', label: '报价产品' }, { value: '技术规范书ID', label: '技术规范书ID' }, { value: '计量单位', label: '计量单位' }, { value: '数量', label: '数量' } ]; const batchUpdateUseSelect = computed(() => batchUpdateType.value === 'standard' || batchUpdateType.value === 'voltage' ); const visibleColumns = computed(() => { const count = detectedColumnCount.value || 0; return Array.from({ length: count }, (_, i) => i + 1); }); let clipboardText = ''; // 状态变量 const loading = ref(false); const FGF = ref(''); const ruleDialogVisible = ref(false); const EXRuleDialogVisible = ref(false); const syntaxDialogVisible = ref(false); const filterDialogVisible = ref(false); const YFGZDialogVisible = ref(false); const iframeUrl = ref(''); const BJCPJXDR_XHYF = ref('BJCPJXDR_XHYF.html'); const tableData = ref([]); const tableRef = ref(null); const selectedProduct = ref(''); const currentRowModel = ref(''); // 当前行型号 // 批量调整相关变量 const batchUpdateDialogVisible = ref(false); const batchUpdateType = ref(''); const batchUpdateValue = ref(''); const batchUpdateOptions = ref([]); const batchUpdateFilterQuery = ref(''); const batchUpdateFilteredOptions = computed(() => { const options = batchUpdateOptions.value || []; const query = (batchUpdateFilterQuery.value || '').trim().toLowerCase(); if (!query) return options; const normalizedQuery = query.replace(/\s+/g, ''); return options.filter(option => { const label = (option.label || '').toString().toLowerCase(); const value = (option.value || '').toString().toLowerCase(); const normalizedLabel = label.replace(/\s+/g, ''); const normalizedValue = value.replace(/\s+/g, ''); return label.includes(query) || value.includes(query) || normalizedLabel.includes(normalizedQuery) || normalizedValue.includes(normalizedQuery); }); }); const filterBatchUpdateOptions = (query) => { batchUpdateFilterQuery.value = query || ''; }; const resolveBatchUpdateSelectValue = () => { const raw = batchUpdateValue.value; if (raw == null || raw === '') return ''; const text = String(raw).trim(); const options = batchUpdateOptions.value || []; const byValue = options.find(item => String(item.value) === text); if (byValue) return String(byValue.value); const byLabel = options.find(item => String(item.label).trim() === text); if (byLabel) return String(byLabel.value); return ''; }; const hasSelectedRows = ref(false); const selectedRowsCount = ref(0); const batchUpdateTitle = ref(''); const currentRowVoltage = ref(''); // 当前行电压 const currentRowStandard = ref(''); // 当前行标准 const currentRowSpec = ref(''); // 当前行规格 const currentRowXLJXGZXH = ref(''); const ruleEditor = ref(null); const selection = ref({ start: 0, end: 0, text: '' }); const resultReceived = ref(false); // 规则配置相关变量 const ruleString = ref('| 电力电缆,AC220kV,YJLW,1600,1,03,ZC,Z'); // 查询条件变量 const productQuery = ref(''); // 报价产品(模糊查询) const modelQuery = ref(''); // 线缆型号(模糊查询) const specQuery = ref(''); // 线缆规格(模糊查询) const standardQuery = ref(''); // 线缆标准(精确查询) const voltageQuery = ref(''); // 电压等级(精确查询) const missingElementQuery = ref([]); // 缺失要素(多选) const missingElementOptions = [ { value: 'XLXH', label: '线缆型号' }, { value: 'XLGG', label: '线缆规格' }, { value: 'XLBZ', label: '线缆标准' }, { value: 'DYDJ', label: '电压等级' } ]; const buildListQueryParams = () => ({ XLJXDJ: 'XSBJ', XLJXDH: BJDID, sXLJXGZXH: filterRule.value || '0', sDCZT: filterStatus.value || ' ', sBJCP: productQuery.value, sXLXH: modelQuery.value, sXLGG: specQuery.value, sXLBZ: standardQuery.value, sDYDJID: voltageQuery.value, sQSYS: (missingElementQuery.value && missingElementQuery.value.length > 0) ? missingElementQuery.value.join(',') : '' }); // 下拉选项变量 const standardOptions = ref([]); // 线缆标准下拉选项 const voltageOptions = ref([]); // 电压等级下拉选项 const standardNameMap = ref({}); // 标准编码->名称映射 // 线缆型号标记相关变量 const modelTags = ref([]); const modelNextChar = ref(97); // 'a'的ASCII码 const modelTagOrder = { '前缀码': 1, '型号码': 2, '后缀码': 3, '型号': 4 }; const modelActualValue = ref(''); // 线缆规格标记相关变量 const specTags = ref([]); const specNextChar = ref(97); // 'a'的ASCII码 const specTagOrder = { '芯数': 1, '截面': 2, '线组数': 3, '线对数': 4, '规格':5 }; const specActualValue = ref(''); const voltageTags = ref([]); const voltageNextChar = ref(97); // 'a'的ASCII码 const voltageTagOrder = { '相电压': 1, '线电压': 2, '电压单位': 3, '电压等级': 4 }; const voltageActualValue = ref(''); const standardTags = ref([]); const standardNextChar = ref(97); // 'a'的ASCII码 const standardTagOrder = { '标准名': 1 }; const standardActualValue = ref(''); // 配置项的值 const modelValue = ref(''); const specValue = ref(''); const voltageValue = ref(''); const standardValue = ref(''); const colorValue = ref(''); // 筛选条件变量 const filterRule = ref('0'); const ExRule = ref('0'); const filterStatus = ref(''); const filterEquivalent=ref(false); const isLoading = ref(false); // 解析规则选项 const ruleOptions = ref([ { value: '0', label: '未解析' } ]); // 通用解析规则选项 const commonRuleOptions = ref([ { value: '0', label: '请选择通用规则' } ]); // 删除规则函数 const deleteRule = async (ruleId) => { try { const result = await ElMessageBox.confirm( '确定要删除此解析规则吗?此操作不可恢复。', '确认删除', { confirmButtonText: '确定', cancelButtonText: '取消', type: 'warning' } ); if (result) { // 设置服务路径 GThinking.Web.AjaxServiceProxy.servicePath = 'S_XLXSBJ/102373012.ashx'; // 调用删除服务 const deleteResult = await new Promise((resolve, reject) => { GThinking.Web.AjaxServiceProxy.invoke( 'DeleteXLJXGZ', false, { '-RefUmId': 102855005, 'XLJXDH': BJDID, 'sXLJXGZXH': ruleId }, (data) => resolve(data), (error) => reject(error), "DeleteXLJXGZ", 50000 ); }); if (deleteResult && deleteResult.success) { ElMessage.success('解析规则删除成功'); // 重新加载规则列表 await loadRuleOptions(); // 如果删除的是当前选中的规则,重置为默认值 if (filterRule.value === ruleId) { filterRule.value = '0'; } } else { ElMessage.error(`删除失败: ${deleteResult?.message || '未知错误'}`); } } } catch (error) { if (error !== 'cancel') { console.error('删除规则失败:', error); ElMessage.error(`删除规则失败: ${error.message || '服务异常'}`); } } }; // 删除通用规则函数 const deleteCommonRule = async (ruleId) => { try { const result = await ElMessageBox.confirm( '确定要删除此通用解析规则吗?此操作不可恢复。', '确认删除', { confirmButtonText: '确定', cancelButtonText: '取消', type: 'warning' } ); if (result) { // 设置服务路径 GThinking.Web.AjaxServiceProxy.servicePath = 'S_XLXSBJ/102373012.ashx'; // 调用删除通用规则服务 const deleteResult = await new Promise((resolve, reject) => { GThinking.Web.AjaxServiceProxy.invoke( 'DeleteXLJXGZ', false, { '-RefUmId': 102855005, 'XLJXDH':' ', 'sXLJXGZXH': ruleId }, (data) => resolve(data), (error) => reject(error), "DeleteXLJXGZ", 50000 ); }); if (deleteResult && deleteResult.success) { ElMessage.success('通用解析规则删除成功'); // 重新加载通用规则列表 await loadCommonRuleOptions(); } else { ElMessage.error(`删除失败: ${deleteResult?.message || '未知错误'}`); } } } catch (error) { if (error !== 'cancel') { console.error('删除通用规则失败:', error); ElMessage.error(`删除通用规则失败: ${error.message || '服务异常'}`); } } }; const statusOptions = ref([ { value: 'N', label: '未导入' }, { value: 'Y', label: '已导入' } ]); //todo // 正确声明对象路径 const cable_model_syntax = ref("/GTHINKING/Components/N_XLBJDX/cable_model_syntax.html"); // ==== Excel导入相关变量 ==== const importDialogVisible = ref(false); const fileInput = ref(null); const excelFile = ref(null); const excelColumns = ref([]); const previewData = ref([]); const columnMapping = reactive({ '序号': null, '包号': null, '报价产品': null, '技术规范书ID': null, '计量单位': null, // 新增 '数量': null, '型号': null, '电压等级': null, '标准': null, '规格': null, '等效': null, }); const tableColumns = ref(['包号','报价产品', '技术规范书ID','计量单位', '数量', '型号', '电压等级', '标准', '规格', '等效']); const importing = ref(false); const importProgress = ref(0); const totalRows = ref(0); const importedCount = ref(0); const importStatus = ref(null); const errorMessage = ref(''); const successMessage = ref(''); const canImport = ref(false); // ==== el-table-v2 相关变量 ==== const TABLE_CELL_BORDER_STYLE = { borderRight: '1px solid #dcdfe6', borderBottom: '1px solid #dcdfe6', boxSizing: 'border-box' }; const withTableCellBorder = (column) => ({ ...column, style: { ...TABLE_CELL_BORDER_STYLE, ...(column.style || {}) } }); // 表头拖拽排序 / 列宽拖拽:固定列不可排序,配置持久化到 localStorage const PINNED_COLUMN_KEYS = new Set(['selection', 'index']); const COLUMN_ORDER_STORAGE_KEY = 'BJCPJXDR_tableColumnOrder_v1'; const COLUMN_WIDTH_STORAGE_KEY = 'BJCPJXDR_tableColumnWidths_v1'; const MIN_COLUMN_WIDTH = 48; const columnDragSourceKey = ref(null); const columnDragOverKey = ref(null); let resizingColumnKey = null; let resizeStartX = 0; let resizeStartWidth = 0; let resizeRafId = 0; let pendingResizeWidth = 0; let resizeGuideEl = null; let resizeColumnIndex = -1; const refreshTableColumns = () => { tableColumnsV2.value = tableColumnsV2.value.map(col => ({ ...col })); }; const loadSavedColumnWidths = () => { try { const raw = localStorage.getItem(COLUMN_WIDTH_STORAGE_KEY); if (!raw) return null; const parsed = JSON.parse(raw); return parsed && typeof parsed === 'object' ? parsed : null; } catch (e) { return null; } }; const applySavedWidthsToColumns = (columns, widths) => { if (!widths) return columns; return columns.map(col => { if (col.hidden) return col; const saved = widths[col.key]; if (typeof saved === 'number' && saved >= MIN_COLUMN_WIDTH) { return { ...col, width: Math.round(saved) }; } return col; }); }; const saveColumnWidths = () => { const widths = {}; tableColumnsV2.value.forEach(col => { if (!col.hidden) widths[col.key] = col.width; }); try { localStorage.setItem(COLUMN_WIDTH_STORAGE_KEY, JSON.stringify(widths)); } catch (e) {} }; const setColumnWidth = (key, width) => { const w = Math.max(MIN_COLUMN_WIDTH, Math.round(width)); const idx = tableColumnsV2.value.findIndex(col => col.key === key); if (idx < 0) return; const col = tableColumnsV2.value[idx]; if (col.width === w) return; tableColumnsV2.value[idx] = { ...col, width: w }; tableColumnsV2.value = [...tableColumnsV2.value]; }; const ensureResizeGuide = () => { if (!resizeGuideEl) { resizeGuideEl = document.createElement('div'); resizeGuideEl.className = 'bjcpjxdr-col-resize-guide'; document.body.appendChild(resizeGuideEl); } return resizeGuideEl; }; const getHeaderGuideHost = () => document.querySelector('.table-container .el-table-v2__header-wrapper') || document.querySelector('.el-table-v2__header-wrapper') || document.querySelector('.el-table-v2__header'); const getHeaderCellByResizeIndex = () => { if (resizeColumnIndex < 0) return null; const host = getHeaderGuideHost(); if (!host) return null; const cells = host.querySelectorAll('.el-table-v2__header-cell'); return cells[resizeColumnIndex] || null; }; const updateResizeGuide = () => { const guide = ensureResizeGuide(); const headerHost = getHeaderGuideHost(); if (headerHost) { const hRect = headerHost.getBoundingClientRect(); guide.style.top = `${hRect.top}px`; guide.style.height = `${hRect.height}px`; } const headerCell = getHeaderCellByResizeIndex(); if (headerCell) { const cellRect = headerCell.getBoundingClientRect(); guide.style.left = `${cellRect.right - 1}px`; } guide.style.display = 'block'; }; const hideResizeGuide = () => { if (resizeGuideEl) resizeGuideEl.style.display = 'none'; }; const applyColumnResizeByPointer = (clientX) => { if (!resizingColumnKey) return; pendingResizeWidth = Math.max( MIN_COLUMN_WIDTH, Math.round(resizeStartWidth + (clientX - resizeStartX)) ); if (resizeRafId) return; resizeRafId = requestAnimationFrame(() => { resizeRafId = 0; setColumnWidth(resizingColumnKey, pendingResizeWidth); updateResizeGuide(); }); }; const onColumnResizeMove = (e) => { if (!resizingColumnKey) return; applyColumnResizeByPointer(e.clientX); }; const stopColumnResize = () => { if (!resizingColumnKey) return; const key = resizingColumnKey; if (resizeRafId) { cancelAnimationFrame(resizeRafId); resizeRafId = 0; } setColumnWidth(key, pendingResizeWidth); resizingColumnKey = null; resizeColumnIndex = -1; document.removeEventListener('mousemove', onColumnResizeMove); document.removeEventListener('mouseup', stopColumnResize); document.body.classList.remove('bjcpjxdr-col-resizing'); hideResizeGuide(); saveColumnWidths(); }; const startColumnResize = (columnKey, e) => { e.preventDefault(); e.stopPropagation(); const headerCell = e.target.closest('.el-table-v2__header-cell'); const domWidth = headerCell ? headerCell.getBoundingClientRect().width : 0; const col = tableColumnsV2.value.find(c => c.key === columnKey); const visibleCols = tableColumnsV2.value.filter(c => !c.hidden); resizeColumnIndex = visibleCols.findIndex(c => c.key === columnKey); resizingColumnKey = columnKey; resizeStartX = e.clientX; resizeStartWidth = domWidth > 0 ? domWidth : (col ? col.width : MIN_COLUMN_WIDTH); pendingResizeWidth = resizeStartWidth; document.body.classList.add('bjcpjxdr-col-resizing'); updateResizeGuide(); document.addEventListener('mousemove', onColumnResizeMove); document.addEventListener('mouseup', stopColumnResize); }; const createColumnResizeHandle = (columnKey) => h('span', { class: 'bjcpjxdr-col-resize-handle', title: '拖动调整列宽', onMousedown: (e) => startColumnResize(columnKey, e) }); const loadSavedTableColumnOrder = () => { try { const raw = localStorage.getItem(COLUMN_ORDER_STORAGE_KEY); if (!raw) return null; const parsed = JSON.parse(raw); return Array.isArray(parsed) ? parsed : null; } catch (e) { return null; } }; const applySavedOrderToColumns = (columns, savedKeys) => { if (!savedKeys || !savedKeys.length) return columns; const pinnedStart = columns.filter(c => PINNED_COLUMN_KEYS.has(c.key)); const hidden = columns.filter(c => c.hidden); const draggable = columns.filter(c => !PINNED_COLUMN_KEYS.has(c.key) && !c.hidden); const map = new Map(draggable.map(c => [c.key, c])); const ordered = []; savedKeys.forEach(k => { if (map.has(k)) { ordered.push(map.get(k)); map.delete(k); } }); map.forEach(c => ordered.push(c)); return [...pinnedStart, ...ordered, ...hidden]; }; const reorderTableColumns = (fromKey, toKey) => { if (!fromKey || !toKey || fromKey === toKey) return; if (PINNED_COLUMN_KEYS.has(fromKey) || PINNED_COLUMN_KEYS.has(toKey)) return; const cols = tableColumnsV2.value; const draggable = cols.filter(c => !PINNED_COLUMN_KEYS.has(c.key) && !c.hidden); const keys = draggable.map(c => c.key); const fromIdx = keys.indexOf(fromKey); const toIdx = keys.indexOf(toKey); if (fromIdx < 0 || toIdx < 0) return; keys.splice(fromIdx, 1); keys.splice(toIdx, 0, fromKey); const pinnedStart = cols.filter(c => PINNED_COLUMN_KEYS.has(c.key)); const hidden = cols.filter(c => c.hidden); const map = new Map(draggable.map(c => [c.key, c])); const reordered = keys.map(k => map.get(k)).filter(Boolean); tableColumnsV2.value = [...pinnedStart, ...reordered, ...hidden]; try { localStorage.setItem(COLUMN_ORDER_STORAGE_KEY, JSON.stringify(keys)); } catch (e) {} }; const withDraggableHeader = (column) => { if (column.hidden) return column; if (column.key === 'selection') { return { ...column, headerCellRenderer: () => h('div', { class: 'bjcpjxdr-header-cell bjcpjxdr-header-pinned' }, [ h('input', { type: 'checkbox', onChange: (e) => { if (e.target.checked) { tableData.value.forEach(row => { row.selected = true; }); } else { tableData.value.forEach(row => { row.selected = false; }); } updateSelectedRows(); }, checked: hasSelectedRows.value && selectedRowsCount.value === tableData.value.length }), createColumnResizeHandle(column.key) ]) }; } if (PINNED_COLUMN_KEYS.has(column.key)) { return { ...column, headerCellRenderer: () => h('div', { class: 'bjcpjxdr-header-cell bjcpjxdr-header-pinned' }, [ h('span', column.title), createColumnResizeHandle(column.key) ]) }; } return { ...column, headerCellRenderer: () => { const key = column.key; const isDragging = columnDragSourceKey.value === key; const isOver = columnDragOverKey.value === key; return h('div', { class: [ 'bjcpjxdr-header-cell', 'bjcpjxdr-header-draggable', isDragging ? 'is-dragging' : '', isOver ? 'is-drag-over' : '' ], draggable: true, title: '按住拖动可调整列顺序', onDragstart: (e) => { columnDragSourceKey.value = key; e.dataTransfer.effectAllowed = 'move'; try { e.dataTransfer.setData('text/plain', key); } catch (err) {} }, onDragover: (e) => { e.preventDefault(); if (columnDragSourceKey.value && columnDragSourceKey.value !== key && columnDragOverKey.value !== key) { columnDragOverKey.value = key; refreshTableColumns(); } }, onDragleave: () => { if (columnDragOverKey.value === key) { columnDragOverKey.value = null; refreshTableColumns(); } }, onDrop: (e) => { e.preventDefault(); const fromKey = columnDragSourceKey.value || (e.dataTransfer && e.dataTransfer.getData('text/plain')); reorderTableColumns(fromKey, key); columnDragSourceKey.value = null; columnDragOverKey.value = null; refreshTableColumns(); }, onDragend: () => { columnDragSourceKey.value = null; columnDragOverKey.value = null; refreshTableColumns(); } }, [ h('span', { class: 'bjcpjxdr-header-grip', 'aria-hidden': 'true' }, '⋮⋮'), h('span', { class: 'bjcpjxdr-header-title' }, column.title), createColumnResizeHandle(column.key) ]); } }; }; const createBaseTableColumns = () => ([ { key: 'selection', dataKey: 'selection', title: '选择', width: 60, align: 'center', cellRenderer: ({ rowData }) => { return h('input', { type: 'checkbox', checked: rowData.selected || false, onChange: (e) => { rowData.selected = e.target.checked; updateSelectedRows(); } }); } }, { key: 'index', dataKey: 'index', title: '序号', width: 50, align: 'center' }, { key: 'packageNumber', dataKey: 'packageNumber', title: '包号', width: 80, align: 'left' }, { key: 'product', dataKey: 'product', title: '报价产品', width: 300, align: 'left' }, { key: 'techSpecId', dataKey: 'techSpecId', title: '技术规范ID', width: 100, align: 'left' }, { key: 'unit', dataKey: 'unit', title: '计量单位', width: 80, align: 'left' }, { key: 'quantity', dataKey: 'quantity', title: '数量', width: 80, align: 'left' }, { key: 'model', dataKey: 'model', title: '型号', width: 150, align: 'left' }, { key: 'voltage', dataKey: 'voltage', title: '电压等级', width: 100, align: 'left' }, { key: 'standard', dataKey: 'standard', title: '标准', width: 80, align: 'left', cellRenderer: ({ rowData }) => { const name = standardNameMap.value[rowData.standard]; return name || rowData.standard || ''; } }, { key: 'spec', dataKey: 'spec', title: '规格', width: 120, align: 'left' }, { key: 'dx', dataKey: 'dx', title: '等效', width: 200, align: 'left' }, { key: 'XLJXGZXH', dataKey: 'XLJXGZXH', title: 'XLJXGZXH', width: 0, align: 'left', hidden: true } ]); const buildTableColumnsV2 = () => { const savedOrder = loadSavedTableColumnOrder(); const ordered = applySavedOrderToColumns(createBaseTableColumns(), savedOrder); const withWidths = applySavedWidthsToColumns(ordered, loadSavedColumnWidths()); return withWidths.map(withDraggableHeader).map(withTableCellBorder); }; const tableColumnsV2 = ref(buildTableColumnsV2()); const getRowKey = row => { // 方案1:直接使用唯一字段 return row.id } const tableWidth = ref(window.innerWidth - 30); const tableHeight = ref(window.innerHeight - 50); // 启动进度条显示 const startCenterProgress = (text) => { showCenterProgress.value = true; centerProgressPercentage.value = 0; centerProgressStatus.value = ''; centerProgressText.value = text || '处理中...'; // 模拟进度增长 progressTimer = setInterval(() => { if (centerProgressPercentage.value < 75) { centerProgressPercentage.value += 5; } }, 300); }; // 完成进度条显示 const completeCenterProgress = (success = true, message = '') => { if (progressTimer) clearInterval(progressTimer); // 设置完成状态 centerProgressPercentage.value = 100; centerProgressStatus.value = success ? 'success' : 'exception'; centerProgressText.value = message || (success ? '完成!' : '失败!'); // 2秒后自动关闭 setTimeout(() => { showCenterProgress.value = false; }, 2000); }; // 显示手动粘贴对话框 const showManualPasteDialog = () => { manualPasteText.value = ''; manualPasteDialogVisible.value = true; }; // 处理手动粘贴确认(第一步:粘贴数据) const handleManualPasteConfirm = () => { logMappingDebug('handleManualPasteConfirm.click', { protocol: window.location.protocol, textLength: manualPasteText.value ? manualPasteText.value.length : 0 }); if (!manualPasteText.value.trim()) { ElMessage.warning('请输入要粘贴的数据'); return; } const text = manualPasteText.value.trim(); const rows = text.split('\n').filter(row => row.trim() !== ''); if (rows.length === 0) { ElMessage.warning('粘贴的数据为空'); return; } const firstRow = rows[0].split('\t'); detectedColumnCount.value = firstRow.length; logMappingDebug('handleManualPasteConfirm.detected', { rows: rows.length, detectedColumnCount: detectedColumnCount.value, firstRow }); detectedPreviewRows.value = rows.slice(0, 5).map((row, idx) => { const cols = row.split('\t'); const rowData = { rowIndex: idx + 1 }; for (let i = 0; i < cols.length; i++) { rowData['col' + i] = cols[i]; } return rowData; }); // 点击“下一步”时强制覆盖列映射(HTTP场景) applyDefaultColumnMapping(columnFieldMapping, detectedColumnCount.value); pasteStep.value = 'mapping'; nextTick(() => forceApplyDefaultColumnMapping(columnFieldMapping, detectedColumnCount.value)); logMappingDebug('handleManualPasteConfirm.toMapping', { pasteStep: pasteStep.value, mapping: JSON.parse(JSON.stringify(columnFieldMapping)) }); }; // 处理映射确认(第二步:确认映射并导入) const handleMappingConfirm = () => { const hasProduct = Object.values(columnFieldMapping).includes('报价产品'); if (!hasProduct) { ElMessage.warning('请设置"报价产品"列的对应位置(必填)'); return; } const fieldMapping = {}; Object.entries(columnFieldMapping).forEach(([col, field]) => { if (field) { fieldMapping[field] = col; } }); manualPasteDialogVisible.value = false; pasteStep.value = 'input'; const text = manualPasteText.value; manualPasteText.value = ''; processPastedTextWithMapping(fieldMapping, text); }; // 返回上一步 const handleMappingBack = () => { pasteStep.value = 'input'; }; // 处理手动粘贴取消 const handleManualPasteCancel = () => { manualPasteDialogVisible.value = false; manualPasteText.value = ''; pasteStep.value = 'input'; }; // 提取粘贴文本处理逻辑为独立函数 const processPastedText = async (text) => { startCenterProgress('正在处理数据...'); // 解析剪贴板数据为表格 const rows = text.split('\n'); const itemsToInsert = []; const parsedData = []; // 为所有记录生成相同的XLJXDH const commonXLJXDH = BJDID; for (let i = 0; i < rows.length; i++) { const row = rows[i].split('\t'); if (row.length > 0 && row[0].trim() !== '') { const sequenceNumber = (i + 1).toString(); const packageNumber = row[0].trim(); const product= row.length > 1 ? row[1].trim() : ''; // 第二列为计量单位 const techSpecId= row.length > 2 ? row[2].trim() : ''; // 第三列为数量 const unit= row.length > 3 ? row[3].trim() : ''; // 第四列为包号 const quantity = row.length > 4 ? row[4].trim() : ''; // 第五列为技术规范ID // 创建XLJXMX对象 itemsToInsert.push({ XLJXDJ: "XSBJ", XLJXDH: commonXLJXDH, XLJXMXH: sequenceNumber, XLBSC: product, XLJXGZXH: "0", JXXLXHID: "", XLXHID: "", JXXLGGID: "", XLGGID: "", JXDYDJID: "", DYDJID: "", XLBZID: "", JXXLBZID: "", XLYSID: "", JXXLYSID: "", WHR: "", WHRID: "", WHSJ: "", DCZT: "N", JLDW: unit, // 计量单位 SL: quantity, // 数量 FBH: packageNumber, // 包号 JSGFID: techSpecId // 技术规范ID }); parsedData.push({ index: sequenceNumber, product: product, unit: unit, quantity: quantity, packageNumber: packageNumber, // 包号 techSpecId: techSpecId, // 技术规范ID model: '', voltage: '', standard: '', spec: '', status: 'N', checked: false }); } } // 批量插入数据 if (itemsToInsert.length > 0) { loading.value = true; const result = await bulkInsertXLJXMX(itemsToInsert); if (result && result.success) { await loadTableData(); ElMessage.success(`已粘贴并插入 ${parsedData.length} 条数据`); await commonParse(); } else { completeCenterProgress(false, '粘贴失败'); ElMessage.error(`插入失败: ${result?.msg || result?.message || '未知错误'}`); } loading.value = false; } completeCenterProgress(true, '数据处理完成!'); }; // 使用动态列映射处理粘贴文本 const processPastedTextWithMapping = async (fieldMapping, text) => { startCenterProgress('正在处理数据...'); const rows = text.split('\n'); const itemsToInsert = []; const parsedData = []; const commonXLJXDH = BJDID; const getMappedValue = (row, fieldName) => { const colIndex = fieldMapping[fieldName]; if (colIndex) { const idx = parseInt(colIndex) - 1; return row.length > idx ? row[idx].trim() : ''; } return ''; }; for (let i = 0; i < rows.length; i++) { const row = rows[i].split('\t'); if (row.length > 0 && row[0].trim() !== '') { const sequenceNumber = (i + 1).toString(); const packageNumber = getMappedValue(row, '包号'); const product = getMappedValue(row, '报价产品'); const techSpecId = getMappedValue(row, '技术规范书ID'); const unit = getMappedValue(row, '计量单位'); const quantity = getMappedValue(row, '数量'); itemsToInsert.push({ XLJXDJ: "XSBJ", XLJXDH: commonXLJXDH, XLJXMXH: sequenceNumber, XLBSC: product, XLJXGZXH: "0", JXXLXHID: "", XLXHID: "", JXXLGGID: "", XLGGID: "", JXDYDJID: "", DYDJID: "", XLBZID: "", JXXLBZID: "", XLYSID: "", JXXLYSID: "", WHR: "", WHRID: "", WHSJ: "", DCZT: "N", JLDW: unit, SL: quantity, FBH: packageNumber, JSGFID: techSpecId }); parsedData.push({ index: sequenceNumber, product: product, unit: unit, quantity: quantity, packageNumber: packageNumber, techSpecId: techSpecId, model: '', voltage: '', standard: '', spec: '', status: 'N', checked: false }); } } if (itemsToInsert.length > 0) { loading.value = true; const result = await bulkInsertXLJXMX(itemsToInsert); if (result && result.success) { await loadTableData(); ElMessage.success(`已粘贴并插入 ${parsedData.length} 条数据`); await commonParse(); } else { completeCenterProgress(false, '粘贴失败'); ElMessage.error(`插入失败: ${result?.msg || result?.message || '未知错误'}`); } loading.value = false; } completeCenterProgress(true, '数据处理完成!'); }; // ==== 通用函数 ==== // 检查字符是否为字母数字 const isAlphanumeric = (char) => { const code = char.charCodeAt(0); return (code >= 48 && code <= 57) || // 0-9 (code >= 65 && code <= 90) || // A-Z (code >= 97 && code <= 122); // a-z }; const isnumeric = (char) => { const code = char.charCodeAt(0); return (code >= 48 && code <= 57) ; // 0-9 }; const isnumericDot = (char) => { const code = char.charCodeAt(0); return (code >= 48 && code <= 57)||char==='.' ; // 0-9 }; const isAlpha= (char) => { const code = char.charCodeAt(0); return (code >= 65 && code <= 90) || // A-Z (code >= 97 && code <= 122); // a-z }; function validateString(input) { // 如果输入为空或不是字符串,直接返回 false if (typeof input !== 'string' || input.length === 0) { return false; } // 正则表达式:匹配中文字符(\u4e00-\u9fa5)或字母数字 const regex = /^[\u4e00-\u9fa5a-zA-Z0-9]+$/; // 遍历字符串中的每个字符 for (let i = 0; i < input.length; i++) { const char = input[i]; // 如果字符不符合要求,返回 false if (!regex.test(char)) { return false; } } // 所有字符都符合要求 return true; } // 通用标记添加函数 const addTag = (tagName,RuleStr,context) => { // 解构上下文对象 const { tags, nextChar, tagOrder, value } = context; const sBSC=GetBSC(RuleStr); let sCPH='',sCXH=''; // 获取当前字符 if (tagName === 'XLXH') { sCPH=ProdCPH_XLXH(sBSC); sCXH=ProdCXH_XLXH(sBSC); } else if (tagName === 'DYDJ') { sCPH=ProdCPH_DYDJ(sBSC); sCXH=ProdCXH_DYDJ(sBSC); } else if (tagName === 'XLBZ') { sCPH=ProdCPH_XLBZ(sBSC); sCXH=ProdCXH_XLBZ(sBSC); } else if (tagName === 'XLGG') { sCPH=ProdCPH_XLGG(sBSC); sCXH=ProdCXH_XLGG(sBSC); } // 生成标记字符串 value.value =GetMRYFC(tagName,sCPH,sCXH); }; // 创建上下文对象 const modelContext = { tags: modelTags, nextChar: modelNextChar, tagOrder: modelTagOrder, value: modelValue }; const specContext = { tags: specTags, nextChar: specNextChar, tagOrder: specTagOrder, value: specValue }; const voltageContext = { tags: voltageTags, nextChar: voltageNextChar, tagOrder: voltageTagOrder, value: voltageValue }; const standardContext = { tags: standardTags, nextChar: standardNextChar, tagOrder: standardTagOrder, value: standardValue }; // 原函数改为调用通用函数 const addModelTag = RuleStr => addTag('XLXH',RuleStr,modelContext); const addSpecTag = RuleStr => addTag('XLGG',RuleStr, specContext); const addvoltageTag = RuleStr => addTag('DYDJ',RuleStr, voltageContext); const addstandardTag = RuleStr => addTag('XLBZ',RuleStr, standardContext); function GetMRYFC(sYFLX, sCPH, sCXH) { debugger sYFLX = (sYFLX || '').trim(); sCPH = (sCPH || '').trim(); sCXH = (sCXH || '').trim(); let sYFC = '', tmp; // 型号拆分处理(XLXH) if (sYFLX === 'XLXH') { const processCode = (char, typeName) => { let s = sCXH, res = ''; while (s.includes(char)) { const pos = s.indexOf(char); res += `[${s.substr(pos, 2).replace(new RegExp(char, 'g'), typeName)}]`; s = s.substring(pos + 2); } return res; }; if(FGF.value==='空') return processCode('B', '前缀码') + processCode('A', '型号码') + processCode('C', '后缀码'); else { if(processCode('A', '型号码')!=''&&processCode('B', '前缀码')!='') return processCode('B', '前缀码') +FGF.value+ processCode('A', '型号码') + processCode('C', '后缀码'); else return processCode('B', '前缀码') + processCode('A', '型号码') + processCode('C', '后缀码'); } } // 规格处理(XLGG) else if (sYFLX === 'XLGG') { const getCode = (char, typeName) => { const pos = sCXH.indexOf(char); return pos >= 0 ? `[${sCXH.substr(pos, 2).replace(char, typeName)}]` : ''; }; const getNextCode = (startChar, str, typeName) => { const pos = str.indexOf(startChar); return pos >= 0 ? `[${str.substr(pos, 2).replace(startChar, typeName)}]` : ''; }; switch (sCPH) { case 'A1': if (sCXH.includes('A')) sYFC = '[截面a]'; break; case 'A2': if (sCXH.includes('A')) sYFC = '[截面a]/[截面b]'; break; case 'A1B1': if (sCXH.includes('A') && sCXH.includes('B')) { sYFC = `${getCode('B', '芯数')}*${getCode('A', '截面')}`; } break; case 'A1B2': const a1Pos = sCXH.indexOf('A'); if (a1Pos >= 0) { tmp = sCXH.substring(a1Pos + 2); if (sCXH.includes('B') && tmp.includes('A')) { sYFC = `${getCode('B', '芯数')}*${getCode('A', '截面')}` + `+${getCode('B', '芯数')}*${getNextCode('A', tmp, '截面')}`; } } break; case 'A2B2': const aPos = sCXH.indexOf('A'); const bPos = sCXH.indexOf('B'); if (aPos >= 0 && bPos >= 0) { const bStr = sCXH.substring(bPos + 2); tmp = sCXH.substring(aPos + 2); if (bStr.includes('B') && tmp.includes('A')) { sYFC = `${getCode('B', '芯数')}*${getCode('A', '截面')}` + `+${getNextCode('B', bStr, '芯数')}*${getNextCode('A', tmp, '截面')}`; } } break; case 'A1B1C1': if (['A','B','C'].every(c => sCXH.includes(c))) { sYFC = `${getCode('C', '线对数')}*${getCode('B', '芯数')}*${getCode('A', '截面')}`; } break; case 'A1B1D1': if (['A','B','D'].every(c => sCXH.includes(c))) { sYFC = `${getCode('D', '线组数')}*${getCode('B', '芯数')}*${getCode('A', '截面')}`; } break; } // 默认处理规则 if (!sYFC && sCXH) { let result = sCXH .replace(/A/g, '][截面') .replace(/B/g, '][芯数') .replace(/C/g, '][线对数') .replace(/D/g, '][线组数'); sYFC =result.substring(1) + ']'; } return sYFC; } // 电压等级(DYDJ)处理 else if (sYFLX === 'DYDJ') { const g = (c, n) => sCXH.includes(c) ? `[${sCXH.substr(sCXH.indexOf(c), 2).replace(c, n)}]` : ''; switch (sCPH) { case 'A1': sYFC = g('A', '相电压'); break; case 'B1': sYFC = g('B', '线电压'); break; case 'A1B1': if (sCXH.includes('A') && sCXH.includes('B')) { sYFC = `${g('A', '相电压')}/${g('B', '线电压')}`; } break; case 'B1C1': if (sCXH.includes('B') && sCXH.includes('C')) { sYFC = `${g('B', '线电压')}${g('C', '电压单位')}`; } break; case 'A1B1C1': if (sCXH.includes('A') && sCXH.includes('B') && sCXH.includes('C')) { sYFC = `${g('A', '相电压')}/${g('B', '线电压')}${g('C', '电压单位')}`; } break; } if (!sYFC && sCXH) { let result = sCXH .replace(/A/g, '][相电压') .replace(/B/g, '][线电压') .replace(/C/g, '][电压单位') sYFC =result.substring(1) + ']'; } return sYFC; } // 标准(XLBZ)处理 else if (sYFLX === 'XLBZ') { if (sCPH === 'A1' && sCXH.includes('A')) { sYFC = '[标准名a]'; } if (!sYFC && sCXH) { sYFC = `[${sCXH.replace(/A/g, '标准名').replace(/A/g, '][标准名').substring(2)}]`; } return sYFC; } // 颜色(XLYS)处理 else if (sYFLX === 'XLYS') { if (sCPH === 'A1' && sCXH.includes('A')) { sYFC = '[颜色名a]'; } else if (sCPH === 'A2' && sCXH.includes('A')) { sYFC = '[颜色名a][颜色名b]'; } if (!sYFC && sCXH) { sYFC = `[${sCXH.replace(/A/g, '][颜色名').substring(2)}]`; } return sYFC; } return ''; } function GetBSC(inputText) { // 实现 GetOptionIdList 的功能:提取文本中所有 [XX=YY] 中的 XX const getOptionIdList = (str) => { const matches = []; // 存储提取结果的数组 // 使用正则表达式匹配 [XX=YY] 模式,并提取 XX const regex = /\[([^\]=]+)=[^\]]+\]/g; let match; // 循环获取所有匹配项 while ((match = regex.exec(str)) !== null) { matches.push(match[1]); // 将捕获组1(XX)添加到结果数组 } return matches; }; const str = inputText; const BLZList = getOptionIdList(str); let sBSC = ''; // 拼接成 [XX][YY] 格式的字符串 for (let i = 0; i < BLZList.length; i++) { sBSC += '[' + BLZList[i] + ']'; } return sBSC; } function ProdCPH_XLXH(aJXGZC) { const SBLZsXLXH = ['型号码', '前缀码', '后缀码']; return prodCPH(aJXGZC, SBLZsXLXH); } function ProdCXH_XLXH(aJXGZC) { const SBLZsXLXH = ['型号码', '前缀码', '后缀码']; return ProdCXH(aJXGZC, SBLZsXLXH); } function ProdCPH_XLGG(aJXGZC) { const SBLZsXLXH = ['截面', '芯数', '线对数', '线组数']; return prodCPH(aJXGZC, SBLZsXLXH); } function ProdCXH_XLGG(aJXGZC) { const SBLZsXLXH = ['截面', '芯数', '线对数', '线组数']; return ProdCXH(aJXGZC, SBLZsXLXH); } function ProdCPH_DYDJ(aJXGZC) { const SBLZsXLXH = ['相电压', '线电压', '电压单位']; return prodCPH(aJXGZC, SBLZsXLXH); } function ProdCXH_DYDJ(aJXGZC) { const SBLZsXLXH = ['相电压', '线电压', '电压单位']; return ProdCXH(aJXGZC, SBLZsXLXH); } function ProdCPH_XLBZ(aJXGZC) { const SBLZsXLXH = ['标准名']; return prodCPH(aJXGZC, SBLZsXLXH); } function ProdCXH_XLBZ(aJXGZC) { const SBLZsXLXH = ['标准名']; return ProdCXH(aJXGZC, SBLZsXLXH); } function prodCPH(aJXGZC, aBJCTag) { // 初始化计数数组 const tokenCount = new Array(64).fill(0); const BJCTagLen = []; // 存储每个标签的长度 for (let i = 0; i < aBJCTag.length; i++) { BJCTagLen[i] = aBJCTag[i].length; } let index = 0; const inputLength = aJXGZC.length; let result = ''; while (index < inputLength) { // 查找下一个左括号 '[' while (index < inputLength && aJXGZC[index] !== '[') { index++; } if (index >= inputLength) break; index++; // 跳过 '[' const startIndex = index; // 查找下一个右括号 ']' while (index < inputLength && aJXGZC[index] !== ']') { index++; } if (index >= inputLength) break; const tagContent = aJXGZC.substring(startIndex, index); const tagLen = tagContent.length; let found = false; // 处理单字符标签 (A-Z) if (tagLen === 1) { const charCode = tagContent.charCodeAt(0); if (charCode >= 65 && charCode <= 90) { // A-Z const idx = charCode - 65; if (idx < aBJCTag.length) { tokenCount[idx]++; found = true; } } } // 处理多字符标签 else { for (let i = 0; i < aBJCTag.length; i++) { const tag = aBJCTag[i]; // 检查标签长度匹配 if (tagLen === BJCTagLen[i]) { // 不区分大小写的比较 if (tagContent.toLowerCase() === tag.toLowerCase()) { tokenCount[i]++; found = true; break; } } } } index++; // 跳过 ']' } // 构造结果字符串 for (let i = 0; i < aBJCTag.length; i++) { if (tokenCount[i] > 0) { result += String.fromCharCode(65 + i) + tokenCount[i].toString(); } } return result; } function ProdCXH(aJXGZC, aBJCTag) { // 获取选项ID列表 (如 ['型号码', '前缀码', ...]) const getOptionIdList = (str) => { const matches = []; const regex = /\[([^\]]+)\]/g; let match; while ((match = regex.exec(str)) !== null) { matches.push(match[1]); } return matches; }; let result = ''; const BLZList = getOptionIdList(aJXGZC); let BLZOrder = 97; // 'a'的ASCII码 // 遍历每个保留字标识符 for (let i = 0; i < BLZList.length; i++) { const curBLZ = BLZList[i]; let found = false; // 检查当前保留字是否在指定标签列表中 for (let j = 0; j < aBJCTag.length; j++) { if (aBJCTag[j] === curBLZ) { // 生成编码:字母(A,B,C...) + 顺序号(a,b,c...) const letter = String.fromCharCode(65 + j); const orderChar = String.fromCharCode(BLZOrder); result += letter + orderChar; BLZOrder++; // 顺序号递增 found = true; break; } } } return result; } const openSyntaxPage = () => { // 构建URL参数 const title = "线缆型号语法"; const ruleString1 = encodeURIComponent(ruleString.value); const reservedWords = "型号码,前缀码,后缀码"; const connectors = ",-,/,(,)"; const syntaxString = encodeURIComponent(modelValue.value); // 生成唯一ID用于标识这个窗口 const windowId = Date.now().toString(); // 打开新窗口 const url = `cable_model_syntax.html?title=${title}&ruleString=${ruleString1}&reservedWords=${reservedWords}&connectors=${connectors}&syntaxString=${syntaxString}&windowId=${windowId}`; const syntaxWindow = window.open(url, '_blank', 'width=950,height=750,location=no'); window.syntaxWindows = window.syntaxWindows || {}; window.syntaxWindows[windowId] = syntaxWindow; // 设置轮询检查窗口状态 const checkWindowClosed = setInterval(() => { if (!window.syntaxWindows[windowId] || window.syntaxWindows[windowId].closed) { clearInterval(checkWindowClosed); handleSyntaxWindowClosed(windowId); } }, 500); }; const closePage = () => { let topDocument; try { topDocument = top.document; } catch (e) { topDocument = document; // 跨域时回退到当前文档 } try { // 获取元素引用 const divZDY = topDocument.getElementById("div_ZDY"); const divZDY_100860140 = topDocument.getElementById("divZDY_100860140"); // 确保主容器存在 if (!divZDY) return; // 清除divZDY_102849000(如果存在) if (divZDY_100860140) { divZDY.removeChild(divZDY_100860140); } while (divZDY.firstChild) { divZDY.removeChild(divZDY.firstChild); } // 隐藏主容器 divZDY.style.display = "none"; } catch (error) { console.error("隐藏自定义元素时出错:", error); } // 刷新报价单 const frameElement = topDocument.getElementById('XLBJDInfo_frame'); if (!frameElement) { console.log('未找到 XLBJDInfo_frame'); } else { const iframeDoc = frameElement.contentWindow.document; if (!iframeDoc) { console.log('跨域访问被阻止'); } else { const reloadButton = iframeDoc.getElementById('ctl00_CPHButton_btnReLoad'); if (reloadButton) { reloadButton.click(); } else { console.log('未找到 btnReLoad 控件'); } } } }; // 处理窗口关闭 const handleSyntaxWindowClosed = (windowId) => { // 从localStorage获取返回值 const resultKey = `syntaxResult_${windowId}`; const result = localStorage.getItem(resultKey); if (result) { try { const parsedResult = JSON.parse(result); processSyntaxResult(parsedResult); } catch (e) { console.error('解析返回值失败:', e); ElMessage.error('解析语法规则返回值失败'); } finally { // 清理存储 localStorage.removeItem(resultKey); delete window.syntaxWindows[windowId]; } } else { ElMessage.warning('语法规则窗口已关闭,但未返回任何值'); } }; // 处理返回值 const processSyntaxResult = (result) => { if (result && result.modelValue) { // 更新实际值 if (result.modelValue) { modelValue.value = result.modelValue; modelActualValue.value = result.modelActualValue; } ElMessage.success('语法规则已更新'); } else { ElMessage.warning('未返回有效的语法规则'); } }; // 重置线缆型号标记 const resetTags = () => { modelTags.value = []; modelNextChar.value = 97; modelValue.value = ''; modelActualValue.value = ''; specTags.value = []; specNextChar.value = 97; specValue.value = ''; specActualValue.value = ''; voltageTags.value = []; voltageNextChar.value = 97; voltageValue.value = ''; voltageActualValue.value = ''; standardTags.value = []; standardNextChar.value = 97; standardValue.value = ''; standardActualValue.value = ''; specValue.value = ''; voltageValue.value = ''; standardValue.value = ''; colorValue.value = ''; }; const parseRuleValue = async () => { if (!ruleString.value) { modelActualValue.value = ''; specActualValue.value = ''; voltageActualValue.value = ''; standardActualValue.value = ''; return; } try { // 设置服务路径 GThinking.Web.AjaxServiceProxy.servicePath = 'S_XLXSBJ/102373012.ashx'; // 创建 XLJXGZ 对象 const ruleConfig = { XLJXDJ: "XSBJ", XLJXDH: BJDID, // 使用固定的解析规则代号 XLJXGZXH: "0", // 默认序号 XLJXGZC: ruleString.value, XLXHYFC: modelValue.value, XLGGYFC: specValue.value, DYDJYFC: voltageValue.value, XLBZYFC: standardValue.value, XLYSYFC: colorValue.value || "", WHR: "", WHRID: "", WHSJ: new Date().toISOString() }; // 调用 XLYSTZJX 服务 const result = await new Promise((resolve, reject) => { GThinking.Web.AjaxServiceProxy.invoke( 'XLYSTZJX', false, { '-RefUmId': 102855005, // 替换为实际RefUmId 'item': ruleConfig, 'sXLBSC': ruleString.value.replace(/\[([^\]]+)=([^\]]+)\]/g, '$2') // 添加规则串参数 }, (data) => resolve(data), (error) => reject(error), "XLYSTZJX", 50000 // 5秒超时 ); }); // 更新实际值 if (result) { modelActualValue.value = result.XLXH || ''; specActualValue.value = result.XLGG || ''; voltageActualValue.value = result.DYDJ || ''; standardActualValue.value = result.XLBZ || ''; } else { ElMessage.warning('解析服务返回空结果'); } } catch (error) { console.error('规则解析失败:', error); ElMessage.error(`规则解析失败: ${error.message || '服务异常'}`); // 设置默认值 modelActualValue.value = ''; specActualValue.value = ''; voltageActualValue.value = ''; standardActualValue.value = ''; } }; // 原始函数改为调用通用函数 const parseModelValue = parseRuleValue; const parseSpecValue = parseRuleValue; const parsevoltageValue = parseRuleValue; const parsestandardValue = parseRuleValue; // 通用标记函数 const createMarker = (tagName, validatorFunc, errorMessage) => { return () => { if (!ruleEditor.value) return; const textarea = ruleEditor.value; const text = ruleString.value; let start = textarea.selectionStart; let end = textarea.selectionEnd; // 检查选中区域是否在已有标记内部 function isInsideMark(startPos, endPos) { let inMark = false; let lastOpen = -1; for (let i = 0; i <= endPos; i++) { if (i === text.length) break; if (text[i] === '[') { lastOpen = i; inMark = true; } else if (text[i] === ']' && lastOpen !== -1) { inMark = false; } // 检查当前位置是否在标记范围内 if (i >= startPos && i < endPos && inMark) { return true; } } // 检查结束位置是否在未闭合的标记内 return inMark && (lastOpen <= startPos); } // 自动扩展选择范围的通用逻辑 if (end - start <= 0) { // 向左扩展 let left = start; while (left > 0 && validatorFunc(text.charAt(left - 1))) left--; // 向右扩展 let right = start; while (right < text.length && validatorFunc(text.charAt(right))) right++; if (left < right) { textarea.setSelectionRange(left, right); start = left; end = right; } else { ElMessage.warning('请先选中要标记的文本'); return; } } const selectedText = text.substring(start, end); if (!selectedText) { ElMessage.warning('请先选中要标记的文本'); return; } // 精确判断是否在已有标记内部 if (isInsideMark(start, end)) { ElMessage.error('选中区域位于已有标记内部,无法再次标记!'); return; } // 统一使用传入的验证函数 for (let i = 0; i < selectedText.length; i++) { if (!validatorFunc(selectedText[i])) { ElMessage.error(errorMessage); return; } } const markedText = `[${tagName}=${selectedText}]`; ruleString.value = text.substring(0, start) + markedText + text.substring(end); // 统一处理标记分组 const groups = { // 型号分组 型号: { tags: ['前缀码', '型号码', '后缀码', '型号'], add: addModelTag, parse: parseModelValue }, // 规格分组 规格: { tags: ['芯数', '截面', '线组数', '线对数', '规格'], add: addSpecTag, parse: parseSpecValue }, // 电压分组 电压: { tags: ['相电压', '线电压', '电压单位', '电压等级'], add: addvoltageTag, parse: parsevoltageValue }, // 标准分组 标准: { tags: ['标准名'], add: addstandardTag, parse: parsestandardValue } }; // 找到对应的分组并执行 Object.values(groups).forEach(group => { if (group.tags.includes(tagName)) { group.add(ruleString.value); group.parse(); } }); // 重置选择和设置光标位置 selection.value = { start: 0, end: 0, text: '' }; nextTick(() => { const newStart = start + markedText.length; ruleEditor.value.setSelectionRange(newStart, newStart); ruleEditor.value.focus(); }); }; }; // ==== 创建具体标记函数 ==== // 型号相关标记函数 const markPrefixCode = createMarker( '前缀码', isAlphanumeric, '前缀码只能包含字母和数字' ); const markModelCode = createMarker( '型号码', isAlphanumeric, '型号码只能包含字母和数字' ); const markSuffixCode = createMarker( '后缀码', isAlphanumeric, '后缀码只能包含字母和数字' ); // 标准名标记函数 const markStandardName = createMarker( '标准名', validateString, // 使用统一的验证函数 '标准名包含无效字符' // 统一错误消息 ); // 电压相关标记函数 const markVoltagePhase = createMarker( '相电压', isnumericDot, '相电压应为数字' ); const markVoltageLine = createMarker( '线电压', isnumericDot, '线电压应为数字' ); const markVoltageUnit = createMarker( '电压单位', isAlpha, '电压单位只能为字母' ); const markVoltageLevel = createMarker( '电压等级', isnumeric, '电压等级应为数字' ); // 规格相关标记函数 const markWireCount = createMarker( '芯数', isnumeric, '芯数必须为数字' ); const markSection = createMarker( '截面', isnumericDot, '截面必须为数字' ); const markWireGroup = createMarker( '线组数', isnumeric, '线组数必须为数字' ); const markWirePair = createMarker( '线对数', isnumeric, '线对数必须为数字' ); const markSpec = createMarker( '规格', isnumeric, '规格必须为数字' ); // 批量插入函数 const bulkInsertXLJXMX = async (items) => { try { // 设置服务路径 GThinking.Web.AjaxServiceProxy.servicePath = 'S_XLXSBJ/102373012.ashx'; // 分批处理(每批500条) const batchSize = 100000; const totalBatches = Math.ceil(items.length / batchSize); let successCount = 0; let errorMessages = []; for (let i = 0; i < totalBatches; i++) { const start = i * batchSize; const end = Math.min(start + batchSize, items.length); const batch = items.slice(start, end); try { const result = await new Promise((resolve, reject) => { GThinking.Web.AjaxServiceProxy.invoke( 'InsertXLJXMXList', false, { '-RefUmId': 102851007, 'items': batch }, (data) => resolve(data), (error) => reject(error), "InsertXLJXMXList", 300000 // 30秒超时 ); }); if (result && result.success) { successCount += batch.length; } else { errorMessages.push(`批次${i+1}插入失败: ${result?.message || '未知错误'}`); } } catch (error) { errorMessages.push(`批次${i+1}插入失败: ${error.message || '服务异常'}`); } // 更新进度(仅针对导入Excel) if (importing.value) { importProgress.value = Math.round(((i + 1) / totalBatches) * 100); } } // 返回合并结果 if (errorMessages.length === 0) { return { success: true, message: `成功插入${successCount}条数据` }; } else { return { success: false, message: `成功插入${successCount}条,失败${items.length - successCount}条。错误详情:${errorMessages.slice(0, 5).join('')}${errorMessages.length > 5 ? `...等${errorMessages.length}条错误` : ''}` }; } } catch (error) { console.error('批量插入失败:', error); return { success: false, message: `批量插入失败: ${error.message || '服务异常'}` }; } }; // ==== Excel导入相关函数 ==== const showImportDialog = () => { importDialogVisible.value = true; resetImport(); }; const closeImportDialog = () => { importDialogVisible.value = false; resetImport(); }; const resetImport = () => { excelFile.value = null; excelColumns.value = []; previewData.value = []; importProgress.value = 0; importedCount.value = 0; totalRows.value = 0; importStatus.value = null; errorMessage.value = ''; successMessage.value = ''; importing.value = false; canImport.value = false; // 重置映射关系 tableColumns.value.forEach(col => { columnMapping[col] = null; }); }; const triggerFileInput = () => { if (fileInput.value) { fileInput.value.click(); } }; const handleFileChange = (e) => { const file = e.target.files ? e.target.files[0] : null; if (!file) return; // 检查文件类型 if (!/\.(xlsx|xls)$/i.test(file.name)) { errorMessage.value = '请选择Excel文件(.xlsx或.xls格式)'; return; } // 检查文件大小 (最大100MB) if (file.size > 100 * 1024 * 1024) { errorMessage.value = '文件过大,请选择小于100MB的Excel文件'; return; } excelFile.value = file; errorMessage.value = ''; // 开始解析Excel readExcelFile(file); }; const readExcelFile = (file) => { importing.value = true; errorMessage.value = ''; importStatus.value = null; const reader = new FileReader(); reader.onload = function(e) { try { const data = new Uint8Array(e.target.result); const workbook = XLSX.read(data, { type: 'array' }); // 获取第一个工作表 const firstSheetName = workbook.SheetNames[0]; const worksheet = workbook.Sheets[firstSheetName]; // 将工作表转换为JSON const jsonData = XLSX.utils.sheet_to_json(worksheet, { header: 1 }); if (jsonData.length === 0) { errorMessage.value = 'Excel文件中没有数据'; importing.value = false; return; } // 获取列名(假设第一行是列名) excelColumns.value = jsonData[0].map(col => col || '未命名列'); // 提取预览数据(2-11行) previewData.value = []; for (let i = 1; i < Math.min(jsonData.length, 11); i++) { const rowObj = {}; jsonData[i].forEach((cell, index) => { rowObj[excelColumns.value[index]] = cell; }); previewData.value.push(rowObj); } canImport.value = true; importing.value = false; totalRows.value = jsonData.length - 1; ElMessage.success(`成功解析${totalRows.value}条数据`); } catch (error) { console.error('Excel解析错误:', error); errorMessage.value = `Excel文件解析失败: ${error.message}`; importing.value = false; } }; reader.onerror = (error) => { console.error('文件读取错误:', error); errorMessage.value = `文件读取失败: ${error.target.error.message}`; importing.value = false; }; reader.readAsArrayBuffer(file); }; const startImport = async () => { // 验证映射配置 if (!columnMapping['报价产品']) { errorMessage.value = '请至少映射"报价产品"列'; return; } importing.value = true; importProgress.value = 0; importedCount.value = 0; importStatus.value = null; errorMessage.value = ''; successMessage.value = ''; // 重新读取文件以获取完整数据 const reader = new FileReader(); reader.onload = async function(e) { try { const data = new Uint8Array(e.target.result); const workbook = XLSX.read(data, { type: 'array' }); const firstSheetName = workbook.SheetNames[0]; const worksheet = workbook.Sheets[firstSheetName]; const jsonData = XLSX.utils.sheet_to_json(worksheet, { header: 1 }); // 跳过标题行 const rows = jsonData.slice(1); const itemsToInsert = []; const newTableData = []; // 为所有记录生成相同的XLJXDH const commonXLJXDH =BJDID; // 处理每一行数据 for (let i = 0; i < rows.length; i++) { const row = rows[i]; const rowData = {}; // 映射Excel列到系统字段 tableColumns.value.forEach(col => { const excelCol = columnMapping[col]; if (excelCol) { const colIndex = excelColumns.value.indexOf(excelCol); if (colIndex !== -1) { rowData[col.toLowerCase()] = row[colIndex] || ''; } } }); // 创建数据库对象 const product = rowData['报价产品'] || ''; const sequenceNumber = (i + 1).toString(); // 生成序号 itemsToInsert.push({ XLJXDJ: "XSBJ", XLJXDH: BJDID, // 使用相同的代号 XLJXMXH: sequenceNumber, XLBSC: product, XLJXGZXH: "0", JXXLXHID: rowData['型号'] || "", XLXHID: "", JXXLGGID: rowData['规格'] || "", XLGGID: "", JXDYDJID: rowData['电压等级'] || "", DYDJID: "", XLBZID: rowData['标准'] || "", JXXLBZID: "", XLYSID: "", JXXLYSID: "", WHR: "", WHRID: "", WHSJ: "", DCZT: "N" , JLDW: rowData['计量单位'] || "", SL: rowData['数量'] || "" }); newTableData.push({ index: sequenceNumber, // 添加序号字段 product, unit: rowData['计量单位'] || '', quantity: rowData['数量'] || '', model: rowData['型号'] || '', voltage: rowData['电压等级'] || '', standard: rowData['标准'] || '', spec: rowData['规格'] || '', status: 'N', checked: false }); // 更新进度 importedCount.value = i + 1; importProgress.value = Math.round(((i + 1) / rows.length) * 100); } // 批量插入数据 if (itemsToInsert.length > 0) { const result = await bulkInsertXLJXMX(itemsToInsert); if (result && result.success) { // 重新加载以同步服务端分配的解析序号(与 DRHH 关联) await loadTableData(); importing.value = false; successMessage.value = `成功导入${itemsToInsert.length}条产品数据`; ElMessage.success(`成功导入${itemsToInsert.length}条产品数据`); } else { importing.value = false; errorMessage.value = `导入失败: ${result?.message || '未知错误'}`; ElMessage.error(`导入失败: ${result?.message || '未知错误'}`); } } else { importing.value = false; ElMessage.warning('Excel中没有有效数据'); } } catch (error) { console.error('导入错误:', error); errorMessage.value = `导入失败: ${error.message}`; importing.value = false; importStatus.value = 'exception'; } }; reader.readAsArrayBuffer(excelFile.value); }; // 辅助函数:格式化文件大小 const formatFileSize = (bytes) => { if (bytes < 1024) return bytes + ' bytes'; else if (bytes < 1048576) return (bytes / 1024).toFixed(2) + ' KB'; else return (bytes / 1048576).toFixed(2) + ' MB'; }; // ==== 其他功能函数 ==== // 保存文本选择 const saveSelection = () => { if (!ruleEditor.value) return; const textarea = ruleEditor.value; const start = textarea.selectionStart; const end = textarea.selectionEnd; const text = textarea.value.substring(start, end); selection.value = { start, end, text }; }; // 取消所有标记 const unmarkAll = () => { // 移除所有标记格式 [tag=value] ruleString.value = ruleString.value .replace(/\[([^\]]+)=([^\]]+)\]/g, '$2'); // 清空所有配置项的值 resetTags(); // ElMessage.success('已取消所有标记'); }; // 粘贴数据 const pasteData = async () => { const isHttps = window.location.protocol === 'https:'; logMappingDebug('pasteData.enter', { isHttps, protocol: window.location.protocol }); if (!isHttps) { showManualPasteDialog(); logMappingDebug('pasteData.http.showManualPasteDialog', {}); return; } // HTTPS环境,使用列映射功能 try { const text = await navigator.clipboard.readText(); if (!text) { ElMessage.warning('剪贴板中没有数据'); return; } clipboardText = text; const rows = text.split('\n').filter(row => row.trim() !== ''); if (rows.length === 0) { ElMessage.warning('剪贴板中的数据为空'); return; } const firstRow = rows[0].split('\t'); detectedColumnCount.value = firstRow.length; detectedPreviewRows.value = rows.slice(0, 5).map((row, idx) => { const cols = row.split('\t'); const rowData = { rowIndex: idx + 1 }; for (let i = 0; i < cols.length; i++) { rowData['col' + i] = cols[i]; } return rowData; }); applyDefaultColumnMapping(columnFieldMapping, detectedColumnCount.value); manualPasteText.value = text; pasteStep.value = 'mapping'; manualPasteDialogVisible.value = true; nextTick(() => forceApplyDefaultColumnMapping(columnFieldMapping, detectedColumnCount.value)); } catch (err) { if (err.name === 'NotAllowedError' || err.name === 'NotSupportedError') { ElMessage.warning('剪贴板访问被拒绝,请使用手动粘贴'); showManualPasteDialog(); } else { completeCenterProgress(false, `粘贴失败: ${err.message}`); console.error('粘贴失败:', err); ElMessage.error('粘贴数据失败: ' + (err.message || '服务异常')); loading.value = false; } } }; const GetFGF = async () => { try { GThinking.Web.AjaxServiceProxy.servicePath = 'S_XLXSBJ/102373012.ashx'; const result = await new Promise((resolve, reject) => { GThinking.Web.AjaxServiceProxy.invoke( 'GetXHFGF', false, { '-RefUmId': 102851007 }, (data) => resolve(data), (error) => reject(error), "GetXHFGF", 50000 ); }); FGF.value = result || []; } catch (error) { ElMessage.error('获取失败: ' + (error.message || '服务异常')); } finally { } }; const normalizeBatchSpec = (value) => (value || '').replace(/×/g, '*'); // 加载表格数据 const loadTableData = async (options = {}) => { const silent = options && options.silent === true; loading.value = true; try { GThinking.Web.AjaxServiceProxy.servicePath = 'S_XLXSBJ/102373012.ashx'; const params = buildListQueryParams(); const result = await new Promise((resolve, reject) => { GThinking.Web.AjaxServiceProxy.invoke( 'GetXLJXMXList', false, { '-RefUmId': 102851007, ...params }, (data) => resolve(data), (error) => reject(error), "GetXLJXMXList", 50000 ); }); tableData.value = (result || []).map(item => ({ index: item.XLJXMXH, // 序号字段 product: item.XLBSC, unit: item.JLDW || '', // 新增 quantity: item.SL || '', // 新增 packageNumber:item.FBH, // 包号 techSpecId:item.JSGFID, // 技术规范ID model: item.JXXLXHID || item.XLXHID, XLXHID: item.XLXHID || '', voltage: item.JXDYDJID || item.DYDJID, standard: item.JXXLBZID || item.XLBZID, spec: item.JXXLGGID || item.XLGGID, XLGGID: item.XLGGID || '', status: item.DCZT, dx:item.DX, XLJXGZXH:item.XLJXGZXH, selected: false, current: false // 添加当前行状态标识 })); if (filterEquivalent.value) { tableData.value=tableData.value.filter(item => item.dx !== ""&&item.dx != null); } // 更新下拉选项 updateFilterOptions(); if (!silent) { ElMessage.success(`加载${tableData.value.length}条数据`); } } catch (error) { ElMessage.error('数据加载失败: ' + (error.message || '服务异常')); } finally { loading.value = false; } }; const deleteData = async () => { loading.value = true; try { GThinking.Web.AjaxServiceProxy.servicePath = 'S_XLXSBJ/102373012.ashx'; const params = buildListQueryParams(); const result = await new Promise((resolve, reject) => { GThinking.Web.AjaxServiceProxy.invoke( 'DeleteXLJXMX', false, { '-RefUmId': 102851007, ...params }, (data) => resolve(data), (error) => reject(error), "DeleteXLJXMX", 50000 ); }); loadTableData(); ElMessage.success(`删除成功!`); } catch (error) { ElMessage.error('数据删除失败: ' + (error.message || '服务异常')); } finally { loading.value = false; } }; const exportExcel = () => { if (!tableData.value || tableData.value.length === 0) { ElMessage.warning('当前列表没有可导出的数据') return } // Excel 表头(和页面一致) const header = [ '序号', '包号', '报价产品', '技术规范ID', '计量单位', '数量', '型号', '电压等级', '标准', '规格', '等效' ] // 数据行(严格对应 tableData 字段) const rows = tableData.value.map((row, idx) => [ idx + 1, // 序号(按页面顺序) row.packageNumber ?? '', row.product ?? '', row.techSpecId ?? '', row.unit ?? '', row.quantity ?? '', row.model ?? '', row.voltage ?? '', row.standard ?? '', row.spec ?? '', row.dx ?? '' ]) const ws = XLSX.utils.aoa_to_sheet([header, ...rows]) // 列宽 ws['!cols'] = [ { wch: 6 }, // 序号 { wch: 10 }, // 包号 { wch: 20 }, // 报价产品 { wch: 18 }, // 技术规范ID { wch: 10 }, // 计量单位 { wch: 10 }, // 数量 { wch: 14 }, // 型号 { wch: 14 }, // 电压等级 { wch: 14 }, // 标准 { wch: 14 }, // 规格 { wch: 10 } // 等效 ] const wb = XLSX.utils.book_new() XLSX.utils.book_append_sheet(wb, ws, '报价产品明细') XLSX.writeFile( wb, `报价产品明细_${new Date().toISOString().slice(0, 10)}.xlsx` ) } // 更新下拉选项 const updateFilterOptions = () => { // 从表格数据中提取唯一的电压等级值 const voltageSet = new Set(); const standardSet = new Set(); tableData.value.forEach(item => { if (item.voltage && item.voltage.trim()) { voltageSet.add(item.voltage.trim()); } if (item.standard && item.standard.trim()) { standardSet.add(item.standard.trim()); } }); // 转换为数组并排序,添加空选项 voltageOptions.value = [ { value: '', label: '全部' }, { value: '空', label: '空' } ].concat(Array.from(voltageSet).sort().map(value => ({ value: value, label: value }))); standardOptions.value = [ { value: '', label: '全部' } , { value: '空', label: '空' } ].concat(Array.from(standardSet).sort().map(value => ({ value: value, label: value }))); }; // 更新选中行状态 const updateSelectedRows = () => { const selectedRows = tableData.value.filter(row => row.selected); selectedRowsCount.value = selectedRows.length; hasSelectedRows.value = selectedRowsCount.value > 0; }; // 加载批量调整线缆标准选项 const loadBatchStandardOptions = async () => { try { GThinking.Web.AjaxServiceProxy.servicePath = 'S_XLXSBJ/102373012.ashx'; const result = await new Promise((resolve, reject) => { GThinking.Web.AjaxServiceProxy.invoke( 'XLBZList', false, {}, (data) => resolve(data), (error) => reject(error), "XLBZList_CallBack", 50000 ); }); if (result) { batchUpdateOptions.value = result.map(item => ({ value: item.XLBZID, label: item.XLBZMC })); } } catch (error) { console.error('加载线缆标准失败:', error); ElMessage.error('加载线缆标准失败'); } }; // 加载批量调整电压等级选项 const loadBatchVoltageOptions = async () => { try { GThinking.Web.AjaxServiceProxy.servicePath = 'S_XLXSBJ/102373012.ashx'; const result = await new Promise((resolve, reject) => { GThinking.Web.AjaxServiceProxy.invoke( 'GetDYDJList', false, {}, (data) => resolve(data), (error) => reject(error), "GetDYDJList_CallBack", 50000 ); }); if (result) { batchUpdateOptions.value = result.map(item => ({ value: item, label: item })); } } catch (error) { console.error('加载电压等级失败:', error); ElMessage.error('加载电压等级失败'); } }; // 加载标准编码名称映射 const loadStandardNameMap = async () => { try { GThinking.Web.AjaxServiceProxy.servicePath = 'S_XLXSBJ/102373012.ashx'; const result = await new Promise((resolve, reject) => { GThinking.Web.AjaxServiceProxy.invoke( 'XLBZList', false, {}, (data) => resolve(data), (error) => reject(error), "LoadStandardNameMap_CallBack", 50000 ); }); if (result) { const map = {}; result.forEach(item => { map[item.XLBZID] = item.XLBZMC; }); standardNameMap.value = map; } } catch (error) { console.error('加载标准名称映射失败:', error); } }; // 显示批量调整对话框 const showBatchUpdateDialog = async (type) => { batchUpdateType.value = type; batchUpdateValue.value = ''; batchUpdateOptions.value = []; batchUpdateFilterQuery.value = ''; updateSelectedRows(); if (type === 'standard') { batchUpdateTitle.value = '批量调整线缆标准'; await loadBatchStandardOptions(); } else if (type === 'voltage') { batchUpdateTitle.value = '批量调整电压等级'; await loadBatchVoltageOptions(); } else if (type === 'model') { batchUpdateTitle.value = '批量调整线缆型号'; } else if (type === 'spec') { batchUpdateTitle.value = '批量调整线缆规格'; } batchUpdateDialogVisible.value = true; }; // 关闭批量调整对话框 const closeBatchUpdateDialog = () => { batchUpdateDialogVisible.value = false; batchUpdateValue.value = ''; batchUpdateFilterQuery.value = ''; }; const buildBatchUpdateItem = (row) => ({ XLJXDJ: "XSBJ", XLJXDH: BJDID, XLJXMXH: (row.index != null ? row.index : '').toString() }); // 确认批量调整 const confirmBatchUpdate = async () => { if (!batchUpdateValue.value.trim()) { ElMessage.warning(batchUpdateUseSelect.value ? '请选择调整值' : '请输入调整值'); return; } const selectedRows = tableData.value.filter(row => row.selected); if (selectedRows.length === 0) { ElMessage.warning('请先选择要调整的记录'); return; } let updateValue = ''; if (batchUpdateUseSelect.value) { updateValue = resolveBatchUpdateSelectValue(); if (!updateValue) { ElMessage.warning( batchUpdateType.value === 'standard' ? '请从下拉列表中选择有效的线缆标准' : '请从下拉列表中选择有效的电压等级' ); return; } } else { updateValue = batchUpdateType.value === 'spec' ? normalizeBatchSpec(batchUpdateValue.value.trim()) : batchUpdateValue.value.trim(); } try { startCenterProgress('正在批量调整数据...'); const items = selectedRows.map(row => buildBatchUpdateItem(row)); // 调用后端批量更新服务 GThinking.Web.AjaxServiceProxy.servicePath = 'S_XLXSBJ/102373012.ashx'; const result = await new Promise((resolve, reject) => { GThinking.Web.AjaxServiceProxy.invoke( 'BatchUpdateXLJXMX', false, { '-RefUmId': 102851007, items: items, updateType: batchUpdateType.value, updateValue: updateValue }, (data) => resolve(data), (error) => reject(error), "BatchUpdateXLJXMX", 50000 ); }); if (result && result.success) { tableData.value = tableData.value.map(row => { if (!row.selected) { return row; } if (batchUpdateType.value === 'standard') { return { ...row, standard: updateValue }; } if (batchUpdateType.value === 'voltage') { return { ...row, voltage: updateValue }; } if (batchUpdateType.value === 'model') { return { ...row, model: updateValue, XLXHID: updateValue }; } if (batchUpdateType.value === 'spec') { return { ...row, spec: updateValue, XLGGID: updateValue }; } return row; }); closeBatchUpdateDialog(); completeCenterProgress(true, '批量调整成功!'); ElMessage.success(result.msg || `已成功调整 ${selectedRows.length} 条记录`); await loadTableData({ silent: true }); updateSelectedRows(); } else { completeCenterProgress(false, result?.msg || '批量调整失败'); ElMessage.error(result?.msg || '批量调整失败'); } } catch (error) { completeCenterProgress(false, '批量调整失败'); ElMessage.error('批量调整失败: ' + (error.message || '服务异常')); } }; const InsertBJDMX = async () => { try { if (!tableData.value || tableData.value.length === 0) { ElMessage.warning('没有可导入的数据'); return; } if (!filterRule.value || filterRule.value=== '0') { ElMessage.warning('当前数据未解析,请先解析数据'); return; } startCenterProgress('正在导入数据...'); if (!BJDID) return; // 用户取消输入 // 转换数据 const items = tableData.value.map((row, index) => ({ XLJXDJ: "XSBJ", XLJXDH: BJDID, XLJXMXH: row.index.toString(), XLBSC: row.product, XLJXGZXH: "0", JXXLXHID: row.model, XLXHID: "", JXXLGGID: row.spec, XLGGID: "", JXDYDJID: row.voltage, DYDJID: "", XLBZID: row.standard, JXXLBZID: row.standard, XLYSID: "", JXXLYSID: "", WHR: "", WHRID: "", WHSJ: new Date().toISOString(), DCZT: row.status, JLDW: row.unit || "", SL: row.quantity || "", FBH: row.packageNumber || "", JSGFID: row.techSpecId || "" })); // 设置服务路径(确保正确) GThinking.Web.AjaxServiceProxy.servicePath = 'S_XLXSBJ/102373012.ashx'; isLoading.value = true; // 调用服务(使用正确的服务方法名) const result = await new Promise((resolve, reject) => { GThinking.Web.AjaxServiceProxy.invoke( 'InsertBJDMX', // 确保这是正确的服务方法名 false, { '-RefUmId': 102851007, // 根据实际服务调整 'items': items, 'sBJDID': BJDID }, (data) => resolve(data), (error) => reject(error), "InsertBJDMX", 300000 ); }); if (result && result.success) { ElMessage.success(result.msg || `成功导入${items.length}条报价单明细`); completeCenterProgress(true, result.msg || '数据导入完成!'); setTimeout(() => { closePage(); }, 1000); // 延时 2000 毫秒(2 秒) } else { const errorMsg = result?.msg || result?.message || '服务返回未知错误'; ElMessage.error(`导入失败: ${errorMsg}`); completeCenterProgress(false, '导入失败'); } isLoading.value = false; } catch (error) { // 处理用户取消输入的情况 if (error.toString().includes('cancel')) { return; } isLoading.value = false; console.error('导入报价单明细失败:', error); const errorMsg = error.message || '服务异常'; completeCenterProgress(false, '导入失败'); ElMessage.error(`导入失败: ${errorMsg}`); } }; const loadRuleOptions = async () => { try { // 设置服务路径 GThinking.Web.AjaxServiceProxy.servicePath = 'S_XLXSBJ/102373012.ashx'; // 调用服务获取解析规则列表 const result = await new Promise((resolve, reject) => { GThinking.Web.AjaxServiceProxy.invoke( 'GetXLJXGZList', false, { '-RefUmId': 102855005, // 替换为实际RefUmId 'XLJXDJ': 'XSBJ', // 固定值 'XLJXDH': BJDID // 可为空 }, (data) => resolve(data), (error) => reject(error), "GetXLJXGZList", 50000 // 5秒超时 ); }); if (result && Array.isArray(result)) { // 去重处理:基于XLJXGZXH const uniqueRules = []; const seen = new Set(); uniqueRules.push({ value: '0', label: '未解析' }); uniqueRules.push({ value: '-1', label: '已解析' }); uniqueRules.push({ value: '-2', label: '全部' }); result.forEach(rule => { if (!seen.has(rule.XLJXGZXH)) { seen.add(rule.XLJXGZXH); uniqueRules.push({ value: rule.XLJXGZXH, label: rule.XLJXGZC }); } }); ruleOptions.value = uniqueRules; ElMessage.success(`加载${uniqueRules.length}条解析规则`); } else { ruleOptions.value = []; ElMessage.warning('未获取到解析规则'); } } catch (error) { console.error('加载解析规则失败:', error); ElMessage.error(`加载解析规则失败: ${error.message || '服务异常'}`); ruleOptions.value = []; } }; // 加载通用解析规则选项 const loadCommonRuleOptions = async () => { try { // 设置服务路径 GThinking.Web.AjaxServiceProxy.servicePath = 'S_XLXSBJ/102373012.ashx'; // 调用服务获取通用解析规则列表 const result = await new Promise((resolve, reject) => { GThinking.Web.AjaxServiceProxy.invoke( 'GetXLJXGZList', false, { '-RefUmId': 102855005, // 替换为实际RefUmId 'XLJXDJ': 'XSBJ', 'XLJXDH':' ' // 固定值 }, (data) => resolve(data), (error) => reject(error), "GetXLJXGZList", 50000 // 5秒超时 ); }); if (result && Array.isArray(result)) { // 去重处理:基于XLJXGZXH const uniqueRules = []; const seen = new Set(); uniqueRules.push({ value: '0', label: '请选择通用规则' }); result.forEach(rule => { if (!seen.has(rule.XLJXGZXH)) { seen.add(rule.XLJXGZXH); uniqueRules.push({ value: rule.XLJXGZXH, label: rule.XLJXGZC }); } }); commonRuleOptions.value = uniqueRules; ElMessage.success(`加载${uniqueRules.length}条通用解析规则`); } else { commonRuleOptions.value = []; ElMessage.warning('未获取到通用解析规则'); } } catch (error) { console.error('加载通用解析规则失败:', error); ElMessage.error(`加载通用解析规则失败: ${error.message || '服务异常'}`); commonRuleOptions.value = []; } }; // 应用通用解析规则 const showXlxhDialog = () => { // 构建带参数的 URL const params = new URLSearchParams({ title: '线缆型号语法', ruleString1 : ruleString.value, reservedWords : "型号码,前缀码,后缀码", connectors : ",-,/,(,)", syntaxString : modelValue.value }); // 设置 iframe 的 URL 并添加参数 iframeUrl.value = `${BJCPJXDR_XHYF.value}?${params.toString()}`; YFGZDialogVisible.value = true; resultReceived.value = false; }; const showXLGGDialog = () => { // 构建带参数的 URL const params = new URLSearchParams({ title: '线缆规格语法', ruleString1 : ruleString.value, reservedWords : "截面,芯数,线对数,线组数", connectors : "*,×,+,/,(,)", syntaxString : specValue.value }); // 设置 iframe 的 URL 并添加参数 iframeUrl.value = `${BJCPJXDR_XHYF.value}?${params.toString()}`; YFGZDialogVisible.value = true; resultReceived.value = false; }; const showXlBZDialog = () => { // 构建带参数的 URL const params = new URLSearchParams({ title: '线缆标准语法', ruleString1 : ruleString.value, reservedWords : "标准名", connectors : ",-,/,(,)", syntaxString : standardValue.value }); // 设置 iframe 的 URL 并添加参数 iframeUrl.value = `${BJCPJXDR_XHYF.value}?${params.toString()}`; YFGZDialogVisible.value = true; resultReceived.value = false; }; const showDYDJDialog = () => { // 构建带参数的 URL const params = new URLSearchParams({ title: '电压等级语法', ruleString1 : ruleString.value, reservedWords : "相电压,线电压,电压单位", connectors : "/,V,kV", syntaxString : voltageValue.value }); // 设置 iframe 的 URL 并添加参数 iframeUrl.value = `${BJCPJXDR_XHYF.value}?${params.toString()}`; YFGZDialogVisible.value = true; resultReceived.value = false; }; const handleMessage = (event) => { if (event.data && event.data.type === 'SAVE_SYNTAX_RESULT') { // 从子页面接收结果 const result = event.data.payload; const { type, Value, ActualValue } = result; switch(type) { case '线缆型号语法': modelValue.value = Value; modelActualValue.value = ActualValue; break; case '线缆规格语法': specValue.value = Value; specActualValue.value = ActualValue; break; case '电压等级语法': voltageValue.value = Value; voltageActualValue.value = ActualValue; break; case '线缆标准语法': standardValue.value = Value; standardActualValue.value = ActualValue; break; default: console.warn(`未知语法类型: ${type}`); return; } ElMessage.success(`${type}已更新`); // 关闭对话框 YFGZDialogVisible.value = false; resultReceived.value = true; } }; onMounted(() => { window.addEventListener('message', handleMessage); }); // 清理监听器 onUnmounted(() => { window.removeEventListener('message', handleMessage); }); // 显示规则配置对话框 const showRuleDialog = async () => { if (!selectedProduct.value) { ElMessage.warning('请先在表格中选择一条数据'); return; } GetFGF(); // 1. 创建请求参数 const requestItem = { XLBSC: selectedProduct.value, XLJXDJ:'XSBJ', XLJXDH:BJDID, XLJXGZXH:filterRule.value<=0?currentRowXLJXGZXH.value:filterRule.value, XLXHID: currentRowModel.value, // 当前行型号值 DYDJID: currentRowVoltage.value, // 当前行电压值 XLBZID: currentRowStandard.value, // 当前行标准值 XLGGID: currentRowSpec.value // 当前行规格值 }; try { // 设置服务路径 GThinking.Web.AjaxServiceProxy.servicePath = 'S_XLXSBJ/102373012.ashx'; // 调用服务获取解析规则列表 const result = await new Promise((resolve, reject) => { GThinking.Web.AjaxServiceProxy.invoke( 'GetJXPZ', false, { '-RefUmId': 102855005, // 替换为实际RefUmId 'item': requestItem }, (data) => resolve(data), (error) => reject(error), "GetJXPZ", 50000 // 5秒超时 ); }); if (result) { ruleString.value = result.XLJXGZC; modelValue.value = result.XLXHYFC; modelActualValue.value = result.XLXH; specValue.value = result.XLGGYFC; specActualValue.value = result.XLGG; voltageValue.value = result.DYDJYFC; voltageActualValue.value = result.DYDJ; standardValue.value = result.XLBZYFC; standardActualValue.value = result.XLBZ; ruleDialogVisible.value = true; } else { } } catch (error) { } // 重置选择状态 nextTick(() => { selection.value = { start: 0, end: 0, text: '' }; if (ruleEditor.value) { ruleEditor.value.focus(); } }); //parseRuleValue(); }; // 关闭规则配置对话框 const closeRuleDialog = () => { ruleDialogVisible.value = false; unmarkAll(); }; //todo // todo const showSyntaxDialog = () => { syntaxDialogVisible.value = true; }; // todo const closeSyntaxDialog = () => { syntaxDialogVisible.value = false; }; // 保存规则配置 const saveRuleConfig = async (IsCommon) => { try { // 设置服务路径 GThinking.Web.AjaxServiceProxy.servicePath = 'S_XLXSBJ/102373012.ashx'; // 生成唯一的规则代号(使用时间戳) const XLJXDH = BJDID; // 创建XLJXGZ对象 const ruleConfig = { XLJXDJ: "XSBJ", // 固定值 XLJXDH: XLJXDH, XLJXGZXH: filterRule.value<=0?currentRowXLJXGZXH.value:filterRule.value, // 默认序号 XLJXGZC: ruleString.value, XLXHYFC: modelValue.value, XLGGYFC: specValue.value, DYDJYFC: voltageValue.value, XLBZYFC: standardValue.value, XLYSYFC: colorValue.value || "", // 颜色标记串(可选) WHR: "", WHRID: "", // 维护人ID(可选) WHSJ: new Date().toISOString() // 当前时间 }; isLoading.value = true; // 调用服务 const result = await new Promise((resolve, reject) => { GThinking.Web.AjaxServiceProxy.invoke( 'InsertXLJXGZ', false, { '-RefUmId': 102855005, // 替换为实际RefUmId 'item': ruleConfig, 'IsCommon':IsCommon }, (data) => resolve(data), (error) => reject(error), "InsertXLJXGZ", 50000 // 5秒超时 ); }); if (result && result.success) { ElMessage.success('解析规则已保存'); ruleDialogVisible.value = false; loadRuleOptions(); filterRule.value=result.msg; filterRule.label=ruleOptions.value[result.msg]; loadTableData(); unmarkAll(); } else { ElMessage.error(`保存失败: ${result?.message || '未知错误'}`); } isLoading.value = false; } catch (error) { isLoading.value = false; console.error('保存规则失败:', error); ElMessage.error(`保存失败: ${error.message || '服务异常'}`); } }; const commonParse = async () => { try { // 设置服务路径 GThinking.Web.AjaxServiceProxy.servicePath = 'S_XLXSBJ/102373012.ashx'; // 生成唯一的规则代号(使用时间戳) const XLJXDH = BJDID; // 调用服务 const result = await new Promise((resolve, reject) => { GThinking.Web.AjaxServiceProxy.invoke( 'commonParse', false, { '-RefUmId': 102855005, // 替换为实际RefUmId 'BJDID': XLJXDH }, (data) => resolve(data), (error) => reject(error), "commonParse", 500000 // 5秒超时 ); }); if (result && result.success) { ElMessage.success('通用解析规则已执行'); loadRuleOptions(); filterRule.value=result.msg; loadTableData(); } else { ElMessage.error(`通用解析失败: ${result?.message || '未知错误'}`); } } catch (error) { console.error('通用解析失败:', error); ElMessage.error(`通用解析失败: ${error.message || '服务异常'}`); } }; // 解析数据 const parseData = () => { if (tableData.value.length === 0) { ElMessage.warning('请先粘贴数据'); return; } loading.value = true; // 模拟解析过程 setTimeout(() => { const parsedData = tableData.value.map(item => { // 简单模拟解析逻辑 const parts = item.product.split(','); return { ...item, model: parts.length > 2 ? parts[2] : '', voltage: parts.length > 1 ? parts[1] : '', spec: parts.length > 3 ? parts[3] : '', status: 'N' }; }); tableData.value = parsedData; loading.value = false; ElMessage.success('解析完成'); }, 1000); }; // 显示筛选对话框 const showFilterDialog = () => { loadRuleOptions(); filterDialogVisible.value = true; }; const showEXRuleDialog = () => { loadRuleOptions(); EXRuleDialogVisible.value = true; }; // 关闭筛选对话框 const closeFilterDialog = () => { filterDialogVisible.value = false; }; // 关闭筛选对话框 const closeEXRuleDialog = () => { EXRuleDialogVisible.value = false; }; // 应用筛选条件 const applyFilter = () => { // 应用筛选条件后重新加载表格数据 loadTableData(); ElMessage.success('筛选条件已应用'); }; const applyRule = async () => { try { // 设置服务路径 GThinking.Web.AjaxServiceProxy.servicePath = 'S_XLXSBJ/102373012.ashx'; // 1. 获取规则数据 const item = await new Promise((resolve, reject) => { GThinking.Web.AjaxServiceProxy.invoke( 'GetXLJXGZ', false, { '-RefUmId': 102855005, 'XLJXDJ': 'XSBJ', 'XLJXDH': BJDID, 'XLJXGZXH': ExRule.value }, (data) => resolve(data), (error) => reject(error), "GetXLJXGZ", 50000 ); }); // 2. 更新规则属性 item.XLJXGZXH = filterRule.value; // 3. 更新规则 const result = await new Promise((resolve, reject) => { GThinking.Web.AjaxServiceProxy.invoke( 'InsertXLJXGZ', false, { '-RefUmId': 102855005, 'item': item, 'IsCommon':'N' }, (data) => resolve(data), (error) => reject(error), "InsertXLJXGZ", 50000 ); }); // 4. 处理结果 if (result && result.success) { ElMessage.success('解析规则已保存'); ruleDialogVisible.value = false; ExRule.value = '0'; filterRule.value = result.msg || filterRule.value; // 5. 刷新表格数据 await loadTableData(); unmarkAll(); } else { const errorMsg = result?.message || '未知错误'; ElMessage.error(`保存失败: ${errorMsg}`); } } catch (error) { console.error('保存规则失败:', error); const errorMsg = error.message || '服务异常'; ElMessage.error(`保存失败: ${errorMsg}`); } finally { // 6. 确保关闭对话框并刷新数据 EXRuleDialogVisible.value = false; } }; // ===== el-table-v2 相关方法 ===== // 处理行点击 // const handleRowClick = (params) => { // const { rowData, rowIndex } = params; // // 使用 map 创建新数组确保响应性 // tableData.value = tableData.value.map((row, idx) => ({ // ...row, // current: idx === rowIndex // })); // // 设置选中的产品 // selectedProduct.value = rowData.product; // currentRowModel.value = rowData.model || ''; // currentRowVoltage.value = rowData.voltage || ''; // currentRowStandard.value = rowData.standard || ''; // currentRowSpec.value = rowData.spec || ''; // }; const handleTableClick = (e) => { const rowElement = e.target.closest('.el-table-v2__row'); if (!rowElement) return; const rowIndex = Array.from(rowElement.parentNode.children).indexOf(rowElement); const rowData = tableData.value[rowIndex]; if (rowData) { // 清除所有行的选中状态 tableData.value = tableData.value.map(row => ({ ...row, current: false })); // 设置当前行选中 tableData.value[rowIndex] = { ...tableData.value[rowIndex], current: true }; // 设置选中的产品 selectedProduct.value = rowData.product; currentRowModel.value = rowData.model || ''; currentRowVoltage.value = rowData.voltage || ''; currentRowStandard.value = rowData.standard || ''; currentRowSpec.value = rowData.spec || ''; currentRowXLJXGZXH.value = rowData.XLJXGZXH || '0'; } }; const getRowClass = ({ rowData }) => { return rowData.current ? 'current-row' : ''; }; // 处理窗口大小变化 const handleResize = () => { tableWidth.value = window.innerWidth - 30; tableHeight.value = window.innerHeight - 150; }; const handleRowClick = (row)=>{ //console.log('选中的行ID:', row.id) //根据选中行id获取rowdata // 获取rowIndex const rowIndex = row.rowIndex; const rowData = tableData.value[rowIndex]; if (rowData) { // 清除所有行的选中状态 tableData.value = tableData.value.map(row => ({ ...row, current: false })); // 设置当前行选中 tableData.value[rowIndex] = { ...tableData.value[rowIndex], current: true }; // 设置选中的产品 selectedProduct.value = rowData.product; currentRowModel.value = rowData.model || ''; currentRowVoltage.value = rowData.voltage || ''; currentRowStandard.value = rowData.standard || ''; currentRowSpec.value = rowData.spec || ''; currentRowXLJXGZXH.value = rowData.XLJXGZXH || '0'; } } // 监听规则串变化 watch(ruleString, () => { parseModelValue }); // 监听窗口大小变化 window.addEventListener('resize', handleResize); // 页面加载时自动加载数据 onMounted(() => { loadTableData(); loadStandardNameMap(); handleResize(); const tableElement = document.querySelector('.el-table-v2'); if (tableElement) { //tableElement.addEventListener('click', handleTableClick); } }); const handleEnterKey = (e) => { // 检查是否在查询条件输入框中 const isInQueryInput = e.target.matches('input[placeholder*="报价产品"], input[placeholder*="线缆型号"], input[placeholder*="线缆规格"], input[placeholder*="电压等级"], input[placeholder*="线缆标准"]'); if (isInQueryInput && e.key === 'Enter') { e.preventDefault(); // 阻止默认行为 loadTableData(); // 执行查询 } }; onMounted(() => { // 添加全局键盘事件监听 document.addEventListener('keydown', handleEnterKey); window.addEventListener('message', handleMessage); }); onUnmounted(() => { // 清理事件监听 document.removeEventListener('keydown', handleEnterKey); window.removeEventListener('message', handleMessage); stopColumnResize(); if (resizeGuideEl && resizeGuideEl.parentNode) { resizeGuideEl.parentNode.removeChild(resizeGuideEl); resizeGuideEl = null; } }); // 返回所有变量和方法 return { // 状态变量 loading, ruleDialogVisible, EXRuleDialogVisible, filterDialogVisible, tableData, // 批量调整相关变量 batchUpdateDialogVisible, batchUpdateType, batchUpdateValue, hasSelectedRows, selectedRowsCount, batchUpdateTitle, selectedProduct, ruleEditor, ruleString, modelValue, specValue, voltageValue, standardValue, colorValue, filterRule, filterStatus, ruleOptions, modelActualValue, specActualValue, voltageActualValue, standardActualValue, // Excel导入相关 importDialogVisible, fileInput, excelFile, excelColumns, previewData, columnMapping, tableColumns, importing, importProgress, totalRows, importedCount, importStatus, errorMessage, successMessage, canImport, // el-table-v2相关 tableColumnsV2, tableWidth, tableHeight, // 方法 pasteData, showRuleDialog, closeRuleDialog, saveRuleConfig, showFilterDialog, showEXRuleDialog, closeFilterDialog, applyFilter, applyRule, markPrefixCode, markModelCode, markSuffixCode, markVoltagePhase, markVoltageLine, markVoltageUnit, markVoltageLevel, markWireCount, markSection, markWireGroup, markWirePair, markSpec, markStandardName, saveSelection, parseData, handleResize, handleRowClick, unmarkAll, openSyntaxPage, // Excel导入方法 showImportDialog, closeImportDialog, triggerFileInput, handleFileChange, startImport, resetImport, formatFileSize, // el-table-v2方法 getRowClass, InsertBJDMX, closePage, statusOptions, closeEXRuleDialog, ExRule, showXlxhDialog, showXlBZDialog, showDYDJDialog, showXLGGDialog, YFGZDialogVisible, iframeUrl, loadRuleOptions, loadTableData, getRowKey, deleteData, exportExcel, isLoading, showCenterProgress, centerProgressPercentage, centerProgressStatus, centerProgressText, filterEquivalent, handleManualPasteCancel, handleManualPasteConfirm, handleMappingConfirm, handleMappingBack, manualPasteText, manualPasteDialogVisible, pasteStep, detectedColumnCount, detectedPreviewRows, columnFieldMapping, pasteFieldOptions, visibleColumns, productQuery, modelQuery, specQuery, voltageQuery, standardQuery, missingElementQuery, missingElementOptions, deleteRule, // 新增通用解析规则相关 commonRuleOptions, loadCommonRuleOptions, deleteCommonRule, // 批量调整相关方法 updateSelectedRows, showBatchUpdateDialog, closeBatchUpdateDialog, confirmBatchUpdate, batchUpdateOptions, batchUpdateFilteredOptions, filterBatchUpdateOptions, loadBatchStandardOptions, loadBatchVoltageOptions, voltageOptions, standardOptions, standardNameMap, loadStandardNameMap }; } }); app.use(ElementPlus); // 全局注册所有图标组件 for (const [key, component] of Object.entries(ElementPlusIconsVue)) { app.component(key, component); } app.mount('#app');