openlearn-next 0.4.2 → 0.6.0

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.
Files changed (74) hide show
  1. package/README.md +21 -20
  2. package/dist/assets/ActivityWorkspaceWidget-_6XMBAcc.js +1 -0
  3. package/dist/assets/AdminDirectoryView-BufUF-sk.js +5 -0
  4. package/dist/assets/{BatchPickerModal-BpWu0Lil.js → BatchPickerModal-CES2DlPx.js} +1 -1
  5. package/dist/assets/ClassesView-BLvRJKcc.js +24 -0
  6. package/dist/assets/ClassroomCountdownWidget-DfKotHP8.js +2 -0
  7. package/dist/assets/{CloudDriveModal-DEQ1nkNk.js → CloudDriveModal-CLe4I18S.js} +1 -1
  8. package/dist/assets/ComputerLabView-CPnWWguS.js +1 -0
  9. package/dist/assets/CourseManagement-BSR61ggI.js +1 -0
  10. package/dist/assets/CourseWizardModal-D2m3PG7k.js +3 -0
  11. package/dist/assets/CoursewareHubPanel-gqjte-Pv.js +1 -0
  12. package/dist/assets/Dashboard-BPBJd0QR.js +8 -0
  13. package/dist/assets/ExportWeightModal-C3gIzDaP.js +1 -0
  14. package/dist/assets/HelpTour-B-RKDb1-.js +1 -0
  15. package/dist/assets/{HelpView-CtzdqhBq.js → HelpView-Bk64VK-J.js} +12 -12
  16. package/dist/assets/ImportLessonsModal-DUGpcZV3.js +1 -0
  17. package/dist/assets/ImportModal-ChY_Y5DZ.js +1 -0
  18. package/dist/assets/InteractiveCoursewareViewer-B9wvha7w.js +1 -0
  19. package/dist/assets/InteractiveWhiteboard-FPrze5CJ.js +78 -0
  20. package/dist/assets/LazyCourseware-BV5nOs5y.js +2 -0
  21. package/dist/assets/LazyWhiteboard-Cy5DdYnO.js +2 -0
  22. package/dist/assets/LessonEditorView-3SyplRhr.js +1 -0
  23. package/dist/assets/LiveClassroomView-CX7SUnmx.js +61 -0
  24. package/dist/assets/{NotificationDetailModal-Baqnc5pU.js → NotificationDetailModal-BBATA8Lh.js} +1 -1
  25. package/dist/assets/{PluginView-CCbIuZ24.js → PluginView-D5jMNscn.js} +5 -5
  26. package/dist/assets/ProcessLogsModal-DfKPVIYe.js +1 -0
  27. package/dist/assets/{QuizGeneratorModal-BBEDssp7.js → QuizGeneratorModal-CbRirQId.js} +1 -1
  28. package/dist/assets/StudentAssignmentView-ucXAOac9.js +1 -0
  29. package/dist/assets/StudentLessonView-CW6FYMtd.js +13 -0
  30. package/dist/assets/StudentView-Bxrut8tS.js +2 -0
  31. package/dist/assets/SystemResourceLibraryModal-CXdrWHDL.js +1 -0
  32. package/dist/assets/TeacherView-DXg0boJH.js +2 -0
  33. package/dist/assets/TimetableView-DPABkaFX.js +6 -0
  34. package/dist/assets/index-B3W5zons.css +1 -0
  35. package/dist/assets/index-B6wtREUD.js +221 -0
  36. package/dist/assets/{index.es-C5eWEO4o.js → index.es-DvJa33KC.js} +1 -1
  37. package/dist/assets/{vendor-charts-qLbgF1eL.js → vendor-charts-DGsG2RUv.js} +1 -1
  38. package/dist/assets/{vendor-icons-BRmhY6fg.js → vendor-icons-CyfamhaC.js} +2 -2
  39. package/dist/assets/{vendor-konva-CEOq4dcl.js → vendor-konva-DBWwlLTb.js} +1 -1
  40. package/dist/assets/{vendor-pdf-D7rGevI1.js → vendor-pdf-D0UGJOgo.js} +49 -49
  41. package/dist/assets/{vendor-pptx-C5-U7ieS.js → vendor-pptx-D4btWy5L.js} +8 -8
  42. package/dist/assets/{vendor-react-B0t7H3hh.js → vendor-react-CZ1I7IcM.js} +1 -1
  43. package/dist/assets/{vendor-utils-m0Urvtws.js → vendor-utils-B6R8dnOe.js} +1 -1
  44. package/dist/index.html +13 -10
  45. package/dist/server.cjs +19224 -11247
  46. package/package.json +11 -4
  47. package/dist/assets/AdminDirectoryView-DY--WM5Z.js +0 -1
  48. package/dist/assets/ClassesView-KbHEqJto.js +0 -22
  49. package/dist/assets/ClassroomCountdownWidget-96WFRO9A.js +0 -2
  50. package/dist/assets/ComputerLabView-1qWDNRQ2.js +0 -1
  51. package/dist/assets/CourseManagement-D3ZpxY0l.js +0 -1
  52. package/dist/assets/CourseWizardModal-Ck_-M8pk.js +0 -3
  53. package/dist/assets/CoursewareHubPanel-CaEizhxl.js +0 -1
  54. package/dist/assets/Dashboard-CYbpbofV.js +0 -8
  55. package/dist/assets/ExportWeightModal-DW2bu9Zz.js +0 -1
  56. package/dist/assets/HelpTour-CMJbbGne.js +0 -1
  57. package/dist/assets/ImportLessonsModal-jBuIK453.js +0 -1
  58. package/dist/assets/ImportModal-D7L-KNhZ.js +0 -1
  59. package/dist/assets/InteractiveCoursewareViewer-Bj7ahXMs.js +0 -1
  60. package/dist/assets/InteractiveWhiteboard-B7JcJvDu.js +0 -77
  61. package/dist/assets/LazyCourseware-CuiPxhDg.js +0 -2
  62. package/dist/assets/LazyWhiteboard-BJwCEZAU.js +0 -2
  63. package/dist/assets/LessonEditorView-DFrOp2qp.js +0 -1
  64. package/dist/assets/LiveClassroomView-BZ5nGee3.js +0 -59
  65. package/dist/assets/ProcessLogsModal-DmFXg9mG.js +0 -1
  66. package/dist/assets/StudentAssignmentView-DgIjUsXz.js +0 -1
  67. package/dist/assets/StudentLessonView-CBJbI5x6.js +0 -1
  68. package/dist/assets/StudentPreviewModal-Bh8OZs0t.js +0 -1
  69. package/dist/assets/StudentView--uGxc5TJ.js +0 -2
  70. package/dist/assets/SystemResourceLibraryModal-BVCclcqA.js +0 -1
  71. package/dist/assets/TeacherView-D4Zsc0eZ.js +0 -2
  72. package/dist/assets/TimetableView-BQG-rEb5.js +0 -6
  73. package/dist/assets/index-BKBCBKvy.js +0 -217
  74. package/dist/assets/index-CvGu7LSj.css +0 -1
