openlearn-next 0.7.3 → 0.7.4
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/dist/assets/{ActivityWorkspaceWidget-5PzyxF6a.js → ActivityWorkspaceWidget-CMN8elwQ.js} +1 -1
- package/dist/assets/{AdminDirectoryView-BCtmQTEK.js → AdminDirectoryView-Dlz7q-xf.js} +1 -1
- package/dist/assets/{AssessmentCenter-B43ojHG-.js → AssessmentCenter-CaoAI9Ke.js} +1 -1
- package/dist/assets/{BatchPickerModal-CbmjInp7.js → BatchPickerModal-CzutdtIz.js} +1 -1
- package/dist/assets/{ClassesView-DEnMaDOt.js → ClassesView-RkFPpWRu.js} +1 -1
- package/dist/assets/{ClassroomCountdownWidget-CHq4983w.js → ClassroomCountdownWidget-gs42lIGW.js} +1 -1
- package/dist/assets/{CloudDriveModal-D2t3Uyzr.js → CloudDriveModal-C6JtK08M.js} +1 -1
- package/dist/assets/{ComputerLabView-YtnoT5Rb.js → ComputerLabView-Dr-g8FrU.js} +1 -1
- package/dist/assets/{CourseManagement-DOXyJ_j-.js → CourseManagement-DNeaJcT9.js} +1 -1
- package/dist/assets/{CourseWizardModal-Dbi6Caw2.js → CourseWizardModal-vw876VJr.js} +1 -1
- package/dist/assets/{Dashboard-2rLu_ZBy.js → Dashboard-C1iYnfCh.js} +1 -1
- package/dist/assets/{ExportWeightModal-BrmAh6VX.js → ExportWeightModal-CTZ-O_wi.js} +1 -1
- package/dist/assets/{HelpView-CVBrKDrd.js → HelpView-wyKldm_R.js} +1 -1
- package/dist/assets/{ImportLessonsModal-PhHtX31R.js → ImportLessonsModal-C09Z-qtx.js} +1 -1
- package/dist/assets/{InteractiveCoursewareViewer-Vi6lLz7a.js → InteractiveCoursewareViewer-V97euiJF.js} +1 -1
- package/dist/assets/{InteractiveWhiteboard-lTzeayX5.js → InteractiveWhiteboard-COLMh_-w.js} +1 -1
- package/dist/assets/{LazyCourseware-KIt0rGtW.js → LazyCourseware-0iFYlRGj.js} +2 -2
- package/dist/assets/{LazyWhiteboard-CCN3pYcW.js → LazyWhiteboard-CcoBIx6V.js} +2 -2
- package/dist/assets/{LessonEditorView-D_GVhHuM.js → LessonEditorView-BWmtKwmP.js} +1 -1
- package/dist/assets/{LiveClassroomView-BRsZ6QEq.js → LiveClassroomView-CaS1DzSS.js} +1 -1
- package/dist/assets/{NotificationDetailModal-tY5rxYCN.js → NotificationDetailModal-4MdNF4tw.js} +1 -1
- package/dist/assets/{PluginView-CedpAW6d.js → PluginView-BqTbAp30.js} +1 -1
- package/dist/assets/{QuizGeneratorModal-bUA002kP.js → QuizGeneratorModal-xTq22vDq.js} +1 -1
- package/dist/assets/{StudentAssignmentView-BhAz6Hfk.js → StudentAssignmentView-Cy_JdPYB.js} +1 -1
- package/dist/assets/{StudentLessonView-DC1yX4kG.js → StudentLessonView-B3fKejCU.js} +1 -1
- package/dist/assets/{StudentView-PHKxIV9T.js → StudentView-CpJsG7FT.js} +2 -2
- package/dist/assets/{SystemResourceLibraryModal-DgXYe6_x.js → SystemResourceLibraryModal-YZ85mv_v.js} +1 -1
- package/dist/assets/{TeacherView-DscJtOJ9.js → TeacherView-B3zhzd5g.js} +2 -2
- package/dist/assets/{TimetableView-D2ozoj_D.js → TimetableView-D_4XmrRN.js} +1 -1
- package/dist/assets/{index-2676X8YB.js → index-BzXADCXZ.js} +5 -5
- package/dist/assets/{pluginParsers-e4PSm2Iy.js → pluginParsers-PzgFzxS9.js} +1 -1
- package/dist/cli-migrator.cjs +18 -1
- package/dist/index.html +1 -1
- package/dist/server.cjs +339 -249
- package/package.json +3 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
import{j as e}from"./vendor-react-Kv_JATwr.js";import{CloudDrivePanel as T}from"./CloudDriveModal-
|
|
1
|
+
import{j as e}from"./vendor-react-Kv_JATwr.js";import{CloudDrivePanel as T}from"./CloudDriveModal-C6JtK08M.js";import{ao as h,aY as D,ac as $}from"./vendor-icons-CXrZ3R2V.js";import"./vendor-utils-aM7aYvPP.js";import"./LazyCourseware-0iFYlRGj.js";import"./vendor-pdf-C1Vh2Aqq.js";import"./index-BzXADCXZ.js";import"./vendor-motion-BFAPOs-b.js";import"./vendor-charts-SrpBsvM3.js";function _(b){const{isSystemResourceLibraryOpen:y,setIsSystemResourceLibraryOpen:v,lang:s,systemResourceTab:d,setSystemResourceTab:p,selectedLibraryResourceId:o,setSelectedLibraryResourceId:c,vfsNodes:N,currentVfsParent:j,setCurrentVfsParent:w,cloudDrivePreviewNode:k,setCloudDrivePreviewNode:R,loadingLibraryResources:f,libraryResources:g,fetchLibraryResources:x}=b;return e.jsx(e.Fragment,{children:y&&e.jsx("div",{className:"fixed inset-0 bg-gray-900/40 backdrop-blur-sm flex items-center justify-center p-6 z-50",children:e.jsxs("div",{className:"bg-white border text-gray-900 border-gray-200 rounded-2xl shadow-2xl w-full max-w-6xl h-[85vh] flex flex-col overflow-hidden animate-in fade-in zoom-in-95 duration-150",children:[e.jsxs("div",{className:"p-4 border-b border-gray-100 flex items-center justify-between bg-gray-50/80 shrink-0 flex-wrap gap-2",children:[e.jsxs("div",{className:"flex items-center gap-3 flex-wrap",children:[e.jsx(h,{size:20,className:"text-emerald-500 animate-pulse"}),e.jsx("h2",{className:"font-semibold text-gray-800 text-lg",children:s==="zh"?"系统资源库与应用商城":"System Resource Library"}),e.jsxs("div",{className:"flex items-center gap-1 bg-slate-200/80 p-0.5 rounded-xl border border-slate-300/60 shadow-3xs ml-2",children:[e.jsxs("button",{onClick:()=>p("system"),className:`px-3 py-1 text-xs font-bold rounded-lg transition-all flex items-center gap-1.5 cursor-pointer ${d==="system"?"bg-white text-emerald-800 shadow-2xs font-extrabold":"text-slate-600 hover:text-slate-900"}`,children:[e.jsx(h,{size:13,className:"text-emerald-500"}),e.jsx("span",{children:s==="zh"?"互动课件与系统资源":"System Resources"})]}),e.jsxs("button",{onClick:()=>p("cloud"),className:`px-3 py-1 text-xs font-bold rounded-lg transition-all flex items-center gap-1.5 cursor-pointer ${d==="cloud"?"bg-white text-indigo-800 shadow-2xs font-extrabold":"text-slate-600 hover:text-slate-900"}`,children:[e.jsx(D,{size:13,className:"text-indigo-500"}),e.jsx("span",{children:s==="zh"?"云端课程资源 (Cloud Drive)":"Cloud Course Resource"})]})]})]}),e.jsx("button",{onClick:()=>{v(!1),c(null)},className:"text-gray-400 hover:text-gray-600 font-bold p-1 overflow-hidden hover:bg-gray-200 rounded transition-colors text-lg inline-flex items-center justify-center w-8 h-8 cursor-pointer",children:"×"})]}),d==="cloud"?e.jsx(T,{vfsNodes:N,currentVfsParent:j,setCurrentVfsParent:w,cloudDrivePreviewNode:k,setCloudDrivePreviewNode:R}):e.jsxs("div",{className:"flex-1 flex overflow-hidden min-h-0",children:[e.jsxs("div",{className:"w-80 border-r border-gray-100 bg-slate-50 flex flex-col shrink-0",children:[e.jsxs("div",{className:"p-4 border-b border-gray-200 bg-white space-y-2",children:[e.jsx("span",{className:"block text-xs font-semibold text-gray-500 uppercase tracking-wider mb-1",children:s==="zh"?"上传新资源":"Upload New Resource"}),e.jsxs("div",{className:"grid grid-cols-2 gap-2",children:[e.jsxs("label",{className:"flex flex-col items-center justify-center p-3 bg-slate-50 hover:bg-indigo-50 border border-dashed border-gray-300 hover:border-indigo-400 rounded-xl cursor-pointer text-center transition-all group",children:[e.jsx("span",{className:"text-lg mb-1 group-hover:scale-110 transition-transform",children:"📄"}),e.jsx("span",{className:"font-bold text-indigo-600 text-xs break-all leading-tight",children:s==="zh"?"单HTML文件":"Single HTML"}),e.jsx("input",{type:"file",accept:".html,.htm",className:"hidden",onChange:async t=>{const r=t.target.files?.[0];if(!r)return;const i=new FileReader;i.onload=async n=>{const a=n.target?.result;try{(await fetch("/api/resources",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({name:r.name,type:"html",content:a})})).ok&&x()}catch(l){console.error("Library upload failed:",l)}},i.readAsText(r)}})]}),e.jsxs("label",{className:"flex flex-col items-center justify-center p-3 bg-slate-50 hover:bg-teal-50 border border-dashed border-gray-300 hover:border-teal-400 rounded-xl cursor-pointer text-center transition-all group",children:[e.jsx("span",{className:"text-lg mb-1 group-hover:scale-110 transition-transform",children:"📁"}),e.jsx("span",{className:"font-bold text-teal-600 text-xs break-all leading-tight",children:s==="zh"?"完整文件夹":"Directory Folder"}),e.jsx("input",{type:"file",webkitdirectory:"",directory:"",multiple:!0,className:"hidden",onChange:async t=>{const r=t.target.files;if(!r||r.length===0)return;const i=[];let n="";for(let a=0;a<r.length;a++){const l=r[a],u=l.webkitRelativePath||l.name;n||(n=u.split("/")[0]||"library_resource");const z=l.name.split(".").pop()?.toLowerCase(),C=["png","jpg","jpeg","gif","webp","ico"].includes(z||"");await new Promise(L=>{const m=new FileReader;m.onload=S=>{const P=S.target?.result;i.push({path:u,content:P}),L()},C?m.readAsDataURL(l):m.readAsText(l)})}try{(await fetch("/api/resources",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({name:n,type:"folder",content:JSON.stringify(i)})})).ok&&x()}catch(a){console.error("Folder upload failed:",a)}}})]})]})]}),e.jsxs("div",{className:"flex-1 overflow-y-auto p-3 space-y-2",children:[e.jsx("span",{className:"block text-xs font-bold text-gray-400 uppercase tracking-widest pl-1",children:s==="zh"?"当前已存储的资源":"Stored Resources"}),f&&e.jsx("div",{className:"text-center py-8 text-xs text-slate-400",children:"Loading resources..."}),!f&&g.length===0&&e.jsx("div",{className:"text-center py-12 text-xs text-slate-400 italic",children:s==="zh"?"暂无资源,支持拖入或上传文件。":"No resources in library. Upload some above!"}),g.map(t=>{const r=o===t.id;return e.jsxs("div",{onClick:()=>c(t.id),className:`p-2.5 rounded-xl border flex justify-between items-center cursor-pointer transition-all ${r?"bg-indigo-50 border-indigo-200 shadow-xs":"bg-white border-slate-100 hover:border-slate-200 hover:shadow-2xs"}`,children:[e.jsxs("div",{className:"flex items-center gap-2.5 min-w-0",children:[e.jsx("span",{className:"text-base select-none",children:t.type==="folder"?"📁":"📄"}),e.jsxs("div",{className:"text-left min-w-0",children:[e.jsx("div",{className:"text-xs font-semibold text-gray-700 truncate font-sans",title:t.name,children:t.name}),e.jsxs("div",{className:"text-xs text-gray-400 mt-0.5 font-mono",children:[new Date(t.created_at).toLocaleDateString()," • ",t.id]})]})]}),e.jsx("button",{onClick:async i=>{i.stopPropagation(),confirm(s==="zh"?`确认删除资源 [${t.name}] 吗?`:`Delete resource [${t.name}]?`)&&(await fetch(`/api/resources/${t.id}`,{method:"DELETE"}),o===t.id&&c(null),x())},className:"p-1 hover:bg-red-50 text-slate-400 hover:text-red-500 rounded-md transition-colors cursor-pointer",title:"Delete",children:e.jsx($,{size:12,className:"shrink-0"})})]},t.id)})]})]}),e.jsx("div",{className:"flex-1 bg-white flex flex-col min-w-0",children:o?e.jsxs("div",{className:"flex-1 flex flex-col h-full min-h-0",children:[e.jsxs("div",{className:"p-3 border-b border-gray-100 bg-gray-50 flex items-center justify-between shrink-0",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("span",{className:"font-bold text-gray-700 text-sm",children:s==="zh"?"交互沙箱应用预览:":"Sandbox Live Preview:"}),e.jsxs("span",{className:"text-xs bg-slate-200/70 text-slate-700 px-2 py-0.5 rounded font-mono",children:["/api/resources/",o,"/"]})]}),e.jsx("button",{onClick:()=>c(null),className:"text-xs text-indigo-600 hover:text-indigo-800 font-medium cursor-pointer",children:s==="zh"?"关闭预览":"Close Preview"})]}),e.jsx("div",{className:"flex-1 relative bg-slate-100/50",children:e.jsx("iframe",{src:`/api/resources/${o}/`,sandbox:"allow-scripts","data-lms-bridge":"true",className:"w-full h-full border-none bg-white font-sans",title:"Interactive Resource Preview"})})]}):e.jsxs("div",{className:"flex-1 flex flex-col items-center justify-center p-6 text-gray-400 bg-slate-50/50",children:[e.jsx(h,{size:48,className:"text-gray-300 mb-3 opacity-60"}),e.jsx("p",{className:"text-sm font-semibold text-gray-600",children:s==="zh"?"未选择资源进行预览":"No Resource Selected"}),e.jsx("p",{className:"text-xs text-center text-gray-400 mt-1 max-w-sm",children:s==="zh"?"请在左侧列表中点击选择要预览/管理的 HTML 单文件或完整 applet 文件夹,右侧即可进行沙箱实时运行。":"Click any resource in the list on the left to preview its interactive live sandbox iframe here."})]})})]})]})})})}export{_ as SystemResourceLibraryModal};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/Dashboard-
|
|
2
|
-
import{_ as m}from"./vendor-pdf-C1Vh2Aqq.js";import{r as u,j as e}from"./vendor-react-Kv_JATwr.js";import{c as T,d as N,e as j,E,t as C,o as P,P as k,D as A}from"./index-2676X8YB.js";import{aV as S,aT as V,B as I,a4 as L,U as D,an as O,aG as $,am as R,P as z,S as M,e as H,$ as G,a6 as K,E as U,c as B}from"./vendor-icons-CXrZ3R2V.js";import"./vendor-utils-aM7aYvPP.js";import"./vendor-motion-BFAPOs-b.js";import"./vendor-charts-SrpBsvM3.js";function J(s){return s==="en"?"en":"zh"}const w="openlearn_nav_collapsed_groups",Y=s=>{if(s.status==="cancelled"||s.status==="holiday")return!1;if(!s.time_slot)return!0;try{const a=s.time_slot.split("-");if(a.length<2)return!0;const t=a[1].trim(),[o,r]=t.split(":").map(Number),i=new Date,n=i.getHours(),b=i.getMinutes();return!(n>o||n===o&&b>=r)}catch{return!0}};function F(s={}){const a=T(),t=s.mainNavCollapsed??a?.mainNavCollapsed??!1,o=s.setMainNavCollapsed??a?.setMainNavCollapsed??(()=>{}),r=s.teacherTab??a?.teacherTab??"dashboard",i=s.setTeacherTab??a?.setTeacherTab??(()=>{}),n=s.lang??a?.lang??"zh",b=s.session!==void 0?s.session:a?.session??null,c=s.todaySchedules??a?.todaySchedules??[],l=N(d=>d.extensionPoints).get("teacher.tab")||[];j(d=>d.siteInfo);const[x,y]=u.useState(()=>{try{const d=localStorage.getItem(w);return d?JSON.parse(d):{}}catch{return{}}}),f=d=>{y(v=>{const g={...v,[d]:!v[d]};try{localStorage.setItem(w,JSON.stringify(g))}catch{}return g})};return e.jsxs("div",{id:"navigation_sidebar",className:`${t?"w-16":"w-44 md:w-44"} shrink-0 bg-surface border-r border-theme text-main flex flex-col transition-all duration-300`,children:[e.jsxs("div",{className:`p-2 flex border-b border-theme-subtle ${t?"justify-center":"justify-between items-center px-3"} min-h-[48px] shrink-0`,children:[!t&&e.jsx("span",{className:"inline text-xs font-black tracking-widest text-muted uppercase select-none",children:n==="zh"?"系统导航":"NAVIGATION"}),e.jsx("button",{onClick:()=>o(!t),className:"p-1.5 rounded-lg hover:bg-surface-secondary text-muted hover:text-primary-theme transition-colors cursor-pointer flex items-center justify-center shrink-0",title:t?n==="zh"?"展开导航":"Expand Sidebar":n==="zh"?"折叠导航":"Collapse Sidebar",children:t?e.jsx(S,{size:18}):e.jsx(V,{size:18})})]}),e.jsxs("div",{className:`p-2 ${t?"md:p-2":"md:p-2.5"} flex flex-col gap-2 overflow-y-auto flex-1`,children:[e.jsx(_,{label:n==="zh"?"教学工具":"TEACHING",groupKey:"teaching",mainNavCollapsed:t,isCollapsed:!!x.teaching,onToggle:()=>f("teaching"),lang:n}),(!x.teaching||t)&&e.jsxs("div",{className:"flex flex-col gap-1",children:[e.jsx(p,{icon:I,label:n==="zh"?"课程管理":"Courses",tab:"courses",teacherTab:r,setTeacherTab:i,mainNavCollapsed:t,lang:n}),e.jsx(p,{icon:L,label:n==="zh"?"互动课堂":"Live Class",tab:"live_class",teacherTab:r,setTeacherTab:i,mainNavCollapsed:t,lang:n,highlight:!0}),e.jsx(p,{icon:D,label:n==="zh"?"班级管理":"Classes & Students",tab:"classes",teacherTab:r,setTeacherTab:i,mainNavCollapsed:t,lang:n}),e.jsx(p,{icon:O,label:n==="zh"?"测评中心":"Assessment Center",tab:"assessments",teacherTab:r,setTeacherTab:i,mainNavCollapsed:t,lang:n})]}),e.jsx(_,{label:n==="zh"?"系统管理":"SYSTEM MANAGEMENT",groupKey:"system",mainNavCollapsed:t,isCollapsed:!!x.system,onToggle:()=>f("system"),lang:n}),(!x.system||t)&&e.jsxs("div",{className:"flex flex-col gap-1",children:[e.jsx(p,{icon:$,label:n==="zh"?"课表管理":"Timetable Routine",tab:"timetable",teacherTab:r,setTeacherTab:i,mainNavCollapsed:t,lang:n}),e.jsx(p,{icon:R,label:n==="zh"?"机房管理":"Computer Lab Seating",tab:"computer_labs",teacherTab:r,setTeacherTab:i,mainNavCollapsed:t,lang:n}),e.jsx(p,{icon:z,label:n==="zh"?"插件中心":"App Store / Plugins",tab:"plugins",teacherTab:r,setTeacherTab:i,mainNavCollapsed:t,lang:n}),b?.subRole==="administrator"&&e.jsx(p,{icon:M,label:n==="zh"?"管理后台":"⭐ Admin Center",tab:"admin_directory",isAdmin:!0,teacherTab:r,setTeacherTab:i,mainNavCollapsed:t,lang:n})]}),l.length>0&&e.jsxs(e.Fragment,{children:[e.jsx(_,{label:n==="zh"?"扩展应用":"EXTENSIONS",groupKey:"extensions",mainNavCollapsed:t,isCollapsed:!!x.extensions,onToggle:()=>f("extensions"),lang:n}),(!x.extensions||t)&&e.jsx("div",{className:"flex flex-col gap-1",children:e.jsx(E,{slot:"teacher.tab",slotProps:{renderType:"button",mainNavCollapsed:t,teacherTab:r,setTeacherTab:i,lang:n}})})]}),e.jsx(_,{label:n==="zh"?"帮助支持":"HELP & SUPPORT",groupKey:"support",mainNavCollapsed:t,isCollapsed:!!x.support,onToggle:()=>f("support"),lang:n}),(!x.support||t)&&e.jsx("div",{className:"flex flex-col gap-1",children:e.jsx(p,{icon:H,label:n==="zh"?"帮助文档":"System Commands / Help",tab:"help",teacherTab:r,setTeacherTab:i,mainNavCollapsed:t,lang:n})})]}),(()=>{const d=c.filter(Y),v=d.length;return t||c.length===0?null:e.jsxs("div",{className:"mt-auto p-2.5 m-2 bg-indigo-50/55 dark:bg-indigo-950/20 rounded-xl border border-indigo-100 dark:border-indigo-900/30 block select-none shadow-3xs",id:"today_schedule_sidebar_panel",children:[e.jsxs("div",{className:"flex items-center gap-1.5 text-xs font-bold text-indigo-700 mb-1",children:[e.jsx(G,{size:12,className:"text-indigo-600 animate-pulse shrink-0"}),e.jsx("span",{className:"truncate",children:n==="zh"?"本堂余课":"Classes Remaining"})]}),e.jsx("div",{className:"text-xs text-gray-500 mb-1.5 truncate",children:n==="zh"?`今天还有 ${v} 节课`:`${v} more classes left`}),d.length>0&&e.jsx("div",{className:"max-h-[130px] overflow-y-auto space-y-1 pr-0.5",children:d.map(g=>e.jsxs("div",{className:"text-xs p-1.5 bg-white rounded border border-indigo-100/60 shadow-3xs hover:border-indigo-200 transition-colors",children:[e.jsx("div",{className:"font-bold text-gray-750 truncate",title:g.lesson_title,children:g.lesson_title}),e.jsxs("div",{className:"text-xs text-gray-450 truncate flex justify-between items-center mt-0.5 gap-1",children:[e.jsx("span",{className:"font-medium text-slate-500 truncate max-w-[55px]",children:g.class_name}),e.jsx("span",{className:"font-mono text-indigo-700 font-semibold shrink-0",children:g.time_slot})]})]},g.id))})]})})()]})}function _({label:s,groupKey:a,mainNavCollapsed:t,isCollapsed:o,onToggle:r,lang:i}){return t?e.jsx("div",{className:"h-px bg-border-theme-subtle my-1 w-full opacity-60"}):e.jsxs("button",{type:"button",onClick:r,"aria-expanded":!o,"data-testid":`nav_group_${a}`,className:"w-full flex items-center justify-between px-2.5 py-1.5 rounded-lg bg-surface-secondary/40 hover:bg-surface-secondary/80 border-0 text-xs font-semibold text-muted hover:text-main cursor-pointer transition-all duration-150 select-none group mt-1.5",title:`${s} (${o?i==="zh"?"点击展开":"Click to expand":i==="zh"?"点击折叠":"Click to collapse"})`,children:[e.jsxs("div",{className:"flex items-center gap-2 min-w-0",children:[e.jsx("span",{className:"w-1 h-3 rounded-full bg-primary-theme/75 group-hover:bg-primary-theme transition-colors shrink-0"}),e.jsx("span",{className:"truncate tracking-wide text-xs",children:s})]}),e.jsx(K,{size:13,className:`text-muted/60 group-hover:text-main transition-transform duration-200 shrink-0 ${o?"-rotate-90":"rotate-0"}`})]})}function p({icon:s,label:a,tab:t,teacherTab:o,setTeacherTab:r,mainNavCollapsed:i,highlight:n,isAdmin:b,lang:c}){const h=o===t,l=J(c),x=C[l],y=l==="zh"?`在新标签页打开"${a}"`:`Open "${a}" in a new tab`;return e.jsxs("div",{className:`group relative flex items-center rounded-xl transition-all duration-150 ${h?"bg-primary-theme-light text-primary-theme font-bold border border-primary-theme/25 shadow-3xs":"border border-transparent text-muted hover:bg-surface-secondary hover:text-main"} ${i?"justify-center":""}`,title:a,children:[e.jsxs("button",{type:"button",onClick:()=>r(t),id:`nav_btn_${t}`,"aria-label":a,"aria-current":h?"page":void 0,className:`flex items-center gap-2.5 py-2 flex-1 min-w-0 text-sm font-medium focus:outline-none focus-visible:ring-1 focus-visible:ring-primary-theme/50 rounded-lg ${h?"font-bold":""} ${i?"justify-center px-2":"pl-2.5 pr-8"}`,children:[e.jsx(s,{size:18,className:`shrink-0 transition-colors ${h||n?"text-primary-theme":b?"text-indigo-600 dark:text-indigo-400":""}`}),e.jsx("span",{className:i?"hidden":"block truncate",children:a})]}),!i&&e.jsx("button",{type:"button",onClick:f=>{f.stopPropagation(),P(t)},id:`nav_btn_${t}_newtab`,"aria-label":y,title:x.openInNewTab,"data-testid":`nav_newtab_${t}`,className:"absolute right-1.5 p-1 rounded-md opacity-0 group-hover:opacity-100 focus-visible:opacity-100 hover:bg-black/10 dark:hover:bg-white/15 focus:outline-none focus-visible:ring-1 focus-visible:ring-primary-theme/50 transition-opacity text-current",children:e.jsx(U,{size:12,className:"shrink-0"})})]})}function Q({component:s,lessonId:a,classId:t}){const o=s;return e.jsx(o,{renderType:"panel",lessonId:a,classId:t})}function W({activeNavPlugin:s}){const a=N(l=>l.extensionPoints),t=N(l=>l.pluginErrors),o=j(l=>l.lang),r=j(l=>l.selectedLesson),i=j(l=>l.liveClassSelectedClassId),n=a.get("teacher.tab")||[],b=s||(n.length>0?n[0].pluginId:null),c=n.find(l=>l.pluginId===b),h=c?t.get(c.pluginId):void 0;return e.jsx("div",{className:"flex-1 flex flex-col min-h-0",children:e.jsx("div",{className:"flex-1 overflow-auto",children:h?e.jsx(k,{pluginId:c.pluginId,message:h,lang:o==="en"?"en":"zh"}):c?.component?e.jsx(Q,{component:c.component,lessonId:r,classId:i}):c&&typeof c.render=="function"?e.jsx(A,{ext:c,slot:"teacher.tab",slotProps:{renderType:"panel",lessonId:r,classId:i}}):e.jsx("div",{className:"flex items-center justify-center h-full",children:e.jsxs("div",{className:"text-center",children:[e.jsx(z,{size:48,className:"mx-auto text-gray-300 mb-3"}),e.jsx("p",{className:"text-sm text-subtle font-medium",children:o==="zh"?"此插件未提供页面组件":"This plugin has no page component"}),e.jsx("p",{className:"text-xs text-muted mt-1",children:o==="zh"?"插件已注册导航条目,但未提供对应的界面渲染逻辑。":"The plugin registered a navigation entry but did not provide a render component."})]})})})})}const X=u.lazy(()=>m(()=>import("./Dashboard-2rLu_ZBy.js"),__vite__mapDeps([0,1,2,3,4,5,6,7])).then(s=>({default:s.Dashboard}))),q=u.lazy(()=>m(()=>import("./LessonEditorView-D_GVhHuM.js"),__vite__mapDeps([8,1,2,3,4,5,9,10,7])).then(s=>({default:s.LessonEditorView}))),Z=u.lazy(()=>m(()=>import("./LiveClassroomView-BRsZ6QEq.js"),__vite__mapDeps([11,1,2,3,4,5,9,6,10,12,7])).then(s=>({default:s.LiveClassroomView}))),ee=u.lazy(()=>m(()=>import("./PluginView-CedpAW6d.js"),__vite__mapDeps([13,1,2,4,3,5,14,15,7])).then(s=>({default:s.PluginView}))),te=u.lazy(()=>m(()=>import("./CourseManagement-DOXyJ_j-.js"),__vite__mapDeps([16,1,2,3,4,5,7])).then(s=>({default:s.CourseManagement}))),se=u.lazy(()=>m(()=>import("./ClassesView-DEnMaDOt.js"),__vite__mapDeps([17,1,2,3,4,5,14,18,7])).then(s=>({default:s.ClassesView}))),ne=u.lazy(()=>m(()=>import("./TimetableView-D2ozoj_D.js"),__vite__mapDeps([19,1,2,3,4,5,18,12,7])).then(s=>({default:s.TimetableView}))),ae=u.lazy(()=>m(()=>import("./AdminDirectoryView-BCtmQTEK.js"),__vite__mapDeps([20,1,2,4,3,5,7])).then(s=>({default:s.AdminDirectoryView}))),ie=u.lazy(()=>m(()=>import("./ComputerLabView-YtnoT5Rb.js"),__vite__mapDeps([21,1,2,3,4,5,7])).then(s=>({default:s.ComputerLabView}))),re=u.lazy(()=>m(()=>import("./HelpView-CVBrKDrd.js"),__vite__mapDeps([22,1,2,3,4,5,7])).then(s=>({default:s.HelpView}))),oe=u.lazy(()=>m(()=>import("./AssessmentCenter-B43ojHG-.js"),__vite__mapDeps([23,1,2,3,4,5,7])).then(s=>({default:s.AssessmentCenter})));function he(s={}){const a=T(),t=s.teacherTab??a?.teacherTab??"dashboard";return e.jsxs("div",{className:"flex-1 overflow-hidden flex bg-gray-50",children:[e.jsx(F,{}),e.jsxs("div",{className:"flex-1 p-6 overflow-hidden flex gap-6 relative",children:[["dashboard","lesson_editor","live_class","plugins","courses","classes","timetable","admin_directory","help","computer_labs","assessments"].includes(t)?null:e.jsx(W,{activeNavPlugin:t.includes("/")?t.split("/")[0]:null}),e.jsx(u.Suspense,{fallback:e.jsxs("div",{className:"flex-1 flex flex-col items-center justify-center min-h-[400px] text-slate-400 gap-3",children:[e.jsx(B,{className:"w-8 h-8 animate-spin text-indigo-500"}),e.jsx("span",{className:"text-sm font-medium",children:"加载视图中..."})]}),children:t==="dashboard"?e.jsx(X,{}):t==="lesson_editor"?e.jsx(q,{}):t==="live_class"?e.jsx("div",{className:"flex-grow flex-1 flex flex-col min-h-0 min-w-0",children:e.jsx(Z,{})}):t==="plugins"?e.jsx(ee,{}):t==="courses"?e.jsx(te,{}):t==="classes"?e.jsx(se,{}):t==="timetable"?e.jsx(ne,{}):t==="admin_directory"?e.jsx(ae,{}):t==="computer_labs"?e.jsx(ie,{}):t==="assessments"?e.jsx(oe,{}):t==="help"?e.jsx(re,{}):null})]})]})}export{he as TeacherView};
|
|
1
|
+
const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/Dashboard-C1iYnfCh.js","assets/vendor-react-Kv_JATwr.js","assets/vendor-utils-aM7aYvPP.js","assets/index-BzXADCXZ.js","assets/vendor-icons-CXrZ3R2V.js","assets/vendor-motion-BFAPOs-b.js","assets/ClassroomCountdownWidget-gs42lIGW.js","assets/index-C6hlh8pw.css","assets/LessonEditorView-BWmtKwmP.js","assets/LazyWhiteboard-CcoBIx6V.js","assets/timeline-duration-BgdJCSrW.js","assets/LiveClassroomView-CaS1DzSS.js","assets/teaching-modes-client-BeVaDdJ-.js","assets/PluginView-BqTbAp30.js","assets/pluginParsers-PzgFzxS9.js","assets/vendor-pptx-DIWdXF1L.css","assets/CourseManagement-DNeaJcT9.js","assets/ClassesView-RkFPpWRu.js","assets/AcademicYearFilter-DUUGpDKt.js","assets/TimetableView-D_4XmrRN.js","assets/AdminDirectoryView-Dlz7q-xf.js","assets/ComputerLabView-Dr-g8FrU.js","assets/HelpView-wyKldm_R.js","assets/AssessmentCenter-CaoAI9Ke.js"])))=>i.map(i=>d[i]);
|
|
2
|
+
import{_ as m}from"./vendor-pdf-C1Vh2Aqq.js";import{r as u,j as e}from"./vendor-react-Kv_JATwr.js";import{c as T,d as N,e as j,E,t as C,o as P,P as k,D as A}from"./index-BzXADCXZ.js";import{aV as S,aT as V,B as I,a4 as L,U as D,an as O,aG as $,am as R,P as z,S as M,e as H,$ as G,a6 as K,E as U,c as B}from"./vendor-icons-CXrZ3R2V.js";import"./vendor-utils-aM7aYvPP.js";import"./vendor-motion-BFAPOs-b.js";import"./vendor-charts-SrpBsvM3.js";function J(s){return s==="en"?"en":"zh"}const w="openlearn_nav_collapsed_groups",Y=s=>{if(s.status==="cancelled"||s.status==="holiday")return!1;if(!s.time_slot)return!0;try{const a=s.time_slot.split("-");if(a.length<2)return!0;const t=a[1].trim(),[o,r]=t.split(":").map(Number),i=new Date,n=i.getHours(),b=i.getMinutes();return!(n>o||n===o&&b>=r)}catch{return!0}};function F(s={}){const a=T(),t=s.mainNavCollapsed??a?.mainNavCollapsed??!1,o=s.setMainNavCollapsed??a?.setMainNavCollapsed??(()=>{}),r=s.teacherTab??a?.teacherTab??"dashboard",i=s.setTeacherTab??a?.setTeacherTab??(()=>{}),n=s.lang??a?.lang??"zh",b=s.session!==void 0?s.session:a?.session??null,c=s.todaySchedules??a?.todaySchedules??[],l=N(d=>d.extensionPoints).get("teacher.tab")||[];j(d=>d.siteInfo);const[x,y]=u.useState(()=>{try{const d=localStorage.getItem(w);return d?JSON.parse(d):{}}catch{return{}}}),f=d=>{y(v=>{const g={...v,[d]:!v[d]};try{localStorage.setItem(w,JSON.stringify(g))}catch{}return g})};return e.jsxs("div",{id:"navigation_sidebar",className:`${t?"w-16":"w-44 md:w-44"} shrink-0 bg-surface border-r border-theme text-main flex flex-col transition-all duration-300`,children:[e.jsxs("div",{className:`p-2 flex border-b border-theme-subtle ${t?"justify-center":"justify-between items-center px-3"} min-h-[48px] shrink-0`,children:[!t&&e.jsx("span",{className:"inline text-xs font-black tracking-widest text-muted uppercase select-none",children:n==="zh"?"系统导航":"NAVIGATION"}),e.jsx("button",{onClick:()=>o(!t),className:"p-1.5 rounded-lg hover:bg-surface-secondary text-muted hover:text-primary-theme transition-colors cursor-pointer flex items-center justify-center shrink-0",title:t?n==="zh"?"展开导航":"Expand Sidebar":n==="zh"?"折叠导航":"Collapse Sidebar",children:t?e.jsx(S,{size:18}):e.jsx(V,{size:18})})]}),e.jsxs("div",{className:`p-2 ${t?"md:p-2":"md:p-2.5"} flex flex-col gap-2 overflow-y-auto flex-1`,children:[e.jsx(_,{label:n==="zh"?"教学工具":"TEACHING",groupKey:"teaching",mainNavCollapsed:t,isCollapsed:!!x.teaching,onToggle:()=>f("teaching"),lang:n}),(!x.teaching||t)&&e.jsxs("div",{className:"flex flex-col gap-1",children:[e.jsx(p,{icon:I,label:n==="zh"?"课程管理":"Courses",tab:"courses",teacherTab:r,setTeacherTab:i,mainNavCollapsed:t,lang:n}),e.jsx(p,{icon:L,label:n==="zh"?"互动课堂":"Live Class",tab:"live_class",teacherTab:r,setTeacherTab:i,mainNavCollapsed:t,lang:n,highlight:!0}),e.jsx(p,{icon:D,label:n==="zh"?"班级管理":"Classes & Students",tab:"classes",teacherTab:r,setTeacherTab:i,mainNavCollapsed:t,lang:n}),e.jsx(p,{icon:O,label:n==="zh"?"测评中心":"Assessment Center",tab:"assessments",teacherTab:r,setTeacherTab:i,mainNavCollapsed:t,lang:n})]}),e.jsx(_,{label:n==="zh"?"系统管理":"SYSTEM MANAGEMENT",groupKey:"system",mainNavCollapsed:t,isCollapsed:!!x.system,onToggle:()=>f("system"),lang:n}),(!x.system||t)&&e.jsxs("div",{className:"flex flex-col gap-1",children:[e.jsx(p,{icon:$,label:n==="zh"?"课表管理":"Timetable Routine",tab:"timetable",teacherTab:r,setTeacherTab:i,mainNavCollapsed:t,lang:n}),e.jsx(p,{icon:R,label:n==="zh"?"机房管理":"Computer Lab Seating",tab:"computer_labs",teacherTab:r,setTeacherTab:i,mainNavCollapsed:t,lang:n}),e.jsx(p,{icon:z,label:n==="zh"?"插件中心":"App Store / Plugins",tab:"plugins",teacherTab:r,setTeacherTab:i,mainNavCollapsed:t,lang:n}),b?.subRole==="administrator"&&e.jsx(p,{icon:M,label:n==="zh"?"管理后台":"⭐ Admin Center",tab:"admin_directory",isAdmin:!0,teacherTab:r,setTeacherTab:i,mainNavCollapsed:t,lang:n})]}),l.length>0&&e.jsxs(e.Fragment,{children:[e.jsx(_,{label:n==="zh"?"扩展应用":"EXTENSIONS",groupKey:"extensions",mainNavCollapsed:t,isCollapsed:!!x.extensions,onToggle:()=>f("extensions"),lang:n}),(!x.extensions||t)&&e.jsx("div",{className:"flex flex-col gap-1",children:e.jsx(E,{slot:"teacher.tab",slotProps:{renderType:"button",mainNavCollapsed:t,teacherTab:r,setTeacherTab:i,lang:n}})})]}),e.jsx(_,{label:n==="zh"?"帮助支持":"HELP & SUPPORT",groupKey:"support",mainNavCollapsed:t,isCollapsed:!!x.support,onToggle:()=>f("support"),lang:n}),(!x.support||t)&&e.jsx("div",{className:"flex flex-col gap-1",children:e.jsx(p,{icon:H,label:n==="zh"?"帮助文档":"System Commands / Help",tab:"help",teacherTab:r,setTeacherTab:i,mainNavCollapsed:t,lang:n})})]}),(()=>{const d=c.filter(Y),v=d.length;return t||c.length===0?null:e.jsxs("div",{className:"mt-auto p-2.5 m-2 bg-indigo-50/55 dark:bg-indigo-950/20 rounded-xl border border-indigo-100 dark:border-indigo-900/30 block select-none shadow-3xs",id:"today_schedule_sidebar_panel",children:[e.jsxs("div",{className:"flex items-center gap-1.5 text-xs font-bold text-indigo-700 mb-1",children:[e.jsx(G,{size:12,className:"text-indigo-600 animate-pulse shrink-0"}),e.jsx("span",{className:"truncate",children:n==="zh"?"本堂余课":"Classes Remaining"})]}),e.jsx("div",{className:"text-xs text-gray-500 mb-1.5 truncate",children:n==="zh"?`今天还有 ${v} 节课`:`${v} more classes left`}),d.length>0&&e.jsx("div",{className:"max-h-[130px] overflow-y-auto space-y-1 pr-0.5",children:d.map(g=>e.jsxs("div",{className:"text-xs p-1.5 bg-white rounded border border-indigo-100/60 shadow-3xs hover:border-indigo-200 transition-colors",children:[e.jsx("div",{className:"font-bold text-gray-750 truncate",title:g.lesson_title,children:g.lesson_title}),e.jsxs("div",{className:"text-xs text-gray-450 truncate flex justify-between items-center mt-0.5 gap-1",children:[e.jsx("span",{className:"font-medium text-slate-500 truncate max-w-[55px]",children:g.class_name}),e.jsx("span",{className:"font-mono text-indigo-700 font-semibold shrink-0",children:g.time_slot})]})]},g.id))})]})})()]})}function _({label:s,groupKey:a,mainNavCollapsed:t,isCollapsed:o,onToggle:r,lang:i}){return t?e.jsx("div",{className:"h-px bg-border-theme-subtle my-1 w-full opacity-60"}):e.jsxs("button",{type:"button",onClick:r,"aria-expanded":!o,"data-testid":`nav_group_${a}`,className:"w-full flex items-center justify-between px-2.5 py-1.5 rounded-lg bg-surface-secondary/40 hover:bg-surface-secondary/80 border-0 text-xs font-semibold text-muted hover:text-main cursor-pointer transition-all duration-150 select-none group mt-1.5",title:`${s} (${o?i==="zh"?"点击展开":"Click to expand":i==="zh"?"点击折叠":"Click to collapse"})`,children:[e.jsxs("div",{className:"flex items-center gap-2 min-w-0",children:[e.jsx("span",{className:"w-1 h-3 rounded-full bg-primary-theme/75 group-hover:bg-primary-theme transition-colors shrink-0"}),e.jsx("span",{className:"truncate tracking-wide text-xs",children:s})]}),e.jsx(K,{size:13,className:`text-muted/60 group-hover:text-main transition-transform duration-200 shrink-0 ${o?"-rotate-90":"rotate-0"}`})]})}function p({icon:s,label:a,tab:t,teacherTab:o,setTeacherTab:r,mainNavCollapsed:i,highlight:n,isAdmin:b,lang:c}){const h=o===t,l=J(c),x=C[l],y=l==="zh"?`在新标签页打开"${a}"`:`Open "${a}" in a new tab`;return e.jsxs("div",{className:`group relative flex items-center rounded-xl transition-all duration-150 ${h?"bg-primary-theme-light text-primary-theme font-bold border border-primary-theme/25 shadow-3xs":"border border-transparent text-muted hover:bg-surface-secondary hover:text-main"} ${i?"justify-center":""}`,title:a,children:[e.jsxs("button",{type:"button",onClick:()=>r(t),id:`nav_btn_${t}`,"aria-label":a,"aria-current":h?"page":void 0,className:`flex items-center gap-2.5 py-2 flex-1 min-w-0 text-sm font-medium focus:outline-none focus-visible:ring-1 focus-visible:ring-primary-theme/50 rounded-lg ${h?"font-bold":""} ${i?"justify-center px-2":"pl-2.5 pr-8"}`,children:[e.jsx(s,{size:18,className:`shrink-0 transition-colors ${h||n?"text-primary-theme":b?"text-indigo-600 dark:text-indigo-400":""}`}),e.jsx("span",{className:i?"hidden":"block truncate",children:a})]}),!i&&e.jsx("button",{type:"button",onClick:f=>{f.stopPropagation(),P(t)},id:`nav_btn_${t}_newtab`,"aria-label":y,title:x.openInNewTab,"data-testid":`nav_newtab_${t}`,className:"absolute right-1.5 p-1 rounded-md opacity-0 group-hover:opacity-100 focus-visible:opacity-100 hover:bg-black/10 dark:hover:bg-white/15 focus:outline-none focus-visible:ring-1 focus-visible:ring-primary-theme/50 transition-opacity text-current",children:e.jsx(U,{size:12,className:"shrink-0"})})]})}function Q({component:s,lessonId:a,classId:t}){const o=s;return e.jsx(o,{renderType:"panel",lessonId:a,classId:t})}function W({activeNavPlugin:s}){const a=N(l=>l.extensionPoints),t=N(l=>l.pluginErrors),o=j(l=>l.lang),r=j(l=>l.selectedLesson),i=j(l=>l.liveClassSelectedClassId),n=a.get("teacher.tab")||[],b=s||(n.length>0?n[0].pluginId:null),c=n.find(l=>l.pluginId===b),h=c?t.get(c.pluginId):void 0;return e.jsx("div",{className:"flex-1 flex flex-col min-h-0",children:e.jsx("div",{className:"flex-1 overflow-auto",children:h?e.jsx(k,{pluginId:c.pluginId,message:h,lang:o==="en"?"en":"zh"}):c?.component?e.jsx(Q,{component:c.component,lessonId:r,classId:i}):c&&typeof c.render=="function"?e.jsx(A,{ext:c,slot:"teacher.tab",slotProps:{renderType:"panel",lessonId:r,classId:i}}):e.jsx("div",{className:"flex items-center justify-center h-full",children:e.jsxs("div",{className:"text-center",children:[e.jsx(z,{size:48,className:"mx-auto text-gray-300 mb-3"}),e.jsx("p",{className:"text-sm text-subtle font-medium",children:o==="zh"?"此插件未提供页面组件":"This plugin has no page component"}),e.jsx("p",{className:"text-xs text-muted mt-1",children:o==="zh"?"插件已注册导航条目,但未提供对应的界面渲染逻辑。":"The plugin registered a navigation entry but did not provide a render component."})]})})})})}const X=u.lazy(()=>m(()=>import("./Dashboard-C1iYnfCh.js"),__vite__mapDeps([0,1,2,3,4,5,6,7])).then(s=>({default:s.Dashboard}))),q=u.lazy(()=>m(()=>import("./LessonEditorView-BWmtKwmP.js"),__vite__mapDeps([8,1,2,3,4,5,9,10,7])).then(s=>({default:s.LessonEditorView}))),Z=u.lazy(()=>m(()=>import("./LiveClassroomView-CaS1DzSS.js"),__vite__mapDeps([11,1,2,3,4,5,9,6,10,12,7])).then(s=>({default:s.LiveClassroomView}))),ee=u.lazy(()=>m(()=>import("./PluginView-BqTbAp30.js"),__vite__mapDeps([13,1,2,4,3,5,14,15,7])).then(s=>({default:s.PluginView}))),te=u.lazy(()=>m(()=>import("./CourseManagement-DNeaJcT9.js"),__vite__mapDeps([16,1,2,3,4,5,7])).then(s=>({default:s.CourseManagement}))),se=u.lazy(()=>m(()=>import("./ClassesView-RkFPpWRu.js"),__vite__mapDeps([17,1,2,3,4,5,14,18,7])).then(s=>({default:s.ClassesView}))),ne=u.lazy(()=>m(()=>import("./TimetableView-D_4XmrRN.js"),__vite__mapDeps([19,1,2,3,4,5,18,12,7])).then(s=>({default:s.TimetableView}))),ae=u.lazy(()=>m(()=>import("./AdminDirectoryView-Dlz7q-xf.js"),__vite__mapDeps([20,1,2,4,3,5,7])).then(s=>({default:s.AdminDirectoryView}))),ie=u.lazy(()=>m(()=>import("./ComputerLabView-Dr-g8FrU.js"),__vite__mapDeps([21,1,2,3,4,5,7])).then(s=>({default:s.ComputerLabView}))),re=u.lazy(()=>m(()=>import("./HelpView-wyKldm_R.js"),__vite__mapDeps([22,1,2,3,4,5,7])).then(s=>({default:s.HelpView}))),oe=u.lazy(()=>m(()=>import("./AssessmentCenter-CaoAI9Ke.js"),__vite__mapDeps([23,1,2,3,4,5,7])).then(s=>({default:s.AssessmentCenter})));function he(s={}){const a=T(),t=s.teacherTab??a?.teacherTab??"dashboard";return e.jsxs("div",{className:"flex-1 overflow-hidden flex bg-gray-50",children:[e.jsx(F,{}),e.jsxs("div",{className:"flex-1 p-6 overflow-hidden flex gap-6 relative",children:[["dashboard","lesson_editor","live_class","plugins","courses","classes","timetable","admin_directory","help","computer_labs","assessments"].includes(t)?null:e.jsx(W,{activeNavPlugin:t.includes("/")?t.split("/")[0]:null}),e.jsx(u.Suspense,{fallback:e.jsxs("div",{className:"flex-1 flex flex-col items-center justify-center min-h-[400px] text-slate-400 gap-3",children:[e.jsx(B,{className:"w-8 h-8 animate-spin text-indigo-500"}),e.jsx("span",{className:"text-sm font-medium",children:"加载视图中..."})]}),children:t==="dashboard"?e.jsx(X,{}):t==="lesson_editor"?e.jsx(q,{}):t==="live_class"?e.jsx("div",{className:"flex-grow flex-1 flex flex-col min-h-0 min-w-0",children:e.jsx(Z,{})}):t==="plugins"?e.jsx(ee,{}):t==="courses"?e.jsx(te,{}):t==="classes"?e.jsx(se,{}):t==="timetable"?e.jsx(ne,{}):t==="admin_directory"?e.jsx(ae,{}):t==="computer_labs"?e.jsx(ie,{}):t==="assessments"?e.jsx(oe,{}):t==="help"?e.jsx(re,{}):null})]})]})}export{he as TeacherView};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{j as e,r as d}from"./vendor-react-Kv_JATwr.js";import{E as we,Y as ue,x as Cs,V as ks,Z as $s,_ as _s,N as Pt,Q as Ts,B as Ds,c as Is}from"./index-2676X8YB.js";import{aA as Mt,aJ as As,c7 as Ps,ad as ut,c2 as Es,a$ as Os,X as ve,ak as Jt,c as Le,bv as Ue,bt as qe,ac as Et,aT as Ls,f as Rs,z as Qe,$ as Ot,c8 as Fs,i as Wt,D as Ms,c9 as Lt,a8 as Js,C as Bt,ca as Ws,T as Bs,cb as Gs,u as Hs,cc as Rt,az as Vs,o as xt,a9 as Ys,aG as Us}from"./vendor-icons-CXrZ3R2V.js";import{A as qs}from"./AcademicYearFilter-DUUGpDKt.js";import{f as Qs}from"./teaching-modes-client-BeVaDdJ-.js";import"./vendor-utils-aM7aYvPP.js";import"./vendor-pdf-C1Vh2Aqq.js";import"./vendor-motion-BFAPOs-b.js";import"./vendor-charts-SrpBsvM3.js";const Ks=a=>{const m=[];for(let l=0;l<7;l++){const j=new Date(a.getTime()+l*24*60*60*1e3),_=j.getFullYear(),A=String(j.getMonth()+1).padStart(2,"0"),L=String(j.getDate()).padStart(2,"0");m.push(`${_}-${A}-${L}`)}return m},Ft=a=>{if(!a)return!1;const m=a.match(/^(\d{1,2}):(\d{2})/);return m?parseInt(m[1],10)>=12:!1},Zs=({lang:a,viewMode:m,setViewMode:l,selectedClassId:j,setSelectedClassId:_,statusFilter:A,setStatusFilter:L,searchQuery:P,setSearchQuery:w,classes:C,getClassDisplayName:H,loading:k,filteredSchedules:E,currentWeekMonday:he,setCurrentWeekMonday:q,showWeekend:ze,setShowWeekend:le,dateOverrides:F,setDateOverrides:W,setOverridingDateKey:O,setOverrideMode:T,setOverrideTargetDow:te,setOverrideTargetDate:Q,openEditModal:B,handleDeleteSchedule:Se,getDayOfWeekIndex:V,getMonday:me,getWeekRangeString:h,setFormClassId:$,setFormLessonId:se,setFormDate:Ce,setFormStatus:ke,setFormNotes:ae,setIsAddOpen:ie,onQuickStart:M,activeSessionLessonIds:oe})=>{const ne=[{key:1,label:a==="zh"?"周一 (Mon)":"Mon"},{key:2,label:a==="zh"?"周二 (Tue)":"Tue"},{key:3,label:a==="zh"?"周三 (Wed)":"Wed"},{key:4,label:a==="zh"?"周四 (Thu)":"Thu"},{key:5,label:a==="zh"?"周五 (Fri)":"Fri"},{key:6,label:a==="zh"?"周六 (Sat)":"Sat"},{key:7,label:a==="zh"?"周日 (Sun)":"Sun"}],pe=Ks(he),Re=r=>{const x=/^(\d{1,2}):(\d{2})\s*-\s*(\d{1,2}):(\d{2})$/.exec((r||"").trim());return x?{start:`${x[1].padStart(2,"0")}:${x[2]}`,end:`${x[3].padStart(2,"0")}:${x[4]}`}:null},de=(()=>{const r=new Date;return`${String(r.getHours()).padStart(2,"0")}:${String(r.getMinutes()).padStart(2,"0")}`})(),Ke=new Date().toISOString().split("T")[0],be=E.filter(r=>r.scheduled_date===Ke&&r.status!=="cancelled"&&r.status!=="holiday").sort((r,x)=>(r.time_slot||"").localeCompare(x.time_slot||"")),G=be.find(r=>{const x=Re(r.time_slot);return x&&x.start<=de&&de<=x.end}),$e=be.find(r=>{const x=Re(r.time_slot);return x&&x.start>de}),K=G||$e,ce=(r,x="xs")=>{const u=r.status==="cancelled"||r.status==="holiday",N=!!r.lesson_id,f=u||!N,g=N&&oe.has(r.lesson_id),D=u?a==="zh"?"停课/假期排课不能开始上课":"Cancelled/holiday schedules cannot start a class":N?g?a==="zh"?"该课已有进行中的课堂会话,点击直接进入":"An active session exists. Click to enter directly.":a==="zh"?"快速开始上这节课":"Quick start this class":a==="zh"?"未关联课程,请先编辑排课关联课程":"No lesson linked. Edit the schedule to link one first.",v=x==="sm"?"px-2.5 py-1 text-xs gap-1":"px-1.5 py-0.5 text-[11px] gap-0.5",y=g?a==="zh"?"进入课堂":"Enter class":a==="zh"?"开始上课":"Start class";return e.jsxs("button",{type:"button","data-testid":`quick-start-${r.id}`,disabled:f,"aria-label":`${y}:${D}:${r.lesson_title||r.class_name||r.id}`,title:D,onClick:()=>M(r),className:`flex items-center rounded-md font-bold transition-all ${f?"text-slate-300 bg-slate-50 border border-slate-100 cursor-not-allowed":g?"text-emerald-700 bg-emerald-50 border border-emerald-200 hover:bg-emerald-100 cursor-pointer":"text-white bg-indigo-600 hover:bg-indigo-700 border border-indigo-500 shadow-2xs cursor-pointer"} ${v}`,children:[g?e.jsx(Fs,{size:11,"aria-hidden":"true"}):e.jsx(Wt,{size:11,"aria-hidden":"true"}),g?a==="zh"?"进入课堂":"Enter":a==="zh"?"开始上课":"Start"]})},fe=r=>{const x=r.status==="cancelled"||r.status==="holiday";let u="border-l-green-500 bg-green-50/5 hover:bg-green-50/10 hover:border-l-green-600";return r.status==="cancelled"?u="border-l-red-500 bg-red-50/5 hover:bg-red-50/10 hover:border-l-red-600":r.status==="holiday"?u="border-l-amber-500 bg-amber-50/5 hover:bg-amber-50/10 hover:border-l-amber-600":r.status==="swap"&&(u="border-l-blue-500 bg-blue-50/5 hover:bg-blue-50/10 hover:border-l-blue-600"),e.jsxs("div",{className:`p-2.5 rounded-xl border border-slate-150 border-l-4 ${u} transition-all hover:shadow-xs relative group flex flex-col justify-between min-h-[85px]`,children:[e.jsxs("div",{children:[e.jsxs("div",{className:"text-xs font-mono text-slate-500 mb-1 font-bold flex justify-between items-center",children:[e.jsxs("span",{className:"flex items-center gap-1",children:[e.jsx(Ot,{size:11,className:"text-slate-400"}),r.time_slot||(a==="zh"?"全天":"All-day")]}),m==="cycle"&&e.jsx("span",{className:"text-xs text-slate-400 font-sans font-normal bg-slate-100 px-1 py-0.5 rounded-sm",children:r.scheduled_date})]}),e.jsx("div",{className:`font-extrabold text-sm text-slate-805 tracking-tight leading-snug mt-1 ${x?"line-through opacity-60 text-slate-400":""}`,title:r.lesson_title||"",children:r.class_name}),r.notes&&e.jsxs("div",{className:"text-xs text-amber-600 font-medium mt-1 truncate",title:r.notes,children:["📌 ",r.notes]})]}),e.jsxs("div",{className:"flex items-center justify-between mt-2.5 pt-2 border-t border-slate-100/50",children:[e.jsxs("div",{className:"flex items-center gap-1 flex-wrap",children:[e.jsx("span",{className:`inline-block text-xs px-1.5 py-0.5 rounded-full font-bold uppercase tracking-wide border ${r.status==="cancelled"?"bg-red-50 border-red-100 text-red-600":r.status==="holiday"?"bg-amber-50 border-amber-100 text-amber-600":r.status==="swap"?"bg-blue-50 border-blue-100 text-blue-600":"bg-green-50 border-green-100 text-green-600"}`,children:r.status==="cancelled"?a==="zh"?"停课":"Cancelled":r.status==="holiday"?a==="zh"?"假期":"Holiday":r.status==="swap"?a==="zh"?"代课":"Swapped":a==="zh"?"正常":"Active"}),e.jsx(we,{slot:"timetable.card.badge",slotProps:{schedule:r,lang:a}}),ce(r)]}),e.jsxs("div",{className:"flex gap-1 opacity-0 group-hover:opacity-100 transition-opacity items-center",children:[e.jsx(we,{slot:"timetable.entry.action",slotProps:{schedule:r,lang:a,onEdit:()=>B(r)}}),e.jsx("button",{onClick:()=>B(r),className:"text-slate-400 hover:text-indigo-600 hover:bg-indigo-50 p-1 rounded-md transition-colors cursor-pointer",title:a==="zh"?"微调":"Edit",children:e.jsx(qe,{size:11})}),e.jsx("button",{onClick:()=>Se(r.id,r.class_id,r.isRepeating,r.scheduled_date),className:"text-slate-400 hover:text-red-600 hover:bg-red-50 p-1 rounded-md transition-colors cursor-pointer",title:a==="zh"?"删除":"Delete",children:e.jsx(Et,{size:11})})]})]})]},r.id)},ge=(r,x)=>{if(r===x){const f=E.filter(y=>y.scheduled_date===x);if(f.length>0)return f;const g=V(x),D=E.filter(y=>V(y.scheduled_date)===g&&y.scheduled_date<=x),v={};return D.forEach(y=>{const Ne=`${y.class_id}_${y.time_slot||"all-day"}`;v[Ne]||(v[Ne]={...y,scheduled_date:x,isRepeating:!0})}),Object.values(v)}let u=[];if(r.startsWith("dow-")){const f=parseInt(r.split("-")[1],10),g=E.filter(v=>V(v.scheduled_date)===f&&v.scheduled_date<=x),D={};g.forEach(v=>{const y=`${v.class_id}_${v.time_slot||"all-day"}`;D[y]||(D[y]={...v,scheduled_date:x,isRepeating:!0})}),u=Object.values(D)}else{const f=E.filter(g=>g.scheduled_date===r);if(f.length>0)u=f.map(g=>({...g,scheduled_date:x,isRepeating:!0}));else{const g=V(r),D=E.filter(y=>V(y.scheduled_date)===g&&y.scheduled_date<=r),v={};D.forEach(y=>{const Ne=`${y.class_id}_${y.time_slot||"all-day"}`;v[Ne]||(v[Ne]={...y,scheduled_date:x,isRepeating:!0})}),u=Object.values(v)}}const N=E.filter(f=>f.scheduled_date===x);if(N.length>0){const f=[...u];return N.forEach(g=>{const D=`${g.class_id}_${g.time_slot||"all-day"}`,v=f.findIndex(y=>`${y.class_id}_${y.time_slot||"all-day"}`===D);v!==-1?f[v]=g:g.status!=="cancelled"&&g.status!=="holiday"&&f.push(g)}),f}return u},je=ne.map((r,x)=>{const u=pe[x],N=F[u]||u,f=ge(N,u);return f.sort((g,D)=>(g.time_slot||"").localeCompare(D.time_slot||"")),{...r,dateStr:u,displayLabel:a==="zh"?`${r.label.split(" ")[0]} (${u.substring(5)})`:`${r.label} (${u.substring(5)})`,schedules:f}}),ye=ne.map(r=>{const x=pe[r.key-1],u=E.filter(N=>V(N.scheduled_date)===r.key);return u.sort((N,f)=>(N.time_slot||"").localeCompare(f.time_slot||"")),{...r,dateStr:x,displayLabel:r.label,schedules:u}}),Y=(m==="week"?je:ye).filter(r=>m==="week"&&!ze?r.key!==6&&r.key!==7:!0);return e.jsxs("div",{className:"flex flex-col gap-4",children:[K&&e.jsxs("div",{id:"timetable_quick_start_card","data-testid":"timetable-quick-start-card",className:`flex flex-wrap items-center gap-3 p-3 rounded-xl border shadow-2xs ${G?"bg-emerald-50/60 border-emerald-200/70":"bg-indigo-50/60 border-indigo-200/60"}`,children:[e.jsxs("div",{className:`flex items-center gap-1.5 text-xs font-extrabold uppercase tracking-wider px-2 py-0.5 rounded-full border select-none ${G?"bg-emerald-100 border-emerald-200 text-emerald-700":"bg-indigo-100 border-indigo-200 text-indigo-700"}`,children:[e.jsx(Mt,{size:12,"aria-hidden":"true"}),G?a==="zh"?"正在进行":"In Progress":a==="zh"?"下一节课":"Up Next"]}),e.jsxs("div",{className:"flex-1 min-w-[180px] leading-snug",children:[e.jsx("div",{className:"text-sm font-bold text-slate-800",children:K.lesson_title||K.class_name}),e.jsxs("div",{className:"text-xs text-slate-500 flex flex-wrap gap-x-3",children:[e.jsx("span",{className:"font-mono",children:K.time_slot}),e.jsx("span",{children:K.class_name})]})]}),ce(K,"sm")]}),e.jsxs("div",{className:"bg-slate-50 border border-slate-200/50 p-3 rounded-xl flex flex-wrap gap-3 items-center justify-between",children:[e.jsxs("div",{className:"flex flex-wrap items-center gap-2",children:[e.jsxs("span",{className:"text-xs font-bold text-gray-500 flex items-center gap-1",children:[e.jsx(As,{size:13}),a==="zh"?"筛选:":"Filters:"]}),e.jsxs("div",{className:"flex bg-slate-200/70 p-0.5 rounded-lg border border-slate-300/30 shadow-xs mr-2 shrink-0",children:[e.jsxs("button",{onClick:()=>l("week"),className:`px-2.5 py-1 rounded-lg text-xs font-bold transition-all flex items-center gap-1 ${m==="week"?"bg-white text-indigo-700 shadow-xs":"text-muted hover:text-gray-800"}`,children:[e.jsx(Ps,{size:11}),a==="zh"?"周课表":"Week View"]}),e.jsxs("button",{onClick:()=>l("cycle"),className:`px-2.5 py-1 rounded-lg text-xs font-bold transition-all flex items-center gap-1 ${m==="cycle"?"bg-white text-indigo-700 shadow-xs":"text-muted hover:text-gray-800"}`,children:[e.jsx(ut,{size:11}),a==="zh"?"星期总览":"Cycle View"]}),e.jsxs("button",{onClick:()=>l("list"),className:`px-2.5 py-1 rounded-lg text-xs font-bold transition-all flex items-center gap-1 ${m==="list"?"bg-white text-indigo-700 shadow-xs":"text-muted hover:text-gray-800"}`,children:[e.jsx(Es,{size:11}),a==="zh"?"列表":"List View"]})]}),e.jsxs("select",{id:"timetable_class_select",title:"Select Class",className:"bg-white border border-gray-200 rounded-lg text-xs py-1.5 px-2 text-gray-700 focus:outline-hidden focus:ring-1 focus:ring-indigo-500 font-sans cursor-pointer",value:j,onChange:r=>_(r.target.value),children:[e.jsx("option",{value:"all",children:a==="zh"?"所有班级 (All Classes)":"All Classes"}),C.map(r=>e.jsx("option",{value:r.id,children:H(r.name)},r.id))]}),e.jsxs("select",{id:"timetable_status_select",title:"Select Status",className:"bg-white border border-gray-200 rounded-lg text-xs py-1.5 px-2 text-gray-700 focus:outline-hidden focus:ring-1 focus:ring-indigo-500 font-sans cursor-pointer",value:A,onChange:r=>L(r.target.value),children:[e.jsx("option",{value:"all",children:a==="zh"?"所有状态 (All Status)":"All Status"}),e.jsx("option",{value:"scheduled",children:a==="zh"?"正常上课 (Scheduled)":"Scheduled"}),e.jsx("option",{value:"cancelled",children:a==="zh"?"停课 (Cancelled)":"Cancelled"}),e.jsx("option",{value:"holiday",children:a==="zh"?"假期调休 (Holiday)":"Holiday"}),e.jsx("option",{value:"swap",children:a==="zh"?"代课换课 (Swapped)":"Swapped"})]})]}),e.jsxs("div",{className:"flex items-center gap-2 flex-1 max-w-xs min-w-[200px]",children:[e.jsxs("div",{className:"relative w-full",children:[e.jsx(Os,{className:"absolute left-2.5 top-2 text-gray-400",size:14}),e.jsx("input",{type:"text",placeholder:a==="zh"?"检索课程标题, 班级, 备注...":"Search title, class, notes...",className:"w-full bg-white border border-gray-200 rounded-lg pl-8 pr-2.5 py-1.5 text-xs text-gray-700 focus:outline-hidden focus:ring-1 focus:ring-indigo-500",value:P,onChange:r=>w(r.target.value)}),P&&e.jsx("button",{onClick:()=>w(""),className:"absolute right-2.5 top-2 text-gray-400 hover:text-gray-600",children:e.jsx(ve,{size:14})})]}),e.jsxs("button",{onClick:()=>{$(C[0]?.id||""),se(""),Ce(new Date().toISOString().split("T")[0]),ke("scheduled"),ae(""),ie(!0)},className:"bg-indigo-600 hover:bg-indigo-700 text-white font-semibold text-xs py-1.5 px-3 rounded-lg flex items-center gap-1 shadow-sm shrink-0 cursor-pointer transition-all",children:[e.jsx(Jt,{size:14}),a==="zh"?"排定课时":"Schedule Class"]})]})]}),k?e.jsxs("div",{className:"flex flex-col items-center justify-center py-20 text-indigo-500",children:[e.jsx(Le,{className:"animate-spin mb-2",size:32}),e.jsx("span",{className:"text-xs font-semibold",children:a==="zh"?"查询数据中...":"Accessing SQLite Database..."})]}):E.length===0?e.jsxs("div",{className:"text-center py-16 bg-slate-50/50 border border-dashed rounded-xl border-slate-200 flex flex-col items-center",children:[e.jsx(Ue,{className:"text-gray-300 mb-2",size:40}),e.jsx("p",{className:"text-gray-500 text-sm font-semibold",children:a==="zh"?"暂未匹配到对应的课次安排数据":"No schedules match your filters"}),e.jsx("p",{className:"text-subtle text-xs mt-1",children:a==="zh"?"您可以点击右上角“排定课时”为班级新增课程。":"Try adding a new entry using the schedule button above."})]}):m==="list"?e.jsx("div",{className:"border border-slate-200 rounded-xl overflow-hidden shadow-2xs",children:e.jsxs("table",{className:"w-full text-left border-collapse table-auto text-sm bg-white",children:[e.jsx("thead",{children:e.jsxs("tr",{className:"bg-slate-50 border-b border-slate-200 text-gray-600 font-semibold text-xs",children:[e.jsx("th",{className:"p-3 w-[15%]",children:a==="zh"?"上课日期":"Date"}),e.jsx("th",{className:"p-3 w-[15%]",children:a==="zh"?"具体时间段":"Time Slot"}),e.jsx("th",{className:"p-3 w-[20%]",children:a==="zh"?"关联班级":"Class"}),e.jsx("th",{className:"p-3 w-[25%]",children:a==="zh"?"授课内容主题":"Lesson Topic"}),e.jsx("th",{className:"p-3 w-[10%] text-center",children:a==="zh"?"日常状态":"Status"}),e.jsx("th",{className:"p-3 w-[15%] text-right",children:a==="zh"?"教务微调":"Actions"})]})}),e.jsx("tbody",{className:"divide-y divide-slate-150",children:E.map(r=>{const x=r.status==="cancelled"||r.status==="holiday";return e.jsxs("tr",{className:`hover:bg-slate-50/80 transition-colors ${x?"bg-red-50/10 text-gray-400":"text-gray-700"}`,children:[e.jsx("td",{className:"p-3 font-semibold text-xs",children:e.jsxs("span",{className:"flex items-center gap-1",children:[e.jsx(Ue,{size:13,className:"text-slate-400"}),r.scheduled_date]})}),e.jsx("td",{className:"p-3 font-mono text-xs text-indigo-750",children:r.time_slot||e.jsx("span",{className:"text-xs text-gray-300 italic",children:a==="zh"?"全天":"All-day"})}),e.jsx("td",{className:"p-3 text-xs",children:e.jsx("span",{className:"bg-slate-100 text-slate-800 px-2 py-1 rounded-md border border-slate-250 font-medium",children:r.class_name})}),e.jsx("td",{className:"p-3",children:e.jsxs("div",{className:"flex flex-col leading-snug",children:[e.jsx("span",{className:`font-semibold ${x?"line-through opacity-70":""}`,children:r.lesson_title}),r.notes&&e.jsxs("span",{className:`text-xs italic mt-0.5 ${r.status==="holiday"?"text-amber-600 font-medium":r.status==="cancelled"?"text-red-500 font-medium":"text-slate-400"}`,children:["📌 ",r.notes]})]})}),e.jsx("td",{className:"p-3 text-center",children:e.jsx("span",{className:`inline-block text-xs px-2 py-0.5 rounded-full font-bold uppercase tracking-wide border ${r.status==="cancelled"?"bg-red-100 border-red-200 text-red-700":r.status==="holiday"?"bg-amber-100 border-amber-200 text-amber-700":r.status==="swap"?"bg-blue-100 border-blue-200 text-blue-700":"bg-green-100 border-green-200 text-green-700"}`,children:r.status==="cancelled"?a==="zh"?"停课":"Cancelled":r.status==="holiday"?a==="zh"?"假期调休":"Holiday":r.status==="swap"?a==="zh"?"换代课":"Swapped":a==="zh"?"正常上课":"Active"})}),e.jsx("td",{className:"p-3 text-right",children:e.jsxs("div",{className:"flex items-center justify-end gap-1.5",children:[ce(r,"sm"),e.jsx(we,{slot:"timetable.entry.action",slotProps:{schedule:r,lang:a,onEdit:()=>B(r)}}),e.jsx("button",{onClick:()=>B(r),className:"text-slate-500 hover:text-indigo-600 hover:bg-indigo-50 p-1.5 rounded transition-colors cursor-pointer",title:a==="zh"?"调整此节课排课 (换课/换时间/写备注)":"Adjust this class (Swap/Edit)",children:e.jsx(qe,{size:13})}),e.jsx("button",{onClick:()=>Se(r.id,r.class_id),className:"text-slate-500 hover:text-red-600 hover:bg-red-50 p-1.5 rounded transition-colors cursor-pointer",title:a==="zh"?"永久删除该课课表":"Delete schedule",children:e.jsx(Et,{size:13})})]})})]},r.id)})})]})}):e.jsxs("div",{className:"flex flex-col gap-4",children:[m==="week"&&e.jsxs("div",{className:"flex flex-col md:flex-row items-center justify-between bg-indigo-50/40 border border-indigo-100/60 p-3 rounded-xl gap-3 shadow-2xs",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("button",{onClick:()=>q(r=>new Date(r.getTime()-10080*60*1e3)),className:"p-1.5 rounded-lg hover:bg-indigo-100 hover:text-indigo-700 text-indigo-600 transition-all cursor-pointer border border-indigo-200/50 bg-white shadow-2xs flex items-center justify-center",title:a==="zh"?"上一周":"Previous Week",children:e.jsx(Ls,{size:16})}),e.jsx("button",{onClick:()=>q(me(new Date)),className:"px-3 py-1.5 rounded-lg hover:bg-indigo-100 hover:text-indigo-700 text-indigo-600 transition-all cursor-pointer text-xs font-bold border border-indigo-200/50 bg-white shadow-2xs",children:a==="zh"?"本周":"This Week"}),e.jsx("button",{onClick:()=>q(r=>new Date(r.getTime()+10080*60*1e3)),className:"p-1.5 rounded-lg hover:bg-indigo-100 hover:text-indigo-700 text-indigo-600 transition-all cursor-pointer border border-indigo-200/50 bg-white shadow-2xs flex items-center justify-center",title:a==="zh"?"下一周":"Next Week",children:e.jsx(Rs,{size:16})})]}),e.jsxs("div",{className:"text-sm font-bold text-indigo-900 flex items-center gap-2",children:[e.jsx(Ue,{size:16,className:"text-indigo-500"}),e.jsx("span",{children:h(he)})]}),e.jsxs("div",{className:"flex items-center gap-3 flex-wrap",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("span",{className:"text-xs text-indigo-700 font-semibold",children:a==="zh"?"跳转日期:":"Go to Date:"}),e.jsx("input",{type:"date",title:"Go to Date",className:"bg-white border border-indigo-200 rounded-lg text-xs py-1 px-2 text-indigo-950 focus:outline-hidden focus:ring-1 focus:ring-indigo-500 font-sans cursor-pointer",onChange:r=>{r.target.value&&q(me(new Date(r.target.value)))}})]}),e.jsx("div",{className:"flex items-center gap-2 border-l border-indigo-150 pl-3",children:e.jsxs("label",{className:"flex items-center gap-1.5 text-xs text-indigo-700 font-semibold cursor-pointer select-none",children:[e.jsx("input",{type:"checkbox",checked:ze,onChange:r=>le(r.target.checked),className:"w-3.5 h-3.5 text-indigo-600 border-indigo-300 rounded-sm focus:ring-indigo-500 focus:outline-hidden cursor-pointer"}),a==="zh"?"显示周末":"Show Weekend"]})})]})]}),e.jsx("div",{className:"w-full overflow-x-auto pb-2",children:e.jsxs("div",{className:"flex flex-col gap-4 min-w-[1050px]",children:[e.jsx("div",{className:`grid ${Y.length===5?"grid-cols-5":"grid-cols-7"} gap-4`,children:Y.map(r=>e.jsxs("div",{className:"bg-slate-50 border border-slate-200/50 rounded-xl p-3 text-center flex flex-col items-center justify-center gap-1 relative group/col",children:[e.jsxs("div",{className:"flex items-center justify-center gap-1.5 w-full",children:[e.jsx("span",{className:"font-extrabold text-xs text-indigo-700 uppercase tracking-wider",children:r.displayLabel}),m==="week"&&e.jsx("button",{onClick:()=>{const x=F[r.dateStr]||"";O(r.dateStr),x.startsWith("dow-")?(T("dow"),te(x.split("-")[1]),Q("")):x?(T("date"),Q(x),te("")):(T("dow"),te(""),Q(""))},className:"text-slate-400 hover:text-indigo-600 p-0.5 rounded-md hover:bg-slate-200/50 transition-all opacity-0 group-hover/col:opacity-100 focus:opacity-100 cursor-pointer flex items-center justify-center",title:a==="zh"?"临时切换显示日期":"Temporarily switch date",children:e.jsx(qe,{size:10})})]}),m==="week"&&F[r.dateStr]&&(()=>{const x=F[r.dateStr];let u="";if(x.startsWith("dow-")){const N=parseInt(x.split("-")[1],10);u=a==="zh"?`常规${["","周一","周二","周三","周四","周五","周六","周日"][N]}`:`Regular ${["","Mon","Tue","Wed","Thu","Fri","Sat","Sun"][N]}`}else u=x.substring(5);return e.jsxs("div",{className:"flex items-center gap-1 bg-amber-50 border border-amber-200 text-amber-700 text-xs px-1.5 py-0.5 rounded-md font-semibold select-none shadow-3xs animate-fade-in",children:[e.jsxs("span",{children:["🔄 ",u]}),e.jsx("button",{onClick:()=>{const N={...F};delete N[r.dateStr],W(N)},className:"hover:text-red-600 hover:bg-amber-100 rounded-sm p-px flex items-center justify-center cursor-pointer",title:a==="zh"?"恢复原日期课程":"Reset to original",children:e.jsx(ve,{size:8})})]})})()]},`header-${r.key}`))}),e.jsxs("div",{className:"bg-slate-50/30 border border-slate-200/50 rounded-2xl p-3 flex flex-col gap-2.5",children:[e.jsxs("div",{className:"flex items-center gap-1.5 text-xs font-bold text-sky-600 bg-sky-50 px-2 py-0.5 rounded-lg w-fit select-none border border-sky-100/60 shadow-3xs",children:[e.jsx(Qe,{size:10,className:"animate-pulse"}),a==="zh"?"上午课程 (AM)":"Morning (AM)"]}),e.jsx("div",{className:`grid ${Y.length===5?"grid-cols-5":"grid-cols-7"} gap-4`,children:Y.map(r=>{const x=r.schedules.filter(u=>!Ft(u.time_slot));return e.jsx("div",{className:"flex flex-col gap-2 bg-white/40 p-2.5 rounded-xl border border-dashed border-slate-200/60 min-h-[160px] justify-start",children:x.length===0?e.jsx("div",{className:"flex-1 flex items-center justify-center text-xs text-slate-350 italic text-center p-3 border border-dashed border-slate-150 rounded-xl bg-white/30 select-none",children:a==="zh"?"无课":"Free"}):x.map(u=>fe(u))},`morning-col-${r.key}`)})})]}),e.jsxs("div",{className:"relative my-2 flex items-center justify-center",children:[e.jsx("div",{className:"absolute inset-0 flex items-center","aria-hidden":"true",children:e.jsx("div",{className:"w-full border-t-2 border-dashed border-slate-200/80"})}),e.jsxs("div",{className:"relative flex justify-center text-xs font-extrabold uppercase tracking-wider text-slate-400 bg-white px-4 py-1.5 rounded-full border border-slate-200/60 shadow-3xs",children:["☕ ",a==="zh"?"午休时间 / Midday Break":"Lunch Break"]})]}),e.jsxs("div",{className:"bg-slate-50/30 border border-slate-200/50 rounded-2xl p-3 flex flex-col gap-2.5",children:[e.jsxs("div",{className:"flex items-center gap-1.5 text-xs font-bold text-amber-600 bg-amber-50 px-2 py-0.5 rounded-lg w-fit select-none border border-amber-100/60 shadow-3xs",children:[e.jsx(Ot,{size:10}),a==="zh"?"下午课程 (PM)":"Afternoon (PM)"]}),e.jsx("div",{className:`grid ${Y.length===5?"grid-cols-5":"grid-cols-7"} gap-4`,children:Y.map(r=>{const x=r.schedules.filter(u=>Ft(u.time_slot));return e.jsx("div",{className:"flex flex-col gap-2 bg-white/40 p-2.5 rounded-xl border border-dashed border-slate-200/60 min-h-[160px] justify-start",children:x.length===0?e.jsx("div",{className:"flex-1 flex items-center justify-center text-xs text-slate-350 italic text-center p-3 border border-dashed border-slate-150 rounded-xl bg-white/30 select-none",children:a==="zh"?"无课":"Free"}):x.map(u=>fe(u))},`afternoon-col-${r.key}`)})})]})]})})]})]})},Xs=({lang:a,holStartDate:m,setHolStartDate:l,holEndDate:j,setHolEndDate:_,holType:A,setHolType:L,holNotes:P,setHolNotes:w,handleBatchHolidayAdjustment:C,loading:H})=>e.jsxs("div",{className:"max-w-2xl mx-auto bg-slate-50/50 border border-slate-200 rounded-2xl p-6 shadow-3xs",children:[e.jsxs("h2",{className:"text-base font-bold text-slate-800 flex items-center gap-2 border-b border-slate-200 pb-3 mb-4",children:[e.jsx(Qe,{className:"text-amber-500 shrink-0",size:18}),a==="zh"?"批量节假日调休排班":"Holiday / Cancellation Scheduler"]}),e.jsx("p",{className:"text-xs text-gray-500 mb-5",children:a==="zh"?"此工具能快速把选定日期范围内的课程一键设为“假期调休”或“统一停课”,避免讲师依次手动调整,极大提高教务效率。":"Instantly cancel or exclude classes falling within a holiday or default break period."}),e.jsxs("div",{className:"space-y-4",children:[e.jsxs("div",{className:"grid grid-cols-2 gap-4",children:[e.jsxs("div",{children:[e.jsx("label",{className:"block text-xs font-semibold text-gray-700 mb-1.5",children:a==="zh"?"开始日期 *":"Start Date *"}),e.jsx("input",{type:"date",className:"w-full border border-gray-200 rounded-lg text-xs p-2.5 bg-white focus:outline-hidden focus:ring-1 focus:ring-indigo-500 transition-all font-sans text-gray-750",value:m,onChange:k=>l(k.target.value)})]}),e.jsxs("div",{children:[e.jsx("label",{className:"block text-xs font-semibold text-gray-700 mb-1.5",children:a==="zh"?"结束日期 *":"End Date *"}),e.jsx("input",{type:"date",className:"w-full border border-gray-200 rounded-lg text-xs p-2.5 bg-white focus:outline-hidden focus:ring-1 focus:ring-indigo-500 transition-all font-sans text-gray-750",value:j,onChange:k=>_(k.target.value)})]})]}),e.jsxs("div",{children:[e.jsx("label",{className:"block text-xs font-semibold text-gray-700 mb-1.5",children:a==="zh"?"调整状态标签":"Target Status"}),e.jsxs("div",{className:"flex gap-4",children:[e.jsxs("label",{className:"flex items-center gap-2 text-xs font-medium text-slate-700 cursor-pointer",children:[e.jsx("input",{type:"radio",name:"holType",checked:A==="holiday",onChange:()=>L("holiday"),className:"accent-indigo-600 cursor-pointer"}),"🏝️ ",a==="zh"?"假期调休 (Holiday)":"Holiday Exclusion"]}),e.jsxs("label",{className:"flex items-center gap-2 text-xs font-medium text-slate-700 cursor-pointer",children:[e.jsx("input",{type:"radio",name:"holType",checked:A==="cancelled",onChange:()=>L("cancelled"),className:"accent-red-600 cursor-pointer"}),"🛑 ",a==="zh"?"异常停课 (Cancelled)":"Suspicious Cancellation"]})]})]}),e.jsxs("div",{children:[e.jsx("label",{className:"block text-xs font-semibold text-gray-700 mb-1.5",children:a==="zh"?"假日说明 / 停课备注":"Exclusion Note / Reason"}),e.jsx("input",{type:"text",placeholder:a==="zh"?"例: 国庆节假期停课调休 / 因极寒气象全市停课":"e.g., National Day break / weather closures",className:"w-full border border-gray-200 rounded-lg text-xs p-2.5 bg-white focus:outline-hidden focus:ring-1 focus:ring-indigo-500 transition-all",value:P,onChange:k=>w(k.target.value)})]}),e.jsxs("button",{onClick:C,disabled:H,className:"w-full bg-slate-800 hover:bg-slate-900 text-white font-bold text-xs py-2.5 rounded-xl cursor-pointer transition-all flex items-center justify-center gap-1.5 shadow-sm disabled:opacity-50",children:[H?e.jsx(Le,{className:"animate-spin",size:14}):e.jsx(ut,{size:14}),a==="zh"?"一键更新该周期课表":"Execute Batch Holiday Updates"]})]})]}),ea=({lang:a,classes:m,getClassDisplayName:l,handleExportCSV:j,handleExportJSON:_,importClassId:A,setImportClassId:L,csvText:P,setCsvText:w,importMessage:C,handleImportData:H})=>e.jsxs("div",{className:"grid grid-cols-1 md:grid-cols-2 gap-8",children:[e.jsxs("div",{className:"bg-slate-50/50 border border-slate-200 rounded-xl p-5 flex flex-col justify-between",children:[e.jsxs("div",{children:[e.jsxs("h3",{className:"text-sm font-bold text-gray-800 flex items-center gap-2 border-b border-slate-100 pb-2.5 mb-3",children:[e.jsx(Ms,{className:"text-green-600",size:16}),a==="zh"?"导出系统课表":"Export Timetables"]}),e.jsx("p",{className:"text-xs text-gray-500 mb-4 leading-relaxed",children:a==="zh"?"把系统中当前排定的所有班级课表一键备份成标准 CSV 或 JSON 文件。您可以使用 Excel 便捷编辑修改后再导入回来。":"Download the compiled records from SQLite memory db into standard JSON or CSV sheet formats."})]}),e.jsxs("div",{className:"flex gap-2.5 mt-4",children:[e.jsxs("button",{onClick:j,className:"flex-1 bg-white hover:bg-slate-50 text-slate-800 border border-slate-250 font-bold text-xs py-2 rounded-lg cursor-pointer transition-all flex justify-center items-center gap-1",children:[e.jsx(Lt,{className:"text-green-600",size:13}),a==="zh"?"导出为 Excel CSV":"Export CSV Sheet"]}),e.jsxs("button",{onClick:_,className:"flex-1 bg-white hover:bg-slate-50 text-slate-800 border border-slate-250 font-bold text-xs py-2 rounded-lg cursor-pointer transition-all flex justify-center items-center gap-1",children:[e.jsx(Lt,{className:"text-amber-500",size:13}),a==="zh"?"导出为 JSON 树":"Export JSON Data"]})]})]}),e.jsxs("div",{className:"bg-slate-50/50 border border-slate-200 rounded-xl p-5 flex flex-col gap-3",children:[e.jsxs("h3",{className:"text-sm font-bold text-gray-800 flex items-center gap-2 border-b border-slate-100 pb-2.5",children:[e.jsx(Js,{className:"text-indigo-600",size:16}),a==="zh"?"导入课表流程":"Import New Schedule"]}),e.jsxs("div",{className:"flex flex-col gap-3",children:[e.jsxs("div",{children:[e.jsx("label",{className:"block text-xs uppercase font-bold text-gray-500 mb-1",children:a==="zh"?"分配排定给哪一个班级 *":"Target Class to load schedules *"}),e.jsxs("select",{id:"import_class_select",title:"Import Target Class",className:"w-full bg-white border border-gray-200 rounded-lg text-xs p-2 text-gray-750 cursor-pointer focus:outline-hidden",value:A,onChange:k=>L(k.target.value),children:[e.jsx("option",{value:"",children:a==="zh"?"选择班级...":"Select Class..."}),m.map(k=>e.jsx("option",{value:k.id,children:l(k.name)},k.id))]})]}),e.jsxs("div",{children:[e.jsx("label",{className:"block text-xs uppercase font-bold text-gray-500 mb-1",children:a==="zh"?"粘贴 CSV 数据内容":"Paste CSV data rows"}),e.jsx("textarea",{rows:4,placeholder:a==="zh"?`date,lesson_id,time_slot,status,notes
|
|
1
|
+
import{j as e,r as d}from"./vendor-react-Kv_JATwr.js";import{E as we,Y as ue,x as Cs,V as ks,Z as $s,_ as _s,N as Pt,Q as Ts,B as Ds,c as Is}from"./index-BzXADCXZ.js";import{aA as Mt,aJ as As,c7 as Ps,ad as ut,c2 as Es,a$ as Os,X as ve,ak as Jt,c as Le,bv as Ue,bt as qe,ac as Et,aT as Ls,f as Rs,z as Qe,$ as Ot,c8 as Fs,i as Wt,D as Ms,c9 as Lt,a8 as Js,C as Bt,ca as Ws,T as Bs,cb as Gs,u as Hs,cc as Rt,az as Vs,o as xt,a9 as Ys,aG as Us}from"./vendor-icons-CXrZ3R2V.js";import{A as qs}from"./AcademicYearFilter-DUUGpDKt.js";import{f as Qs}from"./teaching-modes-client-BeVaDdJ-.js";import"./vendor-utils-aM7aYvPP.js";import"./vendor-pdf-C1Vh2Aqq.js";import"./vendor-motion-BFAPOs-b.js";import"./vendor-charts-SrpBsvM3.js";const Ks=a=>{const m=[];for(let l=0;l<7;l++){const j=new Date(a.getTime()+l*24*60*60*1e3),_=j.getFullYear(),A=String(j.getMonth()+1).padStart(2,"0"),L=String(j.getDate()).padStart(2,"0");m.push(`${_}-${A}-${L}`)}return m},Ft=a=>{if(!a)return!1;const m=a.match(/^(\d{1,2}):(\d{2})/);return m?parseInt(m[1],10)>=12:!1},Zs=({lang:a,viewMode:m,setViewMode:l,selectedClassId:j,setSelectedClassId:_,statusFilter:A,setStatusFilter:L,searchQuery:P,setSearchQuery:w,classes:C,getClassDisplayName:H,loading:k,filteredSchedules:E,currentWeekMonday:he,setCurrentWeekMonday:q,showWeekend:ze,setShowWeekend:le,dateOverrides:F,setDateOverrides:W,setOverridingDateKey:O,setOverrideMode:T,setOverrideTargetDow:te,setOverrideTargetDate:Q,openEditModal:B,handleDeleteSchedule:Se,getDayOfWeekIndex:V,getMonday:me,getWeekRangeString:h,setFormClassId:$,setFormLessonId:se,setFormDate:Ce,setFormStatus:ke,setFormNotes:ae,setIsAddOpen:ie,onQuickStart:M,activeSessionLessonIds:oe})=>{const ne=[{key:1,label:a==="zh"?"周一 (Mon)":"Mon"},{key:2,label:a==="zh"?"周二 (Tue)":"Tue"},{key:3,label:a==="zh"?"周三 (Wed)":"Wed"},{key:4,label:a==="zh"?"周四 (Thu)":"Thu"},{key:5,label:a==="zh"?"周五 (Fri)":"Fri"},{key:6,label:a==="zh"?"周六 (Sat)":"Sat"},{key:7,label:a==="zh"?"周日 (Sun)":"Sun"}],pe=Ks(he),Re=r=>{const x=/^(\d{1,2}):(\d{2})\s*-\s*(\d{1,2}):(\d{2})$/.exec((r||"").trim());return x?{start:`${x[1].padStart(2,"0")}:${x[2]}`,end:`${x[3].padStart(2,"0")}:${x[4]}`}:null},de=(()=>{const r=new Date;return`${String(r.getHours()).padStart(2,"0")}:${String(r.getMinutes()).padStart(2,"0")}`})(),Ke=new Date().toISOString().split("T")[0],be=E.filter(r=>r.scheduled_date===Ke&&r.status!=="cancelled"&&r.status!=="holiday").sort((r,x)=>(r.time_slot||"").localeCompare(x.time_slot||"")),G=be.find(r=>{const x=Re(r.time_slot);return x&&x.start<=de&&de<=x.end}),$e=be.find(r=>{const x=Re(r.time_slot);return x&&x.start>de}),K=G||$e,ce=(r,x="xs")=>{const u=r.status==="cancelled"||r.status==="holiday",N=!!r.lesson_id,f=u||!N,g=N&&oe.has(r.lesson_id),D=u?a==="zh"?"停课/假期排课不能开始上课":"Cancelled/holiday schedules cannot start a class":N?g?a==="zh"?"该课已有进行中的课堂会话,点击直接进入":"An active session exists. Click to enter directly.":a==="zh"?"快速开始上这节课":"Quick start this class":a==="zh"?"未关联课程,请先编辑排课关联课程":"No lesson linked. Edit the schedule to link one first.",v=x==="sm"?"px-2.5 py-1 text-xs gap-1":"px-1.5 py-0.5 text-[11px] gap-0.5",y=g?a==="zh"?"进入课堂":"Enter class":a==="zh"?"开始上课":"Start class";return e.jsxs("button",{type:"button","data-testid":`quick-start-${r.id}`,disabled:f,"aria-label":`${y}:${D}:${r.lesson_title||r.class_name||r.id}`,title:D,onClick:()=>M(r),className:`flex items-center rounded-md font-bold transition-all ${f?"text-slate-300 bg-slate-50 border border-slate-100 cursor-not-allowed":g?"text-emerald-700 bg-emerald-50 border border-emerald-200 hover:bg-emerald-100 cursor-pointer":"text-white bg-indigo-600 hover:bg-indigo-700 border border-indigo-500 shadow-2xs cursor-pointer"} ${v}`,children:[g?e.jsx(Fs,{size:11,"aria-hidden":"true"}):e.jsx(Wt,{size:11,"aria-hidden":"true"}),g?a==="zh"?"进入课堂":"Enter":a==="zh"?"开始上课":"Start"]})},fe=r=>{const x=r.status==="cancelled"||r.status==="holiday";let u="border-l-green-500 bg-green-50/5 hover:bg-green-50/10 hover:border-l-green-600";return r.status==="cancelled"?u="border-l-red-500 bg-red-50/5 hover:bg-red-50/10 hover:border-l-red-600":r.status==="holiday"?u="border-l-amber-500 bg-amber-50/5 hover:bg-amber-50/10 hover:border-l-amber-600":r.status==="swap"&&(u="border-l-blue-500 bg-blue-50/5 hover:bg-blue-50/10 hover:border-l-blue-600"),e.jsxs("div",{className:`p-2.5 rounded-xl border border-slate-150 border-l-4 ${u} transition-all hover:shadow-xs relative group flex flex-col justify-between min-h-[85px]`,children:[e.jsxs("div",{children:[e.jsxs("div",{className:"text-xs font-mono text-slate-500 mb-1 font-bold flex justify-between items-center",children:[e.jsxs("span",{className:"flex items-center gap-1",children:[e.jsx(Ot,{size:11,className:"text-slate-400"}),r.time_slot||(a==="zh"?"全天":"All-day")]}),m==="cycle"&&e.jsx("span",{className:"text-xs text-slate-400 font-sans font-normal bg-slate-100 px-1 py-0.5 rounded-sm",children:r.scheduled_date})]}),e.jsx("div",{className:`font-extrabold text-sm text-slate-805 tracking-tight leading-snug mt-1 ${x?"line-through opacity-60 text-slate-400":""}`,title:r.lesson_title||"",children:r.class_name}),r.notes&&e.jsxs("div",{className:"text-xs text-amber-600 font-medium mt-1 truncate",title:r.notes,children:["📌 ",r.notes]})]}),e.jsxs("div",{className:"flex items-center justify-between mt-2.5 pt-2 border-t border-slate-100/50",children:[e.jsxs("div",{className:"flex items-center gap-1 flex-wrap",children:[e.jsx("span",{className:`inline-block text-xs px-1.5 py-0.5 rounded-full font-bold uppercase tracking-wide border ${r.status==="cancelled"?"bg-red-50 border-red-100 text-red-600":r.status==="holiday"?"bg-amber-50 border-amber-100 text-amber-600":r.status==="swap"?"bg-blue-50 border-blue-100 text-blue-600":"bg-green-50 border-green-100 text-green-600"}`,children:r.status==="cancelled"?a==="zh"?"停课":"Cancelled":r.status==="holiday"?a==="zh"?"假期":"Holiday":r.status==="swap"?a==="zh"?"代课":"Swapped":a==="zh"?"正常":"Active"}),e.jsx(we,{slot:"timetable.card.badge",slotProps:{schedule:r,lang:a}}),ce(r)]}),e.jsxs("div",{className:"flex gap-1 opacity-0 group-hover:opacity-100 transition-opacity items-center",children:[e.jsx(we,{slot:"timetable.entry.action",slotProps:{schedule:r,lang:a,onEdit:()=>B(r)}}),e.jsx("button",{onClick:()=>B(r),className:"text-slate-400 hover:text-indigo-600 hover:bg-indigo-50 p-1 rounded-md transition-colors cursor-pointer",title:a==="zh"?"微调":"Edit",children:e.jsx(qe,{size:11})}),e.jsx("button",{onClick:()=>Se(r.id,r.class_id,r.isRepeating,r.scheduled_date),className:"text-slate-400 hover:text-red-600 hover:bg-red-50 p-1 rounded-md transition-colors cursor-pointer",title:a==="zh"?"删除":"Delete",children:e.jsx(Et,{size:11})})]})]})]},r.id)},ge=(r,x)=>{if(r===x){const f=E.filter(y=>y.scheduled_date===x);if(f.length>0)return f;const g=V(x),D=E.filter(y=>V(y.scheduled_date)===g&&y.scheduled_date<=x),v={};return D.forEach(y=>{const Ne=`${y.class_id}_${y.time_slot||"all-day"}`;v[Ne]||(v[Ne]={...y,scheduled_date:x,isRepeating:!0})}),Object.values(v)}let u=[];if(r.startsWith("dow-")){const f=parseInt(r.split("-")[1],10),g=E.filter(v=>V(v.scheduled_date)===f&&v.scheduled_date<=x),D={};g.forEach(v=>{const y=`${v.class_id}_${v.time_slot||"all-day"}`;D[y]||(D[y]={...v,scheduled_date:x,isRepeating:!0})}),u=Object.values(D)}else{const f=E.filter(g=>g.scheduled_date===r);if(f.length>0)u=f.map(g=>({...g,scheduled_date:x,isRepeating:!0}));else{const g=V(r),D=E.filter(y=>V(y.scheduled_date)===g&&y.scheduled_date<=r),v={};D.forEach(y=>{const Ne=`${y.class_id}_${y.time_slot||"all-day"}`;v[Ne]||(v[Ne]={...y,scheduled_date:x,isRepeating:!0})}),u=Object.values(v)}}const N=E.filter(f=>f.scheduled_date===x);if(N.length>0){const f=[...u];return N.forEach(g=>{const D=`${g.class_id}_${g.time_slot||"all-day"}`,v=f.findIndex(y=>`${y.class_id}_${y.time_slot||"all-day"}`===D);v!==-1?f[v]=g:g.status!=="cancelled"&&g.status!=="holiday"&&f.push(g)}),f}return u},je=ne.map((r,x)=>{const u=pe[x],N=F[u]||u,f=ge(N,u);return f.sort((g,D)=>(g.time_slot||"").localeCompare(D.time_slot||"")),{...r,dateStr:u,displayLabel:a==="zh"?`${r.label.split(" ")[0]} (${u.substring(5)})`:`${r.label} (${u.substring(5)})`,schedules:f}}),ye=ne.map(r=>{const x=pe[r.key-1],u=E.filter(N=>V(N.scheduled_date)===r.key);return u.sort((N,f)=>(N.time_slot||"").localeCompare(f.time_slot||"")),{...r,dateStr:x,displayLabel:r.label,schedules:u}}),Y=(m==="week"?je:ye).filter(r=>m==="week"&&!ze?r.key!==6&&r.key!==7:!0);return e.jsxs("div",{className:"flex flex-col gap-4",children:[K&&e.jsxs("div",{id:"timetable_quick_start_card","data-testid":"timetable-quick-start-card",className:`flex flex-wrap items-center gap-3 p-3 rounded-xl border shadow-2xs ${G?"bg-emerald-50/60 border-emerald-200/70":"bg-indigo-50/60 border-indigo-200/60"}`,children:[e.jsxs("div",{className:`flex items-center gap-1.5 text-xs font-extrabold uppercase tracking-wider px-2 py-0.5 rounded-full border select-none ${G?"bg-emerald-100 border-emerald-200 text-emerald-700":"bg-indigo-100 border-indigo-200 text-indigo-700"}`,children:[e.jsx(Mt,{size:12,"aria-hidden":"true"}),G?a==="zh"?"正在进行":"In Progress":a==="zh"?"下一节课":"Up Next"]}),e.jsxs("div",{className:"flex-1 min-w-[180px] leading-snug",children:[e.jsx("div",{className:"text-sm font-bold text-slate-800",children:K.lesson_title||K.class_name}),e.jsxs("div",{className:"text-xs text-slate-500 flex flex-wrap gap-x-3",children:[e.jsx("span",{className:"font-mono",children:K.time_slot}),e.jsx("span",{children:K.class_name})]})]}),ce(K,"sm")]}),e.jsxs("div",{className:"bg-slate-50 border border-slate-200/50 p-3 rounded-xl flex flex-wrap gap-3 items-center justify-between",children:[e.jsxs("div",{className:"flex flex-wrap items-center gap-2",children:[e.jsxs("span",{className:"text-xs font-bold text-gray-500 flex items-center gap-1",children:[e.jsx(As,{size:13}),a==="zh"?"筛选:":"Filters:"]}),e.jsxs("div",{className:"flex bg-slate-200/70 p-0.5 rounded-lg border border-slate-300/30 shadow-xs mr-2 shrink-0",children:[e.jsxs("button",{onClick:()=>l("week"),className:`px-2.5 py-1 rounded-lg text-xs font-bold transition-all flex items-center gap-1 ${m==="week"?"bg-white text-indigo-700 shadow-xs":"text-muted hover:text-gray-800"}`,children:[e.jsx(Ps,{size:11}),a==="zh"?"周课表":"Week View"]}),e.jsxs("button",{onClick:()=>l("cycle"),className:`px-2.5 py-1 rounded-lg text-xs font-bold transition-all flex items-center gap-1 ${m==="cycle"?"bg-white text-indigo-700 shadow-xs":"text-muted hover:text-gray-800"}`,children:[e.jsx(ut,{size:11}),a==="zh"?"星期总览":"Cycle View"]}),e.jsxs("button",{onClick:()=>l("list"),className:`px-2.5 py-1 rounded-lg text-xs font-bold transition-all flex items-center gap-1 ${m==="list"?"bg-white text-indigo-700 shadow-xs":"text-muted hover:text-gray-800"}`,children:[e.jsx(Es,{size:11}),a==="zh"?"列表":"List View"]})]}),e.jsxs("select",{id:"timetable_class_select",title:"Select Class",className:"bg-white border border-gray-200 rounded-lg text-xs py-1.5 px-2 text-gray-700 focus:outline-hidden focus:ring-1 focus:ring-indigo-500 font-sans cursor-pointer",value:j,onChange:r=>_(r.target.value),children:[e.jsx("option",{value:"all",children:a==="zh"?"所有班级 (All Classes)":"All Classes"}),C.map(r=>e.jsx("option",{value:r.id,children:H(r.name)},r.id))]}),e.jsxs("select",{id:"timetable_status_select",title:"Select Status",className:"bg-white border border-gray-200 rounded-lg text-xs py-1.5 px-2 text-gray-700 focus:outline-hidden focus:ring-1 focus:ring-indigo-500 font-sans cursor-pointer",value:A,onChange:r=>L(r.target.value),children:[e.jsx("option",{value:"all",children:a==="zh"?"所有状态 (All Status)":"All Status"}),e.jsx("option",{value:"scheduled",children:a==="zh"?"正常上课 (Scheduled)":"Scheduled"}),e.jsx("option",{value:"cancelled",children:a==="zh"?"停课 (Cancelled)":"Cancelled"}),e.jsx("option",{value:"holiday",children:a==="zh"?"假期调休 (Holiday)":"Holiday"}),e.jsx("option",{value:"swap",children:a==="zh"?"代课换课 (Swapped)":"Swapped"})]})]}),e.jsxs("div",{className:"flex items-center gap-2 flex-1 max-w-xs min-w-[200px]",children:[e.jsxs("div",{className:"relative w-full",children:[e.jsx(Os,{className:"absolute left-2.5 top-2 text-gray-400",size:14}),e.jsx("input",{type:"text",placeholder:a==="zh"?"检索课程标题, 班级, 备注...":"Search title, class, notes...",className:"w-full bg-white border border-gray-200 rounded-lg pl-8 pr-2.5 py-1.5 text-xs text-gray-700 focus:outline-hidden focus:ring-1 focus:ring-indigo-500",value:P,onChange:r=>w(r.target.value)}),P&&e.jsx("button",{onClick:()=>w(""),className:"absolute right-2.5 top-2 text-gray-400 hover:text-gray-600",children:e.jsx(ve,{size:14})})]}),e.jsxs("button",{onClick:()=>{$(C[0]?.id||""),se(""),Ce(new Date().toISOString().split("T")[0]),ke("scheduled"),ae(""),ie(!0)},className:"bg-indigo-600 hover:bg-indigo-700 text-white font-semibold text-xs py-1.5 px-3 rounded-lg flex items-center gap-1 shadow-sm shrink-0 cursor-pointer transition-all",children:[e.jsx(Jt,{size:14}),a==="zh"?"排定课时":"Schedule Class"]})]})]}),k?e.jsxs("div",{className:"flex flex-col items-center justify-center py-20 text-indigo-500",children:[e.jsx(Le,{className:"animate-spin mb-2",size:32}),e.jsx("span",{className:"text-xs font-semibold",children:a==="zh"?"查询数据中...":"Accessing SQLite Database..."})]}):E.length===0?e.jsxs("div",{className:"text-center py-16 bg-slate-50/50 border border-dashed rounded-xl border-slate-200 flex flex-col items-center",children:[e.jsx(Ue,{className:"text-gray-300 mb-2",size:40}),e.jsx("p",{className:"text-gray-500 text-sm font-semibold",children:a==="zh"?"暂未匹配到对应的课次安排数据":"No schedules match your filters"}),e.jsx("p",{className:"text-subtle text-xs mt-1",children:a==="zh"?"您可以点击右上角“排定课时”为班级新增课程。":"Try adding a new entry using the schedule button above."})]}):m==="list"?e.jsx("div",{className:"border border-slate-200 rounded-xl overflow-hidden shadow-2xs",children:e.jsxs("table",{className:"w-full text-left border-collapse table-auto text-sm bg-white",children:[e.jsx("thead",{children:e.jsxs("tr",{className:"bg-slate-50 border-b border-slate-200 text-gray-600 font-semibold text-xs",children:[e.jsx("th",{className:"p-3 w-[15%]",children:a==="zh"?"上课日期":"Date"}),e.jsx("th",{className:"p-3 w-[15%]",children:a==="zh"?"具体时间段":"Time Slot"}),e.jsx("th",{className:"p-3 w-[20%]",children:a==="zh"?"关联班级":"Class"}),e.jsx("th",{className:"p-3 w-[25%]",children:a==="zh"?"授课内容主题":"Lesson Topic"}),e.jsx("th",{className:"p-3 w-[10%] text-center",children:a==="zh"?"日常状态":"Status"}),e.jsx("th",{className:"p-3 w-[15%] text-right",children:a==="zh"?"教务微调":"Actions"})]})}),e.jsx("tbody",{className:"divide-y divide-slate-150",children:E.map(r=>{const x=r.status==="cancelled"||r.status==="holiday";return e.jsxs("tr",{className:`hover:bg-slate-50/80 transition-colors ${x?"bg-red-50/10 text-gray-400":"text-gray-700"}`,children:[e.jsx("td",{className:"p-3 font-semibold text-xs",children:e.jsxs("span",{className:"flex items-center gap-1",children:[e.jsx(Ue,{size:13,className:"text-slate-400"}),r.scheduled_date]})}),e.jsx("td",{className:"p-3 font-mono text-xs text-indigo-750",children:r.time_slot||e.jsx("span",{className:"text-xs text-gray-300 italic",children:a==="zh"?"全天":"All-day"})}),e.jsx("td",{className:"p-3 text-xs",children:e.jsx("span",{className:"bg-slate-100 text-slate-800 px-2 py-1 rounded-md border border-slate-250 font-medium",children:r.class_name})}),e.jsx("td",{className:"p-3",children:e.jsxs("div",{className:"flex flex-col leading-snug",children:[e.jsx("span",{className:`font-semibold ${x?"line-through opacity-70":""}`,children:r.lesson_title}),r.notes&&e.jsxs("span",{className:`text-xs italic mt-0.5 ${r.status==="holiday"?"text-amber-600 font-medium":r.status==="cancelled"?"text-red-500 font-medium":"text-slate-400"}`,children:["📌 ",r.notes]})]})}),e.jsx("td",{className:"p-3 text-center",children:e.jsx("span",{className:`inline-block text-xs px-2 py-0.5 rounded-full font-bold uppercase tracking-wide border ${r.status==="cancelled"?"bg-red-100 border-red-200 text-red-700":r.status==="holiday"?"bg-amber-100 border-amber-200 text-amber-700":r.status==="swap"?"bg-blue-100 border-blue-200 text-blue-700":"bg-green-100 border-green-200 text-green-700"}`,children:r.status==="cancelled"?a==="zh"?"停课":"Cancelled":r.status==="holiday"?a==="zh"?"假期调休":"Holiday":r.status==="swap"?a==="zh"?"换代课":"Swapped":a==="zh"?"正常上课":"Active"})}),e.jsx("td",{className:"p-3 text-right",children:e.jsxs("div",{className:"flex items-center justify-end gap-1.5",children:[ce(r,"sm"),e.jsx(we,{slot:"timetable.entry.action",slotProps:{schedule:r,lang:a,onEdit:()=>B(r)}}),e.jsx("button",{onClick:()=>B(r),className:"text-slate-500 hover:text-indigo-600 hover:bg-indigo-50 p-1.5 rounded transition-colors cursor-pointer",title:a==="zh"?"调整此节课排课 (换课/换时间/写备注)":"Adjust this class (Swap/Edit)",children:e.jsx(qe,{size:13})}),e.jsx("button",{onClick:()=>Se(r.id,r.class_id),className:"text-slate-500 hover:text-red-600 hover:bg-red-50 p-1.5 rounded transition-colors cursor-pointer",title:a==="zh"?"永久删除该课课表":"Delete schedule",children:e.jsx(Et,{size:13})})]})})]},r.id)})})]})}):e.jsxs("div",{className:"flex flex-col gap-4",children:[m==="week"&&e.jsxs("div",{className:"flex flex-col md:flex-row items-center justify-between bg-indigo-50/40 border border-indigo-100/60 p-3 rounded-xl gap-3 shadow-2xs",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("button",{onClick:()=>q(r=>new Date(r.getTime()-10080*60*1e3)),className:"p-1.5 rounded-lg hover:bg-indigo-100 hover:text-indigo-700 text-indigo-600 transition-all cursor-pointer border border-indigo-200/50 bg-white shadow-2xs flex items-center justify-center",title:a==="zh"?"上一周":"Previous Week",children:e.jsx(Ls,{size:16})}),e.jsx("button",{onClick:()=>q(me(new Date)),className:"px-3 py-1.5 rounded-lg hover:bg-indigo-100 hover:text-indigo-700 text-indigo-600 transition-all cursor-pointer text-xs font-bold border border-indigo-200/50 bg-white shadow-2xs",children:a==="zh"?"本周":"This Week"}),e.jsx("button",{onClick:()=>q(r=>new Date(r.getTime()+10080*60*1e3)),className:"p-1.5 rounded-lg hover:bg-indigo-100 hover:text-indigo-700 text-indigo-600 transition-all cursor-pointer border border-indigo-200/50 bg-white shadow-2xs flex items-center justify-center",title:a==="zh"?"下一周":"Next Week",children:e.jsx(Rs,{size:16})})]}),e.jsxs("div",{className:"text-sm font-bold text-indigo-900 flex items-center gap-2",children:[e.jsx(Ue,{size:16,className:"text-indigo-500"}),e.jsx("span",{children:h(he)})]}),e.jsxs("div",{className:"flex items-center gap-3 flex-wrap",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("span",{className:"text-xs text-indigo-700 font-semibold",children:a==="zh"?"跳转日期:":"Go to Date:"}),e.jsx("input",{type:"date",title:"Go to Date",className:"bg-white border border-indigo-200 rounded-lg text-xs py-1 px-2 text-indigo-950 focus:outline-hidden focus:ring-1 focus:ring-indigo-500 font-sans cursor-pointer",onChange:r=>{r.target.value&&q(me(new Date(r.target.value)))}})]}),e.jsx("div",{className:"flex items-center gap-2 border-l border-indigo-150 pl-3",children:e.jsxs("label",{className:"flex items-center gap-1.5 text-xs text-indigo-700 font-semibold cursor-pointer select-none",children:[e.jsx("input",{type:"checkbox",checked:ze,onChange:r=>le(r.target.checked),className:"w-3.5 h-3.5 text-indigo-600 border-indigo-300 rounded-sm focus:ring-indigo-500 focus:outline-hidden cursor-pointer"}),a==="zh"?"显示周末":"Show Weekend"]})})]})]}),e.jsx("div",{className:"w-full overflow-x-auto pb-2",children:e.jsxs("div",{className:"flex flex-col gap-4 min-w-[1050px]",children:[e.jsx("div",{className:`grid ${Y.length===5?"grid-cols-5":"grid-cols-7"} gap-4`,children:Y.map(r=>e.jsxs("div",{className:"bg-slate-50 border border-slate-200/50 rounded-xl p-3 text-center flex flex-col items-center justify-center gap-1 relative group/col",children:[e.jsxs("div",{className:"flex items-center justify-center gap-1.5 w-full",children:[e.jsx("span",{className:"font-extrabold text-xs text-indigo-700 uppercase tracking-wider",children:r.displayLabel}),m==="week"&&e.jsx("button",{onClick:()=>{const x=F[r.dateStr]||"";O(r.dateStr),x.startsWith("dow-")?(T("dow"),te(x.split("-")[1]),Q("")):x?(T("date"),Q(x),te("")):(T("dow"),te(""),Q(""))},className:"text-slate-400 hover:text-indigo-600 p-0.5 rounded-md hover:bg-slate-200/50 transition-all opacity-0 group-hover/col:opacity-100 focus:opacity-100 cursor-pointer flex items-center justify-center",title:a==="zh"?"临时切换显示日期":"Temporarily switch date",children:e.jsx(qe,{size:10})})]}),m==="week"&&F[r.dateStr]&&(()=>{const x=F[r.dateStr];let u="";if(x.startsWith("dow-")){const N=parseInt(x.split("-")[1],10);u=a==="zh"?`常规${["","周一","周二","周三","周四","周五","周六","周日"][N]}`:`Regular ${["","Mon","Tue","Wed","Thu","Fri","Sat","Sun"][N]}`}else u=x.substring(5);return e.jsxs("div",{className:"flex items-center gap-1 bg-amber-50 border border-amber-200 text-amber-700 text-xs px-1.5 py-0.5 rounded-md font-semibold select-none shadow-3xs animate-fade-in",children:[e.jsxs("span",{children:["🔄 ",u]}),e.jsx("button",{onClick:()=>{const N={...F};delete N[r.dateStr],W(N)},className:"hover:text-red-600 hover:bg-amber-100 rounded-sm p-px flex items-center justify-center cursor-pointer",title:a==="zh"?"恢复原日期课程":"Reset to original",children:e.jsx(ve,{size:8})})]})})()]},`header-${r.key}`))}),e.jsxs("div",{className:"bg-slate-50/30 border border-slate-200/50 rounded-2xl p-3 flex flex-col gap-2.5",children:[e.jsxs("div",{className:"flex items-center gap-1.5 text-xs font-bold text-sky-600 bg-sky-50 px-2 py-0.5 rounded-lg w-fit select-none border border-sky-100/60 shadow-3xs",children:[e.jsx(Qe,{size:10,className:"animate-pulse"}),a==="zh"?"上午课程 (AM)":"Morning (AM)"]}),e.jsx("div",{className:`grid ${Y.length===5?"grid-cols-5":"grid-cols-7"} gap-4`,children:Y.map(r=>{const x=r.schedules.filter(u=>!Ft(u.time_slot));return e.jsx("div",{className:"flex flex-col gap-2 bg-white/40 p-2.5 rounded-xl border border-dashed border-slate-200/60 min-h-[160px] justify-start",children:x.length===0?e.jsx("div",{className:"flex-1 flex items-center justify-center text-xs text-slate-350 italic text-center p-3 border border-dashed border-slate-150 rounded-xl bg-white/30 select-none",children:a==="zh"?"无课":"Free"}):x.map(u=>fe(u))},`morning-col-${r.key}`)})})]}),e.jsxs("div",{className:"relative my-2 flex items-center justify-center",children:[e.jsx("div",{className:"absolute inset-0 flex items-center","aria-hidden":"true",children:e.jsx("div",{className:"w-full border-t-2 border-dashed border-slate-200/80"})}),e.jsxs("div",{className:"relative flex justify-center text-xs font-extrabold uppercase tracking-wider text-slate-400 bg-white px-4 py-1.5 rounded-full border border-slate-200/60 shadow-3xs",children:["☕ ",a==="zh"?"午休时间 / Midday Break":"Lunch Break"]})]}),e.jsxs("div",{className:"bg-slate-50/30 border border-slate-200/50 rounded-2xl p-3 flex flex-col gap-2.5",children:[e.jsxs("div",{className:"flex items-center gap-1.5 text-xs font-bold text-amber-600 bg-amber-50 px-2 py-0.5 rounded-lg w-fit select-none border border-amber-100/60 shadow-3xs",children:[e.jsx(Ot,{size:10}),a==="zh"?"下午课程 (PM)":"Afternoon (PM)"]}),e.jsx("div",{className:`grid ${Y.length===5?"grid-cols-5":"grid-cols-7"} gap-4`,children:Y.map(r=>{const x=r.schedules.filter(u=>Ft(u.time_slot));return e.jsx("div",{className:"flex flex-col gap-2 bg-white/40 p-2.5 rounded-xl border border-dashed border-slate-200/60 min-h-[160px] justify-start",children:x.length===0?e.jsx("div",{className:"flex-1 flex items-center justify-center text-xs text-slate-350 italic text-center p-3 border border-dashed border-slate-150 rounded-xl bg-white/30 select-none",children:a==="zh"?"无课":"Free"}):x.map(u=>fe(u))},`afternoon-col-${r.key}`)})})]})]})})]})]})},Xs=({lang:a,holStartDate:m,setHolStartDate:l,holEndDate:j,setHolEndDate:_,holType:A,setHolType:L,holNotes:P,setHolNotes:w,handleBatchHolidayAdjustment:C,loading:H})=>e.jsxs("div",{className:"max-w-2xl mx-auto bg-slate-50/50 border border-slate-200 rounded-2xl p-6 shadow-3xs",children:[e.jsxs("h2",{className:"text-base font-bold text-slate-800 flex items-center gap-2 border-b border-slate-200 pb-3 mb-4",children:[e.jsx(Qe,{className:"text-amber-500 shrink-0",size:18}),a==="zh"?"批量节假日调休排班":"Holiday / Cancellation Scheduler"]}),e.jsx("p",{className:"text-xs text-gray-500 mb-5",children:a==="zh"?"此工具能快速把选定日期范围内的课程一键设为“假期调休”或“统一停课”,避免讲师依次手动调整,极大提高教务效率。":"Instantly cancel or exclude classes falling within a holiday or default break period."}),e.jsxs("div",{className:"space-y-4",children:[e.jsxs("div",{className:"grid grid-cols-2 gap-4",children:[e.jsxs("div",{children:[e.jsx("label",{className:"block text-xs font-semibold text-gray-700 mb-1.5",children:a==="zh"?"开始日期 *":"Start Date *"}),e.jsx("input",{type:"date",className:"w-full border border-gray-200 rounded-lg text-xs p-2.5 bg-white focus:outline-hidden focus:ring-1 focus:ring-indigo-500 transition-all font-sans text-gray-750",value:m,onChange:k=>l(k.target.value)})]}),e.jsxs("div",{children:[e.jsx("label",{className:"block text-xs font-semibold text-gray-700 mb-1.5",children:a==="zh"?"结束日期 *":"End Date *"}),e.jsx("input",{type:"date",className:"w-full border border-gray-200 rounded-lg text-xs p-2.5 bg-white focus:outline-hidden focus:ring-1 focus:ring-indigo-500 transition-all font-sans text-gray-750",value:j,onChange:k=>_(k.target.value)})]})]}),e.jsxs("div",{children:[e.jsx("label",{className:"block text-xs font-semibold text-gray-700 mb-1.5",children:a==="zh"?"调整状态标签":"Target Status"}),e.jsxs("div",{className:"flex gap-4",children:[e.jsxs("label",{className:"flex items-center gap-2 text-xs font-medium text-slate-700 cursor-pointer",children:[e.jsx("input",{type:"radio",name:"holType",checked:A==="holiday",onChange:()=>L("holiday"),className:"accent-indigo-600 cursor-pointer"}),"🏝️ ",a==="zh"?"假期调休 (Holiday)":"Holiday Exclusion"]}),e.jsxs("label",{className:"flex items-center gap-2 text-xs font-medium text-slate-700 cursor-pointer",children:[e.jsx("input",{type:"radio",name:"holType",checked:A==="cancelled",onChange:()=>L("cancelled"),className:"accent-red-600 cursor-pointer"}),"🛑 ",a==="zh"?"异常停课 (Cancelled)":"Suspicious Cancellation"]})]})]}),e.jsxs("div",{children:[e.jsx("label",{className:"block text-xs font-semibold text-gray-700 mb-1.5",children:a==="zh"?"假日说明 / 停课备注":"Exclusion Note / Reason"}),e.jsx("input",{type:"text",placeholder:a==="zh"?"例: 国庆节假期停课调休 / 因极寒气象全市停课":"e.g., National Day break / weather closures",className:"w-full border border-gray-200 rounded-lg text-xs p-2.5 bg-white focus:outline-hidden focus:ring-1 focus:ring-indigo-500 transition-all",value:P,onChange:k=>w(k.target.value)})]}),e.jsxs("button",{onClick:C,disabled:H,className:"w-full bg-slate-800 hover:bg-slate-900 text-white font-bold text-xs py-2.5 rounded-xl cursor-pointer transition-all flex items-center justify-center gap-1.5 shadow-sm disabled:opacity-50",children:[H?e.jsx(Le,{className:"animate-spin",size:14}):e.jsx(ut,{size:14}),a==="zh"?"一键更新该周期课表":"Execute Batch Holiday Updates"]})]})]}),ea=({lang:a,classes:m,getClassDisplayName:l,handleExportCSV:j,handleExportJSON:_,importClassId:A,setImportClassId:L,csvText:P,setCsvText:w,importMessage:C,handleImportData:H})=>e.jsxs("div",{className:"grid grid-cols-1 md:grid-cols-2 gap-8",children:[e.jsxs("div",{className:"bg-slate-50/50 border border-slate-200 rounded-xl p-5 flex flex-col justify-between",children:[e.jsxs("div",{children:[e.jsxs("h3",{className:"text-sm font-bold text-gray-800 flex items-center gap-2 border-b border-slate-100 pb-2.5 mb-3",children:[e.jsx(Ms,{className:"text-green-600",size:16}),a==="zh"?"导出系统课表":"Export Timetables"]}),e.jsx("p",{className:"text-xs text-gray-500 mb-4 leading-relaxed",children:a==="zh"?"把系统中当前排定的所有班级课表一键备份成标准 CSV 或 JSON 文件。您可以使用 Excel 便捷编辑修改后再导入回来。":"Download the compiled records from SQLite memory db into standard JSON or CSV sheet formats."})]}),e.jsxs("div",{className:"flex gap-2.5 mt-4",children:[e.jsxs("button",{onClick:j,className:"flex-1 bg-white hover:bg-slate-50 text-slate-800 border border-slate-250 font-bold text-xs py-2 rounded-lg cursor-pointer transition-all flex justify-center items-center gap-1",children:[e.jsx(Lt,{className:"text-green-600",size:13}),a==="zh"?"导出为 Excel CSV":"Export CSV Sheet"]}),e.jsxs("button",{onClick:_,className:"flex-1 bg-white hover:bg-slate-50 text-slate-800 border border-slate-250 font-bold text-xs py-2 rounded-lg cursor-pointer transition-all flex justify-center items-center gap-1",children:[e.jsx(Lt,{className:"text-amber-500",size:13}),a==="zh"?"导出为 JSON 树":"Export JSON Data"]})]})]}),e.jsxs("div",{className:"bg-slate-50/50 border border-slate-200 rounded-xl p-5 flex flex-col gap-3",children:[e.jsxs("h3",{className:"text-sm font-bold text-gray-800 flex items-center gap-2 border-b border-slate-100 pb-2.5",children:[e.jsx(Js,{className:"text-indigo-600",size:16}),a==="zh"?"导入课表流程":"Import New Schedule"]}),e.jsxs("div",{className:"flex flex-col gap-3",children:[e.jsxs("div",{children:[e.jsx("label",{className:"block text-xs uppercase font-bold text-gray-500 mb-1",children:a==="zh"?"分配排定给哪一个班级 *":"Target Class to load schedules *"}),e.jsxs("select",{id:"import_class_select",title:"Import Target Class",className:"w-full bg-white border border-gray-200 rounded-lg text-xs p-2 text-gray-750 cursor-pointer focus:outline-hidden",value:A,onChange:k=>L(k.target.value),children:[e.jsx("option",{value:"",children:a==="zh"?"选择班级...":"Select Class..."}),m.map(k=>e.jsx("option",{value:k.id,children:l(k.name)},k.id))]})]}),e.jsxs("div",{children:[e.jsx("label",{className:"block text-xs uppercase font-bold text-gray-500 mb-1",children:a==="zh"?"粘贴 CSV 数据内容":"Paste CSV data rows"}),e.jsx("textarea",{rows:4,placeholder:a==="zh"?`date,lesson_id,time_slot,status,notes
|
|
2
2
|
2026-06-15,les-1,09:00 - 10:30,scheduled,首节授课
|
|
3
3
|
2026-06-16,les-2,10:45 - 12:15,holiday,假期放假停课`:`date,lesson_id,time_slot,status,notes
|
|
4
4
|
2026-06-15,les-1,09:00 - 10:30,scheduled,First Class`,className:"w-full bg-white border border-gray-250 text-xs p-2 rounded-lg font-mono placeholder:text-gray-350 focus:outline-hidden",value:P,onChange:k=>w(k.target.value)}),e.jsx("span",{className:"text-xs text-gray-400 mt-1 block",children:a==="zh"?"首行必须为属性列(支持:date, lesson_id, time_slot, status, notes)。支持复制 JSON 树粘贴直接解析。":"Ensure first line consists of column keys (date, lesson_id, time_slots)."})]}),C&&e.jsxs("div",{className:`p-2.5 rounded-lg text-xs border flex items-center gap-1.5 ${C.type==="error"?"bg-red-50 border-red-200 text-red-700":"bg-green-50 border-green-200 text-green-700"}`,children:[e.jsx(Bt,{size:14}),e.jsx("span",{children:C.text})]}),e.jsxs("button",{onClick:H,className:"w-full bg-indigo-600 hover:bg-indigo-700 text-white font-bold text-xs py-2 rounded-lg cursor-pointer transition-all flex items-center justify-center gap-1 shadow-xs",children:[e.jsx(Jt,{size:13}),a==="zh"?"开始解析并安全导入":"Execute Schema Check & Upload"]})]})]})]}),ta=({lang:a,ocrProviderId:m,setOcrProviderId:l,aiProviders:j,ocrFileInputRef:_,handleOcrDrop:A,handleOcrImageSelect:L,ocrImagePreview:P,setOcrImagePreview:w,setOcrImageBase64:C,setOcrEntries:H,setOcrMessage:k,setOcrSelectedEntries:E,ocrImageBase64:he,ocrLoading:q,handleOcrRecognize:ze,ocrProgressStatus:le,ocrProgress:F,ocrMessage:W,ocrEntries:O,ocrSelectedEntries:T,toggleAllOcrEntries:te,toggleOcrEntry:Q,dayNames:B,findMatchedClass:Se,handleOcrImport:V,ocrImporting:me})=>e.jsxs("div",{className:"flex flex-col gap-5",children:[e.jsxs("div",{className:"bg-slate-50/50 border border-slate-200 rounded-2xl p-5",children:[e.jsxs("h2",{className:"text-base font-bold text-slate-800 flex items-center gap-2 border-b border-slate-200 pb-3 mb-4",children:[e.jsx(Ws,{className:"text-violet-500 shrink-0",size:18}),a==="zh"?"第一步:上传课表图片":"Step 1: Upload Timetable Image"]}),e.jsx("p",{className:"text-xs text-gray-500 mb-4 leading-relaxed",children:a==="zh"?"拍照或截图您的纸质/电子课表,AI 将自动识别课程信息并生成结构化数据。支持 PNG、JPG 格式,建议图片清晰、文字可辨。":"Upload a photo or screenshot of your timetable. AI will automatically recognize class information and generate structured data."}),e.jsxs("div",{className:"mb-4 p-3 bg-white rounded-xl border border-slate-200",children:[e.jsxs("label",{className:"block text-xs font-semibold text-gray-700 mb-1.5 flex items-center gap-1.5",children:[e.jsx(Qe,{size:12,className:"text-violet-500"}),a==="zh"?"AI 识别引擎":"AI Recognition Engine"]}),j.length===0&&e.jsxs("div",{className:"p-3 bg-amber-50 border border-amber-200 rounded-xl text-xs text-amber-800 flex items-start gap-2 mb-2",children:[e.jsx(Bs,{size:15,className:"shrink-0 text-amber-600 mt-0.5"}),e.jsx("div",{className:"flex-1 leading-relaxed",children:a==="zh"?"未检测到可用的 AI 提供商。课表识别需借助支持视觉(Vision)的大模型(如 GPT-4o 等),请先前往「系统管理 -> AI 提供商管理」添加模型服务。":"No AI providers configured. Timetable recognition requires a vision-capable AI model. Please configure one in System Management."})]}),e.jsx("select",{title:"OCR AI Provider",disabled:j.length===0,className:"w-full bg-slate-50 border border-gray-200 rounded-lg text-xs p-2.5 text-gray-750 cursor-pointer focus:outline-hidden focus:ring-1 focus:ring-violet-500 disabled:opacity-60 disabled:cursor-not-allowed",value:m,onChange:h=>l(h.target.value),children:j.length===0?e.jsx("option",{value:"",disabled:!0,children:a==="zh"?"未配置 AI 提供商":"No AI Provider"}):j.map(h=>e.jsxs("option",{value:h.id,children:[h.name," (",h.model_name,")"]},h.id))}),e.jsx("span",{className:"text-xs text-gray-400 mt-1 block",children:a==="zh"?"选择用于识别课表图片的 AI 模型。需要支持图片输入的模型(如 GPT-4o 等)。":"Choose the AI model for timetable recognition. Must support vision/image input."})]}),e.jsxs("div",{className:"flex flex-col sm:flex-row gap-4",children:[e.jsxs("div",{className:"flex-1 border-2 border-dashed border-slate-300 rounded-xl p-6 flex flex-col items-center justify-center gap-3 cursor-pointer hover:border-violet-400 hover:bg-violet-50/30 transition-all group",onClick:()=>_.current?.click(),onDragOver:h=>{h.preventDefault(),h.stopPropagation()},onDrop:A,children:[e.jsx("input",{ref:_,type:"file",accept:"image/png,image/jpeg,image/jpg,image/webp",className:"hidden",onChange:L}),e.jsx(Gs,{className:"text-slate-400 group-hover:text-violet-500 transition-colors",size:36}),e.jsx("span",{className:"text-xs font-semibold text-slate-500 group-hover:text-violet-600 transition-colors",children:a==="zh"?"点击选择、拖拽图片至此处 或 Ctrl+V 粘贴截图":"Click, drag & drop, or Ctrl+V to paste screenshot"}),e.jsx("span",{className:"text-xs text-slate-400",children:a==="zh"?"支持 PNG / JPG / JPEG / WebP,最大 20MB":"Supports PNG / JPG / JPEG / WebP, max 20MB"})]}),P&&e.jsxs("div",{className:"flex-1 relative rounded-xl overflow-hidden border border-slate-200 bg-white shadow-sm",children:[e.jsx("img",{src:P,alt:"Timetable preview",className:"w-full h-full object-contain max-h-[280px]"}),e.jsx("button",{onClick:h=>{h.stopPropagation(),w(null),C(null),H([]),k(null),E(new Set),ue.getState().clearTimetableOcrTask(),_.current&&(_.current.value="")},className:"absolute top-2 right-2 bg-black/50 hover:bg-black/70 text-white p-1.5 rounded-lg transition-colors cursor-pointer",title:a==="zh"?"移除图片":"Remove image",children:e.jsx(ve,{size:14})}),e.jsxs("div",{className:"absolute bottom-2 left-2 bg-black/50 text-white text-xs px-2 py-1 rounded-lg flex items-center gap-1",children:[e.jsx(Hs,{size:10}),a==="zh"?"课表预览":"Preview"]})]})]}),e.jsx("button",{onClick:ze,disabled:!he||q||j.length===0,className:"mt-4 w-full bg-violet-600 hover:bg-violet-700 disabled:bg-slate-300 text-white font-bold text-xs py-2.5 rounded-xl cursor-pointer transition-all flex items-center justify-center gap-2 shadow-sm disabled:cursor-not-allowed",children:q?e.jsxs(e.Fragment,{children:[e.jsx(Le,{className:"animate-spin",size:14}),a==="zh"?"AI 识别中,请稍候...":"AI recognizing..."]}):e.jsxs(e.Fragment,{children:[e.jsx(Rt,{size:14}),a==="zh"?"开始 AI 智能识别":"Start AI Recognition"]})})]}),e.jsx(we,{slot:"timetable.import.source",slotProps:{lang:a,onImportEntries:h=>{H(h),E(new Set(h.map(($,se)=>se))),k({type:"success",text:a==="zh"?`✅ 外部导入成功!共载入 ${h.length} 节课程安排,请审核后导入。`:`✅ Successfully imported ${h.length} timetable entries. Review below.`})}}}),q&&e.jsxs("div",{className:"bg-slate-50 border border-slate-200 rounded-xl p-3.5 space-y-2.5 animate-in fade-in duration-200 text-left",children:[e.jsxs("div",{className:"flex justify-between items-center text-xs",children:[e.jsx("span",{className:"font-semibold text-slate-700",children:le}),e.jsxs("span",{className:"font-mono font-bold text-indigo-600",children:[F,"%"]})]}),e.jsx("div",{className:"w-full h-2 bg-slate-200 rounded-full overflow-hidden shrink-0",children:e.jsx("div",{className:"h-full bg-gradient-to-r from-violet-500 to-indigo-600 transition-all duration-300 rounded-full",style:{width:`${F}%`}})})]}),W&&e.jsxs("div",{className:`p-3 rounded-xl text-xs border flex items-start gap-2 ${W.type==="error"?"bg-red-50 border-red-200 text-red-700":W.type==="success"?"bg-green-50 border-green-200 text-green-700":"bg-blue-50 border-blue-200 text-blue-700"}`,children:[W.type==="error"?e.jsx(Vs,{size:14,className:"shrink-0 mt-0.5"}):W.type==="success"?e.jsx(xt,{size:14,className:"shrink-0 mt-0.5"}):e.jsx(Rt,{size:14,className:"shrink-0 mt-0.5 animate-pulse"}),e.jsx("span",{children:W.text})]}),O.length>0&&e.jsxs("div",{className:"bg-slate-50/50 border border-slate-200 rounded-2xl p-5",children:[e.jsxs("h2",{className:"text-base font-bold text-slate-800 flex items-center gap-2 border-b border-slate-200 pb-3 mb-4",children:[e.jsx(xt,{className:"text-emerald-500 shrink-0",size:18}),a==="zh"?"第二步:审核识别结果":"Step 2: Review Recognized Entries"]}),e.jsx("p",{className:"text-xs text-gray-500 mb-3",children:a==="zh"?"以下是 AI 从课表图片中识别出的课程安排,请勾选需要导入的条目。":"Below are the class entries recognized by AI. Select the ones you want to import."}),e.jsxs("div",{className:"flex items-center justify-between mb-3",children:[e.jsxs("label",{className:"flex items-center gap-2 text-xs font-medium text-slate-700 cursor-pointer select-none",children:[e.jsx("input",{type:"checkbox",checked:T.size===O.length,onChange:te,className:"accent-violet-600 cursor-pointer rounded"}),a==="zh"?`全选 (${T.size}/${O.length})`:`Select All (${T.size}/${O.length})`]}),e.jsx("span",{className:"text-xs text-slate-400",children:a==="zh"?"取消勾选可排除不需要导入的条目":"Uncheck to exclude entries from import"})]}),e.jsx("div",{className:"border border-slate-200 rounded-xl overflow-hidden shadow-2xs",children:e.jsxs("table",{className:"w-full text-left border-collapse table-auto text-xs bg-white",children:[e.jsx("thead",{children:e.jsxs("tr",{className:"bg-slate-50 border-b border-slate-200 text-gray-600 font-semibold text-xs uppercase tracking-wide",children:[e.jsx("th",{className:"p-2.5 w-[40px] text-center",children:"✓"}),e.jsx("th",{className:"p-2.5",children:a==="zh"?"星期":"Day"}),e.jsx("th",{className:"p-2.5",children:a==="zh"?"节次":"Period"}),e.jsx("th",{className:"p-2.5",children:a==="zh"?"班级":"Class"}),e.jsx("th",{className:"p-2.5",children:a==="zh"?"科目":"Subject"}),e.jsx("th",{className:"p-2.5",children:a==="zh"?"时间段":"Time"}),e.jsx("th",{className:"p-2.5",children:a==="zh"?"教室":"Room"}),e.jsx("th",{className:"p-2.5",children:a==="zh"?"教师":"Teacher"})]})}),e.jsx("tbody",{className:"divide-y divide-slate-100",children:O.map((h,$)=>e.jsxs("tr",{className:`hover:bg-violet-50/30 transition-colors cursor-pointer ${T.has($)?"bg-violet-50/20":"opacity-50"}`,onClick:()=>Q($),children:[e.jsx("td",{className:"p-2.5 text-center",children:e.jsx("input",{type:"checkbox",checked:T.has($),onChange:()=>Q($),onClick:se=>se.stopPropagation(),className:"accent-violet-600 cursor-pointer"})}),e.jsx("td",{className:"p-2.5 font-medium",children:e.jsx("span",{className:"inline-block bg-indigo-100 text-indigo-700 px-1.5 py-0.5 rounded-md text-xs font-bold",children:B[h.dayOfWeek]||`Day${h.dayOfWeek}`})}),e.jsx("td",{className:"p-2.5",children:e.jsx("span",{className:"inline-block bg-slate-100 text-slate-700 px-1.5 py-0.5 rounded-md text-xs font-bold",children:a==="zh"?`第${h.periodNumber}节`:`P${h.periodNumber}`})}),e.jsx("td",{className:"p-2.5 font-semibold text-slate-800",children:h.className||"-"}),e.jsx("td",{className:"p-2.5",children:e.jsx("span",{className:"inline-block bg-amber-100 text-amber-800 px-1.5 py-0.5 rounded-md text-xs font-bold",children:h.subject||"-"})}),e.jsx("td",{className:"p-2.5 font-mono text-slate-600",children:h.timeSlot||"-"}),e.jsx("td",{className:"p-2.5 text-slate-600",children:h.location||"-"}),e.jsx("td",{className:"p-2.5 text-slate-600",children:h.teacherName||"-"})]},$))})]})})]}),O.length>0&&e.jsxs("div",{className:"bg-slate-50/50 border border-slate-200 rounded-2xl p-5",children:[e.jsxs("h2",{className:"text-base font-bold text-slate-800 flex items-center gap-2 border-b border-slate-200 pb-3 mb-4",children:[e.jsx(xt,{className:"text-emerald-500 shrink-0",size:18}),a==="zh"?"第三步:确认导入日程":"Step 3: Confirm Import"]}),(()=>{const h=new Date,$=h.getDay(),se=h.getDate()-$+($===0?-6:1),ke=new Date(h.setDate(se)).toISOString().split("T")[0],ae=O.filter((oe,ne)=>T.has(ne)),ie=new Set;let M=0;return ae.forEach(oe=>{Se(oe.className||"")?M++:oe.className&&ie.add(oe.className.trim())}),e.jsxs("div",{className:"flex flex-col gap-4 mb-4",children:[e.jsxs("div",{className:"p-3.5 bg-indigo-50 border border-indigo-100 rounded-xl text-xs leading-relaxed",children:[e.jsxs("div",{className:"font-semibold text-indigo-900 flex items-center gap-1.5 mb-1.5",children:[e.jsx(Qe,{size:14,className:"text-indigo-600 animate-pulse"}),a==="zh"?"智能自动匹配规则":"Intelligent Auto-Mapping"]}),e.jsxs("div",{className:"text-gray-650 space-y-1",children:[e.jsxs("div",{children:["•"," ",a==="zh"?`本周起始日期(周一):${ke}`:`Week Start Date (Monday): ${ke}`]}),e.jsxs("div",{children:["•"," ",a==="zh"?"班级匹配:系统将根据识别到的班级名称自动导入至系统中对应班级。若班级不存在,将自动创建。":"Class Matching: System will automatically import entries into matched classes or create new classes on the fly."]})]})]}),e.jsxs("div",{className:"text-xs",children:[e.jsx("div",{className:"font-semibold text-gray-700",children:a==="zh"?`已选择 ${ae.length} 条记录,其中 ${M} 条可直接匹配到系统班级。`:`${ae.length} entries selected, ${M} matched existing classes.`}),ie.size>0&&e.jsxs("div",{className:"mt-2 p-2.5 bg-violet-50 border border-violet-200 text-violet-800 rounded-lg leading-relaxed",children:["💡"," ",a==="zh"?`以下识别出的班级在系统中暂不存在,导入时将自动创建:${Array.from(ie).join(", ")}`:`The following recognized classes do not exist and will be automatically created on import: ${Array.from(ie).join(", ")}.`]})]})]})})(),e.jsx("button",{onClick:V,disabled:me||T.size===0,className:"w-full bg-emerald-600 hover:bg-emerald-700 disabled:bg-slate-300 text-white font-bold text-xs py-2.5 rounded-xl cursor-pointer transition-all flex items-center justify-center gap-2 shadow-sm disabled:cursor-not-allowed",children:me?e.jsxs(e.Fragment,{children:[e.jsx(Le,{className:"animate-spin",size:14}),a==="zh"?"正在导入...":"Importing..."]}):e.jsxs(e.Fragment,{children:[e.jsx(Ys,{size:14}),a==="zh"?`确认导入选中的 ${T.size} 条课程`:`Import ${T.size} Selected Entries`]})})]})]}),sa=({classes:a,lessons:m,lang:l,onSchedulesUpdated:j,onClassesUpdated:_})=>{const A=Cs(),L=ks(),P=L?.academicYear==="all"?null:L?.academicYear??null,[w,C]=d.useState("view"),[H,k]=d.useState("week"),E=t=>{const s=new Date(t.getTime()),o=s.getDay(),i=s.getDate()-o+(o===0?-6:1),n=new Date(s.setDate(i));return n.setHours(0,0,0,0),n},[he,q]=d.useState(()=>E(new Date)),ze=t=>{const s=new Date(t.getTime()+5184e5),o=i=>{const n=i.getFullYear(),c=String(i.getMonth()+1).padStart(2,"0"),b=String(i.getDate()).padStart(2,"0");return`${n}-${c}-${b}`};return`${o(t)} ~ ${o(s)}`},[le,F]=d.useState(null),[W,O]=d.useState(""),[T,te]=d.useState("dow"),[Q,B]=d.useState(""),[Se,V]=d.useState({}),[me,h]=d.useState(!1),[$,se]=d.useState("all"),[Ce,ke]=d.useState(""),[ae,ie]=d.useState("all"),[M,oe]=d.useState([]),[ne,pe]=d.useState(!1),[Re,de]=d.useState(!1),[Ke,be]=d.useState(!1),[G,$e]=d.useState(null),[K,ce]=d.useState(""),[fe,ge]=d.useState(""),[je,ye]=d.useState(""),[Y,r]=d.useState("09:00 - 10:30"),[x,u]=d.useState("scheduled"),[N,f]=d.useState(""),[g,D]=d.useState(""),[v,y]=d.useState(""),[Ne,Fe]=d.useState(null),[Pe,ht]=d.useState(""),[Ee,mt]=d.useState(""),[Oe,Gt]=d.useState("holiday"),[pt,bt]=d.useState(""),[Me,Je]=d.useState(null),[_e,We]=d.useState(null),[Ze,Xe]=d.useState(""),[Ht,Be]=d.useState(!1),[Vt,ft]=d.useState(0),[Yt,gt]=d.useState(""),[re,Te]=d.useState([]),[Ut,R]=d.useState(null),[aa,ra]=d.useState(""),[la,ia]=d.useState(""),[qt,et]=d.useState(!1),[De,xe]=d.useState(new Set),Qt=d.useRef(null),[Kt,jt]=d.useState([]),[Ge,tt]=d.useState(""),Ie=$s(t=>t.timetableOcrTask),st=_s(t=>t.pendingTimetableSubTab),yt=d.useRef(!1);d.useEffect(()=>{const t=ue.getState().timetableOcrDraft;t&&(t.entries.length>0&&(yt.current=!0,Te(t.entries),xe(new Set(t.selected)),R({type:"info",text:l==="zh"?"已恢复上次的识别结果,请核对后导入。":"Previous OCR result restored. Review and import below."})),t.imagePreview&&Je(t.imagePreview),t.imageBase64&&We(t.imageBase64),t.fileName&&Xe(t.fileName),t.providerId&&tt(t.providerId));const s=ue.getState().timetableOcrTask?.status;(s==="running"||s==="completed")&&C("ocr_import")},[]),d.useEffect(()=>{st&&(C(st),Pt.getState().setPendingTimetableSubTab(null))},[st]),d.useEffect(()=>{const t=ue.getState().timetableOcrTask;!Me&&!_e&&re.length===0&&!t||ue.getState().setTimetableOcrDraft({imagePreview:Me,imageBase64:_e,fileName:Ze,providerId:Ge,entries:re,selected:Array.from(De)})},[Me,_e,Ze,Ge,re,De]);const[U,at]=d.useState(null),[Nt,vt]=d.useState([]),[Zt,wt]=d.useState(!1),[He,zt]=d.useState(null),[rt,St]=d.useState(!1),[Ct,lt]=d.useState(""),[Xt,es]=d.useState(new Set);d.useEffect(()=>{let t=!1;return(async()=>{try{const s=await fetch("/api/classroom/sessions?pageSize=all&status=active");if(!s.ok)return;const o=await s.json(),i=Array.isArray(o)?o:Array.isArray(o?.items)?o.items:[];t||es(new Set(i.map(n=>n.lessonId).filter(Boolean)))}catch{}})(),()=>{t=!0}},[]);const ts=t=>{at(t),zt(null),lt(""),Zt||Qs().then(s=>{vt(s),wt(!0)}).catch(()=>{vt([]),wt(!0)})},ss=async t=>{if(!(!U?.lesson_id||rt)){St(!0),lt("");try{const s=await fetch(`/api/classroom/sessions/${U.lesson_id}/init`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({classId:U.class_id,teachingModeId:t??void 0})});if(!s.ok){const o=await s.json().catch(()=>null);throw new Error(o?.error||(l==="zh"?"初始化课堂会话失败":"Failed to initialise the classroom session"))}Pt.getState().setPendingLiveClassLaunch({lessonId:U.lesson_id,classId:U.class_id,teachingModeId:t}),Ds.getState().setTeacherTab("live_class"),at(null)}catch(s){lt(s?.message||(l==="zh"?"初始化课堂会话失败,请重试":"Failed to initialise the classroom session"))}finally{St(!1)}}};d.useEffect(()=>{if(Ie?.status==="running")Be(!0),gt(l==="zh"?"🧠 AI 正在后台分析提取课表...":"🧠 AI analyzing timetable in background..."),C("ocr_import");else if(Ie?.status==="completed"){Be(!1),ft(100),C("ocr_import");const t=Ie.result?.entries||[];t.length>0&&re.length===0&&!yt.current&&(Te(t),xe(new Set(t.map((s,o)=>o))),R({type:"success",text:l==="zh"?`✅ 识别成功!共检测到 ${t.length} 节课程安排,请审核后导入。`:`✅ Success! Detected ${t.length} class entries. Review and import below.`}))}else Ie?.status==="failed"&&(Be(!1),R({type:"error",text:Ie.error||(l==="zh"?"课表识别失败":"OCR recognition failed")}))},[Ie,l,re.length]);const kt=["08:00 - 09:30","09:45 - 11:15","11:30 - 13:00","13:30 - 15:00","15:15 - 16:45","19:00 - 20:30"],$t=d.useRef(""),_t=d.useRef(""),as=t=>{try{const s=t.split("-");if(s.length<3)return 1;const o=parseInt(s[0],10),i=parseInt(s[1],10)-1,n=parseInt(s[2],10),b=new Date(o,i,n).getDay();return b===0?7:b}catch{return 1}},Z=async()=>{pe(!0);try{let t=[];const s=P?`&academicYear=${encodeURIComponent(P)}`:"";if($==="all"){const o=await fetch(`/api/schedules?pageSize=all${s}`);o.ok&&(t=Ts(await o.json()))}else{const o=a.find(i=>i.id===$);if(o){const i=await fetch(`/api/classes/${o.id}/schedules${P?`?academicYear=${encodeURIComponent(P)}`:""}`);i.ok&&(t=await i.json(),t.forEach(n=>{n.class_name=o.name}))}}t.sort((o,i)=>{const n=i.scheduled_date.localeCompare(o.scheduled_date);return n!==0?n:(o.time_slot||"").localeCompare(i.time_slot||"")}),oe(t)}catch(t){console.error(t)}finally{pe(!1)}};d.useEffect(()=>{const t=a.map(i=>`${i.id}:${i.name}`).join(","),s=t!==$t.current,o=$!==_t.current;a.length>0&&(s||o)&&($t.current=t,_t.current=$,Z())},[$,a,P]),d.useEffect(()=>{if(!A)return;const t=A.getDispatcher?.();if(!t)return;const s=t.registerHandler("host:refresh",async o=>{const i=o.action.payload.target;if(i==="timetable"||i==="all")return await Z(),j?.(),{success:!0,refreshed:["timetable"]}});return()=>{s.dispose()}},[A,j]),d.useEffect(()=>{fetch("/api/ai-providers").then(t=>t.ok?t.json():[]).then(t=>{const s=Array.isArray(t)?t:[];jt(s),s.length>0&&tt(o=>o&&s.some(i=>i.id===o)?o:s[0].id)}).catch(()=>jt([]))},[]);const rs=async t=>{if(t.preventDefault(),!K||!je){alert(l==="zh"?"请填写所有必填字段":"Please fill all required fields");return}try{const s=await fetch(`/api/classes/${K}/schedules`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({lessonId:fe,scheduledDate:je,timeSlot:Y,status:x,notes:N})});if(s.ok)de(!1),ce(""),ge(""),ye(""),f(""),u("scheduled"),Z(),j();else{const o=await s.json();alert(o.error||"Failed to schedule")}}catch(s){alert(s.message)}},ls=async t=>{if(t.preventDefault(),!!G)try{const s=G.isRepeating,o=s?`/api/classes/${G.class_id}/schedules`:`/api/classes/${G.class_id}/schedules/${G.id}`,n=await fetch(o,{method:s?"POST":"PUT",headers:{"Content-Type":"application/json"},body:JSON.stringify({lessonId:fe,scheduledDate:je,timeSlot:Y,status:x,notes:N})});if(n.ok)be(!1),$e(null),Z(),j();else{const c=await n.json();alert(c.error||"Failed to update schedule")}}catch(s){alert(s.message)}},is=async(t,s,o,i)=>{if(o&&i){if(!confirm(l==="zh"?"该课程是由上周循环生成的。您确定要取消(停课)本周这一天的课程安排吗?":"This is a repeating class. Do you want to cancel (set to Cancelled) this class for this week?"))return;try{const b=M.find(z=>z.id===t);(await fetch(`/api/classes/${s}/schedules`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({lessonId:b?.lesson_id||"",scheduledDate:i,timeSlot:b?.time_slot||"",status:"cancelled",notes:l==="zh"?"循环排课取消":"Repeating schedule cancelled"})})).ok?(Z(),j()):alert("Cancel failed")}catch(b){alert(b.message)}return}if(confirm(l==="zh"?"您确定要完全删除该条课表排课记录吗?关联的考勤记录也将一并清除!":"Are you sure you want to completely delete this schedule record? Associated attendance logs will be cleared as well!"))try{(await fetch(`/api/classes/${s}/schedules/${t}`,{method:"DELETE"})).ok?(Z(),j()):alert("Delete failed")}catch(c){alert(c.message)}},os=t=>{$e(t),ce(t.class_id),ge(t.lesson_id),ye(t.scheduled_date),r(t.time_slot||"09:00 - 10:30"),u(t.status||"scheduled"),f(t.notes||""),be(!0)},ns=async()=>{if(!Pe||!Ee){alert(l==="zh"?"请选择开始日期和结束日期":"Please select both start and end dates");return}const t=M.filter(i=>{const n=i.scheduled_date;return n>=Pe&&n<=Ee&&i.status!==Oe});if(t.length===0){alert(l==="zh"?"在此日期范围内没有找到可调整的研究课表记录!":"No schedules found in the selected date range to adjust!");return}const s=l==="zh"?`此操作将会把 ${Pe} 到 ${Ee} 之间的共 ${t.length} 个课时记录一键标记为 [${Oe==="holiday"?"假日停课":"异常停课"}]。确认执行吗?`:`This will mark ${t.length} active classes between ${Pe} and ${Ee} as [${Oe}]. Continue?`;if(!confirm||!confirm(s))return;pe(!0);let o=0;try{for(const i of t)(await fetch(`/api/classes/${i.class_id}/schedules/${i.id}`,{method:"PUT",headers:{"Content-Type":"application/json"},body:JSON.stringify({lessonId:i.lesson_id,scheduledDate:i.scheduled_date,timeSlot:i.time_slot,status:Oe,notes:pt||(l==="zh"?"假期统一调休":"Holiday adjustments")})})).ok&&o++;alert(l==="zh"?`调整成功!共更新 ${o} 个课表安排。`:`Success! Updated ${o} entries.`),ht(""),mt(""),bt(""),Z(),j()}catch(i){alert(i.message)}finally{pe(!1)}},it=t=>{if(!t.type.startsWith("image/")){R({type:"error",text:l==="zh"?"请选择图片文件(PNG, JPG, JPEG)":"Please select an image file (PNG, JPG, JPEG)"});return}if(t.size>20*1024*1024){R({type:"error",text:l==="zh"?"图片大小不能超过 20MB":"Image size must be under 20MB"});return}Xe(t.name);const s=new FileReader;s.onload=o=>{const i=o.target?.result;Je(i),We(i),Te([]),R(null),xe(new Set),ue.getState().clearTimetableOcrTask()},s.readAsDataURL(t)},ds=t=>{const s=t.target.files?.[0];s&&it(s)},cs=t=>{const s=t.clipboardData?.items;if(s){for(let o=0;o<s.length;o++)if(s[o].type.startsWith("image/")){t.preventDefault();const i=s[o].getAsFile();i&&it(i);return}}},xs=t=>{t.preventDefault(),t.stopPropagation();const s=t.dataTransfer?.files?.[0];s&&s.type.startsWith("image/")&&it(s)};d.useEffect(()=>{if(w!=="ocr_import")return;const t=s=>cs(s);return document.addEventListener("paste",t),()=>document.removeEventListener("paste",t)},[w,l]);const us=async()=>{if(!_e){R({type:"error",text:l==="zh"?"请先上传课表图片":"Please upload a timetable image first"});return}Be(!0),ft(15),gt(l==="zh"?"🚀 任务已在后台运行中,可随时切换页面...":"🚀 Task running in background, you can navigate away..."),R({type:"info",text:l==="zh"?"🔍 AI 正在后台分析提取课表,您可以随时前往其他页面,识别完成后将通过通知提醒您。":"🔍 AI is analyzing timetable in background, you can navigate freely."}),Te([]),ue.getState().startTimetableOcr({imageBase64:_e,lang:l==="zh"?"zh":"en",providerId:Ge||void 0,fileName:Ze})},hs=(t,s)=>{if(!s)return"";try{const o=new Date(s);let i=Number(t);isNaN(i)&&typeof t=="string"&&(t.includes("一")||t.includes("1")||t.includes("Mon")?i=1:t.includes("二")||t.includes("2")||t.includes("Tue")?i=2:t.includes("三")||t.includes("3")||t.includes("Wed")?i=3:t.includes("四")||t.includes("4")||t.includes("Thu")?i=4:t.includes("五")||t.includes("5")||t.includes("Fri")?i=5:t.includes("六")||t.includes("6")||t.includes("Sat")?i=6:(t.includes("日")||t.includes("天")||t.includes("7")||t.includes("Sun"))&&(i=7)),(isNaN(i)||i<1||i>7)&&(i=1);const n=i-1,c=new Date(o);return c.setDate(o.getDate()+n),c.toISOString().split("T")[0]}catch(o){return console.error("Failed to convert day of week to date:",o),s}},Tt=t=>{if(!t)return null;const s=t.replace(/\s+/g,"").trim(),o=s.match(/(\d+)(?:班)?\)?$/)||s.match(/\((\d+)\)/);if(!o)return null;const i=o[1];let n="",c=0;if(s.startsWith("高")?(n="高",s.includes("一")||s.includes("1")?c=1:s.includes("二")||s.includes("2")?c=2:(s.includes("三")||s.includes("3"))&&(c=3)):s.startsWith("初")?(n="初",s.includes("一")||s.includes("1")?c=1:s.includes("二")||s.includes("2")?c=2:(s.includes("三")||s.includes("3"))&&(c=3)):s.startsWith("七")||s.startsWith("7")?(n="初",c=1):s.startsWith("八")||s.startsWith("8")?(n="初",c=2):s.startsWith("九")||s.startsWith("9")?(n="初",c=3):s.startsWith("小")?(n="小",s.includes("一")||s.includes("1")?c=1:s.includes("二")||s.includes("2")?c=2:s.includes("三")||s.includes("3")?c=3:s.includes("四")||s.includes("4")?c=4:s.includes("五")||s.includes("5")?c=5:(s.includes("六")||s.includes("6"))&&(c=6)):s.startsWith("一")||s.startsWith("1")?(n="小",c=1):s.startsWith("二")||s.startsWith("2")?(n="小",c=2):s.startsWith("三")||s.startsWith("3")?(n="小",c=3):s.startsWith("四")||s.startsWith("4")?(n="小",c=4):s.startsWith("五")||s.startsWith("5")?(n="小",c=5):(s.startsWith("六")||s.startsWith("6"))&&(n="小",c=6),!n||c===0)return null;const b=new Date,J=b.getFullYear(),Ae=(b.getMonth()+1>=9?J:J-1)-(c-1);return`${n}${Ae}级${i}班`},ms=t=>{if(!t)return null;const s=t.match(/^(初|高|小|小学)(\d{4})级(\d+)班$/);if(!s)return null;const o=s[1],i=parseInt(s[2],10),n=s[3],c=new Date,b=c.getFullYear(),J=c.getMonth()+1;let z=b-i;if(J>=9&&(z+=1),z<1)return l==="zh"?"未开学":"Not Started";if(z>(o==="高"||o==="初"?3:6))return l==="zh"?"已毕业":"Graduated";const X=l==="zh"&&["","一","二","三","四","五","六","七","八","九","十"][z]||z.toString();return`${o}${X}(${n})`},ot=t=>{const s=ms(t);return s?`${t} (${s})`:t},nt=t=>{if(!t)return;const s=t.replace(/\s+/g,"").toLowerCase();let o=a.find(i=>{if(!i||!i.name)return!1;const n=i.name.replace(/\s+/g,"").toLowerCase();return n===s||n.includes(s)||s.includes(n)});if(!o){const i=s.replace(/[^0-9a-zA-Z\u4e00-\u9fa5]/g,"");o=a.find(n=>{if(!n||!n.name)return!1;const c=n.name.replace(/\s+/g,"").toLowerCase().replace(/[^0-9a-zA-Z\u4e00-\u9fa5]/g,"");return c===i||c.includes(i)||i.includes(c)})}return o},ps=async()=>{try{if(De.size===0){R({type:"error",text:l==="zh"?"请至少选择一条课程记录":"Please select at least one entry"});return}const t={1:"08:00 - 08:40",2:"08:50 - 09:30",3:"10:00 - 10:40",4:"10:50 - 11:30",5:"11:40 - 12:15",6:"14:20 - 15:00",7:"15:10 - 15:50",8:"16:20 - 17:00",9:"19:00 - 20:30"},s=new Date,o=s.getDay(),i=s.getDate()-o+(o===0?-6:1),c=new Date(s.setDate(i)).toISOString().split("T")[0];et(!0),R(null);const b=re.filter((p,I)=>De.has(I)),J=new Set;b.forEach(p=>{if(p.className){const I=Tt(p.className)||p.className.trim();nt(I)||J.add(I)}});const z={};J.size>0&&(await Promise.all(Array.from(J).map(async p=>{try{const I=await fetch("/api/classes",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({name:p,description:"OCR自动生成规范班级"})});if(I.ok){const ee=await I.json();ee.success&&ee.id&&(z[p]=ee.id)}}catch(I){console.error(`Failed to dynamically create class ${p}:`,I)}})),_&&_());const S={},Ae=new Set;b.forEach(p=>{const I=hs(p.dayOfWeek||1,c),ee=p.timeSlot||t[p.periodNumber]||"09:00 - 10:30",Ve=p.className?Tt(p.className)||p.className.trim():"",It=nt(Ve),Ye=It?It.id:Ve?z[Ve]:null;if(!Ye){p.className&&Ae.add(p.className);return}const ws=m.find(zs=>{const ct=zs.title.toLowerCase(),At=Ve.toLowerCase(),Ss=(p.subject||"").toLowerCase();return ct.includes(At)||ct.includes(Ss)||At.includes(ct)});S[Ye]||(S[Ye]=[]),S[Ye].push({lessonId:ws?.id||"",scheduledDate:I,timeSlot:ee,status:"scheduled",notes:`${p.className||""} ${p.subject||""} ${p.location?"教室:"+p.location:""} ${p.teacherName?"教师:"+p.teacherName:""}`.trim()})});const X=Object.keys(S);if(X.length===0){R({type:"error",text:l==="zh"?"无法导入:没有解析出任何有效的班级名称。":"Could not match or create any classes for import."}),et(!1);return}let dt=0;await Promise.all(X.map(async p=>{const I=await fetch(`/api/classes/${p}/schedules/batch`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({schedules:S[p]})});if(I.ok){const ee=await I.json();dt+=ee.count||0}else{const ee=await I.json().catch(()=>({}));throw new Error(ee.error||`Failed to import schedules for class ${p}`)}})),Te([]),xe(new Set),Je(null),We(null),Xe(""),ue.getState().clearTimetableOcrTask();let Dt=l==="zh"?`🎉 导入成功!共写入 ${dt} 节课时安排。`:`🎉 Import successful! Saved ${dt} schedule entries.`;if(J.size>0){const p=Array.from(J).filter(I=>z[I]);p.length>0&&(Dt+=l==="zh"?`(自动创建并规范了新班级:${p.join(", ")})`:` (Automatically created classes: ${p.join(", ")})`)}R({type:"success",text:Dt}),Z(),j()}catch(t){console.error("OCR Import Error:",t),alert(`${l==="zh"?"导入出错提示:":"Import error alert: "}${t.message}`),R({type:"error",text:`${l==="zh"?"导入失败:":"Import failed: "}${t.message}`})}finally{et(!1)}},bs=t=>{xe(s=>{const o=new Set(s);return o.has(t)?o.delete(t):o.add(t),o})},fs=()=>{De.size===re.length?xe(new Set):xe(new Set(re.map((t,s)=>s)))},gs=l==="zh"?["","周一","周二","周三","周四","周五","周六","周日"]:["","Mon","Tue","Wed","Thu","Fri","Sat","Sun"],js=()=>{const t=["Date","Class Name","Lesson Title","Time Slot","Status","Notes","Class ID","Lesson ID"],s=M.map(c=>[c.scheduled_date,c.class_name||"",c.lesson_title||"",c.time_slot||"",c.status||"scheduled",c.notes||"",c.class_id,c.lesson_id]),o="data:text/csv;charset=utf-8,"+[t.join(","),...s.map(c=>c.map(b=>`"${String(b).replace(/"/g,'""')}"`).join(","))].join(`
|