160 lines
4.1 KiB
TypeScript
160 lines
4.1 KiB
TypeScript
/**
|
||
* 按“主图 + SKU 图 + 详情图齐全”规则回填任务-详情的 isFullSet。
|
||
*
|
||
* 默认只预览结果,不写库。
|
||
* 真正写入请加:--apply
|
||
* 可选限制数量:--limit=200
|
||
*/
|
||
|
||
import { PrismaClient } from '@prisma/client';
|
||
import { isTaskDetailFullSetFromAssets } from '../lib/task-detail-full-set';
|
||
|
||
const prisma = new PrismaClient();
|
||
|
||
function parseLimitArg(): number | undefined {
|
||
const limitArg = process.argv.find((arg) => arg.startsWith('--limit='));
|
||
if (!limitArg) {
|
||
return undefined;
|
||
}
|
||
|
||
const parsed = Number(limitArg.split('=')[1]);
|
||
if (!Number.isFinite(parsed) || parsed <= 0) {
|
||
throw new Error(`无效的 --limit 参数:${limitArg}`);
|
||
}
|
||
|
||
return Math.floor(parsed);
|
||
}
|
||
|
||
async function main() {
|
||
const shouldApply = process.argv.includes('--apply');
|
||
const limit = parseLimitArg();
|
||
|
||
console.log('='.repeat(72));
|
||
console.log('任务-详情 isFullSet 回填脚本');
|
||
console.log(`模式: ${shouldApply ? '写入数据库' : '仅预览(dry-run)'}`);
|
||
if (limit) {
|
||
console.log(`限制数量: ${limit}`);
|
||
}
|
||
console.log('规则: 同时拥有主图、SKU 图、详情图 => 整套');
|
||
console.log('='.repeat(72));
|
||
|
||
const materials = await prisma.material.findMany({
|
||
where: {
|
||
materialType: '任务-详情',
|
||
deletedAt: null,
|
||
},
|
||
select: {
|
||
id: true,
|
||
taskNo: true,
|
||
productModel: true,
|
||
isFullSet: true,
|
||
createdAt: true,
|
||
assets: {
|
||
select: {
|
||
assetType: true,
|
||
},
|
||
},
|
||
},
|
||
orderBy: {
|
||
createdAt: 'desc',
|
||
},
|
||
...(limit ? { take: limit } : {}),
|
||
});
|
||
|
||
let shouldBeTrue = 0;
|
||
let shouldBeFalse = 0;
|
||
let toTrue = 0;
|
||
let toFalse = 0;
|
||
let unchanged = 0;
|
||
|
||
const changedMaterials: Array<{
|
||
id: string;
|
||
taskNo: string | null;
|
||
productModel: string;
|
||
before: boolean;
|
||
after: boolean;
|
||
assetTypes: string[];
|
||
}> = [];
|
||
|
||
for (const material of materials) {
|
||
const derivedIsFullSet = isTaskDetailFullSetFromAssets(material.assets);
|
||
const currentIsFullSet = Boolean(material.isFullSet);
|
||
|
||
if (derivedIsFullSet) {
|
||
shouldBeTrue += 1;
|
||
} else {
|
||
shouldBeFalse += 1;
|
||
}
|
||
|
||
if (derivedIsFullSet === currentIsFullSet) {
|
||
unchanged += 1;
|
||
continue;
|
||
}
|
||
|
||
if (derivedIsFullSet) {
|
||
toTrue += 1;
|
||
} else {
|
||
toFalse += 1;
|
||
}
|
||
|
||
changedMaterials.push({
|
||
id: material.id,
|
||
taskNo: material.taskNo,
|
||
productModel: material.productModel,
|
||
before: currentIsFullSet,
|
||
after: derivedIsFullSet,
|
||
assetTypes: material.assets.map((asset) => asset.assetType),
|
||
});
|
||
}
|
||
|
||
console.log(`总素材数: ${materials.length}`);
|
||
console.log(`应为整套: ${shouldBeTrue}`);
|
||
console.log(`应为非整套: ${shouldBeFalse}`);
|
||
console.log(`待改为 true: ${toTrue}`);
|
||
console.log(`待改为 false: ${toFalse}`);
|
||
console.log(`无需修改: ${unchanged}`);
|
||
|
||
if (changedMaterials.length > 0) {
|
||
console.log('\n待修改样例(最多展示前 20 条):');
|
||
changedMaterials.slice(0, 20).forEach((material, index) => {
|
||
console.log(
|
||
`${index + 1}. ${material.productModel} | taskNo=${material.taskNo || '无'} | ${material.before} -> ${material.after} | assets=${material.assetTypes.join(', ')}`,
|
||
);
|
||
});
|
||
} else {
|
||
console.log('\n没有需要修改的素材。');
|
||
}
|
||
|
||
if (!shouldApply) {
|
||
console.log('\n当前为 dry-run,未写入数据库。');
|
||
console.log('如需真正回填,请执行: npx tsx scripts/backfill-task-detail-full-set.ts --apply');
|
||
return;
|
||
}
|
||
|
||
if (changedMaterials.length === 0) {
|
||
console.log('\n没有可写入的变更,结束。');
|
||
return;
|
||
}
|
||
|
||
console.log('\n开始写入数据库...');
|
||
for (const material of changedMaterials) {
|
||
await prisma.material.update({
|
||
where: { id: material.id },
|
||
data: {
|
||
isFullSet: material.after,
|
||
},
|
||
});
|
||
}
|
||
|
||
console.log(`写入完成,共更新 ${changedMaterials.length} 条素材。`);
|
||
}
|
||
|
||
main()
|
||
.catch((error) => {
|
||
console.error('脚本执行失败:', error);
|
||
process.exitCode = 1;
|
||
})
|
||
.finally(async () => {
|
||
await prisma.$disconnect();
|
||
});
|