openlearn-next 0.7.6 → 0.7.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +66 -150
- package/dist/assets/{AcademicYearFilter-DUUGpDKt.js → AcademicYearFilter-Dm3no4Nb.js} +1 -1
- package/dist/assets/ActivityWorkspaceWidget-BXS1IamH.js +1 -0
- package/dist/assets/{AdminDirectoryView-DL9zZi-_.js → AdminDirectoryView-479SfYyD.js} +2 -2
- package/dist/assets/{AssessmentCenter-B2JzXBGe.js → AssessmentCenter-CJ-pchOQ.js} +1 -1
- package/dist/assets/{AssignmentFilePreview-Bk751Blz.js → AssignmentFilePreview-wjnrKjsp.js} +1 -1
- package/dist/assets/{BatchPickerModal-9ekXDUUj.js → BatchPickerModal-JvoD-1pF.js} +1 -1
- package/dist/assets/{ClassesView-PCt8I3MU.js → ClassesView-CB8q2kW0.js} +12 -12
- package/dist/assets/ClassroomCountdownWidget-BqzBpAvi.js +2 -0
- package/dist/assets/{CloudDriveModal-Mp59sr-C.js → CloudDriveModal-DHxOnL4m.js} +1 -1
- package/dist/assets/ComputerLabView-BEDe7WiU.js +1 -0
- package/dist/assets/CourseManagement-BjxQC6sq.js +1 -0
- package/dist/assets/{CourseWizardModal-B7-e8otR.js → CourseWizardModal-D3UPFtT_.js} +2 -2
- package/dist/assets/{CoursewareHubPanel-DLjH-UzF.js → CoursewareHubPanel-CqJqcZGs.js} +1 -1
- package/dist/assets/{Dashboard-D3LXLQNC.js → Dashboard-C3BaEHIG.js} +2 -2
- package/dist/assets/{ExportWeightModal-vd7XgaJ0.js → ExportWeightModal-iF0pVevG.js} +1 -1
- package/dist/assets/{HelpTour-BLuiS8rr.js → HelpTour-6ChRqWnB.js} +1 -1
- package/dist/assets/{HelpView-C4BHoNqR.js → HelpView-D3iYhzBz.js} +2 -2
- package/dist/assets/ImportLessonsModal-BOwj7ezj.js +1 -0
- package/dist/assets/{ImportModal-H5s5MyZY.js → ImportModal-DAHGdI9h.js} +1 -1
- package/dist/assets/{InteractiveCoursewareViewer-D9GzG28E.js → InteractiveCoursewareViewer-DX9xnk6j.js} +1 -1
- package/dist/assets/InteractiveWhiteboard-41mi9keH.js +65 -0
- package/dist/assets/LazyCourseware-DKyUHXaE.js +2 -0
- package/dist/assets/LazyWhiteboard-fXS2P44c.js +2 -0
- package/dist/assets/LessonEditorView-Dx-hOKtt.js +1 -0
- package/dist/assets/LiveClassroomView-m0hKdcVK.js +61 -0
- package/dist/assets/NotificationDetailModal-C2tg_IoJ.js +1 -0
- package/dist/assets/PluginView-BPRUpCjV.js +77 -0
- package/dist/assets/{ProcessLogsModal-_BwkmJVw.js → ProcessLogsModal-CULHzXp7.js} +1 -1
- package/dist/assets/{QuizGeneratorModal-DiItok6z.js → QuizGeneratorModal-CYxngpW9.js} +1 -1
- package/dist/assets/StudentAssignmentEvalPanel-Dfe4IOs5.js +1 -0
- package/dist/assets/{StudentAssignmentView-UK_7_MF3.js → StudentAssignmentView-IfRo3yJk.js} +1 -1
- package/dist/assets/StudentLessonView-Dw2uxBhq.js +1 -0
- package/dist/assets/StudentView-DVYUSrVU.js +2 -0
- package/dist/assets/{SystemResourceLibraryModal-dEdNKbk2.js → SystemResourceLibraryModal-BhbpfIBt.js} +1 -1
- package/dist/assets/TeacherView-CZjIejet.js +2 -0
- package/dist/assets/{TimetableView-AkReskNG.js → TimetableView-CupOIfEy.js} +1 -1
- package/dist/assets/{UTIF-4E-wdh3X.js → UTIF-BtQhea94.js} +1 -1
- package/dist/assets/index-BDFyco9S.css +1 -0
- package/dist/assets/index-BiHQqzdm.js +131 -0
- package/dist/assets/{index.es-WXdI0L-F.js → index.es-CijVATXs.js} +1 -1
- package/dist/assets/{pluginParsers-k90WUDrU.js → pluginParsers-C9W6GBVx.js} +1 -1
- package/dist/assets/{student-workspace-BDw1i4Vl.js → student-workspace-CsbA8Cs4.js} +1 -1
- package/dist/assets/{vendor-charts-SrpBsvM3.js → vendor-charts-skggaP9D.js} +1 -1
- package/dist/assets/{vendor-icons-hc6MjYFv.js → vendor-icons-DaYNfRAc.js} +2 -2
- package/dist/assets/{vendor-konva-Dne0Z-WC.js → vendor-konva-BOuJWFuE.js} +1 -1
- package/dist/assets/{vendor-pdf-By0fofA0.js → vendor-pdf-DVWGghIL.js} +3 -3
- package/dist/assets/{vendor-pptx-EjNUtdws.js → vendor-pptx-BqU7v5zS.js} +5 -5
- package/dist/assets/{vendor-react-Kv_JATwr.js → vendor-react-DHoBZpn2.js} +2 -2
- package/dist/assets/{vendor-utils-aM7aYvPP.js → vendor-utils-BxOuk3id.js} +1 -1
- package/dist/env-validation.cjs +7 -1
- package/dist/index.html +6 -6
- package/dist/server.cjs +343 -37
- package/migrations/044_students_gender.sql +8 -0
- package/migrations/README.md +1 -0
- package/migrations/schema-golden.json +3 -2
- package/package.json +2 -2
- package/dist/assets/ActivityWorkspaceWidget-0DUqiqFK.js +0 -1
- package/dist/assets/ClassroomCountdownWidget-HxelcHUp.js +0 -2
- package/dist/assets/ComputerLabView-FStILvFC.js +0 -1
- package/dist/assets/CourseManagement-BQw2idgZ.js +0 -1
- package/dist/assets/ImportLessonsModal-Y6uIIemO.js +0 -1
- package/dist/assets/InteractiveWhiteboard-DswIV-ES.js +0 -65
- package/dist/assets/LazyCourseware-BEoTTg5h.js +0 -2
- package/dist/assets/LazyWhiteboard-CMBBxnFX.js +0 -2
- package/dist/assets/LessonEditorView-BgJtG8Ks.js +0 -1
- package/dist/assets/LiveClassroomView-Czwt5WW-.js +0 -61
- package/dist/assets/NotificationDetailModal-D42vEs3S.js +0 -1
- package/dist/assets/PluginView-BcOWIjLu.js +0 -77
- package/dist/assets/StudentAssignmentEvalPanel-DHoZc3g0.js +0 -1
- package/dist/assets/StudentLessonView-C11Qkdi_.js +0 -1
- package/dist/assets/StudentView-j0hx3IOi.js +0 -2
- package/dist/assets/TeacherView-COZw2tFl.js +0 -2
- package/dist/assets/index-DN3E-Fmw.js +0 -131
- package/dist/assets/index-DPky2leG.css +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{j as e}from"./vendor-react-DHoBZpn2.js";import{m as $,C as P}from"./index-BiHQqzdm.js";import{ac as b,J as D,aW as T,aX as O,c as u,h as V,ad as f}from"./vendor-icons-DaYNfRAc.js";import"./vendor-utils-BxOuk3id.js";import"./vendor-pdf-DVWGghIL.js";import"./vendor-motion-BFAPOs-b.js";import"./vendor-charts-skggaP9D.js";const j=Math.round(P/(1024*1024));function _(y){const{isImportLessonsOpen:N,setIsImportLessonsOpen:o,lang:s,importStatus:a,setIsDraggingImport:m,handleCSVFileChange:F,handleImportFileChange:h,downloadCsvTemplate:v,downloadCourseTemplate:w,packagePreview:t,handlePackageImportSubmit:p,packageDuplicate:n=null,handlePackageDuplicateDismiss:k=()=>{},isDraggingImport:C,previewImportData:l,setPreviewImportData:g,setImportStatus:d,importProgress:i,importProgressTotal:c,importErrorMsg:z,setImportErrorMsg:S,handleCSVImportSubmit:I}=y;return e.jsx(e.Fragment,{children:N&&e.jsx("div",{className:"fixed inset-0 bg-gray-900/50 backdrop-blur-sm flex items-center justify-center p-4 md:p-6 z-50 overflow-y-auto text-gray-850",children:e.jsxs($.div,{initial:{opacity:0,y:15,scale:.98},animate:{opacity:1,y:0,scale:1},exit:{opacity:0,y:10,scale:.98},className:"bg-white border text-gray-900 border-gray-250 rounded-2xl shadow-2xl w-full max-w-2xl flex flex-col overflow-hidden max-h-[90vh] font-sans text-left",children:[e.jsxs("div",{className:"p-4 md:p-5 border-b border-gray-100 flex items-center justify-between bg-slate-50 shrink-0",children:[e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsx("div",{className:"p-2 bg-indigo-50 border border-indigo-100 rounded-lg text-indigo-650",children:e.jsx(b,{size:20,className:"animate-pulse"})}),e.jsxs("div",{children:[e.jsx("h2",{className:"font-bold text-gray-850 text-base md:text-lg",children:s==="zh"?"批量导入课程":"Bulk-Import Courses"}),e.jsx("p",{className:"text-xs text-gray-500 mt-0.5",children:s==="zh"?"CSV 为「简易导入」(仅标题与正文);需要教学环节 + 白板组件 + 课件附件的完整课程请用课程包 JSON。":'CSV is a "quick import" (title and body only). For a complete lesson — segments, whiteboard components and assets — use a course package JSON.'})]})]}),e.jsx("button",{onClick:()=>{a!=="importing"&&o(!1)},disabled:a==="importing",className:"text-gray-400 hover:text-gray-650 font-bold p-1 rounded-lg hover:bg-gray-150 transition-all text-xl leading-none disabled:opacity-40",children:"×"})]}),e.jsxs("div",{className:"flex-1 overflow-y-auto p-6 space-y-5",children:[a==="idle"&&e.jsxs("div",{className:"space-y-4",children:[e.jsxs("div",{className:"p-4 bg-indigo-50/50 border border-indigo-100 rounded-xl",children:[e.jsxs("h4",{className:"text-xs font-bold text-indigo-850 uppercase tracking-wide flex items-center gap-2",children:[e.jsx("span",{children:"📌"}),s==="zh"?"简易导入(CSV)":"Quick import (CSV)",e.jsx("span",{className:"text-[10px] font-mono font-normal normal-case tracking-normal text-indigo-700 bg-indigo-100 border border-indigo-200 rounded px-1.5 py-0.5","data-testid":"csv-simple-import-badge",children:s==="zh"?"仅标题 + 正文":"title + body only"})]}),e.jsx("p",{className:"text-xs text-indigo-900 mt-1 leading-relaxed",children:s==="zh"?"CSV 文件的首行必须定义列标题(不区分大小写、无多余空格),包含以下两项必需内容:":"Your CSV file must include exactly these header columns on the first row (case-insensitive):"}),e.jsxs("ul",{className:"list-disc pl-5 mt-2 text-xs text-indigo-950 space-y-1",children:[e.jsxs("li",{children:[e.jsx("strong",{children:"title"}),":"," ",s==="zh"?'课程名 (非空,例如 "代数几何")':'Course title (Required, e.g. "Linear Algebra")']}),e.jsxs("li",{children:[e.jsx("strong",{children:"content"}),":"," ",s==="zh"?"教学大纲 / Markdown 格式的课堂细目":"Syllabus content supporting rich markdown."]})]}),e.jsxs("div",{className:"mt-3.5 flex flex-wrap gap-2 justify-start",children:[e.jsxs("button",{onClick:v,className:"flex items-center gap-1 p-2 text-xs font-bold text-indigo-700 bg-white border border-indigo-200 rounded-lg shadow-3xs hover:bg-indigo-50 hover:-translate-y-0.5 hover:shadow-xs transition-all cursor-pointer",children:[e.jsx(D,{size:12}),s==="zh"?"获取标准 CSV 模板":"Download Template CSV"]}),e.jsxs("button",{onClick:w,"data-testid":"download-course-package-template-btn",className:"flex items-center gap-1 p-2 text-xs font-bold text-emerald-700 bg-white border border-emerald-200 rounded-lg shadow-3xs hover:bg-emerald-50 hover:-translate-y-0.5 hover:shadow-xs transition-all cursor-pointer",children:[e.jsx(T,{size:12}),s==="zh"?"下载课程模板(JSON)":"Download Course Template (JSON)"]})]}),e.jsx("p",{className:"text-[11px] text-indigo-800/80 mt-2.5 leading-relaxed",children:s==="zh"?"课程模板是一个自包含的 JSON 文件:包含教学环节、全部预设组件的白板元素,以及内嵌的 PDF / PPTX 课件附件 —— 拖回本对话框即可导入成一节完整的课。完整课程统一走这条通道,CSV 只做批量建空壳。":"The course template is a self-contained JSON file: teaching segments, whiteboard elements for every preset component, and embedded PDF/PPTX assets — drop it back here to import a complete lesson. Complete lessons go through this path; CSV only creates shells in bulk."})]}),e.jsxs("div",{onDragOver:r=>{r.preventDefault(),m(!0)},onDragLeave:()=>m(!1),onDrop:r=>{r.preventDefault(),m(!1),r.dataTransfer.files&&r.dataTransfer.files[0]&&h(r.dataTransfer.files[0])},onClick:()=>{document.getElementById("import-csv-file-picker")?.click()},className:`border-2 border-dashed rounded-2xl p-8 text-center cursor-pointer transition-all flex flex-col items-center justify-center min-h-[180px] ${C?"border-indigo-500 bg-indigo-50/70 scale-[1.01]":"border-gray-250 bg-gray-50/50 hover:bg-gray-50 hover:border-indigo-400"}`,children:[e.jsx("input",{id:"import-csv-file-picker",type:"file",accept:".csv,.json",className:"hidden",onChange:r=>{r.target.files&&r.target.files[0]&&h(r.target.files[0])}}),e.jsx("div",{className:"p-3 bg-gray-100 border border-gray-200 rounded-full text-indigo-600 mb-3 group-hover:scale-105 transition-all",children:e.jsx(b,{size:24})}),e.jsx("span",{className:"text-sm font-bold text-gray-800",children:s==="zh"?"选择 CSV / 课程包 JSON 文件,或拖放至此处":"Click to select or drag and drop a CSV / course-package JSON file here"}),e.jsx("span",{className:"text-xs text-gray-400 mt-1",children:s==="zh"?`CSV(简易导入)或课程包 JSON(完整课程),单文件最大 ${j}MB`:`CSV (quick import) or course-package JSON (full lesson), up to ${j}MB`})]})]}),a==="parsing"&&t&&e.jsxs("div",{className:"space-y-4","data-testid":"course-package-preview",children:[e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsxs("span",{className:"text-xs font-bold text-emerald-600 bg-emerald-50 border border-emerald-200 px-2.5 py-1 rounded-full",children:["✓"," ",s==="zh"?`课程包解析成功:${t.segments} 个教学环节 · ${t.elements} 个白板元素`:`Course package parsed: ${t.segments} segments · ${t.elements} elements`]}),e.jsx("button",{onClick:()=>{g([]),d("idle")},className:"text-xs text-indigo-600 hover:text-indigo-800 font-semibold",children:s==="zh"?"重新上传":"Upload Different File"})]}),e.jsxs("div",{className:"p-4 bg-white border border-gray-200 rounded-xl shadow-3xs",children:[e.jsxs("div",{className:"flex items-start gap-3",children:[e.jsx("div",{className:"p-2 bg-emerald-50 border border-emerald-100 rounded-lg text-emerald-600",children:e.jsx(O,{size:18})}),e.jsxs("div",{className:"min-w-0 flex-1",children:[e.jsx("h4",{className:"text-sm font-bold text-gray-800 truncate",title:t.title,children:t.title}),t.metaName&&e.jsx("p",{className:"text-[11px] text-gray-500 mt-0.5 truncate",children:t.metaName}),e.jsx("p",{className:"text-[11px] text-gray-400 mt-0.5 font-mono truncate",children:t.fileName})]})]}),e.jsxs("dl",{className:"grid grid-cols-3 gap-2 mt-3",children:[e.jsxs("div",{className:"p-2 bg-gray-50 border border-gray-150 rounded-lg",children:[e.jsx("dt",{className:"text-[10px] text-gray-500 font-semibold",children:s==="zh"?"教学环节":"Segments"}),e.jsx("dd",{className:"text-base font-bold text-gray-800",children:t.segments})]}),e.jsxs("div",{className:"p-2 bg-gray-50 border border-gray-150 rounded-lg",children:[e.jsx("dt",{className:"text-[10px] text-gray-500 font-semibold",children:s==="zh"?"白板元素":"Elements"}),e.jsx("dd",{className:"text-base font-bold text-gray-800",children:t.elements})]}),e.jsxs("div",{className:"p-2 bg-gray-50 border border-gray-150 rounded-lg",children:[e.jsx("dt",{className:"text-[10px] text-gray-500 font-semibold",children:s==="zh"?"课件附件":"Assets"}),e.jsx("dd",{className:"text-base font-bold text-gray-800",children:t.assets})]})]}),t.componentTypes.length>0&&e.jsxs("div",{className:"mt-3",children:[e.jsx("p",{className:"text-[10px] text-gray-500 font-semibold mb-1.5",children:s==="zh"?"覆盖的预设组件":"Covered components"}),e.jsx("div",{className:"flex flex-wrap gap-1",children:t.componentTypes.map(r=>e.jsx("span",{className:"px-1.5 py-0.5 rounded bg-indigo-50 border border-indigo-100 text-[10px] font-mono text-indigo-700",children:r},r))})]})]}),e.jsxs("div",{className:"bg-amber-50 border border-amber-100 text-amber-900 text-xs rounded-xl p-3 flex gap-2.5 items-start",children:[e.jsx("span",{className:"text-base leading-none",children:"⚠️"}),e.jsx("p",{className:"leading-relaxed",children:s==="zh"?"导入将以单个事务写入:教学环节、白板元素与课件附件要么全部成功,要么全部回滚,不会留下半截课程。":"The import runs as a single transaction: segments, whiteboard elements and assets are either all written or all rolled back."})]})]}),a==="parsing"&&!t&&l.length>0&&e.jsxs("div",{className:"space-y-4",children:[e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsxs("span",{className:"text-xs font-bold text-emerald-600 bg-emerald-50 border border-emerald-200 px-2.5 py-1 rounded-full",children:["✓"," ",s==="zh"?`解析成功:查找到 ${l.length} 门课程`:`Parsed Successfully: Found ${l.length} records`]}),e.jsx("button",{onClick:()=>{g([]),d("idle")},className:"text-xs text-indigo-600 hover:text-indigo-800 font-semibold",children:s==="zh"?"重新上传":"Upload Different File"})]}),e.jsx("div",{className:"border border-gray-200 rounded-xl overflow-hidden shadow-3xs max-h-[300px] overflow-y-auto",children:e.jsxs("table",{className:"w-full text-left text-xs border-collapse",children:[e.jsx("thead",{className:"bg-gray-50 text-gray-600 border-b border-gray-200 font-bold",children:e.jsxs("tr",{children:[e.jsx("th",{className:"p-3 w-1/4",children:s==="zh"?"课程名称":"Course Title"}),e.jsx("th",{className:"p-3 w-3/4",children:s==="zh"?"大纲简介片段":"Syllabus Preview"})]})}),e.jsx("tbody",{className:"divide-y divide-gray-100 bg-white",children:l.map((r,x)=>e.jsxs("tr",{className:"hover:bg-slate-50/50",children:[e.jsx("td",{className:"p-3 font-semibold text-gray-800 align-top truncate max-w-[150px]",title:r.title,children:r.title}),e.jsx("td",{className:"p-3 text-gray-500 font-mono text-xs leading-relaxed break-words col-span-2",children:r.content.length>150?r.content.substring(0,150)+"...":r.content||e.jsx("em",{className:"text-gray-300 italic",children:"None"})})]},x))})]})}),e.jsxs("div",{className:"bg-amber-50 border border-amber-100 text-amber-900 text-xs rounded-xl p-3 flex gap-2.5 items-start",children:[e.jsx("span",{className:"text-base leading-none",children:"⚠️"}),e.jsx("p",{className:"leading-relaxed",children:s==="zh"?'请确认课程名称没有与系统已有的课程同名。确认无误后点击下方"开始导入"写入 SQLite。':"Please ensure column details are accurate. Clicking Import will instantly commit all parsed courses into the server SQLite backend."})]})]}),a==="importing"&&t&&e.jsxs("div",{className:"py-8 flex flex-col items-center justify-center space-y-4",children:[e.jsx("div",{className:"relative w-20 h-20 flex items-center justify-center",children:e.jsx(u,{size:36,className:"text-indigo-600 animate-spin"})}),e.jsxs("div",{className:"text-center",children:[e.jsx("h3",{className:"font-bold text-gray-800 text-sm",children:s==="zh"?"正在导入课程包":"Importing course package"}),e.jsx("p",{className:"text-xs text-gray-500 mt-1",children:s==="zh"?`正在写入 ${t.segments} 个教学环节、${t.elements} 个白板元素与 ${t.assets} 份课件附件...`:`Writing ${t.segments} segments, ${t.elements} elements and ${t.assets} assets...`})]}),e.jsx("div",{className:"w-full max-w-md bg-gray-50 rounded-xl p-3 border border-gray-150 font-mono text-xs text-gray-400",children:e.jsx("div",{children:"[API] POST /api/course-packages/import -> single transaction..."})})]}),a==="importing"&&!t&&e.jsxs("div",{className:"py-8 flex flex-col items-center justify-center space-y-4",children:[e.jsxs("div",{className:"relative w-20 h-20 flex items-center justify-center",children:[e.jsx(u,{size:36,className:"text-indigo-600 animate-spin"}),e.jsxs("span",{className:"absolute text-xs font-extrabold text-indigo-700",children:[Math.round(i/c*100),"%"]})]}),e.jsxs("div",{className:"text-center",children:[e.jsx("h3",{className:"font-bold text-gray-800 text-sm",children:s==="zh"?"正在写入数据库":"Populating Database Records"}),e.jsx("p",{className:"text-xs text-gray-500 mt-1",children:s==="zh"?`正在导入第 ${i} / ${c} 项...`:`Importing item ${i} of ${c}...`})]}),e.jsx("div",{className:"w-full max-w-sm bg-gray-100 h-2 rounded-full overflow-hidden border border-gray-200",children:e.jsx("div",{className:"bg-indigo-600 h-full transition-all duration-300 rounded-full",style:{width:`${i/c*100}%`}})}),e.jsxs("div",{className:"w-full max-w-md bg-gray-50 rounded-xl p-3 border border-gray-150 font-mono text-xs text-gray-400 max-h-[140px] overflow-y-auto",children:[e.jsx("div",{children:"[API] POST /api/lessons -> one request per course (no cross-course transaction)"}),l.slice(0,i).map((r,x)=>e.jsx("div",{className:"text-indigo-600 font-bold mt-1",children:`✓ [${x+1}] "${r.title}" -> status 200 (Success)`},x))]})]}),a==="success"&&e.jsxs("div",{className:"py-8 text-center flex flex-col items-center justify-center space-y-4",children:[e.jsx("div",{className:"w-16 h-16 bg-emerald-50 rounded-full flex items-center justify-center border border-emerald-200 text-emerald-600 animate-bounce",children:e.jsx(V,{size:32})}),e.jsxs("div",{children:[e.jsx("h3",{className:"font-bold text-gray-800 text-base",children:s==="zh"?"🎉 批量导入大功告成":"🎉 Bulk-Import Complete"}),e.jsx("p",{className:"text-xs text-gray-500 mt-1 max-w-md mx-auto",children:t?s==="zh"?`课程包已导入:${t.segments} 个教学环节、${t.elements} 个白板元素、${t.assets} 份课件附件均已写入。`:`Course package imported: ${t.segments} segments, ${t.elements} elements and ${t.assets} assets written.`:s==="zh"?`所有 ${l.length} 门学科教案数据已顺畅写入系统底层 SQLite 数据仓库,现在已可以用于备课。`:`All ${l.length} curriculum lessons records have been successfully saved into security logs and SQLite storage.`})]})]}),a==="error"&&e.jsxs("div",{className:"space-y-4",children:[n?e.jsxs("div",{className:"p-4 bg-amber-50 border border-amber-100 rounded-xl flex gap-3 items-start","data-testid":"course-package-duplicate-notice",children:[e.jsx("span",{className:"text-amber-600 font-bold text-lg leading-none",children:"⧉"}),e.jsxs("div",{children:[e.jsx("h4",{className:"text-xs font-bold text-amber-850",children:s==="zh"?"该课程包已经导入过了":"This course package was already imported"}),e.jsx("p",{className:"text-xs text-amber-900 mt-1 leading-relaxed",children:s==="zh"?e.jsxs(e.Fragment,{children:["已存在课程「",n.lessonTitle,"」",n.hasDeclaredId?"(同一个课程包 id)":"(内容完全相同)",", 再次导入会得到两节内容相同的课程。"]}):e.jsxs(e.Fragment,{children:['A lesson named "',n.lessonTitle,'" already exists',n.hasDeclaredId?" (same course-package id)":" (identical content)",". Importing again would create two lessons with the same content."]})})]})]}):e.jsxs("div",{className:"p-4 bg-rose-50 border border-rose-100 rounded-xl flex gap-3 items-start",children:[e.jsx("span",{className:"text-rose-600 font-bold text-lg leading-none",children:"⚠️"}),e.jsxs("div",{children:[e.jsx("h4",{className:"text-xs font-bold text-rose-850",children:s==="zh"?"数据导入或解析中断":"Import or Parsing Error"}),e.jsx("p",{className:"text-xs text-rose-900 mt-1 leading-relaxed",children:z||(s==="zh"?"未知异常或文件破损。":"An unknown exception or corrupted CSV formatting occurred.")})]})]}),e.jsx("div",{className:"flex gap-3 justify-end",children:n?e.jsxs(e.Fragment,{children:[e.jsx("button",{onClick:k,"data-testid":"course-package-duplicate-cancel",className:"px-4 py-2 text-xs font-bold text-gray-700 bg-white border border-gray-250 cursor-pointer hover:bg-gray-50 rounded-lg transition-all",children:s==="zh"?"取消":"Cancel"}),e.jsx("button",{onClick:()=>p(!0),"data-testid":"course-package-duplicate-force",className:"px-4 py-2 text-xs font-bold text-white bg-amber-600 cursor-pointer hover:bg-amber-700 rounded-lg transition-all",children:s==="zh"?"仍然导入副本":"Import as a Copy Anyway"})]}):e.jsxs(e.Fragment,{children:[e.jsx("button",{onClick:()=>{d("idle"),S("")},className:"px-4 py-2 text-xs font-bold text-gray-700 bg-white border border-gray-250 cursor-pointer hover:bg-gray-50 rounded-lg transition-all",children:s==="zh"?"返回重试":"Go Back & Retry"}),e.jsx("button",{onClick:()=>o(!1),className:"px-4 py-2 text-xs font-bold text-white bg-indigo-600 cursor-pointer hover:bg-indigo-700 rounded-lg transition-all",children:s==="zh"?"关闭窗口":"Close"})]})})]})]}),a!=="idle"&&a!=="error"&&e.jsxs("div",{className:"p-4 md:p-5 border-t border-gray-100 flex items-center justify-between bg-slate-50 shrink-0",children:[e.jsx("button",{onClick:()=>{g([]),d("idle")},disabled:a==="importing",className:"px-4 py-2 text-xs font-bold text-gray-650 bg-white border border-gray-200 hover:bg-gray-100 rounded-lg transition-all disabled:opacity-40 cursor-pointer",children:s==="zh"?"重置重选":"Reset & Clear"}),e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("button",{onClick:()=>o(!1),disabled:a==="importing",className:"px-4 py-2 text-xs font-bold text-gray-600 hover:text-gray-800 transition-all disabled:opacity-40 cursor-pointer",children:s==="zh"?"取消":"Cancel"}),a==="parsing"&&t&&e.jsxs("button",{onClick:()=>p(!1),"data-testid":"import-course-package-btn",className:"px-4 py-2 text-xs font-bold text-white bg-indigo-600 hover:bg-indigo-700 rounded-lg shadow-sm transition-all flex items-center gap-1 cursor-pointer",children:[e.jsx(f,{size:12}),s==="zh"?"导入课程包":"Import Course Package"]}),a==="parsing"&&!t&&e.jsxs("button",{onClick:I,className:"px-4 py-2 text-xs font-bold text-white bg-indigo-600 hover:bg-indigo-700 rounded-lg shadow-sm transition-all flex items-center gap-1 cursor-pointer",children:[e.jsx(f,{size:12}),s==="zh"?`开始导入 (${l.length} 类)`:`Proceed and Import (${l.length})`]}),a==="success"&&e.jsx("button",{onClick:()=>o(!1),className:"px-4 py-2 text-xs font-bold text-white bg-indigo-600 hover:bg-indigo-700 rounded-lg shadow-sm transition-all cursor-pointer",children:s==="zh"?"完成":"Done"})]})]})]})})})}export{_ as ImportLessonsModal};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{j as e}from"./vendor-react-
|
|
1
|
+
import{j as e}from"./vendor-react-DHoBZpn2.js";import{ac as d,J as g,z as x,ad as h,c as f}from"./vendor-icons-DaYNfRAc.js";import"./vendor-utils-BxOuk3id.js";function j({show:c,onClose:r,lang:s,handleImportFile:a,importError:n,importSuccess:l,isImporting:m,downloadCSVTemplate:i}){return c?e.jsx("div",{className:"fixed inset-0 bg-black/50 flex items-center justify-center z-50 p-4 font-sans text-gray-800",children:e.jsxs("div",{className:"bg-white rounded-xl shadow-xl w-full max-w-lg flex flex-col p-6 relative",children:[e.jsx("button",{type:"button",onClick:r,className:"absolute top-4 right-4 text-gray-400 hover:text-gray-600 text-xl font-medium cursor-pointer",children:"×"}),e.jsxs("h3",{className:"text-base font-semibold text-gray-900 mb-1 flex items-center gap-2",children:[e.jsx(d,{size:18,className:"text-indigo-600"}),s==="zh"?"手动批量导入数据":"Manual Bulk Import"]}),e.jsx("p",{className:"text-xs text-gray-500 mb-4 font-sans text-left",children:s==="zh"?"支持导入 CSV 或 JSON 文件。CSV 文件需包含标题行(支持中英文标题),仅「学生姓名」为必填,其余列可选:":'Supports CSV or JSON files. Only "Student Name" is required; all other columns are optional:'}),e.jsxs("div",{className:"bg-gray-50 p-3 rounded-lg border border-gray-100 text-xs font-mono text-gray-600 mb-4 whitespace-pre overflow-x-auto select-all text-left leading-relaxed",children:["班级名称, 班级描述, 学生学号, 学生姓名, 学生邮箱, 初始密码, 学生备注",`
|
|
2
2
|
`,"高一A班, 基础英语课程, 20260101, 李明, liming@example.com, , 数学较弱"]}),e.jsx("ul",{className:"mb-4 text-xs text-gray-500 space-y-1 list-disc pl-5 font-sans text-left",children:s==="zh"?e.jsxs(e.Fragment,{children:[e.jsxs("li",{children:[e.jsx("strong",{className:"text-gray-700",children:"学号"}),":学生登录账号。留空则自动生成; 已存在同",e.jsx("strong",{className:"text-gray-700",children:"邮箱"}),"或同学号的学生会被识别为同一人,不会重复建档。"]}),e.jsxs("li",{children:[e.jsx("strong",{className:"text-gray-700",children:"初始密码"}),":留空则系统生成 12 位随机密码, 并在导入成功提示中列出「学号 / 姓名 / 密码」供你分发(仅显示一次,请及时保存)。"]}),e.jsxs("li",{children:[e.jsx("strong",{className:"text-gray-700",children:"学生备注"}),":仅本平台教师可见的私有备注。"]})]}):e.jsxs(e.Fragment,{children:[e.jsxs("li",{children:[e.jsx("strong",{className:"text-gray-700",children:"Student Number"})," is the login account. Auto-generated if blank; students already matching by ",e.jsx("strong",{className:"text-gray-700",children:"email"})," or student number are reused instead of duplicated."]}),e.jsxs("li",{children:[e.jsx("strong",{className:"text-gray-700",children:"Initial Password"}),": leave blank and a 12-character random password is generated and listed once in the success message for you to distribute."]}),e.jsxs("li",{children:[e.jsx("strong",{className:"text-gray-700",children:"Student Notes"})," is a teacher-only private note."]})]})}),e.jsxs("div",{className:"mb-4 flex flex-col gap-2 p-3 bg-indigo-50/50 border border-indigo-100 rounded-lg text-left select-none",children:[e.jsxs("span",{className:"text-xs font-semibold text-indigo-900 flex items-center gap-1",children:[e.jsx(g,{size:13,className:"text-indigo-600"}),s==="zh"?"下载导入数据模板文件:":"Download Import Templates:"]}),e.jsxs("div",{className:"flex flex-col sm:flex-row gap-2 mt-1",children:[e.jsxs("button",{type:"button",onClick:()=>i("class"),className:"flex-1 flex items-center justify-center gap-1.5 text-xs px-2.5 py-2 bg-white border border-indigo-200 text-indigo-700 rounded-lg hover:bg-indigo-50 transition-colors shadow-sm font-medium cursor-pointer",children:[e.jsx(x,{size:12,className:"text-emerald-600"}),s==="zh"?"下载班级与学生模板":"Class & Students Template"]}),e.jsxs("button",{type:"button",onClick:()=>i("student"),className:"flex-1 flex items-center justify-center gap-1.5 text-xs px-2.5 py-2 bg-white border border-indigo-200 text-indigo-700 rounded-lg hover:bg-indigo-50 transition-colors shadow-sm font-medium cursor-pointer",children:[e.jsx(x,{size:12,className:"text-emerald-600"}),s==="zh"?"下载独立学生模板":"Independent Students Template"]})]})]}),e.jsxs("div",{onDragOver:t=>t.preventDefault(),onDrop:t=>{t.preventDefault(),!(!t.dataTransfer.files||t.dataTransfer.files.length===0)&&a(t.dataTransfer.files[0])},className:"border-2 border-dashed border-gray-300 rounded-xl p-8 text-center cursor-pointer hover:border-indigo-500 hover:bg-indigo-50/20 transition-all mb-4",onClick:()=>{const t=document.createElement("input");t.type="file",t.accept=".csv,.json",t.onchange=o=>{o.target.files?.[0]&&a(o.target.files[0])},t.click()},children:[e.jsx(d,{className:"mx-auto text-gray-400 mb-2",size:24}),e.jsx("p",{className:"text-xs font-semibold text-gray-700",children:s==="zh"?"点击选择文件 或 拖拽文件到这里":"Click to select file or drag it here"}),e.jsx("p",{className:"text-xs text-gray-400 mt-1",children:"CSV or JSON (max 5MB)"})]}),n&&e.jsxs("div",{className:"p-3 bg-red-50 border border-red-100 text-red-700 text-xs rounded-lg mb-4 flex items-start gap-2 max-h-32 overflow-y-auto",children:[e.jsx("span",{className:"font-bold shrink-0",children:"✕"}),e.jsx("span",{className:"font-sans text-left leading-tight break-all",children:n})]}),l&&e.jsxs("div",{className:"p-3 bg-green-50 border border-green-105 text-green-700 text-xs rounded-lg mb-4 flex items-start gap-2",children:[e.jsx(h,{size:14,className:"shrink-0 mt-0.5"}),e.jsx("span",{className:"font-sans text-left leading-tight",children:l})]}),m&&e.jsxs("div",{className:"flex items-center justify-center gap-2 text-indigo-600 text-xs py-2",children:[e.jsx(f,{size:16,className:"animate-spin"}),e.jsx("span",{children:s==="zh"?"正在分析数据并导入系统数据库...":"Validating data and transferring records..."})]}),e.jsx("div",{className:"flex justify-end gap-2 mt-2",children:e.jsx("button",{type:"button",onClick:r,className:"px-4 py-2 text-xs font-medium border border-gray-200 text-gray-700 rounded-lg hover:bg-gray-50 transition-colors cursor-pointer",children:s==="zh"?"关闭":"Close"})})]})}):null}export{j as ImportModal};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{r as n,j as e}from"./vendor-react-
|
|
1
|
+
import{r as n,j as e}from"./vendor-react-DHoBZpn2.js";import{af as j,ag as v,E as x,ah as y,ai as k}from"./index-BiHQqzdm.js";import{ar as u,M as N,r as E,X as F}from"./vendor-icons-DaYNfRAc.js";import"./vendor-utils-BxOuk3id.js";import"./vendor-pdf-DVWGghIL.js";import"./vendor-motion-BFAPOs-b.js";import"./vendor-charts-skggaP9D.js";const h=new Map,C=45*1e3;function q({coursewareId:r,onClose:d}){const[m,g]=n.useState(!1),[o,l]=n.useState(null),a=n.useRef(null),i=n.useRef(null),{theme:f}=j();n.useEffect(()=>{if(i.current)return v(i.current)},[o]);const p=()=>{y(f,k(f))};n.useEffect(()=>{const t=()=>{g(!!document.fullscreenElement&&document.fullscreenElement===a.current)};return document.addEventListener("fullscreenchange",t),()=>{document.removeEventListener("fullscreenchange",t)}},[]),n.useEffect(()=>{let t=!1;if(!r){l(null);return}const c=h.get(r),w=Date.now();if(c&&c.expiresAt>w){l(c.token);return}return l(null),fetch(`/api/courseware/${encodeURIComponent(r)}/access-token`).then(s=>s.ok?s.json():Promise.reject(new Error(`HTTP ${s.status}`))).then(s=>{!t&&typeof s?.token=="string"&&s.token&&(h.set(r,{token:s.token,expiresAt:Date.now()+C}),l(s.token))}).catch(s=>{console.warn("[InteractiveCoursewareViewer] Failed to mint courseware access token:",s)}),()=>{t=!0}},[r]);const b=()=>{const t=a.current;t&&(document.fullscreenElement?document.exitFullscreen?document.exitFullscreen():document.webkitExitFullscreen&&document.webkitExitFullscreen():t.requestFullscreen?t.requestFullscreen():t.webkitRequestFullscreen&&t.webkitRequestFullscreen())};return r?e.jsxs("div",{ref:a,className:"flex flex-col h-full bg-white rounded-xl shadow-sm border border-gray-200 overflow-hidden relative",children:[e.jsxs("div",{className:"flex items-center justify-between px-4 py-2 bg-gray-100 border-b border-gray-200 shrink-0",children:[e.jsxs("div",{className:"flex items-center gap-2 select-none",children:[e.jsx(u,{size:16,className:"text-indigo-500"}),e.jsx("span",{className:"font-semibold text-sm text-gray-700",children:"Interactive Courseware"})]}),e.jsx(x,{slot:"courseware.viewer.toolbar",slotProps:{coursewareId:r,classId:null,lessonId:null}}),e.jsxs("div",{className:"flex items-center gap-2 ml-auto",children:[e.jsx("button",{onClick:b,className:"p-1 hover:bg-gray-200 rounded-lg text-gray-500 transition-colors cursor-pointer",title:m?"退出全屏":"全屏播放",children:m?e.jsx(N,{size:16}):e.jsx(E,{size:16})}),d&&e.jsx("button",{onClick:d,className:"p-1 hover:bg-gray-200 rounded-lg text-gray-500 transition-colors cursor-pointer",children:e.jsx(F,{size:16})})]})]}),e.jsxs("div",{className:"flex-1 relative bg-white",children:[e.jsx("div",{className:"absolute inset-0 pointer-events-none overflow-hidden",children:e.jsx(x,{slot:"courseware.viewer.overlay",slotProps:{coursewareId:r}})}),o?e.jsx("iframe",{ref:i,src:`/api/courseware/${r}?ct=${encodeURIComponent(o)}`,sandbox:"allow-scripts allow-forms allow-downloads","data-lms-bridge":"true",loading:"lazy",referrerPolicy:"no-referrer",allowFullScreen:!0,className:"w-full h-full border-none transition-opacity duration-300",title:"Interactive Courseware",onLoad:p}):e.jsxs("div",{className:"absolute inset-0 flex flex-col items-center justify-center bg-slate-50/80 backdrop-blur-xs select-none",children:[e.jsxs("div",{className:"relative flex items-center justify-center",children:[e.jsx("div",{className:"w-10 h-10 border-3 border-indigo-200 border-t-indigo-600 rounded-full animate-spin"}),e.jsx(u,{size:18,className:"absolute text-indigo-500 opacity-80"})]}),e.jsx("span",{className:"mt-3 text-xs font-medium text-slate-500 tracking-wide animate-pulse",children:"正在准备课件沙箱环境…"})]})]})]}):e.jsxs("div",{className:"flex flex-col items-center justify-center h-full text-gray-400 bg-gray-50 rounded-xl border border-dashed border-gray-300",children:[e.jsx(u,{size:48,className:"mb-4 text-gray-300 opacity-50"}),e.jsx("h3",{className:"text-lg font-medium text-gray-700",children:"No Courseware Selected"}),e.jsx("p",{className:"mt-2 text-sm text-center",children:"Please select a courseware from the list to view it interactively."})]})}export{q as InteractiveCoursewareViewer,q as default};
|