const fs = require('fs') const ExcelJS = require('exceljs') const csvPath = process.argv[2] || '历史SKU目录清单.csv' const xlsxPath = process.argv[3] || '历史SKU目录清单.xlsx' const rootHeader = 'source_root(来源根路径)' const relativeHeader = 'relative_path(相对路径)' const windowsHeader = 'windows_path(Windows路径)' const ROOT_MAPPINGS = [ { linuxRoot: '/mnt/history-sc/大货营销策划图片', windowsRoot: '\\\\192.168.58.116\\sc\\大货营销策划图片', }, { linuxRoot: '/mnt/history-cp-gb', windowsRoot: '\\\\192.168.58.116\\cp-gb', }, { linuxRoot: '/mnt/history-yya', windowsRoot: '\\\\192.168.58.116\\yya', }, ] function parseCsvLine(line) { const result = [] let current = '' let inQuotes = false for (let i = 0; i < line.length; i += 1) { const char = line[i] const next = line[i + 1] if (char === '"') { if (inQuotes && next === '"') { current += '"' i += 1 } else { inQuotes = !inQuotes } continue } if (char === ',' && !inQuotes) { result.push(current) current = '' continue } current += char } result.push(current) return result } function escapeCsvCell(value) { const text = String(value ?? '') if (/[",\r\n]/.test(text)) { return `"${text.replace(/"/g, '""')}"` } return text } function buildWindowsPath(sourceRoot, relativePath) { const source = String(sourceRoot || '').trim() const relative = String(relativePath || '').trim() const mapping = ROOT_MAPPINGS.find((item) => item.linuxRoot === source) if (!mapping) { return relative.replace(/\//g, '\\') } if (!relative) { return mapping.windowsRoot } return `${mapping.windowsRoot}\\${relative.replace(/\//g, '\\')}` } function updateCsv() { const raw = fs.readFileSync(csvPath, 'utf8') const lines = raw.split(/\r?\n/).filter((line) => line.length > 0) const rows = lines.map(parseCsvLine) if (rows.length === 0) { return } const header = rows[0] if (header.length > 0) { header[0] = String(header[0] || '').replace(/^\uFEFF/, '') } const rootIndex = header.indexOf(rootHeader) const relativeIndex = header.indexOf(relativeHeader) let windowsIndex = header.indexOf(windowsHeader) if (windowsIndex === -1) { const insertAt = relativeIndex + 1 header.splice(insertAt, 0, windowsHeader) windowsIndex = insertAt for (let i = 1; i < rows.length; i += 1) { rows[i].splice(insertAt, 0, '') } } for (let i = 1; i < rows.length; i += 1) { const row = rows[i] row[windowsIndex] = buildWindowsPath(row[rootIndex], row[relativeIndex]) } const output = rows.map((row) => row.map(escapeCsvCell).join(',')).join('\r\n') fs.writeFileSync(csvPath, `\uFEFF${output}`, 'utf8') } async function updateXlsx() { const workbook = new ExcelJS.Workbook() const worksheet = await workbook.csv.readFile(csvPath) worksheet.name = 'SKU目录' worksheet.views = [{ state: 'frozen', ySplit: 1 }] worksheet.columns.forEach((column) => { let maxLength = String(column.header || '').length column.eachCell({ includeEmpty: true }, (cell) => { const length = String(cell.value ?? '').length if (length > maxLength) { maxLength = length } }) column.width = Math.min(90, Math.max(12, maxLength + 2)) }) await workbook.xlsx.writeFile(xlsxPath) } async function main() { updateCsv() await updateXlsx() console.log('done') } main().catch((error) => { console.error(error) process.exit(1) })