/** * 回滚已迁移的素材 * * 用于回滚迁移失败或路径错误的素材 */ import { PrismaClient } from '@prisma/client'; import { unlink } from 'fs/promises'; import path from 'path'; const prisma = new PrismaClient(); // 要回滚的素材型号 const PRODUCT_MODEL = 'XG0176'; async function main() { console.log('='.repeat(60)); console.log('回滚已迁移的素材'); console.log('='.repeat(60)); console.log(`素材型号: ${PRODUCT_MODEL}`); console.log(''); try { // 1. 查询素材 const material = await prisma.material.findFirst({ where: { productModel: PRODUCT_MODEL, materialType: '任务-详情', deletedAt: null, }, include: { assets: true, }, }); if (!material) { console.log('未找到素材'); return; } console.log(`找到素材: ${material.id}`); console.log(`当前 zipFilePath: ${material.zipFilePath}`); console.log(`当前 zipFileSize: ${material.zipFileSize}`); console.log(''); // 2. 删除新增的资产记录(只删除新增的,保留老的 main/sku/detail) const assetsToDelete = material.assets.filter( (a) => a.assetType === 'main-preview' || a.assetType === 'sku-preview' || a.assetType === 'detail-preview' || (a.assetType === 'main' && a.fileUrl.startsWith('uploads/')) || (a.assetType === 'sku' && a.fileUrl.startsWith('uploads/')) || (a.assetType === 'detail' && a.fileUrl.startsWith('uploads/')) || a.assetType === 'all' ); console.log(`将删除 ${assetsToDelete.length} 条资产记录:`); assetsToDelete.forEach((a) => { console.log(` - ${a.assetType}: ${a.fileName}`); }); console.log(''); // 3. 删除生成的zip文件(只删除本地zip文件) const zipFiles = material.assets.filter( (a) => ((a.assetType === 'main' || a.assetType === 'sku' || a.assetType === 'detail') && a.fileUrl.startsWith('uploads/')) || a.assetType === 'all' ); console.log(`将删除 ${zipFiles.length} 个zip文件:`); for (const asset of zipFiles) { const filePath = path.join(process.cwd(), asset.fileUrl); console.log(` - ${filePath}`); try { await unlink(filePath); console.log(` ✅ 删除成功`); } catch (err) { console.log(` ⚠️ 删除失败: ${err}`); } } console.log(''); // 4. 执行数据库回滚 await prisma.$transaction(async (tx) => { // 删除新增的资产记录(逐个删除,避免误删老记录) for (const asset of assetsToDelete) { await tx.materialAsset.delete({ where: { id: asset.id }, }); } // 恢复素材记录 await tx.material.update({ where: { id: material.id }, data: { zipFilePath: '', zipFileName: '', zipFileSize: BigInt(0), }, }); }); console.log('✅ 回滚完成'); } catch (error) { console.error('回滚失败:', error); process.exit(1); } finally { await prisma.$disconnect(); } } main();