113 lines
3.4 KiB
TypeScript
113 lines
3.4 KiB
TypeScript
/**
|
||
* 修复数据库中 videoCoverUrl 字段为 true 的问题
|
||
*
|
||
* 问题:某些素材的 videoCoverUrl 字段值是布尔值 true 或字符串 'true' 而不是 URL 字符串
|
||
* 这会导致前端尝试访问 http://192.168.58.20:4320/true 这样的无效URL
|
||
*
|
||
* 使用方法:
|
||
* npx tsx scripts/fix-true-url-values.ts [--dry-run]
|
||
*/
|
||
|
||
import { PrismaClient } from '@prisma/client';
|
||
|
||
const DATABASE_URL = process.env.DATABASE_URL || 'postgresql://gongxiangpan:gongxiangpan123@192.168.58.20:5432/lobechat';
|
||
const prisma = new PrismaClient({
|
||
datasources: {
|
||
db: {
|
||
url: DATABASE_URL,
|
||
},
|
||
},
|
||
});
|
||
|
||
const args = process.argv.slice(2);
|
||
const isDryRun = args.includes('--dry-run');
|
||
|
||
async function main() {
|
||
console.log('开始执行脚本...');
|
||
console.log('='.repeat(60));
|
||
console.log('修复 videoCoverUrl 为 true 的问题');
|
||
console.log('='.repeat(60));
|
||
console.log();
|
||
|
||
if (isDryRun) {
|
||
console.log('⚠️ 试运行模式:不会实际修改数据库');
|
||
console.log();
|
||
}
|
||
|
||
try {
|
||
console.log('查询问题数据...');
|
||
|
||
// 直接查询 videoCoverUrl 为字符串 'true' 的记录
|
||
const problematicMaterials = await prisma.$queryRaw<Array<{
|
||
id: string;
|
||
productModel: string;
|
||
materialType: string;
|
||
videoCoverUrl: any;
|
||
}>>`
|
||
SELECT
|
||
id,
|
||
"productModel",
|
||
"materialType",
|
||
"videoCoverUrl"
|
||
FROM materials
|
||
WHERE
|
||
"videoCoverUrl"::text = 'true'
|
||
AND "deletedAt" IS NULL
|
||
`;
|
||
|
||
console.log(` 找到 ${problematicMaterials.length} 个素材的 videoCoverUrl 为 true`);
|
||
console.log();
|
||
|
||
if (problematicMaterials.length === 0) {
|
||
console.log('✅ 没有发现 videoCoverUrl 为 true 的素材');
|
||
} else {
|
||
console.log('问题素材列表(前10个):');
|
||
for (const material of problematicMaterials.slice(0, 10)) {
|
||
console.log(` - ${material.productModel} (${material.materialType})`);
|
||
console.log(` ID: ${material.id}`);
|
||
console.log(` videoCoverUrl: ${material.videoCoverUrl}`);
|
||
console.log();
|
||
}
|
||
if (problematicMaterials.length > 10) {
|
||
console.log(` ... 还有 ${problematicMaterials.length - 10} 个素材`);
|
||
console.log();
|
||
}
|
||
|
||
if (!isDryRun) {
|
||
console.log('开始修复...');
|
||
let fixedCount = 0;
|
||
|
||
for (const material of problematicMaterials) {
|
||
try {
|
||
// 将 videoCoverUrl 设置为 null
|
||
await prisma.material.update({
|
||
where: { id: material.id },
|
||
data: {
|
||
videoCoverUrl: null,
|
||
} as any,
|
||
});
|
||
console.log(` ✅ 已修复: ${material.productModel} (videoCoverUrl: true -> null)`);
|
||
fixedCount++;
|
||
} catch (error: any) {
|
||
console.error(` ❌ 修复失败: ${material.productModel} - ${error.message}`);
|
||
}
|
||
}
|
||
|
||
console.log();
|
||
console.log(`修复完成: ${fixedCount}/${problematicMaterials.length} 个素材已修复`);
|
||
} else {
|
||
console.log('⚠️ 试运行模式:不会实际修改数据库');
|
||
console.log(' 如果要实际修复,请运行: npx tsx scripts/fix-true-url-values.ts');
|
||
}
|
||
}
|
||
|
||
} catch (error) {
|
||
console.error('执行失败:', error);
|
||
process.exit(1);
|
||
} finally {
|
||
await prisma.$disconnect();
|
||
}
|
||
}
|
||
|
||
main();
|