import fs from 'node:fs'; import assert from 'node:assert/strict'; import { login, call } from './role-permissions-live.mjs'; import { scripts, scriptDefinition } from '../../unreal_tran_web/src/features/virtual-training-scripts/definition.js'; // Explicitly run to register/migrate these four tasks. Existing task codes and IDs are preserved. const session = await login('root'); const api = async (endpoint, body, method) => { const r = await call(`tran/v1/${endpoint}`, session.accessToken, body, method); assert.equal(r.status, 200, `${endpoint}: ${r.message}`); return r.data; }; const registered = []; for (const script of scripts) { const tasks = await api(`teaching/assignments?channel=VIRTUAL&assignmentKind=TRAINING&keyword=${script.code}&size=100`); let task = tasks.records.find(item => item.code === script.code); if (task) assert.equal(task.definitionSnapshot.runtime?.scriptId, script.id, 'Refuse to replace an unrelated task'); let detail = task ? await api(`content/projects/${task.contentProjectId}`) : null; if (!detail) { const found = await api(`content/projects?type=TRAINING&keyword=${encodeURIComponent(script.title)}&size=100`); for (const candidate of found.records) { const item = await api(`content/projects/${candidate.id}`); if (item.currentVersion.content?.runtime?.scriptId === script.id) { detail = item; break; } } } const correct = task?.definitionSnapshot.runtime?.definitionSource === 'SCRIPT' && task?.definitionSnapshot.runtime?.scriptVersion === script.version && task.executionMode === 'PRACTICE'; if (task?.status === 'PUBLISHED' && !correct) task = await api(`teaching/assignments/${task.id}/withdraw`, { version: task.version, reason: '静态 JS 作为流程来源,恢复普通训练与成绩评定' }); const projectCommand = { type: 'TRAINING', name: script.title, description: `原稿:${script.source}`, categoryCode: 'MAINTENANCE', trainingMode: 'VIRTUAL', content: scriptDefinition(script), dependencies: [], assets: [], changeSummary: '脚本来源 v2:复用正式教学运行、步骤记录与成绩评定' }; if (!detail) detail = await api('content/projects', projectCommand); else if (detail.currentVersion.content?.runtime?.definitionSource !== 'SCRIPT' || detail.currentVersion.content?.runtime?.scriptVersion !== script.version) { detail = await api(`content/projects/${detail.project.id}`, { ...projectCommand, version: detail.project.version }, 'PUT'); } let project = detail.project; if (project.publishedVersionId !== detail.currentVersion.id) { project = (await api(`content/projects/${project.id}/publish`, { version: project.version })).project; } const command = { code: script.code, name: script.title, description: `原稿:${script.source}`, channel: 'VIRTUAL', assignmentKind: 'TRAINING', executionMode: 'PRACTICE', audienceType: 'COMMON', collaborationMode: 'INDIVIDUAL', digitalHumanAllowed: false, contentProjectId: project.id, contentVersionId: project.publishedVersionId, members: [] }; if (!task) task = await api('teaching/assignments', command); else if (!correct || task.contentVersionId !== project.publishedVersionId) { assert.ok(['DRAFT', 'WITHDRAWN'].includes(task.status)); task = await api(`teaching/assignments/${task.id}`, { ...command, version: task.version }, 'PUT'); } if (task.status !== 'PUBLISHED') task = await api(`teaching/assignments/${task.id}/publish`, { version: task.version }); assert.equal(task.executionMode, 'PRACTICE'); assert.equal(task.definitionSnapshot.runtime.definitionSource, 'SCRIPT'); registered.push({ code: script.code, id: task.id, projectId: project.id, versionId: task.contentVersionId, name: script.title, scriptId: script.id, scriptVersion: script.version, steps: script.steps.length, previewUrl: `/teaching/virtual-training/preview/${task.id}`, presentation: script.presentation }); console.log(JSON.stringify(registered.at(-1))); } fs.mkdirSync('reports/bridge-scripted-tasks-20260913', { recursive: true }); fs.writeFileSync('reports/bridge-scripted-tasks-20260913/registered.json', JSON.stringify(registered, null, 2));