Files
massive-cloud/scripts/migrate-inspection-objects.ts

61 lines
4.9 KiB
TypeScript

import mysql from 'mysql2/promise';
type Mapping = { modelId: number; objectName: string; pointclouds: string[]; defaultPointcloud: string; cadFiles: string[]; defaultCad: string };
const mappings: Mapping[] = [
{ modelId: 1, objectName: '中间车', pointclouds: ['1_10.ply', '1_11.ply', '1_12.ply'], defaultPointcloud: '1_10.ply', cadFiles: ['train_1_mesh.ply'], defaultCad: 'train_1_mesh.ply' },
{ modelId: 2, objectName: '头车', pointclouds: ['2_10.ply', '2_11.ply', '2_12.ply', 'train_2_10M.ply', 'train_2_1T.ply'], defaultPointcloud: '2_10.ply', cadFiles: ['m000004802418tc01_asm.stp', 'train_2_mesh.ply'], defaultCad: 'm000004802418tc01_asm.stp' },
];
const connectionString = process.env.DATABASE_URL;
if (!connectionString) throw new Error('DATABASE_URL is required');
const connection = await mysql.createConnection(connectionString);
let createdObjects = 0;
let assignedPointclouds = 0;
let assignedCads = 0;
let classifiedTasks = 0;
const warnings: Array<{ taskId: number; reason: string }> = [];
const conflicts: string[] = [];
try {
await connection.beginTransaction();
for (const mapping of mappings) {
const [existing] = await connection.query<mysql.RowDataPacket[]>('SELECT id FROM inspection_objects WHERE modelId=? AND name=?', [mapping.modelId, mapping.objectName]);
if (existing.length === 0) {
await connection.execute('INSERT INTO inspection_objects (modelId,name,status) VALUES (?,?,\'draft\')', [mapping.modelId, mapping.objectName]);
createdObjects += 1;
}
const [objectRows] = await connection.query<mysql.RowDataPacket[]>('SELECT id FROM inspection_objects WHERE modelId=? AND name=?', [mapping.modelId, mapping.objectName]);
const objectId = Number(objectRows[0].id);
for (const name of mapping.pointclouds) {
const [rows] = await connection.query<mysql.RowDataPacket[]>('SELECT id,inspectionObjectId FROM model_pointcloud_files WHERE modelId=? AND name=?', [mapping.modelId, name]);
if (rows.length !== 1) { conflicts.push(`点云 model=${mapping.modelId} name=${name} 匹配数量=${rows.length}`); continue; }
if (rows[0].inspectionObjectId && Number(rows[0].inspectionObjectId) !== objectId) { conflicts.push(`点云 ${name} 已属于其他检测对象`); continue; }
if (!rows[0].inspectionObjectId) { await connection.execute('UPDATE model_pointcloud_files SET inspectionObjectId=?,status=\'available\' WHERE id=?', [objectId, rows[0].id]); assignedPointclouds += 1; }
}
for (const name of mapping.cadFiles) {
const [rows] = await connection.query<mysql.RowDataPacket[]>('SELECT id FROM model_cad_files WHERE modelId=? AND name=?', [mapping.modelId, name]);
if (rows.length !== 1) { conflicts.push(`CAD model=${mapping.modelId} name=${name} 匹配数量=${rows.length}`); continue; }
const [result] = await connection.execute<mysql.ResultSetHeader>('INSERT IGNORE INTO model_cad_inspection_objects (cadFileId,inspectionObjectId) VALUES (?,?)', [rows[0].id, objectId]);
assignedCads += result.affectedRows;
}
const [[defaultPc]] = await connection.query<mysql.RowDataPacket[]>('SELECT id FROM model_pointcloud_files WHERE modelId=? AND name=? AND inspectionObjectId=?', [mapping.modelId, mapping.defaultPointcloud, objectId]);
const [[defaultCad]] = await connection.query<mysql.RowDataPacket[]>('SELECT c.id FROM model_cad_files c JOIN model_cad_inspection_objects r ON r.cadFileId=c.id WHERE c.modelId=? AND c.name=? AND r.inspectionObjectId=?', [mapping.modelId, mapping.defaultCad, objectId]);
if (defaultPc && defaultCad) await connection.execute('UPDATE inspection_objects SET defaultModelPointcloudId=?,defaultModelCadFileId=?,status=\'active\' WHERE id=?', [defaultPc.id, defaultCad.id, objectId]);
else conflicts.push(`${mapping.objectName} 默认输入方案资源不完整`);
}
const [tasks] = await connection.query<mysql.RowDataPacket[]>('SELECT id FROM inspection_tasks WHERE inspectionObjectId IS NULL ORDER BY id');
for (const task of tasks) {
const [sources] = await connection.query<mysql.RowDataPacket[]>('SELECT DISTINCT mp.inspectionObjectId FROM task_pointcloud_files tp JOIN model_pointcloud_files mp ON mp.id=tp.sourceModelPointcloudId WHERE tp.taskId=? AND mp.inspectionObjectId IS NOT NULL', [task.id]);
if (sources.length === 1) { await connection.execute('UPDATE inspection_tasks SET inspectionObjectId=? WHERE id=? AND inspectionObjectId IS NULL', [sources[0].inspectionObjectId, task.id]); classifiedTasks += 1; }
else warnings.push({ taskId: Number(task.id), reason: sources.length > 1 ? '包含不同检测对象的车型库点云' : '无可推断的车型库来源点云' });
}
await connection.commit();
console.log(JSON.stringify({ createdObjects, assignedPointclouds, assignedCads, classifiedTasks, unclassifiedTasks: warnings, conflicts }, null, 2));
} catch (error) {
await connection.rollback();
throw error;
} finally {
await connection.end();
}