You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

39 line
3.6 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} from '../../unreal_tran_web/src/features/virtual-training-scripts/definition.js';
  5. const dir='reports/bridge-006-hose-connections-20260921';fs.mkdirSync(dir,{recursive:true});
  6. const signed=await login('root');
  7. const api=async(path,data,method)=>{const r=await call('tran/v1/'+path,signed.accessToken,data,method);assert.equal(r.status,200,path+': '+r.message);return r.data;};
  8. const backup=(name,value)=>{const file=dir+'/'+name+'.json';if(!fs.existsSync(file))fs.writeFileSync(file,JSON.stringify(value,null,2));};
  9. let task=await api('teaching/assignments/87'),project=await api('content/projects/'+task.contentProjectId);
  10. assert.equal(task.code,'TASK-VIRTUAL-006');assert.equal(task.definitionSnapshot.runtime.scriptVersion,'4');
  11. backup('before-task',task);backup('before-project',project);
  12. const previous=JSON.parse(fs.readFileSync(dir+'/before-task.json'));
  13. const expected=scripts.find(s=>s.code===task.code).definition.steps[1];
  14. if(JSON.stringify(task.definitionSnapshot.steps[1].action)!==JSON.stringify(expected.action)){
  15. const runs=await api('teaching/runs?assignmentId=87&size=100');
  16. assert.equal(runs.total,0,'Only migrate this unused task; do not interrupt active learners');
  17. const content=structuredClone(project.currentVersion.content);
  18. content.steps[1]={...content.steps[1],action:expected.action,targetName:expected.targetName,guidance:expected.guidance};
  19. content.scenario.operableParts=[...new Set(content.steps.flatMap(step=>step.action.mechanism.steps.map(op=>op.targetId)))];
  20. if(JSON.stringify(project.currentVersion.content.steps[1].action)!==JSON.stringify(expected.action)){
  21. assert.equal(project.currentVersion.id,project.project.publishedVersionId,'Do not overwrite an unrelated unpublished draft');
  22. project=await api('content/projects/'+project.project.id,{...project.project,content,assets:project.currentVersion.assets,dependencies:project.currentVersion.dependencies,version:project.project.version,changeSummary:'006软管连接修正:两车防尘盖与供回油软管四个端头分开操作,保留讲解、准备项与评分规则'},'PUT');
  23. }
  24. if(project.project.publishedVersionId!==project.currentVersion.id)project=await api('content/projects/'+project.project.id+'/publish',{version:project.project.version});
  25. if(task.status==='PUBLISHED')task=await api('teaching/assignments/87/withdraw',{version:task.version,reason:'修正软管连接操作,保留原任务及旧内容版本'});
  26. assert.ok(['DRAFT','WITHDRAWN'].includes(task.status));
  27. task=await api('teaching/assignments/87',{...task,contentVersionId:project.project.publishedVersionId,version:task.version},'PUT');
  28. task=await api('teaching/assignments/87/publish',{version:task.version});
  29. }
  30. assert.equal(task.status,'PUBLISHED');assert.deepEqual(task.definitionSnapshot.steps[1].action,expected.action);
  31. for(let i=0;i<7;i++){
  32. if(i!==1)assert.deepEqual(task.definitionSnapshot.steps[i],previous.definitionSnapshot.steps[i]);
  33. else for(const key of ['audio','assessment','stepCode','actionCode','instruction'])assert.deepEqual(task.definitionSnapshot.steps[i][key],previous.definitionSnapshot.steps[i][key]);
  34. }
  35. assert.deepEqual(task.members,previous.members);
  36. fs.writeFileSync(dir+'/after-task.json',JSON.stringify(task,null,2));
  37. fs.writeFileSync(dir+'/migration.json',JSON.stringify({pass:true,id:task.id,oldContentVersion:previous.contentVersionId,newContentVersion:task.contentVersionId,operations:6,runCount:task.runCount},null,2));
  38. console.log('006 published content version',task.contentVersionId);