mirror of
https://github.com/patdelphi/suanming.git
synced 2026-02-28 05:33:11 +08:00
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
This commit is contained in:
@@ -81,8 +81,7 @@ CREATE INDEX IF NOT EXISTS idx_sessions_expires ON user_sessions(expires_at);
|
||||
CREATE TABLE IF NOT EXISTS ai_interpretations (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
user_id INTEGER NOT NULL,
|
||||
analysis_id INTEGER NOT NULL, -- 关联到numerology_readings表的id
|
||||
analysis_type TEXT NOT NULL CHECK (analysis_type IN ('bazi', 'ziwei', 'yijing')),
|
||||
reading_id INTEGER NOT NULL, -- 直接关联到numerology_readings表的id
|
||||
content TEXT NOT NULL, -- AI解读的完整内容
|
||||
model TEXT, -- 使用的AI模型
|
||||
tokens_used INTEGER, -- 消耗的token数量
|
||||
@@ -91,12 +90,13 @@ CREATE TABLE IF NOT EXISTS ai_interpretations (
|
||||
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE,
|
||||
FOREIGN KEY (analysis_id) REFERENCES numerology_readings(id) ON DELETE CASCADE
|
||||
FOREIGN KEY (reading_id) REFERENCES numerology_readings(id) ON DELETE CASCADE,
|
||||
UNIQUE(reading_id) -- 确保1对1关系
|
||||
);
|
||||
|
||||
-- 创建AI解读相关索引
|
||||
CREATE INDEX IF NOT EXISTS idx_ai_interpretations_user_id ON ai_interpretations(user_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_ai_interpretations_analysis_id ON ai_interpretations(analysis_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_ai_interpretations_reading_id ON ai_interpretations(reading_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_ai_interpretations_created_at ON ai_interpretations(created_at DESC);
|
||||
|
||||
-- 触发器:自动更新updated_at字段
|
||||
|
||||
@@ -6,32 +6,32 @@ const router = express.Router();
|
||||
// 保存AI解读结果
|
||||
router.post('/save', authenticate, async (req, res) => {
|
||||
try {
|
||||
const { analysis_id, analysis_type, content, model, tokens_used, success, error_message } = req.body;
|
||||
const { reading_id, content, model, tokens_used, success, error_message } = req.body;
|
||||
const user_id = req.user.id;
|
||||
|
||||
// 验证必需参数
|
||||
if (!analysis_id || !analysis_type || (!content && success !== false)) {
|
||||
if (!reading_id || (!content && success !== false)) {
|
||||
return res.status(400).json({
|
||||
error: '缺少必需参数:analysis_id, analysis_type, content'
|
||||
error: '缺少必需参数:reading_id, content'
|
||||
});
|
||||
}
|
||||
|
||||
// 验证analysis_id是否属于当前用户
|
||||
// 验证reading_id是否属于当前用户
|
||||
const db = getDB();
|
||||
const analysisExists = db.prepare(
|
||||
const readingExists = db.prepare(
|
||||
'SELECT id FROM numerology_readings WHERE id = ? AND user_id = ?'
|
||||
).get(analysis_id, user_id);
|
||||
|
||||
if (!analysisExists) {
|
||||
).get(reading_id, user_id);
|
||||
|
||||
if (!readingExists) {
|
||||
return res.status(404).json({
|
||||
error: '分析记录不存在或无权限访问'
|
||||
});
|
||||
}
|
||||
|
||||
// 检查是否已存在AI解读记录
|
||||
// 检查是否已存在AI解读记录(1对1关系)
|
||||
const existingInterpretation = db.prepare(
|
||||
'SELECT id FROM ai_interpretations WHERE analysis_id = ? AND user_id = ?'
|
||||
).get(analysis_id, user_id);
|
||||
'SELECT id FROM ai_interpretations WHERE reading_id = ? AND user_id = ?'
|
||||
).get(reading_id, user_id);
|
||||
|
||||
if (existingInterpretation) {
|
||||
// 更新现有记录
|
||||
@@ -50,10 +50,10 @@ router.post('/save', authenticate, async (req, res) => {
|
||||
} else {
|
||||
// 创建新记录
|
||||
const insertStmt = db.prepare(`
|
||||
INSERT INTO ai_interpretations (user_id, analysis_id, analysis_type, content, model, tokens_used, success, error_message)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?)
|
||||
INSERT INTO ai_interpretations (user_id, reading_id, content, model, tokens_used, success, error_message)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?)
|
||||
`);
|
||||
const result = insertStmt.run(user_id, analysis_id, analysis_type, content, model, tokens_used, success ? 1 : 0, error_message);
|
||||
const result = insertStmt.run(user_id, reading_id, content, model, tokens_used, success ? 1 : 0, error_message);
|
||||
|
||||
res.json({
|
||||
success: true,
|
||||
@@ -71,21 +71,22 @@ router.post('/save', authenticate, async (req, res) => {
|
||||
});
|
||||
|
||||
// 获取AI解读结果
|
||||
router.get('/get/:analysis_id', authenticate, async (req, res) => {
|
||||
router.get('/get/:reading_id', authenticate, async (req, res) => {
|
||||
try {
|
||||
const { analysis_id } = req.params;
|
||||
const { reading_id } = req.params;
|
||||
const user_id = req.user.id;
|
||||
const db = getDB();
|
||||
|
||||
// 获取AI解读记录及关联的分析记录信息
|
||||
const interpretation = db.prepare(`
|
||||
SELECT ai.*, nr.name, nr.reading_type, nr.created_at as analysis_created_at
|
||||
FROM ai_interpretations ai
|
||||
JOIN numerology_readings nr ON ai.analysis_id = nr.id
|
||||
WHERE ai.analysis_id = ? AND ai.user_id = ?
|
||||
JOIN numerology_readings nr ON ai.reading_id = nr.id
|
||||
WHERE ai.reading_id = ? AND ai.user_id = ?
|
||||
ORDER BY ai.created_at DESC
|
||||
LIMIT 1
|
||||
`).get(analysis_id, user_id);
|
||||
|
||||
`).get(reading_id, user_id);
|
||||
|
||||
if (!interpretation) {
|
||||
return res.status(404).json({
|
||||
error: 'AI解读结果不存在'
|
||||
@@ -96,8 +97,7 @@ router.get('/get/:analysis_id', authenticate, async (req, res) => {
|
||||
success: true,
|
||||
data: {
|
||||
id: interpretation.id,
|
||||
analysis_id: interpretation.analysis_id,
|
||||
analysis_type: interpretation.analysis_type,
|
||||
reading_id: interpretation.reading_id,
|
||||
content: interpretation.content,
|
||||
model: interpretation.model,
|
||||
tokens_used: interpretation.tokens_used,
|
||||
@@ -106,6 +106,7 @@ router.get('/get/:analysis_id', authenticate, async (req, res) => {
|
||||
created_at: interpretation.created_at,
|
||||
updated_at: interpretation.updated_at,
|
||||
analysis_name: interpretation.name,
|
||||
analysis_type: interpretation.reading_type,
|
||||
analysis_created_at: interpretation.analysis_created_at
|
||||
}
|
||||
});
|
||||
@@ -122,22 +123,22 @@ router.get('/get/:analysis_id', authenticate, async (req, res) => {
|
||||
router.get('/list', authenticate, async (req, res) => {
|
||||
try {
|
||||
const user_id = req.user.id;
|
||||
const { page = 1, limit = 20, analysis_type } = req.query;
|
||||
const { page = 1, limit = 20, reading_type } = req.query;
|
||||
const offset = (page - 1) * limit;
|
||||
const db = getDB();
|
||||
|
||||
let whereClause = 'WHERE ai.user_id = ?';
|
||||
let params = [user_id];
|
||||
|
||||
if (analysis_type) {
|
||||
whereClause += ' AND ai.analysis_type = ?';
|
||||
params.push(analysis_type);
|
||||
if (reading_type) {
|
||||
whereClause += ' AND nr.reading_type = ?';
|
||||
params.push(reading_type);
|
||||
}
|
||||
|
||||
const interpretations = db.prepare(`
|
||||
SELECT ai.*, nr.name, nr.birth_date, nr.reading_type, nr.created_at as analysis_created_at
|
||||
FROM ai_interpretations ai
|
||||
JOIN numerology_readings nr ON ai.analysis_id = nr.id
|
||||
JOIN numerology_readings nr ON ai.reading_id = nr.id
|
||||
${whereClause}
|
||||
ORDER BY ai.created_at DESC
|
||||
LIMIT ? OFFSET ?
|
||||
@@ -147,7 +148,7 @@ router.get('/list', authenticate, async (req, res) => {
|
||||
const totalResult = db.prepare(`
|
||||
SELECT COUNT(*) as count
|
||||
FROM ai_interpretations ai
|
||||
JOIN numerology_readings nr ON ai.analysis_id = nr.id
|
||||
JOIN numerology_readings nr ON ai.reading_id = nr.id
|
||||
${whereClause}
|
||||
`).get(...params);
|
||||
const total = totalResult.count;
|
||||
@@ -156,8 +157,8 @@ router.get('/list', authenticate, async (req, res) => {
|
||||
success: true,
|
||||
data: interpretations.map(item => ({
|
||||
id: item.id,
|
||||
analysis_id: item.analysis_id,
|
||||
analysis_type: item.analysis_type,
|
||||
reading_id: item.reading_id,
|
||||
analysis_type: item.reading_type,
|
||||
content: item.content,
|
||||
model: item.model,
|
||||
tokens_used: item.tokens_used,
|
||||
@@ -186,16 +187,16 @@ router.get('/list', authenticate, async (req, res) => {
|
||||
});
|
||||
|
||||
// 删除AI解读结果
|
||||
router.delete('/delete/:analysis_id', authenticate, async (req, res) => {
|
||||
router.delete('/delete/:reading_id', authenticate, async (req, res) => {
|
||||
try {
|
||||
const { analysis_id } = req.params;
|
||||
const { reading_id } = req.params;
|
||||
const user_id = req.user.id;
|
||||
const db = getDB();
|
||||
|
||||
const deleteStmt = db.prepare(
|
||||
'DELETE FROM ai_interpretations WHERE analysis_id = ? AND user_id = ?'
|
||||
'DELETE FROM ai_interpretations WHERE reading_id = ? AND user_id = ?'
|
||||
);
|
||||
const result = deleteStmt.run(analysis_id, user_id);
|
||||
const result = deleteStmt.run(reading_id, user_id);
|
||||
|
||||
if (result.changes === 0) {
|
||||
return res.status(404).json({
|
||||
|
||||
@@ -26,28 +26,30 @@ router.get('/', authenticate, asyncHandler(async (req, res) => {
|
||||
}
|
||||
|
||||
// 获取总数
|
||||
const countQuery = `SELECT COUNT(*) as total FROM numerology_readings ${whereClause}`;
|
||||
const countQuery = `SELECT COUNT(*) as total FROM numerology_readings nr ${whereClause.replace('WHERE', 'WHERE nr.')}`;
|
||||
const { total } = db.prepare(countQuery).get(...params);
|
||||
|
||||
// 获取分页数据
|
||||
// 获取分页数据,包含AI解读状态
|
||||
const dataQuery = `
|
||||
SELECT
|
||||
id,
|
||||
reading_type,
|
||||
name,
|
||||
birth_date,
|
||||
birth_time,
|
||||
birth_place,
|
||||
gender,
|
||||
input_data,
|
||||
results,
|
||||
analysis,
|
||||
status,
|
||||
created_at,
|
||||
updated_at
|
||||
FROM numerology_readings
|
||||
${whereClause}
|
||||
ORDER BY created_at DESC
|
||||
nr.id,
|
||||
nr.reading_type,
|
||||
nr.name,
|
||||
nr.birth_date,
|
||||
nr.birth_time,
|
||||
nr.birth_place,
|
||||
nr.gender,
|
||||
nr.input_data,
|
||||
nr.results,
|
||||
nr.analysis,
|
||||
nr.status,
|
||||
nr.created_at,
|
||||
nr.updated_at,
|
||||
CASE WHEN ai.id IS NOT NULL THEN 1 ELSE 0 END as has_ai_interpretation
|
||||
FROM numerology_readings nr
|
||||
LEFT JOIN ai_interpretations ai ON (ai.reading_id = nr.id AND ai.user_id = nr.user_id)
|
||||
${whereClause.replace('WHERE', 'WHERE nr.')}
|
||||
ORDER BY nr.created_at DESC
|
||||
LIMIT ? OFFSET ?
|
||||
`;
|
||||
|
||||
|
||||
103
server/scripts/migrateAiInterpretations.cjs
Normal file
103
server/scripts/migrateAiInterpretations.cjs
Normal file
@@ -0,0 +1,103 @@
|
||||
const { getDB } = require('../database/index.cjs');
|
||||
|
||||
/**
|
||||
* 迁移ai_interpretations表,将analysis_id字段从INTEGER改为TEXT
|
||||
* 这样可以支持字符串类型的analysis_id
|
||||
*/
|
||||
function migrateAiInterpretationsTable() {
|
||||
const db = getDB();
|
||||
|
||||
try {
|
||||
console.log('开始迁移ai_interpretations表...');
|
||||
|
||||
// 检查表是否存在
|
||||
const tableExists = db.prepare(
|
||||
"SELECT name FROM sqlite_master WHERE type='table' AND name='ai_interpretations'"
|
||||
).get();
|
||||
|
||||
if (!tableExists) {
|
||||
console.log('ai_interpretations表不存在,跳过迁移');
|
||||
return;
|
||||
}
|
||||
|
||||
// 检查analysis_id字段的类型
|
||||
const columnInfo = db.prepare("PRAGMA table_info(ai_interpretations)").all();
|
||||
const analysisIdColumn = columnInfo.find(col => col.name === 'analysis_id');
|
||||
|
||||
if (analysisIdColumn && analysisIdColumn.type === 'TEXT') {
|
||||
console.log('analysis_id字段已经是TEXT类型,无需迁移');
|
||||
return;
|
||||
}
|
||||
|
||||
// 开始事务
|
||||
db.exec('BEGIN TRANSACTION');
|
||||
|
||||
// 1. 创建新的临时表
|
||||
db.exec(`
|
||||
CREATE TABLE ai_interpretations_new (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
user_id INTEGER NOT NULL,
|
||||
analysis_id TEXT NOT NULL,
|
||||
analysis_type TEXT NOT NULL CHECK (analysis_type IN ('bazi', 'ziwei', 'yijing')),
|
||||
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
|
||||
)
|
||||
`);
|
||||
|
||||
// 2. 复制数据到新表(将INTEGER转换为TEXT)
|
||||
db.exec(`
|
||||
INSERT INTO ai_interpretations_new
|
||||
(id, user_id, analysis_id, analysis_type, content, model, tokens_used, success, error_message, created_at, updated_at)
|
||||
SELECT
|
||||
id, user_id, CAST(analysis_id AS TEXT), analysis_type, content, model, tokens_used, success, error_message, created_at, updated_at
|
||||
FROM ai_interpretations
|
||||
`);
|
||||
|
||||
// 3. 删除旧表
|
||||
db.exec('DROP TABLE ai_interpretations');
|
||||
|
||||
// 4. 重命名新表
|
||||
db.exec('ALTER TABLE ai_interpretations_new RENAME TO ai_interpretations');
|
||||
|
||||
// 5. 重新创建索引
|
||||
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_analysis_id ON ai_interpretations(analysis_id)');
|
||||
db.exec('CREATE INDEX IF NOT EXISTS idx_ai_interpretations_created_at ON ai_interpretations(created_at DESC)');
|
||||
|
||||
// 提交事务
|
||||
db.exec('COMMIT');
|
||||
|
||||
console.log('ai_interpretations表迁移完成');
|
||||
|
||||
} catch (error) {
|
||||
// 回滚事务
|
||||
try {
|
||||
db.exec('ROLLBACK');
|
||||
} catch (rollbackError) {
|
||||
console.error('回滚失败:', rollbackError);
|
||||
}
|
||||
|
||||
console.error('迁移失败:', error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
// 如果直接运行此脚本
|
||||
if (require.main === module) {
|
||||
try {
|
||||
migrateAiInterpretationsTable();
|
||||
console.log('迁移成功完成');
|
||||
process.exit(0);
|
||||
} catch (error) {
|
||||
console.error('迁移失败:', error);
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = { migrateAiInterpretationsTable };
|
||||
171
server/scripts/refactorAiInterpretations.cjs
Normal file
171
server/scripts/refactorAiInterpretations.cjs
Normal file
@@ -0,0 +1,171 @@
|
||||
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 };
|
||||
Reference in New Issue
Block a user