- 创建统一的下载错误处理模块 (lib/download-errors.ts) - 实现13种错误类型分类和中文错误消息 - 后端统一使用 createDownloadError 创建标准化错误响应 - 前端统一使用 parseDownloadError 解析错误并显示 - 修复正式系统数据库Schema,添加产品全案相关字段和表 - 执行数据库迁移:添加 task_no, task_status, task_fetched_at 字段 - 创建 material_assets, api_keys, api_call_logs 表
133 lines
3.8 KiB
TypeScript
133 lines
3.8 KiB
TypeScript
/**
|
||
* 检查数据库 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);
|
||
});
|