141 lines
3.5 KiB
JavaScript
141 lines
3.5 KiB
JavaScript
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)
|
||
})
|