gongxiangp2/scripts/export-history-import-scan-summary.js
chenpei 9cd3c0f231 feat: 任务详情无条码开关 + 上传面板信息密度优化 + 历史导入/脚本补全
- 任务详情上传支持"本批素材无条码"开关,跳过条码必填校验
- SKU卡片/主图网格从4列改5列,图片高度压缩,去掉冗余标签和提示
- 详情图/PSD上传区去掉大占位框,改成紧凑按钮+标签
- 补充历史导入相关脚本和工具文件

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-05-11 10:01:08 +08:00

77 lines
2.4 KiB
JavaScript
Raw Permalink 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 fs = require('fs')
const path = require('path')
const inputPath = process.argv[2] || path.join('output', 'tianlan-history-sku-import-scan-full.json')
const outputDir = process.argv[3] || path.join('output')
const baseName = process.argv[4] || 'tianlan-history-sku-import'
function escapeCsvCell(value) {
const text = String(value ?? '')
if (/[",\r\n]/.test(text)) {
return `"${text.replace(/"/g, '""')}"`
}
return text
}
function writeCsv(filePath, rows) {
const headers = [
'status(状态)',
'spu(SPU)',
'store(店铺)',
'product_category(产品品类)',
'author(作者)',
'main_count(主图数量)',
'sku_count(SKU图数量)',
'detail_count(详情图数量)',
'skip_reason(跳过或复核原因)',
'source_path(来源完整路径)',
'relative_source_path(来源相对路径)',
]
const lines = [
headers.join(','),
...rows.map((record) =>
[
record.status,
record.spu,
record.guessedStore,
record.productCategoryName,
record.authorName,
record.mainCount,
record.skuCount,
record.detailCount,
record.skipReason || '',
record.sourcePath,
record.relativeSourcePath,
]
.map(escapeCsvCell)
.join(','),
),
]
fs.writeFileSync(filePath, `\uFEFF${lines.join('\r\n')}`, 'utf8')
}
function countBy(records, picker) {
return records.reduce((acc, record) => {
const key = picker(record) || '<empty>'
acc[key] = (acc[key] || 0) + 1
return acc
}, {})
}
const records = JSON.parse(fs.readFileSync(inputPath, 'utf8'))
fs.mkdirSync(outputDir, { recursive: true })
writeCsv(path.join(outputDir, `${baseName}-ready.csv`), records.filter((record) => record.status === 'ready'))
writeCsv(path.join(outputDir, `${baseName}-needs-review.csv`), records.filter((record) => record.status === 'needs_review'))
writeCsv(path.join(outputDir, `${baseName}-skipped.csv`), records.filter((record) => record.status === 'skipped'))
const summary = {
total: records.length,
status: countBy(records, (record) => record.status),
store: countBy(records, (record) => record.guessedStore),
productCategory: countBy(records, (record) => record.productCategoryName),
}
fs.writeFileSync(path.join(outputDir, `${baseName}-summary.json`), JSON.stringify(summary, null, 2), 'utf8')
console.log(JSON.stringify(summary, null, 2))