選択できるのは25トピックまでです。 トピックは、先頭が英数字で、英数字とダッシュ('-')を使用した35文字以内のものにしてください。
 
 
 
 

60 行
4.1 KiB

  1. import fs from 'node:fs';
  2. import assert from 'node:assert/strict';
  3. import { login, call } from './role-permissions-live.mjs';
  4. import { scripts, scriptDefinition } from '../../unreal_tran_web/src/features/virtual-training-scripts/definition.js';
  5. // Explicitly run to register/migrate these four tasks. Existing task codes and IDs are preserved.
  6. const session = await login('root');
  7. const api = async (endpoint, body, method) => {
  8. const r = await call(`tran/v1/${endpoint}`, session.accessToken, body, method);
  9. assert.equal(r.status, 200, `${endpoint}: ${r.message}`); return r.data;
  10. };
  11. const registered = [];
  12. for (const script of scripts) {
  13. const tasks = await api(`teaching/assignments?channel=VIRTUAL&assignmentKind=TRAINING&keyword=${script.code}&size=100`);
  14. let task = tasks.records.find(item => item.code === script.code);
  15. if (task) assert.equal(task.definitionSnapshot.runtime?.scriptId, script.id, 'Refuse to replace an unrelated task');
  16. let detail = task ? await api(`content/projects/${task.contentProjectId}`) : null;
  17. if (!detail) {
  18. const found = await api(`content/projects?type=TRAINING&keyword=${encodeURIComponent(script.title)}&size=100`);
  19. for (const candidate of found.records) {
  20. const item = await api(`content/projects/${candidate.id}`);
  21. if (item.currentVersion.content?.runtime?.scriptId === script.id) { detail = item; break; }
  22. }
  23. }
  24. const correct = task?.definitionSnapshot.runtime?.definitionSource === 'SCRIPT'
  25. && task?.definitionSnapshot.runtime?.scriptVersion === script.version && task.executionMode === 'PRACTICE';
  26. if (task?.status === 'PUBLISHED' && !correct) task = await api(`teaching/assignments/${task.id}/withdraw`,
  27. { version: task.version, reason: '静态 JS 作为流程来源,恢复普通训练与成绩评定' });
  28. const projectCommand = { type: 'TRAINING', name: script.title, description: `原稿:${script.source}`,
  29. categoryCode: 'MAINTENANCE', trainingMode: 'VIRTUAL', content: scriptDefinition(script), dependencies: [], assets: [],
  30. changeSummary: '脚本来源 v2:复用正式教学运行、步骤记录与成绩评定' };
  31. if (!detail) detail = await api('content/projects', projectCommand);
  32. else if (detail.currentVersion.content?.runtime?.definitionSource !== 'SCRIPT'
  33. || detail.currentVersion.content?.runtime?.scriptVersion !== script.version) {
  34. detail = await api(`content/projects/${detail.project.id}`, { ...projectCommand, version: detail.project.version }, 'PUT');
  35. }
  36. let project = detail.project;
  37. if (project.publishedVersionId !== detail.currentVersion.id) {
  38. project = (await api(`content/projects/${project.id}/publish`, { version: project.version })).project;
  39. }
  40. const command = { code: script.code, name: script.title, description: `原稿:${script.source}`,
  41. channel: 'VIRTUAL', assignmentKind: 'TRAINING', executionMode: 'PRACTICE', audienceType: 'COMMON',
  42. collaborationMode: 'INDIVIDUAL', digitalHumanAllowed: false, contentProjectId: project.id,
  43. contentVersionId: project.publishedVersionId, members: [] };
  44. if (!task) task = await api('teaching/assignments', command);
  45. else if (!correct || task.contentVersionId !== project.publishedVersionId) {
  46. assert.ok(['DRAFT', 'WITHDRAWN'].includes(task.status));
  47. task = await api(`teaching/assignments/${task.id}`, { ...command, version: task.version }, 'PUT');
  48. }
  49. if (task.status !== 'PUBLISHED') task = await api(`teaching/assignments/${task.id}/publish`, { version: task.version });
  50. assert.equal(task.executionMode, 'PRACTICE');
  51. assert.equal(task.definitionSnapshot.runtime.definitionSource, 'SCRIPT');
  52. registered.push({ code: script.code, id: task.id, projectId: project.id, versionId: task.contentVersionId,
  53. name: script.title, scriptId: script.id, scriptVersion: script.version, steps: script.steps.length,
  54. previewUrl: `/teaching/virtual-training/preview/${task.id}`, presentation: script.presentation });
  55. console.log(JSON.stringify(registered.at(-1)));
  56. }
  57. fs.mkdirSync('reports/bridge-scripted-tasks-20260913', { recursive: true });
  58. fs.writeFileSync('reports/bridge-scripted-tasks-20260913/registered.json', JSON.stringify(registered, null, 2));