@@ -0,0 +1,78 @@
1
+ const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/vendor-react-CZ1I7IcM.js","assets/vendor-utils-B6R8dnOe.js"])))=>i.map(i=>d[i]);
2
+ import{r as i,j as e,R as Bs,b as Ur}from"./vendor-react-CZ1I7IcM.js";import{S as Gr,L as Kr,G as Ze,H as Qe,a as ts,R as Rr,C as _r,T as Ar}from"./vendor-konva-DBWwlLTb.js";/* empty css */import{K as Pt,c as Vr,d as ai,L as oi,N as ss,f as ae,O as li,M as Fr,E as _e,Q as ns,R as ci,T as di,v as ui,G as xi,U as hi,V as Lr,W as mi,X as pi,Y as fi}from"./index-B6wtREUD.js";import{c6 as Zr,af as bi,bA as Hs,m as Ws,c7 as gi,a8 as ct,l as Qr,c as Ke,w as Yt,n as Ps,N as en,c8 as yi,Z as wi,e as tn,ah as Ct,ao as sn,q as rn,an as Xs,_ as is,aR as Wt,f as Xt,i as ji,B as vi,u as Es,a3 as as,aq as Ut,P as Cs,c9 as nn,aO as an,bE as on,bB as ln,ae as cn,al as qs,c0 as Ni,aS as Rs,bC as ki,a9 as Ci,a1 as Si,ab as Br,ag as It,X as Jt,U as _s,o as Ot,T as dn,bb as zi,ar as $i,O as Mi,C as qt,k as Ti,ca as un,cb as Di,bK as Pi,cc as Ei,cd as Ri,ce as _i,bP as Ai,az as Fi,aa as Li,b7 as Ss}from"./vendor-icons-CyfamhaC.js";import{v as oe}from"./vendor-pptx-D4btWy5L.js";import{_ as Bi}from"./vendor-pdf-D0UGJOgo.js";import"./vendor-utils-B6R8dnOe.js";import"./vendor-motion-BFAPOs-b.js";import"./vendor-charts-DGsG2RUv.js";function Hi(t={},r={}){const{replay:x=0,maxItems:l=50}=r,[c,u]=i.useState(()=>x>0?Pt.query(t,{limit:x}):[]),d=i.useRef(t);d.current=t;const a=i.useCallback(n=>{u(g=>{const j=[n,...g];return j.length>l&&(j.length=l),j})},[l]);return i.useEffect(()=>(x>0?u(Pt.query(t,{limit:x})):u([]),Pt.subscribe(d.current,a)),[JSON.stringify(t),x,a]),c}function Wi(t,r,x={}){const l=i.useRef(r);l.current=r;const c=i.useRef(t);c.current=t,i.useEffect(()=>Pt.subscribe(c.current,d=>l.current(d),x),[JSON.stringify(t),x.replay])}function Xi({lessonId:t,defaultCollapsed:r=!0}){const[x,l]=i.useState(r),[c,u]=i.useState(""),[d,a]=i.useState(""),[n,g]=i.useState(!1),j=i.useMemo(()=>({lessonId:t,types:c?[c]:void 0,sources:d?[d]:void 0}),[t,c,d]),P=Hi(j,{replay:100,maxItems:100}),X=i.useMemo(()=>P,[P,n]),k=i.useMemo(()=>Pt.stats(),[P]),M=i.useMemo(()=>Object.keys(k.byType).sort(),[k]);return e.jsx("div",{"data-testid":"whiteboard-event-panel",className:"fixed bottom-4 right-4 z-50",style:{maxWidth:380},children:x?e.jsxs("button",{type:"button",onClick:()=>l(!1),"data-testid":"whiteboard-event-panel-toggle",className:"px-3 py-2 bg-white/95 backdrop-blur-sm rounded-lg shadow-lg border border-gray-200 text-xs font-medium text-gray-700 hover:bg-white",children:["🔔 事件流 (",P.length,")"]}):e.jsxs("div",{"data-testid":"whiteboard-event-panel-body",className:"bg-white/95 backdrop-blur-sm rounded-xl shadow-2xl border border-gray-200 p-3 text-xs",children:[e.jsxs("div",{className:"flex items-center justify-between gap-2 mb-2",children:[e.jsx("div",{className:"font-semibold text-gray-700",children:"白板事件槽"}),e.jsxs("div",{className:"flex gap-1",children:[e.jsx("button",{type:"button",onClick:()=>g(b=>!b),"data-testid":"whiteboard-event-panel-pause",className:`px-2 py-1 rounded ${n?"bg-amber-100 text-amber-700":"bg-gray-100 text-gray-600"}`,children:n?"继续":"暂停"}),e.jsx("button",{type:"button",onClick:()=>Pt.clear(),"data-testid":"whiteboard-event-panel-clear",className:"px-2 py-1 rounded bg-gray-100 text-gray-600",children:"清空"}),e.jsx("button",{type:"button",onClick:()=>l(!0),"data-testid":"whiteboard-event-panel-collapse",className:"px-2 py-1 rounded bg-gray-100 text-gray-600",children:"收起"})]})]}),e.jsxs("div",{className:"flex gap-1 mb-2",children:[e.jsxs("select",{value:c,onChange:b=>u(b.target.value),"data-testid":"whiteboard-event-panel-type-filter",className:"flex-1 px-2 py-1 text-xs border border-gray-200 rounded",children:[e.jsxs("option",{value:"",children:["全部类型 (",k.total,")"]}),M.map(b=>e.jsxs("option",{value:b,children:[b," (",k.byType[b]??0,")"]},b))]}),e.jsxs("select",{value:d,onChange:b=>a(b.target.value),"data-testid":"whiteboard-event-panel-source-filter",className:"px-2 py-1 text-xs border border-gray-200 rounded",children:[e.jsx("option",{value:"",children:"全部来源"}),e.jsx("option",{value:"iframe.postMessage",children:"iframe.postMessage"}),e.jsx("option",{value:"iframe.bridge",children:"iframe.bridge"}),e.jsx("option",{value:"applet.score",children:"applet.score"}),e.jsx("option",{value:"widget.quiz",children:"widget.quiz"}),e.jsx("option",{value:"widget.canvas",children:"widget.canvas"}),e.jsx("option",{value:"manual",children:"manual"})]})]}),e.jsx("div",{"data-testid":"whiteboard-event-panel-list",className:"space-y-1 max-h-80 overflow-y-auto",children:X.length===0?e.jsx("div",{className:"text-center text-gray-400 py-4",children:"暂无事件"}):X.map(b=>e.jsx(qi,{event:b},b.id))})]})})}function qi({event:t}){const[r,x]=i.useState(!1),l=new Date(t.timestamp).toLocaleTimeString(),c=t.type==="courseware.submitted",u=c&&typeof t.payload.score=="number"&&typeof t.payload.total=="number"?` · ${t.payload.score}/${t.payload.total}`:"",d=c&&t.payload.score>=60;return e.jsxs("div",{"data-testid":`whiteboard-event-row-${t.id}`,className:"border border-gray-100 rounded p-1.5 bg-white/80 hover:bg-white",children:[e.jsx("div",{className:"flex items-center justify-between",children:e.jsxs("button",{type:"button",onClick:()=>x(a=>!a),className:"flex-1 text-left",children:[e.jsx("span",{className:"font-mono text-gray-400 text-[10px]",children:l})," ",e.jsx("span",{className:`font-semibold ${d?"text-green-600":c?"text-red-500":"text-gray-700"}`,children:t.type}),e.jsx("span",{className:"text-gray-500",children:u}),t.coursewareUuid&&e.jsxs("span",{className:"text-gray-400 text-[10px]",children:[" · ",t.coursewareUuid.slice(0,8)]})]})}),r&&e.jsx("pre",{"data-testid":`whiteboard-event-row-detail-${t.id}`,className:"mt-1 text-[10px] text-gray-600 bg-gray-50 rounded p-1 overflow-x-auto whitespace-pre-wrap break-all",children:JSON.stringify(t,null,2)})]})}const ls=8,Yi=8,Ii=["page_meta","pen","highlighter","quiz"];function Ge(t){return!Ii.includes(t)}function ut(t,r=0){const x=typeof t=="number"?t:Number(t);return Number.isFinite(x)?x:r}function os(t){return{x:t.x,y:t.y,width:Math.max(0,t.width),height:Math.max(0,t.height)}}function Ji(t,r,x=0,l){if(r<=0)return[];if(r===1)return[os(t)];const c=[os(t)];for(;c.length<r;){let u=0,d=-1;for(let g=0;g<c.length;g+=1){const j=c[g];if(c.length>=2&&l&&(l==="bottom-full"&&j.y>t.y+1||l==="top-full"&&j.y<=t.y+1||l==="right-full"&&j.x>t.x+1||l==="left-full"&&j.x<=t.x+1))continue;const P=j.width*j.height,X=Math.max(j.width,j.height),k=P*1e4+X;k>=d&&(d=k,u=g)}const a=c.splice(u,1)[0];let n=a.width>=a.height;if(c.length===0&&l&&(l==="bottom-full"||l==="top-full"?n=!1:(l==="left-full"||l==="right-full")&&(n=!0)),n){const g=a.width/2,j={x:a.x,y:a.y,width:g,height:a.height},P={x:a.x+g,y:a.y,width:a.width-g,height:a.height};c.splice(u,0,j,P)}else{const g=a.height/2,j={x:a.x,y:a.y,width:a.width,height:g},P={x:a.x,y:a.y+g,width:a.width,height:a.height-g};c.splice(u,0,j,P)}}return c.sort((u,d)=>Math.abs(u.y-d.y)>1?u.y-d.y:u.x-d.x)}function Oi(t,r,x,l="fill",c=1/0){return l==="fill"||t.width<=0||t.height<=0?{id:"",x:t.x,y:t.y,width:Math.max(0,t.width),height:Math.max(0,t.height)}:Ui(t,r,x,c)}function Ui(t,r,x,l=1/0){const c=r>0?r:t.width,u=x>0?x:t.height;if(c<=0||u<=0||t.width<=0||t.height<=0)return{id:"",x:t.x,y:t.y,width:Math.max(0,t.width),height:Math.max(0,t.height)};const d=Math.min(t.width/c,t.height/u,l),a=c*d,n=u*d;return{id:"",x:t.x+(t.width-a)/2,y:t.y+(t.height-n)/2,width:a,height:n}}function Gi(t,r,x={}){const l=x.gap??ls,c=x.padding??Yi,u=x.fillMode??"fill",d=x.maxScale??1/0;if(t.length===0)return[];if(r.width<=0||r.height<=0)return[];const a=os({x:c,y:c,width:r.width-c*2,height:r.height-c*2});if(a.width<=0||a.height<=0)return[];const n=Ji(a,t.length,0,x.stackDirection),g=Math.max(0,l)/2;return t.map((j,P)=>{const X=n[P];if(!X)return{id:j.id,x:j.x,y:j.y,width:j.width,height:j.height};const k=os({x:X.x+g,y:X.y+g,width:X.width-g*2,height:X.height-g*2}),M=Oi(k,j.width,j.height,u,d);return{id:j.id,x:M.x,y:M.y,width:M.width,height:M.height}})}function As(t,r,x){if(!Ge(t.type))return null;const l=ut(r?.x),c=ut(r?.y);if(t.type==="circle"){const u=x.width>0?x.width/2:24,d=ut(r?.radius)>0?ut(r.radius):u;return{id:t.id,x:l,y:c,width:d*2,height:d*2,shape:"circle"}}return{id:t.id,x:l,y:c,width:ut(r?.width)>0?ut(r.width):x.width,height:ut(r?.height)>0?ut(r.height):x.height}}function Fs(t="rect"){return t==="circle"?["x","y","radius"]:["x","y","width","height"]}function Ue(t,r="rect"){const x={};for(const l of Fs(r)){const c=Number(t?.[l]);x[l]=Number.isFinite(c)?c:0}return x}function Ls(t,r,x,l=.5){const c=u=>Number.isFinite(Number(u))?Number(u):0;return x.every(u=>Math.abs(c(t?.[u])-c(r?.[u]))<l)}function Ki(t,r){if(t.shape==="circle"){const x=Math.max(1,Math.min(r.width,r.height)/2);return{x:r.x+r.width/2,y:r.y+r.height/2,radius:x}}return{x:r.x,y:r.y,width:r.width,height:r.height}}function Vi(t,r,x){const l=r.filter(n=>n.id!==t.id);if(l.length===0)return null;const c=t.x+t.width/2,u=t.y+t.height/2;let d=null,a=1/0;for(const n of l){const g=n.x+n.width/2,j=n.y+n.height/2,P=g-c,X=j-u;if(x==="left"&&P>=-1||x==="right"&&P<=1||x==="up"&&X>=-1||x==="down"&&X<=1)continue;const k=x==="left"||x==="right",M=Math.abs(k?P:X),b=Math.abs(k?X:P);let N=0;if(k){const _=Math.max(t.y,n.y),F=Math.min(t.y+t.height,n.y+n.height);N=Math.max(0,F-_)}else{const _=Math.max(t.x,n.x),F=Math.min(t.x+t.width,n.x+n.width);N=Math.max(0,F-_)}const y=N>0?1/(N+1):b*2.5,f=M+b*1.5+y*10;f<a&&(a=f,d=n)}return d}function Zi(t,r,x){for(const l of r)if(l.id!==x&&t.x>=l.x&&t.x<=l.x+l.width&&t.y>=l.y&&t.y<=l.y+l.height)return l;return null}function Qi(t,r){return[...t].sort((x,l)=>{const c=r?.get(x.id),u=r?.get(l.id);return typeof c=="number"&&typeof u=="number"?c-u:typeof c=="number"?-1:typeof u=="number"?1:Math.abs(x.y-l.y)>10?x.y-l.y:x.x-l.x})}function ea(t,r=ls,x=100){const l=[],c=t.length;if(c<2)return l;for(let u=0;u<c;u+=1){const d=t[u];for(let a=0;a<c;a+=1){if(u===a)continue;const n=t[a],g=d.y+d.height+r;if(Math.abs(n.y-g)<=3){const j=Math.max(d.x,n.x),X=Math.min(d.x+d.width,n.x+n.width)-j;if(X>20){const k=d.y+d.height;l.push({id:`h-split-${d.id}-${n.id}`,orientation:"horizontal",x:j,y:k,length:X,thickness:Math.max(r,8),firstIds:[d.id],secondIds:[n.id],minPos:d.y+x,maxPos:n.y+n.height-x-r,currentPos:k})}}}}for(let u=0;u<c;u+=1){const d=t[u];for(let a=0;a<c;a+=1){if(u===a)continue;const n=t[a],g=d.x+d.width+r;if(Math.abs(n.x-g)<=3){const j=Math.max(d.y,n.y),X=Math.min(d.y+d.height,n.y+n.height)-j;if(X>20){const k=d.x+d.width;l.push({id:`v-split-${d.id}-${n.id}`,orientation:"vertical",x:k,y:j,length:X,thickness:Math.max(r,8),firstIds:[d.id],secondIds:[n.id],minPos:d.x+x,maxPos:n.x+n.width-x-r,currentPos:k})}}}}return l}function ta(t,r,x){const c=Math.max(t.minPos,Math.min(t.maxPos,t.currentPos+r))-t.currentPos;if(Math.abs(c)<.5)return{};const u={},d=t.orientation==="horizontal";for(const a of t.firstIds){const n=x.find(g=>g.id===a);n&&(d?u[a]={height:Math.max(20,n.height+c)}:u[a]={width:Math.max(20,n.width+c)})}for(const a of t.secondIds){const n=x.find(g=>g.id===a);n&&(d?u[a]={y:n.y+c,height:Math.max(20,n.height-c)}:u[a]={x:n.x+c,width:Math.max(20,n.width-c)})}return u}function sa(t,r,x,l=2,c=ls){const u=(r.x-t.x)/t.width,d=(r.y-t.y)/t.height,n=l<=2&&x!==void 0?{x:x.x??0,y:x.y??0,width:x.width,height:x.height}:t,g=Math.max(40,(n.height-c)/2),j=Math.max(40,(n.width-c)/2);return d<.25?{type:"split-top",targetId:t.id,label:"↑ 上方分割插入",previewRect:{x:n.x,y:n.y,width:n.width,height:g}}:d>.75?{type:"split-bottom",targetId:t.id,label:"↓ 下方分割插入",previewRect:{x:n.x,y:n.y+g+c,width:n.width,height:g}}:u<.25?{type:"split-left",targetId:t.id,label:"← 左侧分割插入",previewRect:{x:n.x,y:n.y,width:j,height:n.height}}:u>.75?{type:"split-right",targetId:t.id,label:"→ 右侧分割插入",previewRect:{x:n.x+j+c,y:n.y,width:j,height:n.height}}:{type:"swap",targetId:t.id,label:"⇄ 松开对调位置",previewRect:{x:t.x,y:t.y,width:t.width,height:t.height}}}function ra(t,r,x,l,c,u=ls){if(t===r)return{};const d=l.find(N=>N.id===t),a=l.find(N=>N.id===r);if(!d||!a)return{};const n={};if(l.length<=2&&c){const N=c.x??0,y=c.y??0,f=c.width,_=c.height,F=Math.max(40,(_-u)/2),L=Math.max(40,(f-u)/2);return x==="split-bottom"?(n[r]={x:N,y,width:f,height:F},n[t]={x:N,y:y+F+u,width:f,height:F}):x==="split-top"?(n[t]={x:N,y,width:f,height:F},n[r]={x:N,y:y+F+u,width:f,height:F}):x==="split-right"?(n[r]={x:N,y,width:L,height:_},n[t]={x:N+L+u,y,width:L,height:_}):x==="split-left"&&(n[t]={x:N,y,width:L,height:_},n[r]={x:N+L+u,y,width:L,height:_}),n}const g=Math.abs(a.x-d.x)<=4&&Math.abs(a.width-d.width)<=4&&(Math.abs(a.y+a.height+u-d.y)<=4||Math.abs(d.y+d.height+u-a.y)<=4),j=Math.abs(a.y-d.y)<=4&&Math.abs(a.height-d.height)<=4&&(Math.abs(a.x+a.width+u-d.x)<=4||Math.abs(d.x+d.width+u-a.x)<=4);if(g){const N=Math.min(d.y,a.y),y=d.height+a.height+u;if(x==="split-top"){const f=Math.max(40,(y-u)/2);return n[t]={x:a.x,y:N,width:a.width,height:f},n[r]={x:a.x,y:N+f+u,width:a.width,height:f},n}if(x==="split-bottom"){const f=Math.max(40,(y-u)/2);return n[r]={x:a.x,y:N,width:a.width,height:f},n[t]={x:a.x,y:N+f+u,width:a.width,height:f},n}if(x==="split-left"){const f=Math.max(40,(a.width-u)/2);return n[t]={x:a.x,y:N,width:f,height:y},n[r]={x:a.x+f+u,y:N,width:f,height:y},n}if(x==="split-right"){const f=Math.max(40,(a.width-u)/2);return n[r]={x:a.x,y:N,width:f,height:y},n[t]={x:a.x+f+u,y:N,width:f,height:y},n}}if(j){const N=Math.min(d.x,a.x),y=d.width+a.width+u;if(x==="split-left"){const f=Math.max(40,(y-u)/2);return n[t]={x:N,y:a.y,width:f,height:a.height},n[r]={x:N+f+u,y:a.y,width:f,height:a.height},n}if(x==="split-right"){const f=Math.max(40,(y-u)/2);return n[r]={x:N,y:a.y,width:f,height:a.height},n[t]={x:N+f+u,y:a.y,width:f,height:a.height},n}if(x==="split-top"){const f=Math.max(40,(a.height-u)/2);return n[t]={x:N,y:a.y,width:y,height:f},n[r]={x:N,y:a.y+f+u,width:y,height:f},n}if(x==="split-bottom"){const f=Math.max(40,(a.height-u)/2);return n[r]={x:N,y:a.y,width:y,height:f},n[t]={x:N,y:a.y+f+u,width:y,height:f},n}}const P=l.filter(N=>N.id!==t&&N.id!==r),X=P.find(N=>Math.abs(N.x-d.x)<=4&&Math.abs(N.width-d.width)<=4&&(Math.abs(N.y+N.height+u-d.y)<=4||Math.abs(d.y+d.height+u-N.y)<=4)),k=P.find(N=>Math.abs(N.y-d.y)<=4&&Math.abs(N.height-d.height)<=4&&(Math.abs(N.x+N.width+u-d.x)<=4||Math.abs(d.x+d.width+u-N.x)<=4));if(X){const N=Math.min(X.y,d.y),y=X.height+d.height+u;n[X.id]={x:X.x,y:N,width:X.width,height:y}}else if(k){const N=Math.min(k.x,d.x),y=k.width+d.width+u;n[k.id]={x:N,y:k.y,width:y,height:k.height}}const M=Math.max(40,(a.height-u)/2),b=Math.max(40,(a.width-u)/2);return x==="split-top"?(n[t]={x:a.x,y:a.y,width:a.width,height:M},n[r]={x:a.x,y:a.y+M+u,width:a.width,height:M}):x==="split-bottom"?(n[r]={x:a.x,y:a.y,width:a.width,height:M},n[t]={x:a.x,y:a.y+M+u,width:a.width,height:M}):x==="split-left"?(n[t]={x:a.x,y:a.y,width:b,height:a.height},n[r]={x:a.x+b+u,y:a.y,width:b,height:a.height}):x==="split-right"&&(n[r]={x:a.x,y:a.y,width:b,height:a.height},n[t]={x:a.x+b+u,y:a.y,width:b,height:a.height}),n}const na=1e3,xt=new Map;function Je(t,r){const x=r!==void 0?r:{};if(!t)return x;const l=typeof t=="string"?t:t.data;if(!l||typeof l!="string")return l||x;if(xt.has(l)){const c=xt.get(l);return xt.delete(l),xt.set(l,c),c}try{const c=JSON.parse(l);if(xt.size>=na){const u=xt.keys().next().value;u!==void 0&&xt.delete(u)}return xt.set(l,c),c}catch(c){return console.warn("[parseElementData] Failed to parse element data:",c,l),x}}function xn(t,r,x){if(t.type==="page_meta")return!1;try{const l=JSON.parse(t.data),c=l.page??0,u=x[r];return l.pageId&&u?.id?l.pageId===u.id:c===r}catch{return r===0}}function ia(t,r,x,l){return t.filter(c=>{if(!xn(c,r,x))return!1;try{const u=JSON.parse(c.data);return!(l&&u.segmentId&&u.segmentId!==l)}catch{return r===0}})}function aa(t,r,x=Date.now()){const l=t.length,c={id:`page-${x}-${l}`,title:r||`P${l+1} · 备课页面`,order:l};return{newPages:[...t,c],newIndex:l,newPage:c}}function oa(t,r,x){const l=x.trim();return l?t.map((c,u)=>u===r?{...c,title:l}:c):t}function la(t,r,x=Date.now()){const l=t[r];if(!l)return null;const c=r+1,u={id:`page-${x}-${c}`,title:`${l.title} (副本)`,order:c};return{newPages:[...t.slice(0,c),u,...t.slice(c).map(a=>({...a,order:a.order+1}))],newIndex:c,newPage:u}}function ca(t,r,x){const l=x==="left"?r-1:r+1;if(l<0||l>=t.length)return null;const c=[...t],u=c[r];return c[r]=c[l],c[l]=u,c.forEach((d,a)=>{d.order=a}),{newPages:c,targetIndex:l}}class da{constructor(){this.frameTimes=[],this.lastTime=performance.now(),this.stats={fps:60,renderTimeMs:0,drawCount:0,visibleCount:0,totalCount:0,memoryUsageMb:0}}recordFrame(r,x,l,c){const u=performance.now(),d=u-this.lastTime;this.lastTime=u,d>0&&(this.frameTimes.push(1e3/d),this.frameTimes.length>30&&this.frameTimes.shift());const a=Math.round(this.frameTimes.reduce((g,j)=>g+j,0)/(this.frameTimes.length||1));let n=0;performance.memory&&(n=Math.round(performance.memory.usedJSHeapSize/(1024*1024)*10)/10),this.stats={fps:a,renderTimeMs:Math.round(r*100)/100,drawCount:x,visibleCount:l,totalCount:c,memoryUsageMb:n}}getStats(){return{...this.stats}}}new da;class ua{constructor(){this.currentTheme="light",this.lightTokens={primary:"#4f46e5",background:"#f8fafc",gridDot:"#cbd5e1",selectionBorder:"#6366f1",selectionHandle:"#4f46e5",textPrimary:"#1e293b",borderDefault:"#e2e8f0",guideLine:"#ec4899"},this.darkTokens={primary:"#6366f1",background:"#0b0f19",gridDot:"#334155",selectionBorder:"#818cf8",selectionHandle:"#6366f1",textPrimary:"#f8fafc",borderDefault:"#1e293b",guideLine:"#f472b6"},this.eyecareTokens={primary:"#2d6a4f",background:"#f2f7f4",gridDot:"#b7d5c5",selectionBorder:"#40916c",selectionHandle:"#2d6a4f",textPrimary:"#143526",borderDefault:"#cce0d6",guideLine:"#10b981"},this.chalkboardTokens={primary:"#4caf50",background:"#0e1713",gridDot:"#2d5242",selectionBorder:"#81c784",selectionHandle:"#4caf50",textPrimary:"#e8f5e9",borderDefault:"#1f382d",guideLine:"#66bb6a"},this.teachingTokens={primary:"#d97706",background:"#fffbeb",gridDot:"#fde68a",selectionBorder:"#f59e0b",selectionHandle:"#d97706",textPrimary:"#78350f",borderDefault:"#fef3c7",guideLine:"#ef4444"},this.customTokens=new Map,this.listeners=new Set}getTokens(){if(this.customTokens.has(this.currentTheme))return this.customTokens.get(this.currentTheme);switch(this.currentTheme){case"dark":return this.darkTokens;case"eyecare":return this.eyecareTokens;case"chalkboard":return this.chalkboardTokens;case"teaching":return this.teachingTokens;default:return this.lightTokens}}setTheme(r){this.currentTheme=r;const x=this.getTokens();this.listeners.forEach(l=>{try{l(x,r)}catch(c){console.error("[ThemeManager] Error in theme change listener:",c)}})}getTheme(){return this.currentTheme}registerCustomTokens(r,x){this.customTokens.set(r,x),this.currentTheme===r&&this.setTheme(r)}unregisterCustomTokens(r){this.customTokens.delete(r),this.currentTheme===r&&this.setTheme("light")}subscribe(r){return this.listeners.add(r),()=>{this.listeners.delete(r)}}}const Hr=new ua;function it({title:t,icon:r,hidden:x=!1,readOnly:l=!1,isMinimized:c=!1,isMaximized:u=!1,isPropertiesOpen:d=!1,themeColor:a="default",onPointerDown:n,onPointerMove:g,onPointerUp:j,onOpenProperties:P,onMinimize:X,onRestore:k,onMaximize:M,onBrowserFullscreen:b,onDelete:N,extraActions:y}){const f=()=>{switch(a){case"indigo":return"bg-indigo-50/90 dark:bg-indigo-950/60 text-indigo-900 dark:text-indigo-200 border-indigo-200/80 dark:border-indigo-800/60";case"orange":return"bg-orange-50/90 dark:bg-orange-950/60 text-orange-900 dark:text-orange-200 border-orange-200/80 dark:border-orange-800/60";case"purple":return"bg-purple-50/90 dark:bg-purple-950/60 text-purple-900 dark:text-purple-200 border-purple-200/80 dark:border-purple-800/60";case"gray":case"slate":case"default":default:return"bg-surface-secondary/90 text-main border-theme"}};return x?null:e.jsxs("div",{"data-widget-titlebar":"true",className:`px-3 py-1.5 flex justify-between items-center text-xs font-semibold border-b select-none shrink-0 transition-colors ${f()} ${l?"cursor-default":"cursor-move"}`,onPointerDown:n,onPointerMove:g,onPointerUp:j,children:[e.jsxs("div",{className:"flex items-center gap-1.5 min-w-0 mr-2 truncate",children:[r&&e.jsx("span",{className:"shrink-0 opacity-80",children:r}),e.jsx("span",{className:"truncate tracking-tight",children:t}),l&&e.jsx("span",{className:"px-1.5 py-0.5 rounded text-xs bg-amber-100 text-amber-800 dark:bg-amber-950/60 dark:text-amber-300 border border-amber-300 dark:border-amber-700 font-semibold select-none flex items-center gap-0.5 shrink-0",children:"🔒 只读锁定"})]}),!l&&e.jsxs("div",{className:"flex items-center gap-0.5 shrink-0",onPointerDown:_=>_.stopPropagation(),children:[y,P&&e.jsx("button",{type:"button",onClick:P,className:`p-1 rounded-lg transition-all cursor-pointer flex items-center justify-center ${d?"bg-primary-theme text-white shadow-2xs":"text-muted hover:text-main hover:bg-black/5 dark:hover:bg-white/10"}`,title:"属性配置",children:e.jsx(Zr,{size:12})}),X&&e.jsx("button",{type:"button",onClick:X,disabled:c,className:`p-1 rounded-lg transition-all flex items-center justify-center ${c?"opacity-30 cursor-not-allowed text-muted":"text-muted hover:text-main hover:bg-black/5 dark:hover:bg-white/10 cursor-pointer"}`,title:"最小化组件",children:e.jsx(bi,{size:12})}),k&&e.jsx("button",{type:"button",onClick:k,className:`p-1 rounded-lg transition-all flex items-center justify-center ${c||u?"text-primary-theme font-bold bg-primary-theme/15 hover:bg-primary-theme/25 cursor-pointer shadow-2xs ring-1 ring-primary-theme/30":"text-muted hover:text-main hover:bg-black/5 dark:hover:bg-white/10 cursor-pointer"}`,title:"还原组件",children:e.jsx(Hs,{size:11,className:c||u?"stroke-[2.5]":""})}),M&&e.jsx("button",{type:"button","data-testid":"widget-titlebar-board-fullscreen",onClick:M,disabled:u,className:`p-1 rounded-lg transition-all flex items-center justify-center ${u?"opacity-30 cursor-not-allowed text-muted":"text-muted hover:text-main hover:bg-black/5 dark:hover:bg-white/10 cursor-pointer"}`,title:"白板全屏(组件在画布内最大化)",children:e.jsx(Ws,{size:11})}),b&&e.jsx("button",{type:"button","data-testid":"widget-titlebar-browser-fullscreen",onClick:b,className:"p-1 rounded-lg text-muted hover:text-main hover:bg-black/5 dark:hover:bg-white/10 transition-all cursor-pointer flex items-center justify-center",title:"整个浏览器全屏(脱离白板并铺满屏幕,适合投屏)",children:e.jsx(gi,{size:11})}),N&&e.jsx("button",{type:"button",onClick:N,className:"p-1 rounded-lg text-muted hover:text-rose-600 hover:bg-rose-500/10 transition-all cursor-pointer flex items-center justify-center",title:"删除组件",children:e.jsx(ct,{size:12})})]})]})}const xa=1e5;function Wr({children:t,onMaximize:r,onBrowserFullscreen:x,isBrowserFullscreen:l=!1,browserFullscreenDismissible:c=!0,contentClassName:u="flex-1 min-h-0 overflow-auto",...d}){if(l)return e.jsxs("div",{"data-widget-frame":"browser-fullscreen",style:{pointerEvents:"auto"},className:"fixed inset-0 bg-white dark:bg-slate-950 flex flex-col",children:[c&&x&&e.jsxs("button",{type:"button","data-testid":"widget-frame-exit-browser-fullscreen",onClick:x,className:"fixed top-4 right-4 z-[100001] px-3 py-2 rounded-xl bg-slate-900/85 hover:bg-slate-900 text-slate-100 text-xs font-bold flex items-center gap-1.5 shadow-2xl backdrop-blur-md border border-white/15 transition-colors cursor-pointer",title:"退出全屏(Esc)",children:[e.jsx(Qr,{size:14}),"退出全屏"]}),e.jsx("div",{className:"flex-1 min-h-0 overflow-auto",children:t})]});const{title:a,icon:n,readOnly:g,isMinimized:j,isMaximized:P,isPropertiesOpen:X,themeColor:k,extraActions:M,...b}=d;return e.jsxs("div",{"data-widget-frame":"true",className:"w-full h-full flex flex-col min-h-0",children:[e.jsx(it,{title:a,icon:n,readOnly:g,isMinimized:j,isMaximized:P,isPropertiesOpen:X,themeColor:k,extraActions:M,...b,onMaximize:r,onBrowserFullscreen:x}),!j&&e.jsx("div",{className:u,children:t})]})}function Xr(){if(typeof document>"u")return!1;const t=document.documentElement;return!!(t.requestFullscreen||t.webkitRequestFullscreen)}function zs(){return typeof document>"u"?!1:!!(document.fullscreenElement||document.webkitFullscreenElement)}function ha({elementId:t,enableNativeFullscreen:r=!0,onChange:x}){const l=Xr(),[c,u]=i.useState(!1),d=i.useRef(t);d.current=t;const a=i.useRef(x);a.current=x,i.useEffect(()=>()=>{zs()&&document.exitFullscreen?.()?.catch?.(()=>{})},[]),i.useEffect(()=>{if(typeof document>"u")return;const j=()=>{const P=zs();u(P),!P&&d.current&&a.current&&a.current(null)};return document.addEventListener("fullscreenchange",j),document.addEventListener("webkitfullscreenchange",j),()=>{document.removeEventListener("fullscreenchange",j),document.removeEventListener("webkitfullscreenchange",j)}},[]);const n=i.useCallback(async j=>{if(a.current?.(j),!!r&&Xr())try{const P=document.documentElement;await(P.requestFullscreen?.()??P.webkitRequestFullscreen?.()),u(!0)}catch(P){console.warn("[BrowserFullscreen] native fullscreen rejected:",P)}},[r]),g=i.useCallback(async()=>{if(a.current?.(null),zs())try{await document.exitFullscreen?.()}catch(j){console.warn("[BrowserFullscreen] exit failed:",j)}u(!1)},[]);return{nativeSupported:l,nativeActive:c,enter:n,exit:g}}function ma({pluginId:t,slot:r,widgetId:x,elementId:l,lessonId:c}){const d=Vr(g=>g.extensionPoints).get(r)||[],a=d.find(g=>g.id===x)??d.find(g=>g.pluginId===t&&g.id===x),n=i.useRef(null);return i.useEffect(()=>{a&&n.current&&(n.current.innerHTML="",!a.component&&a.render&&Promise.resolve(a.render(n.current,{elementId:l,lessonId:c})).catch(console.error))},[a,t,x,l,c]),a?a.component?Bs.createElement(a.component,{elementId:l,lessonId:c}):e.jsx("div",{ref:n,className:"w-full h-full min-h-0"}):e.jsxs("div",{className:"text-center py-6 text-xs text-gray-400 italic flex flex-col justify-center items-center h-full",children:[e.jsx(Ke,{size:16,className:"animate-spin mb-1"}),e.jsxs("span",{children:["组件 [",x,"] 正在加载或未启用..."]})]})}function pa({elementId:t,data:r,lessonId:x,classId:l,onElementUpdate:c,onPointerDown:u,onPointerMove:d,onPointerUp:a,onDelete:n,readOnly:g=!1,userRole:j="teacher",isMinimized:P=!1,isMaximized:X=!1,hidden:k=!1,onBrowserFullscreen:M,isPropertiesOpen:b=!1,onOpenProperties:N,onMinimize:y,onRestore:f,onMaximize:_}){const F=ai(Y=>Y.classes)||[],[L,ie]=i.useState(l||r.classId||(F[0]?.id??"")),[U,xe]=i.useState(()=>r.candidates||r.allStudents||[{id:"mock-s-1",name:"张明",student_number:"101",tier:"basic",term_picked_count:0,lesson_picked_count:0},{id:"mock-s-2",name:"李华",student_number:"102",tier:"intermediate",term_picked_count:1,lesson_picked_count:0},{id:"mock-s-3",name:"王超",student_number:"103",tier:"advanced",term_picked_count:2,lesson_picked_count:0},{id:"mock-s-4",name:"赵丽",student_number:"104",tier:"basic",term_picked_count:0,lesson_picked_count:0},{id:"mock-s-5",name:"钱科",student_number:"105",tier:"intermediate",term_picked_count:1,lesson_picked_count:0},{id:"mock-s-6",name:"孙雪",student_number:"106",tier:"advanced",term_picked_count:3,lesson_picked_count:0}]),[ee,J]=i.useState(!1),[z,T]=i.useState(r.pickerMode||"fair_all"),[R,p]=i.useState(r.difficulty||"intermediate"),[C,m]=i.useState(r.selectedStudent||null),[O,v]=i.useState(!1),[w,q]=i.useState(null),[I,D]=i.useState(r.evaluation||null),ne=i.useMemo(()=>JSON.stringify([r.pickedTime??null,r.selectedStudent?.id??null,r.evaluation?.rating??null,r.evaluation?.submitted??null]),[r.pickedTime,r.selectedStudent,r.evaluation]),ce=i.useRef(null),re=i.useRef(r);re.current=r,i.useEffect(()=>{r.pickedTime!=null&&ce.current!==ne&&(ce.current=ne,m(r.selectedStudent??null),D(r.evaluation??null),v(!1),q(null))},[ne,r.pickedTime,r.selectedStudent,r.evaluation]),i.useEffect(()=>{if(!L)return;let Y=!0;J(!0);const le=`/api/classes/${L}/picker-candidates${x?`?lessonId=${encodeURIComponent(x)}`:""}`;return fetch(le).then(be=>{if(!be.ok)throw new Error("Failed to load class picker candidates");return be.json()}).then(be=>{Y&&Array.isArray(be)&&be.length>0&&xe(be)}).catch(be=>{console.warn("[RollCallWrapper] candidates fallback:",be)}).finally(()=>{Y&&J(!1)}),()=>{Y=!1}},[L,x]);const te=i.useMemo(()=>{if(z==="fair_all")return U;const{filtered:Y}=oi(U,R);return Y},[U,z,R]),B=()=>{if(te.length===0||O)return;v(!0),D(null);let Y=0;const le=16,je=setInterval(()=>{const Me=Math.floor(Math.random()*te.length);if(q(te[Me]),Y++,Y>=le){clearInterval(je);const Ie=li(te),E=Ie?Ie.student:te[0];m(E),v(!1),q(null),xe(se=>se.map(pe=>pe.id===E.id?{...pe,lesson_picked_count:(pe.lesson_picked_count||0)+1}:pe)),c&&c(t,{...re.current,classId:L,pickerMode:z,difficulty:R,selectedStudent:E,pickedTime:new Date().toISOString(),status:"picked",evaluation:null}),ae.publish({id:oe(),type:"rollcall.picked",source:"rollcall.picker",payload:{elementId:t,studentId:E.id,studentName:E.name,classId:L,lessonId:x},timestamp:Date.now()})}},70)},K=j==="teacher"||j==="administrator",ye=async Y=>{if(!C||I?.submitted)return;const le=ss[Y],be={rating:Y,score:le.score,rewardCoins:le.rewardCoins,submitted:!0};D(be),xe(je=>je.map(Me=>Me.id===C.id?{...Me,total_reward_coins:(Me.total_reward_coins||0)+le.rewardCoins}:Me));try{await fetch("/api/rollcalls/evaluate",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({id:`rollcall-${t}-${C.id}-${Date.now()}`,studentId:C.id,studentName:C.name,classId:L,lessonId:x,rating:Y,score:le.score,rewardCoins:le.rewardCoins,difficulty:z==="tiered"?R:"intermediate"})})}catch(je){console.error("[RollCallWrapper] evaluate rollcall failed:",je)}c&&c(t,{...re.current,evaluation:be}),ae.publish({id:oe(),type:"rollcall.evaluated",source:"rollcall.picker",payload:{elementId:t,studentId:C.id,rating:Y,rewardCoins:le.rewardCoins,score:le.score},timestamp:Date.now()})};return e.jsxs("div",{className:"w-full h-full bg-gradient-to-br from-indigo-950 via-slate-900 to-indigo-900 border border-indigo-500/50 rounded-xl shadow-2xl overflow-hidden flex flex-col font-sans select-none",style:{pointerEvents:g?"none":"auto"},children:[e.jsx(it,{title:"随机点名助手 (分层抽问 Fair Picker)",icon:e.jsx(Yt,{size:13,className:"animate-pulse text-amber-400"}),readOnly:g,isMinimized:P,isMaximized:X,hidden:k,onBrowserFullscreen:M,isPropertiesOpen:b,themeColor:"indigo",onPointerDown:u,onPointerMove:d,onPointerUp:a,onOpenProperties:N,onMinimize:y,onRestore:f,onMaximize:_,onDelete:n,extraActions:F.length>1&&K?e.jsx("div",{className:"relative mr-1",onPointerDown:Y=>Y.stopPropagation(),children:e.jsx("select",{value:L,onChange:Y=>ie(Y.target.value),className:"bg-indigo-900/80 text-indigo-100 text-[11px] rounded px-1.5 py-0.5 border border-indigo-700/60 outline-hidden cursor-pointer",children:F.map(Y=>e.jsx("option",{value:Y.id,className:"bg-slate-900 text-white",children:Y.name},Y.id))})}):null}),!P&&e.jsxs(e.Fragment,{children:[K&&e.jsxs("div",{className:"px-3 py-1.5 bg-indigo-950/40 border-b border-indigo-900/40 flex items-center justify-between gap-2 shrink-0 text-xs",onPointerDown:Y=>Y.stopPropagation(),children:[e.jsxs("div",{className:"flex items-center gap-1 bg-indigo-900/40 p-0.5 rounded-lg border border-indigo-800/40",children:[e.jsx("button",{onClick:()=>T("fair_all"),className:`px-2 py-0.5 rounded text-xs font-medium transition-all ${z==="fair_all"?"bg-indigo-600 text-white shadow-2xs font-bold":"text-indigo-300 hover:text-white"}`,children:"全员公平"}),e.jsx("button",{onClick:()=>T("tiered"),className:`px-2 py-0.5 rounded text-xs font-medium transition-all ${z==="tiered"?"bg-purple-600 text-white shadow-2xs font-bold":"text-indigo-300 hover:text-white"}`,children:"分层抽问"})]}),z==="tiered"&&e.jsx("div",{className:"flex items-center gap-1",children:["basic","intermediate","advanced"].map(Y=>{const le=Y==="basic"?"基础":Y==="intermediate"?"进阶":"拔高",be=Y==="basic"?"bg-emerald-600 text-white":Y==="intermediate"?"bg-blue-600 text-white":"bg-amber-600 text-white";return e.jsx("button",{onClick:()=>p(Y),className:`px-1.5 py-0.5 rounded text-xs font-medium transition-all ${R===Y?`${be} font-bold shadow-2xs`:"text-indigo-400 hover:text-white"}`,children:le},Y)})})]}),e.jsxs("div",{className:"flex-1 p-3 flex flex-col justify-between min-h-0 text-white gap-2",children:[e.jsx("div",{className:"w-full flex-1 flex flex-col items-center justify-center p-2 rounded-lg bg-indigo-950/50 border border-indigo-900/30 relative overflow-hidden",children:O?e.jsxs("div",{className:"text-center space-y-1.5 animate-pulse",children:[e.jsxs("div",{className:"text-xs text-indigo-300 uppercase tracking-widest font-semibold flex items-center justify-center gap-1.5",children:[e.jsx(Ps,{size:12,className:"animate-spin text-amber-400"}),e.jsx("span",{children:"检索加权公平候选池中..."})]}),e.jsx("div",{className:"text-2xl font-extrabold text-amber-300 scale-105 tracking-wider font-sans",children:w?.name||"..."}),e.jsxs("div",{className:"text-xs text-indigo-400/80 font-mono",children:["学号: ",w?.student_number||"---"]})]}):C?e.jsxs("div",{className:"text-center space-y-1 w-full max-w-[260px]",children:[e.jsxs("div",{className:"text-xs text-indigo-400 uppercase tracking-widest font-semibold flex items-center justify-center gap-1",children:[e.jsx(en,{size:12,className:"text-emerald-400"}),e.jsx("span",{children:"抽中的幸运答题者"})]}),e.jsx("div",{className:"text-2xl font-black text-transparent bg-clip-text bg-gradient-to-r from-amber-200 via-yellow-400 to-amber-300 tracking-wider",children:C.name}),e.jsxs("div",{className:"flex items-center justify-center gap-2 text-xs text-indigo-300/80 font-mono",children:[e.jsxs("span",{children:["学号 ",C.student_number||C.id]}),e.jsx("span",{children:"•"}),e.jsxs("span",{children:["已回答 ",C.lesson_picked_count||0," 次"]}),C.total_reward_coins!==void 0&&e.jsxs(e.Fragment,{children:[e.jsx("span",{children:"•"}),e.jsxs("span",{className:"text-amber-400 flex items-center gap-0.5 font-bold",children:[e.jsx(yi,{size:10}),C.total_reward_coins]})]})]}),e.jsx("div",{className:"mt-2 pt-2 border-t border-indigo-900/50 w-full",onPointerDown:Y=>Y.stopPropagation(),children:I?.submitted?e.jsxs("div",{className:"bg-indigo-900/60 border border-emerald-500/40 rounded-lg p-1.5 flex items-center justify-center gap-2 text-xs",children:[e.jsx(wi,{size:14,className:"text-emerald-400"}),e.jsxs("span",{className:"font-bold text-emerald-300",children:["已评定: ",ss[I.rating].badge," ",ss[I.rating].label]}),e.jsxs("span",{className:"text-amber-300 font-bold flex items-center gap-0.5",children:["+",I.rewardCoins," 金币"]})]}):K?e.jsxs("div",{className:"space-y-1",children:[e.jsx("div",{className:"text-2xs text-indigo-300/70 text-center font-medium",children:"作答表现评定与激励下发:"}),e.jsx("div",{className:"grid grid-cols-3 gap-1",children:["excellent","good","encourage"].map(Y=>{const le=ss[Y];return e.jsxs("button",{onClick:()=>void ye(Y),className:"bg-indigo-900/80 hover:bg-indigo-800 border border-indigo-700/60 hover:border-amber-400/80 text-white rounded py-1 px-1 flex flex-col items-center gap-0.5 transition-all active:scale-95 cursor-pointer shadow-3xs group",children:[e.jsx("span",{className:"text-sm group-hover:scale-110 transition-transform",children:le.badge}),e.jsx("span",{className:"text-2xs font-semibold",children:le.label}),e.jsxs("span",{className:"text-3xs text-amber-300 font-mono",children:["+",le.rewardCoins,"币"]})]},Y)})})]}):null})]}):e.jsxs("div",{className:"text-center space-y-1",children:[e.jsx(tn,{size:26,className:"text-indigo-400/80 mx-auto animate-pulse"}),e.jsx("div",{className:"text-xs text-indigo-300 font-semibold",children:"随机抽取与分层轮盘"}),e.jsx("p",{className:"text-2xs text-indigo-400/60 leading-tight",children:"频次反比加权算法 • 支持基础/进阶/拔高分层抽问"})]})}),e.jsxs("div",{className:"w-full shrink-0 flex flex-col items-center gap-1",onPointerDown:Y=>Y.stopPropagation(),children:[e.jsxs("button",{onClick:B,disabled:O||te.length===0,className:"w-full py-1.5 bg-gradient-to-r from-indigo-500 via-purple-600 to-indigo-600 hover:from-indigo-600 hover:to-purple-700 text-white font-bold text-xs uppercase tracking-wider rounded-lg shadow-md active:scale-98 disabled:opacity-50 transition-all flex items-center justify-center gap-1.5 cursor-pointer",children:[e.jsx(Ps,{size:12,className:O?"animate-spin":""}),e.jsx("span",{children:O?"加权滚轮运转中...":C?"抽取下一位学生":"开始随机点名"})]}),e.jsxs("div",{className:"text-2xs text-indigo-400/60 text-center font-mono flex items-center justify-center gap-1.5",children:[e.jsxs("span",{children:["候选池:",te.length," 人"]}),e.jsx("span",{children:"•"}),e.jsx("span",{children:z==="fair_all"?"全员公平":`分层: ${R}`}),ee&&e.jsx(Ct,{size:9,className:"animate-spin text-indigo-400"})]})]})]})]})]})}function fa({elementId:t,data:r,onElementUpdate:x,onPointerDown:l,onPointerMove:c,onPointerUp:u,onDelete:d,readOnly:a=!1,isMinimized:n=!1,isMaximized:g=!1,hidden:j=!1,isPropertiesOpen:P=!1,onOpenProperties:X,onMinimize:k,onRestore:M,onMaximize:b,onBrowserFullscreen:N}){const[y,f]=i.useState(r.code||"console.log('Hello from sandbox!');"),[_,F]=i.useState("");i.useEffect(()=>{r.code!==void 0&&r.code!==y&&f(r.code)},[r.code]);const L=()=>{F("Running in isolated Web Worker...");try{const U=`
3
+ const logs = [];
4
+ const originalLog = console.log;
5
+ console.log = (...args) => {
6
+ logs.push(args.map(a => typeof a === 'object' ? JSON.stringify(a) : String(a)).join(' '));
7
+ };
8
+ self.onmessage = function(e) {
9
+ try {
10
+ const fn = new Function(e.data);
11
+ const res = fn();
12
+ if (res !== undefined) logs.push('Return: ' + String(res));
13
+ self.postMessage({ success: true, logs: logs.join('\\n') });
14
+ } catch (err) {
15
+ self.postMessage({ success: false, error: err.message, logs: logs.join('\\n') });
16
+ }
17
+ };
18
+ `,xe=new Blob([U],{type:"application/javascript"}),ee=URL.createObjectURL(xe),J=new Worker(ee),z=setTimeout(()=>{J.terminate(),URL.revokeObjectURL(ee),F("Execution timed out (3000ms limit). Worker terminated.")},3e3);J.onmessage=T=>{clearTimeout(z),J.terminate(),URL.revokeObjectURL(ee),T.data.success?F(T.data.logs||"Code executed successfully (no output)"):F((T.data.logs?T.data.logs+`
19
+ `:"")+"Error: "+T.data.error)},J.onerror=T=>{clearTimeout(z),J.terminate(),URL.revokeObjectURL(ee),F(`Worker Error: ${T.message}`)},J.postMessage(y)}catch(U){F(`Failed to spawn isolated worker: ${U.message}`)}},ie=()=>{x&&y!==r.code&&x(t,{...r,code:y})};return e.jsxs("div",{className:"w-full h-full bg-gray-900 border border-gray-700 rounded-lg shadow-xl overflow-hidden flex flex-col font-mono text-sm",style:{pointerEvents:a?"none":"auto"},children:[e.jsx(it,{title:r.title||"JS Sandbox",icon:e.jsx(sn,{size:13,className:"text-emerald-500"}),readOnly:a,isMinimized:n,isMaximized:g,hidden:j,isPropertiesOpen:P,themeColor:"default",onPointerDown:l,onPointerMove:c,onPointerUp:u,onOpenProperties:X,onMinimize:k,onRestore:M,onMaximize:b,onBrowserFullscreen:N,onDelete:d,extraActions:a?null:e.jsx("button",{onClick:L,onPointerDown:U=>U.stopPropagation(),className:"bg-emerald-600 hover:bg-emerald-500 text-white px-2 py-0.5 rounded shadow text-xs cursor-pointer font-sans mr-1",children:"Run"})}),!n&&e.jsxs(e.Fragment,{children:[e.jsx("textarea",{value:y,onChange:U=>f(U.target.value),onBlur:ie,className:"w-full flex-1 min-h-0 bg-gray-900 text-green-400 p-3 focus:outline-none resize-none font-mono text-xs",placeholder:"// Write JS here",onPointerDown:U=>{U.stopPropagation()},onKeyDown:U=>{U.stopPropagation()}}),_&&e.jsx("div",{className:"bg-black text-gray-400 p-2 border-t border-gray-800 h-24 overflow-y-auto whitespace-pre-wrap text-xs shrink-0",children:_})]})]})}function ba(t,r){const x=(t||"").trim();if(!x)return NaN;if(/[;={}\[\]'"`\\&|<>?!]|constructor|prototype|__proto__|window|document|fetch|eval|import|require|process/i.test(x))throw new Error("表达式包含不安全字符");const c=x.replace(/Math\./gi,"").toLowerCase(),u=[];let d=0;for(;d<c.length;){const y=c[d];if(/\s/.test(y)){d++;continue}if(/[0-9.]/.test(y)){let f="";for(;d<c.length&&/[0-9.]/.test(c[d]);)f+=c[d++];u.push(f);continue}if(/[a-z]/.test(y)){let f="";for(;d<c.length&&/[a-z]/.test(c[d]);)f+=c[d++];u.push(f);continue}if("+-*/^%()".includes(y)){u.push(y),d++;continue}throw new Error(`不支持的符号: ${y}`)}let a=0;const n=()=>u[a],g=y=>{const f=u[a++];if(y&&f!==y)throw new Error(`预期 '${y}',但得到 '${f}'`);return f},j=()=>P(),P=()=>{let y=X();for(;n()==="+"||n()==="-";){const f=g(),_=X();y=f==="+"?y+_:y-_}return y},X=()=>{let y=k();for(;n()==="*"||n()==="/"||n()==="%";){const f=g(),_=k();f==="*"?y*=_:f==="/"?y=_===0?NaN:y/_:y%=_}return y},k=()=>{let y=M();for(;n()==="^";){g();const f=k();y=Math.pow(y,f)}return y},M=()=>n()==="-"?(g(),-M()):n()==="+"?(g(),M()):b(),b=()=>{const y=n();if(!y)throw new Error("意外的表达式结尾");if(y==="("){g("(");const _=j();return g(")"),_}if(/^[0-9.]+$/.test(y))return g(),parseFloat(y);if(y==="x")return g(),r;if(y==="pi")return g(),Math.PI;if(y==="e")return g(),Math.E;const f=g();if(n()==="("){g("(");const _=j();switch(g(")"),f){case"sin":return Math.sin(_);case"cos":return Math.cos(_);case"tan":return Math.tan(_);case"sqrt":return Math.sqrt(_);case"abs":return Math.abs(_);case"log":return Math.log(_);case"exp":return Math.exp(_);case"round":return Math.round(_);case"floor":return Math.floor(_);case"ceil":return Math.ceil(_);default:throw new Error(`未知的数学函数: ${f}`)}}throw new Error(`未知的数学标识符: ${y}`)},N=j();if(a<u.length)throw new Error(`多余语法: ${u.slice(a).join(" ")}`);return N}function ga({elementId:t,data:r,onElementUpdate:x,onPointerDown:l,onPointerMove:c,onPointerUp:u,onDelete:d,readOnly:a=!1,isMinimized:n=!1,isMaximized:g=!1,hidden:j=!1,isPropertiesOpen:P=!1,onOpenProperties:X,onMinimize:k,onRestore:M,onMaximize:b,onBrowserFullscreen:N}){const[y,f]=i.useState(r.equation||"sin(x)"),[_,F]=i.useState(""),[L,ie]=i.useState(""),[U,xe]=i.useState({width:400,height:300}),ee=i.useRef(null);i.useEffect(()=>{r.equation!==void 0&&r.equation!==y&&f(r.equation)},[r.equation]),i.useEffect(()=>{if(!ee.current)return;const z=new ResizeObserver(T=>{for(const R of T)xe({width:R.contentRect.width||400,height:R.contentRect.height||300})});return z.observe(ee.current),()=>z.disconnect()},[]),i.useEffect(()=>{try{const z=[],T=U.width/2,R=U.height/2;for(let p=-10;p<=10;p+=.2){const C=p,m=ba(y,C);if(typeof m!="number"||isNaN(m))continue;const O=T+C*20,v=R-m*20;z.push(`${O},${v}`)}F(z.join(" ")),ie("")}catch(z){ie(z.message)}},[y,U]);const J=()=>{x&&y!==r.equation&&x(t,{...r,equation:y})};return e.jsxs("div",{className:"w-full h-full bg-white border border-gray-300 rounded-lg shadow-xl overflow-hidden flex flex-col font-mono text-sm",style:{pointerEvents:a?"none":"auto"},children:[e.jsx(it,{title:r.title||"Math Graph Sandbox",icon:e.jsx(rn,{size:13,className:"text-indigo-500"}),readOnly:a,isMinimized:n,isMaximized:g,hidden:j,isPropertiesOpen:P,themeColor:"default",onPointerDown:l,onPointerMove:c,onPointerUp:u,onOpenProperties:X,onMinimize:k,onRestore:M,onMaximize:b,onBrowserFullscreen:N,onDelete:d}),!n&&e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:"p-3 border-b border-gray-200 flex-none flex flex-col gap-1",children:[e.jsx("span",{className:"text-gray-500 text-xs",children:"y = f(x)"}),e.jsx("input",{type:"text",value:y,disabled:a,onChange:z=>f(z.target.value),onBlur:J,className:"w-full border border-gray-300 rounded px-2 py-1 focus:outline-none focus:border-indigo-500 font-mono text-xs disabled:bg-gray-100 disabled:cursor-not-allowed",placeholder:"e.g. Math.sin(x) * x",onPointerDown:z=>z.stopPropagation(),onKeyDown:z=>z.stopPropagation()}),L&&e.jsx("div",{className:"text-red-500 text-xs mt-1",children:L})]}),e.jsx("div",{className:"flex-1 relative overflow-hidden bg-white min-h-0",ref:ee,children:e.jsxs("svg",{width:U.width,height:U.height,viewBox:`0 0 ${U.width} ${U.height}`,className:"absolute top-0 left-0",children:[e.jsx("line",{x1:U.width/2,y1:"0",x2:U.width/2,y2:U.height,stroke:"#e5e7eb",strokeWidth:"1"}),e.jsx("line",{x1:"0",y1:U.height/2,x2:U.width,y2:U.height/2,stroke:"#e5e7eb",strokeWidth:"1"}),_&&e.jsx("polyline",{points:_,fill:"none",stroke:"#6366f1",strokeWidth:"2",strokeLinejoin:"round"})]})})]})]})}function ya({elementId:t,data:r,onElementUpdate:x,onPointerDown:l,onPointerMove:c,onPointerUp:u,onDelete:d,lessonId:a,readOnly:n=!1,isMinimized:g=!1,isMaximized:j=!1,hidden:P=!1,onBrowserFullscreen:X,isPropertiesOpen:k=!1,onOpenProperties:M,onMinimize:b,onRestore:N,onMaximize:y}){const[f,_]=i.useState(!1),F=async()=>{_(!0);try{await fetch("/api/commands",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({commandType:"hello.say",payload:{lessonId:a,username:"World",shout:!0}})})}catch(L){console.error("Failed to trigger hello.say command:",L)}finally{_(!1)}};return e.jsxs("div",{className:"w-full h-full bg-white border border-slate-200/80 rounded-xl shadow-lg overflow-hidden flex flex-col font-sans select-none",style:{pointerEvents:n?"none":"auto"},children:[e.jsx(it,{title:"Hello World 插件",icon:e.jsx(Yt,{size:11,className:"text-amber-500 animate-pulse"}),readOnly:n,isMinimized:g,isMaximized:j,hidden:P,onBrowserFullscreen:X,isPropertiesOpen:k,themeColor:"slate",onPointerDown:l,onPointerMove:c,onPointerUp:u,onOpenProperties:M,onMinimize:b,onRestore:N,onMaximize:y,onDelete:d}),!g&&e.jsx("div",{className:"flex-1 p-2 flex items-center justify-center bg-slate-50/20",children:e.jsxs("button",{onClick:F,disabled:f,onPointerDown:L=>L.stopPropagation(),className:"w-full py-1 bg-gradient-to-r from-indigo-500 to-purple-600 hover:from-indigo-650 hover:to-purple-750 text-white font-bold text-xs rounded-lg shadow-sm active:scale-95 transition-all flex items-center justify-center gap-1 cursor-pointer",children:[e.jsx(Xs,{size:11,className:f?"animate-spin":""}),e.jsx("span",{children:f?"输出中...":"点击输出"})]})})]})}function wa({elementId:t,data:r,userRole:x="teacher",onElementUpdate:l}){const[c,u]=i.useState("ppt"),[d,a]=i.useState(r.markdown||`# Title Slide
20
+ ---
21
+ ## Slide 2`),[n,g]=i.useState(r.slideX||0),[j,P]=i.useState(!1),[X,k]=i.useState(4),[M,b]=i.useState(!1),N=i.useRef(null),y=x==="teacher",f=x==="student",_=r.fileUrl||"",F=r.fileType||"md",L=r.fileName||"",ie=!!_,[U,xe]=i.useState(!1),ee=i.useRef(null),J=i.useRef(null),z=i.useRef(null),T=!!r.isFullscreenSynced,R=!!r.isFullscreenForced,p=M||f&&T&&R,C=d.split(/(?:\r?\n|^)---(?:\r?\n|$)/).map(B=>B.trim()).filter(B=>B.length>0),m=F==="md"?Math.max(1,C.length):r.slideCount||1;i.useEffect(()=>{F!=="md"&&c!=="ppt"&&u("ppt")},[F,c]),i.useEffect(()=>{r.slideX!==void 0&&r.slideX!==n&&g(r.slideX)},[r.slideX]),i.useEffect(()=>{r.markdown!==void 0&&r.markdown!==d&&a(r.markdown)},[r.markdown]),i.useEffect(()=>{if(F!=="pptx"||!_){z.current&&(z.current.destroy(),z.current=null);return}let B=!0;return fetch(_).then(K=>K.arrayBuffer()).then(async K=>{if(B&&(z.current&&(z.current.destroy(),z.current=null),J.current)){J.current.innerHTML="";try{const{init:ye}=await Bi(async()=>{const{init:le}=await import("./vendor-pptx-D4btWy5L.js").then(be=>be.p);return{init:le}},__vite__mapDeps([0,1])),Y=ye(J.current,{mode:"slide"});z.current=Y,await Y.load(K),B&&(y&&l&&r.slideCount!==Y.slideCount&&l(t,{...r,slideCount:Y.slideCount}),Y.renderSingleSlide(n))}catch(ye){console.error("PPTX preview init failed",ye)}}}).catch(K=>console.error("Fetch PPTX failed",K)),()=>{B=!1,z.current&&(z.current.destroy(),z.current=null)}},[_,F,p]),i.useEffect(()=>{if(F==="pptx"&&z.current)try{z.current.renderSingleSlide(n)}catch(B){console.error("PPTX renderSingleSlide failed",B)}},[n,F]),i.useEffect(()=>{if(!j||c!=="ppt"||F!=="md")return;const B=setInterval(()=>{g(K=>{const ye=(K+1)%Math.max(1,C.length);return l&&l(t,{...r,slideX:ye}),ye})},X*1e3);return()=>clearInterval(B)},[j,X,C.length,c,F]),i.useEffect(()=>{const B=K=>{f&&T&&R||(K.key==="ArrowRight"||K.key===" "?(K.preventDefault(),O(n+1)):K.key==="ArrowLeft"?(K.preventDefault(),O(n-1)):K.key==="Escape"&&p&&(K.preventDefault(),I(!1)))};return window.addEventListener("keydown",B),()=>window.removeEventListener("keydown",B)},[n,p,f,T,R,m]);const O=B=>{if(f&&T&&R)return;const K=Math.min(Math.max(0,B),m-1);g(K),y&&l&&l(t,{...r,slideX:K})},v=B=>{a(B),l&&l(t,{...r,markdown:B})},w=async B=>{const K=B.target.files?.[0];if(!K)return;const ye=K.name.split(".").pop()?.toLowerCase();if(ye!=="pdf"&&ye!=="pptx"){alert("仅支持上传 PDF 或 PPTX 格式的课件文件!");return}xe(!0);try{const Y=new FileReader;Y.onload=async le=>{const je=(le.target?.result).split(",")[1],Me=await fetch("/api/upload",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({filename:K.name,base64Data:je})});if(!Me.ok)throw new Error("服务器上传文件失败");const Ie=await Me.json();l&&(await l(t,{...r,fileUrl:Ie.url,fileName:K.name,fileType:Ie.type,slideX:0,slideCount:Ie.pageCount||1,isFullscreenSynced:r.isFullscreenSynced!==void 0?r.isFullscreenSynced:!0,isFullscreenForced:!1}),g(0))},Y.readAsDataURL(K)}catch(Y){console.error(Y),alert("课件文件上传失败,请重试")}finally{xe(!1)}},q=()=>{window.confirm("确定要清除已上传的课件并恢复为 Markdown 编辑模式吗?")&&l&&(l(t,{...r,fileUrl:"",fileName:"",fileType:"md",slideX:0,slideCount:0,isFullscreenForced:!1}),g(0))},I=B=>{b(B),y&&l&&l(t,{...r,isFullscreenForced:B})},D=B=>{l&&l(t,{...r,isFullscreenSynced:B,isFullscreenForced:B?M:!1})},ne=[{name:"基础通用课件",desc:"标准的课件 structure",content:`# 物理学原理与探究
22
+ ---
23
+ ## 课程介绍
24
+ 1. 经典力学基础
25
+ 2. 能量守恒定律
26
+ 3. 万有引力应用
27
+ ---
28
+ ## 科学探究要素
29
+ - 观察与提问
30
+ - 制定计划与设计实验
31
+ - 进行实验与收集证据
32
+ - 交流、评估及得出结论
33
+ ---
34
+ ## 物理课后思考一
35
+ > 牛顿第一定律是否可以在地球上直接通过实验完全验证?请结合摩擦力阐述。`},{name:"英语词汇互动",desc:"交互式英文闪卡",content:`# Topic: Smart Education
36
+ ---
37
+ ## Key Vocabulary
38
+ - **Orchestration**: Arrangement or cooperation of system systems.
39
+ - **Heuristic**: Practical method not guaranteed to be perfect.
40
+ - **Applet**: Lightweight interactive program.
41
+ ---
42
+ ## Reading Passage
43
+ Modern class orchestration allows instructors to dispatch customized applets directly onto the virtual desk interfaces of student endpoints instantly!
44
+ ---
45
+ ## Fill in the Blank
46
+ The teacher used the virtual whiteboard to ___ classroom active learning slides.
47
+ *(Answer: orchestrate)*`},{name:"微课探究文档",desc:"一页式大纲微课",content:`# 探究牛顿第三定律
48
+ 在本节微课中,我们将探讨作用力与反作用力的核心性质。
49
+
50
+ ## 概念要点
51
+ - 作用力与反作用力**大小相等**
52
+ - 作用力与反作用力**方向相反**
53
+ - 作用力与反作用力作用在**不同的物体上**
54
+ - 它们伴随发生,同时消失。
55
+
56
+ ---
57
+
58
+ ## 经典实验设计
59
+ 1. 准备两个完全相同的弹簧测力计 A 与 B。
60
+ 2. 将它们对拉,观察两者的示数变化。
61
+ 3. 会发现:不管拉力如何变化,A 的读数总是等于 B 的读数。
62
+
63
+ ## 问题思考
64
+ 当马拉着车在水平路面上加速前进时,马拉车的力与车拉马的力,哪一个更大?`}],re=(()=>{const B=d.split(`
65
+ `),K=[];return B.forEach((ye,Y)=>{const le=ye.match(/^(#{1,3})\s+(.*)$/);le&&K.push({text:le[2].trim(),level:le[1].length,lineIndex:Y})}),K})();if(p&&typeof document<"u")return e.jsxs("div",{className:"w-full h-full flex flex-col items-center justify-center bg-slate-900/10 text-slate-400 font-sans p-4",children:[e.jsxs("div",{className:"flex flex-col items-center gap-2",children:[e.jsx(is,{size:24,className:"text-indigo-500 animate-pulse"}),e.jsx("span",{className:"text-xs",children:"演示文稿正在全屏放映中"})]}),Ur.createPortal(e.jsxs("div",{className:"fixed inset-0 z-[99999] bg-neutral-950 flex flex-col items-center justify-center font-sans p-6",children:[e.jsxs("div",{className:"absolute top-4 left-4 right-4 flex items-center justify-between text-white/80 select-none z-[100001] px-4 py-2 bg-neutral-900/60 backdrop-blur-md rounded-xl border border-neutral-800",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("span",{className:"w-2.5 h-2.5 rounded-full bg-emerald-500 animate-pulse"}),e.jsxs("span",{className:"font-bold text-xs tracking-wider uppercase",children:[F==="md"?"Markdown Slides":`${F.toUpperCase()} Presentation`," ",f&&"(Synced)"]})]}),e.jsxs("div",{className:"flex items-center gap-4",children:[e.jsxs("span",{className:"text-xs font-mono text-white/50",children:["Slide ",n+1," / ",m]}),y&&e.jsxs(e.Fragment,{children:[F==="md"&&e.jsx("button",{onClick:()=>P(B=>!B),className:`px-2.5 py-1 rounded-md text-xs uppercase font-bold tracking-wider transition-colors border cursor-pointer ${j?"bg-emerald-50 border-emerald-400 text-white animate-pulse":"bg-transparent border-neutral-700 text-neutral-400 hover:bg-neutral-850"}`,children:j?"Autoplay Live":"Autoplay"}),e.jsxs("label",{className:"flex items-center gap-1.5 text-xs text-white/70 cursor-pointer",children:[e.jsx("input",{type:"checkbox",checked:T,onChange:B=>D(B.target.checked),className:"rounded border-neutral-700 bg-neutral-800 text-indigo-500 focus:ring-0 focus:ring-offset-0 cursor-pointer"}),e.jsx("span",{children:"同步学生全屏"})]})]}),(!f||!R||!T||M)&&e.jsx("button",{onClick:()=>I(!1),className:"p-1 px-2.5 bg-red-600 text-white text-xs font-bold rounded-lg transition-colors cursor-pointer border-0 hover:bg-red-700",title:"退出放映",children:"退出放映 (Esc)"})]})]}),e.jsx("div",{className:"w-full flex-1 min-h-0 flex items-center justify-center relative",children:F==="pdf"?e.jsx("div",{className:"w-full h-full flex items-center justify-center p-2 bg-slate-100 max-w-[90vw] max-h-[82vh] aspect-video rounded-2xl overflow-hidden shadow-2xl border border-neutral-850",children:e.jsx("iframe",{src:`${_}#page=${n+1}&toolbar=0&navpanes=0`,className:"w-full h-full border-0 rounded-xl"},`${_}-fs-${n}`)}):F==="pptx"?e.jsx("div",{className:"w-full h-full flex items-center justify-center p-2 bg-slate-900/5 max-w-[90vw] max-h-[82vh] aspect-video rounded-2xl overflow-hidden shadow-2xl border border-neutral-850",children:e.jsx("div",{ref:J,className:"w-full h-full overflow-auto rounded-xl bg-white border border-slate-100 shadow-md flex items-center justify-center"})}):e.jsx("div",{className:"flex-1 w-full flex items-center justify-center max-w-[90vw] min-h-0",children:e.jsxs("div",{className:"w-full bg-white rounded-xl shadow-md border border-slate-100 flex flex-col overflow-y-auto p-6 md:p-8 aspect-video relative transition-all duration-300 hover:shadow-lg max-h-[82vh] max-w-none p-12 md:p-16 border-neutral-850 rounded-3xl shadow-2xl",children:[e.jsxs("div",{className:"flex justify-between items-center text-xs font-semibold text-slate-400 border-b border-slate-100 pb-2 mb-4 shrink-0",children:[e.jsx("span",{className:"tracking-wide uppercase text-indigo-650",children:"SMART CLASS SLIDE DECK"}),e.jsxs("span",{className:"font-mono",children:["SLIDE ",n+1," / ",m]})]}),e.jsx("div",{className:"flex-1 min-h-0 overflow-y-auto pr-1",children:e.jsx("div",{className:"markdown-body text-slate-800 leading-relaxed font-sans prose prose-neutral max-w-none text-xs",children:C[n]?e.jsx(Fr,{children:C[n]}):e.jsx("div",{className:"text-center text-slate-400 italic py-8",children:"幻灯片没有内容,请在“编辑文档”中添加。"})})}),e.jsxs("div",{className:"mt-4 pt-2 border-t border-slate-50 flex items-center justify-between text-xs text-slate-400 shrink-0 font-sans",children:[e.jsx("span",{children:"智慧互动教室白板演示系统"}),e.jsxs("span",{children:["Page ",n+1]})]})]})})}),!(f&&T&&R)&&e.jsxs("div",{className:"absolute bottom-6 bg-neutral-900/80 backdrop-blur-md px-6 py-2.5 rounded-full border border-neutral-800 shadow-2xl z-[100001]",children:[e.jsx("button",{disabled:n===0||f,onClick:()=>O(n-1),className:`p-1.5 rounded-full border transition-colors cursor-pointer ${n===0||f?"border-neutral-800 text-neutral-600 bg-neutral-950/20 cursor-not-allowed":"border-neutral-700 text-neutral-300 hover:bg-neutral-800"}`,title:"上一张 (ArrowLeft)",children:e.jsx(Wt,{size:18})}),e.jsxs("div",{className:"flex items-center gap-1.5 px-1 font-mono text-xs text-neutral-200",children:[e.jsx("span",{className:"font-bold text-white text-base",children:n+1}),e.jsx("span",{className:"text-neutral-600",children:"/"}),e.jsx("span",{children:m})]}),e.jsx("button",{disabled:n>=m-1||f,onClick:()=>O(n+1),className:`p-1.5 rounded-full border transition-colors cursor-pointer ${n>=m-1||f?"border-neutral-800 text-neutral-600 bg-neutral-950/20 cursor-not-allowed":"border-neutral-700 text-neutral-300 hover:bg-neutral-800"}`,title:"下一张 (ArrowRight)",children:e.jsx(Xt,{size:18})})]})]}),document.body)]});const te=p?"fixed inset-0 z-[99999] bg-neutral-950 flex flex-col items-center justify-center font-sans p-6":"flex-1 flex flex-col items-center justify-between p-4 bg-slate-900/5 relative min-w-0";return e.jsxs("div",{className:"w-full h-full flex flex-col bg-slate-50 text-slate-800 overflow-hidden text-xs relative font-sans",children:[!p&&e.jsxs("div",{className:"flex items-center justify-between px-3 py-1.5 bg-slate-100 border-b border-slate-200 shrink-0 select-none relative z-10",children:[e.jsx("div",{className:"flex items-center gap-1",children:F==="md"?e.jsxs(e.Fragment,{children:[e.jsxs("button",{onClick:()=>u("ppt"),className:`px-2 py-1 rounded flex items-center gap-1 font-medium transition-colors cursor-pointer ${c==="ppt"?"bg-indigo-600 text-white shadow-sm":"text-slate-600 hover:bg-slate-200"}`,title:"播放课件幻灯片 (PPT Mode)",children:[e.jsx(ji,{size:11}),e.jsx("span",{children:"PPT 播放"})]}),e.jsxs("button",{onClick:()=>u("doc"),className:`px-2 py-1 rounded flex items-center gap-1 font-medium transition-colors cursor-pointer ${c==="doc"?"bg-indigo-600 text-white shadow-sm":"text-slate-600 hover:bg-slate-200"}`,title:"以精美文档形式阅读 (Markdown Document mode)",children:[e.jsx(vi,{size:11}),e.jsx("span",{children:"文档阅读"})]}),e.jsxs("button",{onClick:()=>u("edit"),className:`px-2 py-1 rounded flex items-center gap-1 font-medium transition-colors cursor-pointer ${c==="edit"?"bg-indigo-600 text-white shadow-sm":"text-slate-600 hover:bg-slate-200"}`,title:"在线编辑 Markdown 内容",children:[e.jsx(Es,{size:11}),e.jsx("span",{children:"编辑文档"})]})]}):e.jsxs("div",{className:"flex items-center gap-1 bg-indigo-50 border border-indigo-200/50 text-indigo-700 px-2 py-0.5 rounded text-xs font-semibold",children:[e.jsx(is,{size:10}),e.jsxs("span",{children:[F.toUpperCase()," 课件演示中"]})]})}),e.jsxs("div",{className:"flex items-center gap-3",children:[y&&e.jsx("div",{className:"flex items-center gap-1.5 border-r border-slate-200 pr-3",children:U?e.jsxs("div",{className:"flex items-center gap-1 text-xs text-slate-500 font-medium",children:[e.jsx(Ke,{size:10,className:"animate-spin"}),e.jsx("span",{children:"上传解析中..."})]}):ie?e.jsxs("div",{className:"flex items-center gap-1.5 bg-slate-200/50 pl-2 pr-1.5 py-0.5 rounded border border-slate-300/30",children:[e.jsx("span",{className:"text-xs font-medium text-slate-600 max-w-[120px] truncate font-mono",title:L,children:L}),e.jsx("button",{onClick:q,className:"p-0.5 hover:bg-slate-300 rounded text-red-500 cursor-pointer border-0 bg-transparent",title:"清除并切换回 Markdown",children:e.jsx(ct,{size:10})})]}):e.jsxs("div",{children:[e.jsxs("button",{onClick:()=>ee.current?.click(),className:"px-2 py-1 rounded bg-indigo-50 border border-indigo-200 text-indigo-700 hover:bg-indigo-100 flex items-center gap-1 font-semibold text-xs cursor-pointer",title:"上传 PPTX 或 PDF 课件",children:[e.jsx(as,{size:10}),e.jsx("span",{children:"上传课件"})]}),e.jsx("input",{type:"file",ref:ee,onChange:w,accept:".pdf,.pptx",className:"hidden"})]})}),c==="ppt"&&F==="md"&&e.jsxs("div",{className:"flex items-center gap-1.5",children:[e.jsxs("button",{onClick:()=>P(B=>!B),className:`p-1 rounded flex items-center gap-1 font-semibold text-xs transition-colors border cursor-pointer ${j?"bg-emerald-50 border-emerald-300 text-emerald-700":"bg-white border-slate-200 text-slate-500 hover:bg-slate-50"}`,title:"开启/关闭幻灯片自动播放",children:[j?e.jsx("span",{className:"w-1.5 h-1.5 rounded-full bg-emerald-500 animate-ping"}):null,e.jsx("span",{children:j?"自动播放中":"自动播放"})]}),j&&e.jsxs("select",{value:X,onChange:B=>k(Number(B.target.value)),className:"bg-white border border-slate-200 rounded px-1 text-xs py-0.5 text-slate-700 font-medium",children:[e.jsx("option",{value:2,children:"2秒"}),e.jsx("option",{value:4,children:"4秒"}),e.jsx("option",{value:6,children:"6秒"}),e.jsx("option",{value:10,children:"10秒"})]})]}),y&&c==="ppt"&&e.jsxs("label",{className:"flex items-center gap-1 text-xs text-slate-500 font-medium cursor-pointer",children:[e.jsx("input",{type:"checkbox",checked:T,onChange:B=>D(B.target.checked),className:"rounded border-slate-300 text-indigo-650 focus:ring-0 focus:ring-offset-0 cursor-pointer"}),e.jsx("span",{children:"同步学生全屏"})]}),c==="ppt"&&(!f||!(T&&R))&&e.jsx("button",{onClick:()=>I(!0),className:"p-1 rounded-lg text-slate-655 hover:bg-slate-200 border border-slate-200 bg-white transition-colors cursor-pointer",title:"全屏放映",children:e.jsx(Ws,{size:11})})]})]}),e.jsxs("div",{className:"flex-1 min-h-0 relative flex flex-row overflow-hidden",children:[c==="ppt"&&e.jsxs("div",{className:te,children:[p&&e.jsxs("div",{className:"absolute top-4 left-4 right-4 flex items-center justify-between text-white/80 select-none z-[100001] px-4 py-2 bg-neutral-900/60 backdrop-blur-md rounded-xl border border-neutral-800",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("span",{className:"w-2.5 h-2.5 rounded-full bg-emerald-500 animate-pulse"}),e.jsxs("span",{className:"font-bold text-xs tracking-wider uppercase",children:[F==="md"?"Markdown Slides":`${F.toUpperCase()} Presentation`," ",f&&"(Synced)"]})]}),e.jsxs("div",{className:"flex items-center gap-4",children:[e.jsxs("span",{className:"text-xs font-mono text-white/50",children:["Slide ",n+1," / ",m]}),y&&e.jsxs(e.Fragment,{children:[F==="md"&&e.jsx("button",{onClick:()=>P(B=>!B),className:`px-2.5 py-1 rounded-md text-xs uppercase font-bold tracking-wider transition-colors border cursor-pointer ${j?"bg-emerald-50 border-emerald-400 text-white animate-pulse":"bg-transparent border-neutral-700 text-neutral-400 hover:bg-neutral-850"}`,children:j?"Autoplay Live":"Autoplay"}),e.jsxs("label",{className:"flex items-center gap-1.5 text-xs text-white/70 cursor-pointer",children:[e.jsx("input",{type:"checkbox",checked:T,onChange:B=>D(B.target.checked),className:"rounded border-neutral-700 bg-neutral-800 text-indigo-500 focus:ring-0 focus:ring-offset-0 cursor-pointer"}),e.jsx("span",{children:"同步学生全屏"})]}),e.jsx("button",{onClick:()=>I(!1),className:"p-1 px-2.5 bg-red-655 text-white text-xs font-bold rounded-md transition-colors cursor-pointer border-0",title:"退出放映",children:"退出放映 (Esc)"})]})]})]}),e.jsx("div",{className:"w-full flex-1 min-h-0 flex items-center justify-center relative",children:F==="pdf"?e.jsx("div",{className:`w-full h-full flex items-center justify-center p-2 bg-slate-100 ${p?"max-w-5xl aspect-video rounded-2xl overflow-hidden shadow-2xl border border-neutral-850":""}`,children:e.jsx("iframe",{src:`${_}#page=${n+1}&toolbar=0&navpanes=0`,className:"w-full h-full border-0 rounded-xl"},`${_}-${p?"fs":"card"}-${n}`)}):F==="pptx"?e.jsx("div",{className:`w-full h-full flex items-center justify-center p-2 bg-slate-900/5 ${p?"max-w-5xl aspect-video rounded-2xl overflow-hidden shadow-2xl border border-neutral-850":""}`,children:e.jsx("div",{ref:J,className:"w-full h-full overflow-auto rounded-xl bg-white border border-slate-100 shadow-md flex items-center justify-center"})}):e.jsx("div",{className:"flex-1 w-full flex items-center justify-center max-w-2xl min-h-0",children:e.jsxs("div",{className:`w-full bg-white rounded-xl shadow-md border border-slate-100 flex flex-col overflow-y-auto p-6 md:p-8 aspect-video relative transition-all duration-300 hover:shadow-lg max-h-full ${p?"max-w-4xl p-12 md:p-16 border-neutral-850 rounded-3xl shadow-2xl":""}`,children:[e.jsxs("div",{className:"flex justify-between items-center text-xs font-semibold text-slate-400 border-b border-slate-100 pb-2 mb-4 shrink-0",children:[e.jsx("span",{className:"tracking-wide uppercase text-indigo-650",children:"SMART CLASS SLIDE DECK"}),e.jsxs("span",{className:"font-mono",children:["SLIDE ",n+1," / ",m]})]}),e.jsx("div",{className:"flex-1 min-h-0 overflow-y-auto pr-1",children:e.jsx("div",{className:"markdown-body text-slate-800 leading-relaxed font-sans prose prose-neutral max-w-none text-xs",children:C[n]?e.jsx(Fr,{children:C[n]}):e.jsx("div",{className:"text-center text-slate-400 italic py-8",children:"幻灯片没有内容,请在“编辑文档”中添加。"})})}),e.jsxs("div",{className:"mt-4 pt-2 border-t border-slate-50 flex items-center justify-between text-xs text-slate-400 shrink-0 font-sans",children:[e.jsx("span",{children:"智慧互动教室白板演示系统"}),e.jsxs("span",{children:["Page ",n+1]})]})]})})}),!(f&&T&&R)&&e.jsxs("div",{className:`mt-4 flex items-center justify-center gap-3 select-none shrink-0 ${p?"absolute bottom-6 bg-neutral-900/80 backdrop-blur-md px-6 py-2.5 rounded-full border border-neutral-800 shadow-2xl z-[100001]":"bg-white px-4 py-2 rounded-full border border-slate-200/80 shadow-md relative z-10"}`,children:[e.jsx("button",{disabled:n===0||f&&T&&R,onClick:()=>O(n-1),className:`p-1.5 rounded-full border transition-colors cursor-pointer ${n===0||f&&T&&R?p?"border-neutral-800 text-neutral-600 bg-neutral-950/20 cursor-not-allowed":"border-slate-100 bg-slate-50 text-slate-300 cursor-not-allowed":p?"border-neutral-700 text-neutral-300 hover:bg-neutral-800":"border-slate-205 text-slate-655 hover:bg-slate-50"}`,title:"上一张 (ArrowLeft)",children:e.jsx(Wt,{size:p?18:14})}),e.jsxs("div",{className:`flex items-center gap-1.5 px-1 font-mono text-xs ${p?"text-neutral-200":"text-slate-700"}`,children:[e.jsx("span",{className:`font-bold ${p?"text-white text-base":"text-slate-900"}`,children:n+1}),e.jsx("span",{className:p?"text-neutral-600":"text-slate-350",children:"/"}),e.jsx("span",{children:m})]}),e.jsx("button",{disabled:n>=m-1||f&&T&&R,onClick:()=>O(n+1),className:`p-1.5 rounded-full border transition-colors cursor-pointer ${n>=m-1||f&&T&&R?p?"border-neutral-800 text-neutral-600 bg-neutral-950/20 cursor-not-allowed":"border-slate-100 bg-slate-50 text-slate-300 cursor-not-allowed":p?"border-neutral-700 text-neutral-300 hover:bg-neutral-800":"border-slate-205 text-slate-655 hover:bg-slate-50"}`,title:"下一张 (ArrowRight)",children:e.jsx(Xt,{size:p?18:14})})]})]}),c==="doc"&&F==="md"&&e.jsxs("div",{className:"flex-1 flex flex-row min-h-0 bg-white",children:[re.length>0&&e.jsxs("div",{className:"w-1/4 min-w-[120px] max-w-[200px] border-r border-slate-200 bg-slate-50/50 flex flex-col py-3 px-2 overflow-y-auto shrink-0 select-none",children:[e.jsxs("span",{className:"text-xs font-bold text-slate-400 uppercase tracking-widest px-2 mb-2 flex items-center gap-1",children:[e.jsx(Ut,{size:10}),"文档大纲"]}),e.jsx("div",{className:"flex flex-col gap-0.5",children:re.map((B,K)=>e.jsx("button",{onClick:()=>{const ye=N.current?.querySelector(`[data-line-index="${B.lineIndex}"]`);ye&&ye.scrollIntoView({behavior:"smooth",block:"start"})},className:"text-left text-xs py-1 px-2 rounded hover:bg-slate-100 text-slate-600 hover:text-slate-900 truncate cursor-pointer font-medium whitespace-nowrap border-0 bg-transparent",style:{paddingLeft:`${Math.max(8,B.level*6)}px`},title:B.text,children:B.text},K))})]}),e.jsx("div",{className:"flex-1 min-h-0 overflow-y-auto p-6 md:p-8",ref:N,children:e.jsx("div",{className:"markdown-body prose prose-neutral max-w-none text-xs leading-relaxed text-slate-700",children:d.split(`
66
+ `).map((B,K)=>{const ye=B.match(/^(#{1,3})\s+(.*)$/);if(ye){const Y=ye[1].length,le=ye[2].trim(),be=Y===1?"h1":Y===2?"h2":"h3",je=Y===1?"text-lg font-bold text-indigo-900 border-b pb-1 mt-4 mb-2":Y===2?"text-base font-bold text-slate-800 mt-3 mb-1.5":"text-sm font-semibold text-slate-700 mt-2 mb-1";return e.jsx(be,{"data-line-index":K,className:je,children:le},K)}return B.trim()==="---"?e.jsx("hr",{className:"my-4 border-slate-200"},K):e.jsx("p",{className:"my-1.5 text-slate-600 antialiased leading-relaxed",children:B},K)})})})]}),c==="edit"&&F==="md"&&e.jsxs("div",{className:"flex-1 flex flex-col md:flex-row min-h-0 bg-white",children:[e.jsxs("div",{className:"w-full md:w-1/3 border-b md:border-b-0 md:border-r border-slate-100 bg-slate-50/40 p-3 flex flex-col overflow-y-auto shrink-0 select-none",children:[e.jsxs("span",{className:"text-xs font-bold text-slate-400 tracking-wider uppercase mb-2 flex items-center gap-1",children:[e.jsx(Xs,{size:10,className:"text-indigo-650"}),"推荐课件及文档模板"]}),e.jsx("div",{className:"flex flex-col gap-2",children:ne.map((B,K)=>e.jsxs("button",{type:"button",onClick:()=>{window.confirm(`确定要加载模板 “${B.name}” 吗?这将会覆盖当前白板课件中的所有编辑内容。`)&&(v(B.content),g(0))},className:"w-full text-left p-2.5 rounded-lg border border-slate-200 bg-white hover:border-indigo-300 hover:shadow-sm transition-all focus:outline-none cursor-pointer group",children:[e.jsx("div",{className:"font-bold text-xs text-slate-800 group-hover:text-indigo-700 whitespace-nowrap overflow-hidden text-ellipsis",children:B.name}),e.jsx("div",{className:"text-xs text-slate-400 mt-0.5",children:B.desc})]},K))}),e.jsxs("div",{className:"mt-4 p-2 bg-amber-50 rounded border border-amber-100 text-xs text-amber-700 font-sans leading-relaxed",children:[e.jsx("strong",{children:"💡 使用提示"}),e.jsx("br",{}),"在任意位置插入一行 ",e.jsx("code",{children:"---"})," 即可分割出一个新的幻灯片(PPT)页面。"]})]}),e.jsxs("div",{className:"flex-1 flex flex-col p-3 min-h-[200px]",children:[e.jsxs("div",{className:"flex items-center justify-between mb-1.5 px-1",children:[e.jsx("span",{className:"font-bold text-slate-500 text-xs uppercase",children:"Markdown Source Code"}),e.jsx("span",{className:"text-xs text-slate-400",children:"实时自动同步到所有协同终端"})]}),e.jsx("textarea",{value:d,onChange:B=>v(B.target.value),placeholder:"在此输入 Markdown 文档。使用 '---' 来作为 PPT 页面分页符...",className:"flex-1 w-full p-3 font-mono text-xs bg-slate-50 border border-slate-200 rounded-lg focus:outline-none focus:ring-1 focus:ring-indigo-500 focus:bg-white transition-all resize-none leading-relaxed text-slate-800"})]})]})]})]})}const ja=({tool:t,setTool:r,setSelectedShapeId:x,highlighterColor:l,setHighlighterColor:c,onElementAdd:u,currentPage:d,activeSegmentId:a,lessonId:n,safeElements:g,selectedShapeId:j,showGrid:P,setShowGrid:X,autoTileEnabled:k=!1,onToggleAutoTile:M,readOnly:b=!1,userRole:N="teacher",isSyncing:y,setIsSyncing:f,handleClearBoard:_,handleResetBoard:F,handleElementDelete:L,setDialog:ie,setDialogInput:U,onRefresh:xe,classroomTools:ee=[],onExecuteTool:J})=>{const[z,T]=i.useState(!1),R=i.useRef(null),[p,C]=i.useState(null),m=i.useCallback(()=>{const w=R.current?.getBoundingClientRect();w&&C({top:w.bottom+6,left:Math.max(8,Math.min(w.left,window.innerWidth-340))}),T(q=>!q)},[]);i.useEffect(()=>{if(!z)return;const w=()=>T(!1);return window.addEventListener("scroll",w,!0),window.addEventListener("resize",w),()=>{window.removeEventListener("scroll",w,!0),window.removeEventListener("resize",w)}},[z]);const O=i.useCallback(w=>{T(!1),J?.(w)},[J]),v=z&&p?Ur.createPortal(e.jsxs(e.Fragment,{children:[e.jsx("div",{className:"fixed inset-0 z-[9998]",onPointerDown:()=>T(!1)}),e.jsxs("div",{className:"fixed z-[9999] w-[320px] max-h-[420px] overflow-y-auto bg-surface border border-theme rounded-xl shadow-xl p-2 font-sans text-main",style:{top:p.top,left:p.left},children:[e.jsxs("div",{className:"px-2 py-1.5 text-2xs font-black uppercase tracking-wider text-muted flex items-center gap-1.5 sticky top-0 bg-surface",children:[e.jsx(Cs,{size:11,className:"text-primary-theme"}),ee.length>0?`互动工具 · ${ee.length} 个插件`:"互动工具"]}),ee.length>0?ee.map(w=>e.jsxs("button",{onClick:()=>O(w),disabled:!n,title:w.description,className:"w-full flex items-start gap-2.5 px-2 py-2 rounded-lg hover:bg-surface-secondary text-left transition-colors disabled:opacity-40 disabled:cursor-not-allowed cursor-pointer",children:[e.jsx("span",{className:"p-1.5 rounded-lg bg-primary-theme/10 text-primary-theme border border-primary-theme/20 shrink-0",children:e.jsx(Cs,{size:13})}),e.jsxs("span",{className:"min-w-0 flex-1",children:[e.jsx("span",{className:"block text-xs font-bold text-main truncate",children:w.name}),e.jsx("span",{className:"block text-2xs text-muted truncate mt-0.5",children:w.description||w.name})]})]},`${w.pluginId}/${w.id}`)):e.jsx("div",{className:"px-2 py-3 text-xs text-muted italic text-center",children:"暂无可用的互动工具。请在应用商店启用插件。"})]})]}),document.body):null;return e.jsxs("div",{className:"flex items-center justify-between gap-1.5 px-2 py-1 bg-surface/95 backdrop-blur-md border-b border-theme/80 shrink-0 font-sans select-none text-main min-h-[38px] overflow-x-auto no-scrollbar",children:[e.jsxs("div",{className:"flex items-center gap-1.5 min-w-0",children:[e.jsxs("div",{className:"flex items-center gap-0.5 bg-surface-secondary/70 p-0.5 rounded-xl border border-theme/60 shrink-0",children:[e.jsx("button",{onClick:()=>{r("cursor"),x(null)},className:`w-7 h-7 flex items-center justify-center rounded-lg transition-all cursor-pointer ${t==="cursor"?"bg-primary-theme text-white shadow-2xs":"text-muted hover:bg-surface hover:text-main"}`,title:"选择工具 (Pointer / Selector)",children:e.jsx(nn,{size:14})}),e.jsx("div",{className:"w-px h-3.5 bg-border-theme/60 mx-0.5"}),e.jsx("button",{onClick:()=>r("pen"),className:`w-7 h-7 flex items-center justify-center rounded-lg transition-all cursor-pointer ${t==="pen"?"bg-primary-theme text-white shadow-2xs":"text-muted hover:bg-surface hover:text-main"}`,title:"画笔工具 (Pen)",children:e.jsx(an,{size:14})}),e.jsx("button",{onClick:()=>r("highlighter"),className:`w-7 h-7 flex items-center justify-center rounded-lg transition-all cursor-pointer ${t==="highlighter"?"bg-amber-500 text-white shadow-2xs":"text-muted hover:bg-surface hover:text-main"}`,title:"荧光高亮笔 (Highlighter)",children:e.jsx(on,{size:14})}),t==="highlighter"&&e.jsx("div",{className:"flex items-center gap-1 bg-surface px-1 py-0.5 rounded-lg border border-theme animate-in zoom-in-95 duration-150",children:[{hex:"#facc15",label:"Yellow"},{hex:"#4ade80",label:"Green"},{hex:"#f472b6",label:"Pink"},{hex:"#60a5fa",label:"Blue"}].map(w=>e.jsx("button",{onClick:()=>c(w.hex),className:`w-3 h-3 rounded-full border transition-all ${l===w.hex?"ring-2 ring-primary-theme scale-110 border-white":"border-transparent"}`,style:{backgroundColor:w.hex},title:w.label},w.hex))}),e.jsx("div",{className:"w-px h-3.5 bg-border-theme/60 mx-0.5"}),e.jsx("button",{onClick:()=>r("rect"),className:`w-7 h-7 flex items-center justify-center rounded-lg transition-all cursor-pointer ${t==="rect"?"bg-primary-theme text-white shadow-2xs":"text-muted hover:bg-surface hover:text-main"}`,title:"矩形工具 (Rectangle)",children:e.jsx(Hs,{size:14})}),e.jsx("button",{onClick:()=>r("circle"),className:`w-7 h-7 flex items-center justify-center rounded-lg transition-all cursor-pointer ${t==="circle"?"bg-primary-theme text-white shadow-2xs":"text-muted hover:bg-surface hover:text-main"}`,title:"圆形工具 (Circle)",children:e.jsx(ln,{size:14})}),e.jsx("button",{onClick:()=>r("text"),className:`w-7 h-7 flex items-center justify-center rounded-lg transition-all cursor-pointer ${t==="text"?"bg-primary-theme text-white shadow-2xs":"text-muted hover:bg-surface hover:text-main"}`,title:"文本工具 (Text)",children:e.jsx(cn,{size:14})})]}),e.jsxs("div",{className:"flex items-center gap-0.5 bg-surface-secondary/70 p-0.5 rounded-xl border border-theme/60 shrink-0",children:[e.jsx(_e,{slot:"anchor:whiteboard-toolbar:presentation",placement:"before"}),e.jsx("button",{onClick:()=>{U(`# Title Slide
67
+ ---
68
+ ## Slide 2`),ie({type:"prompt",title:"添加演示文稿",message:"请输入演示文稿的 Markdown 内容 (使用 --- 拆分新幻灯片):",placeholder:`# Title Slide
69
+ ---
70
+ ## Slide 2`,onConfirm:async w=>{const q=w||`# Title Slide
71
+ ---
72
+ ## Slide 2`;f(!0);try{await u("presentation",{markdown:q,x:50,y:50,width:600,height:400,slideX:0,slideY:0,page:d,segmentId:a}),ae.publish({id:oe(),type:"whiteboard.element_updated",source:"whiteboard",payload:{lessonId:n},timestamp:Date.now(),correlationId:n})}finally{f(!1),ie(null)}}})},className:"w-7 h-7 flex items-center justify-center rounded-lg text-muted hover:bg-surface hover:text-main transition-all cursor-pointer",title:"插入演示幻灯片 (Presentation)",children:e.jsx(is,{size:14})}),e.jsx(_e,{slot:"anchor:whiteboard-toolbar:presentation",placement:"after"}),e.jsx(_e,{slot:"anchor:whiteboard-toolbar:code-sandbox",placement:"before"}),e.jsx("button",{onClick:async()=>{f(!0);try{await u("code-sandbox",{code:"console.log('Hello Sandbox!');",x:100,y:100,page:d,segmentId:a}),ae.publish({id:oe(),type:"whiteboard.element_updated",source:"whiteboard",payload:{lessonId:n},timestamp:Date.now(),correlationId:n})}finally{f(!1)}},className:"w-7 h-7 flex items-center justify-center rounded-lg text-muted hover:bg-surface hover:text-main transition-all cursor-pointer",title:"插入代码沙箱 (Code Sandbox)",children:e.jsx(sn,{size:14})}),e.jsx(_e,{slot:"anchor:whiteboard-toolbar:code-sandbox",placement:"after"}),e.jsx(_e,{slot:"anchor:whiteboard-toolbar:math-graph",placement:"before"}),e.jsx("button",{onClick:async()=>{f(!0);try{await u("math-graph",{equation:"Math.sin(x)",x:100,y:150,page:d,segmentId:a}),ae.publish({id:oe(),type:"whiteboard.element_updated",source:"whiteboard",payload:{lessonId:n},timestamp:Date.now(),correlationId:n})}finally{f(!1)}},className:"w-7 h-7 flex items-center justify-center rounded-lg text-muted hover:bg-surface hover:text-main transition-all cursor-pointer",title:"插入数学函数图表 (Math Graph)",children:e.jsx(rn,{size:14})}),e.jsx(_e,{slot:"anchor:whiteboard-toolbar:math-graph",placement:"after"}),e.jsx(_e,{slot:"anchor:whiteboard-toolbar:courseware",placement:"before"}),e.jsx("button",{onClick:async()=>{f(!0);try{await u("html-applet",{code:`<!-- Interactive Web Courseware -->
73
+ <div style='padding:20px; text-align:center;'>
74
+ <h2>Interactive Web Courseware</h2>
75
+ <p>可在右侧属性栏中选择本地 ZIP/HTML 部署包。</p>
76
+ </div>`,x:100,y:150,page:d,segmentId:a}),ae.publish({id:oe(),type:"whiteboard.element_updated",source:"whiteboard",payload:{lessonId:n},timestamp:Date.now(),correlationId:n})}finally{f(!1)}},className:"w-7 h-7 flex items-center justify-center rounded-lg text-muted hover:bg-surface hover:text-main transition-all cursor-pointer",title:"插入交互网页课件 (Interactive Courseware)",children:e.jsx(qs,{size:14})}),e.jsx(_e,{slot:"anchor:whiteboard-toolbar:courseware",placement:"after"}),e.jsx("div",{className:"w-px h-3.5 bg-border-theme/60 mx-0.5"}),e.jsx(_e,{slot:"anchor:whiteboard-toolbar:rollcall",placement:"before"}),e.jsx("button",{onClick:async()=>{f(!0);try{await u("rollcall",{title:"随机点名助手",x:120,y:120,page:d,segmentId:a}),ae.publish({id:oe(),type:"whiteboard.element_updated",source:"whiteboard",payload:{lessonId:n},timestamp:Date.now(),correlationId:n})}finally{f(!1)}},className:"w-7 h-7 flex items-center justify-center rounded-lg text-primary-theme hover:bg-primary-theme-light transition-all cursor-pointer",title:"插入随机点名组件 (Roll Call)",children:e.jsx(en,{size:14})}),e.jsx(_e,{slot:"anchor:whiteboard-toolbar:rollcall",placement:"after"})]}),e.jsx(_e,{slot:"classroom.tool"}),e.jsx("div",{className:"flex items-center gap-0.5 bg-surface-secondary/70 p-0.5 rounded-xl border border-theme/60 shrink-0",children:e.jsxs("button",{ref:R,onClick:m,className:`relative w-7 h-7 flex items-center justify-center rounded-lg transition-all cursor-pointer ${z?"bg-primary-theme text-white shadow-2xs":"text-primary-theme hover:bg-primary-theme-light"} ${ee.length===0?"opacity-50":""}`,title:"互动工具 (插件扩展)",children:[e.jsx(Cs,{size:14}),ee.length>0&&e.jsx("span",{className:"absolute -top-1 -right-1 min-w-[14px] h-[14px] px-0.5 rounded-full bg-primary-theme text-white text-[9px] font-bold flex items-center justify-center leading-none",children:ee.length})]})}),v,e.jsx(_e,{slot:"anchor:whiteboard-toolbar:ai-tutor",placement:"before"}),e.jsx("button",{onClick:async()=>{f(!0);try{(await fetch(`/api/lessons/${n}/ai-tutor`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({elements:g.map(q=>({type:q.type,data:JSON.parse(q.data)}))})})).ok?(ae.publish({id:oe(),type:"whiteboard.element_updated",source:"whiteboard",payload:{lessonId:n},timestamp:Date.now(),correlationId:n}),xe&&xe()):ie({type:"alert",title:"AI 辅导提示",message:"无法获取 AI 授课助手的帮助,请稍后再试。",onConfirm:()=>ie(null)})}finally{f(!1)}},className:"w-7 h-7 flex items-center justify-center rounded-lg text-purple-600 hover:bg-purple-500/10 transition-all cursor-pointer shrink-0",title:"请求 AI 助教建议 (Ask AI Tutor)",children:e.jsx(Xs,{size:14})}),e.jsx(_e,{slot:"anchor:whiteboard-toolbar:ai-tutor",placement:"after"})]}),e.jsxs("div",{className:"flex items-center gap-1 shrink-0 ml-auto",children:[e.jsx(_e,{slot:"anchor:whiteboard-toolbar:grid",placement:"before"}),e.jsx("button",{onClick:()=>X(w=>!w),className:`w-7 h-7 flex items-center justify-center rounded-lg transition-all cursor-pointer ${P?"text-primary-theme bg-primary-theme-light":"text-muted hover:bg-surface-secondary hover:text-main"}`,title:P?"关闭网格背景":"开启网格背景",children:e.jsx(Ni,{size:14})}),e.jsx(_e,{slot:"anchor:whiteboard-toolbar:grid",placement:"after"}),!b&&M&&e.jsxs(e.Fragment,{children:[e.jsx("button",{onClick:M,className:`w-7 h-7 flex items-center justify-center rounded-lg transition-all cursor-pointer ${k?"text-primary-theme bg-primary-theme-light":"text-muted hover:bg-surface-secondary hover:text-main"}`,title:k?"关闭自动平铺,恢复自由布局":"开启自动平铺(i3 式镶嵌布局)",children:e.jsx(Rs,{size:14})}),k&&e.jsx("span",{className:"text-2xs font-semibold text-primary-theme whitespace-nowrap",title:"当前为自动平铺模式,新组件会自动落入下一个格子",children:"平铺中"})]}),j&&e.jsxs("button",{onClick:()=>{L(j),x(null)},className:"px-2 py-0.5 rounded-lg text-rose-500 bg-rose-500/10 hover:bg-rose-500/20 border border-rose-500/30 text-xs font-semibold flex items-center gap-1 transition-all cursor-pointer shadow-2xs",title:"删除选中图形",children:[e.jsx(ct,{size:12}),e.jsx("span",{className:"hidden sm:inline",children:"删除"})]}),N!=="student"?e.jsx("button",{onClick:_,className:"w-7 h-7 flex items-center justify-center rounded-lg text-muted hover:text-rose-500 hover:bg-rose-500/10 transition-all cursor-pointer",title:"清空白板 (Clear Board)",children:e.jsx(ki,{size:14})}):e.jsx("button",{onClick:F,className:"w-7 h-7 flex items-center justify-center rounded-lg text-muted hover:text-amber-500 hover:bg-amber-500/10 transition-all cursor-pointer",title:"重置白板 (Reset Board)",children:e.jsx(Ci,{size:14})}),y&&e.jsx(Ke,{size:13,className:"text-primary-theme animate-spin ml-0.5"})]})]})},va=({pages:t,currentPage:r,showPageDrawer:x,setShowPageDrawer:l,editingPageIdx:c,setEditingPageIdx:u,editingPageTitle:d,setEditingPageTitle:a,activeMenuPageIdx:n,setActiveMenuPageIdx:g,safeElements:j,handleSwitchPage:P,handleRenamePage:X,handleDuplicatePage:k,handleMovePage:M,handleDeletePage:b,handleAddPage:N})=>e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:"absolute top-3 left-1/2 -translate-x-1/2 z-20 flex items-center gap-1.5 bg-surface/90 backdrop-blur-md px-3 py-1.5 rounded-full shadow-lg border border-theme font-sans select-none text-main",children:[e.jsxs("button",{onClick:()=>l(!x),className:`p-1.5 rounded-full transition-colors cursor-pointer flex items-center gap-1 text-xs font-medium ${x?"bg-primary-theme-light text-primary-theme":"text-muted hover:bg-surface-secondary hover:text-main"}`,title:"页面大纲与预览 (Pages Outline)",children:[e.jsx(Rs,{size:15}),e.jsxs("span",{className:"hidden sm:inline text-xs font-semibold",children:["大纲 (",t.length,")"]})]}),e.jsx("div",{className:"h-4 w-px bg-border-theme mx-0.5"}),e.jsx("button",{onClick:()=>P(Math.max(0,r-1)),className:"p-1 hover:bg-surface-secondary rounded-full text-muted hover:text-main disabled:opacity-30 disabled:hover:bg-transparent transition-colors cursor-pointer",disabled:r===0,title:"上一页",children:e.jsx(Wt,{size:16})}),e.jsx("div",{className:"flex items-center gap-1 max-w-[500px] overflow-x-auto no-scrollbar py-0.5",children:t.map((y,f)=>{const _=f===r,F=c===f;return e.jsxs("div",{className:"relative group flex items-center",children:[F?e.jsx("input",{type:"text",autoFocus:!0,value:d,onChange:L=>a(L.target.value),onKeyDown:L=>{L.key==="Enter"&&X(f,d),L.key==="Escape"&&u(null)},onBlur:()=>X(f,d),className:"px-2 py-0.5 text-xs font-bold bg-surface border border-primary-theme rounded-full outline-none w-28 text-main shadow-2xs"}):e.jsx("button",{onClick:()=>P(f),onDoubleClick:()=>{u(f),a(y.title)},className:`px-3 py-1 rounded-full text-xs font-bold transition-all cursor-pointer flex items-center gap-1 border ${_?"bg-primary-theme text-white border-primary-theme shadow-2xs":"text-muted hover:bg-surface-secondary hover:text-main border-transparent"}`,title:"双击重命名",children:e.jsx("span",{className:"truncate max-w-[120px]",children:y.title})}),e.jsx("button",{onClick:L=>{L.stopPropagation(),g(n===f?null:f)},className:`p-0.5 rounded-full hover:bg-black/10 transition-colors ml-[-4px] z-10 ${_?"text-white/80 hover:text-white":"text-muted hover:text-main"}`,title:"页面选项",children:e.jsx(Si,{size:12})}),n===f&&e.jsxs("div",{className:"absolute top-full mt-2 left-1/2 -translate-x-1/2 bg-surface rounded-xl shadow-xl border border-theme py-1 w-36 z-50 text-xs font-normal text-main",onClick:L=>L.stopPropagation(),children:[e.jsxs("button",{onClick:()=>{u(f),a(y.title),g(null)},className:"w-full px-3 py-1.5 text-left text-main hover:bg-primary-theme-light hover:text-primary-theme flex items-center gap-2 cursor-pointer",children:[e.jsx(Es,{size:13})," 重命名"]}),e.jsxs("button",{onClick:()=>{k(f),g(null)},className:"w-full px-3 py-1.5 text-left text-main hover:bg-primary-theme-light hover:text-primary-theme flex items-center gap-2 cursor-pointer",children:[e.jsx(Br,{size:13})," 复制页面"]}),f>0&&e.jsxs("button",{onClick:()=>{M(f,"left"),g(null)},className:"w-full px-3 py-1.5 text-left text-main hover:bg-primary-theme-light hover:text-primary-theme flex items-center gap-2 cursor-pointer",children:[e.jsx(Wt,{size:13})," 向左移动"]}),f<t.length-1&&e.jsxs("button",{onClick:()=>{M(f,"right"),g(null)},className:"w-full px-3 py-1.5 text-left text-main hover:bg-primary-theme-light hover:text-primary-theme flex items-center gap-2 cursor-pointer",children:[e.jsx(Xt,{size:13})," 向右移动"]}),e.jsx("div",{className:"my-1 border-t border-theme"}),e.jsxs("button",{onClick:()=>{b(f),g(null)},className:"w-full px-3 py-1.5 text-left text-rose-500 hover:bg-rose-500/10 flex items-center gap-2 cursor-pointer disabled:opacity-30",disabled:t.length<=1,children:[e.jsx(ct,{size:13})," 删除页面"]})]})]},y.id||f)})}),e.jsx("button",{onClick:()=>N(),className:"p-1 hover:bg-primary-theme-light hover:text-primary-theme text-muted rounded-full transition-colors cursor-pointer ml-0.5",title:"新建白板页面",children:e.jsx(It,{size:16})}),e.jsx("button",{onClick:()=>P(Math.min(t.length-1,r+1)),className:"p-1 hover:bg-surface-secondary rounded-full text-muted hover:text-main disabled:opacity-30 disabled:hover:bg-transparent transition-colors cursor-pointer",disabled:r>=t.length-1,title:"下一页",children:e.jsx(Xt,{size:16})})]}),x&&e.jsx("div",{className:"absolute inset-0 bg-slate-950/40 backdrop-blur-xs z-30 flex flex-col justify-end pointer-events-auto font-sans",onClick:()=>l(!1),children:e.jsxs("div",{className:"bg-surface/95 backdrop-blur-xl border-t border-theme rounded-t-2xl shadow-2xl p-4 max-h-[70vh] flex flex-col w-full max-w-5xl mx-auto animate-in slide-in-from-bottom duration-200 text-main",onClick:y=>y.stopPropagation(),children:[e.jsxs("div",{className:"flex items-center justify-between pb-3 border-b border-theme shrink-0",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx(Rs,{className:"w-5 h-5 text-primary-theme"}),e.jsx("h3",{className:"font-bold text-main text-sm",children:"白板页面大纲与预览"}),e.jsxs("span",{className:"px-2 py-0.5 bg-primary-theme-light text-primary-theme text-xs rounded-full font-semibold",children:["共 ",t.length," 页"]})]}),e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsxs("button",{onClick:()=>N(),className:"px-3 py-1.5 bg-primary-theme hover:bg-primary-theme-hover text-white rounded-lg text-xs font-semibold flex items-center gap-1.5 transition-colors cursor-pointer shadow-xs",children:[e.jsx(It,{size:14})," 新建页面"]}),e.jsx("button",{onClick:()=>l(!1),className:"p-1.5 hover:bg-surface-secondary rounded-full text-muted hover:text-main transition-colors cursor-pointer",children:e.jsx(Jt,{size:16})})]})]}),e.jsx("div",{className:"grid grid-cols-2 sm:grid-cols-3 md:grid-cols-4 lg:grid-cols-5 gap-3 py-4 overflow-y-auto max-h-[50vh]",children:t.map((y,f)=>{const _=f===r,F=j.filter(L=>L.type!=="page_meta"&&(()=>{try{const ie=JSON.parse(L.data);return(ie.page??0)===f||ie.pageId===y.id}catch{return f===0}})()).length;return e.jsxs("div",{onClick:()=>{P(f),l(!1)},className:`relative flex flex-col p-3 rounded-xl border-2 transition-all cursor-pointer group bg-surface ${_?"border-primary-theme bg-primary-theme-light/30 shadow-md ring-2 ring-[var(--color-primary)]/20":"border-theme hover:border-primary-theme hover:shadow-sm"}`,children:[e.jsxs("div",{className:"flex items-center justify-between mb-2",children:[e.jsxs("span",{className:`text-xs font-extrabold px-2 py-0.5 rounded-md ${_?"bg-primary-theme text-white":"bg-surface-secondary text-muted"}`,children:["P",f+1]}),_&&e.jsx("span",{className:"text-xs font-bold text-primary-theme bg-primary-theme-light px-1.5 py-0.5 rounded",children:"当前激活"})]}),e.jsxs("div",{className:"h-20 bg-surface-secondary border border-theme rounded-lg flex flex-col items-center justify-center mb-2 overflow-hidden relative",children:[e.jsx(Ut,{size:24,className:_?"text-primary-theme":"text-subtle"}),e.jsxs("span",{className:"text-xs text-muted font-medium mt-1",children:[F," 个组件/笔画"]})]}),e.jsx("div",{className:"font-bold text-xs text-main truncate mb-1",title:y.title,children:y.title}),e.jsxs("div",{className:"flex items-center justify-between pt-2 border-t border-theme text-muted text-xs",onClick:L=>L.stopPropagation(),children:[e.jsx("button",{onClick:()=>{u(f),a(y.title)},className:"hover:text-primary-theme p-1 rounded hover:bg-surface-secondary transition-colors",title:"重命名",children:e.jsx(Es,{size:13})}),e.jsx("button",{onClick:()=>k(f),className:"hover:text-primary-theme p-1 rounded hover:bg-surface-secondary transition-colors",title:"复制页面",children:e.jsx(Br,{size:13})}),f>0&&e.jsx("button",{onClick:()=>M(f,"left"),className:"hover:text-primary-theme p-1 rounded hover:bg-surface-secondary transition-colors",title:"向左移",children:e.jsx(Wt,{size:13})}),f<t.length-1&&e.jsx("button",{onClick:()=>M(f,"right"),className:"hover:text-primary-theme p-1 rounded hover:bg-surface-secondary transition-colors",title:"向右移",children:e.jsx(Xt,{size:13})}),e.jsx("button",{onClick:()=>b(f),className:"hover:text-rose-500 p-1 rounded hover:bg-rose-500/10 transition-colors disabled:opacity-30",disabled:t.length<=1,title:"删除页面",children:e.jsx(ct,{size:13})})]})]},y.id||f)})})]})})]}),Na=({dialog:t,dialogInput:r,setDialogInput:x,setDialog:l})=>t?e.jsx("div",{className:"absolute inset-0 bg-neutral-900/40 backdrop-blur-[2px] flex items-center justify-center z-[9999] p-4 font-sans",children:e.jsxs("div",{className:"bg-white rounded-xl shadow-2xl overflow-hidden max-w-sm w-full border border-gray-100 flex flex-col scale-100 pointer-events-auto",children:[e.jsxs("div",{className:"px-5 py-4 border-b border-gray-150/60 bg-gray-50 flex justify-between items-center shrink-0",children:[e.jsx("h3",{className:"font-bold text-gray-800 text-sm",children:t.title}),e.jsx("button",{onClick:()=>l(null),className:"text-gray-400 hover:text-gray-650 transition-colors text-xl font-light cursor-pointer",children:"×"})]}),e.jsxs("div",{className:"p-5 flex-1 min-h-0",children:[e.jsx("p",{className:"text-xs text-gray-600 leading-relaxed whitespace-pre-wrap mb-4 font-medium",children:t.message}),t.type==="prompt"&&e.jsx("textarea",{value:r,onChange:c=>x(c.target.value),placeholder:t.placeholder,className:"w-full h-32 p-3 border border-gray-300 rounded-lg text-xs font-mono focus:outline-none focus:ring-2 focus:ring-indigo-500 bg-gray-50 focus:bg-white transition-all resize-none font-medium",onPointerDown:c=>c.stopPropagation()})]}),e.jsxs("div",{className:"px-5 py-3 border-t border-gray-100 bg-gray-50 flex justify-end gap-2 text-xs shrink-0",children:[t.type!=="alert"&&e.jsx("button",{onClick:()=>l(null),className:"px-4 py-2 text-gray-500 hover:bg-gray-100 rounded-lg transition-colors font-medium border border-gray-200 cursor-pointer",children:"取消"}),e.jsx("button",{onClick:async()=>{try{await t.onConfirm(r)}catch(c){console.error("Dialog action error:",c)}},className:"px-4 py-2 bg-indigo-600 hover:bg-indigo-700 text-white rounded-lg font-semibold transition-all shadow-sm cursor-pointer",children:"确定"})]})]})}):null,$s=[{key:"content",zh:"内容完整",en:"Completeness",weight:30},{key:"technical",zh:"技术实现",en:"Technical",weight:30},{key:"expression",zh:"表达规范",en:"Presentation",weight:20},{key:"innovation",zh:"创新亮点",en:"Originality",weight:20}],Ms=[{key:"low",zh:"未达标",en:"Below",factor:.4},{key:"basic",zh:"基本达标",en:"Basic",factor:.7},{key:"good",zh:"良好",en:"Good",factor:.85},{key:"excellent",zh:"优秀",en:"Excellent",factor:1}];function ka(t){if(!Number.isFinite(t)||t<=0)return"0 B";const r=["B","KB","MB","GB"],x=Math.min(r.length-1,Math.floor(Math.log(t)/Math.log(1024)));return`${(t/1024**x).toFixed(x===0?0:1)} ${r[x]}`}function Ts(t){if(!t)return"—";const r=t<1e12?t*1e3:t;try{return new Date(r).toLocaleString()}catch{return"—"}}function qr(t,r,x){const l=String.fromCharCode(65+t%26);return x?`${r?"匿名同学":"待评同学"} ${l}`:`${r?"Anonymous":"Peer"} ${l}`}function Ca({assignmentId:t,tasks:r,onSubmitted:x,onToast:l,lang:c="zh"}){const u=c==="zh",[d,a]=i.useState(null),[n,g]=i.useState({}),[j,P]=i.useState(""),[X,k]=i.useState(""),[M,b]=i.useState(!1),[N,y]=i.useState(null),[f,_]=i.useState(null),F=Math.max(0,r.findIndex(p=>p.taskId===d)),L=r[F],ie=i.useCallback((p,C,m)=>{if(l){l(p,C,m);return}_(C?`${p}:${C}`:p)},[l]);i.useEffect(()=>{const p=r[F];p&&(P(p.review?String(p.review.score):""),k(p.review?.comment||""),g({}),y(null),_(null))},[F,r]);const U=i.useMemo(()=>{if($s.filter(m=>n[m.key]).length===0)return null;const C=$s.reduce((m,O)=>{const v=Ms.find(w=>w.key===n[O.key]);return m+O.weight*(v?.factor??Ms[1].factor)},0);return Math.round(C)},[n]),xe=j.trim()===""?U:Math.round(Number(j)),ee=L?.dueAt!==null&&L?.dueAt!==void 0&&Date.now()>Number(L.dueAt),J=r.filter(p=>p.review).length,z=(p,C)=>{g(m=>{const O={...m};return O[p]===C?delete O[p]:O[p]=C,O}),P("")},T=i.useCallback(async()=>{if(M||!L||ee)return;const p=xe;if(p===null||!Number.isFinite(p)||p<0||p>100){y(u?"请给出 0-100 的互评分数":"Score must be between 0 and 100");return}if(!L.submissionId){y(u?"该互评任务缺少提交物信息,请刷新后重试":"Missing submission for this task");return}b(!0),y(null);try{const C=await fetch(`/api/assignments/${encodeURIComponent(t)}/peer-review`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({submissionId:L.submissionId,score:p,comment:X.trim(),taskId:L.taskId})}),m=await C.json().catch(()=>null);if(!C.ok||m?.success===!1)throw new Error(m?.error||`HTTP ${C.status}`);ie(L.review?u?"互评已更新":"Review updated":u?"互评已提交":"Review submitted",u?`已给 ${qr(F,L.anonymous,u)} 打 ${p} 分`:"","success"),await x?.()}catch(C){y(C?.message||(u?"提交失败":"submit failed"))}finally{b(!1)}},[F,L,t,X,ee,ie,x,xe,M,u]);if(r.length===0)return e.jsxs("div",{className:"rounded-xl border border-theme bg-surface-secondary p-4 text-xs text-muted inline-flex items-center gap-2",children:[e.jsx(_s,{size:13}),u?"老师还没有给你分配互评任务。":"No peer review task assigned yet."]});const R=L?.submission;return e.jsxs("div",{"data-testid":"peer-review-panel",className:"space-y-3",children:[e.jsxs("div",{className:"flex flex-wrap items-center justify-between gap-2",children:[e.jsxs("div",{className:"text-xs font-semibold text-main inline-flex items-center gap-1.5",children:[e.jsx(_s,{size:13})," ",u?"互评任务":"Peer review",e.jsx("span",{className:"font-normal text-muted",children:u?`已完成 ${J} / ${r.length}`:`${J} / ${r.length} done`})]}),L?.dueAt?e.jsxs("span",{className:`text-[11px] ${ee?"text-red-600":"text-muted"}`,children:[u?"互评截止":"Due"," ",Ts(L.dueAt),ee?u?"(已截止)":" (closed)":""]}):null]}),e.jsxs("div",{className:"grid grid-cols-1 sm:grid-cols-[9rem_1fr] gap-3",children:[e.jsx("div",{className:"space-y-1",children:r.map((p,C)=>{const m=C===F;return e.jsxs("button",{type:"button",onClick:()=>a(p.taskId),className:`w-full flex items-center justify-between gap-1 rounded-lg border px-2 py-1.5 text-left text-xs transition-colors ${m?"border-orange-300 bg-orange-50 text-main":"border-theme bg-surface text-muted hover:bg-surface-secondary"}`,children:[e.jsx("span",{className:"truncate",children:qr(C,p.anonymous,u)}),p.review?e.jsxs("span",{className:"inline-flex items-center gap-1 text-emerald-600 shrink-0",children:[e.jsx(Ot,{size:11})," ",p.review.score]}):e.jsx("span",{className:"text-[11px] text-amber-600 shrink-0",children:u?"待评":"todo"})]},p.taskId)})}),e.jsxs("div",{className:"rounded-xl border border-theme bg-surface p-3 space-y-3",children:[L?.stale&&e.jsxs("div",{className:"flex items-start gap-1.5 rounded-lg border border-amber-200 bg-amber-50 px-2 py-1.5 text-[11px] text-amber-800",children:[e.jsx(dn,{size:12,className:"mt-0.5 shrink-0"}),u?"该作者在你评价后又更新了提交,建议复核后再提交一次。":"The author resubmitted after your review."]}),R?e.jsxs("div",{className:"space-y-2",children:[e.jsxs("div",{className:"flex items-center gap-2 text-[11px] text-muted",children:[e.jsx("span",{className:"px-1.5 py-0.5 rounded bg-surface-secondary border border-theme",children:u?`第 ${R.version} 版`:`v${R.version}`}),e.jsx("span",{children:Ts(R.submittedAt)}),R.isLate&&e.jsx("span",{className:"text-amber-600",children:u?"迟交":"late"})]}),R.textContent?e.jsx("pre",{className:"max-h-48 overflow-y-auto whitespace-pre-wrap break-words rounded-lg border border-theme bg-surface-secondary p-2 text-xs text-main",children:R.textContent}):e.jsx("div",{className:"text-[11px] text-muted",children:u?"该同学没有留下文本作答。":"No text answer."}),R.linkUrl?e.jsxs("a",{href:R.linkUrl,target:"_blank",rel:"noreferrer",className:"inline-flex items-center gap-1 text-xs text-orange-600 hover:underline break-all",children:[e.jsx(zi,{size:11})," ",R.linkUrl]}):null,R.files.length>0&&e.jsx("div",{className:"space-y-1",children:R.files.map(p=>e.jsxs("a",{href:`/api/assignments/${encodeURIComponent(t)}/files/${encodeURIComponent(p.id)}`,target:"_blank",rel:"noreferrer",className:"flex items-center gap-1.5 rounded-lg border border-theme bg-surface-secondary px-2 py-1.5 text-xs text-main hover:border-orange-300",children:[e.jsx(Ut,{size:12,className:"shrink-0"}),e.jsx("span",{className:"truncate",children:p.original_name}),e.jsx("span",{className:"text-[11px] text-muted shrink-0",children:ka(p.size)})]},p.id))})]}):e.jsx("div",{className:"text-[11px] text-muted",children:u?"该同学还没有提交,无法互评。":"This peer has not submitted yet."}),e.jsxs("div",{className:"space-y-1.5",children:[e.jsx("div",{className:"text-[11px] font-semibold text-main",children:u?"评价量规":"Rubric"}),$s.map(p=>e.jsxs("div",{className:"flex flex-wrap items-center gap-1.5",children:[e.jsxs("span",{className:"w-20 shrink-0 text-[11px] text-muted",children:[u?p.zh:p.en,e.jsxs("span",{className:"ml-1 text-[10px]",children:["(",p.weight,")"]})]}),Ms.map(C=>{const m=n[p.key]===C.key;return e.jsx("button",{type:"button",disabled:ee,onClick:()=>z(p.key,C.key),className:`px-1.5 py-0.5 rounded border text-[11px] transition-colors disabled:opacity-50 ${m?"border-orange-300 bg-orange-50 text-main":"border-theme text-muted hover:bg-surface-secondary"}`,children:u?C.zh:C.en},C.key)})]},p.key))]}),e.jsxs("div",{className:"flex flex-wrap items-center gap-2",children:[e.jsxs("label",{className:"text-[11px] text-muted inline-flex items-center gap-1",children:[u?"互评总分":"Score",e.jsx("input",{type:"number",min:0,max:100,value:j,disabled:ee,placeholder:U===null?"":String(U),onChange:p=>{P(p.target.value),g({})},className:"w-20 px-2 py-1 border border-theme rounded-lg text-xs bg-surface text-main focus:outline-none focus:ring-1 focus:ring-orange-400"})]}),U!==null&&j.trim()===""&&e.jsx("span",{className:"text-[11px] text-muted",children:u?`量规建议 ${U} 分`:`Rubric suggests ${U}`})]}),e.jsx("textarea",{value:X,disabled:ee,onChange:p=>k(p.target.value),rows:3,placeholder:u?"写点具体建议:哪里做得好、哪里可以改进…":"Leave specific feedback…",className:"w-full px-2 py-1.5 border border-theme rounded-lg text-xs bg-surface text-main focus:outline-none focus:ring-1 focus:ring-orange-400 resize-y"}),N&&e.jsx("div",{className:"text-[11px] text-red-600 break-all",children:N}),f&&e.jsx("div",{className:"text-[11px] text-emerald-600 break-all",children:f}),e.jsxs("div",{className:"flex items-center justify-between gap-2",children:[e.jsx("span",{className:"text-[11px] text-muted",children:L?.review?u?`已评 ${L.review.score} 分 · ${Ts(L.review.submittedAt)}`:`Reviewed ${L.review.score}`:u?"同学之间双盲互评,作者看不到是谁评的":"Double-blind review"}),e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsxs("button",{type:"button",disabled:M||ee,onClick:()=>{P(L?.review?String(L.review.score):""),k(L?.review?.comment||""),g({}),y(null)},className:"px-2 py-1.5 rounded-lg text-xs border border-theme text-muted hover:bg-surface-secondary inline-flex items-center gap-1 disabled:opacity-50",children:[e.jsx(Ct,{size:11})," ",u?"重填":"Reset"]}),e.jsxs("button",{type:"button",disabled:M||ee,onClick:()=>void T(),className:"px-3 py-1.5 rounded-lg text-xs font-medium bg-orange-500 text-white hover:bg-orange-600 inline-flex items-center gap-1 disabled:opacity-50 disabled:cursor-not-allowed",children:[M?e.jsx(Ke,{size:12,className:"animate-spin"}):null,ee?u?"互评已截止":"Closed":L?.review?u?"更新互评":"Update":u?"提交互评":"Submit"]})]})]})]})]})]})}const Sa=".pdf,.doc,.docx,.ppt,.pptx,.xls,.xlsx,.csv,.txt,.md,.rtf,.odt,.odp,.ods,.png,.jpg,.jpeg,.gif,.webp,.bmp,.svg,.heic,.zip,.py,.js,.mjs,.cjs,.ts,.tsx,.jsx,.java,.c,.h,.cpp,.cs,.go,.rs,.rb,.php,.sql,.json,.xml,.html,.css,.ino",Ds=50*1024*1024;function rs(t){if(!Number.isFinite(t)||t<=0)return"0 B";const r=["B","KB","MB","GB"],x=Math.min(r.length-1,Math.floor(Math.log(t)/Math.log(1024)));return`${(t/1024**x).toFixed(x===0?0:1)} ${r[x]}`}function Yr(t){if(!t)return"—";const r=t<1e12?t*1e3:t;try{return new Date(r).toLocaleString()}catch{return"—"}}function za({assignmentId:t,onClose:r,onToast:x,lang:l="zh"}){const c=l==="zh",[u,d]=i.useState(!0),[a,n]=i.useState(null),[g,j]=i.useState(null),[P,X]=i.useState([]),[k,M]=i.useState([]),[b,N]=i.useState(""),[y,f]=i.useState(""),[_,F]=i.useState(!1),[L,ie]=i.useState(null),[U,xe]=i.useState(null),[ee,J]=i.useState(!1),[z,T]=i.useState("submit"),[R,p]=i.useState(null),C=i.useRef(new Map),m=i.useRef(new Map),O=i.useRef(null),v=i.useCallback((E,se,pe)=>{if(x){x(E,se,pe);return}p({text:se?`${E}:${se}`:E,type:pe==="error"?"warning":pe})},[x]),w=i.useCallback((E,se)=>{M(pe=>pe.map(G=>G.key===E?{...G,...se}:G))},[]),q=i.useCallback(async(E=!1)=>{E||d(!0),n(null);try{const[se,pe]=await Promise.all([fetch(`/api/assignments/${encodeURIComponent(t)}`),fetch(`/api/assignments/${encodeURIComponent(t)}/files`)]),G=await se.json().catch(()=>null);if(!se.ok||G?.success===!1)throw new Error(G?.error||`HTTP ${se.status}`);j(G);const ue=await pe.json().catch(()=>null),ht=Array.isArray(ue?.files)?ue.files:[];X(ht.filter(St=>!St.version_id))}catch(se){n(se?.message||"load failed")}finally{E||d(!1)}},[t]);i.useEffect(()=>{q()},[q]),i.useEffect(()=>{const E=m.current;return()=>{E.forEach(se=>{try{se.abort()}catch{}}),E.clear()}},[]);const I=i.useCallback(E=>new Promise(se=>{const pe=C.current.get(E);if(!pe){w(E,{status:"error",error:c?"文件已失效,请重新选择":"file expired"}),se();return}const G=new XMLHttpRequest;m.current.set(E,G),G.open("POST",`/api/assignments/${encodeURIComponent(t)}/files`,!0),G.setRequestHeader("X-File-Name",encodeURIComponent(pe.name)),G.setRequestHeader("Content-Type","application/octet-stream"),G.upload.onprogress=ue=>{ue.lengthComputable&&w(E,{progress:Math.round(ue.loaded/ue.total*100)})},G.onload=()=>{m.current.delete(E);let ue=null;try{ue=JSON.parse(G.responseText||"{}")}catch{ue=null}G.status>=200&&G.status<300&&ue?.success!==!1&&ue?.file?.id?(w(E,{status:"done",progress:100,fileId:ue.file.id}),X(ht=>[{id:ue.file.id,original_name:ue.file.name??pe.name,size:ue.file.size??pe.size,uploaded_at:Date.now()},...ht])):w(E,{status:"error",error:ue?.error||`HTTP ${G.status}`}),se()},G.onerror=()=>{m.current.delete(E),w(E,{status:"error",error:c?"网络错误":"network error"}),se()},G.onabort=()=>{m.current.delete(E),se()},w(E,{status:"uploading",progress:0,error:void 0}),G.send(pe)}),[t,w,c]),D=i.useCallback(E=>{if(!E.length)return;const se=Date.now(),pe=[],G=[];E.forEach((ue,ht)=>{if(ue.size<=0){G.push(`${ue.name}(${c?"空文件":"empty"})`);return}if(ue.size>Ds){G.push(`${ue.name}(${c?"超过":"over"} ${rs(Ds)})`);return}const St=`${se}-${ht}-${ue.name}`;C.current.set(St,ue),pe.push({key:St,name:ue.name,size:ue.size,status:"queued",progress:0})}),G.length&&v(c?"部分文件未加入":"Some files skipped",G.join("、"),"warning"),pe.length&&(M(ue=>[...ue,...pe]),(async()=>{for(const ue of pe)await I(ue.key)})())},[v,I,c]),ne=i.useCallback(E=>{I(E)},[I]),ce=i.useCallback(E=>{try{m.current.get(E)?.abort()}catch{}C.current.delete(E),M(se=>se.filter(pe=>pe.key!==E))},[]),re=i.useCallback(async E=>{try{const se=await fetch(`/api/assignments/${encodeURIComponent(t)}/files/${E}`,{method:"DELETE"}),pe=await se.json().catch(()=>null);if(!se.ok||pe?.success===!1){v(c?"删除失败":"Delete failed",pe?.error||`HTTP ${se.status}`,"error");return}X(G=>G.filter(ue=>ue.id!==E))}catch(se){v(c?"删除失败":"Delete failed",se?.message||"","error")}},[t,v,c]),te=i.useMemo(()=>{const E=P.map(G=>G.id),se=new Set(E),pe=[];for(const G of k)G.status!=="done"||!G.fileId||se.has(G.fileId)||(se.add(G.fileId),pe.push(G.fileId));return[...E,...pe]},[P,k]),B=k.some(E=>E.status==="uploading"),K=te.length>0||b.trim().length>0||y.trim().length>0,ye=i.useCallback(async()=>{if(!(_||B)){F(!0),ie(null);try{const E=await fetch(`/api/assignments/${encodeURIComponent(t)}/submit`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({fileIds:te,textContent:b.trim()||void 0,linkUrl:y.trim()||void 0})}),se=await E.json().catch(()=>null);if(!E.ok||se?.success===!1)throw new Error(se?.error||`HTTP ${E.status}`);xe(Number(se?.version)||1),M([]),C.current.clear(),N(""),v(c?"提交成功":"Submitted",c?`已生成第 ${se?.version??1} 版提交`:"","success"),await q(!0)}catch(E){ie(E?.message||"submit failed")}finally{F(!1)}}},[t,te,q,v,_,b,B,c]),Y=g?.assignment,le=Array.isArray(g?.versions)?g.versions:[],be=g?.grade,je=g?.stats,Me=Array.isArray(g?.peerReviewTasks)?g.peerReviewTasks:[],Ie=Me.filter(E=>!E.review||E.stale).length;return e.jsx("div",{className:"fixed inset-0 z-[120] flex items-center justify-center bg-black/40 p-4",onClick:r,children:e.jsxs("div",{className:"w-full max-w-2xl max-h-[88vh] flex flex-col rounded-2xl bg-surface border border-theme shadow-2xl overflow-hidden",onClick:E=>E.stopPropagation(),children:[e.jsxs("div",{className:"flex items-start justify-between gap-3 px-4 py-3 border-b border-theme",children:[e.jsxs("div",{className:"min-w-0",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx($i,{size:14,className:"text-orange-600 shrink-0"}),e.jsx("h3",{className:"font-bold text-main text-sm truncate",children:Y?.title||(c?"课堂作业":"Assignment")})]}),Y&&e.jsxs("div",{className:"flex flex-wrap items-center gap-2 mt-1 text-[11px] text-muted",children:[e.jsx("span",{className:"px-1.5 py-0.5 rounded-full bg-surface-secondary border border-theme",children:Y.status==="published"?c?"已发布":"published":Y.status}),Y.due_at?e.jsxs("span",{className:"inline-flex items-center gap-1",children:[e.jsx(Mi,{size:10})," ",c?"截止":"Due"," ",Yr(Y.due_at)]}):null,Y.allow_late?e.jsx("span",{children:c?"允许迟交":"late allowed"}):null,je?e.jsx("span",{children:c?`已提交 ${je.submissionCount}`:`${je.submissionCount} submitted`}):null]})]}),e.jsxs("div",{className:"flex items-center gap-1 shrink-0",children:[e.jsx("button",{onClick:()=>void q(!0),className:"p-1.5 rounded-lg text-muted hover:text-main hover:bg-surface-secondary transition-colors",title:c?"刷新":"Refresh",children:e.jsx(Ct,{size:13})}),e.jsx("button",{onClick:r,className:"p-1.5 rounded-lg text-muted hover:text-main hover:bg-surface-secondary transition-colors",title:c?"关闭":"Close",children:e.jsx(Jt,{size:14})})]})]}),e.jsxs("div",{className:"flex items-center gap-1 px-4 pt-2 border-b border-theme",children:[e.jsx("button",{type:"button",onClick:()=>T("submit"),className:`px-2.5 py-1.5 text-xs rounded-t-lg border-b-2 transition-colors ${z==="submit"?"border-orange-500 text-main font-medium":"border-transparent text-muted hover:text-main"}`,children:c?"我的提交":"My submission"}),Me.length>0&&e.jsxs("button",{type:"button",onClick:()=>T("peer"),className:`px-2.5 py-1.5 text-xs rounded-t-lg border-b-2 transition-colors inline-flex items-center gap-1.5 ${z==="peer"?"border-orange-500 text-main font-medium":"border-transparent text-muted hover:text-main"}`,children:[c?"互评任务":"Peer review",e.jsx("span",{className:"text-[11px]",children:Ie>0?`${Me.length-Ie}/${Me.length}`:Me.length}),Ie>0&&e.jsx("span",{className:"px-1 rounded-full bg-amber-100 text-amber-700 text-[10px]",children:c?`待评 ${Ie}`:`${Ie} todo`})]})]}),e.jsx("div",{className:"flex-1 overflow-y-auto px-4 py-3 space-y-4",children:u?e.jsxs("div",{className:"flex items-center justify-center gap-2 py-10 text-muted text-xs",children:[e.jsx(Ke,{size:14,className:"animate-spin"})," ",c?"加载中…":"Loading…"]}):a?e.jsxs("div",{className:"flex items-start gap-2 rounded-xl border border-red-200 bg-red-50 px-3 py-2 text-xs text-red-700",children:[e.jsx(qt,{size:14,className:"mt-0.5 shrink-0"}),e.jsxs("div",{children:[e.jsx("div",{className:"font-semibold",children:c?"无法加载作业":"Failed to load assignment"}),e.jsx("div",{className:"mt-0.5 break-all",children:a})]})]}):z==="peer"?e.jsx(Ca,{assignmentId:t,tasks:Me,onSubmitted:()=>q(!0),onToast:x,lang:l}):e.jsxs(e.Fragment,{children:[Y?.description?e.jsx("div",{className:"rounded-xl border border-theme bg-surface-secondary px-3 py-2 text-xs text-main whitespace-pre-wrap leading-relaxed",children:Y.description}):null,be?e.jsxs("div",{className:"rounded-xl border border-theme px-3 py-2 text-xs flex items-center gap-2",children:[e.jsx(Ti,{size:14,className:"text-amber-500 shrink-0"}),be.status==="confirmed"?e.jsxs("span",{className:"text-main",children:[c?"最终成绩":"Final score",":",e.jsx("span",{className:"font-bold text-amber-600 ml-1",children:be.calculated_final_score})]}):e.jsx("span",{className:"text-muted",children:c?"成绩待教师确认":"Grade pending confirmation"})]}):null,e.jsxs("div",{children:[e.jsxs("div",{className:"flex items-center justify-between mb-1.5",children:[e.jsx("span",{className:"text-xs font-semibold text-main",children:c?"作业文件":"Files"}),e.jsxs("span",{className:"text-[11px] text-muted",children:[c?"单个不超过":"max"," ",rs(Ds)]})]}),e.jsxs("div",{onDragOver:E=>{E.preventDefault(),J(!0)},onDragLeave:()=>J(!1),onDrop:E=>{E.preventDefault(),J(!1);const se=Array.from(E.dataTransfer?.files||[]);se.length&&D(se)},onClick:()=>O.current?.click(),className:`rounded-xl border-2 border-dashed px-3 py-4 text-center cursor-pointer transition-colors ${ee?"border-orange-400 bg-orange-50":"border-theme hover:border-orange-300"}`,children:[e.jsx(as,{size:16,className:"mx-auto text-muted"}),e.jsx("div",{className:"mt-1 text-xs text-main font-medium",children:c?"点击选择文件,或拖拽到此处":"Click to choose files, or drop them here"}),e.jsx("div",{className:"text-[11px] text-muted mt-0.5",children:c?"支持文档、图片、压缩包与常见代码文件":"documents, images, archives, source files"}),e.jsx("input",{ref:O,type:"file",multiple:!0,accept:Sa,className:"hidden",onChange:E=>{const se=Array.from(E.target.files||[]);se.length&&D(se),E.target.value=""}})]}),P.length>0&&e.jsx("ul",{className:"mt-2 space-y-1",children:P.map(E=>e.jsxs("li",{className:"flex items-center gap-2 rounded-lg border border-theme px-2 py-1.5 text-xs",children:[e.jsx(Ut,{size:12,className:"text-muted shrink-0"}),e.jsx("span",{className:"flex-1 truncate text-main",children:E.original_name}),e.jsx("span",{className:"text-[11px] text-muted shrink-0",children:rs(E.size)}),e.jsx("button",{onClick:()=>void re(E.id),className:"p-1 rounded text-orange-600 hover:text-red-500 hover:bg-surface-secondary",title:c?"移除":"Remove",children:e.jsx(ct,{size:12})})]},E.id))}),k.length>0&&e.jsx("ul",{className:"mt-2 space-y-1",children:k.map(E=>e.jsxs("li",{className:"rounded-lg border border-theme px-2 py-1.5 text-xs",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[E.status==="done"?e.jsx(Ot,{size:12,className:"text-emerald-600 shrink-0"}):E.status==="error"?e.jsx(qt,{size:12,className:"text-red-500 shrink-0"}):e.jsx(Ke,{size:12,className:"animate-spin text-muted shrink-0"}),e.jsx("span",{className:"flex-1 truncate text-main",children:E.name}),e.jsx("span",{className:"text-[11px] text-muted shrink-0",children:rs(E.size)}),E.status==="error"&&e.jsx("button",{onClick:()=>ne(E.key),className:"p-1 rounded text-primary-theme hover:bg-surface-secondary",title:c?"重试":"Retry",children:e.jsx(Ct,{size:12})}),e.jsx("button",{onClick:()=>ce(E.key),className:"p-1 rounded text-muted hover:text-main hover:bg-surface-secondary",title:c?"从列表移除":"Remove from list",children:e.jsx(Jt,{size:12})})]}),E.status==="uploading"&&e.jsx("div",{className:"mt-1 h-1 rounded-full bg-surface-secondary overflow-hidden",children:e.jsx("div",{className:"h-full bg-orange-500 transition-all",style:{width:`${E.progress}%`}})}),E.status==="error"&&E.error?e.jsx("div",{className:"mt-0.5 text-[11px] text-red-600 break-all",children:E.error}):null]},E.key))})]}),e.jsxs("div",{className:"space-y-2",children:[e.jsxs("div",{children:[e.jsx("label",{className:"block text-xs font-semibold text-main mb-1",children:c?"文字作答(可选)":"Text answer (optional)"}),e.jsx("textarea",{value:b,onChange:E=>N(E.target.value),className:"w-full h-20 p-2 border border-theme rounded-lg text-xs bg-surface text-main resize-none focus:outline-none focus:ring-1 focus:ring-orange-400",placeholder:c?"可直接粘贴代码或说明…":"Paste code or notes…"})]}),e.jsxs("div",{children:[e.jsx("label",{className:"block text-xs font-semibold text-main mb-1",children:e.jsxs("span",{className:"inline-flex items-center gap-1",children:[e.jsx(un,{size:11})," ",c?"作品链接(可选)":"Link (optional)"]})}),e.jsx("input",{type:"url",value:y,onChange:E=>f(E.target.value),className:"w-full px-2 py-1.5 border border-theme rounded-lg text-xs bg-surface text-main focus:outline-none focus:ring-1 focus:ring-orange-400",placeholder:"https://"})]})]}),le.length>0&&e.jsxs("div",{children:[e.jsx("div",{className:"text-xs font-semibold text-main mb-1.5",children:c?`提交历史(共 ${le.length} 版)`:`Submission history (${le.length})`}),e.jsx("ul",{className:"space-y-1",children:le.map(E=>e.jsxs("li",{className:"flex items-center gap-2 rounded-lg border border-theme px-2 py-1.5 text-xs",children:[e.jsxs("span",{className:"px-1.5 py-0.5 rounded bg-surface-secondary border border-theme text-[11px] text-main shrink-0",children:["v",E.version]}),e.jsx("span",{className:"flex-1 truncate text-muted",children:E.text_content||E.link_url||"—"}),e.jsx("span",{className:"text-[11px] text-muted shrink-0",children:Yr(E.created_at||E.submitted_at)})]},E.id))})]}),U!==null&&e.jsxs("div",{className:"flex items-center gap-2 rounded-xl border border-emerald-200 bg-emerald-50 px-3 py-2 text-xs text-emerald-700",children:[e.jsx(Ot,{size:14,className:"shrink-0"}),c?`已提交第 ${U} 版`:`Version ${U} submitted`]}),L&&e.jsxs("div",{className:"flex items-start gap-2 rounded-xl border border-red-200 bg-red-50 px-3 py-2 text-xs text-red-700",children:[e.jsx(qt,{size:14,className:"mt-0.5 shrink-0"}),e.jsx("span",{className:"break-all",children:L})]})]})}),e.jsxs("div",{className:"flex items-center justify-between gap-2 px-4 py-3 border-t border-theme",children:[e.jsx("span",{className:"text-[11px] text-muted",children:R?e.jsx("span",{className:R.type==="warning"?"text-amber-700":"text-emerald-700",children:R.text}):c?`本次将提交 ${te.length} 个附件${b.trim()?" + 文本":""}${y.trim()?" + 链接":""}`:`${te.length} file(s)`}),e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("button",{onClick:r,className:"px-3 py-1.5 rounded-lg text-xs border border-theme text-main hover:bg-surface-secondary transition-colors",children:c?"关闭":"Close"}),e.jsxs("button",{onClick:()=>void ye(),disabled:_||B||!K,className:"px-3 py-1.5 rounded-lg text-xs font-medium bg-orange-600 hover:bg-orange-700 disabled:opacity-50 disabled:cursor-not-allowed text-white transition-colors inline-flex items-center gap-1.5",children:[_?e.jsx(Ke,{size:12,className:"animate-spin"}):e.jsx(as,{size:12}),_?c?"提交中…":"Submitting…":c?"提交作业":"Submit"]})]})]})]})})}function $a(t){if(!t)return"";const r=t<1e12?t*1e3:t;try{return new Date(r).toLocaleString()}catch{return""}}function Ma({lessonId:t,classId:r,elementId:x,value:l,draftTitle:c,draftDescription:u,disabled:d,onChange:a,onToast:n,lang:g="zh"}){const j=g==="zh",[P,X]=i.useState(!1),[k,M]=i.useState([]),[b,N]=i.useState(null),[y,f]=i.useState(null),[_,F]=i.useState(!1),[L,ie]=i.useState(null),U=i.useCallback((R,p,C)=>{if(n){n(R,p,C);return}ie({text:p?`${R}:${p}`:R,type:C})},[n]),xe=i.useCallback(async(R=!1)=>{if(t){R||X(!0),f(null);try{const p=await fetch(`/api/assignments?lessonId=${encodeURIComponent(t)}`),C=await p.json().catch(()=>null);if(!p.ok||C?.success===!1)throw new Error(C?.error||`HTTP ${p.status}`);M(Array.isArray(C?.assignments)?C.assignments:[])}catch(p){f(p?.message||"load failed")}finally{R||X(!1)}}},[t]),ee=i.useCallback(async()=>{if(!l){N(null);return}try{const R=await fetch(`/api/assignments/${encodeURIComponent(l)}`),p=await R.json().catch(()=>null);R.ok&&p?.success!==!1&&N(p.assignment||null)}catch{}},[l]);i.useEffect(()=>{xe()},[xe]),i.useEffect(()=>{ee()},[ee]);const J=i.useCallback(async()=>{if(!(_||!t)){F(!0);try{const R=await fetch("/api/assignments",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({title:c?.trim()||(j?"课堂作业":"Class assignment"),description:u?.trim()||"",lessonId:t,classId:r||void 0,elementId:x||void 0,status:"published"})}),p=await R.json().catch(()=>null);if(!R.ok||p?.success===!1)throw new Error(p?.error||`HTTP ${R.status}`);const C=p?.assignment||p?.result?.assignment,m=C?.id||p?.assignmentId||p?.result?.assignmentId||p?.id;if(!m)throw new Error(j?"服务端未返回作业 ID":"no assignment id returned");N(C||{id:m,title:c,status:"published"}),await xe(!0),a(String(m),C),U(j?"已创建并绑定作业":"Assignment created",j?"学生端可以开始提交了":"","success")}catch(R){U(j?"创建作业失败":"Create failed",R?.message||"","error")}finally{F(!1)}}},[r,_,u,c,x,t,xe,U,a,j]),z=i.useCallback(R=>{if(!R){a(null),N(null);return}const p=k.find(C=>String(C.id)===R);N(p||null),a(R,p)},[a,k]),T=b?.title||k.find(R=>String(R.id)===l)?.title;return e.jsxs("div",{className:"space-y-2 rounded-xl border border-theme bg-surface-secondary p-2.5",children:[e.jsxs("div",{className:"flex items-center justify-between gap-2",children:[e.jsxs("span",{className:"text-xs font-semibold text-main inline-flex items-center gap-1",children:[e.jsx(un,{size:11})," ",j?"绑定作业中心":"Assignment binding"]}),e.jsx("button",{type:"button",onClick:()=>void xe(!0),disabled:P,className:"p-1 rounded text-muted hover:text-main hover:bg-surface transition-colors",title:j?"刷新":"Refresh",children:P?e.jsx(Ke,{size:11,className:"animate-spin"}):e.jsx(Ct,{size:11})})]}),l&&T?e.jsxs("div",{className:"flex items-start gap-2 rounded-lg border border-emerald-200 bg-emerald-50 px-2 py-1.5",children:[e.jsx(Ot,{size:12,className:"mt-0.5 text-emerald-600 shrink-0"}),e.jsxs("div",{className:"min-w-0 flex-1",children:[e.jsx("div",{className:"text-xs font-medium text-main truncate",children:T}),e.jsx("div",{className:"text-[11px] text-muted truncate",children:[b?.status,b?.due_at?`${j?"截止":"due"} ${$a(b.due_at)}`:""].filter(Boolean).join(" · ")})]}),e.jsx("button",{type:"button",disabled:d,onClick:()=>z(""),className:"p-1 rounded text-muted hover:text-red-500 hover:bg-surface transition-colors shrink-0",title:j?"解除绑定":"Unbind",children:e.jsx(Di,{size:11})})]}):e.jsxs("div",{className:"flex items-start gap-2 rounded-lg border border-amber-200 bg-amber-50 px-2 py-1.5",children:[e.jsx(qt,{size:12,className:"mt-0.5 text-amber-600 shrink-0"}),e.jsx("span",{className:"text-[11px] text-amber-800",children:j?"尚未绑定作业:学生端只能看到提示、无法提交。请选择已有作业或直接新建。":"Not bound yet — students cannot submit."})]}),e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsxs("select",{value:l||"",disabled:d,onChange:R=>z(R.target.value),className:"flex-1 min-w-0 px-2 py-1.5 border border-theme rounded-lg text-xs bg-surface text-main focus:outline-none focus:ring-1 focus:ring-orange-400",children:[e.jsx("option",{value:"",children:j?"— 选择本课时的作业 —":"— select assignment —"}),k.map(R=>e.jsxs("option",{value:R.id,children:[R.title||R.id,R.status?` (${R.status})`:""]},R.id))]}),e.jsxs("button",{type:"button",disabled:d||_||!t,onClick:()=>void J(),className:"px-2 py-1.5 rounded-lg text-xs font-medium border border-theme text-main hover:bg-surface transition-colors inline-flex items-center gap-1 disabled:opacity-50 disabled:cursor-not-allowed shrink-0",children:[_?e.jsx(Ke,{size:11,className:"animate-spin"}):e.jsx(It,{size:11}),j?"新建":"New"]})]}),y&&e.jsx("div",{className:"text-[11px] text-red-600 break-all",children:y}),L&&e.jsx("div",{className:`text-[11px] break-all ${L.type==="success"?"text-emerald-600":L.type==="error"?"text-red-600":"text-amber-700"}`,children:L.text}),k.length===0&&!P&&!y&&e.jsx("div",{className:"text-[11px] text-muted",children:j?"本课时还没有作业,点「新建」即可。":"No assignment yet."})]})}const Ir={peer_review_pending:{zh:"未完成互评",en:"Pending"},all_full_marks:{zh:"全部满分",en:"All full marks"},score_gap:{zh:"分数差异大",en:"Score gap"}};function Ta(){const t=new Date(Date.now()+2592e5),r=x=>String(x).padStart(2,"0");return`${t.getFullYear()}-${r(t.getMonth()+1)}-${r(t.getDate())}T${r(t.getHours())}:${r(t.getMinutes())}`}function Da({assignmentId:t,progress:r,onAssigned:x,onToast:l,lang:c="zh"}){const u=c==="zh",[d,a]=i.useState(!1),[n,g]=i.useState(r||null),[j,P]=i.useState(!1),[X,k]=i.useState(!1),[M,b]=i.useState("2"),[N,y]=i.useState(""),[f,_]=i.useState(null),[F,L]=i.useState(null),ie=i.useCallback((z,T,R)=>{if(l){l(z,T,R);return}L(T?`${z}:${T}`:z)},[l]),U=i.useCallback(async()=>{if(r){g(r);return}P(!0),_(null);try{const z=await fetch(`/api/assignments/${encodeURIComponent(t)}`),T=await z.json().catch(()=>null);if(!z.ok||T?.success===!1)throw new Error(T?.error||`HTTP ${z.status}`);g(T?.peerProgress||null)}catch(z){_(z?.message||"load failed")}finally{P(!1)}},[t,r]);i.useEffect(()=>{U()},[U]);const xe=i.useCallback(async()=>{if(!X){k(!0),_(null);try{const z=Math.max(1,Math.min(10,Math.round(Number(M)||2))),T=N?new Date(N).getTime():void 0,R=await fetch(`/api/assignments/${encodeURIComponent(t)}/assign-peer-reviews`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({reviewerCount:z,dueAt:T&&Number.isFinite(T)?T:void 0})}),p=await R.json().catch(()=>null);if(!R.ok||p?.success===!1)throw new Error(p?.error||`HTTP ${R.status}`);ie(u?"互评已分配":"Peer reviews assigned",u?`新增 ${p?.created??0} 个互评任务,覆盖 ${p?.submissions??0} 份提交(重复分配不会重复建任务)`:"","success"),a(!0),await U(),await x?.()}catch(z){ie(u?"分配互评失败":"Assign failed",z?.message||"","error")}finally{k(!1)}}},[t,X,N,U,ie,x,M,u]),ee=(n?.reviewers||[]).filter(z=>z.pending>0),J=n?.flags?.length||0;return e.jsxs("div",{className:"space-y-2 rounded-xl border border-theme bg-surface-secondary p-2.5",children:[e.jsxs("div",{className:"flex items-center justify-between gap-2",children:[e.jsxs("span",{className:"text-xs font-semibold text-main inline-flex items-center gap-1",children:[e.jsx(_s,{size:11})," ",u?"互评进度":"Peer review",n?e.jsx("span",{className:"font-normal text-muted",children:u?`${n.completed} / ${n.tasks} 已完成`:`${n.completed} / ${n.tasks} done`}):null,J>0?e.jsx("span",{className:"px-1 rounded-full bg-amber-100 text-amber-700 text-[10px]",children:u?`${J} 项待复核`:`${J} flags`}):null]}),e.jsxs("div",{className:"flex items-center gap-1 shrink-0",children:[e.jsx("button",{type:"button",onClick:()=>void U(),disabled:j,className:"p-1 rounded text-muted hover:text-main hover:bg-surface transition-colors",title:u?"刷新":"Refresh",children:j?e.jsx(Ke,{size:11,className:"animate-spin"}):e.jsx(Ct,{size:11})}),e.jsx("button",{type:"button",onClick:()=>a(z=>!z),className:"px-1.5 py-0.5 rounded text-[11px] text-muted hover:text-main hover:bg-surface transition-colors",children:d?u?"收起":"Hide":u?"展开":"Show"})]})]}),n?e.jsxs("div",{className:"flex flex-wrap items-center gap-1.5 text-[11px] text-muted",children:[e.jsx("span",{className:"px-1.5 py-0.5 rounded bg-surface border border-theme",children:u?`提交 ${n.submissions}`:`${n.submissions} subs`}),e.jsx("span",{className:"px-1.5 py-0.5 rounded bg-surface border border-theme",children:u?`任务 ${n.tasks}`:`${n.tasks} tasks`}),e.jsx("span",{className:"px-1.5 py-0.5 rounded bg-surface border border-theme",children:u?`待完成 ${n.pending}`:`${n.pending} pending`})]}):e.jsx("div",{className:"text-[11px] text-muted",children:u?"暂无互评数据。":"No peer review data."}),n&&n.tasks===0&&e.jsx("div",{className:"text-[11px] text-muted",children:u?"还没有分配互评:点「随机分配互评」,系统会给每份提交随机分配若干同学(双盲、不评自己、负载均衡)。":"No peer reviews assigned yet."}),e.jsxs("div",{className:"flex flex-wrap items-center gap-2",children:[e.jsxs("label",{className:"text-[11px] text-muted inline-flex items-center gap-1",children:[u?"每份提交分配":"Reviewers",e.jsx("input",{type:"number",min:1,max:10,value:M,onChange:z=>b(z.target.value),className:"w-14 px-2 py-1 border border-theme rounded-lg text-xs bg-surface text-main focus:outline-none focus:ring-1 focus:ring-orange-400"}),u?"人":""]}),e.jsxs("label",{className:"text-[11px] text-muted inline-flex items-center gap-1",children:[u?"互评截止":"Due",e.jsx("input",{type:"datetime-local",value:N,placeholder:Ta(),onChange:z=>y(z.target.value),className:"px-2 py-1 border border-theme rounded-lg text-xs bg-surface text-main focus:outline-none focus:ring-1 focus:ring-orange-400"})]}),e.jsxs("button",{type:"button",disabled:X,onClick:()=>void xe(),className:"px-2 py-1.5 rounded-lg text-xs font-medium border border-theme text-main hover:bg-surface transition-colors inline-flex items-center gap-1 disabled:opacity-50 disabled:cursor-not-allowed",children:[X?e.jsx(Ke,{size:11,className:"animate-spin"}):e.jsx(Ps,{size:11}),u?"随机分配互评":"Assign"]})]}),f&&e.jsx("div",{className:"text-[11px] text-red-600 break-all",children:f}),F&&e.jsx("div",{className:"text-[11px] text-emerald-600 break-all",children:F}),d&&n&&e.jsxs("div",{className:"space-y-2",children:[n.flags.length>0?e.jsx("div",{className:"space-y-1",children:n.flags.map((z,T)=>e.jsxs("div",{className:"flex items-start gap-1.5 rounded-lg border border-amber-200 bg-amber-50 px-2 py-1 text-[11px] text-amber-800",children:[e.jsx(dn,{size:11,className:"mt-0.5 shrink-0"}),e.jsxs("span",{className:"break-all",children:[e.jsx("span",{className:"font-medium",children:u?Ir[z.type]?.zh||z.type:Ir[z.type]?.en||z.type}),":",z.detail]})]},`${z.type}-${z.reviewerId||T}-${T}`))}):e.jsxs("div",{className:"text-[11px] text-emerald-600 inline-flex items-center gap-1",children:[e.jsx(Ot,{size:11})," ",u?"暂未发现异常,互评进度正常。":"No anomaly detected."]}),n.reviewers.length>0&&e.jsxs("div",{className:"space-y-1",children:[e.jsx("div",{className:"text-[11px] font-medium text-main",children:u?`互评人(${ee.length} 人还有待评)`:"Reviewers"}),e.jsx("div",{className:"max-h-40 overflow-y-auto space-y-0.5",children:n.reviewers.map(z=>e.jsxs("div",{className:"flex items-center justify-between gap-2 rounded border border-theme bg-surface px-2 py-1 text-[11px]",children:[e.jsx("span",{className:"truncate text-main",children:z.name}),e.jsx("span",{className:z.pending>0?"text-amber-700 shrink-0":"text-emerald-600 shrink-0",children:u?`已评 ${z.submitted} · 待评 ${z.pending}`:`${z.submitted} done · ${z.pending} todo`})]},z.studentId))})]})]})]})}const Pa=({isEditMode:t,selectedShapeId:r,setSelectedShapeId:x,activePropertiesElementId:l,setActivePropertiesElementId:c,safeElements:u,editingProperties:d,handleLocalPropChange:a,handlePropBlur:n,handleNumericPropBlur:g,handlePropsUpdate:j,handleUpdateElementData:P,handleElementDelete:X,handleUndoProp:k,handleRedoProp:M,propertyUndoStack:b,propertyRedoStack:N,isSyncing:y,lessonId:f,classId:_,fullscreenBroadcastClassId:F,coursewares:L,fetchCoursewares:ie,setZipCandidates:U,setZipUploadInfo:xe,setShowEntrySelector:ee,handleAddOption:J,handleRemoveOption:z,handleOptionChangeLocal:T,handleOptionBlur:R})=>{if(!t||!r||!d)return null;const p=u.find(m=>m.id===r);return!p||(["plugin","hello-world","rollcall","quiz","assignment","html-applet","code-sandbox","math-graph","presentation"].includes(p.type)||ns.has(p.type))&&l!==r?null:e.jsxs("div",{className:"w-80 h-full max-h-full bg-surface border-l border-theme flex flex-col font-sans text-xs select-none shadow-xl shrink-0 z-20 animate-in slide-in-from-right duration-200 text-main",onPointerDown:m=>m.stopPropagation(),children:[e.jsxs("div",{className:"px-4 py-3 border-b border-theme bg-surface-secondary flex justify-between items-center shrink-0",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx(Pi,{size:15,className:"text-muted animate-spin",style:{animationDuration:"6s"}}),e.jsx("span",{className:"font-bold text-main text-sm",children:"属性编辑器"})]}),e.jsxs("div",{className:"flex items-center gap-1.5 font-sans",children:[e.jsxs("button",{onClick:k,disabled:(b[r]||[]).length===0,className:`p-1 rounded-lg transition-all flex items-center justify-center gap-1 border border-transparent select-none cursor-pointer ${(b[r]||[]).length===0?"text-subtle bg-transparent border-transparent opacity-40 cursor-not-allowed":"text-main bg-surface hover:bg-surface-secondary hover:border-theme active:bg-surface-secondary"}`,title:"撤销属性修改",children:[e.jsx(Ei,{size:13}),(b[r]||[]).length>0&&e.jsx("span",{className:"text-xs font-bold text-muted",children:(b[r]||[]).length})]}),e.jsxs("button",{onClick:M,disabled:(N[r]||[]).length===0,className:`p-1 rounded-lg transition-all flex items-center justify-center gap-1 border border-transparent select-none cursor-pointer ${(N[r]||[]).length===0?"text-subtle bg-transparent border-transparent opacity-40 cursor-not-allowed":"text-main bg-surface hover:bg-surface-secondary hover:border-theme active:bg-surface-secondary"}`,title:"重做属性修改",children:[e.jsx(Ri,{size:13}),(N[r]||[]).length>0&&e.jsx("span",{className:"text-xs font-bold text-muted",children:(N[r]||[]).length})]}),e.jsx("div",{className:"h-4 w-px bg-border-theme mx-0.5 shrink-0"}),e.jsx("button",{onClick:()=>{c(null),x(null)},className:"text-muted hover:text-main hover:bg-surface-secondary p-1 rounded-full transition-all cursor-pointer",title:"关闭属性编辑器",children:e.jsx(Jt,{size:15})})]})]}),e.jsxs("div",{className:"flex-1 overflow-y-auto p-4 space-y-4",children:[e.jsxs("div",{className:"bg-surface p-3 rounded-xl border border-theme shadow-sm space-y-2",children:[e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsx("span",{className:"text-muted text-xs font-bold uppercase tracking-wider",children:"组件类型"}),e.jsx("span",{className:"px-2 py-0.5 bg-primary-theme-light text-primary-theme rounded text-xs font-bold uppercase tracking-wider",children:p.type})]}),e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsx("span",{className:"text-muted text-xs font-bold uppercase tracking-wider",children:"组件标识"}),e.jsx("span",{className:"font-mono text-muted text-xs truncate max-w-[155px]",title:p.id,children:p.id})]})]}),e.jsxs("div",{className:"bg-surface p-3 rounded-xl border border-theme shadow-sm space-y-3",children:[e.jsx("h4",{className:"font-bold text-main text-xs border-b border-theme pb-1.5 flex items-center gap-1.5",children:"物理定位 & 尺寸"}),e.jsxs("div",{className:"grid grid-cols-2 gap-2",children:[e.jsxs("div",{children:[e.jsx("label",{className:"block text-xs text-muted font-semibold mb-1",children:"X 坐标"}),e.jsx("input",{type:"number",value:Math.round(d.x??0),onChange:m=>a("x",parseFloat(m.target.value)||0),onBlur:m=>g("x",m.target.value),className:"w-full px-2 py-1.5 border border-theme rounded-lg text-xs font-mono focus:outline-none focus:ring-1 focus:ring-primary-theme bg-surface text-main"})]}),e.jsxs("div",{children:[e.jsx("label",{className:"block text-xs text-muted font-semibold mb-1",children:"Y 坐标"}),e.jsx("input",{type:"number",value:Math.round(d.y??0),onChange:m=>a("y",parseFloat(m.target.value)||0),onBlur:m=>g("y",m.target.value),className:"w-full px-2 py-1.5 border border-theme rounded-lg text-xs font-mono focus:outline-none focus:ring-1 focus:ring-primary-theme bg-surface text-main"})]})]}),p.type!=="pen"&&p.type!=="circle"&&e.jsxs("div",{className:"grid grid-cols-2 gap-2 mt-2",children:[e.jsxs("div",{children:[e.jsx("label",{className:"block text-xs text-muted font-semibold mb-1",children:"宽度 (Width)"}),e.jsx("input",{type:"number",min:"50",value:Math.round(d.width??300),onChange:m=>a("width",parseFloat(m.target.value)||50),onBlur:m=>g("width",m.target.value),className:"w-full px-2 py-1.5 border border-theme rounded-lg text-xs font-mono focus:outline-none focus:ring-1 focus:ring-primary-theme bg-surface text-main"})]}),e.jsxs("div",{children:[e.jsx("label",{className:"block text-xs text-muted font-semibold mb-1",children:"高度 (Height)"}),e.jsx("input",{type:"number",min:"50",value:Math.round(d.height??300),onChange:m=>a("height",parseFloat(m.target.value)||50),onBlur:m=>g("height",m.target.value),className:"w-full px-2 py-1.5 border border-theme rounded-lg text-xs font-mono focus:outline-none focus:ring-1 focus:ring-primary-theme bg-surface text-main"})]})]}),p.type==="circle"&&e.jsxs("div",{className:"mt-2",children:[e.jsx("label",{className:"block text-xs text-muted font-semibold mb-1",children:"半径 (Radius)"}),e.jsx("input",{type:"number",min:"5",value:Math.round(d.radius??50),onChange:m=>a("radius",parseFloat(m.target.value)||5),onBlur:m=>g("radius",m.target.value),className:"w-full px-2 py-1.5 border border-theme rounded-lg text-xs font-mono focus:outline-none focus:ring-1 focus:ring-primary-theme bg-surface text-main"})]})]}),(()=>{const m=ci.get(p.type);if(m)return e.jsx(m,{elementId:p.id,elementType:p.type,data:d,updateData:j,lessonId:f,onClose:()=>x(null)});const O=ns.get(p.type);if(O){const v=O.editFields||[];return e.jsxs("div",{className:"bg-surface p-3 rounded-xl border border-theme shadow-sm space-y-3",children:[e.jsxs("h4",{className:"font-bold text-main text-xs border-b border-theme pb-1.5 flex items-center justify-between",children:[e.jsxs("span",{children:[O.labelZh," 配置"]}),e.jsx("span",{className:"text-xs text-muted font-normal",children:"插件扩展"})]}),v.length===0?e.jsxs("div",{children:[e.jsx("label",{className:"block text-xs text-muted font-semibold mb-1",children:"标题 (Title)"}),e.jsx("input",{type:"text",value:d.title||"",onChange:w=>a("title",w.target.value),onBlur:w=>n("title",w.target.value),className:"w-full px-2 py-1.5 border border-theme rounded-lg text-xs focus:outline-none focus:ring-1 focus:ring-primary-theme bg-surface text-main",placeholder:"组件标题..."})]}):v.map(w=>{const q=d[w.key]??"";return w.kind==="textarea"?e.jsxs("div",{children:[e.jsx("label",{className:"block text-xs text-muted font-semibold mb-1",children:w.labelZh}),e.jsx("textarea",{value:q,onChange:I=>a(w.key,I.target.value),onBlur:I=>n(w.key,I.target.value),className:"w-full h-20 p-2 border border-theme rounded-lg text-xs focus:outline-none focus:ring-1 focus:ring-primary-theme bg-surface text-main resize-none font-medium leading-relaxed",placeholder:w.placeholderZh||""})]},w.key):w.kind==="select"?e.jsxs("div",{children:[e.jsx("label",{className:"block text-xs text-muted font-semibold mb-1",children:w.labelZh}),e.jsxs("select",{value:q,onChange:I=>{a(w.key,I.target.value),n(w.key,I.target.value)},className:"w-full px-2 py-1.5 border border-theme rounded-lg text-xs bg-surface text-main focus:outline-none focus:ring-1 focus:ring-primary-theme",children:[e.jsx("option",{value:"",children:"请选择..."}),(w.options||[]).map(I=>e.jsx("option",{value:I.value,children:I.label},I.value))]})]},w.key):e.jsxs("div",{children:[e.jsx("label",{className:"block text-xs text-muted font-semibold mb-1",children:w.labelZh}),e.jsx("input",{type:"text",value:q,onChange:I=>a(w.key,I.target.value),onBlur:I=>n(w.key,I.target.value),className:"w-full px-2 py-1.5 border border-theme rounded-lg text-xs focus:outline-none focus:ring-1 focus:ring-primary-theme bg-surface text-main",placeholder:w.placeholderZh||""})]},w.key)})]})}return null})(),p.type==="quiz"&&e.jsxs("div",{className:"bg-surface p-3 rounded-xl border border-theme shadow-sm space-y-3",children:[e.jsx("h4",{className:"font-bold text-main text-xs border-b border-theme pb-1.5",children:"随堂测验配置"}),e.jsxs("div",{children:[e.jsx("label",{className:"block text-xs text-muted font-semibold mb-1",children:"测验题目 (Question)"}),e.jsx("textarea",{value:d.question||"",onChange:m=>a("question",m.target.value),onBlur:m=>n("question",m.target.value),className:"w-full h-20 p-2 border border-theme rounded-lg text-xs focus:outline-none focus:ring-1 focus:ring-primary-theme bg-surface text-main resize-none font-medium leading-relaxed",placeholder:"编写问题描述..."})]}),(d.options||[]).length>0&&e.jsxs("div",{className:"bg-amber-500/10 border border-amber-500/30 rounded-lg p-2.5",children:[e.jsx("label",{className:"block text-xs text-amber-500 font-bold mb-1.5",children:"⚠️ 正确答案 (Correct Answer)"}),e.jsxs("select",{value:d.correctAnswer||"",onChange:m=>{a("correctAnswer",m.target.value),n("correctAnswer",m.target.value)},className:`w-full px-2 py-1.5 border rounded-lg text-xs font-medium focus:outline-none focus:ring-1 focus:ring-amber-500 cursor-pointer ${d.correctAnswer?"border-green-500/40 bg-green-500/10 text-green-600":"border-amber-500/40 bg-surface text-main"}`,children:[e.jsx("option",{value:"",children:"-- 请选择正确答案 --"}),(d.options||[]).map((m,O)=>e.jsx("option",{value:m,children:m},O))]}),!d.correctAnswer&&e.jsx("p",{className:"text-xs text-amber-500 mt-1",children:"未设置正确答案将无法自动判分"})]}),e.jsxs("div",{className:"space-y-2",children:[e.jsx("label",{className:"block text-xs text-muted font-semibold",children:"选项列表 (Options)"}),e.jsx("div",{className:"space-y-1.5 max-h-48 overflow-y-auto pr-1",children:(d.options||[]).map((m,O)=>{const w="ABCDEFGHIJKLMNOPQRSTUVWXYZ"[O]||O+1;return e.jsxs("div",{className:"flex items-center gap-1.5",children:[e.jsx("span",{className:"font-bold text-main bg-surface-secondary rounded px-1.5 py-1 text-center shrink-0 min-w-[22px]",children:w}),e.jsx("input",{type:"text",value:m||"",onChange:q=>T(O,q.target.value),onBlur:q=>R(O,q.target.value),className:"flex-1 px-2 py-1 border border-theme rounded-lg text-xs font-medium bg-surface text-main"}),e.jsx("button",{onClick:()=>z(O),title:"删除选项",className:"text-muted hover:text-rose-500 hover:bg-rose-500/10 p-1 rounded-md shrink-0 transition-colors cursor-pointer",children:e.jsx(ct,{size:13})})]},O)})}),e.jsxs("button",{onClick:J,className:"w-full mt-2 py-1 bg-surface-secondary hover:bg-surface-secondary text-main font-bold border border-theme rounded-lg flex items-center justify-center gap-1 transition-all text-xs cursor-pointer",children:[e.jsx(It,{size:12})," 添加选项"]})]})]}),p.type==="assignment"&&e.jsxs("div",{className:"bg-surface p-3 rounded-xl border border-theme shadow-sm space-y-3",children:[e.jsx("h4",{className:"font-bold text-main text-xs border-b border-theme pb-1.5",children:"作业选项配置"}),e.jsxs("div",{children:[e.jsx("label",{className:"block text-xs text-muted font-semibold mb-1",children:"作业任务标题 (Title)"}),e.jsx("input",{type:"text",value:d.title||"",onChange:m=>a("title",m.target.value),onBlur:m=>n("title",m.target.value),className:"w-full px-2 py-1.5 border border-theme rounded-lg text-xs font-semibold focus:outline-none focus:ring-1 focus:ring-primary-theme bg-surface text-main",placeholder:"作业名..."})]}),e.jsxs("div",{children:[e.jsx("label",{className:"block text-xs text-muted font-semibold mb-1",children:"详细作业要求描述"}),e.jsx("textarea",{value:d.description||"",onChange:m=>a("description",m.target.value),onBlur:m=>n("description",m.target.value),className:"w-full h-24 p-2 border border-theme rounded-lg text-xs focus:outline-none focus:ring-1 focus:ring-primary-theme bg-surface text-main resize-none font-medium leading-relaxed",placeholder:"请输入详细的作业指南..."})]}),e.jsx(Ma,{lessonId:f,classId:_||F||void 0,elementId:p.id,value:d.assignmentId||"",draftTitle:d.title||"",draftDescription:d.description||"",onChange:m=>{a("assignmentId",m),n("assignmentId",m)}}),d.assignmentId?e.jsx(Da,{assignmentId:String(d.assignmentId)},String(d.assignmentId)):null]}),(p.type==="code-sandbox"||p.type==="html-applet")&&e.jsxs("div",{className:"bg-surface p-3 rounded-xl border border-theme shadow-sm space-y-3",children:[e.jsxs("h4",{className:"font-bold text-main text-xs border-b border-theme pb-1.5 flex justify-between items-center",children:[e.jsx("span",{children:"动态运行代码定制"}),p.type==="html-applet"&&e.jsx("span",{className:"text-xs bg-primary-theme-light text-primary-theme px-1.5 py-0.5 rounded-full font-bold",children:"HTML Applet"})]}),p.type==="html-applet"&&e.jsxs("div",{className:"space-y-3 border-b border-theme pb-3",children:[e.jsxs("div",{children:[e.jsx("label",{className:"block text-xs text-primary-theme font-bold mb-1",children:"选择互动网络课件 (ZIP/HTML):"}),e.jsxs("select",{value:d.coursewareUuid||"",onChange:m=>{const O=m.target.value;j({coursewareUuid:O,resourceId:""})},className:"w-full text-xs p-2 bg-surface-secondary border border-theme hover:border-primary-theme rounded-lg text-main focus:outline-none focus:ring-1 focus:ring-primary-theme transition-all font-semibold",children:[e.jsx("option",{value:"",children:"-- 使用自定义沙箱代码 --"}),L.map(m=>e.jsxs("option",{value:m.uuid,children:["📁 [互动课件] ",m.name]},m.id))]})]}),e.jsxs("div",{className:"bg-surface-secondary p-2.5 rounded-xl border border-theme text-xs text-muted space-y-2",children:[e.jsx("span",{className:"font-bold text-main block",children:"上传新课件 (自动生成独立运行实例):"}),e.jsxs("label",{className:"w-full flex flex-col items-center justify-center p-3 bg-indigo-50 hover:bg-indigo-100 border border-dashed border-indigo-300 hover:border-indigo-400 rounded-lg cursor-pointer text-center transition-all",children:[e.jsx("span",{className:"font-bold text-indigo-700 text-xs",children:"✨ 上传互动网络课件 (.zip / .html)"}),e.jsx("span",{className:"text-xs text-indigo-500 mt-0.5",children:"支持多文件打包 ZIP 或单页 HTML,自动接入 LMS Bridge"}),e.jsx("input",{type:"file",accept:".zip,.html,.htm",className:"hidden",onChange:async m=>{const O=m.target.files?.[0];if(!O)return;const v=new FileReader;v.onload=async w=>{const q=w.target?.result;try{const I=await fetch("/api/courseware/upload",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({name:O.name.replace(/\.[^/.]+$/,""),filename:O.name,base64Data:q})});if(I.ok){const D=await I.json();D.need_select_entry?(U(D.candidates),xe({uuid:D.uuid,name:D.name}),ee(!0)):(j({coursewareUuid:D.uuid,resourceId:""}),ie({force:!0}))}else{const D=await I.json();alert("上传失败: "+(D.error||I.statusText))}}catch(I){console.error("Courseware upload failed:",I)}},v.readAsDataURL(O)}})]})]})]}),(!d.coursewareUuid||p.type==="code-sandbox")&&e.jsxs("div",{children:[e.jsx("label",{className:"block text-xs text-slate-400 font-semibold mb-1",children:"沙箱程序代码 (Source Code)"}),e.jsx("textarea",{value:d.code||"",onChange:m=>a("code",m.target.value),onBlur:m=>n("code",m.target.value),className:"w-full h-48 p-3 border border-slate-300 rounded-lg text-xs font-mono focus:outline-none focus:ring-1 focus:ring-indigo-500 bg-slate-900 text-slate-100 resize-none leading-relaxed",placeholder:"// 编写交互沙箱代码..."})]})]}),p.type==="math-graph"&&e.jsxs("div",{className:"bg-surface p-3 rounded-xl border border-theme shadow-sm space-y-3",children:[e.jsx("h4",{className:"font-bold text-main text-xs border-b border-theme pb-1.5",children:"函数解析拟合"}),e.jsxs("div",{children:[e.jsx("label",{className:"block text-xs text-muted font-semibold mb-1",children:"函数表达式 y = f(x)"}),e.jsx("input",{type:"text",value:d.equation||"",onChange:m=>a("equation",m.target.value),onBlur:m=>n("equation",m.target.value),className:"w-full px-2 py-1.5 border border-theme rounded-lg text-xs font-mono focus:outline-none focus:ring-1 focus:ring-primary-theme bg-surface text-main"}),e.jsxs("p",{className:"text-xs text-muted mt-1 leading-snug",children:["支持标准 JS 表达式。 示例:",e.jsx("br",{}),"• ",e.jsx("code",{className:"bg-surface-secondary px-1 rounded",children:"Math.sin(x)"})," 正负弦波形",e.jsx("br",{}),"• ",e.jsx("code",{className:"bg-surface-secondary px-1 rounded",children:"Math.cos(x) * x"})," 振幅衰减"]})]})]}),p.type==="presentation"&&e.jsxs("div",{className:"bg-surface p-3 rounded-xl border border-theme shadow-sm space-y-3",children:[e.jsx("h4",{className:"font-bold text-main text-xs border-b border-theme pb-1.5",children:"幻灯片 Markdown 文案"}),e.jsxs("div",{children:[e.jsx("label",{className:"block text-xs text-muted font-semibold mb-1",children:"Markdown 源代码"}),e.jsx("textarea",{value:d.markdown||"",onChange:m=>a("markdown",m.target.value),onBlur:m=>n("markdown",m.target.value),className:"w-full h-64 p-2.5 border border-theme rounded-lg text-xs font-mono focus:outline-none focus:ring-1 focus:ring-primary-theme resize-none font-medium leading-relaxed bg-surface text-main",placeholder:"修改 Markdown 内容..."})]})]}),p.type==="text"&&e.jsxs("div",{className:"bg-surface p-3 rounded-xl border border-theme shadow-sm space-y-3",children:[e.jsx("h4",{className:"font-bold text-main text-xs border-b border-theme pb-1.5",children:"文字属性管理"}),e.jsxs("div",{children:[e.jsx("label",{className:"block text-xs text-muted font-semibold mb-1",children:"文本内容"}),e.jsx("input",{type:"text",value:d.text||"",onChange:m=>a("text",m.target.value),onBlur:m=>n("text",m.target.value),className:"w-full px-2 py-1.5 border border-theme rounded-lg text-xs font-medium focus:outline-none focus:ring-1 focus:ring-primary-theme bg-surface text-main"})]}),e.jsxs("div",{children:[e.jsx("label",{className:"block text-xs text-muted font-semibold mb-1",children:"文字大小 (FontSize)"}),e.jsx("input",{type:"number",min:"10",max:"100",value:d.fontSize||16,onChange:m=>a("fontSize",parseInt(m.target.value)||10),onBlur:m=>g("fontSize",m.target.value),className:"w-full px-2 py-1.5 border border-theme rounded-lg text-xs font-mono focus:outline-none focus:ring-1 focus:ring-primary-theme bg-surface text-main"})]}),e.jsxs("div",{children:[e.jsx("label",{className:"block text-xs text-muted font-semibold mb-1",children:"文字填充颜色"}),e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("input",{type:"color",value:d.color||"#000000",onChange:m=>a("color",m.target.value),onBlur:m=>n("color",m.target.value),className:"w-8 h-8 rounded border border-theme cursor-pointer shrink-0 bg-surface"}),e.jsx("span",{className:"font-mono text-xs text-muted",children:d.color||"#000000"})]})]})]}),(p.type==="rectangle"||p.type==="shape")&&e.jsxs("div",{className:"bg-surface p-3 rounded-xl border border-theme shadow-sm space-y-3",children:[e.jsx("h4",{className:"font-bold text-main text-xs border-b border-theme pb-1.5",children:"矩形样式配置"}),e.jsxs("div",{children:[e.jsx("label",{className:"block text-xs text-muted font-semibold mb-1",children:"外边框颜色"}),e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("input",{type:"color",value:d.stroke||"#000000",onChange:m=>a("stroke",m.target.value),onBlur:m=>n("stroke",m.target.value),className:"w-8 h-8 rounded border border-theme cursor-pointer shrink-0 bg-surface"}),e.jsx("span",{className:"font-mono text-xs text-muted",children:d.stroke||"#000000"})]})]})]}),p.type==="circle"&&e.jsxs("div",{className:"bg-surface p-3 rounded-xl border border-theme shadow-sm space-y-3",children:[e.jsx("h4",{className:"font-bold text-main text-xs border-b border-theme pb-1.5",children:"圆形样式配置"}),e.jsxs("div",{children:[e.jsx("label",{className:"block text-xs text-muted font-semibold mb-1",children:"外边框颜色"}),e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("input",{type:"color",value:d.stroke||"#000000",onChange:m=>a("stroke",m.target.value),onBlur:m=>n("stroke",m.target.value),className:"w-8 h-8 rounded border border-theme cursor-pointer shrink-0 bg-surface"}),e.jsx("span",{className:"font-mono text-xs text-muted",children:d.stroke||"#000000"})]})]})]}),p.type==="pen"&&e.jsxs("div",{className:"bg-surface p-3 rounded-xl border border-theme shadow-sm space-y-3",children:[e.jsx("h4",{className:"font-bold text-main text-xs border-b border-theme pb-1.5",children:"线条样式配置"}),e.jsxs("div",{children:[e.jsx("label",{className:"block text-xs text-muted font-semibold mb-1",children:"折线颜色"}),e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("input",{type:"color",value:d.color||"#000000",onChange:m=>a("color",m.target.value),onBlur:m=>n("color",m.target.value),className:"w-8 h-8 rounded border border-theme cursor-pointer shrink-0 bg-surface"}),e.jsx("span",{className:"font-mono text-xs text-muted",children:d.color||"#000000"})]})]})]}),p.type==="highlighter"&&e.jsxs("div",{className:"bg-surface p-3 rounded-xl border border-theme shadow-sm space-y-3",children:[e.jsx("h4",{className:"font-bold text-main text-xs border-b border-theme pb-1.5",children:"高亮荧光标记 (Highlighter)"}),e.jsxs("div",{children:[e.jsx("label",{className:"block text-xs text-muted font-semibold mb-1",children:"荧光笔颜色"}),e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("input",{type:"color",value:d.color||"#facc15",onChange:m=>a("color",m.target.value),onBlur:m=>n("color",m.target.value),className:"w-8 h-8 rounded border border-theme cursor-pointer shrink-0 bg-surface"}),e.jsx("span",{className:"font-mono text-xs text-muted",children:d.color||"#facc15"})]})]})]}),e.jsx("div",{className:"text-xs text-muted text-center select-none pt-2 font-medium",children:"提示:属性在失焦或修改时自动同步,多端可见。"})]}),e.jsxs("div",{className:"p-3 border-t border-slate-200 bg-white flex flex-col gap-2 shrink-0",children:[e.jsx("button",{onClick:()=>P(d),disabled:y,className:"w-full py-2 bg-indigo-600 hover:bg-indigo-700 text-white rounded-lg font-bold transition-all shadow-sm hover:shadow active:scale-[0.98] cursor-pointer flex items-center justify-center gap-1.5 text-xs",children:y?e.jsxs(e.Fragment,{children:[e.jsx(Ke,{size:13,className:"animate-spin"}),"正在广播同步..."]}):e.jsxs(e.Fragment,{children:[e.jsx(_i,{size:13}),"应用修改并强制同步"]})}),e.jsxs("button",{onClick:()=>{X(r),x(null)},className:"w-full py-2 bg-red-50 hover:bg-red-105 text-red-650 rounded-lg font-semibold transition-all flex items-center justify-center gap-1.5 border border-red-200 cursor-pointer text-xs",children:[e.jsx(ct,{size:13}),"删除当前组件"]})]})]})},Ea=({isVisible:t})=>t?e.jsxs("div",{className:"absolute inset-0 flex flex-col items-center justify-center pointer-events-none select-none text-muted p-6 z-0",children:[e.jsx("div",{className:"w-16 h-16 rounded-2xl bg-primary-theme-light border border-theme flex items-center justify-center mb-3 shadow-2xs",children:e.jsx(Yt,{className:"w-7 h-7 text-primary-theme animate-pulse"})}),e.jsx("p",{className:"font-bold text-sm text-main mb-1",children:"交互式备课白板"}),e.jsx("p",{className:"text-xs text-muted max-w-sm text-center",children:"从左侧组件库拖拽组件至此处,或使用顶部工具栏插入画笔、几何图形与 AI 助教"})]}):null,Ra=24;function _a({elementId:t,type:r,lessonId:x,readOnly:l=!1,dismissible:c=!0,onExit:u,renderContent:d}){i.useEffect(()=>{if(!c)return;const g=j=>{j.key==="Escape"&&u()};return window.addEventListener("keydown",g),()=>window.removeEventListener("keydown",g)},[u,c]);const[a,n]=i.useState(()=>({width:typeof window>"u"?1024:window.innerWidth,height:typeof window>"u"?768:window.innerHeight}));return i.useEffect(()=>{const g=()=>n({width:window.innerWidth,height:window.innerHeight});return window.addEventListener("resize",g),()=>window.removeEventListener("resize",g)},[]),e.jsxs("div",{"data-testid":"browser-fullscreen-host","data-element-id":t,"data-element-type":r,"data-dismissible":c?"true":"false",style:{pointerEvents:"auto",zIndex:xa},className:"fixed inset-0 bg-white dark:bg-slate-950 flex flex-col",children:[c?e.jsxs("button",{type:"button","data-testid":"browser-fullscreen-exit",onClick:u,className:"fixed top-4 right-4 z-[100001] px-3 py-2 rounded-xl bg-slate-900/85 hover:bg-slate-900 text-slate-100 text-xs font-bold flex items-center gap-1.5 shadow-2xl backdrop-blur-md border border-white/15 transition-colors cursor-pointer",title:"退出全屏(Esc)",children:[e.jsx(Qr,{size:14}),"退出全屏"]}):e.jsx("span",{className:"fixed top-4 right-4 z-[100001] px-3 py-2 rounded-xl bg-slate-900/85 text-slate-200 text-xs font-bold flex items-center gap-1.5 shadow-2xl border border-white/10 select-none",title:l?"教师已开启全班专注锁定":"由教师端控制,无法在本地退出",children:l?"🔒 教师同步视图":"教师同步视图"}),e.jsx("div",{"data-testid":"browser-fullscreen-content",className:"flex-1 min-h-0 overflow-auto",style:{width:a.width,height:a.height},children:d(a)}),e.jsx("span",{hidden:!0,"data-lesson-id":x})]})}function Jr({width:t,height:r,children:x}){return t<=0||r<=0?null:e.jsx(Gr,{"data-testid":"widget-fullscreen-stage",width:t,height:r,style:{backgroundColor:"transparent"},children:e.jsx(Kr,{children:x})})}const Aa={quiz:"📝 随堂测验",timer:"⏱ 计时器",assignment:"📋 作业","code-sandbox":"💻 代码沙箱","html-applet":"🌐 交互课件",rollcall:"🎲 随机点名",presentation:"📽 演示文稿","math-graph":"📐 数学图形",text:"📝 文本"},Fa=({containerSize:t,browserFullscreenElementId:r,isRemoteBrowserFullscreen:x,isBrowserFullscreenDismissible:l,browserFullscreen:c,effectiveFullscreenElementId:u,isRemoteFullscreen:d,isFullscreenDismissible:a,applyFullscreen:n,safeElements:g,lessonId:j,readOnly:P,renderElement:X,children:k})=>{if(t.width<=0||t.height<=0)return null;if(r){const M=g.find(N=>N.id===r);if(!M)return x?e.jsxs("div",{className:"w-full h-full flex flex-col items-center justify-center bg-slate-900/80 backdrop-blur-xs text-white",children:[e.jsx("div",{className:"animate-spin rounded-full h-8 w-8 border-b-2 border-indigo-400 mb-3"}),e.jsx("p",{className:"text-xs font-medium text-slate-200",children:"正在同步教师端的浏览器全屏组件..."})]}):null;const b=Je(M);return e.jsx(_a,{elementId:r,type:M.type,data:b,lessonId:j,readOnly:P,dismissible:l,onExit:()=>void c.exit(),renderContent:N=>e.jsx(Jr,{width:N.width,height:N.height,children:X(M,{fullscreen:{width:N.width,height:N.height,padding:Ra}})})})}if(u){const M=g.find(N=>N.id===u);if(!M)return d?e.jsxs("div",{className:"w-full h-full flex flex-col items-center justify-center bg-slate-900/60 backdrop-blur-xs text-white",children:[e.jsx("div",{className:"animate-spin rounded-full h-8 w-8 border-b-2 border-indigo-400 mb-3"}),e.jsx("p",{className:"text-xs font-medium text-slate-200",children:"正在同步教师端全屏组件..."})]}):null;const b=Je(M);return e.jsx(di,{type:M.type,title:Aa[M.type]||M.type,data:b,containerSize:t,dismissible:a,onClose:()=>n(null),lessonId:j,elementId:M.id,readOnly:P,renderContent:N=>e.jsx(Jr,{width:N.width,height:N.height,children:X(M,{fullscreen:{width:N.width,height:N.height,padding:0}})})})}return e.jsx(e.Fragment,{children:k})},La=({autoTileEnabled:t,readOnly:r,tilingSplitters:x,activeSplitterDrag:l,activeDropZoneAction:c,handleSplitterPointerDown:u})=>!t||r?null:e.jsxs(e.Fragment,{children:[x.length>0&&e.jsx("div",{className:"absolute inset-0 pointer-events-none z-30",children:x.map(d=>{const a=d.orientation==="horizontal",n=l?.splitter.id===d.id;return e.jsxs("div",{"data-testid":`splitter-${d.orientation}-${d.id}`,className:`absolute pointer-events-auto group flex items-center justify-center select-none ${a?"cursor-row-resize":"cursor-col-resize"}`,style:{left:`${d.x}px`,top:`${d.y}px`,width:`${a?d.length:d.thickness}px`,height:`${a?d.thickness:d.length}px`},onPointerDown:g=>u(g,d),title:a?"拖动调整上下分割高度":"拖动调整左右分割宽度",children:[e.jsx("div",{className:`rounded-full transition-all duration-150 ${a?`w-full h-1 my-auto ${n?"bg-indigo-500 h-1.5 shadow-md":"bg-transparent group-hover:bg-indigo-400/80 group-hover:h-1.5"}`:`h-full w-1 mx-auto ${n?"bg-indigo-500 w-1.5 shadow-md":"bg-transparent group-hover:bg-indigo-400/80 group-hover:w-1.5"}`}`}),e.jsx("div",{className:`absolute rounded-full transition-all duration-150 flex items-center justify-center ${n?"bg-indigo-600 text-white scale-110 shadow-lg":"opacity-0 group-hover:opacity-100 bg-white/95 dark:bg-slate-800/95 text-indigo-600 shadow border border-indigo-200 dark:border-indigo-700"} ${a?"w-8 h-3.5":"h-8 w-3.5"}`,children:e.jsxs("div",{className:`flex ${a?"flex-row gap-0.5":"flex-col gap-0.5"}`,children:[e.jsx("div",{className:"w-1 h-1 rounded-full bg-current opacity-70"}),e.jsx("div",{className:"w-1 h-1 rounded-full bg-current opacity-70"}),e.jsx("div",{className:"w-1 h-1 rounded-full bg-current opacity-70"})]})})]},d.id)})}),c&&c.type!=="swap"&&e.jsx("div",{"data-testid":"directional-split-preview",className:"absolute pointer-events-none rounded-2xl border-3 border-dashed border-indigo-500 bg-indigo-500/20 backdrop-blur-[2px] shadow-2xl flex items-center justify-center transition-all duration-150 z-40 animate-in fade-in zoom-in-95",style:{left:`${c.previewRect.x}px`,top:`${c.previewRect.y}px`,width:`${c.previewRect.width}px`,height:`${c.previewRect.height}px`},children:e.jsx("div",{className:"bg-indigo-600 text-white text-xs md:text-sm font-bold px-4 py-2 rounded-full shadow-lg flex items-center gap-2 select-none animate-bounce",children:e.jsx("span",{children:c.label})})})]}),Ba={quiz:{width:340,height:380},timer:{width:280,height:200},assignment:{width:340,height:400},rollcall:{width:340,height:420},"html-applet":{width:400,height:300},"code-sandbox":{width:400,height:320},"math-graph":{width:400,height:350},presentation:{width:600,height:400},plugin:{width:500,height:400}};function kt(t,r){const x=Ba[t];return x?{width:r?.width||x.width,height:r?.height||x.height}:{width:r?.width||300,height:r?.height||300}}function Ha({containerSize:t,safeElements:r,getCurrentPageElements:x,onElementUpdate:l,lessonId:c,readOnly:u,setLocalGeometry:d,localGeometryRef:a,localGeometryVersion:n,currentPage:g,activeSegmentId:j,pages:P,tileSplitPreferenceRef:X,setIsSyncing:k}){const[M,b]=i.useState(!1),[N,y]=i.useState(null),f=i.useRef(null);i.useEffect(()=>{f.current=N},[N]);const _=i.useCallback(async(p,C,m)=>{if(!l||t.width<=0||t.height<=0)return;const O=p.filter(re=>Ge(re.type));if(O.length===0)return;const v=[],w=new Map,q=new Map;let I=C??X.current;for(const re of O){const te=Je(re,null);if(!te)continue;!I&&te.tileStackDir&&(I=te.tileStackDir);const B=As(re,te,kt(re.type,te));if(B)if(v.push(B),w.set(re.id,te),m){const K=m.indexOf(re.id);q.set(re.id,K>=0?K:void 0)}else q.set(re.id,typeof te.tileOrder=="number"?te.tileOrder:void 0)}if(v.length===0)return;const D=Qi(v,q),ne=Gi(D,t,{stackDirection:I});if(ne.length===0)return;let ce=!1;k(!0);try{for(let re=0;re<D.length;re+=1){const te=D[re],B=w.get(te.id);if(!B)continue;const K=Ki(te,ne[re]),ye=Fs(te.shape);if(Ls(B,K,ye)&&B.tileOrder===re&&B.tileStackDir===I)continue;ce=!0,d(te.id,K);const Y={...B,...K,tileOrder:re,tileStackDir:I};B.__preTile||(Y.__preTile=Ue(B,te.shape)),Y.__tiled=K;const le=p.find(be=>be.id===te.id)||r.find(be=>be.id===te.id);le&&(le.data=JSON.stringify(Y)),await l(te.id,Y)}if(!ce)return;ae.publish({id:oe(),type:"whiteboard.element_updated",source:"whiteboard",payload:{lessonId:c},timestamp:Date.now(),correlationId:c})}finally{k(!1)}},[l,t,r,c,d,X,k]),F=i.useCallback(async(p,C)=>{const m=x().filter(O=>Ge(O.type));await _(m,p,C)},[x,_]),L=i.useCallback(async(p,C)=>{if(!l||p===C)return;const m=r.find(je=>je.id===p),O=r.find(je=>je.id===C);if(!m||!O)return;const v=Je(m,null),w=Je(O,null);if(!v||!w)return;const q=Ue(v,m.type==="circle"?"circle":"rect"),I=Ue(w,O.type==="circle"?"circle":"rect"),D=a.current.get(p),ne=a.current.get(C),ce={...q,...D||{}},re={...I,...ne||{}},te=x().filter(je=>Ge(je.type)),B=te.findIndex(je=>je.id===p),K=te.findIndex(je=>je.id===C),ye=typeof v.tileOrder=="number"?v.tileOrder:B>=0?B:0,Y=typeof w.tileOrder=="number"?w.tileOrder:K>=0?K:1,le={...v,...re,tileOrder:Y},be={...w,...ce,tileOrder:ye};v.__preTile||(le.__preTile=Ue(v,m.type==="circle"?"circle":"rect")),w.__preTile||(be.__preTile=Ue(w,O.type==="circle"?"circle":"rect")),le.__tiled=re,be.__tiled=ce,d(p,re),d(C,ce),k(!0);try{await Promise.all([l(p,le),l(C,be)]),ae.publish({id:oe(),type:"whiteboard.element_updated",source:"whiteboard",payload:{lessonId:c},timestamp:Date.now(),correlationId:c})}finally{k(!1)}},[l,r,x,d,a,c,k]),ie=i.useCallback(async()=>{if(!l)return;const p=[];for(const C of r){const m=Je(C,null);if(!m||!m.__preTile)continue;const{__preTile:O,__tiled:v,tileOrder:w,...q}=m,I=Fs(C.type==="circle"?"circle":"rect"),D=!v||Ls(m,v,I);p.push({id:C.id,patch:D?{...q,...O}:q})}if(p.length!==0){k(!0);try{for(const{id:C,patch:m}of p){const O=m.radius!==void 0?"circle":"rect";d(C,Ue(m,O)),await l(C,m)}ae.publish({id:oe(),type:"whiteboard.element_updated",source:"whiteboard",payload:{lessonId:c},timestamp:Date.now(),correlationId:c})}finally{k(!1)}}},[l,r,c,d,k]),U=i.useCallback(async(p,C,m)=>{if(!l||p===C)return;const v=x().filter(D=>Ge(D.type)).map(D=>{const ne=Je(D),ce=kt(D.type,ne),re=a.current.get(D.id);return{id:D.id,x:re?.x??ne.x??0,y:re?.y??ne.y??0,width:re?.width??ne.width??ce.width,height:re?.height??ne.height??ce.height}}),w=12,q={x:w,y:w,width:Math.max(0,t.width-w*2),height:Math.max(0,t.height-w*2)},I=ra(p,C,m,v,q);if(Object.keys(I).length!==0){k(!0);try{for(const[D,ne]of Object.entries(I)){const ce=v.find(re=>re.id===D);ce&&d(D,Object.assign({x:ce.x,y:ce.y,width:ce.width,height:ce.height},ne))}await Promise.all(Object.entries(I).map(async([D,ne])=>{const ce=r.find(ye=>ye.id===D);if(!ce)return;const re=Je(ce,{}),te=ce.type==="circle"?"circle":"rect",K={...Ue(re,te),...ne};d(D,K),await l(D,{...re,...ne,__tiled:K})})),ae.publish({id:oe(),type:"whiteboard.element_updated",source:"whiteboard",payload:{lessonId:c},timestamp:Date.now(),correlationId:c})}finally{k(!1)}}},[l,r,x,t,d,a,c,k]),xe=i.useCallback(()=>{M&&ie(),b(!M)},[M,ie]),ee=i.useMemo(()=>M?x().filter(C=>Ge(C.type)).map(C=>{let m={};try{m=JSON.parse(C.data)}catch{}const O=kt(C.type,m),v=a.current.get(C.id);return{id:C.id,x:v?.x??m.x??0,y:v?.y??m.y??0,width:v?.width??m.width??O.width,height:v?.height??m.height??O.height}}):[],[M,r,g,j,P,n,x,a]),J=i.useMemo(()=>!M||ee.length<2?[]:ea(ee),[M,ee]),z=i.useCallback((p,C)=>{if(u)return;p.preventDefault(),p.stopPropagation();const m=C.orientation==="horizontal"?p.clientY:p.clientX;y({splitter:C,startPointerPos:m,initialBoxes:ee})},[u,ee]),T=i.useRef(F);i.useEffect(()=>{T.current=F},[F]);const R=i.useMemo(()=>M?x().filter(p=>Ge(p.type)).map(p=>p.id).join("|"):"",[M,r,g,j,P,x]);return i.useEffect(()=>{!M||!R||T.current()},[M,R]),i.useEffect(()=>{if(!M||t.width<=0||t.height<=0)return;const p=setTimeout(()=>{T.current()},250);return()=>clearTimeout(p)},[M,t.width,t.height]),i.useEffect(()=>{if(!N)return;const p=m=>{if(!f.current)return;const{splitter:O,startPointerPos:v,initialBoxes:w}=f.current,D=(O.orientation==="horizontal"?m.clientY:m.clientX)-v,ne=ta(O,D,w);for(const[ce,re]of Object.entries(ne)){const te=w.find(B=>B.id===ce);te&&d(ce,{x:te.x,y:te.y,width:te.width,height:te.height,...re})}},C=async()=>{if(!f.current)return;const{splitter:m,startPointerPos:O,initialBoxes:v}=f.current;if(m.orientation==="horizontal"&&window.event&&window.event.clientY,y(null),l&&v.length>0){k(!0);try{await Promise.all(v.map(async q=>{const I=r.find(D=>D.id===q.id);if(I)try{const D=JSON.parse(I.data),ne=a.current.get(q.id);ne&&await l(q.id,{...D,...ne,__tiled:ne})}catch{}})),ae.publish({id:oe(),type:"whiteboard.element_updated",source:"whiteboard",payload:{lessonId:c},timestamp:Date.now(),correlationId:c})}finally{k(!1)}}};return window.addEventListener("pointermove",p),window.addEventListener("pointerup",C),()=>{window.removeEventListener("pointermove",p),window.removeEventListener("pointerup",C)}},[N,l,r,c,d,a,k]),{autoTileEnabled:M,setAutoTileEnabled:b,handleToggleAutoTile:xe,currentTilingBoxes:ee,tilingSplitters:J,activeSplitterDrag:N,setActiveSplitterDrag:y,activeSplitterDragRef:f,handleSplitterPointerDown:z,applyAutoTiling:F,applyAutoTilingForElements:_,swapTileElements:L,restoreAutoTiling:ie,insertTileInDirection:U}}const Wa=({showEntrySelector:t,setShowEntrySelector:r,zipUploadInfo:x,zipCandidates:l,handlePropsUpdate:c,fetchCoursewares:u})=>!t||!x?null:e.jsx("div",{className:"absolute inset-0 bg-neutral-900/40 backdrop-blur-[2px] flex items-center justify-center z-[9999] p-4 font-sans",children:e.jsxs("div",{className:"bg-white rounded-xl shadow-2xl overflow-hidden max-w-sm w-full border border-gray-100 flex flex-col scale-100 pointer-events-auto",children:[e.jsxs("div",{className:"px-5 py-4 border-b border-gray-150/60 bg-gray-50 flex justify-between items-center shrink-0",children:[e.jsx("h3",{className:"font-bold text-gray-800 text-sm",children:"选择课件入口页面"}),e.jsx("button",{onClick:()=>r(!1),className:"text-gray-400 hover:text-gray-650 transition-colors text-xl font-light cursor-pointer",children:"×"})]}),e.jsxs("div",{className:"p-5 flex-1 min-h-0 space-y-3",children:[e.jsx("p",{className:"text-xs text-gray-600 leading-relaxed font-medium",children:"ZIP压缩包中含有多个HTML文件,请选择一个作为课件入口:"}),e.jsx("div",{className:"max-h-60 overflow-y-auto border border-gray-200 rounded-lg p-2 bg-gray-50 space-y-1",children:l.map(d=>e.jsxs("button",{onClick:async()=>{try{const a=await fetch("/api/courseware/confirm",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({uuid:x.uuid,name:x.name,entry:d})});if(a.ok){const n=await a.json();c({coursewareUuid:n.uuid,resourceId:""}),r(!1),u({force:!0})}}catch(a){console.error("Failed to confirm entry point:",a)}},className:"w-full text-left p-2 rounded hover:bg-indigo-50 hover:text-indigo-700 text-xs font-semibold font-mono truncate transition-all cursor-pointer",children:["📄 ",d]},d))})]}),e.jsx("div",{className:"px-5 py-3 border-t border-gray-100 bg-gray-50 flex justify-end gap-2 text-xs shrink-0",children:e.jsx("button",{onClick:()=>r(!1),className:"px-4 py-2 text-gray-500 hover:bg-gray-100 rounded-lg transition-colors font-medium border border-gray-200 cursor-pointer",children:"取消"})})]})}),Xa=({isOpen:t,onClose:r,element:x,coursewares:l=[],fetchCoursewares:c,onApplyTemporary:u,onSavePermanent:d})=>{const a=Bs.useMemo(()=>{if(!x?.data)return{title:"Interactive Courseware"};try{return typeof x.data=="string"?JSON.parse(x.data):x.data}catch{return{title:"Interactive Courseware"}}},[x]),[n,g]=i.useState(a.title||"Interactive Courseware"),[j,P]=i.useState(Number(a.width)||800),[X,k]=i.useState(Number(a.height)||600),[M,b]=i.useState(a.coursewareUuid||""),[N,y]=i.useState(a.code||""),[f,_]=i.useState(!0),[F,L]=i.useState(!1),[ie,U]=i.useState(null);if(i.useEffect(()=>{t&&x&&(g(a.title||"Interactive Courseware"),P(Number(a.width)||800),k(Number(a.height)||600),b(a.coursewareUuid||""),y(a.code||""),_(!0),U(null))},[t,x,a]),i.useEffect(()=>{if(!t)return;const J=z=>{z.key==="Escape"&&r()};return window.addEventListener("keydown",J),()=>window.removeEventListener("keydown",J)},[t,r]),!t||!x)return null;const xe=async J=>{L(!0),U(null);try{const z=new FileReader;z.onload=async T=>{const R=T.target?.result;try{const p=await fetch("/api/courseware/upload",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({name:J.name.replace(/\.[^/.]+$/,""),filename:J.name,base64Data:R})}),C=await p.json();p.ok&&C.uuid?(b(C.uuid),c&&await c({force:!0})):U(C.error||"课件上传失败")}catch(p){U(p.message||"网络异常")}finally{L(!1)}},z.readAsDataURL(J)}catch(z){U(z.message||"读取文件失败"),L(!1)}},ee=async()=>{const J={...a,title:n.trim()||"Interactive Courseware",width:Math.max(300,j),height:Math.max(200,X),coursewareUuid:M||void 0,code:M?void 0:N};f?u(x.id,J):d&&await d(x.id,J),r()};return e.jsx("div",{className:"fixed inset-0 z-[100] flex items-center justify-center p-4 bg-black/60 backdrop-blur-xs select-none animate-in fade-in duration-150",onPointerDown:J=>{J.target===J.currentTarget&&r()},role:"dialog","aria-modal":"true","aria-labelledby":"courseware-props-modal-title",children:e.jsxs("div",{className:"w-full max-w-xl bg-surface border border-theme rounded-2xl shadow-2xl flex flex-col overflow-hidden text-main font-sans animate-in zoom-in-95 duration-150",onPointerDown:J=>J.stopPropagation(),children:[e.jsxs("div",{className:"px-5 py-4 border-b border-theme bg-surface-secondary/50 flex items-center justify-between",children:[e.jsxs("div",{className:"flex items-center gap-2.5",children:[e.jsx("span",{className:"p-2 rounded-xl bg-primary-theme/10 text-primary-theme border border-primary-theme/20",children:e.jsx(qs,{size:18})}),e.jsxs("div",{children:[e.jsx("h3",{id:"courseware-props-modal-title",className:"text-sm font-bold text-main leading-tight",children:"课堂课件属性临时调整"}),e.jsx("p",{className:"text-xs text-muted mt-0.5",children:"实时调节互动课件展示属性与数据源"})]})]}),e.jsx("button",{onClick:r,className:"p-1.5 rounded-lg text-muted hover:text-main hover:bg-surface-secondary transition-colors cursor-pointer",title:"关闭窗口",children:e.jsx(Jt,{size:16})})]}),e.jsxs("div",{className:"p-5 space-y-4 max-h-[75vh] overflow-y-auto",children:[e.jsxs("div",{children:[e.jsx("label",{className:"block text-xs font-semibold text-muted mb-1.5",children:"课件展示标题"}),e.jsx("input",{type:"text",value:n,onChange:J=>g(J.target.value),placeholder:"请输入课件窗口标题...",className:"w-full px-3 py-2 text-xs bg-surface border border-theme hover:border-primary-theme/60 rounded-xl focus:outline-none focus:ring-2 focus:ring-primary-theme/20 text-main transition-all font-medium"})]}),e.jsxs("div",{className:"bg-surface-secondary/40 p-3.5 rounded-xl border border-theme space-y-2.5",children:[e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsxs("span",{className:"text-xs font-semibold text-main flex items-center gap-1.5",children:[e.jsx(Ws,{size:13,className:"text-muted"}),"画布中窗口尺寸 (宽 × 高)"]}),e.jsxs("div",{className:"flex items-center gap-1",children:[e.jsx("button",{type:"button",onClick:()=>{P(800),k(600)},className:"px-2 py-0.5 rounded-md text-2xs bg-surface border border-theme text-muted hover:text-primary-theme hover:border-primary-theme/50 transition-colors",children:"800×600 (4:3)"}),e.jsx("button",{type:"button",onClick:()=>{P(960),k(540)},className:"px-2 py-0.5 rounded-md text-2xs bg-surface border border-theme text-muted hover:text-primary-theme hover:border-primary-theme/50 transition-colors",children:"960×540 (16:9)"}),e.jsx("button",{type:"button",onClick:()=>{P(1200),k(675)},className:"px-2 py-0.5 rounded-md text-2xs bg-surface border border-theme text-muted hover:text-primary-theme hover:border-primary-theme/50 transition-colors",children:"1200×675 (大屏)"})]})]}),e.jsxs("div",{className:"grid grid-cols-2 gap-3",children:[e.jsxs("div",{children:[e.jsx("label",{className:"block text-2xs text-muted mb-1",children:"宽度 (Width, px)"}),e.jsx("input",{type:"number",min:300,max:2400,step:20,value:j,onChange:J=>P(parseInt(J.target.value,10)||300),className:"w-full px-2.5 py-1.5 text-xs font-mono bg-surface border border-theme rounded-lg focus:outline-none focus:ring-1 focus:ring-primary-theme text-main"})]}),e.jsxs("div",{children:[e.jsx("label",{className:"block text-2xs text-muted mb-1",children:"高度 (Height, px)"}),e.jsx("input",{type:"number",min:200,max:1800,step:20,value:X,onChange:J=>k(parseInt(J.target.value,10)||200),className:"w-full px-2.5 py-1.5 text-xs font-mono bg-surface border border-theme rounded-lg focus:outline-none focus:ring-1 focus:ring-primary-theme text-main"})]})]})]}),e.jsxs("div",{className:"space-y-3",children:[e.jsx("label",{className:"block text-xs font-semibold text-muted",children:"关联课件源 (选择现有课件包或使用独立代码)"}),e.jsxs("div",{className:"flex gap-2",children:[e.jsxs("select",{value:M,onChange:J=>b(J.target.value),className:"flex-1 px-3 py-2 text-xs bg-surface border border-theme hover:border-primary-theme/60 rounded-xl focus:outline-none focus:ring-1 focus:ring-primary-theme text-main font-medium",children:[e.jsx("option",{value:"",children:"-- 使用下方手写 HTML/JS 代码 --"}),l.map(J=>e.jsxs("option",{value:J.uuid,children:["📦 [互动课件] ",J.name]},J.id||J.uuid))]}),e.jsxs("label",{className:`px-3 py-2 text-xs rounded-xl border border-primary-theme/30 bg-primary-theme/5 hover:bg-primary-theme/10 text-primary-theme font-semibold flex items-center gap-1.5 transition-colors cursor-pointer shrink-0 ${F?"opacity-50 pointer-events-none":""}`,title:"上传本地互动课件包 (.zip / .html)",children:[F?e.jsx(Ct,{size:13,className:"animate-spin"}):e.jsx(as,{size:13}),e.jsx("span",{children:F?"正在上传...":"上传新课件"}),e.jsx("input",{type:"file",accept:".zip,.html,.htm",className:"hidden",onChange:J=>{const z=J.target.files?.[0];z&&xe(z)}})]})]}),ie&&e.jsxs("div",{className:"p-2.5 rounded-lg bg-rose-500/10 border border-rose-500/20 text-rose-500 text-xs flex items-center gap-2",children:[e.jsx(qt,{size:14,className:"shrink-0"}),e.jsx("span",{children:ie})]}),!M&&e.jsxs("div",{children:[e.jsxs("div",{className:"flex items-center justify-between mb-1.5",children:[e.jsxs("span",{className:"text-2xs text-muted flex items-center gap-1 font-semibold",children:[e.jsx(Ai,{size:12}),"自定义沙箱代码 (HTML / JavaScript):"]}),e.jsx("span",{className:"text-2xs text-muted/80",children:"已自动注入 LMS Bridge SDK"})]}),e.jsx("textarea",{rows:5,value:N,onChange:J=>y(J.target.value),placeholder:"<!DOCTYPE html><html><body><h1>互动演示</h1>...</body></html>",className:"w-full px-3 py-2 text-xs font-mono bg-surface-secondary/70 border border-theme rounded-xl focus:outline-none focus:ring-1 focus:ring-primary-theme text-main"})]})]}),e.jsx("div",{className:"p-3.5 rounded-xl border border-emerald-500/30 bg-emerald-500/5 space-y-2",children:e.jsxs("label",{className:"flex items-start gap-2.5 cursor-pointer",children:[e.jsx("input",{type:"checkbox",checked:f,onChange:J=>_(J.target.checked),className:"mt-0.5 rounded border-emerald-400 text-emerald-600 focus:ring-emerald-500 cursor-pointer"}),e.jsxs("div",{className:"flex-1",children:[e.jsxs("span",{className:"text-xs font-bold text-emerald-800 dark:text-emerald-300 flex items-center gap-1.5",children:[e.jsx(Fi,{size:14,className:"text-emerald-600"}),"仅在本次课堂临时生效(推荐,不覆盖课程设置中的课件内容)"]}),e.jsx("p",{className:"text-2xs text-emerald-700/80 dark:text-emerald-400/80 mt-0.5",children:f?"当前修改仅即时同步给本堂课的学生设备,不会修改原教案数据库,其他平行班级复用不受影响。":"警告:已取消临时保护,点击应用后将直接持久化更新原课程教案中的课件配置!"})]})]})})]}),e.jsxs("div",{className:"px-5 py-3 border-t border-theme bg-surface-secondary/30 flex items-center justify-between",children:[e.jsx("span",{className:"text-xs text-muted",children:f?"⚡ 即时生效,安全无污染":"💾 将同步写回课程数据库"}),e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("button",{type:"button",onClick:r,className:"px-3.5 py-1.5 rounded-xl text-xs font-semibold text-muted hover:text-main hover:bg-surface-secondary border border-transparent transition-colors cursor-pointer",children:"取消"}),e.jsxs("button",{type:"button",onClick:ee,className:"px-4 py-1.5 rounded-xl text-xs font-bold bg-primary-theme hover:bg-primary-theme/90 text-white shadow-sm flex items-center gap-1.5 transition-transform active:scale-95 cursor-pointer",children:[e.jsx(Li,{size:13}),e.jsx("span",{children:f?"临时应用至本课":"保存并更新课程"})]})]})]})]})})},Ht="ABCDEFGHIJKLMNOPQRSTUVWXYZ",qa=({data:t,lessonId:r,elementId:x})=>{const[l,c]=i.useState({}),[u,d]=i.useState(null),[a,n]=i.useState(null),[g,j]=i.useState(!1),[P,X]=i.useState(null),[k,M]=i.useState(t.submissions||{});i.useEffect(()=>{M(t.submissions||{})},[t.submissions]),i.useEffect(()=>{if(!u||u.role==="student"||!r)return;let v=!1;return fetch(`/api/lessons/${encodeURIComponent(r)}/quiz-submissions`).then(w=>w.ok?w.json():null).then(w=>{if(v||!w?.quizzes)return;const q=w.quizzes.find(I=>I.elementId===(x||t.id));q?.submissions&&M(I=>({...I,...q.submissions}))}).catch(()=>{}),()=>{v=!0}},[u,r,x]),i.useEffect(()=>{let v=!1;return fetch("/api/students?pageSize=all").then(q=>q.ok?q.json():{data:[]}).then(q=>{if(v)return;const I=ui(q),D={};for(const ne of I)D[ne.id]=ne.name;c(D)}).catch(()=>{}),(async()=>{try{let q=await fetch("/api/auth/session").catch(()=>null);if((!q||!q.ok)&&(q=await fetch("/api/auth/me").catch(()=>null)),q&&q.ok&&!v){const I=await q.json(),D=I.session||I;D&&typeof D=="object"&&!Array.isArray(D)&&D.role&&d({id:D.id||D.userId,role:D.role,studentId:D.studentId||D.userId||D.id})}}catch{}})(),()=>{v=!0}},[]);const b=Object.entries(k),N=typeof t.correctIndex=="number"?t.correctIndex:void 0,y=typeof t.passScore=="number"?t.passScore:60,f=u?.studentId||u?.id,_=f?k[f]:null,F=typeof window<"u"&&(new URLSearchParams(window.location?.search||"").get("mode")==="student_live"||(window.location?.hash||"").includes("student_live")),L=u?.role==="student"||F,ie=!!_||!!P,U=!L||ie,xe=v=>{if(typeof v=="number"&&!isNaN(v))return v;if(typeof v=="string"){const w=parseFloat(v);return isNaN(w)?null:w}return null},ee=v=>{if(typeof v.answer=="number")return v.answer;if(typeof v.answer=="string"){const w=parseInt(v.answer,10);return isNaN(w)?void 0:w}if(typeof v.optionIndex=="number")return v.optionIndex},J=async()=>{if(a===null||g)return;j(!0);const v=Ht[a]||String(a),w=(t.options||[])[a];let q=v;t.correctAnswer&&!Ht.includes(t.correctAnswer.toUpperCase())&&w&&(q=w);try{const I=r||"current",D=x||t.id||"quiz",ne=await fetch(`/api/lessons/${encodeURIComponent(I)}/quiz-submit`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({elementId:D,answer:q})}),ce=await ne.json().catch(()=>null);if(ne.ok&&ce?.success){X({isCorrect:ce.isCorrect,score:ce.score,answer:v});const re=ce.studentId||f||"me";M(te=>({...te,[re]:{answer:a,score:ce.score,time:Date.now()}}))}}catch{}finally{j(!1)}},z=b.map(([v,w])=>{const q=ee(w),I=xe(w.score),D=q!==void 0&&N!==void 0?q===N:I!==null?I>=y:!1;return{sid:v,v:w,answerIdx:q,scoreNum:I,isCorrect:D}}),T=b.length,R=z.filter(v=>v.isCorrect).length,p=T>0?Math.round(R/T*100):0,C=z.map(v=>v.scoreNum).filter(v=>v!==null),m=C.length>0?C.reduce((v,w)=>v+w,0)/C.length:null,O=v=>{if(v==null)return"-";const w=typeof v=="number"?v:Number(v),q=isNaN(w)?new Date(String(v)):new Date(w);return isNaN(q.getTime())?"-":q.toLocaleTimeString()};return e.jsxs("div",{className:"max-w-2xl mx-auto space-y-6",children:[e.jsx("h3",{className:"text-xl font-bold text-gray-800","data-testid":"quiz-question",children:t.question}),P&&e.jsxs("div",{"data-testid":"quiz-feedback",className:`p-4 rounded-xl border flex items-center justify-between text-sm font-bold ${P.isCorrect?"bg-emerald-50 border-emerald-300 text-emerald-800":"bg-rose-50 border-rose-300 text-rose-800"}`,children:[e.jsx("span",{children:P.isCorrect?`🎉 回答正确!得分:${P.score} 分`:`❌ 回答错误。得分:${P.score} 分`}),e.jsx("span",{className:"text-xs font-normal",children:"提交已实时同步至教师大屏"})]}),e.jsx("div",{className:"flex flex-col gap-3",children:(t.options||[]).map((v,w)=>{const q=a===w,I=N===w;let D="bg-gray-50 border-gray-200 text-gray-700";return U&&I?D="bg-green-50 border-green-300 text-green-800":q?D="bg-indigo-50 border-indigo-400 text-indigo-900 ring-2 ring-indigo-200 shadow-xs":L&&!ie&&(D="bg-white hover:bg-gray-50 border-gray-200 text-gray-800 cursor-pointer"),e.jsxs("div",{"data-testid":`quiz-option-${w}`,onClick:()=>{L&&!ie&&n(w)},className:`px-5 py-4 text-left rounded-xl text-base border-2 transition-all ${D}`,children:[e.jsxs("span",{className:"font-bold text-indigo-600 mr-3",children:[Ht[w],"."]}),v,U&&I&&e.jsx("span",{className:"ml-2 text-xs font-bold text-green-600",children:"✓ 正确答案"})]},w)})}),L&&!ie&&e.jsx("div",{className:"pt-2 flex justify-end",children:e.jsx("button",{"data-testid":"quiz-submit-btn",disabled:a===null||g,onClick:J,className:"px-6 py-2.5 bg-indigo-600 hover:bg-indigo-700 disabled:opacity-50 disabled:cursor-not-allowed text-white font-bold text-sm rounded-xl shadow-sm transition-all cursor-pointer",children:g?"提交中...":"提交答案"})}),!L&&(T===0?e.jsx("div",{className:"mt-4 p-4 bg-gray-50 rounded-xl text-center text-sm text-gray-400",children:"暂无学生提交"}):e.jsxs("div",{className:"mt-4 space-y-4",children:[e.jsxs("div",{className:"grid grid-cols-4 gap-3","data-testid":"quiz-summary",children:[e.jsxs("div",{className:"bg-gray-50 rounded-xl p-3 text-center",children:[e.jsx("div",{className:"text-xs text-gray-400",children:"提交"}),e.jsx("div",{className:"text-xl font-bold text-gray-700","data-testid":"quiz-stat-submitted",children:T})]}),e.jsxs("div",{className:"bg-green-50 rounded-xl p-3 text-center",children:[e.jsx("div",{className:"text-xs text-gray-400",children:"通过"}),e.jsx("div",{className:"text-xl font-bold text-green-600","data-testid":"quiz-stat-passed",children:R})]}),e.jsxs("div",{className:"bg-indigo-50 rounded-xl p-3 text-center",children:[e.jsx("div",{className:"text-xs text-gray-400",children:"通过率"}),e.jsxs("div",{className:"text-xl font-bold text-indigo-600",children:[p,"%"]})]}),e.jsxs("div",{className:"bg-amber-50 rounded-xl p-3 text-center",children:[e.jsx("div",{className:"text-xs text-gray-400",children:"均分"}),e.jsx("div",{className:"text-xl font-bold text-amber-600",children:m!==null?m.toFixed(1):"-"})]})]}),e.jsx("div",{className:"overflow-x-auto border border-gray-200 rounded-xl",children:e.jsxs("table",{className:"w-full text-sm","data-testid":"quiz-submissions-table",children:[e.jsx("thead",{className:"bg-gray-50 text-gray-500 text-xs uppercase",children:e.jsxs("tr",{children:[e.jsx("th",{className:"px-4 py-2 text-left",children:"学生"}),e.jsx("th",{className:"px-4 py-2 text-left",children:"答案"}),e.jsx("th",{className:"px-4 py-2 text-right",children:"得分"}),e.jsx("th",{className:"px-4 py-2 text-right",children:"提交时间"})]})}),e.jsx("tbody",{className:"divide-y divide-gray-100",children:z.map(({sid:v,v:w,answerIdx:q,scoreNum:I,isCorrect:D})=>{const ne=q!==void 0&&q>=0&&q<Ht.length?Ht[q]:"-",ce=I!==null?I:D?100:0,re=l[v]||v;return e.jsxs("tr",{className:"hover:bg-gray-50","data-testid":`quiz-row-${v}`,children:[e.jsx("td",{className:"px-4 py-2 font-medium text-gray-700",children:re}),e.jsxs("td",{className:`px-4 py-2 font-mono ${D?"text-green-600 font-bold":"text-red-500"}`,children:[ne,D?" ✓":""]}),e.jsx("td",{className:`px-4 py-2 text-right font-mono font-bold ${ce>=y?"text-green-600":"text-gray-600"}`,children:ce}),e.jsx("td",{className:"px-4 py-2 text-right text-gray-500 text-xs",children:O(w.time??w.timestamp)})]},v)})})]})})]}))]})};fi.registerHostBuiltin("quiz",qa);const et=({title:t="教师已开启全班专注锁定,当前为只读演示视图"})=>e.jsx("div",{"data-testid":"whiteboard-readonly-lock-cover",className:"absolute inset-0 z-50 bg-transparent cursor-not-allowed select-none",style:{pointerEvents:"auto"},onClick:r=>{r.stopPropagation(),r.preventDefault()},onPointerDown:r=>{r.stopPropagation(),r.preventDefault()},onMouseDown:r=>{r.stopPropagation(),r.preventDefault()},onTouchStart:r=>{r.stopPropagation(),r.preventDefault()},title:t});let tt={data:[],ts:0,inflight:null};const Ya=[{id:"page-0",title:"P1 · 引入导入",order:0},{id:"page-1",title:"P2 · 核心讲解",order:1},{id:"page-2",title:"P3 · 互动练习",order:2}],Or=4,oo=i.forwardRef(({lessonId:t,elements:r,onElementAdd:x,onElementUpdate:l,onElementDelete:c,onClearBoard:u,onRefresh:d,enableAutoAI:a,activeSegmentId:n,onSegmentSync:g,initialPage:j,classroomTools:P,onExecuteTool:X,userRole:k="teacher",isEditMode:M=!0,readOnly:b=!1,classId:N,broadcastFullscreen:y=!1,fullscreenBroadcastClassId:f=null,followRemoteFullscreen:_=!1,onFullscreenSync:F,hidePageBar:L=!1,onPagesStateChange:ie,onElementDragChange:U,onElementDropCheck:xe},ee)=>{const[J,z]=i.useState({}),T=i.useMemo(()=>{const s=Array.isArray(r)?r:[];return Object.keys(J).length===0?s:s.map(h=>J[h.id]||h)},[r,J]),R=xi(s=>s.theme),p=hi(s=>s.scale)/100;i.useEffect(()=>{Hr.setTheme(R)},[R]);const C=Hr.getTokens(),m=R==="dark"||R==="chalkboard",O=Vr(s=>s.extensionPoints.get("whiteboard.renderer")),[v,w]=i.useState("cursor"),[q,I]=i.useState("#facc15"),[D,ne]=i.useState(0),[ce,re]=i.useState(!0),[te,B]=i.useState(null),K=i.useRef(null);i.useEffect(()=>{K.current=te},[te]);const ye=i.useRef(null),[Y,le]=i.useState(null),be=i.useRef(null);i.useEffect(()=>{be.current=Y},[Y]);const je=i.useRef(null),[Me,Ie]=i.useState(void 0),E=i.useRef(Me);i.useEffect(()=>{E.current=Me},[Me]);const[se,pe]=i.useState(!1),[G,ue]=i.useState(Ya),[ht,St]=i.useState(!1),[hn,cs]=i.useState(null),[mn,Ys]=i.useState(""),[pn,Is]=i.useState(null);i.useEffect(()=>{ie?.({pages:G,currentPage:D})},[G,D,ie]),i.useEffect(()=>{const s=T.find(h=>h.type==="page_meta");if(s){const h=Je(s);Array.isArray(h?.pages)&&h.pages.length>0&&ue(h.pages)}},[r]);const Js=i.useRef(!1);i.useEffect(()=>{if(Js.current||!Array.isArray(G)||G.length===0)return;const s=Number(j);Number.isFinite(s)&&s>0&&s<G.length&&ne(s),Js.current=!0},[G]);const Os=i.useCallback(s=>xn(s,D,G),[G,D]),Us=i.useMemo(()=>ia(T,D,G,n),[T,D,G,n]),mt=i.useCallback(()=>Us,[Us]),ds=i.useRef(null),fn=i.useCallback(s=>{k!=="teacher"||!t||(ds.current&&clearTimeout(ds.current),ds.current=setTimeout(()=>{fetch(`/api/classroom/sessions/${encodeURIComponent(t)}/view-state`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({currentPage:s})}).catch(()=>{})},500))},[k,t]);i.useEffect(()=>{b&&(he(null),Ce(null),w("cursor"),st(null),us(!1),hs(null))},[b]);const Et=s=>{const h=T.find(o=>o.type==="page_meta");h&&l?l(h.id,{pages:s}):x&&x("page_meta",{pages:s}),Ne.current&&Ne.current.emit("whiteboard-update",{roomId:t,type:"page-meta-update",payload:{pages:s}})},Gs=s=>{ne(s),Is(null),Ne.current&&Ne.current.emit("whiteboard-update",{roomId:t,type:"page-change",payload:{page:s}}),fn(s)},Ks=s=>{const{newPages:h,newIndex:o}=aa(G,s);ue(h),ne(o),Et(h),Ne.current&&Ne.current.emit("whiteboard-update",{roomId:t,type:"page-change",payload:{page:o}})},Vs=(s,h)=>{if(!h.trim()){cs(null);return}const o=oa(G,s,h);ue(o),Et(o),cs(null),Ys("")},Zs=s=>{const h=G[s];if(!h)return;const o=la(G,s);if(!o)return;const{newPages:$,newIndex:A,newPage:H}=o;ue($),ne(A),Et($),T.filter(Z=>Z.type!=="page_meta"&&(()=>{try{const de=JSON.parse(Z.data);return(de.page??0)===s||de.pageId===h.id}catch{return s===0}})()).forEach(Z=>{try{const de=JSON.parse(Z.data);x&&x(Z.type,{...de,page:A,pageId:H.id,x:(de.x??100)+20,y:(de.y??100)+20})}catch(de){console.error("Failed duplicating page element:",de)}})},Qs=s=>{if(G.length<=1){We({title:"无法删除",message:"至少需要保留一个白板页面!",type:"alert",onConfirm:()=>{}});return}const h=G[s],o=T.filter(A=>A.type!=="page_meta"&&(()=>{try{const H=JSON.parse(A.data);return(H.page??0)===s||H.pageId===h.id}catch{return s===0}})()),$=()=>{c&&o.forEach(V=>c(V.id));const A=G.filter((V,Z)=>Z!==s).map((V,Z)=>({...V,order:Z}));ue(A);const H=Math.min(D,A.length-1);ne(H),Et(A)};o.length>0?We({title:"确认删除白板页面",message:`页面 [${h.title}] 包含 ${o.length} 个组件,删除页面将同时清理该页面的组件,是否确定删除?`,type:"confirm",onConfirm:$}):$()},er=(s,h)=>{const o=ca(G,s,h);if(!o)return;const{newPages:$,targetIndex:A}=o;ue($),D===s?ne(A):D===A&&ne(s),Et($)},[Te,st]=i.useState(null),[tr,us]=i.useState(!1),bn=i.useRef(null),[zt,sr]=i.useState({width:0,height:0}),ve=i.useRef(null),[xs,we]=i.useState(!1),Ne=i.useRef(null),[gn,rr]=i.useState({}),[Ia,Ja]=i.useState({}),[Oa,Ua]=i.useState({}),[Ga,Ka]=i.useState({}),[yn,nr]=i.useState({});i.useEffect(()=>{if(!t)return;let s=!1;return fetch(`/api/lessons/${encodeURIComponent(t)}/quiz-counts`).then(h=>h.ok?h.json():null).then(h=>{if(!h?.quizzes||s)return;const o={};for(const $ of h.quizzes)o[$.elementId]=$.submissionCount;nr(o)}).catch(()=>{}),()=>{s=!0}},[t]),Wi({types:["quiz.answered"]},s=>{!s.elementId||s.lessonId!==t||nr(h=>({...h,[s.elementId]:(h[s.elementId]??0)+1}))});const[wn,hs]=i.useState(null),[jn,vn]=i.useState(null),ir=Lr(s=>s.remoteFullscreenElementId),Rt=_&&!!ir,rt=Rt?ir:wn,Nn=!Rt,ar=Lr(s=>s.remoteBrowserFullscreenElementId),Gt=_&&!!ar,$t=Gt?ar:jn,kn=!Gt,pt=ha({elementId:$t,enableNativeFullscreen:!Gt,onChange:s=>{vn(s),y&&Ne.current&&Ne.current.emit("teacher-broadcast-fullscreen",{classId:f,lessonId:t,elementId:s,mode:"browser"})}});i.useEffect(()=>{$t&&!T.some(s=>s.id===$t)&&pt.exit()},[$t,T,pt]);const or=i.useRef(F);i.useEffect(()=>{or.current=F},[F]);const at=s=>{hs(s),F?.(s),y&&Ne.current&&Ne.current.emit("teacher-broadcast-fullscreen",{classId:f,lessonId:t,elementId:s,mode:"board"})};i.useEffect(()=>{if(y)return()=>{or.current?.(null);const s={classId:f,lessonId:t,elementId:null};Ne.current?.emit("teacher-broadcast-fullscreen",{...s,mode:"board"}),Ne.current?.emit("teacher-broadcast-fullscreen",{...s,mode:"browser"})}},[y,f,t]);const lr=!!rt&&!T.some(s=>s.id===rt);i.useEffect(()=>{!lr||Rt||(hs(null),F?.(null),y&&Ne.current&&Ne.current.emit("teacher-broadcast-fullscreen",{classId:f,lessonId:t,elementId:null}))},[lr,Rt,y,f,t,F]);const[_t,ms]=i.useState(null),He=i.useRef(new Map),[cr,ft]=i.useState(0),dt=i.useCallback((s,h)=>{He.current.set(s,h),ft(o=>o+1)},[]);i.useCallback(s=>{He.current.delete(s)&&ft(h=>h+1)},[]),i.useEffect(()=>{He.current.clear(),ft(s=>s+1)},[t]),i.useEffect(()=>{if(He.current.size!==0){for(const s of r){const h=He.current.get(s.id);if(!h)continue;const o=Je(s,null);if(!o){He.current.delete(s.id);continue}const $=Object.keys(h);Ls(o,h,$)&&He.current.delete(s.id)}ft(s=>s+1)}},[r]);const dr=i.useRef(void 0),{autoTileEnabled:Le,handleToggleAutoTile:Cn,tilingSplitters:Sn,activeSplitterDrag:zn,handleSplitterPointerDown:$n,applyAutoTiling:ur,applyAutoTilingForElements:Mt,swapTileElements:xr,insertTileInDirection:hr}=Ha({containerSize:zt,safeElements:T,getCurrentPageElements:mt,onElementUpdate:l,lessonId:t,readOnly:b,setLocalGeometry:dt,localGeometryRef:He,localGeometryVersion:cr,currentPage:D,activeSegmentId:n,pages:G,tileSplitPreferenceRef:E,setIsSyncing:we});i.useEffect(()=>{dr.current=Mt,ye.current=xr,je.current=hr},[Mt,xr,hr]);const ze=i.useRef(null),ke=i.useRef(null),bt=i.useRef(null),[me,mr]=i.useState(null),he=s=>{k==="teacher"&&mr(s)},[Tt,Mn]=i.useState(null),Ce=s=>{k==="teacher"&&Mn(s)},[pr,fr]=i.useState(null),[gt,ps]=i.useState(null),At=i.useRef(null),[Tn,We]=i.useState(null),[Dn,br]=i.useState(""),[gr,fs]=i.useState(null),[yt,nt]=i.useState(null),[Kt,wt]=i.useState(null),[bs,yr]=i.useState(null),[wr,gs]=i.useState({}),[jr,ys]=i.useState({}),[vr,ws]=i.useState([]),[Pn,En]=i.useState([]),[Rn,_n]=i.useState(null),[An,Nr]=i.useState(!1),Ft=i.useRef(null),Lt=async s=>{const h=Date.now();if(!s?.force&&tt.data.length>0&&h-tt.ts<3e4){ws(tt.data);return}if(tt.inflight&&!s?.force){const A=await tt.inflight;ws(A);return}const $=(async()=>{try{const A=await fetch("/api/courseware");if(A.ok){const H=await A.json();return tt={data:Array.isArray(H)?H:[],ts:Date.now(),inflight:null},ws(tt.data),tt.data}}catch(A){console.error("Error fetching coursewares:",A)}finally{tt.inflight=null}return tt.data})();tt.inflight=$,await $};i.useEffect(()=>{if(me){const s=T.find(h=>h.id===me);s?(s.type==="html-applet"?Ft.current!==me&&(Ft.current=me,Lt()):Ft.current=null,nt(Je(s,{}))):(Ft.current=null,nt(null),wt(null))}else Ft.current=null,nt(null),wt(null)},[me,r]);const jt=async s=>{const h=T.find(V=>V.id===me);if(!h)return;const $={...Je(h,{}),...s},A=h.data,H=JSON.stringify($);if(A!==H&&(gs(V=>{const Z=V[h.id]?[...V[h.id]]:[];return Z.length>=30&&Z.shift(),Z.push(A),{...V,[h.id]:Z}}),ys(V=>({...V,[h.id]:[]}))),l){we(!0);try{await l(h.id,$),ae.publish({id:oe(),type:"whiteboard.element_updated",source:"whiteboard",payload:{lessonId:t},timestamp:Date.now(),correlationId:t}),d&&d()}catch(V){console.error("更新属性失败:",V)}finally{we(!1)}}},Fn=(s,h)=>{const o=T.find(A=>A.id===s);if(!o)return;const $=JSON.stringify(h);z(A=>({...A,[s]:{...o,data:$}})),ae.publish({id:oe(),type:"whiteboard.element_updated",source:"whiteboard",payload:{lessonId:t,elementId:s,temporary:!0},timestamp:Date.now(),correlationId:t})},Ln=async(s,h)=>{if(z(o=>{const $={...o};return delete $[s],$}),l){we(!0);try{await l(s,h),ae.publish({id:oe(),type:"whiteboard.element_updated",source:"whiteboard",payload:{lessonId:t,elementId:s},timestamp:Date.now(),correlationId:t}),d&&d()}catch(o){console.error("保存课件属性失败:",o)}finally{we(!1)}}},Bn=async()=>{if(!me)return;const s=T.find(H=>H.id===me);if(!s)return;const h=wr[me]||[];if(h.length===0)return;const o=h[h.length-1],$=h.slice(0,h.length-1),A=s.data;if(ys(H=>{const V=H[me]?[...H[me]]:[];return V.push(A),{...H,[me]:V}}),gs(H=>({...H,[me]:$})),l){we(!0);try{const H=JSON.parse(o);nt(H),await l(me,H),ae.publish({id:oe(),type:"whiteboard.element_updated",source:"whiteboard",payload:{lessonId:t},timestamp:Date.now(),correlationId:t}),d&&d()}catch(H){console.error("撤销修改失败:",H)}finally{we(!1)}}},Hn=async()=>{if(!me)return;const s=T.find(H=>H.id===me);if(!s)return;const h=jr[me]||[];if(h.length===0)return;const o=h[h.length-1],$=h.slice(0,h.length-1),A=s.data;if(gs(H=>{const V=H[me]?[...H[me]]:[];return V.push(A),{...H,[me]:V}}),ys(H=>({...H,[me]:$})),l){we(!0);try{const H=JSON.parse(o);nt(H),await l(me,H),ae.publish({id:oe(),type:"whiteboard.element_updated",source:"whiteboard",payload:{lessonId:t},timestamp:Date.now(),correlationId:t}),d&&d()}catch(H){console.error("重做修改失败:",H)}finally{we(!1)}}},Wn=(s,h)=>{nt(o=>o&&{...o,[s]:h})},Xn=(s,h)=>{jt({[s]:h})},kr=s=>{nt(h=>h&&{...h,...s}),jt(s)},qn=(s,h)=>{const o=parseFloat(h);isNaN(o)||jt({[s]:o})},Yn=(s,h)=>{nt(o=>{if(!o)return o;const $=[...o.options||[]];return $[s]=h,{...o,options:$}})},In=(s,h)=>{if(!yt)return;const o=[...yt.options||[]];o[s]=h,jt({options:o})},Jn=()=>{if(!yt)return;const s=yt.options||[],o="ABCDEFGHIJKLMNOPQRSTUVWXYZ"[s.length]||`Option ${s.length+1}`,$=[...s,`选项 ${o}`];nt(A=>A&&{...A,options:$}),jt({options:$})},On=s=>{if(!yt)return;const h=(yt.options||[]).filter((o,$)=>$!==s);nt(o=>o&&{...o,options:h}),jt({options:h})};i.useEffect(()=>{const s=()=>{Ce(null)};return window.addEventListener("click",s),()=>window.removeEventListener("click",s)},[]);const Vt=i.useRef(U);i.useEffect(()=>{Vt.current=U},[U]);const Cr=i.useRef(xe);i.useEffect(()=>{Cr.current=xe},[xe]);const js=(s,h,o)=>{if(k!=="teacher")return;s.preventDefault();const $=o.x??0,A=o.y??0,H={id:h,currentX:$,currentY:A,startPointerX:s.clientX,startPointerY:s.clientY,data:o};ze.current=H,ms(H);const V=T.find(Z=>Z.id===h);Vt.current?.({elementId:h,elementType:V?.type||"unknown",elementData:o,clientX:s.clientX,clientY:s.clientY,initialPage:D,initialSegmentId:o.segmentId||n})},vs=s=>{},Ns=async s=>{},Zt=(s,h,o,$,A,H,V)=>{if(k!=="teacher")return;s.preventDefault(),s.stopPropagation();const Z={id:h,corner:o,startX:s.clientX,startY:s.clientY,initialX:$,initialY:A,initialWidth:H,initialHeight:V},de={id:h,x:$,y:A,width:H,height:V};ke.current=Z,bt.current=de,fr(Z),ps(de)},Qt=s=>{},es=async s=>{};i.useEffect(()=>{if(!_t)return;const s=o=>{if(!ze.current)return;const $=o.clientX-ze.current.startPointerX,A=o.clientY-ze.current.startPointerY,H=ze.current.data.x??0,V=ze.current.data.y??0;ze.current.currentX=H+$,ze.current.currentY=V+A,ms({...ze.current});const Z=T.find(de=>de.id===ze.current?.id);if(Vt.current?.({elementId:ze.current.id,elementType:Z?.type||"unknown",elementData:ze.current.data,clientX:o.clientX,clientY:o.clientY,initialPage:D,initialSegmentId:ze.current.data?.segmentId||n}),Le){const de=ve.current?.getBoundingClientRect();if(de){const fe=o.clientX-de.left,$e=o.clientY-de.top,De=[];let Be=0;for(const Pe of mt())if(Ge(Pe.type)&&(Be+=1,Pe.id!==ze.current.id))try{const Dt=JSON.parse(Pe.data),Se=As(Pe,Dt,kt(Pe.type,Dt));if(!Se)continue;const Ee=He.current.get(Pe.id);De.push({id:Pe.id,x:Ee?.x??Se.x,y:Ee?.y??Se.y,width:Ee?.width??Se.width,height:Ee?.height??Se.height})}catch{}const ot=Zi({x:fe,y:$e},De);if(ot){const Dt={x:12,y:12,width:Math.max(0,zt.width-24),height:Math.max(0,zt.height-24)},Se=sa(ot,{x:fe,y:$e},Dt,Be);le(Se),K.current!==ot.id&&B(ot.id)}else le(null),K.current!==null&&B(null)}}},h=async o=>{if(!ze.current)return;const $=ze.current.currentX,A=ze.current.currentY,H=ze.current.id,V=ze.current.data,Z=ze.current.startPointerX,de=ze.current.startPointerY,$e=Math.abs(o.clientX-Z)>Or||Math.abs(o.clientY-de)>Or?Cr.current?.(o,H):!1;Vt.current?.(null);const De=be.current;if(le(null),B(null),ze.current=null,ms(null),!$e){if(Le){De&&De.targetId&&De.targetId!==H?De.type==="swap"?ye.current?.(H,De.targetId):je.current?.(H,De.targetId,De.type):ur();return}if(l){we(!0);try{await l(H,{...V,x:$,y:A}),dt(H,{...Ue(V,V?.radius!==void 0?"circle":"rect"),x:$,y:A}),ae.publish({id:oe(),type:"whiteboard.element_updated",source:"whiteboard",payload:{lessonId:t},timestamp:Date.now(),correlationId:t})}catch(Be){console.error("Drag end update error:",Be)}finally{we(!1)}}}};return window.addEventListener("pointermove",s),window.addEventListener("pointerup",h),()=>{window.removeEventListener("pointermove",s),window.removeEventListener("pointerup",h)}},[_t,l,t,dt,Le,mt]),i.useEffect(()=>{if(!pr||!gt)return;const s=o=>{if(!ke.current||!bt.current)return;const $=o.clientX-ke.current.startX,A=o.clientY-ke.current.startY;let H=ke.current.initialX,V=ke.current.initialY,Z=ke.current.initialWidth,de=ke.current.initialHeight;const fe=150,$e=100,{corner:De}=ke.current;if(De==="bottom-right")Z=Math.max(fe,ke.current.initialWidth+$),de=Math.max($e,ke.current.initialHeight+A);else if(De==="bottom-left"){const Be=ke.current.initialWidth-$;Be>=fe&&(Z=Be,H=ke.current.initialX+$),de=Math.max($e,ke.current.initialHeight+A)}else if(De==="top-right"){Z=Math.max(fe,ke.current.initialWidth+$);const Be=ke.current.initialHeight-A;Be>=$e&&(de=Be,V=ke.current.initialY+A)}else if(De==="top-left"){const Be=ke.current.initialWidth-$;Be>=fe&&(Z=Be,H=ke.current.initialX+$);const ot=ke.current.initialHeight-A;ot>=$e&&(de=ot,V=ke.current.initialY+A)}bt.current={id:ke.current.id,x:H,y:V,width:Z,height:de},ps({...bt.current})},h=async o=>{if(!ke.current||!bt.current)return;const{id:$}=ke.current,{x:A,y:H,width:V,height:Z}=bt.current;ke.current=null,bt.current=null,fr(null),ps(null);const de=T.find(fe=>fe.id===$);if(de&&l)try{const fe=JSON.parse(de.data);we(!0),await l($,{...fe,x:A,y:H,width:V,height:Z}),dt($,{...Ue(fe,fe?.radius!==void 0?"circle":"rect"),x:A,y:H,width:V,height:Z}),ae.publish({id:oe(),type:"whiteboard.element_updated",source:"whiteboard",payload:{lessonId:t},timestamp:Date.now(),correlationId:t})}catch(fe){console.error("Resize end update error:",fe)}finally{we(!1)}};return window.addEventListener("pointermove",s),window.addEventListener("pointerup",h),()=>{window.removeEventListener("pointermove",s),window.removeEventListener("pointerup",h)}},[pr,gt,r,l,t,dt]);const vt=s=>{b||We({type:"confirm",title:"删除组件",message:"您确定要从白板中删除这个组件或图形吗?该操作不可撤销。",onConfirm:async()=>{we(!0);try{if(He.current.delete(s),ft(h=>h+1),Le){const h=mt().filter(o=>o.id!==s&&Ge(o.type));h.length>0&&await dr.current?.(h)}c?await c(s):await fetch(`/api/lessons/${t}/whiteboard/${s}`,{method:"DELETE"}),ae.publish({id:oe(),type:"whiteboard.element_updated",source:"whiteboard",payload:{lessonId:t},timestamp:Date.now(),correlationId:t}),d&&d(),he(null)}catch(h){console.error("Delete element failed:",h)}finally{we(!1),We(null)}}})},Un=()=>{b||We({type:"confirm",title:"清空白板",message:"您确定要清空画布上的所有组件、图形和线条吗?此操作将永久清空白板且不可逆!",onConfirm:async()=>{we(!0);try{u?await u():await fetch(`/api/lessons/${t}/whiteboard`,{method:"DELETE"}),ae.publish({id:oe(),type:"whiteboard.element_updated",source:"whiteboard",payload:{lessonId:t},timestamp:Date.now(),correlationId:t}),d&&d(),he(null)}catch(s){console.error("Clear board failed:",s)}finally{we(!1),We(null)}}})},Gn=()=>{b||We({type:"confirm",title:"重置白板",message:"您确定要将白板重置为开始上课的状态吗?您在白板上做的所有临时修改都将被重置。",onConfirm:async()=>{we(!0);try{await fetch(`/api/lessons/${t}/whiteboard/reset`,{method:"POST"}),ae.publish({id:oe(),type:"whiteboard.element_updated",source:"whiteboard",payload:{lessonId:t},timestamp:Date.now(),correlationId:t}),d&&d(),he(null)}catch(s){console.error("Reset board failed:",s)}finally{we(!1),We(null)}}})};i.useEffect(()=>{const s=h=>{const o=h.target,$=o.tagName==="INPUT"||o.tagName==="TEXTAREA"||o.isContentEditable;if((h.key==="Delete"||h.key==="Backspace")&&me&&($||(vt(me),he(null))),Le&&me&&!$&&h.altKey){let A=null;if(h.key==="ArrowLeft"||h.key==="h"||h.key==="H"?A="left":h.key==="ArrowRight"||h.key==="l"||h.key==="L"?A="right":h.key==="ArrowUp"||h.key==="k"||h.key==="K"?A="up":(h.key==="ArrowDown"||h.key==="j"||h.key==="J")&&(A="down"),A){const H=[];let V=null;for(const Z of mt())if(Ge(Z.type))try{const de=JSON.parse(Z.data),fe=As(Z,de,kt(Z.type,de));if(!fe)continue;const $e=He.current.get(Z.id),De={id:Z.id,x:$e?.x??fe.x,y:$e?.y??fe.y,width:$e?.width??fe.width,height:$e?.height??fe.height};H.push(De),Z.id===me&&(V=De)}catch{}if(V&&H.length>1){const Z=Vi(V,H,A);Z&&(h.preventDefault(),h.stopPropagation(),h.shiftKey?ye.current?.(me,Z.id):he(Z.id))}}}};return window.addEventListener("keydown",s),()=>window.removeEventListener("keydown",s)},[me,Le,mt]);const Sr=()=>{At.current&&clearTimeout(At.current),a&&(At.current=setTimeout(async()=>{we(!0);try{(await fetch(`/api/lessons/${t}/ai-tutor`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({elements:T.map(h=>({type:h.type,data:JSON.parse(h.data)}))})})).ok&&(ae.publish({id:oe(),type:"whiteboard.element_updated",source:"whiteboard",payload:{lessonId:t},timestamp:Date.now(),correlationId:t}),d&&d())}catch(s){console.error(s)}finally{we(!1)}},6e4))};i.useEffect(()=>(Sr(),()=>{At.current&&clearTimeout(At.current)}),[r]),i.useEffect(()=>{const s=mi();Ne.current=s,s.emit("join-room",t);const h=o=>{o.type==="temp-draw"?rr($=>({...$,[o.userId]:o.payload})):o.type==="temp-end"?rr($=>{const A={...$};return delete A[o.userId],A}):o.type==="refresh"?d&&d():o.type==="segment-change"?g&&o.payload?.segmentId&&g(o.payload.segmentId):o.type==="page-change"?typeof o.payload?.page=="number"&&ne(o.payload.page):o.type==="page-meta-update"&&Array.isArray(o.payload?.pages)&&ue(o.payload.pages)};return Ne.current.on("whiteboard-sync",h),()=>{Ne.current?.off("whiteboard-sync",h)}},[t,d,g]),i.useEffect(()=>{if(!ve.current)return;const s=new ResizeObserver(o=>{for(let $ of o)ve.current&&sr({width:ve.current.offsetWidth,height:ve.current.offsetHeight})});s.observe(ve.current);const h=()=>{ve.current&&sr({width:ve.current.offsetWidth,height:ve.current.offsetHeight})};return h(),window.addEventListener("resize",h),()=>{s.disconnect(),window.removeEventListener("resize",h)}},[]);const Kn=s=>{if(b)return;if(Sr(),Ce(null),v==="cursor"){s.target===s.target.getStage()&&he(null);return}if(xs)return;us(!0);const h=s.target.getStage().getPointerPosition();if(v==="pen"){const o=m?"#f8fafc":"black";st({type:"pen",points:[h.x,h.y],color:o})}else if(v==="highlighter")st({type:"highlighter",points:[h.x,h.y],color:q});else if(v==="rect"){const o=m?"#818cf8":"blue";st({type:"rectangle",x:h.x,y:h.y,width:0,height:0,stroke:o})}else if(v==="circle"){const o=m?"#4ade80":"green";st({type:"circle",x:h.x,y:h.y,radius:0,stroke:o})}else if(v==="text"){const o=m?"#f8fafc":"black";st({type:"text",x:h.x,y:h.y,text:"Click to edit...",fontSize:16,color:o})}},Vn=s=>{if(!tr||!Te)return;const h=s.target.getStage().getPointerPosition();if(Te.type==="pen"||Te.type==="highlighter")st({...Te,points:Te.points.concat([h.x,h.y])});else if(Te.type==="rectangle")st({...Te,width:h.x-Te.x,height:h.y-Te.y});else if(Te.type==="circle"){const o=Math.sqrt(Math.pow(h.x-Te.x,2)+Math.pow(h.y-Te.y,2));st({...Te,radius:o})}},Zn=async()=>{if(!tr||!Te)return;us(!1);const s={...Te,page:D,segmentId:n};st(null),we(!0);try{await x(s.type,s),ae.publish({id:oe(),type:"whiteboard.element_updated",source:"whiteboard",payload:{lessonId:t},timestamp:Date.now(),correlationId:t})}finally{we(!1)}};i.useEffect(()=>{!Ne.current||!Ne.current.id||(Te?Ne.current.emit("whiteboard-update",{roomId:t,type:"temp-draw",userId:Ne.current.id,payload:{...Te,page:D,segmentId:n}}):Ne.current.emit("whiteboard-update",{roomId:t,type:"temp-end",userId:Ne.current.id}))},[Te,t,D,n]),i.useEffect(()=>{n&&Ne.current&&Ne.current.emit("whiteboard-update",{roomId:t,type:"segment-change",payload:{segmentId:n}})},[n,t]);const zr=s=>{if(!s)return null;const h=s.page??0,o=G[D];return!(s.pageId&&o?.id?s.pageId===o.id:h===D)||n&&s.segmentId&&s.segmentId!==n?null:s.type==="pen"?e.jsx(ts,{points:s.points,stroke:s.color,strokeWidth:4,tension:.5,lineCap:"round",lineJoin:"round"}):s.type==="highlighter"?e.jsx(ts,{points:s.points,stroke:s.color||"#facc15",strokeWidth:18,tension:.5,lineCap:"round",lineJoin:"round",opacity:.5}):s.type==="rectangle"?e.jsx(Rr,{x:s.x,y:s.y,width:s.width,height:s.height,stroke:s.stroke}):s.type==="circle"?e.jsx(_r,{x:s.x,y:s.y,radius:s.radius,stroke:s.stroke}):s.type==="text"?e.jsx(Ar,{x:s.x,y:s.y,text:s.text,fontSize:Math.round((s.fontSize||16)*p),fill:s.color}):null},Qn=()=>zr(Te?{...Te,page:D,segmentId:n}:null),ei=()=>Object.values(gn).map((s,h)=>e.jsx(Bs.Fragment,{children:zr(s)},h)),$r=(s,h)=>{try{const o=Je(s),$=He.current.get(s.id),A=_t?.id===s.id,H=gt?.id===s.id,V=$?.x??o.x??0,Z=$?.y??o.y??0,de=H?gt.x:A?_t.currentX:V,fe=H?gt.y:A?_t.currentY:Z,$e=S=>kt(S,o).width,De=S=>kt(S,o).height,Be=H?gt.width:$?.width??o.width??$e(s.type),ot=H?gt.height:o.isMinimized?36:$?.height??o.height??De(s.type),Pe=h?.fullscreen,Dt=!!Pe,Se=Pe?Pe.padding:de,Ee=Pe?Pe.padding:fe,Ae=Pe?Math.max(240,Pe.width-Pe.padding*2):Be,Fe=Pe?Math.max(180,Pe.height-Pe.padding*2):ot,Xe=me===s.id,ii=Le&&te===s.id,Oe=!b&&!Xe?"group hover:ring-2 hover:ring-indigo-400/80 hover:shadow-2xl transition-all duration-150":"group transition-all duration-150",Ve=()=>ii&&Y?.type==="swap"?e.jsx("div",{className:"absolute -inset-1.5 z-50 rounded-xl border-2 border-dashed border-blue-500 bg-blue-500/20 pointer-events-none flex items-center justify-center backdrop-blur-[1px] animate-pulse shadow-xl",children:e.jsx("div",{className:"bg-blue-600 text-white text-xs font-semibold px-2.5 py-1 rounded-full shadow flex items-center gap-1.5 select-none",children:e.jsx("span",{children:"⇄ 松开对调位置"})})}):b||o.isMinimized?null:Xe?e.jsxs(e.Fragment,{children:[e.jsx("div",{className:"absolute -inset-1 border-2 border-indigo-500 rounded-lg pointer-events-none z-50 shadow-md animate-pulse duration-1000 animate-in fade-in"}),Le&&e.jsxs("div",{className:"absolute -top-7 left-0 z-50 bg-indigo-700/90 text-white text-[10px] font-mono px-2 py-0.5 rounded shadow pointer-events-none select-none flex items-center gap-1.5 backdrop-blur",children:[e.jsx("span",{children:"Alt+Shift+方向键 对调"}),e.jsx("span",{className:"text-indigo-300",children:"|"}),e.jsx("span",{children:"Alt+方向键 换焦"})]}),!Le&&e.jsxs(e.Fragment,{children:[e.jsx("div",{className:"absolute -top-1.5 -left-1.5 w-3.5 h-3.5 bg-white border-2 border-indigo-600 rounded-full cursor-nwse-resize z-50 hover:bg-indigo-50 hover:scale-110 transition-transform shadow",onPointerDown:S=>Zt(S,s.id,"top-left",Se,Ee,Ae,Fe),onPointerMove:Qt,onPointerUp:es}),e.jsx("div",{className:"absolute -top-1.5 -right-1.5 w-3.5 h-3.5 bg-white border-2 border-indigo-600 rounded-full cursor-nesw-resize z-50 hover:bg-indigo-50 hover:scale-110 transition-transform shadow",onPointerDown:S=>Zt(S,s.id,"top-right",Se,Ee,Ae,Fe),onPointerMove:Qt,onPointerUp:es}),e.jsx("div",{className:"absolute -bottom-1.5 -left-1.5 w-3.5 h-3.5 bg-white border-2 border-indigo-600 rounded-full cursor-nesw-resize z-50 hover:bg-indigo-50 hover:scale-110 transition-transform shadow",onPointerDown:S=>Zt(S,s.id,"bottom-left",Se,Ee,Ae,Fe),onPointerMove:Qt,onPointerUp:es}),e.jsx("div",{className:"absolute -bottom-1.5 -right-1.5 w-3.5 h-3.5 bg-white border-2 border-indigo-600 rounded-full cursor-nwse-resize z-50 hover:bg-indigo-50 hover:scale-110 transition-transform shadow",onPointerDown:S=>Zt(S,s.id,"bottom-right",Se,Ee,Ae,Fe),onPointerMove:Qt,onPointerUp:es})]})]}):e.jsx("div",{className:"absolute -inset-1 border-2 border-transparent group-hover:border-indigo-400/80 rounded-xl pointer-events-none transition-all duration-150 z-20"}),lt=(S,W,Q="default",ge)=>({title:o.title||S,icon:W,hidden:Dt,readOnly:b,isMinimized:!!o.isMinimized,isMaximized:rt===s.id,isPropertiesOpen:Kt===s.id||bs===s.id,themeColor:Q,extraActions:ge,onPointerDown:Re=>!b&&js(Re,s.id,o),onPointerMove:b?void 0:vs,onPointerUp:b?void 0:Ns,onOpenProperties:()=>{!M&&s.type==="html-applet"?(Lt(),yr(s.id)):(he(s.id),wt(Re=>Re===s.id?null:s.id))},onMinimize:async()=>{l&&(await l(s.id,{...o,isMinimized:!0}),ae.publish({id:oe(),type:"whiteboard.element_updated",source:"whiteboard",payload:{lessonId:t},timestamp:Date.now(),correlationId:t}))},onRestore:async()=>{rt===s.id&&at(null),o.isMinimized&&l&&(await l(s.id,{...o,isMinimized:!1}),ae.publish({id:oe(),type:"whiteboard.element_updated",source:"whiteboard",payload:{lessonId:t},timestamp:Date.now(),correlationId:t}))},onMaximize:()=>at(s.id),onBrowserFullscreen:()=>void pt.enter(s.id),onDelete:()=>vt(s.id)});if(s.type==="plugin"){const S=k==="teacher",W=S?o.teacherWidgetId:o.studentWidgetId,Q=S?"teacher.dashboard.widget":"student.view";return e.jsx(Ze,{children:e.jsx(Qe,{divProps:{style:{position:"absolute",top:`${Ee}px`,left:`${Se}px`,pointerEvents:"none",zIndex:Xe?20:10}},children:e.jsxs("div",{onPointerDown:ge=>{b||(he(s.id),ge.stopPropagation())},onContextMenu:ge=>{if(b){ge.preventDefault(),ge.stopPropagation();return}const Re=ve.current?.getBoundingClientRect();Re&&Ce({x:ge.clientX-Re.left,y:ge.clientY-Re.top,elementId:s.id})},className:`bg-white border border-gray-300 rounded-lg shadow-xl overflow-hidden flex flex-col font-sans text-sm relative ${Oe}`,style:{pointerEvents:b?"none":"auto",userSelect:b?"none":"auto",width:`${Ae}px`,height:`${Fe}px`},children:[e.jsx(Wr,{...lt("Plugin Component",e.jsx(Ss,{size:13,className:"text-indigo-600"}),"indigo"),contentClassName:"flex-grow bg-white overflow-auto relative min-h-0 p-2",children:e.jsx(ma,{pluginId:o.pluginId,slot:Q,widgetId:W,elementId:s.id,lessonId:t})}),b&&e.jsx(et,{}),!o.isMinimized&&Ve()]})})},s.id)}if(s.type==="hello-world")return e.jsx(Ze,{children:e.jsx(Qe,{divProps:{style:{position:"absolute",top:`${Ee}px`,left:`${Se}px`,pointerEvents:"none",zIndex:Xe?20:10}},children:e.jsxs("div",{onPointerDown:S=>{b||(he(s.id),S.stopPropagation())},className:`bg-transparent relative rounded-lg ${Oe}`,style:{pointerEvents:b?"none":"auto",userSelect:b?"none":"auto",width:`${Ae}px`,height:`${Fe}px`},children:[e.jsx(ya,{...Object.assign({elementId:s.id,data:o,readOnly:b},lt("Hello World 插件",e.jsx(Yt,{size:11,className:"text-amber-500 animate-pulse"}),"slate"),{onElementUpdate:l,lessonId:t})}),b&&e.jsx(et,{}),!o.isMinimized&&Ve()]})})},s.id);if(s.type==="rollcall")return e.jsx(Ze,{children:e.jsx(Qe,{divProps:{style:{position:"absolute",top:`${Ee}px`,left:`${Se}px`,pointerEvents:"none",zIndex:Xe?20:10}},children:e.jsxs("div",{onPointerDown:S=>{b||(he(s.id),S.stopPropagation())},onContextMenu:S=>{if(b){S.preventDefault(),S.stopPropagation();return}const W=ve.current?.getBoundingClientRect();W&&Ce({x:S.clientX-W.left,y:S.clientY-W.top,elementId:s.id})},className:`bg-transparent relative rounded-lg ${Oe}`,style:{pointerEvents:b?"none":"auto",userSelect:b?"none":"auto",width:`${Ae}px`,height:`${Fe}px`},children:[e.jsx(pa,{...Object.assign({elementId:s.id,data:o,lessonId:t,classId:f||o&&o.classId,readOnly:b,userRole:k},lt("随机点名助手 (分层抽问 Fair Picker)",e.jsx(Yt,{size:13,className:"animate-pulse text-amber-400"}),"indigo"),{onElementUpdate:l})}),b&&e.jsx(et,{}),Ve()]})})},s.id);if(s.type==="quiz"){const S=Array.isArray(o.options)?o.options:[],W=yn[s.id]??Object.keys(o.submissions||{}).length;return e.jsx(Ze,{children:e.jsx(Qe,{divProps:{style:{position:"absolute",top:`${Ee}px`,left:`${Se}px`,pointerEvents:"none",zIndex:Xe?20:10}},children:e.jsxs("div",{onPointerDown:Q=>{b||(he(s.id),Q.stopPropagation())},onContextMenu:Q=>{if(b){Q.preventDefault(),Q.stopPropagation();return}const ge=ve.current?.getBoundingClientRect();ge&&Ce({x:Q.clientX-ge.left,y:Q.clientY-ge.top,elementId:s.id})},"data-testid":`whiteboard-quiz-${s.id}`,className:`bg-white border border-gray-300 rounded-lg shadow-xl overflow-hidden flex flex-col font-sans text-sm relative select-none ${Oe}`,style:{pointerEvents:b?"none":"auto",userSelect:b?"none":"auto",width:`${Ae}px`,height:`${Fe}px`},children:[e.jsx(it,{...lt("随堂测验 (Interactive Quiz)",e.jsx(tn,{size:13,className:"text-indigo-500"}),"indigo"),onMaximize:()=>at(s.id),onBrowserFullscreen:()=>void pt.enter(s.id)}),!o.isMinimized&&e.jsxs("div",{className:"p-4 text-center flex-1 overflow-y-auto flex flex-col justify-between min-h-0",children:[e.jsxs("div",{className:"text-left space-y-2",children:[e.jsx("p",{className:"font-semibold text-gray-800 text-xs line-clamp-2",title:o.question,children:o.question||"随堂测验题目"}),S.length>0&&e.jsx("div",{className:"space-y-1",children:S.slice(0,4).map((Q,ge)=>e.jsxs("div",{className:"text-[11px] text-gray-600 bg-gray-50 border border-gray-100 rounded px-2 py-0.5 truncate text-left",children:[e.jsxs("span",{className:"font-bold text-indigo-500 mr-1.5",children:[String.fromCharCode(65+ge),"."]}),Q]},ge))})]}),e.jsx("div",{className:"pt-2",children:e.jsx("button",{"data-testid":"quiz-open-fullscreen",className:"w-full bg-indigo-600 hover:bg-indigo-700 text-white font-medium py-1.5 rounded transition-colors text-xs shadow-sm cursor-pointer disabled:opacity-50 disabled:cursor-not-allowed flex items-center justify-center gap-1.5",disabled:b,onClick:()=>{b||at(s.id)},children:e.jsx("span",{children:W>0?`进入测验 (${W} 人已交)`:"点击全屏答题 / 查看"})})})]}),b&&e.jsx(et,{}),!o.isMinimized&&Ve()]})})},s.id)}if(s.type==="assignment")return e.jsx(Ze,{children:e.jsx(Qe,{divProps:{style:{position:"absolute",top:`${Ee}px`,left:`${Se}px`,pointerEvents:"none",zIndex:Xe?20:10}},children:e.jsxs("div",{onPointerDown:S=>{b||(he(s.id),S.stopPropagation())},onContextMenu:S=>{if(b){S.preventDefault(),S.stopPropagation();return}const W=ve.current?.getBoundingClientRect();W&&Ce({x:S.clientX-W.left,y:S.clientY-W.top,elementId:s.id})},className:`bg-white border border-gray-300 rounded-lg shadow-xl overflow-hidden flex flex-col font-sans text-sm relative select-none ${Oe}`,style:{pointerEvents:b?"none":"auto",userSelect:b?"none":"auto",width:`${Ae}px`,height:`${Fe}px`},children:[e.jsx(it,{...lt("Assignment Upload Task",e.jsx(Ut,{size:13,className:"text-orange-500"}),"orange")}),!o.isMinimized&&e.jsxs("div",{className:"p-4 text-center flex-1 overflow-y-auto flex flex-col justify-center min-h-0",children:[e.jsx("p",{className:"font-semibold text-gray-800 mb-1 text-xs",children:o.title}),e.jsx("p",{className:"text-xs text-gray-500 mb-3 line-clamp-3",children:o.description}),e.jsx("button",{"data-testid":"assignment-submit-button",className:"w-full bg-orange-600 hover:bg-orange-700 text-white font-medium py-1.5 rounded transition-colors text-xs shadow-sm cursor-pointer disabled:opacity-50 disabled:cursor-not-allowed",disabled:b,onClick:()=>{if(b)return;const S=typeof o.assignmentId=="string"?o.assignmentId:"";if(S){fs(S);return}(async()=>{try{const Q=await(await fetch(`/api/assignments?lessonId=${encodeURIComponent(t||"")}`)).json().catch(()=>null),ge=Array.isArray(Q?.assignments)?Q.assignments:[],Re=ge.find(qe=>qe?.status==="published")||ge[0];if(Re?.id){fs(String(Re.id));return}We({type:"alert",title:"尚未发布作业",message:"教师还没有发布本课节的作业,请稍后再试。",onConfirm:()=>We(null)})}catch(W){We({type:"alert",title:"无法加载作业",message:W?.message?String(W.message):"请检查网络后重试。",onConfirm:()=>We(null)})}})()},children:o.assignmentId?"提交作业":"Upload File"})]}),b&&e.jsx(et,{}),!o.isMinimized&&Ve()]})})},s.id);if(s.type==="html-applet")return e.jsx(Ze,{children:e.jsx(Qe,{divProps:{style:{position:"absolute",top:`${Ee}px`,left:`${Se}px`,pointerEvents:"none",zIndex:Xe?20:10}},children:e.jsxs("div",{onPointerDown:S=>{b||(he(s.id),S.stopPropagation())},onContextMenu:S=>{if(b){S.preventDefault(),S.stopPropagation();return}const W=ve.current?.getBoundingClientRect();W&&Ce({x:S.clientX-W.left,y:S.clientY-W.top,elementId:s.id})},className:`bg-white border border-gray-300 rounded-lg shadow-xl overflow-hidden flex flex-col font-sans text-sm relative ${Oe}`,style:{pointerEvents:b?"none":"auto",userSelect:b?"none":"auto",width:`${Ae}px`,height:`${Fe}px`},children:[e.jsx(Wr,{...lt(o.title||"Interactive Courseware",e.jsx(qs,{size:13,className:"text-primary-theme"}),"default"),contentClassName:"flex-1 bg-white overflow-hidden relative min-h-0",children:e.jsx(pi,{data:o,lessonId:t,elementId:s.id,className:"w-full h-full border-none"})}),b&&e.jsx(et,{}),!o.isMinimized&&Ve()]})})},s.id);if(s.type==="pen"){const S=me===s.id;return e.jsx(ts,{id:s.id,points:o.points,stroke:S?C.selectionBorder||"#3b82f6":o.color&&o.color!=="black"&&o.color!=="#000000"?o.color:m?"#f8fafc":o.color||"black",strokeWidth:S?6:4,tension:.5,lineCap:"round",lineJoin:"round",draggable:k==="teacher"&&v==="cursor",onClick:W=>{v==="cursor"&&(W.cancelBubble=!0,he(S?null:s.id))},onTap:W=>{v==="cursor"&&(W.cancelBubble=!0,he(S?null:s.id))},onDragEnd:async W=>{const Q=W.target,ge=Q.x(),Re=Q.y();Q.x(0),Q.y(0);const qe=o.points.map((Ye,ks)=>ks%2===0?Ye+ge:Ye+Re);l&&(await l(s.id,{...o,points:qe}),ae.publish({id:oe(),type:"whiteboard.element_updated",source:"whiteboard",payload:{lessonId:t},timestamp:Date.now(),correlationId:t}))}},s.id)}if(s.type==="highlighter"){const S=me===s.id;return e.jsx(ts,{id:s.id,points:o.points,stroke:S?"#3b82f6":o.color||"#facc15",strokeWidth:S?24:18,tension:.5,lineCap:"round",lineJoin:"round",opacity:.5,draggable:k==="teacher"&&v==="cursor",onClick:W=>{v==="cursor"&&(W.cancelBubble=!0,he(S?null:s.id))},onTap:W=>{v==="cursor"&&(W.cancelBubble=!0,he(S?null:s.id))},onDragEnd:async W=>{const Q=W.target,ge=Q.x(),Re=Q.y();Q.x(0),Q.y(0);const qe=o.points.map((Ye,ks)=>ks%2===0?Ye+ge:Ye+Re);l&&(await l(s.id,{...o,points:qe}),ae.publish({id:oe(),type:"whiteboard.element_updated",source:"whiteboard",payload:{lessonId:t},timestamp:Date.now(),correlationId:t}))}},s.id)}if(s.type==="rectangle"||s.type==="shape"&&o.shape==="rect"){const S=me===s.id;return e.jsx(Rr,{id:s.id,x:$?.x??o.x,y:$?.y??o.y,width:$?.width??o.width,height:$?.height??o.height,fill:o.fill||"transparent",stroke:S?"#3b82f6":o.stroke||"blue",strokeWidth:S?3:1,draggable:k==="teacher"&&v==="cursor",onClick:W=>{v==="cursor"&&(W.cancelBubble=!0,he(S?null:s.id))},onTap:W=>{v==="cursor"&&(W.cancelBubble=!0,he(S?null:s.id))},onDragEnd:async W=>{const Q=W.target,ge=Q.x(),Re=Q.y();Q.x(0),Q.y(0);const qe=($?.x??o.x)+ge,Ye=($?.y??o.y)+Re;l&&(dt(s.id,{...Ue(o,"rect"),...$??{},x:qe,y:Ye}),await l(s.id,{...o,x:qe,y:Ye}),ae.publish({id:oe(),type:"whiteboard.element_updated",source:"whiteboard",payload:{lessonId:t},timestamp:Date.now(),correlationId:t}))}},s.id)}if(s.type==="circle"||s.type==="shape"&&o.shape==="circle"){const S=me===s.id;return e.jsx(_r,{id:s.id,x:$?.x??o.x,y:$?.y??o.y,radius:$?.radius??o.radius,fill:o.fill||"transparent",stroke:S?"#3b82f6":o.stroke||"green",strokeWidth:S?3:1,draggable:k==="teacher"&&v==="cursor",onClick:W=>{v==="cursor"&&(W.cancelBubble=!0,he(S?null:s.id))},onTap:W=>{v==="cursor"&&(W.cancelBubble=!0,he(S?null:s.id))},onDragEnd:async W=>{const Q=W.target,ge=Q.x(),Re=Q.y();Q.x(0),Q.y(0);const qe=($?.x??o.x)+ge,Ye=($?.y??o.y)+Re;l&&(dt(s.id,{...Ue(o,"circle"),...$??{},x:qe,y:Ye}),await l(s.id,{...o,x:qe,y:Ye}),ae.publish({id:oe(),type:"whiteboard.element_updated",source:"whiteboard",payload:{lessonId:t},timestamp:Date.now(),correlationId:t}))}},s.id)}if(s.type==="text"){const S=me===s.id;return e.jsx(Ar,{id:s.id,x:$?.x??o.x,y:$?.y??o.y,text:o.text,fontSize:Math.round((o.fontSize||16)*p),fill:S?C.selectionBorder||"#3b82f6":o.color&&o.color!=="black"&&o.color!=="#000000"?o.color:m?"#f8fafc":o.color||"black",fontStyle:S?"bold":"normal",draggable:k==="teacher"&&v==="cursor",onClick:W=>{v==="cursor"&&(W.cancelBubble=!0,he(S?null:s.id))},onTap:W=>{v==="cursor"&&(W.cancelBubble=!0,he(S?null:s.id))},onDragEnd:async W=>{const Q=W.target,ge=Q.x(),Re=Q.y();Q.x(0),Q.y(0);const qe=($?.x??o.x)+ge,Ye=($?.y??o.y)+Re;l&&(dt(s.id,{...Ue(o,"rect"),...$??{},x:qe,y:Ye}),await l(s.id,{...o,x:qe,y:Ye}),ae.publish({id:oe(),type:"whiteboard.element_updated",source:"whiteboard",payload:{lessonId:t},timestamp:Date.now(),correlationId:t}))}},s.id)}if(s.type==="code-sandbox")return e.jsx(Ze,{children:e.jsx(Qe,{divProps:{style:{position:"absolute",top:`${Ee}px`,left:`${Se}px`,pointerEvents:"none",zIndex:Xe?20:10}},children:e.jsxs("div",{onPointerDown:S=>{b||(he(s.id),S.stopPropagation())},onContextMenu:S=>{if(b){S.preventDefault(),S.stopPropagation();return}const W=ve.current?.getBoundingClientRect();W&&Ce({x:S.clientX-W.left,y:S.clientY-W.top,elementId:s.id})},className:`relative rounded-lg shadow-xl ${Oe}`,style:{pointerEvents:b?"none":"auto",userSelect:b?"none":"auto",width:`${Ae}px`,height:`${Fe}px`},children:[e.jsx(fa,{elementId:s.id,data:o,readOnly:b,isMinimized:!!o.isMinimized,isMaximized:rt===s.id,isPropertiesOpen:Kt===s.id,onOpenProperties:()=>{he(s.id),wt(S=>S===s.id?null:s.id)},onMinimize:async()=>{l&&(await l(s.id,{...o,isMinimized:!0}),ae.publish({id:oe(),type:"whiteboard.element_updated",source:"whiteboard",payload:{lessonId:t},timestamp:Date.now(),correlationId:t}))},onRestore:async()=>{rt===s.id&&at(null),o.isMinimized&&l&&(await l(s.id,{...o,isMinimized:!1}),ae.publish({id:oe(),type:"whiteboard.element_updated",source:"whiteboard",payload:{lessonId:t},timestamp:Date.now(),correlationId:t}))},onMaximize:()=>at(s.id),onBrowserFullscreen:()=>void pt.enter(s.id),onElementUpdate:l?async(S,W)=>{await l(S,W),ae.publish({id:oe(),type:"whiteboard.element_updated",source:"whiteboard",payload:{lessonId:t},timestamp:Date.now(),correlationId:t})}:void 0,onPointerDown:S=>!b&&js(S,s.id,o),onPointerMove:b?void 0:vs,onPointerUp:b?void 0:Ns,onDelete:()=>vt(s.id)}),b&&e.jsx(et,{}),Ve()]})})},s.id);if(s.type==="math-graph")return e.jsx(Ze,{children:e.jsx(Qe,{divProps:{style:{position:"absolute",top:`${Ee}px`,left:`${Se}px`,pointerEvents:"none",zIndex:Xe?20:10}},children:e.jsxs("div",{onPointerDown:S=>{b||(he(s.id),S.stopPropagation())},onContextMenu:S=>{if(b){S.preventDefault(),S.stopPropagation();return}const W=ve.current?.getBoundingClientRect();W&&Ce({x:S.clientX-W.left,y:S.clientY-W.top,elementId:s.id})},className:`relative rounded-lg shadow-xl ${Oe}`,style:{pointerEvents:b?"none":"auto",userSelect:b?"none":"auto",width:`${Ae}px`,height:`${Fe}px`},children:[e.jsx(ga,{elementId:s.id,data:o,readOnly:b,isMinimized:!!o.isMinimized,isMaximized:rt===s.id,isPropertiesOpen:Kt===s.id,onOpenProperties:()=>{he(s.id),wt(S=>S===s.id?null:s.id)},onMinimize:async()=>{l&&(await l(s.id,{...o,isMinimized:!0}),ae.publish({id:oe(),type:"whiteboard.element_updated",source:"whiteboard",payload:{lessonId:t},timestamp:Date.now(),correlationId:t}))},onRestore:async()=>{rt===s.id&&at(null),o.isMinimized&&l&&(await l(s.id,{...o,isMinimized:!1}),ae.publish({id:oe(),type:"whiteboard.element_updated",source:"whiteboard",payload:{lessonId:t},timestamp:Date.now(),correlationId:t}))},onMaximize:()=>at(s.id),onBrowserFullscreen:()=>void pt.enter(s.id),onElementUpdate:l?async(S,W)=>{await l(S,W),ae.publish({id:oe(),type:"whiteboard.element_updated",source:"whiteboard",payload:{lessonId:t},timestamp:Date.now(),correlationId:t})}:void 0,onPointerDown:S=>!b&&js(S,s.id,o),onPointerMove:b?void 0:vs,onPointerUp:b?void 0:Ns,onDelete:()=>vt(s.id)}),b&&e.jsx(et,{}),Ve()]})})},s.id);if(s.type==="presentation")return e.jsx(Ze,{children:e.jsx(Qe,{divProps:{style:{position:"absolute",top:`${Ee}px`,left:`${Se}px`,pointerEvents:"none",zIndex:Xe?20:10}},children:e.jsxs("div",{onPointerDown:S=>{b||(he(s.id),S.stopPropagation())},onContextMenu:S=>{if(b){S.preventDefault(),S.stopPropagation();return}const W=ve.current?.getBoundingClientRect();W&&Ce({x:S.clientX-W.left,y:S.clientY-W.top,elementId:s.id})},className:`bg-white border border-gray-305 rounded-lg shadow-xl overflow-hidden flex flex-col font-sans text-sm relative select-none ${Oe}`,style:{pointerEvents:b?"none":"auto",userSelect:b?"none":"auto",width:`${Ae}px`,height:`${Fe}px`},children:[e.jsx(it,{...lt("Interactive Presentation",e.jsx(is,{size:13,className:"text-purple-600"}),"purple")}),!o.isMinimized&&e.jsx("div",{className:"flex-1 min-h-0 relative bg-white",style:{pointerEvents:b?"none":"auto"},children:e.jsx(wa,{elementId:s.id,data:o,userRole:k,onElementUpdate:l?async(S,W)=>{await l(S,W),ae.publish({id:oe(),type:"whiteboard.element_updated",source:"whiteboard",payload:{lessonId:t},timestamp:Date.now(),correlationId:t})}:void 0})}),b&&e.jsx(et,{}),!o.isMinimized&&Ve()]})})},s.id);const Nt=s.type==="whiteboard.renderer"?o.rendererType||o.type||"whiteboard.renderer":s.type,Er=O?.find(S=>{const W=S;return W.targetType===Nt||S.id===Nt||S.route===Nt||`${S.pluginId}/${S.id}`===Nt||W.slotProps?.elementType===Nt||W.slotProps?.targetType===Nt});if(Er){const S=!!o.frameless,W=!!(o.hideTitleBar||S);return e.jsx(Ze,{children:e.jsx(Qe,{divProps:{style:{position:"absolute",top:`${Ee}px`,left:`${Se}px`,pointerEvents:"none",zIndex:Xe?20:10}},children:e.jsxs("div",{onPointerDown:Q=>{b||(he(s.id),Q.stopPropagation())},onContextMenu:Q=>{if(b){Q.preventDefault(),Q.stopPropagation();return}const ge=ve.current?.getBoundingClientRect();ge&&Ce({x:Q.clientX-ge.left,y:Q.clientY-ge.top,elementId:s.id})},className:S?`overflow-hidden flex flex-col font-sans text-sm relative ${Oe}`:`bg-white border border-gray-300 rounded-lg shadow-xl overflow-hidden flex flex-col font-sans text-sm relative ${Oe}`,style:{pointerEvents:b?"none":"auto",userSelect:b?"none":"auto",width:`${Ae}px`,height:`${Fe}px`},children:[!W&&e.jsx(it,{...lt(o.title||Er.label||s.type,e.jsx(Ss,{size:13,className:"text-indigo-600"}),"indigo")}),!o.isMinimized&&e.jsx("div",{className:`flex-1 overflow-hidden relative min-h-0 ${S?"":"bg-white"}`,style:{pointerEvents:b?"none":"auto"},children:e.jsx(_e,{slot:"whiteboard.renderer",slotProps:{element:s,elementId:s.id,elementType:Nt,data:o,width:Ae,height:Fe,isSelected:Xe,readOnly:b,userRole:k,lessonId:t,onElementUpdate:l?async(Q,ge)=>{await l(Q,ge),ae.publish({id:oe(),type:"whiteboard.element_updated",source:"whiteboard",payload:{lessonId:t},timestamp:Date.now(),correlationId:t})}:void 0}})}),b&&e.jsx(et,{}),!o.isMinimized&&Ve()]})})},s.id)}const Bt=ns.get(s.type);if(Bt){const S=Bt.component;return e.jsx(Ze,{children:e.jsx(Qe,{divProps:{style:{position:"absolute",top:`${Ee}px`,left:`${Se}px`,pointerEvents:"none",zIndex:Xe?20:10}},children:e.jsxs("div",{onPointerDown:W=>{b||(he(s.id),W.stopPropagation())},onContextMenu:W=>{if(b){W.preventDefault(),W.stopPropagation();return}const Q=ve.current?.getBoundingClientRect();Q&&Ce({x:W.clientX-Q.left,y:W.clientY-Q.top,elementId:s.id})},className:`bg-white border border-gray-300 rounded-lg shadow-xl overflow-hidden flex flex-col font-sans text-sm relative ${Oe}`,style:{pointerEvents:b?"none":"auto",userSelect:b?"none":"auto",width:`${Ae}px`,height:`${Fe}px`},children:[e.jsx(it,{...lt(Bt.labelZh||s.type,e.jsx(Ss,{size:13,className:"text-indigo-600"}),"indigo")}),!o.isMinimized&&e.jsx("div",{className:"flex-1 bg-white overflow-hidden relative min-h-0",style:{pointerEvents:b?"none":"auto"},children:S?e.jsx(S,{elementId:s.id,lessonId:t,data:o,userRole:k,onElementUpdate:l?async(W,Q)=>{await l(W,Q),ae.publish({id:oe(),type:"whiteboard.element_updated",source:"whiteboard",payload:{lessonId:t},timestamp:Date.now(),correlationId:t})}:void 0}):e.jsxs("div",{className:"w-full h-full flex flex-col items-center justify-center p-4 text-center text-gray-500 select-none",children:[e.jsx("div",{className:"font-semibold text-gray-700",children:Bt.labelZh}),e.jsx("div",{className:"text-xs mt-1 text-gray-400",children:Bt.descriptionZh}),o.title&&e.jsx("div",{className:"mt-2 text-xs bg-gray-100 px-2 py-1 rounded",children:o.title})]})}),b&&e.jsx(et,{}),!o.isMinimized&&Ve()]})})},s.id)}}catch(o){console.error(o)}return null},Mr=s=>{s.preventDefault(),s.dataTransfer.dropEffect="copy",se||pe(!0)},Tr=s=>{s.preventDefault(),s.dataTransfer.dropEffect="copy",pe(!0)},ti=s=>{s.preventDefault(),s.currentTarget.contains(s.relatedTarget)||pe(!1)},Dr=(s,h,o,$)=>{const A={x:o,y:$,page:D,segmentId:n},V=ns.get(s)?.defaultData||{},de=O?.find(fe=>{const $e=fe;return $e.targetType===s||fe.id===s||fe.route===s||`${fe.pluginId}/${fe.id}`===s||$e.slotProps?.elementType===s||$e.slotProps?.targetType===s})?.slotProps?.defaultData||{};switch(s){case"code-sandbox":return{...A,code:h.code??"console.log('Hello Sandbox!');"};case"math-graph":return{...A,equation:h.equation??"Math.sin(x)"};case"presentation":return{...A,markdown:h.markdown??`# Title Slide
77
+ ---
78
+ ## Slide 2`,width:600,height:400,slideX:0,slideY:0};case"quiz":return{...A,question:h.question??"New Quiz",options:Array.isArray(h.options)?h.options:["A","B","C","D"]};case"html-applet":return{...A,title:h.title??"",code:h.code??"",coursewareUuid:h.coursewareUuid??void 0,resourceId:h.resourceId??void 0};case"assignment":return{...A,title:h.title??"New Assignment",description:h.description??""};case"hello-world":return A;case"rollcall":return{...A,allStudents:[]};default:return{...A,...V,...de,...h}}},si=async(s,h)=>{if(!ve.current)return;const o=ve.current.getBoundingClientRect(),$=Math.round(o.width/2),A=Math.round(o.height/2);we(!0);try{await x(s,Dr(s,h,$,A)),ae.publish({id:oe(),type:"whiteboard.element_updated",source:"whiteboard",payload:{lessonId:t},timestamp:Date.now(),correlationId:t}),d&&d()}catch(H){console.error("addElementAtCenter error",H)}finally{we(!1)}},ri=i.useCallback(async(s,h)=>{if(h<0||h>=G.length)return;const o=T.find(A=>A.id===s);if(!o)return;const $=G[h];try{const A=JSON.parse(o.data),H=typeof A.page=="number"?A.page:D,V={...A,page:h,pageId:$?.id};if(delete V.__tiled,delete V.tileOrder,o.data=JSON.stringify(V),He.current.delete(s),ft(Z=>Z+1),l&&await l(s,V),Le){const Z=T.filter(de=>{if(de.id===s||!Ge(de.type))return!1;try{const fe=JSON.parse(de.data);return!((typeof fe.page=="number"?fe.page:0)!==H||n&&fe.segmentId&&fe.segmentId!==n)}catch{return H===0}});Z.length>0&&await Mt(Z)}he(null),ae.publish({id:oe(),type:"whiteboard.element_updated",source:"whiteboard",payload:{lessonId:t,elementId:s,targetPage:h},timestamp:Date.now(),correlationId:t})}catch(A){console.error("Failed to move element to page:",A)}},[G,T,D,n,Le,Mt,l,t]),ni=i.useCallback(async(s,h)=>{const o=T.find($=>$.id===s);if(o)try{const $=JSON.parse(o.data),A=$.segmentId??n,H={...$,segmentId:h};if(delete H.__tiled,delete H.tileOrder,o.data=JSON.stringify(H),He.current.delete(s),ft(V=>V+1),l&&await l(s,H),Le){const V=T.filter(Z=>{if(Z.id===s||!Ge(Z.type))return!1;try{return!((JSON.parse(Z.data).segmentId??"")!==(A??"")||!Os(Z))}catch{return!1}});V.length>0&&await Mt(V)}he(null),ae.publish({id:oe(),type:"whiteboard.element_updated",source:"whiteboard",payload:{lessonId:t,elementId:s,targetSegmentId:h},timestamp:Date.now(),correlationId:t})}catch($){console.error("Failed to move element to segment:",$)}},[T,n,Os,Le,Mt,l,t]);i.useImperativeHandle(ee,()=>({addElementAtCenter:si,applyAutoTiling:ur,switchPage:Gs,addPage:Ks,deletePage:Qs,renamePage:Vs,duplicatePage:Zs,movePage:er,moveElementToPage:ri,moveElementToSegment:ni}));const Pr=async s=>{s.preventDefault(),s.stopPropagation();try{let h=s.dataTransfer.getData("application/json");if(h||(h=s.dataTransfer.getData("text/plain")),h||(h=s.dataTransfer.getData("text")),h||(h=s.dataTransfer.getData("Text")),console.log("Whiteboard drop triggered. Payload:",h),!h)return;let o;try{o=JSON.parse(h)}catch(V){console.error("Failed to parse drop JSON payload:",V);return}if(typeof o!="object"||!o)return;if(!ve.current){console.warn("containerRef.current is not loaded on drop");return}const $=ve.current.getBoundingClientRect();let A=s.clientX-$.left,H=s.clientY-$.top;console.log(`Adding whiteboard element of type ${o.type} at (${A}, ${H})`),we(!0);try{await x(o.type,Dr(o.type,o,A,H)),ae.publish({id:oe(),type:"whiteboard.element_updated",source:"whiteboard",payload:{lessonId:t},timestamp:Date.now(),correlationId:t}),d&&d()}finally{we(!1)}}catch(h){console.error("Drop error",h)}};return e.jsxs("div",{className:"flex-1 flex flex-row min-h-0 overflow-hidden bg-app",children:[e.jsxs("div",{className:"flex-1 flex flex-col min-h-0 bg-app relative min-w-0",onDragOver:Mr,onDragEnter:Tr,onDrop:Pr,children:[!b&&e.jsx(ja,{tool:v,setTool:w,setSelectedShapeId:he,highlighterColor:q,setHighlighterColor:I,onElementAdd:x,currentPage:D,activeSegmentId:n,lessonId:t,safeElements:T,selectedShapeId:me,showGrid:ce,setShowGrid:re,autoTileEnabled:Le,onToggleAutoTile:Cn,readOnly:b,userRole:k,isSyncing:xs,setIsSyncing:we,handleClearBoard:Un,handleResetBoard:Gn,handleElementDelete:vt,setDialog:We,setDialogInput:br,onRefresh:d,classroomTools:P,onExecuteTool:X}),e.jsxs("div",{ref:ve,className:"flex-1 rounded-xl border border-theme/80 relative overflow-hidden w-full shadow-inner transition-colors",style:{backgroundImage:ce?`radial-gradient(${C.gridDot} 1.2px, transparent 1.2px)`:"none",backgroundSize:"24px 24px",backgroundColor:C.background},onDragOver:Mr,onDragEnter:Tr,onDragLeave:ti,onDrop:async s=>{pe(!1),await Pr(s)},children:[se&&e.jsxs("div",{className:"absolute inset-0 border-2 border-dashed border-indigo-500 bg-indigo-500/10 backdrop-blur-[2px] rounded-2xl flex flex-col items-center justify-center text-indigo-600 font-bold text-sm z-30 animate-in fade-in pointer-events-none",children:[e.jsx(It,{size:32,className:"mb-2 text-indigo-600 animate-bounce"}),e.jsx("span",{children:"释放鼠标将组件放入当前白板页面"})]}),e.jsx(Ea,{isVisible:T.filter(s=>{if(s.type==="page_meta")return!1;try{const h=JSON.parse(s.data),o=h.page??0,$=G[D];return!(!(h.pageId&&$?.id?h.pageId===$.id:o===D)||n&&h.segmentId&&h.segmentId!==n)}catch{return D===0}}).length===0&&!rt&&!$t}),e.jsxs("div",{className:"absolute inset-0 w-full h-full overflow-hidden",style:{pointerEvents:se||b?"none":"auto"},children:[e.jsx(Fa,{containerSize:zt,browserFullscreenElementId:$t,isRemoteBrowserFullscreen:Gt,isBrowserFullscreenDismissible:kn,browserFullscreen:pt,effectiveFullscreenElementId:rt,isRemoteFullscreen:Rt,isFullscreenDismissible:Nn,applyFullscreen:at,safeElements:T,lessonId:t,readOnly:b,renderElement:$r,children:e.jsx(Gr,{width:zt.width,height:zt.height,onMouseDown:Kn,onMousemove:Vn,onMouseup:Zn,onContextMenu:s=>{s.evt.preventDefault();const h=ve.current?.getBoundingClientRect();if(h){const o=s.evt.clientX-h.left,$=s.evt.clientY-h.top,H=s.target.id();H?(he(H),Ce({x:o,y:$,elementId:H})):Ce({x:o,y:$})}},ref:bn,className:"w-full h-full cursor-crosshair",children:e.jsxs(Kr,{children:[mt().map(s=>$r(s)),Qn(),ei()]})})}),e.jsx(La,{autoTileEnabled:Le,readOnly:b,tilingSplitters:Sn,activeSplitterDrag:zn,activeDropZoneAction:Y,handleSplitterPointerDown:$n}),!b&&Tt&&e.jsx("div",{style:{left:`${Tt.x}px`,top:`${Tt.y}px`,pointerEvents:"auto"},className:"absolute bg-surface rounded-lg shadow-2xl border border-theme py-1.5 w-44 z-40 font-sans text-sm animate-in fade-in zoom-in-95 duration-100 text-main",onClick:s=>s.stopPropagation(),onContextMenu:s=>s.preventDefault(),children:Tt.elementId?e.jsxs(e.Fragment,{children:[e.jsx("div",{className:"px-3 py-1 text-xs text-muted font-bold uppercase tracking-wider select-none",children:"组件选项"}),e.jsxs("button",{onClick:()=>{const s=Tt.elementId;s&&(he(s),wt(s)),Ce(null)},className:"w-full px-3 py-1.5 flex items-center gap-2 text-left text-main hover:bg-surface-secondary transition-colors text-xs font-semibold cursor-pointer",children:[e.jsx(Zr,{size:14}),"配置组件属性"]}),e.jsxs("button",{onClick:()=>{const s=Tt.elementId;s&&(vt(s),me===s&&he(null)),Ce(null)},className:"w-full px-3 py-1.5 flex items-center gap-2 text-left text-rose-500 hover:bg-rose-500/10 transition-colors text-xs font-semibold cursor-pointer",children:[e.jsx(ct,{size:14}),"删除此组件"]})]}):e.jsxs(e.Fragment,{children:[e.jsx("div",{className:"px-3 py-1 text-xs text-muted font-bold uppercase tracking-wider select-none",children:"白板操作"}),e.jsxs("button",{onClick:()=>{w("cursor"),Ce(null)},className:`w-full px-3 py-1.5 flex items-center gap-2 text-left text-xs font-medium hover:bg-surface-secondary transition-colors cursor-pointer ${v==="cursor"?"text-primary-theme":"text-main"}`,children:[e.jsx(nn,{size:14}),"选择工具 (Cursor)"]}),e.jsxs("button",{onClick:()=>{w("pen"),Ce(null)},className:`w-full px-3 py-1.5 flex items-center gap-2 text-left text-xs font-medium hover:bg-surface-secondary transition-colors cursor-pointer ${v==="pen"?"text-primary-theme":"text-main"}`,children:[e.jsx(an,{size:14}),"画笔工具 (Pen)"]}),e.jsxs("button",{onClick:()=>{w("highlighter"),Ce(null)},className:`w-full px-3 py-1.5 flex items-center gap-2 text-left text-xs font-medium hover:bg-surface-secondary transition-colors cursor-pointer ${v==="highlighter"?"text-primary-theme":"text-main"}`,children:[e.jsx(on,{size:14}),"高亮荧光笔 (Highlighter)"]}),e.jsxs("button",{onClick:()=>{w("rect"),Ce(null)},className:`w-full px-3 py-1.5 flex items-center gap-2 text-left text-xs font-medium hover:bg-surface-secondary transition-colors cursor-pointer ${v==="rect"?"text-primary-theme":"text-main"}`,children:[e.jsx(Hs,{size:14}),"矩形工具 (Rectangle)"]}),e.jsxs("button",{onClick:()=>{w("circle"),Ce(null)},className:`w-full px-3 py-1.5 flex items-center gap-2 text-left text-xs font-medium hover:bg-surface-secondary transition-colors cursor-pointer ${v==="circle"?"text-primary-theme":"text-main"}`,children:[e.jsx(ln,{size:14}),"圆形工具 (Circle)"]}),e.jsxs("button",{onClick:()=>{w("text"),Ce(null)},className:`w-full px-3 py-1.5 flex items-center gap-2 text-left text-xs font-medium hover:bg-surface-secondary transition-colors cursor-pointer ${v==="text"?"text-primary-theme":"text-main"}`,children:[e.jsx(cn,{size:14}),"文本工具 (Text)"]})]})}),e.jsx("div",{className:"absolute inset-0 pointer-events-none z-20 overflow-hidden",children:e.jsx(_e,{slot:"whiteboard.canvas.widget",slotProps:{lessonId:t,classId:N,userRole:k,readOnly:b}})}),e.jsx("div",{className:"absolute bottom-4 left-4 z-30 pointer-events-auto flex items-center gap-2",children:e.jsx(_e,{slot:"whiteboard.dock.plugin",slotProps:{lessonId:t,classId:N,userRole:k,readOnly:b}})})]}),!b&&!L&&e.jsx(va,{pages:G,currentPage:D,showPageDrawer:ht,setShowPageDrawer:St,editingPageIdx:hn,setEditingPageIdx:cs,editingPageTitle:mn,setEditingPageTitle:Ys,activeMenuPageIdx:pn,setActiveMenuPageIdx:Is,safeElements:T,handleSwitchPage:Gs,handleRenamePage:Vs,handleDuplicatePage:Zs,handleMovePage:er,handleDeletePage:Qs,handleAddPage:Ks})]}),e.jsx(Na,{dialog:Tn,dialogInput:Dn,setDialogInput:br,setDialog:We}),gr&&e.jsx(za,{assignmentId:gr,onClose:()=>fs(null),lang:"zh"}),e.jsx(Wa,{showEntrySelector:An,setShowEntrySelector:Nr,zipUploadInfo:Rn,zipCandidates:Pn,handlePropsUpdate:kr,fetchCoursewares:Lt}),e.jsx(Xa,{isOpen:!!bs,onClose:()=>yr(null),element:T.find(s=>s.id===bs)||null,coursewares:vr,fetchCoursewares:Lt,onApplyTemporary:Fn,onSavePermanent:Ln})]}),k==="teacher"&&t&&e.jsx(Xi,{lessonId:t,defaultCollapsed:!0}),e.jsx(Pa,{isEditMode:M,selectedShapeId:me,setSelectedShapeId:he,activePropertiesElementId:Kt,setActivePropertiesElementId:wt,safeElements:T,editingProperties:yt,handleLocalPropChange:Wn,handlePropBlur:Xn,handleNumericPropBlur:qn,handlePropsUpdate:kr,handleUpdateElementData:jt,handleElementDelete:vt,handleUndoProp:Bn,handleRedoProp:Hn,propertyUndoStack:wr,propertyRedoStack:jr,isSyncing:xs,lessonId:t,classId:N,fullscreenBroadcastClassId:f,coursewares:vr,fetchCoursewares:Lt,setZipCandidates:En,setZipUploadInfo:_n,setShowEntrySelector:Nr,handleAddOption:Jn,handleRemoveOption:On,handleOptionChangeLocal:Yn,handleOptionBlur:In})]})});export{Ya as DEFAULT_WHITEBOARD_PAGES,Or as DRAG_ACTIVATION_THRESHOLD_PX,oo as InteractiveWhiteboard};