gongxiangp2/scripts/check-db-schema.ts
chenpei ea9076df45 feat: 实现统一的下载错误处理系统并修复产品全案数据库Schema
- 创建统一的下载错误处理模块 (lib/download-errors.ts)
- 实现13种错误类型分类和中文错误消息
- 后端统一使用 createDownloadError 创建标准化错误响应
- 前端统一使用 parseDownloadError 解析错误并显示
- 修复正式系统数据库Schema,添加产品全案相关字段和表
- 执行数据库迁移:添加 task_no, task_status, task_fetched_at 字段
- 创建 material_assets, api_keys, api_call_logs 表
2026-01-05 17:52:42 +08:00

133 lines
3.8 KiB
TypeScript
Raw 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.

/**
* 检查数据库 Schema 是否与 Prisma Schema 匹配
* 用于排查缺失的列和表
*/
import { prisma } from '../lib/prisma';
// 需要检查的字段(Material 表)
const MATERIAL_FIELDS_TO_CHECK = [
'task_no',
'task_status',
'task_fetched_at',
'deletedAt', // 可能已经存在,但检查一下
'uploadId',
'videoSourceUrl',
'videoPreview540Url',
'videoPreviewClipUrl',
'videoCoverUrl',
'videoProcessingStatus',
'videoDuration',
'transcodeLastError',
'transcodeAttempts',
'originalOwnerId',
'transferredAt',
'transferredBy',
'transferNote',
];
// 需要检查的表
const TABLES_TO_CHECK = [
'material_assets',
'api_keys',
'api_call_logs',
'material_transfers',
];
async function checkTableExists(tableName: string): Promise<boolean> {
try {
const result = await prisma.$queryRawUnsafe<Array<{ exists: boolean }>>(
`SELECT EXISTS (
SELECT FROM information_schema.tables
WHERE table_schema = 'public'
AND table_name = $1
) as exists`,
tableName
);
return result[0]?.exists || false;
} catch (error) {
console.error(`检查表 ${tableName} 时出错:`, error);
return false;
}
}
async function checkColumnExists(tableName: string, columnName: string): Promise<boolean> {
try {
const result = await prisma.$queryRawUnsafe<Array<{ exists: boolean }>>(
`SELECT EXISTS (
SELECT FROM information_schema.columns
WHERE table_schema = 'public'
AND table_name = $1
AND column_name = $2
) as exists`,
tableName,
columnName
);
return result[0]?.exists || false;
} catch (error) {
console.error(`检查列 ${tableName}.${columnName} 时出错:`, error);
return false;
}
}
async function main() {
console.log('========================================');
console.log('数据库 Schema 检查');
console.log('========================================\n');
// 检查 Material 表的字段
console.log('检查 Material 表的字段...');
const missingFields: string[] = [];
for (const field of MATERIAL_FIELDS_TO_CHECK) {
const exists = await checkColumnExists('materials', field);
if (!exists) {
missingFields.push(field);
console.log(` ❌ 缺失字段: materials.${field}`);
} else {
console.log(` ✅ 字段存在: materials.${field}`);
}
}
// 检查表
console.log('\n检查表...');
const missingTables: string[] = [];
for (const table of TABLES_TO_CHECK) {
const exists = await checkTableExists(table);
if (!exists) {
missingTables.push(table);
console.log(` ❌ 缺失表: ${table}`);
} else {
console.log(` ✅ 表存在: ${table}`);
}
}
// 总结
console.log('\n========================================');
console.log('检查结果总结');
console.log('========================================');
if (missingFields.length === 0 && missingTables.length === 0) {
console.log('✅ 所有字段和表都存在,数据库 Schema 完整!');
} else {
console.log('❌ 发现缺失的字段或表:');
if (missingFields.length > 0) {
console.log(`\n缺失的字段 (${missingFields.length} 个):`);
missingFields.forEach(field => console.log(` - materials.${field}`));
}
if (missingTables.length > 0) {
console.log(`\n缺失的表 (${missingTables.length} 个):`);
missingTables.forEach(table => console.log(` - ${table}`));
}
console.log('\n需要执行数据库迁移:');
console.log(' 1. 运行迁移脚本: prisma/migrations/product_package_migration.sql');
console.log(' 2. 或使用 Prisma Migrate: npx prisma migrate deploy');
}
await prisma.$disconnect();
}
main().catch((error) => {
console.error('检查过程中出错:', error);
process.exit(1);
});