Files
suanming/server/scripts/refactorAiInterpretations.cjs
patdelphi d1713be5f5 feat: refactor AI interpretation system and fix recordId issues
- Refactored AI interpretation table to use proper 1-to-1 relationship with reading records
- Fixed recordId parameter passing in AnalysisResultDisplay component
- Updated database schema to use reading_id instead of analysis_id
- Removed complex string ID generation logic
- Fixed TypeScript type definitions for all ID fields
- Added database migration scripts for AI interpretation refactoring
- Improved error handling and debugging capabilities
2025-08-23 23:05:13 +08:00

171 lines
6.0 KiB
JavaScript
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.
const { getDB } = require('../database/index.cjs');
/**
* 重构AI解读记录表建立与分析报告记录的正确1对1关系
* 消除字符串analysis_id使用正确的外键关联
*/
function refactorAiInterpretations() {
const db = getDB();
try {
console.log('=== 开始重构AI解读记录表 ===\n');
// 开始事务
db.exec('BEGIN TRANSACTION');
// 1. 分析现有数据
console.log('1. 分析现有数据...');
const allAI = db.prepare(`
SELECT id, analysis_id, analysis_type, content, model, tokens_used,
success, error_message, created_at, updated_at, user_id
FROM ai_interpretations
ORDER BY created_at DESC
`).all();
console.log(`总AI解读记录: ${allAI.length}`);
const stringIds = allAI.filter(r => typeof r.analysis_id === 'string');
const numericIds = allAI.filter(r => typeof r.analysis_id === 'number');
console.log(`字符串ID记录: ${stringIds.length}`);
console.log(`数字ID记录: ${numericIds.length}`);
if (stringIds.length === 0) {
console.log('没有需要重构的字符串ID记录');
db.exec('ROLLBACK');
return;
}
// 2. 创建新的临时表
console.log('\n2. 创建新的AI解读表结构...');
db.exec(`
CREATE TABLE ai_interpretations_new (
id INTEGER PRIMARY KEY AUTOINCREMENT,
user_id INTEGER NOT NULL,
reading_id INTEGER NOT NULL, -- 直接关联到numerology_readings表的id
content TEXT NOT NULL,
model TEXT,
tokens_used INTEGER,
success BOOLEAN DEFAULT 1,
error_message TEXT,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE,
FOREIGN KEY (reading_id) REFERENCES numerology_readings(id) ON DELETE CASCADE,
UNIQUE(reading_id) -- 确保1对1关系
)
`);
// 3. 迁移数字ID记录如果有的话
if (numericIds.length > 0) {
console.log(`\n3. 迁移 ${numericIds.length} 条数字ID记录...`);
const insertStmt = db.prepare(`
INSERT INTO ai_interpretations_new
(user_id, reading_id, content, model, tokens_used, success, error_message, created_at, updated_at)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
`);
for (const record of numericIds) {
// 验证关联的记录是否存在
const readingExists = db.prepare(
'SELECT id FROM numerology_readings WHERE id = ? AND user_id = ?'
).get(record.analysis_id, record.user_id);
if (readingExists) {
insertStmt.run(
record.user_id,
record.analysis_id,
record.content,
record.model,
record.tokens_used,
record.success,
record.error_message,
record.created_at,
record.updated_at
);
console.log(` 迁移记录: AI_ID=${record.id} -> reading_id=${record.analysis_id}`);
} else {
console.log(` 跳过无效记录: AI_ID=${record.id}, analysis_id=${record.analysis_id} (关联记录不存在)`);
}
}
}
// 4. 处理字符串ID记录 - 删除无效记录
console.log(`\n4. 处理 ${stringIds.length} 条字符串ID记录...`);
console.log('这些记录使用了临时生成的字符串ID无法建立正确的关联关系将被删除:');
stringIds.forEach((record, index) => {
console.log(` ${index + 1}. AI_ID=${record.id}, analysis_id="${record.analysis_id}", type=${record.analysis_type}`);
});
// 5. 删除旧表,重命名新表
console.log('\n5. 更新表结构...');
db.exec('DROP TABLE ai_interpretations');
db.exec('ALTER TABLE ai_interpretations_new RENAME TO ai_interpretations');
// 6. 重新创建索引
console.log('6. 重新创建索引...');
db.exec('CREATE INDEX IF NOT EXISTS idx_ai_interpretations_user_id ON ai_interpretations(user_id)');
db.exec('CREATE INDEX IF NOT EXISTS idx_ai_interpretations_reading_id ON ai_interpretations(reading_id)');
db.exec('CREATE INDEX IF NOT EXISTS idx_ai_interpretations_created_at ON ai_interpretations(created_at DESC)');
// 7. 重新创建触发器
console.log('7. 重新创建触发器...');
db.exec(`
CREATE TRIGGER IF NOT EXISTS update_ai_interpretations_timestamp
AFTER UPDATE ON ai_interpretations
FOR EACH ROW
BEGIN
UPDATE ai_interpretations SET updated_at = CURRENT_TIMESTAMP WHERE id = NEW.id;
END
`);
// 提交事务
db.exec('COMMIT');
// 8. 验证结果
console.log('\n=== 重构完成 ===');
const newCount = db.prepare('SELECT COUNT(*) as count FROM ai_interpretations').get();
console.log(`新表记录数: ${newCount.count}`);
const sampleRecords = db.prepare(`
SELECT ai.id, ai.reading_id, ai.user_id, nr.name, nr.reading_type
FROM ai_interpretations ai
JOIN numerology_readings nr ON ai.reading_id = nr.id
LIMIT 5
`).all();
console.log('\n示例关联记录:');
sampleRecords.forEach((record, index) => {
console.log(` ${index + 1}. AI_ID=${record.id} -> reading_id=${record.reading_id} (${record.name}, ${record.reading_type})`);
});
console.log('\n✅ AI解读记录表重构成功!');
console.log('现在AI解读记录与分析报告记录建立了正确的1对1关系');
} catch (error) {
// 回滚事务
try {
db.exec('ROLLBACK');
} catch (rollbackError) {
console.error('回滚失败:', rollbackError);
}
throw error;
}
}
// 如果直接运行此脚本
if (require.main === module) {
try {
const { dbManager } = require('../database/index.cjs');
dbManager.init();
refactorAiInterpretations();
console.log('\n🎉 重构完成!');
process.exit(0);
} catch (error) {
console.error('\n❌ 重构失败:', error);
process.exit(1);
}
}
module.exports = { refactorAiInterpretations };