PageSourceSearch

https://jenkins-zh.cn/assets/index-CLaaWgG4.js

js jenkins-zh.cn collected 2026-10-02 10:20:27 UTC 300,353 bytes, 166 lines download raw bytes

1import{d as ge,y as be,A as k,D as l,B as e,C as t,O as te,aw as il,b as d,ab as a,t as n,u as se,P as s,X as Oe,al as Je,r as Ae,n as dt,L as Me,R as it,v as N,Q as S,E as ft,c as Le,ac as Ee,V as ct,I as ue,a5 as fe,F as Ye,q as Et,a4 as Ot,w as je,at as ul}from"./@vue-BmGsfn0j.js";import{u as Ie,a as st,c as dl,b as cl}from"./vue-router-Dg7Jw2c_.js";import{Q as qt,n as ht,R as pl,S as Vt,T as ml,U as _t,j as vl,g as Ct,V as Nt,F as vt,W as fl,X as _l,Y as jt,f as Wt,Z as Tt,l as yl,J as gl,_ as Kt,O as kt,$ as bl,a0 as Gt,a1 as Rt,a2 as At,h as wl,a3 as kl,a4 as Ut,a5 as Ft,a6 as hl,a7 as $l,a8 as Vl,a9 as Cl,B as xl,aa as Dl,ab as Sl,ac as Ml,ad as Ul,c as Il,ae as Tl,af as Al,ag as zl}from"./@element-plus-CPyxi4h5.js";import{a as Ll}from"./axios-Dnk_-Q5K.js";import{E as b,a as et,b as Bt,c as nt,i as Yl}from"./element-plus-7oZcWGxi.js";import{d as de,u as pt,t as xt}from"./dayjs-CeYBYhWn.js";import{M as Jt}from"./markdown-it-C44Roubk.js";import{k as Pt}from"./katex-CmXvOE4_.js";import{i as ut}from"./echarts-DZPOz0gw.js";import{Y as Ht}from"./zrender-B4ySFyXH.js";import"./lodash-es-DPM5whWy.js";import"./@vueuse-BONkDHvq.js";import"./@popperjs-D_chPuIy.js";import"./@ctrl-r5W6hzzQ.js";import"./async-validator-9PlIezaS.js";import"./memoize-one-BdPwpGay.js";import"./normalize-wheel-es-BQoi3Ox2.js";import"./@floating-ui-BC47QiC6.js";import"./mdurl-k9Sl0PQj.js";import"./uc.micro-kMc2yuuw.js";import"./entities-C20TfXL6.js";import"./linkify-it-DmNjr4Kv.js";import"./punycode.js-Dj65hjkv.js";import"./tslib-BDyQ-Jie.js";(function(){const c=document.createElement("link").relList;if(c&&c.supports&&c.supports("modulepreload"))return;for(const y of document.querySelectorAll('link[rel="modulepreload"]'))v(y);new MutationObserver(y=>{for(const C of y)if(C.type==="childList")for(const h of C.addedNodes)h.tagName==="LINK"&&h.rel==="modulepreload"&&v(h)}).observe(document,{childList:!0,subtree:!0});function w(y){const C={};return y.integrity&&(C.integrity=y.integrity),y.referrerPolicy&&(C.referrerPolicy=y.referrerPolicy),y.crossOrigin==="use-credentials"?C.credentials="include":y.crossOrigin==="anonymous"?C.credentials="omit":C.credentials="same-origin",C}function v(y){if(y.ep)return;y.ep=!0;const C=w(y);fetch(y.href,C)}})();const El="/assets/siliconflow-DAWLKsZu.png",Rl={class:"home-container"},Fl={class:"features-section"},Bl={key:0,class:"teachers-showcase-section"},Pl={class:"showcase-content"},Hl={class:"cta-section"},Ol=ge({__name:"Home",setup(q){const c=Ie(),w=d(-1);function v(){c.push("/student?tab=dictation")}function y(){sessionStorage.getItem("token")?c.push("/student"):(b.info("请先登录以预约课程"),c.push("/login"))}function C(){sessionStorage.getItem("token")?c.push("/ai-dictionary"):(b.info("请先登录以使用AI词典"),c.push("/login"))}function h(){sessionStorage.getItem("token")?c.push("/student?tab=my-mistakes"):(b.info("请先登录以使用错题集功能"),c.push("/login"))}function u(){c.push(`/institution/${w.value}/showcase`)}function f(){c.push("/login")}function m(){c.push("/register")}function _(){const r=document.createElement("a");r.href="/api/public/download-apk",r.download="open-course.apk",r.target="_blank",document.body.appendChild(r),r.click(),document.body.removeChild(r)}const p=async()=>{A.get("/api/public/institutions-showcase").then(r=>{r.data&&r.data.length>0&&(w.value=r.data[0].id)}).catch(r=>{console.error("Failed to load institution showcase:",r)})};return be(()=>{p()}),(r,o)=>{const g=a("el-icon"),V=a("el-col"),z=a("el-row"),M=a("el-button");return n(),k("div",Rl,[o[16]||(o[16]=l("div",{class:"hero-section"},[l("h1",null,"欢迎来到开放课程系统"),l("p",{class:"subtitle"},"一个功能丰富的在线学习和课程管理系统")],-1)),l("div",Fl,[e(z,{gutter:30,justify:"center"},{default:t(()=>[e(V,{xs:24,sm:12,md:6},{default:t(()=>[l("div",{class:"feature-card",onClick:v},[e(g,{class:"feature-icon"},{default:t(()=>[e(se(qt))]),_:1}),o[0]||(o[0]=l("h3",null,"单词听写练习",-1)),o[1]||(o[1]=l("p",{class:"feature-description"},"通过互动式听写练习提升词汇量,支持按年级和单元选择",-1))])]),_:1}),e(V,{xs:24,sm:12,md:6},{default:t(()=>[l("div",{class:"feature-card",onClick:y},[e(g,{class:"feature-icon"},{default:t(()=>[e(se(ht))]),_:1}),o[2]||(o[2]=l("h3",null,"课程预约",-1)),o[3]||(o[3]=l("p",{class:"feature-description"},"浏览可用课程时间并预约适合您的课程",-1)),o[4]||(o[4]=l("p",{class:"login-required"},"(需要登录)",-1))])]),_:1}),e(V,{xs:24,sm:12,md:6},{default:t(()=>[l("div",{class:"feature-card",onClick:C},[e(g,{class:"feature-icon"},{default:t(()=>[e(se(pl))]),_:1}
1),o[5]||(o[5]=l("h3",null,"AI英语词典",-1)),o[6]||(o[6]=l("p",{class:"feature-description"},"使用AI技术提供详细的单词解释、例句和记忆技巧",-1)),o[7]||(o[7]=l("p",{class:"login-required"},"(需要登录)",-1))])]),_:1}),e(V,{xs:24,sm:12,md:6},{default:t(()=>[l("div",{class:"feature-card",onClick:h},[e(g,{class:"feature-icon"},{default:t(()=>[e(se(Vt))]),_:1}),o[8]||(o[8]=l("h3",null,"错题集",-1)),o[9]||(o[9]=l("p",{class:"feature-description"},"管理和练习您的错题,支持按学科和年级分类",-1)),o[10]||(o[10]=l("p",{class:"login-required"},"(需要登录)",-1))])]),_:1}),e(V,{xs:24,sm:12,md:6},{default:t(()=>[l("div",{class:"feature-card",onClick:_},[e(g,{class:"feature-icon"},{default:t(()=>[e(se(ml))]),_:1}),o[11]||(o[11]=l("h3",null,"下载APP",-1)),o[12]||(o[12]=l("p",{class:"feature-description"},"下载我们的移动应用,随时随地学习",-1))])]),_:1})]),_:1})]),w.value!=-1?(n(),k("div",Bl,[e(z,{gutter:30,justify:"center"},{default:t(()=>[e(V,{span:24},{default:t(()=>[l("div",{class:"teachers-showcase-card",onClick:u},[l("div",Pl,[e(g,{class:"showcase-icon"},{default:t(()=>[e(se(_t))]),_:1}),o[13]||(o[13]=l("div",{class:"showcase-text"},[l("h3",null,"寻找培优、补习的优秀老师"),l("p",null,"汇聚各领域资深教师,为您提供专业的辅导服务")],-1)),e(g,{class:"arrow-icon"},{default:t(()=>[e(se(vl))]),_:1})])])]),_:1})]),_:1})])):te("",!0),o[17]||(o[17]=il('<div class="partners-section" data-v-2ea2b5af><h2 class="section-title" data-v-2ea2b5af>合作伙伴</h2><div class="partner-logo" data-v-2ea2b5af><a href="https://cloud.siliconflow.cn/i/Hpf6kA2O" target="_blank" data-v-2ea2b5af><img src="'+El+'" data-v-2ea2b5af></a></div><div class="partners-slider" data-v-2ea2b5af><div class="slider-track" data-v-2ea2b5af></div></div></div>',1)),l("div",Hl,[e(z,{gutter:20,justify:"center"},{default:t(()=>[e(V,{span:12},{default:t(()=>[e(M,{type:"primary",size:"large",onClick:f,class:"cta-button"},{default:t(()=>[...o[14]||(o[14]=[s("立即登录",-1)])]),_:1})]),_:1}),e(V,{span:12},{default:t(()=>[e(M,{size:"large",onClick:m,class:"cta-button"},{default:t(()=>[...o[15]||(o[15]=[s("注册账户",-1)])]),_:1})]),_:1})]),_:1})])])}}}),Ce=(q,c)=>{const w=q.__vccOpts||q;for(const[v,y]of c)w[v]=y;return w},ql=Ce(Ol,[["__scopeId","data-v-2ea2b5af"]]),Nl={class:"auth-page"},jl={class:"auth-container"},Wl={class:"auth-card"},Kl={class:"auth-header"},Gl={class:"auth-links"},Jl={class:"auth-home-link"},Xl=ge({__name:"Login",setup(q){const c=Ie(),w=d(!1),v=Ae({email:"",password:""}),y=d(!1);async function C(){var h,u;if(!v.email||!v.password){b.error("请输入用户名或邮箱和密码");return}w.value=!0;try{const f=await A.post("/api/login",v),m=f.data.token,_=f.data.user,p=_.role;sessionStorage.setItem("token",m),sessionStorage.setItem("user",JSON.stringify(_)),p==="admin"?c.push("/admin"):p==="teacher"?c.push("/teacher"):p==="institution"?c.push("/institution"):c.push("/student"),y.value=!1,window.dispatchEvent(new Event("loginSuccess"))}catch(f){b.error(((u=(h=f.response)==null?void 0:h.data)==null?void 0:u.error)||"登录失败"),y.value=!0}finally{w.value=!1}}return(h,u)=>{const f=a("el-icon"),m=a("el-input"),_=a("el-form-item"),p=a("el-button"),r=a("el-form"),o=a("router-link");return n(),k("div",Nl,[l("div",jl,[l("div",Wl,[l("div",Kl,[e(f,{class:"auth-icon"},{default:t(()=>[e(se(_t))]),_:1}),u[2]||(u[2]=l("h2",null,"欢迎登录",-1)),u[3]||(u[3]=l("p",{class:"auth-subtitle"},"开放课程系统",-1))]),e(r,{model:v,onSubmit:Oe(C,["prevent"]),class:"auth-form"},{default:t(()=>[e(_,null,{default:t(()=>[e(m,{modelValue:v.email,"onUpdate:modelValue":u[0]||(u[0]=g=>v.email=g),placeholder:"请输入用户名或邮箱","prefix-icon":"User",size:"large",class:"auth-input"},null,8,["modelValue"])]),_:1}),e(_,null,{default:t(()=>[e(m,{type:"password",modelValue:v.password,"onUpdate:modelValue":u[1]||(u[1]=g=>v.password=g),placeholder:"请输入密码","prefix-icon":"Lock",size:"large","show-password":"",class:"auth-input",onKeyup:Je(C,["enter"])},null,8,["modelValue"])]),_:1}),e(_,null,{default:t(()=>
1[e(p,{type:"primary",onClick:C,class:"auth-button",loading:w.value,size:"large"},{default:t(()=>[...u[4]||(u[4]=[s(" 登录 ",-1)])]),_:1},8,["loading"])]),_:1})]),_:1},8,["model"]),l("div",Gl,[e(o,{to:"/forgot-password",class:"auth-link-item"},{default:t(()=>[...u[5]||(u[5]=[s("忘记密码?",-1)])]),_:1}),e(o,{to:"/register",class:"auth-link-item"},{default:t(()=>[...u[6]||(u[6]=[s("注册学生账户",-1)])]),_:1})]),l("div",Jl,[e(o,{to:"/",class:"auth-back-home"},{default:t(()=>[e(f,null,{default:t(()=>[e(se(Ct))]),_:1}),u[7]||(u[7]=s(" 返回首页 ",-1))]),_:1})])])]),u[8]||(u[8]=l("div",{class:"auth-bg"},[l("div",{class:"auth-bg-pattern"})],-1))])}}}),Ql=Ce(Xl,[["__scopeId","data-v-12936464"]]),Xt="/assets/admin-wechat-qrcode-f9CgmCLF.jpg",Zl={class:"auth-page"},ea={class:"auth-container"},ta={class:"auth-card"},la={class:"auth-header"},aa={class:"form-label"},oa={class:"form-label"},na={class:"form-label"},sa={class:"form-label"},ra={class:"form-label"},ia={class:"auth-links"},ua={class:"auth-home-link"},da={class:"qrcode-container"},ca={key:0,class:"qrcode-error"},pa=ge({__name:"Register",setup(q){const c=Ie(),w=d(!1),v=d(),y=d(!1),C=d(!1);function h(){y.value=!0}function u(){C.value=!0,b.error("二维码加载失败,请联系管理员")}const m={name:[{required:!0,message:"请输入用户名",trigger:"blur"},{min:2,max:20,message:"用户名长度在2-20个字符之间",trigger:"blur"}],email:[{required:!0,message:"请输入邮箱地址",trigger:"blur"},{type:"email",message:"请输入正确的邮箱地址",trigger:"blur"}],inviteCode:[{required:!0,message:"请输入邀请码",trigger:"blur"}],password:[{required:!0,message:"请输入密码",trigger:"blur"},{min:6,message:"密码长度至少为6位",trigger:"blur"}],confirmPassword:[{required:!0,validator:(r,o,g)=>{o===""?g(new Error("请再次输入密码")):o!==_.password?g(new Error("两次输入的密码不一致")):g()},trigger:"blur"}]},_=Ae({name:"",email:"",inviteCode:"",password:"",confirmPassword:""});be(()=>{const o=new URLSearchParams(window.location.search.split("?")[1]).get("inviteCode");o&&(_.inviteCode=o),dt(()=>{const g=document.querySelector(".auth-form input");g==null||g.focus()})});async function p(){if(!v.value){b.error("表单初始化失败,请刷新页面重试");return}await v.value.validate(async r=>{var o,g;if(!r){b.error("请检查表单填写是否正确");const V=document.querySelector(".el-form-item.is-error");if(V){const z=V.querySelector("input");z==null||z.focus()}return}w.value=!0;try{await A.post("/api/register",{name:_.name,email:_.email,invite_code:_.inviteCode,password:_.password}),b.success("注册成功!请登录"),v.value&&v.value.resetFields(),setTimeout(()=>{c.push("/login")},1500)}catch(V){console.error(V);const M=(g=(o=V.response)==null?void 0:o.data)==null?void 0:g.error,I={USER_EXISTS:"该用户名已被注册,请更换用户名",EMAIL_EXISTS:"该邮箱已被注册,请使用其他邮箱或直接登录",INVALID_INVITE_CODE:"邀请码无效,请检查后重试",WEAK_PASSWORD:"密码强度不足,请使用更复杂的密码组合"}[M||""]||M||"注册失败,请稍后重试";b.error(I)}finally{w.value=!1}})}return(r,o)=>{const g=a("el-icon"),V=a("el-tooltip"),z=a("el-input"),M=a("el-form-item"),L=a("el-button"),I=a("el-form"),O=a("router-link"),j=a("el-dialog");return n(),k("div",Zl,[l("div",ea,[l("div",ta,[l("div",la,[e(g,{class:"auth-icon"},{default:t(()=>[e(se(Nt))]),_:1}),o[6]||(o[6]=l("h2",null,"学生注册",-1)),o[7]||(o[7]=l("p",{class:"auth-subtitle"},"加入开放课程系统",-1))]),e(I,{model:_,rules:m,ref_key:"formRef",ref:v,onSubmit:Oe(p,["prevent"]),class:"auth-form","label-position":"left"},{default:t(()=>[e(M,{prop:"name"},{label:t(()=>[l("div",aa,[o[8]||(o[8]=l("span",null,"用户名",-1)),e(V,{content:"用于登录系统的唯一标识,建议使用英文字母、数字或下划线组合",placement:"top","show-after":500},{default:t(()=>[e(g,{class:"info-icon",tabindex:"0",role:"button","aria-label":"查看用户名说明"},{default:t(()=>[e(se(vt))]),_:1})]),_:1})])]),default:t(()=>[e(z,{id:"username",modelValue:_.name,"onUpdate:modelValue":o[0]||(o[0]=R=>_.name=R),placeholder:"请输入用户名","prefix-icon":"User",size:"large",class:"auth-input","aria-label":"用户名输入框",autocomplete:"username"},null,8,["modelValue"])]),_:1}),e(M,{prop:"email"},{label:t(()=>[l("div",oa,[o[9]||(o[9]=l("span",null,"邮箱地址",-1)),e(V,{content:"用于找回密码和接收系统通知,请填写真实有效的邮箱",placement:"top","show-after":500},{default:t(()=>[e(g,{class:"info-icon",tabindex:"0",role:"button","aria-label":"查看邮箱说明"},{default:t(()=>[e(se(vt))]),_:1})]),_:1})])]),default:t(()=>[e(z,{id:"email",modelValue:_.email,"onUpdate:modelValue":o[1]||(o[1]=R=>_.email=R),type:"email",placeholder:"请输入邮箱地址","prefix-icon":"Message",size:"large",class:"auth-input","aria-label":"邮箱地址输入框",autocomplete:"email"},null,8,["modelValue"])]),_:1}),e(M,{prop:"inviteCode"},{label:t(()=>[l("div",na,[o[10]||(o[10]=l("span",null,"邀请码",-1)),e(g,{class:"info-icon clickable-icon",onClick:h,onKeydown:[Je(h,["enter"]),Je(Oe(h,["prevent"]),["space"])],tabindex:"0",role:"button","aria-label":"查看邀请码获取方式"},{default:t(()=>[e(se(vt))]),_:1},8,["onKeydown"])])]),default:t(()=>[e(z,{id:"inviteCode",modelValue:_.inviteCode,"onUpdate:modelValue":o[2]||(o[2]=R=>_.inviteCode=R),placeholder:"请输入邀请码","prefix-icon":"Ticket",size:"large",class:"auth-input","aria-label":"邀请码输入框"},null,8,["modelValue"])]),_:1}),e(M,{prop:"password"},{label:t(()=>[l("div",sa,[o[11]||(o[11]=l("span",null,"密码",-1)),e(V,{content:"密码长度至少6位,建议使用字母、数字和符号组合以提高安全性",placement:"top","show-after":500},{default:t(()=>[e(g,{class:"info-icon",tabindex:"0",role:"button","aria-label":"查看密码说明"},{default:t(()=>[e(se(vt))]),_:1})]),_:1})])]),default:t(()=>[e(z,{id:"password",type:"password",modelValue:_.password,"onUpdate:modelValue":o[3]||(o[3]=R=>_.password=R),placeholder:"请输入密码","prefix-icon":"Lock",
1size:"large","show-password":"",class:"auth-input","aria-label":"密码输入框",autocomplete:"new-password"},null,8,["modelValue"])]),_:1}),e(M,{prop:"confirmPassword"},{label:t(()=>[l("div",ra,[o[12]||(o[12]=l("span",null,"确认密码",-1)),e(V,{content:"请再次输入密码以确保密码输入正确",placement:"top","show-after":500},{default:t(()=>[e(g,{class:"info-icon",tabindex:"0",role:"button","aria-label":"查看确认密码说明"},{default:t(()=>[e(se(vt))]),_:1})]),_:1})])]),default:t(()=>[e(z,{id:"confirmPassword",type:"password",modelValue:_.confirmPassword,"onUpdate:modelValue":o[4]||(o[4]=R=>_.confirmPassword=R),placeholder:"请再次输入密码","prefix-icon":"Lock",size:"large","show-password":"",class:"auth-input","aria-label":"确认密码输入框",autocomplete:"new-password",onKeyup:Je(p,["enter"])},null,8,["modelValue"])]),_:1}),e(M,null,{default:t(()=>[e(L,{type:"primary",onClick:p,class:"auth-button",loading:w.value,size:"large"},{default:t(()=>[...o[13]||(o[13]=[s(" 注册 ",-1)])]),_:1},8,["loading"])]),_:1})]),_:1},8,["model"]),l("div",ia,[e(O,{to:"/forgot-password",class:"auth-link-item"},{default:t(()=>[...o[14]||(o[14]=[s("忘记密码?",-1)])]),_:1}),e(O,{to:"/login",class:"auth-link-item"},{default:t(()=>[...o[15]||(o[15]=[s("已有账户?去登录",-1)])]),_:1})]),l("div",ua,[e(O,{to:"/",class:"auth-back-home"},{default:t(()=>[e(g,null,{default:t(()=>[e(se(Ct))]),_:1}),o[16]||(o[16]=s(" 返回首页 ",-1))]),_:1})])])]),o[20]||(o[20]=l("div",{class:"auth-bg"},[l("div",{class:"auth-bg-pattern"})],-1)),e(j,{modelValue:y.value,"onUpdate:modelValue":o[5]||(o[5]=R=>y.value=R),title:"扫码添加管理员微信获取邀请码",width:"320px",center:"",class:"qrcode-dialog"},{default:t(()=>[l("div",da,[Me(l("img",{src:Xt,alt:"管理员微信二维码",class:"qrcode-image",onError:u},null,544),[[it,!C.value]]),C.value?(n(),k("div",ca,[...o[17]||(o[17]=[l("p",null,"二维码加载失败,请联系管理员",-1)])])):te("",!0),o[18]||(o[18]=l("p",{class:"qrcode-tip"},"扫描上方二维码添加管理员微信",-1)),o[19]||(o[19]=l("p",{class:"qrcode-subtip"},'备注"开放课程注册"获取邀请码',-1))])]),_:1},8,["modelValue"])])}}}),ma=Ce(pa,[["__scopeId","data-v-07f7bb45"]]),va={class:"auth-page"},fa={class:"auth-container"},_a={class:"auth-card"},ya={class:"auth-header"},ga={class:"auth-links"},ba={class:"auth-home-link"},wa=ge({__name:"ResetPassword",setup(q){const c=st(),w=Ie(),v=d(!1),y=Ae({password:"",confirmPassword:"",token:""});be(()=>{y.token=c.query.token,y.token||(b.error("重置链接无效或已过期"),setTimeout(()=>{w.push("/forgot-password")},2e3))});async function C(){var h,u;if(!y.password){b.error("请输入新密码");return}if(y.password.length<6){b.error("密码长度至少为6位");return}if(y.password!==y.confirmPassword){b.error("两次输入的密码不一致");return}if(!y.token){b.error("重置令牌缺失");return}v.value=!0;try{await A.post("/api/reset-password",{token:y.token,password:y.password}),b.success("密码重置成功!请登录"),setTimeout(()=>{w.push("/login")},1500)}catch(f){b.error(((u=(h=f.response)==null?void 0:h.data)==null?void 0:u.error)||"密码重置失败")}finally{v.value=!1}}return(h,u)=>{const f=a("el-icon"),m=a("el-input"),_=a("el-form-item"),p=a("el-button"),r=a("el-form"),o=a("router-link");return n(),k("div",va,[l("div",fa,[l("div",_a,[l("div",ya,[e(f,{class:"auth-icon"},{default:t(()=>[e(se(fl))]),_:1}),u[2]||(u[2]=l("h2",null,"重置密码",-1)),u[3]||(u[3]=l("p",{class:"auth-subtitle"},"设置新密码",-1))]),e(r,{model:y,onSubmit:Oe(C,["prevent"]),class:"auth-form"},{default:t(()=>[e(_,null,{default:t(()=>[e(m,{type:"password",modelValue:y.password,"onUpdate:modelValue":u[0]||(u[0]=g=>y.password=g),placeholder:"请输入新密码(至少6位)","prefix-icon":"Lock",size:"large","show-password":"",class:"auth-input"},null,8,["modelValue"])]),_:1}),e(_,null,{default:t(()=>[e(m,{type:"password",modelValue:y.confirmPassword,"onUpdate:modelValue":u[1]||(u[1]=g=>y.confirmPassword=g),placeholder:"请确认新密码","prefix-icon":"Lock",
1size:"large","show-password":"",class:"auth-input",onKeyup:Je(C,["enter"])},null,8,["modelValue"])]),_:1}),e(_,null,{default:t(()=>[e(p,{type:"primary",onClick:C,class:"auth-button",loading:v.value,size:"large"},{default:t(()=>[...u[4]||(u[4]=[s(" 重置密码 ",-1)])]),_:1},8,["loading"])]),_:1})]),_:1},8,["model"]),l("div",ga,[e(o,{to:"/login",class:"auth-link-item"},{default:t(()=>[...u[5]||(u[5]=[s("返回登录",-1)])]),_:1}),e(o,{to:"/forgot-password",class:"auth-link-item"},{default:t(()=>[...u[6]||(u[6]=[s("重新发送链接",-1)])]),_:1})]),l("div",ba,[e(o,{to:"/",class:"auth-back-home"},{default:t(()=>[e(f,null,{default:t(()=>[e(se(Ct))]),_:1}),u[7]||(u[7]=s(" 返回首页 ",-1))]),_:1})])])]),u[8]||(u[8]=l("div",{class:"auth-bg"},[l("div",{class:"auth-bg-pattern"})],-1))])}}}),ka=Ce(wa,[["__scopeId","data-v-38270fe6"]]),ha={class:"auth-page"},$a={class:"auth-container"},Va={class:"auth-card"},Ca={class:"auth-header"},xa={class:"auth-links"},Da={class:"auth-home-link"},Sa=ge({__name:"ForgotPassword",setup(q){const c=Ie(),w=d(!1),v=Ae({email:""});async function y(){var C,h;if(!v.email){b.error("请输入邮箱地址");return}w.value=!0;try{await A.post("/api/request-password-reset",{email:v.email}),b.success("如果邮箱已注册,您将收到密码重置链接"),setTimeout(()=>{c.push("/login")},2e3)}catch(u){b.error(((h=(C=u.response)==null?void 0:C.data)==null?void 0:h.error)||"发送重置链接失败")}finally{w.value=!1}}return(C,h)=>{const u=a("el-icon"),f=a("el-input"),m=a("el-form-item"),_=a("el-button"),p=a("el-form"),r=a("router-link");return n(),k("div",ha,[l("div",$a,[l("div",Va,[l("div",Ca,[e(u,{class:"auth-icon"},{default:t(()=>[e(se(_l))]),_:1}),h[1]||(h[1]=l("h2",null,"忘记密码",-1)),h[2]||(h[2]=l("p",{class:"auth-subtitle"},"重置您的密码",-1))]),e(p,{model:v,onSubmit:Oe(y,["prevent"]),class:"auth-form"},{default:t(()=>[e(m,null,{default:t(()=>[e(f,{modelValue:v.email,"onUpdate:modelValue":h[0]||(h[0]=o=>v.email=o),type:"email",placeholder:"请输入注册邮箱","prefix-icon":"Message",size:"large",class:"auth-input"},null,8,["modelValue"])]),_:1}),e(m,null,{default:t(()=>[e(_,{type:"primary",onClick:y,class:"auth-button",loading:w.value,size:"large"},{default:t(()=>[...h[3]||(h[3]=[s(" 发送重置链接 ",-1)])]),_:1},8,["loading"])]),_:1})]),_:1},8,["model"]),l("div",xa,[e(r,{to:"/login",class:"auth-link-item"},{default:t(()=>[...h[4]||(h[4]=[s("返回登录",-1)])]),_:1}),e(r,{to:"/register",class:"auth-link-item"},{default:t(()=>[...h[5]||(h[5]=[s("注册账户",-1)])]),_:1})]),l("div",Da,[e(r,{to:"/",class:"auth-back-home"},{default:t(()=>[e(u,null,{default:t(()=>[e(se(Ct))]),_:1}),h[6]||(h[6]=s(" 返回首页 ",-1))]),_:1})])])]),h[7]||(h[7]=l("div",{class:"auth-bg"},[l("div",{class:"auth-bg-pattern"})],-1))])}}}),Ma=Ce(Sa,[["__scopeId","data-v-8f3258d6"]]),Ua={class:"note-manager"},Ia={key:2},Ta=["innerHTML"],Aa={key:1},za={key:1,class:"no-notes"},La={class:"toolbar"},Ya={class:"dialog-footer"},Ea=ge({__name:"NoteManager",props:{bookingId:{},studentId:{},teacherId:{},noteId:{},role:{},showContent:{type:Boolean}},emits:["notes-updated"],setup(q,{expose:c,emit:w}){const v=q,y=w,C=new Jt,h=d([]),u=d(!1),f=d(!1),m=d(null),_=d({content:"",is_public:!1,fontSize:"16px"}),p=Le(()=>v.role==="student"||v.role==="teacher"),r=Le(()=>v.role==="student"||v.role==="teacher"||v.role==="admin"),o=Le(()=>m.value&&m.value.teacher_id);be(()=>{g()});async function g(){try{u.value=!0;const R=await A.get(`/api/bookings/${v.bookingId}/notes`);h.value=R.data.map(K=>({...K,creator_type:K.teacher_id?"teacher":"student"}))||[]}catch(R){console.error("Failed to load notes:",R)}finally{u.value=!1}}const V=async R=>{try{u.value=!0;const K=await A.get(`/api/notes/${R}`);m.value=K.data,_.value.content=K.data.content,_.value.is_public=K.data.is_public||!1,_.value.fontSize=K.data.font_size||"16px",f.value=!0}catch(K){console.error("Failed to load note:",K)}finally{u.value=!1}};function z(R){const K=JSON.parse(sessionStorage.getItem("user")||"{}");return v.role==="student"?R.student_id===K.id:v.role==="teacher"?R.teacher_id===K.id:!1}function M(R){R?(m.value=R,_.value.content=R.content,_.value.is_public=R.is_public||!1,_.value.fontSize=R.fontSize||"16px"):(m.value=null,_.value.content="",_.value.is_public=!1,_.value.fontSize="16px"),f.value=!0}async function L(){try{const R={booking_id:v.bookingId,content:_.value.content,font_size:_.value.fontSize};(v.role==="student"||v.role==="teacher")&&(R.is_public=_.value.is_public),await A.post("/api/notes",R),f.value=!1,g(),y("notes-updated")}catch(R){console.error("Failed to save note:",R),alert("保存笔记失败")}}async function I(R){try{await A.delete(`/api/notes/${R}`),g(),y("notes-updated")}catch(K){console.error("Failed to delete note:",K),alert("删除笔记失败")}}function O(R){return C.render(R)}function j(R){return de(R).format("YYYY-MM-DD HH:mm")}return c({loadNotes:g}),(R,K)=>{const H=a("el-button"),x=a("el-table-column"),B=a("el-tag"),D=a("el-table"),U=a("el-option"),F=a("el-select"),i=a("el-input"),$=a("el-form-item"),X=a("el-radio"),G=a("el-radio-group"),E=a("el-form"),oe=a("el-dialog"),Q=Ee("loading");
1return n(),k("div",Ua,[q.noteId?(n(),N(H,{key:0,type:"primary",size:"small",onClick:K[0]||(K[0]=re=>V(q.noteId))},{default:t(()=>[...K[7]||(K[7]=[s(" 查看笔记 ",-1)])]),_:1})):p.value?(n(),N(H,{key:1,type:"primary",size:"small",onClick:K[1]||(K[1]=re=>M(null))},{default:t(()=>[...K[8]||(K[8]=[s(" 添加笔记 ",-1)])]),_:1})):te("",!0),q.showContent?(n(),k("div",Ia,[h.value.length>0?Me((n(),N(D,{key:0,data:h.value,style:{width:"100%","margin-top":"10px"}},{default:t(()=>[e(x,{prop:"content",label:"笔记内容"},{default:t(({row:re})=>[l("div",{innerHTML:O(re.content)},null,8,Ta)]),_:1}),e(x,{prop:"creator_type",label:"类型",width:"100"},{default:t(({row:re})=>[e(B,{type:re.teacher_id?"warning":"primary"},{default:t(()=>[s(S(re.teacher_id?"教师笔记":"学生笔记"),1)]),_:2},1032,["type"])]),_:1}),e(x,{prop:"is_public",label:"可见性",width:"100"},{default:t(({row:re})=>[re.teacher_id?(n(),k("span",Aa,"-")):(n(),N(B,{key:0,type:re.is_public?"success":"info"},{default:t(()=>[s(S(re.is_public?"公开":"私有"),1)]),_:2},1032,["type"]))]),_:1}),e(x,{prop:"created_at",label:"创建时间",width:"180"},{default:t(({row:re})=>[s(S(j(re.created_at)),1)]),_:1}),r.value?(n(),N(x,{key:0,label:"操作",width:"150"},{default:t(({row:re})=>[z(re)?(n(),N(H,{key:0,type:"primary",size:"small",onClick:me=>M(re)},{default:t(()=>[...K[9]||(K[9]=[s(" 编辑 ",-1)])]),_:1},8,["onClick"])):te("",!0),z(re)?(n(),N(H,{key:1,type:"danger",size:"small",onClick:me=>I(re.id)},{default:t(()=>[...K[10]||(K[10]=[s(" 删除 ",-1)])]),_:1},8,["onClick"])):te("",!0)]),_:1})):te("",!0)]),_:1},8,["data"])),[[Q,u.value]]):te("",!0),h.value.length===0&&!u.value?(n(),k("div",za," 暂无笔记 ")):te("",!0)])):te("",!0),e(oe,{modelValue:f.value,"onUpdate:modelValue":K[6]||(K[6]=re=>f.value=re),title:m.value?"编辑笔记":"添加笔记",draggable:"",width:"600px"},{footer:t(()=>[l("span",Ya,[e(H,{onClick:K[5]||(K[5]=re=>f.value=!1)},{default:t(()=>[...K[14]||(K[14]=[s("取消",-1)])]),_:1}),e(H,{type:"primary",onClick:L},{default:t(()=>[...K[15]||(K[15]=[s("保存",-1)])]),_:1})])]),default:t(()=>[e(E,{model:_.value,"label-width":"80px"},{default:t(()=>[e($,{label:"笔记内容"},{default:t(()=>[l("div",La,[K[11]||(K[11]=l("span",null,"字体大小: ",-1)),e(F,{modelValue:_.value.fontSize,"onUpdate:modelValue":K[2]||(K[2]=re=>_.value.fontSize=re),placeholder:"选择字体大小",size:"small",style:{width:"120px","margin-right":"10px"}},{default:t(()=>[e(U,{label:"小",value:"14px"}),e(U,{label:"中",value:"16px"}),e(U,{label:"大",value:"18px"}),e(U,{label:"超大",value:"24px"})]),_:1},8,["modelValue"])]),e(i,{modelValue:_.value.content,"onUpdate:modelValue":K[3]||(K[3]=re=>_.value.content=re),type:"textarea",rows:6,style:ft({fontSize:_.value.fontSize||"16px"}),placeholder:"支持Markdown格式"},null,8,["modelValue","style"])]),_:1}),q.role==="student"&&!o.value?(n(),N($,{key:0,label:"可见性"},{default:t(()=>[e(G,{modelValue:_.value.is_public,"onUpdate:modelValue":K[4]||(K[4]=re=>_.value.is_public=re)},{default:t(()=>[e(X,{label:!0},{default:t(()=>[...K[12]||(K[12]=[s("公开",-1)])]),_:1}),e(X,{label:!1},{default:t(()=>[...K[13]||(K[13]=[s("私有",-1)])]),_:1})]),_:1},8,["modelValue"])]),_:1})):te("",!0)]),_:1},8,["model"])]),_:1},8,["modelValue","title"])])}}}),Qt=Ce(Ea,[["__scopeId","data-v-2e842300"]]),Ra={key:0},Fa={class:"header"},Ba={class:"header-toolbar"},Pa={class:"hours-info"},Ha=["onClick"],Oa={class:"day-num"},qa={key:0,class:"dot available"},Na={key:1,class:"dot mine"},ja={key:0},Wa={key:0,class:"timeslot-list"},Ka={key:1},Ga={key:1},Ja={key:1},Xa=ge({__name:"StudentCourses",setup(q){const c=Ie(),w=d([]),v=d(null),y=d([]),C=d(0),h=d("student"),u=d(!1),f=d(null),m=d(new Date),_=d(null),p=d([]),r=d(new Map),o=d(new Set),g=d(window.innerWidth<=480),V=d(!1),z=()=>{g.value=window.innerWidth<=480,g.value||(V.value=!0)};be(async()=>{window.addEventListener("resize",z),z();const G=await A.get("/api/teachers");w.value=G.data,await I();try{const E=await A.get("/api/me");h.value=E.data.role,C.value=E.data.balance||0}catch(E){console.error("Failed to get user info:",E)}}),ct(()=>{window.removeEventListener("resize",z)});const M=async(G,E)=>{f.value=G,u.value=!0},L=d({});async function I(){try{const G=await A.get("/api/mybookings"),E=new Map,oe=new Set;L.value={};for(const Q of G.data||[])if(E.set(Q.timeslot_id,Q.id),Q.start){const re=de(Q.start).format("YYYY-MM-DD");oe.add(re),L.value[re]=Q}r.value=E,o.value=oe}catch{r.value=new Map,o.value=new Set}}async function O(G){v.value=G;const E=await A.get(`/api/teachers/${G.id}/courses`);y.value=E.data,_.value=null,g.value&&(V.value=!1)}function j(){v.value&&c.push(`/teacher/${v.value.id}/detail`).catch(G=>{console.error("Navigation failed:",G),b.error("页面跳转失败")})}const R=Le(()=>{const G=new Map;for(const E of y.value){const oe=E.title;
1for(const Q of E.timeslots||[]){const re=de(Q.start).format("YYYY-MM-DD"),me=G.get(re)||[];me.push({...Q,courseTitle:oe}),G.set(re,me)}}return G});function K(G){let E="";return G?(G instanceof Date?E=de(G).format("YYYY-MM-DD"):typeof G=="string"?E=de(G).format("YYYY-MM-DD"):G.day?E=de(G.day).format("YYYY-MM-DD"):G.date&&(E=de(G.date).format("YYYY-MM-DD")),(R.value.get(E)||[]).length>0):!1}function H(G){let E="";if(!G)return!1;G instanceof Date?E=de(G).format("YYYY-MM-DD"):typeof G=="string"?E=de(G).format("YYYY-MM-DD"):G.day?E=de(G.day).format("YYYY-MM-DD"):G.date&&(E=de(G.date).format("YYYY-MM-DD"));const oe=L.value[E];if(!oe)return!1;for(const Q of y.value)if(Q.id===oe.id)return!0;return!1}async function x(G){const E=G&&G.day?G.day:G&&G.date?G.date:G;if(_.value=E?de(E).toDate():null,p.value=[],g.value&&(V.value=!0),!(!v.value||!E))try{const Q=(await A.get(`/api/teachers/${v.value.id}/timeslots`,{params:{date:de(E).format("YYYY-MM-DD")}})).data||[];for(const re of Q)re.mine=r.value.has(re.id),re.bookingId=r.value.get(re.id);p.value=Q}catch(oe){console.error("failed to fetch timeslots",oe)}}function B(G){return de(G).format("YYYY-MM-DD")}function D(G,E){return`${de(G).format("HH:mm")} - ${de(E).format("HH:mm")}`}async function U(G){var oe,Q;const E=p.value.find(re=>re.id===G);if(E&&new Date(E.start)<new Date){b.error("不能预约过去的时间");return}try{if(await A.post("/api/book",{timeslot_id:G}),b.success("Booked successfully"),g.value&&(V.value=!1),v.value&&_.value){const re=de(_.value).format("YYYY-MM-DD");try{const me=await A.get(`/api/teachers/${v.value.id}/timeslots`,{params:{date:re}});await I();const ie=me.data||[];for(const ce of ie)ce.mine=r.value.has(ce.id),ce.bookingId=r.value.get(ce.id);p.value=ie;try{const ce=await A.get("/api/me");C.value=ce.data.balance||0}catch{}}catch(me){console.error("failed to refresh timeslots",me)}}}catch(re){const me=((Q=(oe=re==null?void 0:re.response)==null?void 0:oe.data)==null?void 0:Q.error)||"Failed to book";b.error(me)}}async function F(G){var oe,Q;if(!G||!confirm("Cancel this booking?"))return;const E=Array.from(r.value.entries()).find(([re,me])=>me===G);if(E){const re=E[0],me=p.value.find(ie=>ie.id===re);if(me&&new Date(me.start)<new Date){b.error("不能取消过去的时间预约");return}}try{if(await A.delete(`/api/bookings/${G}`),b.success("Cancelled successfully"),g.value&&(V.value=!1),await I(),v.value&&_.value){const re=de(_.value).format("YYYY-MM-DD");try{const ie=(await A.get(`/api/teachers/${v.value.id}/timeslots`,{params:{date:re}})).data||[];for(const ce of ie)ce.mine=r.value.has(ce.id),ce.bookingId=r.value.get(ce.id);p.value=ie;try{const ce=await A.get("/api/me");C.value=ce.data.balance||0}catch{}}catch(me){console.error("failed to refresh timeslots",me)}}}catch(re){const me=((Q=(oe=re==null?void 0:re.response)==null?void 0:oe.data)==null?void 0:Q.error)||"Failed to cancel";b.error(me)}}function i(G){return new Date(G)<new Date}function $(){console.log("Notes updated")}async function X(){try{const G=document.createElement("a");G.href="/api/my-calendar-export",G.setAttribute("download",`课程安排-${de().format("YYYY-MM-DD")}.ics`),G.style.display="none",document.body.appendChild(G),G.click(),document.body.removeChild(G),b.success("日历导出成功")}catch{b.error("导出日历失败")}}return(G,E)=>{const oe=a("el-menu-item"),Q=a("el-menu"),re=a("el-col"),me=a("el-button"),ie=a("el-calendar"),ce=a("el-row"),ke=a("el-card"),De=a("el-dialog");return n(),k(ue,null,[e(ke,{class:"student-courses"},{default:t(()=>[E[14]||(E[14]=l("h2",null,"Teachers & Courses",-1)),e(ce,{gutter:20,class:"main-content"},{default:t(()=>[e(re,{span:g.value?14:4,class:"teacher-list"},{default:t(()=>[e(Q,null,{default:t(()=>[(n(!0),k(ue,null,fe(w.value,ve=>(n(),N(oe,{key:ve.id,onClick:W=>O(ve)},{default:t(()=>[s(S(ve.name),1)]),_:2},1032,["onClick"]))),128))]),_:1})]),_:1},8,["span"]),e(re,{span:g.value?14:20,class:"course-details"},{default:t(()=>[v.value?(n(),k("div",Ra,[l("div",Fa,[l("h3",null,"Courses for "+S(v.value.name),1),l("div",Ba,[e(me,{size:"small",onClick:j,class:"teacher-detail"},{default:t(()=>[...E[2]||(E[2]=[s("查看教师详情",-1)])]),_:1}),e(me,{size:"small",onClick:X},{default:t(()=>[...E[3]||(E[3]=[s("导出为日历",-1)])]),_:1}
1)])]),l("div",Pa,[E[4]||(E[4]=s("余额: ",-1)),l("strong",null,S(C.value),1),E[5]||(E[5]=s(" 元",-1))]),e(ce,{gutter:20},{default:t(()=>[e(re,{span:g.value?24:16,class:"calendar-section"},{default:t(()=>[e(ie,{modelValue:m.value,"onUpdate:modelValue":E[0]||(E[0]=ve=>m.value=ve)},{"date-cell":t(({data:ve})=>[l("div",{class:"date-cell",onClick:W=>x(ve)},[l("div",Oa,S(ve.day.split("-").slice(1)[1]),1),K(ve)?(n(),k("div",qa)):te("",!0),H(ve)?(n(),k("div",Na)):te("",!0)],8,Ha)]),_:1},8,["modelValue"])]),_:1},8,["span"]),e(re,{span:g.value?24:8,class:Ye(["timeslots-section",{"mobile-hidden":g.value&&!V.value}])},{default:t(()=>[_.value?(n(),k("div",ja,[l("h4",null,"Timeslots for "+S(B(_.value)),1),p.value.length?(n(),k("div",Wa,[(n(!0),k(ue,null,fe(p.value,ve=>(n(),k("div",{key:ve.id,class:"timeslot-item"},[l("div",null,[l("div",null,[l("strong",null,S(ve.courseTitle),1)]),l("div",null,S(D(ve.start,ve.end)),1)]),l("div",null,[l("div",null,[!ve.booked||ve.available>0?(n(),N(me,{key:0,type:"success",size:"small",onClick:W=>U(ve.id)},{default:t(()=>[...E[6]||(E[6]=[s("Book",-1)])]),_:1},8,["onClick"])):ve.booked&&ve.mine&&!i(ve.start)?(n(),N(me,{key:1,type:"warning",size:"small",onClick:W=>F(ve.bookingId)},{default:t(()=>[...E[7]||(E[7]=[s("Cancel",-1)])]),_:1},8,["onClick"])):ve.booked&&ve.mine&&i(ve.start)?(n(),N(me,{key:2,type:"info",size:"small",disabled:""},{default:t(()=>[...E[8]||(E[8]=[s("已完成",-1)])]),_:1})):(n(),N(me,{key:3,disabled:"",size:"small"},{default:t(()=>[...E[9]||(E[9]=[s("Booked",-1)])]),_:1})),ve.booked&&ve.mine?(n(),N(me,{key:4,type:"info",size:"small",onClick:W=>M(ve.bookingId,ve.id)},{default:t(()=>[...E[10]||(E[10]=[s("笔记",-1)])]),_:1},8,["onClick"])):te("",!0)])])]))),128))])):(n(),k("div",Ka,[...E[11]||(E[11]=[l("p",null,"No timeslots on this day.",-1)])]))])):(n(),k("div",Ga,[...E[12]||(E[12]=[l("p",null,"Click a date to view available timeslots.",-1)])]))]),_:1},8,["span","class"])]),_:1})])):(n(),k("div",Ja,[...E[13]||(E[13]=[l("p",null,"Select a teacher to view courses.",-1)])]))]),_:1},8,["span"])]),_:1})]),_:1}),e(De,{title:"Notes",modelValue:u.value,"onUpdate:modelValue":E[1]||(E[1]=ve=>u.value=ve)},{default:t(()=>[e(Qt,{"booking-id":f.value,role:h.value,"show-content":"",onNotesUpdated:$},null,8,["booking-id","role"])]),_:1},8,["modelValue"])],64)}}}),Qa=Ce(Xa,[["__scopeId","data-v-79cf3c45"]]),Za={key:0},eo={key:1,class:"pagination-container"},mt=ge({__name:"PaginationTable",props:{data:{type:Object,required:!1},columns:{type:Array,required:!0},dataURL:{type:String,required:!0},deleteKey:{type:String,default:""}},emits:["data-loaded"],setup(q,{expose:c,emit:w}){const v=d(!1),y=d(!1),C=q,h=w,u=d({page:1,page_size:10,total:0,data:[]}),f=async()=>{if(C.dataURL!=="")try{v.value=!0;let V;u&&(V={...o,page:u.value.page,page_size:u.value.page_size});const z=await A.get(C.dataURL,{params:V});Array.isArray(z.data)?u.value={page:0,page_size:0,total:0,data:z.data}:u.value=z.data}catch(V){console.error("Failed to load data:",V)}finally{v.value=!1,h("data-loaded",u.value.data)}},m=()=>{g.value.forEach(V=>{V.searchKey?o[V.searchKey]="":o[V.prop]=""}),f()},_=V=>{u.value.page=V,f()},p=V=>{u.value.page_size=V,u.value.page=1,f()},r=async V=>{try{await et.confirm("确定要删除这个记录吗?","确认删除",{confirmButtonText:"确定",cancelButtonText:"取消",type:"warning"}),await A.delete(`${C.dataURL}/${V.id}`),f()}catch(z){console.error("Failed to delete record:",z)}},o=Ae({}),g=d([]);return be(()=>{const V=window.innerHeight;V<=770?u.value.page_size=10:V>=1180&&(u.value.page_size=20),C.columns.forEach(z=>{z.searchable&&(y.value=!0,g.value.push(z))}),f()}),c({loadData:f}),(V,z)=>{const M=a("el-date-picker"),L=a("el-option"),I=a("el-select"),O=a("el-input"),j=a("el-col"),R=a("el-button"),K=a("el-row"),H=a("el-table-column"),x=a("el-table"),B=a("el-pagination"),D=Ee("loading");return n(),k(ue,null,[y.value?(n(),k("div",Za,[e(K,{gutter:10,style:{"margin-bottom":"10px"}},{default:t(()=>[(n(!0),k(ue,null,fe(g.value,U=>(n(),N(j,{span:4},{default:t(()=>[U.searchKind==="date"?(n(),N(M,{key:0,modelValue:o[U.searchKey?U.searchKey:U.prop],"onUpdate:modelValue":F=>o[U.searchKey?U.searchKey:U.prop]=F,type:"datetime",placeholder:U.label,format:"YYYY-MM-DD HH:mm","value-format":"YYYY-MM-DDTHH:mm:ss[Z]",onChange:f,clearable:""},null,8,["modelValue","onUpdate:modelValue","placeholder"])):U.searchKind==="select"&&U.options?(n(),N(I,{key:1,modelValue:o[U.searchKey?U.searchKey:U.prop],"onUpdate:modelValue":F=>o[U.searchKey?U.searchKey:U.prop]=F,placeholder:U.label,onChange:f,clearable:""},{default:t(()=>[(n(!0),k(ue,null,fe(U.options,F=>(n(),N(L,{key:F.value,label:F.label,value:F.value},null,8,["label","value"]))),128))]),_:2},1032,["modelValue","onUpdate:modelValue","placeholder"])):(n(),N(O,{key:2,modelValue:o[U.searchKey?U.searchKey:U.prop],"onUpdate:modelValue":F=>o[U.searchKey?U.searchKey:U.prop]=F,placeholder:U.label,onKeyup:Je(f,["enter"]),clearable:""},null,8,["modelValue","onUpdate:modelValue","placeholder"]))]),_:2},1024))),256)),e(j,{span:4},{default:t(()=>[e(R,{type:"primary",onClick:f},{default:t(()=>[...z[0]||(z[0]=[s("搜索",-1)])]),_:1}),e(R,{type:"primary",onClick:m},{default:t(()=>[...z[1]||(z[1]=[s("重置",-1)])]),_:1}),Et(V.$slots,"button-tail")]),_:3})]),_:3})])):te("",!0),Me((n(),N(x,{data:u.value?u.value.data:[]},{default:t(()=>[(n(!0),k(ue,null,fe(q.columns,U=>(n(),N(H,{key:U.prop,label:U.label,prop:U.prop,width:U.width?U.width:null,formatter:U.formatter?U.formatter:null},Ot({_:2},[U.kind==="slot"?{name:"default",fn:t(({row:F})=>[Et(V.$slots,U.prop,{row:F})]),key:"0"}:void 0]),1032,["label","prop","width","formatter"]))),128)),C.deleteKey!==""?(n(),N(H,{key:0,label:"操作"},{default:t(({row:U})=>[e(R,{type:"danger",onClick:F=>r(U)},{default:t(()=>[...z[2]||(z[2]=[s("删除",-1)])]),_:1},8,["onClick"])]),_:1})):te("",!0)]),_:3},8,["data"])),[[D,v.value]]),u.value&&u.value.total>u.value.page_size?(n(),k("div",eo,[e(B,{onCurrentChange:_,onSizeChange:p,"current-page":u.value.page,"page-sizes":[10,20,50,100],"page-size":u.value.page_size,total:u.value.total,layout:"total, sizes, prev, pager, next, jumper",background:""},null,8,["current-page","page-size","total"])])):te("",!0)],64)}}}),to=ge({__name:"ClassHourRecords",setup(q,{expose:c}){const w=d(),v=[{label:"时间",prop:"created_at",width:"180",formatter:u=>C(u.created_at)},{label:"金额",prop:"amount",width:"100",kind:"slot"},{label:"缴费类型",prop:"payment_type",width:"120",kind:"slot"},{label:"备注",prop:"remarks"},{label:"操作员ID",prop:"admin_id",width:"100"}];async function y(){var u;(u=w.value)==null||u.loadData()}function C(u){return de(u).format("YYYY-MM-DD HH:mm")}function h(u){return Math.abs(u).toFixed(2)}return c({loadRecords:y}),(u,f)=>{const m=a("el-tag"),_=a("el-card");return n(),N(_,null,{header:t(()=>[...f[0]||(f[0]=[l("div",{class:"card-header"},[l("span",null,"缴费记录")],-1)])]),default:t(()=>[e(mt,{dataURL:"/api/my-payment-records",columns:v,ref_key:"paymentTable",ref:w}
1,{amount:t(({row:p})=>[l("span",{class:Ye(p.amount>0?"positive":"negative")},S(p.amount>0?"+":"")+S(h(p.amount)),3)]),payment_type:t(({row:p})=>[e(m,{type:p.payment_type==="regular"?"primary":"success"},{default:t(()=>[s(S(p.payment_type==="regular"?"正常缴费":"赠送金额"),1)]),_:2},1032,["type"])]),_:1},512)]),_:1})}}}),lo=ge({__name:"PastBookings",setup(q,{expose:c}){de.extend(pt),de.extend(xt),Ie();const w=d([]),v=d(!1),y=d(1),C=d(10),h=d(0),u=d("student"),f=[{label:"课程名称",prop:"courseTitle"},{label:"开始时间",prop:"start",formatter:(_,p,r)=>de(r).local().format("YYYY-MM-DD HH:mm")},{label:"结束时间",prop:"end",formatter:(_,p,r)=>de(r).local().format("YYYY-MM-DD HH:mm")},{label:"时长(小时)",formatter:_=>{const p=de(_.start).local(),r=de(_.end).local();return Math.ceil(r.diff(p,"hour",!0))}}];be(async()=>{try{const _=await A.get("/api/me");u.value=_.data.role}catch(_){console.error("Failed to get user info:",_)}m()});async function m(){try{v.value=!0;const _=await A.get("/api/my-past-bookings",{params:{page:y.value,page_size:C.value}});w.value=_.data.data||[],h.value=_.data.total||0}catch(_){console.error("Failed to load past bookings:",_)}finally{v.value=!1}}return c({loadBookings:m}),(_,p)=>{const r=a("el-card");return n(),N(r,null,{header:t(()=>[...p[0]||(p[0]=[l("div",{class:"card-header"},[l("span",null,"上课记录")],-1)])]),default:t(()=>[e(mt,{dataURL:"/api/my-past-bookings",columns:f})]),_:1})}}}),ao=Ce(lo,[["__scopeId","data-v-74762694"]]),oo=ge({__name:"MyNotes",props:{ownerRole:{type:String,default:""}},setup(q,{expose:c}){const w=Ie(),v=d([]),y=d(!1);be(()=>{C()});async function C(){try{y.value=!0;const _=await A.get("/api/my-notes");v.value=_.data||[]}catch(_){console.error("Failed to load notes:",_)}finally{y.value=!1}}function h(_){w.push(`/note/${_.id}`)}async function u(_){try{await A.delete(`/api/notes/${_}`),C()}catch(p){console.error("Failed to delete note:",p),alert("删除笔记失败")}}function f(_,p){return _?_.length>p?_.substring(0,p)+"...":_:""}function m(_){return de(_).format("YYYY-MM-DD HH:mm")}return c({loadNotes:C}),(_,p)=>{const r=a("el-button"),o=a("el-table-column"),g=a("el-tag"),V=a("el-table"),z=a("el-card"),M=Ee("loading");return n(),N(z,null,{header:t(()=>[...p[0]||(p[0]=[l("div",{class:"card-header"},[l("span",null,"我的笔记")],-1)])]),default:t(()=>[e(r,{type:"primary",size:"small",onClick:C},{default:t(()=>[...p[1]||(p[1]=[s("刷新",-1)])]),_:1}),Me((n(),N(V,{data:v.value,style:{width:"100%"}},{default:t(()=>[e(o,{prop:"id",label:"ID",width:"80"}),e(o,{prop:"content",label:"笔记内容"},{default:t(({row:L})=>[l("div",null,S(f(L.content,50)),1)]),_:1}),e(o,{prop:"is_public",label:"可见性",width:"100"},{default:t(({row:L})=>[e(g,{type:L.is_public?"success":"info"},{default:t(()=>[s(S(L.is_public?"公开":"私有"),1)]),_:2},1032,["type"])]),_:1}),e(o,{prop:"created_at",label:"创建时间",width:"180"},{default:t(({row:L})=>[s(S(m(L.created_at)),1)]),_:1}),e(o,{label:"操作",width:"150"},{default:t(({row:L})=>[e(r,{type:"primary",size:"small",onClick:I=>h(L)},{default:t(()=>[...p[2]||(p[2]=[s(" 查看 ",-1)])]),_:1},8,["onClick"]),L.student_id!==0&&q.ownerRole==="student"||L.teacher_id!==0&&q.ownerRole==="teacher"?(n(),N(r,{key:0,t
1ype:"danger",size:"small",onClick:I=>u(L.id)},{default:t(()=>[...p[3]||(p[3]=[s(" 删除 ",-1)])]),_:1},8,["onClick"])):te("",!0)]),_:1})]),_:1},8,["data"])),[[M,y.value]])]),_:1})}}}),Zt=Ce(oo,[["__scopeId","data-v-89bc58c6"]]),no=ge({name:"AiDictionary",props:{word:{type:String,default:""}},components:{},setup(q){const c=d({word:q.word||"",providerId:0,model:""}),w=d(!1),v=d(null),y=d(""),C=d("definitions"),h=d(null),u=d([]),f=d(null),m=d(!1),_=d(""),p=d(""),r=async()=>{var O,j;try{const R=await A.get("/api/user/api-providers");u.value=R.data;const K=R.data.find(H=>H.is_default);K&&(c.value.providerId=K.id,f.value=K,c.value.model=K.model||"")}catch(R){console.error("Load API providers error:",R),b.error("加载AI提供商失败: "+(((j=(O=R.response)==null?void 0:O.data)==null?void 0:j.error)||R.message))}},o=O=>{const j=u.value.find(R=>R.id===O);j?(f.value=j,c.value.model=j.model||""):f.value=null},g=async()=>{var O,j;if(!c.value.word.trim()){b.error("请输入要查询的单词");return}if(!c.value.providerId){b.error("请选择AI提供商");return}w.value=!0,y.value="";try{const R=await A.post("/api/dictionary/lookup",{word:c.value.word.trim(),provider_id:c.value.providerId,model:c.value.model},{timeout:9e4});v.value=R.data}catch(R){console.error("Dictionary lookup error:",R),y.value=((j=(O=R.response)==null?void 0:O.data)==null?void 0:j.error)||"查询失败,请稍后重试",b.error(y.value)}finally{w.value=!1}},V=()=>{h.value&&h.value.play().catch(O=>{console.error("Audio playback failed:",O),b.error("播放发音失败")})},z=O=>{c.value.word=O,g()},M=O=>O.replace(/\n/g,"<br>"),L=O=>O.replace(/\n/g,"<br>"),I=async()=>{var O,j;if(!c.value.word.trim()){b.error("请输入要查询的单词");return}if(!c.value.providerId){b.error("请选择AI提供商");return}m.value=!0,p.value="",_.value="";try{const R=await A.post("/api/dictionary/generate-image",{word:c.value.word.trim(),provider_id:c.value.providerId},{timeout:12e4});if(R.data.image_url)_.value=R.data.image_url;else if(R.data.image_data){const K=new Uint8Array(R.data.image_data.data||R.data.image_data);let H="";for(let x=0;x<K.byteLength;x++)H+=String.fromCharCode(K[x]);_.value=btoa(H)}else throw new Error("Invalid response format")}catch(R){console.error("Image generation error:",R),p.value=((j=(O=R.response)==null?void 0:O.data)==null?void 0:j.error)||"图像生成失败,请稍后重试",b.error(p.value)}finally{m.value=!1}};return be(()=>{r()}),{form:c,loading:w,result:v,error:y,activeTab:C,pronunciationAudio:h,apiProviders:u,selectedProvider:f,lookupWord:g,playPronunciation:V,searchSynonym:z,formatTips:M,formatEtymology:L,onProviderChange:o,loadApiProviders:r,imageLoading:m,generatedImage:_,imageError:p,generateImage:I}}}),so={class:"ai-dictionary"},ro={key:0,class:"result-section"},io={class:"word-title"},uo=["src"],co={class:"pos-type"},po={class:"pos-definition"},mo={class:"examples-section"},vo={class:"synonyms-list"},fo={key:0},_o={class:"antonyms-list"},yo={key:0},go=["innerHTML"],bo={key:0,class:"root-family-section"},wo={class:"root-family-tags"},ko=["innerHTML"],ho={class:"image-generation-section"},$o={key:0,class:"image-container"},Vo=["src"],Co=["src"],xo={key:1,class:"image-error"},Do={key:1,class:"error-section"};function So(q,c,w,v,y,C){const h=a("el-input"),u=a("el-form-item"),f=a("el-col"),m=a("el-option"),_=a("el-select"),p=a("el-row"),r=a("el-button"),o=a("el-form"),g=a("el-card"),V=a("video-play"),z=a("el-icon"),M=a("el-tab-pane"),L=a("el-tag"),I=a("el-alert"),O=a("el-tabs"),j=Ee("loading");return n(),k("div",so,[c[11]||(c[11]=l("div",{class:"main-header header"},[l("h2",null,"AI 英语词典")],-1)),Me((n(),N(g,{class:"search-card"},{default:t(()=>[e(o,{model:q.form,onSubmit:Oe(q.lookupWord,["prevent"]),"label-width":"auto"},{default:t(()=>[e(p,{gutter:20},{default:t(()=>[e(f,{span:12},{default:t(()=>[e(u,{label:"单词"},{default:t(()=>[e(h,{modelValue:q.form.word,"onUpdate:modelValue":c[0]||(c[0]=R=>q.form.word=R),placeholder:"请输入要查询的英文单词",onKeyup:Je(q.lookupWord,["enter"])},null,8,["modelValue","onKeyup"])]),_:1})]),_:1}),e(f,{span:12},{default:t(()=>[e(u,{label:"AI提供商"},{default:t(()=>[e(_,{modelValue:q.form.providerId,"onUpdate:modelValue":c[1]||(c[1]=R=>q.form.providerId=R),placeholder:"请选择AI提供商",onChange:q.onProviderChange},{default:t(()=>[(n(!0),k(ue,null,fe(q.apiProviders,R=>(n(),N(m,{key:R.id,label:R.name,value:R.id},null,8,["label","value"]))),128))]),_:1},8,["modelValue","onChange"])]),_:1})]),_:1})]),_:1}),e(u,null,{default:t(()=>[e(r,{type:"primary",onClick:q.lookupWord,loading:q.loading,disabled:!q.form.word||!q.form.providerId},{default:t(()=>[...c[5]||(c[5]=[s(" 查询单词 ",-1)])]),_:1},8,["onClick","loading","disabled"])]),_:1})]),_:1},8,["model","onSubmit"])]),_:1})),[[j,q.loading]]),q.result?Me((n(),k("div",ro,[e(g,{class:"word-header"},{default:t(()=>[l("div",io,[l("h3",null,S(q.result.word),1),e(r,{type:"primary",circle:"",onClick:q.playPronunciation,title:"播放发音"},{default:t(()=>[e(z,null,{default:t(()=>[e(V)]),_:1})]),_:1},8,["onClick"])])]),_:1}),l("audio",{ref:"pronunciationAudio",src:`https://dict.youdao.com/dictvoice?type=0&audio=${q.result.word}`,preload:"none"},null,8,uo),e(O,{modelValue:q.activeTab,"onUpdate:modelValue":c[3]||(c[3]=R=>q.activeTab=R)},{default:t(()=>[e(M,{label:"词性与释义",name:"definitions"},{default:t(()=>[(n(!0),k(ue,null,fe(q.result.parts_of_speech,(R,K)=>(n(),k("div",{key:K,class:"part-of-speech"},[e(g,{class:"pos-card"},{default:t(()=>[l("div",co,S(R.type),1),l("div",po,S(R.definition),1),l("div",mo,[c[6]||(c[6]=l("h4",null,"例句:",-1)),l("ul",null,[(n(!0),k(ue,null,fe(R.examples,(H,x)=>(n(),k("li",{key:x},S(H),1))),128))])])]),_:2},1024)]))),128))]),_:1}),e(M,{label:"同义词与反义词",name:"synonyms_antonyms"},{default:t(()=>[e(p,{gutter:20},{default:t(()=>[e(f,{span:12},{default:t(()=>[e(g,{class:"synonyms-card"},{header:t(()=>[...c[7]||(c[7]=[l("div",{class:"card-header"},[l("span",null,"同义词")],-1)])]),default:t(()=>[l("div",vo,[(n(!0),k(ue,null,fe(q.result.synonyms,(R,K)=>(n(),N(L,{key:K,type:"primary",class:"synonym-tag",onClick:H=>q.searchSynonym(R)},{default:t(()=>[s(S(R),1)]),_:2},1032,["onClick"]))),128)),!q.result.synonyms||q.result.synonyms.length===0?(n(),k("p",fo,"暂无同义词信息")):te("",!0)])]),_:1})]),_:1}),e(f,{span:12},{default:t(()=>[e(g,{class:"antonyms-card"},{header:t(()=>[...c[8]||(c[8]=[l("div",{class:"card-header"},[l("span",null,"反义词")],-1)])]),default:t(()=>[l("div",_o,[(n(!0),k(ue,null,fe(q.result.antonyms,(R,K)=>(n(),N(L,{key:K,type:"danger",class:"antonym-tag",onClick:H=>q.searchSynonym(R)},{default:t(()=>[s(S(R),1)]),_:2},1032,["onClick"]))),128)),!q.result.antonyms||q.result.antonyms.length===0?(n(),k("p",yo,"暂无反义词信息")):te("",!0)])]),_:1})]),_:1})]),_:1})]),_:1}),e(M,{label:"词根词缀",name:"etymology"},{default:t(()=>[e(g,{class:"etymology-card"},{default:t(()=>[l("div",{class:"etymology-content",innerHTML:q.formatEtymology(q.result.etymology)},null,8,go),q.result.root_family&&q.result.root_family.length>0?(n(),k("div",bo,[c[9]||(c[9]=l("h4",null,"相同词根的单词:",-1)),l("div",w
1o,[(n(!0),k(ue,null,fe(q.result.root_family,(R,K)=>(n(),N(L,{key:K,type:"info",class:"root-family-tag",onClick:H=>q.searchSynonym(R)},{default:t(()=>[s(S(R),1)]),_:2},1032,["onClick"]))),128))])])):te("",!0)]),_:1})]),_:1}),e(M,{label:"记忆技巧",name:"memorization"},{default:t(()=>[e(g,{class:"tips-card"},{default:t(()=>[l("div",{class:"tips-content",innerHTML:q.formatTips(q.result.memorization_tips)},null,8,ko)]),_:1})]),_:1}),e(M,{label:"单词图像",name:"image"},{default:t(()=>[e(g,{class:"image-card"},{default:t(()=>[l("div",ho,[e(r,{type:"primary",onClick:q.generateImage,loading:q.imageLoading,disabled:!q.form.word||!q.form.providerId},{default:t(()=>[...c[10]||(c[10]=[s(" 生成图像 ",-1)])]),_:1},8,["onClick","loading","disabled"]),q.generatedImage?(n(),k("div",$o,[q.generatedImage.startsWith("http")?(n(),k("img",{key:0,src:q.generatedImage,alt:"Generated image",class:"generated-image"},null,8,Vo)):(n(),k("img",{key:1,src:"data:image/png;base64,"+q.generatedImage,alt:"Generated image",class:"generated-image"},null,8,Co))])):te("",!0),q.imageError?(n(),k("div",xo,[e(I,{title:q.imageError,type:"error","show-icon":"",closable:"",onClose:c[2]||(c[2]=R=>q.imageError="")},null,8,["title"])])):te("",!0)])]),_:1})]),_:1})]),_:1},8,["modelValue"])])),[[j,q.loading]]):te("",!0),q.error?(n(),k("div",Do,[e(I,{title:q.error,type:"error","show-icon":"",closable:"",onClose:c[4]||(c[4]=R=>q.error="")},null,8,["title"])])):te("",!0)])}const yt=Ce(no,[["render",So],["__scopeId","data-v-7b479e9c"]]),Ke={"1st-grade":"一年级","1st-grade-season-2":"一年级下册","2nd-grade":"二年级","2nd-grade-season-2":"二年级下册","3rd-grade":"三年级","3rd-grade-season-2":"三年级下册","4th-grade":"四年级","4th-grade-season-2":"四年级下册","4th-grade-seasson-2":"四年级下册","5th-grade":"五年级","5th-grade-season-2":"五年级下册","6th-grade":"六年级","6th-grade-season-2":"六年级下册","7th-grade":"七年级","7th-grade-season-2":"七年级下册","8th-grade":"八年级","8th-grade-season-2":"八年级下册","9th-grade":"九年级","9th-grade-season-2":"九年级下册","10th-grade":"高一","10th-grade-season-2":"高一下册","11th-grade":"高二","11th-grade-season-2":"高二下册","12th-grade":"高三","12th-grade-season-2":"高三下册","high-school-mandatory-1":"高中必修一","high-school-mandatory-2":"高中必修二","high-school-mandatory-3":"高中必修三","high-school-optional-1":"高中必修一","high-school-optional-2":"高中必修二","high-school-optional-3":"高中必修三","high-school-optional-4":"高中选修四"},Mo={class:"vocabulary-learning"},Uo={class:"header"},Io={class:"grade-selector"},To={key:0,class:"progress-info"},Ao={class:"dialog-footer"},zo={key:1,class:"game-area"},Lo={class:"words-column"},Yo={class:"word-text"},Eo={class:"words-audio"},Ro=["src"],Fo=["src"],Bo={class:"definitions-column"},Po={class:"definition-text"},Ho={key:2,class:"game-area"},Oo={key:3,class:"no-vocabulary"},qo={key:4,class:"no-grade"},No={class:"stats"},jo=ge({__name:"VocabularyLearning",setup(q){const c=Ie(),w=d(!1),v=d(null),y=d(null),C=d(!1),h=d([]),u=d(""),f=d([]),m=d(null),_=d([]),p=d(null),r=d(null),o=d([]),g=d({learned:0,remaining:0,total:0}),V=d(!1),z=d(!1),M=d(""),L=()=>{c.push("/vocabulary-leaderboard")},I=Le(()=>o.value.filter(oe=>oe.was_correct).length),O=Le(()=>o.value.filter(oe=>!oe.was_correct).length),j=Le(()=>o.value.length===0?0:Math.round(I.value/o.value.length*100)),R=async()=>{if(!u.value){b.warning("请选择年级");return}try{const oe=await A.get(`/api/vocabulary/grade/${u.value}`);f.value=oe.data,X(),await H(),await K(),x()}catch(oe){b.error("加载词汇失败"),console.error(oe)}},K=async()=>{if(u.value)try{const oe=await A.get(`/api/vocabulary/progress/${u.value}`);g.value=oe.data}catch(oe){b.error("加载学习进度失败"),console.error(oe)}},H=async()=>{try{const oe=await A.get("/api/vocabulary/practice-records");o.value=oe.data}catch(oe){b.error("加载学习记录失败"),console.error(oe)}},x=()=>{V.value=!1;const oe=f.value.filter(De=>!o.value.some(ve=>ve.word_id===De.id&&ve.was_correct));if(oe.length===0){m.value=null,_.value=[];return}const Q=Math.floor(Math.random()*oe.length);m.value=oe[Q];const re=m.value.definitions[Math.floor(Math.random()*m.value.definitions.length)];if(!re)return;const me=[];f.value.forEach(De=>{o.value.some(ve=>ve.word_id===De.id&&ve.was_correct)||De.definitions.forEach(ve=>{ve.id!==re.id&&me.push(ve)})});const ce=[...me].sort(()=>.5-Math.random()).slice(0,3),ke=[re,...ce];_.value=[...ke].sort(()=>.5-Math.random())},B=oe=>{p.value=oe,r.value=null},D=oe=>m.value?m.value.definitions.some(Q=>Q.id===oe.id):!1,U=oe=>{V.value||(r.value=oe,p.value&&F(oe))}
1,F=async oe=>{if(!m.value)return;const Q=m.value.definitions.some(re=>re.id===oe.id);try{if(w.value=!0,await A.post("/api/vocabulary/practice-records",{word_id:m.value.id,definition_id:oe.id,was_correct:Q}),o.value.push({word_id:m.value.id,definition_id:oe.id,was_correct:Q}),Q)await K(),b.success("匹配正确!"),setTimeout(()=>{x()},1e3);else{V.value=!0;const re=m.value.definitions.find(me=>{var ie;return(ie=m.value)==null?void 0:ie.definitions.some(ce=>ce.id===me.id)});M.value=(re==null?void 0:re.text)||"",z.value=!0,await K()}p.value=null,r.value=null}catch(re){b.error("记录练习结果失败"),console.error(re)}finally{w.value=!1}},i=()=>{z.value=!1,setTimeout(()=>{x()},500)},$=()=>{z.value=!1,setTimeout(()=>{x()},500)},X=()=>{p.value=null,r.value=null,m.value=null,_.value=[],V.value=!1,z.value=!1},G=oe=>{oe&&oe.play()};be(async()=>{await E(),H()});async function E(){try{const oe=await A.get("/api/public/vocabulary/grades");h.value=oe.data.map(Q=>({value:Q,label:Ke[Q]||Q}))}catch(oe){b.error("加载年级选项失败"),console.error(oe)}}return(oe,Q)=>{var De,ve;const re=a("el-button"),me=a("el-option"),ie=a("el-select"),ce=a("el-card"),ke=Ee("loading");return n(),k(ue,null,[l("div",Mo,[l("div",Uo,[Q[8]||(Q[8]=l("h2",null,"英语词汇学习",-1)),e(re,{onClick:L,type:"primary",plain:""},{default:t(()=>[...Q[7]||(Q[7]=[s("查看排行榜",-1)])]),_:1})]),l("div",Io,[e(ie,{modelValue:u.value,"onUpdate:modelValue":Q[0]||(Q[0]=W=>u.value=W),placeholder:"选择年级",onChange:R},{default:t(()=>[(n(!0),k(ue,null,fe(h.value,W=>(n(),N(me,{key:W.value,label:W.label,value:W.value},null,8,["label","value"]))),128))]),_:1},8,["modelValue"]),e(re,{onClick:R,type:"primary",style:{"margin-left":"10px"}},{default:t(()=>[...Q[9]||(Q[9]=[s("加载词汇",-1)])]),_:1})]),u.value&&f.value.length>0?(n(),k("div",To,[l("p",null,"已学单词: "+S(g.value.learned)+" | 未学单词: "+S(g.value.remaining)+" | 总计: "+S(g.value.total),1)])):te("",!0),e(se(Bt),{modelValue:z.value,"onUpdate:modelValue":Q[1]||(Q[1]=W=>z.value=W),title:"正确答案",width:"30%","before-close":$},{footer:t(()=>[l("span",Ao,[e(re,{type:"primary",onClick:i},{default:t(()=>[...Q[10]||(Q[10]=[s("确定",-1)])]),_:1})])]),default:t(()=>{var W;return[l("span",null,'正确答案是: "'+S((W=m.value)==null?void 0:W.word)+'" - '+S(M.value),1)]}),_:1},8,["modelValue"]),m.value?Me((n(),k("div",zo,[l("div",Lo,[Q[14]||(Q[14]=l("h3",null,"单词",-1)),Me((n(),N(ce,{key:m.value.id,class:Ye([{selected:((De=p.value)==null?void 0:De.id)===m.value.id,highlighted:((ve=p.value)==null?void 0:ve.id)===m.value.id},"word-card"]),onClick:Q[2]||(Q[2]=W=>B(m.value))},{default:t(()=>[l("div",Yo,S(m.value.word),1)]),_:1},8,["class"])),[[ke,w.value]]),l("div",Eo,[l("audio",{ref_key:"usAudio",ref:v,src:`https://dict.youdao.com/dictvoice?type=0&audio=${m.value.word}`},null,8,Ro),l("audio",{ref_key:"ukAudio",ref:y,src:`https://dict.youdao.com/dictvoice?type=1&audio=${m.value.word}`},null,8,Fo),e(re,{onClick:Q[3]||(Q[3]=W=>G(v.value)),type:"primary",size:"small"},{default:t(()=>[...Q[11]||(Q[11]=[s("英音",-1)])]),_:1}),e(re,{onClick:Q[4]||(Q[4]=W=>G(y.value)),type:"primary",size:"small"},{default:t(()=>[...Q[12]||(Q[12]=[s("美音",-1)])]),_:1}),e(re,{onClick:Q[5]||(Q[5]=W=>C.value=!0),type:"primary",size:"small"},{default:t(()=>[...Q[13]||(Q[13]=[s("查字典",-1)])]),_:1})])]),l("div",Bo,[Q[15]||(Q[15]=l("h3",null,"定义",-1)),(n(!0),k(ue,null,fe(_.value,W=>{var Z,Ve,xe;return Me((n(),N(ce,{key:W.id,class:Ye([{selected:((Z=r.value)==null?void 0:Z.id)===W.id,highlighted:((Ve=r.value)==null?void 0:Ve.id)===W.id,correct:V.value&&D(W),incorrect:V.value&&((xe=r.value)==null?void 0:xe.id)===W.id&&!D(W)},"definition-card"]),onClick:ae=>U(W)},{default:t(()=>[l("div",Po,S(W.text),1)]),_:2},1032,["class","onClick"])),[[ke,w.value]])}),128))])])),[[ke,w.value]]):u.value&&f.value.length>0?(n(),k("div",Ho,[...Q[16]||(Q[16]=[l("div",{class:"words-column"},[l("h3",null,"单词"),l("p",null,"已完成所有词汇练习")],-1),l("div",{class:"definitions-column"},[l("h3",null,"定义"),l("p",null,"已完成所有词汇练习")],-1)])])):u.value?(n(),k("div",Oo,[...Q[17]||(Q[17]=[l("p",null,"该年级暂无词汇数据",-1)])])):(n(),k("div",qo,[...Q[18]||(Q[18]=[l("p",null,"请选择年级开始学习",-1)])])),l("div",No,[Q[19]||(Q[19]=l("h3",null,"学习统计",-1)),l("p",null,"正确: "+S(I.value)+" | 错误: "+S(O.value)+" | 正确率: "+S(j.value)+"%",1)])]),e(se(Bt),{modelValue:C.value,"onUpdate:modelValue":Q[
16]||(Q[6]=W=>C.value=W),width:"50%",fullscreen:""},{default:t(()=>{var W;return[e(yt,{word:(W=m.value)==null?void 0:W.word},null,8,["word"])]}),_:1},8,["modelValue"])],64)}}}),Wo=Ce(jo,[["__scopeId","data-v-d08f074f"]]),Ko={class:"vocabulary-dictation"},Go={class:"main-header header"},Jo={class:"grade-selector"},Xo={class:"settings"},Qo={key:0,class:"dictation-area"},Zo={class:"progress-info"},en={key:0,class:"current-word"},tn={key:0},ln={key:1},an={key:2},on={key:3},nn={class:"controls"},sn=["src"],rn={key:1,class:"no-vocabulary"},un={key:2,class:"no-grade"},dn={key:3,class:"print-section"},cn={class:"print-controls"},pn={key:0,class:"exercise-sheet"},mn={class:"sheet-words"},vn={class:"word-index"},fn={class:"word-blank"},_n={class:"sheet-actions"},yn={class:"print-header"},gn={class:"print-content"},bn={class:"print-word-index"},wn={class:"print-word-blank"},kn={class:"dialog-footer"},hn={class:"dialog-footer"},$n=ge({__name:"VocabularyDictation",setup(q){const c=d(!1),w=d(!1),v=d(!1),y=d(!1),C=d([]),h=d(!1),u=d(!1),f=d(null),m=!!sessionStorage.getItem("token"),_=d(!1),p=d("unmastered"),r=d([]),o=d([]),g=d([]),V=d(""),z=d(""),M=d(""),L=d([]),I=d([]),O=d(null),j=async()=>{try{const ae=await A.get("/api/public/vocabulary/labels",{params:{grade:z.value,unit:M.value}});g.value=ae.data,ae.data&&ae.data.length>0?V.value=V.value||ae.data[0]:V.value=""}catch(ae){console.error(ae)}};je([z,M],()=>{j()});async function R(){try{const ae=await A.get("/api/public/vocabulary/grades");o.value=ae.data.map(ee=>({value:ee,label:Ke[ee]||ee}))}catch(ae){b.error("加载年级选项失败"),console.error(ae)}}const K=d({interval:3,repeat:2}),H=d(!1),x=d(!1),B=d(0),D=d(null),U=d(0),F=Le(()=>i()),i=()=>{const ae=$.value;return B.value>=0&&B.value<ae.length?ae[B.value]:null},$=Le(()=>m&&p.value==="unmastered"?I.value.filter(ae=>!E(ae.id)):I.value),X=Le(()=>I.value.filter(ae=>E(ae.id)).length),G=Le(()=>F.value?E(F.value.id):!1),E=ae=>{const ee=r.value.filter(Y=>Y.word_id===ae);return ee.length===0?!1:ee[ee.length-1].was_correct},oe=async()=>{if(!m||!F.value){b.warning("请先登录或选择单词");return}await Q(F.value)},Q=async ae=>{var Y;if(!m){b.warning("请先登录");return}const ee=E(ae.id);try{ee?(await A.post("/api/vocabulary/practice-records",{word_id:ae.id,definition_id:0,was_correct:!1}),r.value.push({word_id:ae.id,was_correct:!1}),b.info(`已取消"${ae.word}"的掌握标记`)):(await A.post("/api/vocabulary/practice-records",{word_id:ae.id,definition_id:((Y=ae.definitions[0])==null?void 0:Y.id)||0,was_correct:!0}),r.value.push({word_id:ae.id,was_correct:!0}),b.success(`已标记"${ae.word}"为掌握`))}catch(P){b.error("操作失败"),console.error(P)}},re=async()=>{if(m)try{const ae=await A.get("/api/vocabulary/practice-records");r.value=ae.data}catch(ae){console.error("加载练习记录失败:",ae)}},me=async()=>{if(M.value="",L.value=[],I.value=[],!!z.value)try{const ae=m?`/api/vocabulary/grade/${z.value}/units`:`/api/public/vocabulary/grade/${z.value}/units`,ee=await A.get(ae);L.value=ee.data}catch(ae){b.error("加载单元列表失败"),console.error(ae)}},ie=async()=>{if(!z.value||!M.value){b.warning("请选择年级和单元");return}try{m&&await re();const ae=m?`/api/vocabulary/grade/${z.value}/unit/${M.value}`:`/api/public/vocabulary/grade/${z.value}/unit/${M.value}`,ee=await A.get(ae,{params:{label:V.value}});I.value=ee.data,B.value=0,I.value.length===0?b.info("该单元暂无词汇数据"):b.success("词汇加载成功")}catch(ae){b.error("加载词汇失败"),console.error(ae)}},ce=()=>{O.value&&F.value&&(O.value.currentTime=0,O.value.play().catch(ae=>{console.error("播放失败:",ae),b.error("单词播放失败")}))},ke=()=>{if($.value.length===0){b.warning("没有可听写的单词,请检查过滤设置");return}H.value=!0,x.value=!1,B.value=0,U.value=0,W()},De=()=>{H.value?(H.value=!1,x.value=!0,D.value&&(clearTimeout(D.value),D.value=null),b.info("听写已暂停")):x.value&&(H.value=!0,x.value=!1,W(),b.info("听写已恢复"))},ve=()=>{H.value=!1,x.value=!1,B.value=0,D.value&&(clearTimeout(D.value),D.value=null),b.info("听写已停止")},W=()=>{if(!H.value)return;const ae=$.value;if(B.value>=ae.length){ve(),b.success("听写完成!");return}U.value<K.value.repeat?(ce(),U.value++,D.value=window.setTimeout(()=>{W()},K.value.interval*1e3)):(U.value=0,B.value++,D.value=window.setTimeout(()=>{W()},K.value.interval*1e3))},Z=()=>{C.value=I.value.map(ae=>{const ee=ae.word;
1if(ee.length<=3)return{word:ee,hiddenWord:ee};const Y=Math.min(3,ee.length-2),P=Math.floor(Math.random()*Y)+1,ne=Array.from({length:ee.length-2},(Se,We)=>We+1);for(let Se=ne.length-1;Se>0;Se--){const We=Math.floor(Math.random()*(Se+1));[ne[Se],ne[We]]=[ne[We],ne[Se]]}const we=ne.slice(0,P);let _e="";for(let Se=0;Se<ee.length;Se++)we.includes(Se)?_e+="_":_e+=ee[Se];return{word:ee,hiddenWord:_e}}),b.success("练习单生成成功!")},Ve=()=>{if(!f.value)return;const ae=f.value.innerHTML,ee=document.body.innerHTML;document.body.innerHTML=ae,window.print(),document.body.innerHTML=ee,h.value=!1,location.reload()},xe=ae=>{u.value=!1,ae()};return be(()=>{R()}),ct(()=>{D.value&&clearTimeout(D.value)}),(ae,ee)=>{var lt;const Y=a("el-button"),P=a("el-option"),ne=a("el-select"),we=a("el-input-number"),_e=a("el-form-item"),Se=a("el-form"),We=a("el-switch"),tt=a("Printer"),Xe=a("el-icon"),Ge=a("el-checkbox"),qe=a("el-dialog");return n(),k(ue,null,[l("div",Ko,[l("div",Go,[ee[18]||(ee[18]=l("h2",null,"单词听写练习",-1)),e(Y,{onClick:ee[0]||(ee[0]=ye=>y.value=!0),type:"warning",size:"small"},{default:t(()=>[...ee[17]||(ee[17]=[s(" 问题反馈 ",-1)])]),_:1})]),l("div",Jo,[e(ne,{modelValue:z.value,"onUpdate:modelValue":ee[1]||(ee[1]=ye=>z.value=ye),placeholder:"选择年级",onChange:me},{default:t(()=>[(n(!0),k(ue,null,fe(o.value,ye=>(n(),N(P,{key:ye.value,label:ye.label,value:ye.value},null,8,["label","value"]))),128))]),_:1},8,["modelValue"]),e(ne,{modelValue:M.value,"onUpdate:modelValue":ee[2]||(ee[2]=ye=>M.value=ye),placeholder:"选择单元",onChange:ie,disabled:!z.value},{default:t(()=>[(n(!0),k(ue,null,fe(L.value,ye=>(n(),N(P,{key:ye,label:ye,value:ye},null,8,["label","value"]))),128))]),_:1},8,["modelValue","disabled"]),g.value&&g.value.length>0?(n(),N(ne,{key:0,modelValue:V.value,"onUpdate:modelValue":ee[3]||(ee[3]=ye=>V.value=ye),placeholder:"选择标签",onChange:ie,clearable:""},{default:t(()=>[(n(!0),k(ue,null,fe(g.value,ye=>(n(),N(P,{key:ye,label:ye,value:ye},null,8,["label","value"]))),128))]),_:1},8,["modelValue"])):te("",!0),m?(n(),N(ne,{key:1,modelValue:p.value,"onUpdate:modelValue":ee[4]||(ee[4]=ye=>p.value=ye),placeholder:"掌握状态",disabled:!m||I.value.length===0},{default:t(()=>[e(P,{label:"未掌握",value:"unmastered"}),e(P,{label:"所有",value:"all"})]),_:1},8,["modelValue","disabled"])):te("",!0)]),l("div",Xo,[e(Se,{inline:!0,model:K.value,class:"demo-form-inline","label-width":"auto"},{default:t(()=>[e(_e,{label:"播放间隔(秒)"},{default:t(()=>[e(we,{modelValue:K.value.interval,"onUpdate:modelValue":ee[5]||(ee[5]=ye=>K.value.interval=ye),min:1,max:10},null,8,["modelValue"])]),_:1}),e(_e,{label:"重复次数"},{default:t(()=>[e(we,{modelValue:K.value.repeat,"onUpdate:modelValue":ee[6]||(ee[6]=ye=>K.value.repeat=ye),min:1,max:5},null,8,["modelValue"])]),_:1}),e(_e,null,{default:t(()=>[e(Y,{type:"primary",onClick:ke,disabled:!I.value.length||H.value},{default:t(()=>[s(S(x.value?"重新开始":"开始听写"),1)]),_:1},8,["disabled"]),e(Y,{onClick:De,disabled:!H.value&&!x.value},{default:t(()=>[s(S(x.value?"恢复听写":"暂停听写"),1)]),_:1},8,["disabled"]),e(Y,{onClick:ve,disabled:!H.value&&!x.value},{default:t(()=>[...ee[19]||(ee[19]=[s("停止听写",-1)])]),_:1},8,["disabled"])]),_:1})]),_:1},8,["model"])]),z.value&&M.value&&I.value.length>0?(n(),k("div",Qo,[l("div",Zo,[l("p",null,S(se(Ke)[z.value])+" - "+S(M.value)+" : 单词总数: "+S(I.value.length)+" | 已掌握: "+S(X.value)+" | 待听写: "+S($.value.length),1)]),B.value>=0&&B.value<$.value.length?(n(),k("div",en,[H.value?(n(),k("h3",tn,"正在播放: "+S(B.value+1)+" / "+S($.value.length),1)):(n(),k("h3",ln,"当前单词: "+S(B.value+1)+" / "+S($.value.length),1)),w.value?(n(),k("p",an,"单词: "+S($.value[B.value].word),1)):(n(),k("p",on,"单词已隐藏"))])):te("",!0),l("div",nn,[e(We,{modelValue:w.value,"onUpdate:modelValue":ee[7]||(ee[7]=ye=>w.value=ye),"active-text":"显示单词","inactive-text":"隐藏单词","inline-prompt":""},null,8,["modelValue"]),l("audio",{ref_key:"wordAudio",ref:O,src:`https://dict.youdao.com/dictvoice?type=0&audio=${((lt=F.value)==null?void 0:lt.word)||""}`},null,8,sn),e(Y,{onClick:ce,disabled:H.value},{default:t(()=>[...ee[20]||(ee[20]=[s("播放当前单词",-1)])]),_:1},8,["disabled"]),m?(n(),N(Y,{key:0,onClick:ee[8]||(ee[8]=ye=>c.value=!0)},{default:t(()=>
1[...ee[21]||(ee[21]=[s("查字典",-1)])]),_:1})):te("",!0),m?(n(),N(Y,{key:1,type:G.value?"success":"default",onClick:oe},{default:t(()=>[s(S(G.value?"已掌握":"标记为已掌握"),1)]),_:1},8,["type"])):te("",!0),m?(n(),N(Y,{key:2,onClick:ee[9]||(ee[9]=ye=>_.value=!_.value),type:"primary",class:"hide-text-xs"},{default:t(()=>[ee[22]||(ee[22]=l("span",null,"打印单词",-1)),e(Xe,null,{default:t(()=>[e(tt)]),_:1})]),_:1})):te("",!0)])])):z.value&&M.value?(n(),k("div",rn,[...ee[23]||(ee[23]=[l("p",null,"该单元暂无词汇数据",-1)])])):(n(),k("div",un,[...ee[24]||(ee[24]=[l("p",null,"请选择年级和单元开始听写",-1)])])),m&&I.value.length>0&&_.value?(n(),k("div",dn,[ee[27]||(ee[27]=l("h3",null,"练习模式",-1)),l("div",cn,[e(Y,{onClick:Z,type:"primary"},{default:t(()=>[...ee[25]||(ee[25]=[s("生成练习单",-1)])]),_:1}),e(Y,{onClick:ee[10]||(ee[10]=ye=>h.value=!0),disabled:C.value.length===0},{default:t(()=>[...ee[26]||(ee[26]=[s("打印预览",-1)])]),_:1},8,["disabled"])]),C.value.length>0?(n(),k("div",pn,[l("div",mn,[(n(!0),k(ue,null,fe(C.value,(ye,Fe)=>(n(),k("div",{key:Fe,class:"exercise-word-item"},[l("span",vn,S(Fe+1)+".",1),l("span",fn,S(ye.hiddenWord),1),Me(l("span",{class:"word-original"},"("+S(ye.word)+")",513),[[it,v.value]])]))),128))]),l("div",_n,[e(Ge,{modelValue:v.value,"onUpdate:modelValue":ee[11]||(ee[11]=ye=>v.value=ye),label:"显示答案"},null,8,["modelValue"])])])):te("",!0)])):te("",!0)]),e(qe,{modelValue:h.value,"onUpdate:modelValue":ee[13]||(ee[13]=ye=>h.value=ye),title:"打印预览",width:"80%",class:"print-preview-dialog","before-close":xe},{footer:t(()=>[l("div",kn,[e(Y,{onClick:ee[12]||(ee[12]=ye=>h.value=!1)},{default:t(()=>[...ee[29]||(ee[29]=[s("取消",-1)])]),_:1}),e(Y,{type:"primary",onClick:Ve},{default:t(()=>[...ee[30]||(ee[30]=[s("打印",-1)])]),_:1})])]),default:t(()=>[l("div",{ref_key:"printArea",ref:f,class:"print-area"},[ee[28]||(ee[28]=l("h2",{class:"print-title"},"单词听写练习单",-1)),l("div",yn,[l("p",null,"年级: "+S(se(Ke)[z.value])+" 单元: "+S(M.value)+" 单词数: "+S(C.value.length),1)]),l("div",gn,[(n(!0),k(ue,null,fe(C.value,(ye,Fe)=>(n(),k("div",{key:Fe,class:"print-exercise-word"},[l("span",bn,S(Fe+1)+".",1),l("span",wn,S(ye.hiddenWord),1),Me(l("span",{class:"print-word-original"},"("+S(ye.word)+")",513),[[it,u.value]])]))),128))])],512)]),_:1},8,["modelValue"]),e(qe,{modelValue:c.value,"onUpdate:modelValue":ee[14]||(ee[14]=ye=>c.value=ye),width:"50%",fullscreen:""},{default:t(()=>{var ye;return[e(yt,{word:(ye=F.value)==null?void 0:ye.word},null,8,["word"])]}),_:1},8,["modelValue"]),e(qe,{modelValue:y.value,"onUpdate:modelValue":ee[16]||(ee[16]=ye=>y.value=ye),"body-class":"feedback-dialog",title:"问题反馈"},{footer:t(()=>[l("div",hn,[e(Y,{onClick:ee[15]||(ee[15]=ye=>y.value=!1)},{default:t(()=>[...ee[31]||(ee[31]=[s("关闭",-1)])]),_:1})])]),default:t(()=>[ee[32]||(ee[32]=l("div",{class:"feedback-content"},[l("p",null,"如有任何问题或建议,请联系管理员:"),l("img",{src:Xt,alt:"管理员微信二维码",class:"wechat-qrcode"}),l("p",{class:"text-center"},"扫描上方二维码添加管理员微信")],-1))]),_:1},8,["modelValue"])],64)}}}),Vn=Ce($n,[["__scopeId","data-v-52a5f536"]]),Cn={class:"grade-unit-selector"},xn={class:"form-tip"},Dn={class:"word-count-info"},Sn={key:0,class:"composition-area"},Mn={class:"composition-header"},Un={class:"actions"},In={class:"composition-content"},Tn=["innerHTML"],An={class:"used-words"},zn={key:1,class:"no-vocabulary"},Ln={key:2,class:"no-selection"},Yn={key:3,class:"loading"},En=ge({__name:"VocabularyComposition",setup(q){const c=d([]),w=d(""),v=d(""),y=d(1),C=d([]),h=d([]),u=d(null),f=d(!1),m=d(!1),_=d(!1),p=d(!1),r=d(!1),o=d(null),g=window.speechSynthesis,V=d({wordCount:0,theme:"",style:"",writingGuide:""}),z=d(!1),M=Le(()=>{if(h.value.length===0)return"80-120";const D=Math.min(h.value.length*5,240),U=Math.round(D*.8),F=Math.round(D*1.2);return`${U}-${F}`}),L=async()=>{try{const D=await A.get("/api/public/vocabulary/grades");c.value=D.data.map(U=>({value:U,label:Ke[U]||U}))}catch(D){b.error("加载年级选项失败"),console.error(D)}},I=async()=>
1{if(v.value="",C.value=[],h.value=[],u.value=null,!!w.value)try{const D=await A.get(`/api/vocabulary/grade/${w.value}/units`);C.value=D.data}catch(D){b.error("加载单元列表失败"),console.error(D)}},O=async()=>{if(!w.value||!v.value){b.warning("请选择年级和单元");return}try{const D=await A.get(`/api/vocabulary/grade/${w.value}/unit/${v.value}`);if(h.value=D.data,h.value.length===0)b.info("该单元暂无词汇数据");else{b.success(`已加载 ${h.value.length} 个单词`);const U=Math.min(h.value.length*5,240);V.value.wordCount=U}}catch(D){b.error("加载词汇失败"),console.error(D)}},j=async()=>{if(h.value.length===0){b.warning("请先加载词汇");return}f.value=!0,u.value=null;try{const D=h.value.map(F=>F.word),U=await A.post("/api/ai/compose",{words:D,grade:w.value,unit:v.value,word_count:V.value.wordCount||void 0,theme:V.value.theme||void 0,style:V.value.style||void 0,writing_guide:V.value.writingGuide||void 0},{timeout:D.length*6e4});u.value=U.data,b.success("作文生成成功")}catch(D){b.error("作文生成失败"),console.error(D)}finally{f.value=!1}},R=async()=>{if(u.value){z.value=!0;try{const D=`# ${u.value.title}
2
3## 作文内容
4${u.value.content.replace(/<[^>]+>/g,"")}
5
6## 使用的词汇
7${u.value.used_words.join(", ")}
8
9---
10生成时间: ${new Date().toLocaleString()}`;await A.post("/api/notes",{booking_id:0,content:D,is_public:!1}),b.success("保存为笔记成功")}catch(D){b.error("保存笔记失败"),console.error(D)}finally{z.value=!1}}},K=Le(()=>u.value?u.value.content.replace(/<u>(.*?)<\/u>/g,'<strong style="color: #409EFF;">$1</strong>'):""),H=()=>{if(!u.value||m.value)return;m.value=!0;const D=new SpeechSynthesisUtterance(u.value.content.replace(/<[^>]+>/g,""));D.lang="en-US",D.rate=.9,D.onend=()=>{m.value=!1},D.onerror=()=>{m.value=!1,b.error("朗读失败")},g.speak(D)},x=async()=>{if(!(!u.value||_.value||p.value)){p.value=!0,_.value=!1;try{const D=await A.post("/api/ai/tts",{text:u.value.content.replace(/<[^>]+>/g,""),format:"mp3",speed:Number(y.value)},{responseType:"blob"}),U=window.URL.createObjectURL(new Blob([D.data],{type:"audio/mp3"}));o.value&&(o.value.src=U,o.value.onended=()=>{_.value=!1,window.URL.revokeObjectURL(U)},o.value.onerror=()=>{_.value=!1,window.URL.revokeObjectURL(U),b.error("音频播放失败")},o.value.play(),_.value=!0)}catch(D){b.error("音频生成失败"),console.error(D)}finally{p.value=!1}}},B=async()=>{if(!(!u.value||r.value)){r.value=!0;try{const D=await A.post("/api/ai/tts",{text:u.value.content.replace(/<[^>]+>/g,""),format:"mp3",speed:Number(y.value)},{responseType:"blob"}),U=window.URL.createObjectURL(new Blob([D.data],{type:"audio/mp3"})),F=document.createElement("a");F.href=U,F.setAttribute("download",`${u.value.title}.mp3`),document.body.appendChild(F),F.click(),window.URL.revokeObjectURL(U),document.body.removeChild(F),b.success("音频下载成功")}catch(D){b.error("音频下载失败"),console.error(D)}finally{r.value=!1}}};return be(()=>{L()}),(D,U)=>{const F=a("el-option"),i=a("el-select"),$=a("el-col"),X=a("el-input"),G=a("el-icon"),E=a("el-button"),oe=a("el-input-number"),Q=a("el-form-item"),re=a("el-option-group"),me=a("el-form"),ie=a("el-popover"),ce=a("el-row"),ke=a("el-tag"),De=a("el-skeleton-item"),ve=a("el-skeleton"),W=a("el-main");return n(),N(W,{class:"main-content"},{default:t(()=>[U[17]||(U[17]=l("div",{class:"main-header header"},[l("h2",null,"AI写作助手"),l("p",null,"根据所选年级和单元的词汇生成小作文")],-1)),l("div",Cn,[e(ce,{gutter:8,align:"middle"},{default:t(()=>[e($,{span:6,xs:12},{default:t(()=>[e(i,{modelValue:w.value,"onUpdate:modelValue":U[0]||(U[0]=Z=>w.value=Z),placeholder:"选择年级",onChange:I,style:{width:"100%"}},{default:t(()=>[(n(!0),k(ue,null,fe(c.value,Z=>(n(),N(F,{key:Z.value,label:Z.label,value:Z.value},null,8,["label","value"]))),128))]),_:1},8,["modelValue"])]),_:1}),e($,{span:6,xs:12},{default:t(()=>[e(i,{modelValue:v.value,"onUpdate:modelValue":U[1]||(U[1]=Z=>v.value=Z),placeholder:"选择单元",onChange:O,disabled:!w.value,style:{width:"100%"}},{default:t(()=>[(n(!0),k(ue,null,fe(C.value,Z=>(n(),N(F,{key:Z,label:Z,value:Z},null,8,["label","value"]))),128))]),_:1},8,["modelValue","disabled"])]),_:1}),e($,{span:4,xs:0},{default:t(()=>[e(X,{type:"number",modelValue:y.value,"onUpdate:modelValue":U[2]||(U[2]=Z=>y.value=Z),placeholder:"语速",max:"4",min:"0.25",step:"0.25"},{prepend:t(()=>[...U[7]||(U[7]=[s("语速",-1)])]),_:1},8,["modelValue"])]),_:1}),e($,{span:4,xs:12},{default:t(()=>[e(ie,{placement:"bottom",width:300,trigger:"click"},{reference:t(()=>[e(E,{style:{width:"100%"}},{default:t(()=>[e(G,null,{default:t(()=>[e(se(jt))]),_:1}),U[8]||(U[8]=l("span",{style:{"margin-left":"5px"}},"高级",-1))]),_:1})]),default:t(()=>[e(me,{model:V.value,"label-width":"70px",class:"settings-form"},{default:t(()=>[e(Q,{label:"字数"},{default:t(()=>[e(oe,{modelValue:V.value.wordCount,"onUpdate:modelValue":U[3]||(U[3]=Z=>V.value.wordCount=Z),min:50,max:1e3,step:10,placeholder:"默认",style:{width:"100%"}},null,8,["modelValue"]),l("div",xn,"留空使用默认("+S(M.value)+"词)",1)]),_:1}),e(Q,{label:"主题"},{default:t(()=>[e(X,{modelValue:V.value.theme,"onUpdate:modelValue":U[4]||(U[4]=Z=>V.value.theme=Z),placeholder:"如:我的假期",clearable:""},null,8,["modelValue"]),U[9]||(U[9]=l("div",{class:"form-tip"},"留空使用默认主题",-1))]),_:1}),e(Q,{label:"风格"},{default:t(()=>[e(i,{modelValue:V.value.style,"onUpdate:modelValue":U[5]||(U[5]=Z=>V.value.style=Z),placeholder:"选择或输入",clearable:"",filterable:"","allow-create":"",style:{width:"100%"}},{default:t(()=>[e(re,{label:"常见文体"},{default:t(()=>[e(F,{label:"记叙文",value:"narrative"}),e(F,{label:"描写文",value:"descriptive"}),e(F,{label:"说明文",value:"expository"}),e(F,{label:"议论文",value:"argumentative"})]),_:1}),e(re,{label:"应用文体"},{default:t(()=>[e(F,{label:"书信",value:"letter"}),e(F,{label:"邮件",value:"email"}),e(F,{label:"日记",value:"diary"}),e(F,{label:"读后感",value:"book-report"}),e(F,{label:"看图作文",value:"picture-description"})]),_:1}),e(re,{label:"创意文体"},{default:t(()=>[e(F,{label:"故事",value:"story"}),e(F,{label:"演讲稿",value:"speech"}),e(F,{label:"新闻报道",value:"news-report"}),e(F,{label:"对话",value:"dialogue"})]),_:1})]),_:1},8,["modelValue"]),U[10]||(U[10]=l("div",{class:"form-tip"}
10,"可选项或自定义",-1))]),_:1}),e(Q,{label:"写作思路"},{default:t(()=>[e(X,{modelValue:V.value.writingGuide,"onUpdate:modelValue":U[6]||(U[6]=Z=>V.value.writingGuide=Z),type:"textarea",rows:3,placeholder:"如:模仿《哈利波特》的魔法世界,或者写一个关于友谊的故事",clearable:""},null,8,["modelValue"]),U[11]||(U[11]=l("div",{class:"form-tip"},"补充写作要求或参考风格",-1))]),_:1})]),_:1},8,["model"])]),_:1})]),_:1}),e($,{span:4,xs:12},{default:t(()=>[e(E,{onClick:j,type:"primary",disabled:!h.value.length||f.value,loading:f.value,style:{width:"100%"}},{default:t(()=>[...U[12]||(U[12]=[s(" 生成作文 ",-1)])]),_:1},8,["disabled","loading"])]),_:1})]),_:1}),w.value&&v.value&&h.value.length>0?(n(),N(ce,{key:0},{default:t(()=>[e($,{span:24},{default:t(()=>[l("div",Dn,[s(S(se(Ke)[w.value])+" - "+S(v.value)+":本单元共有 ",1),l("strong",null,S(h.value.length),1),U[13]||(U[13]=s(" 个单词 ",-1))])]),_:1})]),_:1})):te("",!0)]),u.value?(n(),k("div",Sn,[l("div",Mn,[l("h3",null,S(u.value.title),1),l("div",Un,[e(E,{onClick:H,type:"primary",disabled:m.value||!u.value.content},{default:t(()=>[s(S(m.value?"朗读中...":"朗读作文"),1)]),_:1},8,["disabled"]),e(E,{onClick:x,type:"success",disabled:_.value||!u.value.content||p.value},{default:t(()=>[s(S(_.value?"AI朗读中...":p.value?"生成音频中...":"AI朗读作文"),1)]),_:1},8,["disabled"]),e(E,{onClick:B,type:"warning",disabled:!u.value.content||r.value,loading:r.value},{default:t(()=>[s(S(r.value?"下载中...":"下载音频"),1)]),_:1},8,["disabled","loading"]),e(E,{onClick:R,type:"info",disabled:!u.value.content||z.value,loading:z.value},{default:t(()=>[s(S(z.value?"保存中...":"保存为笔记"),1)]),_:1},8,["disabled","loading"])])]),l("div",In,[l("p",{innerHTML:K.value},null,8,Tn)]),l("div",An,[U[14]||(U[14]=l("h4",null,"使用的词汇:",-1)),(n(!0),k(ue,null,fe(u.value.used_words,Z=>(n(),N(ke,{key:Z,type:"success",style:{margin:"5px"}},{default:t(()=>[s(S(Z),1)]),_:2},1024))),128))]),l("audio",{ref_key:"audioPlayer",ref:o,style:{display:"none"}},null,512)])):!f.value&&w.value&&v.value&&h.value.length===0?(n(),k("div",zn,[...U[15]||(U[15]=[l("p",null,"该单元暂无词汇数据",-1)])])):!f.value&&(!w.value||!v.value)?(n(),k("div",Ln,[...U[16]||(U[16]=[l("p",null,"请选择年级和单元以生成作文",-1)])])):te("",!0),f.value?(n(),k("div",Yn,[e(ve,{animated:""},{template:t(()=>[e(De,{variant:"h3",style:{width:"50%"}}),e(De,{variant:"p",style:{width:"100%","margin-top":"20px"}}),e(De,{variant:"p",style:{width:"80%","margin-top":"10px"}}),e(De,{variant:"p",style:{width:"90%","margin-top":"10px"}})]),_:1})])):te("",!0)]),_:1})}}}),Rn=Ce(En,[["__scopeId","data-v-772ef131"]]),$t=["数学","物理","化学","生物","历史","地理","政治","英语","语文","道法","其他"],rt=["一年级上","一年级下","二年级上","二年级下","三年级上","三年级下","四年级上","四年级下","五年级上","五年级下","六年级上","六年级下","七年级上","七年级下","八年级上","八年级下","九年级上","九年级下","高一上","高一下","高二上","高二下","高三上","高三下"],It=["单选题","多选题","填空题","简答题","判断题","计算题"],Qe=q=>{if(!q)return"";try{return q=q.replace(/\$(.*?)\$/g,(c,w)=>{try{return Pt.renderToString(w,{throwOnError:!1})}catch{return c}}),q=q.replace(/\$\$(.*?)\$\$/g,(c,w)=>{try{return Pt.renderToString(w,{displayMode:!0,throwOnError:!1})}catch{return c}}),q}catch{return q}},Fn={class:"card-header"},Bn={class:"search-section"},Pn={class:"topic-cell"},Hn={class:"topic-text"},On={key:1},qn={key:1},Nn={key:1},jn={key:1},Wn={class:"pagination-container"},Kn={class:"dialog-footer"},Gn={class:"dialog-footer"},Jn=["innerHTML"],Xn={key:0},Qn={class:"options"},Zn=["innerHTML"],es=["innerHTML"],ts=["innerHTML"],ls=["innerHTML"],as={key:0},os={key:0},ns={class:"dialog-footer"},ss={class:"ai-prompt-section"},rs={class:"upload-drag-area"},is={key:0,class:"recognition-results"},us={class:"dialog-footer"},ds=ge({__name:"MistakeTracker",setup(q,{expose:c}){const w=d([]),v=d(!1),y=d(!1),C=d(!1),h=d(null),u=d([]),f=d(!1),m=d(!1),_=d(null),p=d(window.innerWidth<=768),r=JSON.parse(sessionStorage.getItem("user")||"{}"),o=d(!1),g=d(!1),V=d([]),z=Ae({count:2,difficulty:3}),M=d(!1),L=d(""),I=d(!1),O=Ae({keyword:"",subject:"",question_type:"",status:"",grade:"",mastery_level:""}
10),j=Ae({currentPage:1,pageSize:10,total:0}),R=d("form"),K=d(""),H=d(r.grade),x=d([]),B=d(r.grade),D=d([]),U=d(!1),F=d(),i=Ae({subject:"",question_type:"",stem:"",option_a:"",option_b:"",option_c:"",option_d:"",answer:"",topic:"",grade:r.grade}),$={subject:[{required:!0,message:"请选择学科",trigger:"change"}],question_type:[{required:!0,message:"请选择题型",trigger:"change"}],grade:[{required:!0,message:"请选择年级",trigger:"change"}],stem:[{required:!0,message:"请输入题干",trigger:"blur"}],option_a:[{required:!1,message:"请输入选项A",trigger:"blur"}],option_b:[{required:!1,message:"请输入选项B",trigger:"blur"}],option_c:[{required:!1,message:"请输入选项C",trigger:"blur"}],option_d:[{required:!1,message:"请输入选项D",trigger:"blur"}],topic:[{required:!1,message:"请输入题目或知识点",trigger:"blur"}],answer:[{required:!0}]},X=()=>{p.value=window.innerWidth<=768};be(()=>{window.addEventListener("resize",X),G(1),$.option_a&&($.option_a[0].required=!1),$.option_b&&($.option_b[0].required=!1),$.option_c&&($.option_c[0].required=!1),$.option_d&&($.option_d[0].required=!1)}),ct(()=>{window.removeEventListener("resize",X)});const G=async(le=1)=>{try{v.value=!0;const T={page:le,page_size:j.pageSize,keyword:O.keyword,subject:O.subject,question_type:O.question_type,status:O.status,grade:O.grade,mastery_level:O.mastery_level},he=await A.get("/api/my-mistakes",{params:T});w.value=he.data.mistakes||[],j.total=he.data.total||0,j.currentPage=le}catch(T){console.error("Failed to load mistakes:",T),b.error("加载错题集失败")}finally{v.value=!1}},E=le=>{h.value=le,Object.assign(i,{subject:le.subject,question_type:le.question_type,stem:le.stem||"",option_a:le.option_a||"",option_b:le.option_b||"",option_c:le.option_c||"",option_d:le.option_d||"",answer:le.answer||"",topic:le.topic,grade:le.grade||""}),W(le.question_type),R.value="form",C.value=!0},oe=async le=>{try{await et.confirm("确定要删除这条错题记录吗?","确认删除",{confirmButtonText:"确定",cancelButtonText:"取消",type:"warning"}),await A.delete(`/api/mistakes/${le}`),w.value=w.value.filter(T=>T.id!==le),u.value=u.value.filter(T=>T.id!==le),b.success("删除成功")}catch(T){T!=="cancel"&&(console.error("Failed to delete mistake:",T),b.error("删除错题失败"))}},Q=async()=>R.value==="json"?me():R.value==="screenshot"?De():re(),re=async()=>{var le;if(await((le=F.value)==null?void 0:le.validate())){y.value=!0;try{let T;if(h.value){T=await A.put(`/api/mistakes/${h.value.id}`,i);const he=w.value.findIndex(Te=>Te.id===h.value.id);he!==-1&&(w.value[he]=T.data),b.success("错题更新成功")}else T=await A.post("/api/mistakes",i),w.value.unshift(T.data),b.success("添加错题成功");ve(),C.value=!1}catch(T){console.error("Failed to save mistake:",T),b.error(h.value?"更新错题失败":"添加错题失败")}finally{y.value=!1}}},me=async()=>{if(!K.value.trim()){b.warning("请输入JSON格式的错题数据");return}try{const le=JSON.parse(K.value);if(!Array.isArray(le)){b.error("JSON数据应为数组格式");return}if(le.length===0){b.warning("JSON数据不能为空");return}y.value=!0;const T=le.map(Be=>(Be.grade=H.value,A.post("/api/mistakes",Be))),Te=(await Promise.all(T)).map(Be=>Be.data);w.value.unshift(...Te),b.success(`成功添加${le.length}条错题`),ve(),C.value=!1}catch(le){le instanceof SyntaxError?b.error("JSON格式错误,请检查后重试"):(console.error("Failed to save mistakes from JSON:",le),b.error("添加错题失败"))}finally{y.value=!1}},ie=le=>{ke(le)},ce=()=>{D.value=[]},ke=async le=>{if(le.raw){U.value=!0;try{const T=new FormData;T.append("image",le.raw);const he=await A.post("/api/mistakes/recognize",T,{headers:{"Content-Type":"multipart/form-data"}});he.data&&he.data.mistakes&&(D.value.push(...he.data.mistakes),b.success(`成功识别 ${he.data.mistakes.length} 道题目`))}catch(T){console.error("Failed to recognize screenshot:",T),b.error("AI识别失败,请重试")}finally{U.value=!1}}},De=async()=>{if(x.value.length===0){b.warning("请先上传截图");return}if(D.value.length===0){b.warning("请等待AI识别完成,或重新上传截图");return}
10if(!B.value){b.warning("请选择年级");return}y.value=!0;try{const le=D.value.map(Te=>(Te.grade=B.value,A.post("/api/mistakes",Te))),he=(await Promise.all(le)).map(Te=>Te.data);w.value.unshift(...he),b.success(`成功添加 ${D.value.length} 条错题`),ve(),C.value=!1}catch(le){console.error("Failed to save mistakes from screenshot:",le),b.error("添加错题失败")}finally{y.value=!1}},ve=()=>{Object.assign(i,{subject:"",question_type:"",stem:"",option_a:"",option_b:"",option_c:"",option_d:"",answer:"",grade:""}),K.value="",x.value=[],B.value=r.grade,D.value=[],R.value="form",h.value=null},W=le=>{le!=="单选题"?(i.option_a="",i.option_b="",i.option_c="",i.option_d="",$.option_a&&($.option_a[0].required=!1),$.option_b&&($.option_b[0].required=!1),$.option_c&&($.option_c[0].required=!1),$.option_d&&($.option_d[0].required=!1)):($.option_a&&($.option_a[0].required=!0),$.option_b&&($.option_b[0].required=!0),$.option_c&&($.option_c[0].required=!0),$.option_d&&($.option_d[0].required=!0))},Z=le=>de(le).format("YYYY-MM-DD HH:mm"),Ve=()=>{K.value=`[
11  {
12    "subject": "数学",
13    "question_type": "单选题",
14    "stem": "已知函数$f(x)=x^2$,求$f(2)$的值",
15    "option_a": "1",
16    "option_b": "2",
17    "option_c": "4",
18    "option_d": "8",
19    "answer": "C",
20    "topic": "二次函数",
21    "grade": "高二上"
22  },
23  {
24    "subject": "数学",
25    "question_type": "填空题",
26    "topic": "三角函数",
27    "description": "在直角三角形ABC中,若角C为直角,且$\\sin A=\\frac{1}{2}$,则$\\cos A=$____",
28    "answer": "$\\frac{\\sqrt{3}}{2}$",
29    "grade": "九年级下"
30  }
31]`},xe=()=>{navigator.clipboard.writeText(`你是一个错题分析助手。请严格遵循以下规则处理试卷图片并输出错题信息:
32
331. 信息提取规则:
34   - 只提取试卷中原始印刷或标准显示的题目内容,包括题干、选项(如果为选择题)。
35   - 完全忽略所有手写内容(如学生作答、笔记、涂改痕迹等)。
36   - 不提取任何非题干或选项的文字(如题号、批改标记、分数、页码、无关符号等)。
37
382. 数学公式处理规则:
39   - 对于包含数学公式的题目,必须将所有数学公式转换为LaTeX格式
40   - 使用行内公式格式,即用$...$包围简单公式,用$$...$$包围独立公式
41   - 保持原文中的文字描述不变,只将数学表达式转换为LaTeX格式
42   - 示例:
43     * "已知函数f(x)=x²" 应转换为 "已知函数$f(x)=x^2$"
44     * "求解方程 x²+2x+1=0" 应转换为 "求解方程 $x^2+2x+1=0$"
45     * 独立的公式行应使用$$...$$格式
46
473. 输出格式要求:
48   - 每道错题按以下 JSON 对象结构输出:
49   {
50     "subject": "学科名称,如数学、语文、英语等",
51     "question_type": "题型,如单选题、多选题、填空题、计算题、解答题、作文题、实验题等",
52     "stem": "题目题干(仅限选择题),其中的数学公式必须使用LaTeX格式",
53     "option_a": "选项A(仅限选择题),其中的数学公式必须使用LaTeX格式",
54     "option_b": "选项B(仅限选择题),其中的数学公式必须使用LaTeX格式",
55     "option_c": "选项C(仅限选择题),其中的数学公式必须使用LaTeX格式",
56     "option_d": "选项D(仅限选择题),其中的数学公式必须使用LaTeX格式",
57     "answer": "正确答案(选择题为A/B/C/D,其他题型为具体内容)",
58     "topic": "题目涉及的知识点或主题",
59     "grade": "题目所属年级,如"一年级上"、"一年级下"、"二年级上"、"二年级下"、...、"高三上"、"高三下""
60   }
61   - 将所有错题对象组成一个 JSON 数组。
62   - 非选择题的题目中,stem、option_a 等字段留空字符串或不适用字段可省略(根据具体题目类型调整)。
63
644. 输出约束:
65   - 只输出合法的 JSON 格式,不包含任何额外的文字、解释或标记。
66   - 确保内容仅来自题目本身,且为原始印刷文本。
67   - 所有数学公式必须使用LaTeX格式表示。
68
69示例输出格式:
70[
71  {
72    "subject": "数学",
73    "question_type": "单选题",
74    "stem": "已知函数$f(x)=x^2$,求$f(2)$的值",
75    "option_a": "1",
76    "option_b": "2",
77    "option_c": "4",
78    "option_d": "8",
79    "answer": "C",
80    "topic": "二次函数",
81    "grade": "高二上"
82  },
83  {
84    "subject": "数学",
85    "question_type": "填空题",
86    "topic": "三角函数",
87    "stem": "在直角三角形ABC中,若角C为直角,且$\\sin A=\\frac{1}{2}$,则$\\cos A=$____",
88    "answer": "$\\frac{\\sqrt{3}}{2}$",
89    "grade": "九年级下"
90  }
91]`).then(()=>{b.success("AI提示词已复制到剪贴板")}).catch(T=>{console.error("复制失败:",T),b.error("复制失败,请手动选择复制")})},ae=le=>{u.value=le},ee=async()=>{if(u.value.length===0){b.warning("请先选择要删除的错题");return}try{await et.confirm(`确定要删除选中的 ${u.value.length} 条错题记录吗?此操作不可恢复。`,"确认批量删除",{confirmButtonText:"确定",cancelButtonText:"取消",type:"warning"});const le=u.value.map(T=>T.id);await A.delete("/api/mistakes/batch",{data:{ids:le}}),w.value=w.value.filter(T=>!le.includes(T.id)),u.value=[],b.success(`成功删除 ${le.length} 条错题`)}catch(le){le!=="cancel"&&(console.error("Failed to batch delete mistakes:",le),b.error("批量删除错题失败"))}},Y=()=>{G(1)},P=()=>{O.keyword="",O.subject="",O.question_type="",O.status="",O.grade="",O.mastery_level="",G(1)},ne=le=>{j.pageSize=le,G(1)},we=le=>{G(le)},_e=()=>{if(u.value.length===0){b.warning("请先选择要预览的错题");return}f.value=!0},Se=()=>{if(u.value.length===0){b.warning("请先选择错题");return}o.value=!0},We=async()=>{if(u.value.length===0){b.warning("请先选择错题");return}g.value=!0;try{const le=await A.post("/api/ai/generate-exam",{mistakes:u.value,count:z.count,difficulty:z.difficulty},{timeout:z.count*6e4});V.value=le.data.questions,o.value=!1,f.value=!0,b.success("试卷生成成功")}catch(le){console.error("AI生成试卷失败:",le),b.error("试卷生成失败")}finally{g.value=!1}},tt=()=>{dt(()=>{if(_.value){const le=_.value.innerHTML,T=document.body.innerHTML;document.body.innerHTML=`
92        <html>
93          <head>
94            <title>错题试卷</title>
95            <style>
96              body { font-family: Arial, sans-serif; font-size: 14px; }
97              .options p { margin: 5px 0; }
98              .mistake-details p { margin: 8px 0; }
99              @media print {
100                body { margin: 15px; }
101                .print-area { max-width: 100%; }
102              }
103            </style>
104          </head>
105          <body>
106            ${le}
107          </body>
108        </html>
109      `,window.print(),document.body.innerHTML=T,location.reload()}})},Xe=async()=>{try{b.info("正在导出错题数据...");const he=((await A.get("/api/my-mistakes",{params:{page:1,page_size:1e4}})).data.mistakes||[]).map(Re=>({subject:Re.subject,question_type:Re.question_type,stem:Re.stem,option_a:Re.option_a,option_b:Re.option_b,option_c:Re.option_c,option_d:Re.option_d,answer:Re.answer,topic:Re.topic,grade:Re.grade,description:Re.description,created_at:Re.created_at,updated_at:Re.updated_at})),Te=JSON.stringify(he,null,2),Be=new Blob([Te],{type:"application/json"}),Ue=URL.createObjectURL(Be),ze=document.createElement("a");ze.href=Ue,ze.download=`错题集_${de().format("YYYYMMDD_HHmmss")}.json`,document.body.appendChild(ze),ze.click(),document.body.removeChild(ze),URL.revokeObjectURL(Ue),b.success(`成功导出 ${he.length} 条错题`)}catch(le){console.error("Failed to export mistakes:",le),b.error("导出错题失败")}},Ge=le=>({not_practiced:"未练习",medium:"难度适中",hard:"比较难",mastered:"已掌握"})[le]||"未练习",qe=le=>({not_practiced:"info",medium:"warning",hard:"danger",mastered:"success"})[le]||"info",lt=async(le,T)=>{try{await A.put(`/api/mistakes/${le.id}`,{mastery_level:T}),le.mastery_level=T,b.success("掌握程度已更新")}catch(he){console.error("Failed to update mastery level:",he),b.error("更新掌握程度失败")}},ye=()=>{L.value="",M.value=!0},Fe=async()=>
109{if(!L.value){b.warning("请选择掌握程度");return}if(u.value.length===0){b.warning("请先选择要设置的错题");return}I.value=!0;try{const le=u.value.map(T=>T.id);await A.put("/api/mistakes/batch",{ids:le,mastery_level:L.value}),w.value.forEach(T=>{le.includes(T.id)&&(T.mastery_level=L.value)}),b.success(`成功设置 ${le.length} 条错题的掌握程度`),M.value=!1,u.value=[]}catch(le){console.error("Failed to batch update mastery level:",le),b.error("批量设置掌握程度失败")}finally{I.value=!1}};return c({loadMistakes:G,exportAllMistakes:Xe}),(le,T)=>{const he=a("el-button"),Te=a("el-input"),Be=a("el-col"),Ue=a("el-option"),ze=a("el-select"),Re=a("el-row"),Pe=a("el-table-column"),at=a("el-tag"),bt=a("el-icon"),Ze=a("el-dropdown-item"),pe=a("el-dropdown-menu"),$e=a("el-dropdown"),Ne=a("el-table"),Lt=a("el-pagination"),tl=a("el-card"),He=a("el-form-item"),St=a("el-form"),wt=a("el-dialog"),ll=a("el-input-number"),al=a("el-rate"),ol=a("el-switch"),Mt=a("el-tab-pane"),nl=a("el-upload"),sl=a("el-tabs"),rl=Ee("loading");return n(),k(ue,null,[e(tl,null,{header:t(()=>[l("div",Fn,[T[42]||(T[42]=l("span",null,"错题集",-1)),l("div",null,[e(he,{type:"primary",size:"small",onClick:G},{default:t(()=>[...T[37]||(T[37]=[s(" 刷新 ",-1)])]),_:1}),e(he,{type:"primary",size:"small",onClick:T[0]||(T[0]=J=>C.value=!0)},{default:t(()=>[...T[38]||(T[38]=[s(" 添加错题 ",-1)])]),_:1}),u.value.length!==0?(n(),N(he,{key:0,type:"danger",size:"small",onClick:ee},{default:t(()=>[s(" 批量删除 ("+S(u.value.length)+") ",1)]),_:1})):te("",!0),u.value.length!==0?(n(),N(he,{key:1,type:"primary",size:"small",onClick:ye},{default:t(()=>[s(" 批量设置掌握程度 ("+S(u.value.length)+") ",1)]),_:1})):te("",!0),u.value.length!==0?(n(),N(he,{key:2,type:"success",size:"small",onClick:_e},{default:t(()=>[...T[39]||(T[39]=[s(" 生成试卷 ",-1)])]),_:1})):te("",!0),u.value.length!==0?(n(),N(he,{key:3,type:"warning",size:"small",onClick:Se},{default:t(()=>[...T[40]||(T[40]=[s(" AI生成试卷 ",-1)])]),_:1})):te("",!0),e(he,{type:"info",size:"small",onClick:Xe},{default:t(()=>[...T[41]||(T[41]=[s(" 导出 ",-1)])]),_:1})])])]),default:t(()=>[l("div",Bn,[e(Re,{gutter:20},{default:t(()=>[e(Be,{span:4,xs:24},{default:t(()=>[e(Te,{modelValue:O.keyword,"onUpdate:modelValue":T[1]||(T[1]=J=>O.keyword=J),placeholder:"知识点",clearable:"",onKeyup:Je(Y,["enter"])},null,8,["modelValue"])]),_:1}),e(Be,{span:4,xs:24},{default:t(()=>[e(ze,{modelValue:O.grade,"onUpdate:modelValue":T[2]||(T[2]=J=>O.grade=J),placeholder:"年级",clearable:"",style:{width:"100%"},onChange:Y},{default:t(()=>[(n(!0),k(ue,null,fe(se(rt),J=>(n(),N(Ue,{label:J,value:J,key:J},null,8,["label","value"]))),128))]),_:1},8,["modelValue"])]),_:1}),e(Be,{span:4,xs:24},{default:t(()=>[e(ze,{modelValue:O.subject,"onUpdate:modelValue":T[3]||(T[3]=J=>O.subject=J),placeholder:"学科",clearable:"",style:{width:"100%"},onChange:Y},{default:t(()=>[(n(!0),k(ue,null,fe(se($t),J=>(n(),N(Ue,{label:J,value:J,key:J},null,8,["label","value"]))),128))]),_:1},8,["modelValue"])]),_:1}),e(Be,{span:4,xs:24},{default:t(()=>[e(ze,{modelValue:O.question_type,"onUpdate:modelValue":T[4]||(T[4]=J=>O.question_type=J),placeholder:"题型",clearable:"",style:{width:"100%"},onChange:Y},{default:t(()=>[(n(!0),k(ue,null,fe(se(It),J=>(n(),N(Ue,{label:J,value:J,key:J},null,8,["label","value"]))),128))]),_:1},8,["modelValue"])]),_:1}),e(Be,{span:4,xs:24},{default:t(()=>[e(ze,{modelValue:O.mastery_level,"onUpdate:modelValue":T[5]||(T[5]=J=>O.mastery_level=J),placeholder:"掌握程度",clearable:"",style:{width:"100%"},onChange:Y},{default:t(()=>[e(Ue,{label:"未练习",value:"not_practiced"}),e(Ue,{label:"难度适中",value:"medium"}),e(Ue,{label:"比较难",value:"hard"}),e(Ue,{label:"已掌握",value:"mastered"})]),_:1},8,["modelValue"])]),_:1}),e(Be,{span:4,xs:24},{default:t(()=>[e(he,{type:"primary",onClick:Y},{default:t(()=>[...T[43]||(T[43]=[s("搜索",-1)])]),_:1}),e(he,{onClick:P},{default:t(()=>[...T[44]||(T[44]=[s("重置",-1)])]),_:1})]),_:1})]),_:1})]),Me((n(),N(Ne,{data:w.value,style:{width:"100%"},"show-overflow-tooltip":"","row-key":"id",onSelectionChange:ae},{default:t(()=>[e(Pe,{type:"selection",width:"40"}),e(Pe,{prop:"topic",label:"知识点","min-width":"110"},{default:t(({row:J})=>[l("div",Pn,[l("span",Hn,S(J.stem),1)])]),_:1}),e(Pe,{prop:"grade",label:"年级",width:"80"},{default:t(({row:J})=>[J.grade?(n(),N(at,{key:0,size:"small"},{default:t(()=>[s(S(J.grade),1)]),_:2},1024)):(n(),k("span",On,"-"))]),_:1}),e(Pe,{prop:"subject",label:"学科",width:"80"},{default:t(({row:J})=>[J.subject?(n(),N(at,{key:0,size:"small"},{default:t(()=>[s(S(J.subject),1)]),_:2},1024)):(n(),k("span",qn,"-"))]),_:1}),e(Pe,{prop:"topic",label:"考点",width:"150"},{default:t(({row:J})=>[J.topic?(n(),N(at,{key:0,size:"small"},{default:t(()=>[s(S(J.topic),1)]),_:2},1024)):(n(),k("span",Nn,"-"))]),_:1}),e(Pe,{prop:"question_type",label:"题型",width:"120"},{default:t(({row:J})=>[J.question_type?(n(),N(at,{key:0,size:"small"},{default:t(()=>[s(S(J.question_type),1)]),_:2},1024)):(n(),k("span",jn,"-"))]),_:1}),e(Pe,{prop:"mastery_level",label:"掌握程度",width:"120"},{default:t(({row:J})=>[e($e,{onCommand:ot=>lt(J,ot)},{dropdown:t(()=>[e(pe,null,{default:t(()=>[e(Ze,{command:"not_practiced"},{default:t(()=>[...T[45]||(T[45]=[s("未练习",-1)])]),_:1}),e(Ze,{command:"medium"},{default:t(()=>[...T[46]||(T[46]=[s("难度适中",-1)])]),_:1}),e(Ze,{command:"hard"},{default:t(()=>[...T[47]||(T[47]=[s("比较难",-1)])]),_:1}),e(Ze,{command:"mastered"},{default:t(()=>[...T[48]||(T[48]=[s("已掌握",-1)])]),_:1})]),_:1})]),default:t(()=>
109[e(at,{type:qe(J.mastery_level),size:"small",style:{cursor:"pointer"}},{default:t(()=>[s(S(Ge(J.mastery_level))+" ",1),e(bt,{style:{"margin-left":"4px"}},{default:t(()=>[e(se(Wt))]),_:1})]),_:2},1032,["type"])]),_:2},1032,["onCommand"])]),_:1}),e(Pe,{prop:"created_at",label:"添加时间",width:"180"},{default:t(({row:J})=>[s(S(Z(J.created_at)),1)]),_:1}),e(Pe,{label:"操作",width:"150"},{default:t(({row:J})=>[e(he,{type:"primary",size:"small",onClick:ot=>E(J)},{default:t(()=>[...T[49]||(T[49]=[s(" 编辑 ",-1)])]),_:1},8,["onClick"]),e(he,{type:"danger",size:"small",onClick:ot=>oe(J.id)},{default:t(()=>[...T[50]||(T[50]=[s(" 删除 ",-1)])]),_:1},8,["onClick"])]),_:1})]),_:1},8,["data"])),[[rl,v.value]]),l("div",Wn,[e(Lt,{"current-page":j.currentPage,"onUpdate:currentPage":T[6]||(T[6]=J=>j.currentPage=J),"page-size":j.pageSize,"onUpdate:pageSize":T[7]||(T[7]=J=>j.pageSize=J),"page-sizes":[10,20,50,100],total:j.total,layout:"total, sizes, prev, pager, next, jumper",onSizeChange:ne,onCurrentChange:we},null,8,["current-page","page-size","total"])])]),_:1}),e(wt,{modelValue:M.value,"onUpdate:modelValue":T[10]||(T[10]=J=>M.value=J),title:"批量设置掌握程度",width:"400px"},{footer:t(()=>[l("span",Kn,[e(he,{onClick:T[9]||(T[9]=J=>M.value=!1)},{default:t(()=>[...T[51]||(T[51]=[s("取消",-1)])]),_:1}),e(he,{type:"primary",onClick:Fe,loading:I.value},{default:t(()=>[s(" 确定设置 ("+S(u.value.length)+") ",1)]),_:1},8,["loading"])])]),default:t(()=>[e(St,{"label-width":"100px"},{default:t(()=>[e(He,{label:"掌握程度"},{default:t(()=>[e(ze,{modelValue:L.value,"onUpdate:modelValue":T[8]||(T[8]=J=>L.value=J),placeholder:"请选择掌握程度",style:{width:"100%"}},{default:t(()=>[e(Ue,{label:"未练习",value:"not_practiced"}),e(Ue,{label:"难度适中",value:"medium"}),e(Ue,{label:"比较难",value:"hard"}),e(Ue,{label:"已掌握",value:"mastered"})]),_:1},8,["modelValue"])]),_:1})]),_:1})]),_:1},8,["modelValue"]),e(wt,{modelValue:o.value,"onUpdate:modelValue":T[14]||(T[14]=J=>o.value=J),title:"AI生成试卷"},{footer:t(()=>[l("span",Gn,[e(he,{onClick:T[13]||(T[13]=J=>o.value=!1)},{default:t(()=>[...T[52]||(T[52]=[s("取消",-1)])]),_:1}),e(he,{type:"primary",onClick:We,loading:g.value},{default:t(()=>[...T[53]||(T[53]=[s(" 生成试卷 ",-1)])]),_:1},8,["loading"])])]),default:t(()=>[e(St,{model:z,"label-width":"100px"},{default:t(()=>[e(He,{label:"题目数量"},{default:t(()=>[e(ll,{modelValue:z.count,"onUpdate:modelValue":T[11]||(T[11]=J=>z.count=J),min:1,max:10,"controls-position":"right"},null,8,["modelValue"])]),_:1}),e(He,{label:"难度等级"},{default:t(()=>[e(al,{modelValue:z.difficulty,"onUpdate:modelValue":T[12]||(T[12]=J=>z.difficulty=J)},null,8,["modelValue"])]),_:1})]),_:1},8,["model"])]),_:1},8,["modelValue"]),e(wt,{modelValue:f.value,"onUpdate:modelValue":T[17]||(T[17]=J=>f.value=J),title:"试卷预览",width:"80%",class:"preview-dialog"},{header:t(()=>[e(ol,{modelValue:m.value,"onUpdate:modelValue":T[15]||(T[15]=J=>m.value=J),"active-text":"显示答案","inactive-text":"隐藏答案"},null,8,["modelValue"])]),footer:t(()=>[l("span",ns,[e(he,{onClick:T[16]||(T[16]=J=>f.value=!1)},{default:t(()=>[...T[59]||(T[59]=[s("关闭",-1)])]),_:1}),e(he,{type:"primary",onClick:tt},{default:t(()=>[...T[60]||(T[60]=[s("打印试卷",-1)])]),_:1})])]),default:t(()=>[l("div",{class:"print-area",ref_key:"printAreaRef",ref:_},[T[58]||(T[58]=l("h2",{style:{"text-align":"center"}},"错题试卷",-1)),(n(!0),k(ue,null,fe(V.value.length>0?V.value:u.value,(J,ot)=>(n(),k("div",{class:"mistake-item",key:J.id},[l("div",null,[s(S(ot+1)+". ("+S(J.subject)+") "+S(J.question_type)+" - ",1),l("span",{innerHTML:se(Qe)(J.stem)},null,8,Jn)]),J.question_type==="单选题"?(n(),k("div",Xn,[l("table",Qn,[l("tbody",null,[l("tr",null,[l("td",null,[T[54]||(T[54]=s("A. ",-1)),l("span",{innerHTML:se(Qe)(J.option_a)},null,8,Zn)]),l("td",null,[T[55]||(T[55]=s("B. ",-1)),l("span",{innerHTML:se(Qe)(J.option_b)},null,8,es)])]),l("tr",null,[l("td",null,[T[56]||(T[56]=s("C. ",-1)),l("span",{innerHTML:se(Qe)(J.option_c)},null,8,ts)]),l("td",null,[T[57]||(T[57]=s("D. ",-1)),l("span",{innerHTML:se(Qe)(J.option_d)},null,8,ls)])])])])])):te("",!0)]))),128)),m.value?(n(),k("div",as,[(n(!0),k(ue,null,fe(V.value.length>0?V.value:u.value,(J,ot)=>(n(),k("span",{class:"answer",key:J.id},[J.question_type==="单选题"?(n(),k("span",os,S(J.answer),1)):te("",!0)]))),128))])):te("",!0)],512)]),_:1},8,["modelValue"]),e(wt,{modelValue:C.value,"onUpdate:modelValue":T[36]||(T[36]=J=>C.value=J),title:h.value?"编辑错题":"添加错题",class:"default-dialog"},{footer:t(()=>[l("span",us,[e(he,{onClick:T[35]||(T[35]=J=>C.value=!1)},{default:t(()=>[...T[67]||(T[67]=[s("取消",-1)])]),_:1}),e(he,{type:"primary",onClick:Q,loading:y.value},{default:t(()=>[s(S(h.value?"更新":"添加"),1)]),_:1},8,["loading"])])]),default:t(()=>[e(sl,{modelValue:R.value,"onUpdate:modelValue":T[34]||(T[34]=J=>R.value=J),type:"card"},{default:t(()=>
109[e(Mt,{label:"表单输入",name:"form"},{default:t(()=>[e(St,{model:i,rules:$,ref_key:"mistakeFormRef",ref:F,"label-width":"100px"},{default:t(()=>[e(He,{label:"年级",prop:"grade"},{default:t(()=>[e(ze,{modelValue:i.grade,"onUpdate:modelValue":T[18]||(T[18]=J=>i.grade=J),placeholder:"请选择年级",style:{width:"100%"}},{default:t(()=>[(n(!0),k(ue,null,fe(se(rt),J=>(n(),N(Ue,{label:J,value:J,key:J},null,8,["label","value"]))),128))]),_:1},8,["modelValue"])]),_:1}),e(He,{label:"学科",prop:"subject"},{default:t(()=>[e(ze,{modelValue:i.subject,"onUpdate:modelValue":T[19]||(T[19]=J=>i.subject=J),placeholder:"请选择学科",style:{width:"100%"}},{default:t(()=>[(n(!0),k(ue,null,fe(se($t),J=>(n(),N(Ue,{label:J,value:J,key:J},null,8,["label","value"]))),128))]),_:1},8,["modelValue"])]),_:1}),e(He,{label:"题型",prop:"question_type"},{default:t(()=>[e(ze,{modelValue:i.question_type,"onUpdate:modelValue":T[20]||(T[20]=J=>i.question_type=J),placeholder:"请选择题型",style:{width:"100%"},onChange:W},{default:t(()=>[(n(!0),k(ue,null,fe(se(It),J=>(n(),N(Ue,{label:J,value:J,key:J},null,8,["label","value"]))),128))]),_:1},8,["modelValue"])]),_:1}),e(He,{label:"题干",prop:"stem"},{default:t(()=>[e(Te,{modelValue:i.stem,"onUpdate:modelValue":T[21]||(T[21]=J=>i.stem=J),type:"textarea",rows:3,placeholder:"请输入题干"},null,8,["modelValue"])]),_:1}),i.question_type==="单选题"||i.question_type==="多选题"?(n(),k(ue,{key:0},[e(He,{label:"选项A",prop:"option_a"},{default:t(()=>[e(Te,{modelValue:i.option_a,"onUpdate:modelValue":T[22]||(T[22]=J=>i.option_a=J),placeholder:"选项A"},null,8,["modelValue"])]),_:1}),e(He,{label:"选项B",prop:"option_b"},{default:t(()=>[e(Te,{modelValue:i.option_b,"onUpdate:modelValue":T[23]||(T[23]=J=>i.option_b=J),placeholder:"选项B"},null,8,["modelValue"])]),_:1}),e(He,{label:"选项C",prop:"option_c"},{default:t(()=>[e(Te,{modelValue:i.option_c,"onUpdate:modelValue":T[24]||(T[24]=J=>i.option_c=J),placeholder:"选项C"},null,8,["modelValue"])]),_:1}),e(He,{label:"选项D",prop:"option_d"},{default:t(()=>[e(Te,{modelValue:i.option_d,"onUpdate:modelValue":T[25]||(T[25]=J=>i.option_d=J),placeholder:"选项D"},null,8,["modelValue"])]),_:1}),e(He,{label:"正确答案",prop:"answer"},{default:t(()=>[e(ze,{modelValue:i.answer,"onUpdate:modelValue":T[26]||(T[26]=J=>i.answer=J),placeholder:"请选择正确答案",style:{width:"100%"}},{default:t(()=>[e(Ue,{label:"A",value:"A"}),e(Ue,{label:"B",value:"B"}),e(Ue,{label:"C",value:"C"}),e(Ue,{label:"D",value:"D"})]),_:1},8,["modelValue"])]),_:1})],64)):i.question_type==="判断题"?(n(),N(He,{key:1,label:"正确答案",prop:"answer"},{default:t(()=>[e(ze,{modelValue:i.answer,"onUpdate:modelValue":T[27]||(T[27]=J=>i.answer=J),placeholder:"请选择正确答案",style:{width:"100%"}},{default:t(()=>[e(Ue,{label:"对",value:"对"}),e(Ue,{label:"错",value:"错"})]),_:1},8,["modelValue"])]),_:1})):(n(),N(He,{key:2,label:"正确答案",prop:"answer"},{default:t(()=>[e(Te,{modelValue:i.answer,"onUpdate:modelValue":T[28]||(T[28]=J=>i.answer=J)},null,8,["modelValue"])]),_:1})),e(He,{label:"知识点",prop:"topic"},{default:t(()=>[e(Te,{modelValue:i.topic,"onUpdate:modelValue":T[29]||(T[29]=J=>i.topic=J),placeholder:"请输入题目或知识点"},null,8,["modelValue"])]),_:1})]),_:1},8,["model"])]),_:1}),e(Mt,{label:"AI JSON输入",name:"json"},{default:t(()=>[e(ze,{modelValue:H.value,"onUpdate:modelValue":T[30]||(T[30]=J=>H.value=J),placeholder:"年级",clearable:"",style:{width:"100%"}},{default:t(()=>[(n(!0),k(ue,null,fe(se(rt),J=>(n(),N(Ue,{label:J,value:J,key:J},null,8,["label","value"]))),128))]),_:1},8,["modelValue"]),e(Te,{modelValue:K.value,"onUpdate:modelValue":T[31]||(T[31]=J=>K.value=J),type:"textarea",rows:10,placeholder:`请输入JSON格式的错题数据,例如:
110[
111  {
112    "subject": "数学",
113    "question_type": "单选题",
114    "stem": "已知函数$f(x)=x^2$,求$f(2)$的值",
115    "option_a": "1",
116    "option_b": "2",
117    "option_c": "4",
118    "option_d": "8",
119    "answer": "C",
120    "topic": "二次函数",
121    "description": "误将f(2)计算为2*2=2",
122    "reason": "对函数概念理解不清",
123    "suggestion": "加强对函数概念的理解和练习"
124  }
125]`},null,8,["modelValue"]),l("div",{class:"json-example-link",onClick:Ve}," 点击查看示例JSON格式 "),l("div",ss,[e(he,{type:"primary",size:"small",onClick:xe,class:"copy-prompt-button"},{default:t(()=>[...T[61]||(T[61]=[s(" 复制AI提示词到剪贴板 ",-1)])]),_:1}),T[62]||(T[62]=l("div",{class:"prompt-description"}," 点击按钮复制提示词,然后在AI工具中使用该提示词生成错题JSON数据 ",-1))])]),_:1}),e(Mt,{label:"截图上传",name:"screenshot"},{default:t(()=>[e(ze,{modelValue:B.value,"onUpdate:modelValue":T[32]||(T[32]=J=>B.value=J),placeholder:"年级",clearable:"",style:{width:"100%","margin-bottom":"12px"}},{default:t(()=>[(n(!0),k(ue,null,fe(se(rt),J=>(n(),N(Ue,{label:J,value:J,key:J},null,8,["label","value"]))),128))]),_:1},8,["modelValue"]),e(nl,{"file-list":x.value,"onUpdate:fileList":T[33]||(T[33]=J=>x.value=J),"auto-upload":!1,"on-change":ie,"on-remove":ce,multiple:!0,accept:"image/*",drag:"",class:"screenshot-upload"},{default:t(()=>[l("div",rs,[e(bt,{class:"upload-icon"},{default:t(()=>[e(se(Tt))]),_:1}),T[63]||(T[63]=l("div",{class:"upload-text"},"拖拽图片到此处或点击上传",-1)),T[64]||(T[64]=l("div",{class:"upload-hint"},"支持 JPG、PNG 等图片格式,可同时上传多张",-1))])]),_:1},8,["file-list"]),T[66]||(T[66]=l("div",{class:"screenshot-tips"},[l("p",null,"支持同时上传多张截图,AI会自动识别图片中的题目")],-1)),D.value.length>0?(n(),k("div",is,[T[65]||(T[65]=l("h4",null,"识别结果预览:",-1)),(n(!0),k(ue,null,fe(D.value,(J,ot)=>{var Yt;return n(),k("div",{key:ot,class:"result-item"},[e(at,{type:"success"},{default:t(()=>[s("✓ "+S(J.subject)+" - "+S(J.question_type),1)]),_:2},1024),l("p",null,S((Yt=J.stem)==null?void 0:Yt.substring(0,50))+"...",1)])}),128))])):te("",!0)]),_:1})]),_:1},8,["modelValue"])]),_:1},8,["modelValue","title"])],64)}}}),cs=Ce(ds,[["__scopeId","data-v-24172e8e"]]);de.extend(pt);function el(q,c=`课程安排-${de().format("YYYY-MM-DD")}.ics`,w=!0){const v=w?q.filter(f=>de(f.timeslot_start).isAfter(de())):q;if(!v.length)throw new Error("没有可导出的课程安排");let y=["BEGIN:VCALENDAR","VERSION:2.0","PRODID:-//OpenCourse//Calendar Export//EN","CALSCALE:GREGORIAN"];v.forEach(f=>{const m=de(f.timeslot_start).utc().format("YYYYMMDDTHHmmss[Z]"),_=de(f.timeslot_end).utc().format("YYYYMMDDTHHmmss[Z]"),p=de(f.timeslot_start).utc().subtract(15,"minute").format("YYYYMMDDTHHmmss[Z]");y=y.concat(["BEGIN:VEVENT",`UID:${f.book_id}@opencourse`,`DTSTART:${m}`,`DTEND:${_}`,`SUMMARY:${f.course_name} - ${f.student_name}`,`DESCRIPTION:课程名称: ${f.course_name}\\n学生: ${f.student_name||"暂无学生"}`,"LOCATION:Online Lesson","URL:http://jenkins-zh.cn","BEGIN:VALARM","ACTION:DISPLAY","DESCRIPTION:课程即将开始",`TRIGGER;VALUE=DATE-TIME:${p}`,"END:VALARM","END:VEVENT"])}),y.push("END:VCALENDAR");const C=new Blob([y.join(`\r
126`)],{type:"text/calendar;charset=utf-8"}),h=window.URL.createObjectURL(C),u=document.createElement("a");u.href=h,u.setAttribute("download",c),document.body.appendChild(u),u.click(),document.body.removeChild(u),window.URL.revokeObjectURL(h)}const ps={class:"card-header"},ms={class:"header-actions"},vs={class:"calendar-header"},fs={class:"calendar-date"},_s=["onClick"],ys={class:"calendar-date-number"},gs={class:"calendar-events"},bs=["onClick"],ws={class:"event-title"}
126,ks={class:"week-view"},hs={class:"view-header"},$s={class:"view-title"},Vs={class:"week-grid"},Cs={class:"day-name"},xs={class:"day-date"},Ds={class:"grid-time-slot"},Ss=["onClick"],Ms=["onClick"],Us={class:"week-event-title"},Is={class:"week-event-time"},Ts={class:"day-view"},As={class:"view-header"},zs={class:"view-title"},Ls={class:"day-grid"},Ys={class:"grid-time-slot"},Es=["onClick"],Rs=["onClick"],Fs={class:"day-event-title"},Bs={class:"day-event-time"},Ps={class:"dialog-footer"},Hs={key:0,class:"upload-drag-area"},Os={key:1,class:"upload-drag-area"},qs={key:0,class:"image-preview-container"},Ns={class:"image-error"},js={class:"dialog-footer"},Ws={class:"subscription-content"},Ks={class:"subscription-list"},Gs={class:"dialog-footer"},Js=ge({__name:"MyCalendar",setup(q){de.extend(pt);const c=d(),w=d(new Date),v=d([]),y=d(!1),C=d(!1),h=d(null),u=d([]),f=d(!1),m=d(!1),_=d(!1),p=d(localStorage.getItem("calendarView")||"month"),r=Ae({id:"",title:"",description:"",start:"",end:"",location:""}),o=Ae({title:"",description:"",start:"",end:""}),g=d([]),V=d(!1),z=d(null),M=Ae({name:"",url:"",username:"",password:"",color:"#909399"}),L=Array.from({length:24},(Y,P)=>P),I=Le(()=>{const Y=de(w.value).startOf("week");return Array.from({length:7},(P,ne)=>{const we=Y.add(ne,"day");return{date:we.format("YYYY-MM-DD"),dateNum:we.format("MM-DD"),name:["周日","周一","周二","周三","周四","周五","周六"][we.day()]}})}),O=Le(()=>de(w.value).format("YYYY-MM-DD"));be(()=>{D()}),je(w,()=>{D()}),je(p,Y=>{localStorage.setItem("calendarView",Y)});function j(){}function R(){const Y=de(w.value).startOf("week"),P=de(w.value).endOf("week");return`${Y.format("YYYY年MM月DD日")} - ${P.format("MM月DD日")}`}function K(){return de(w.value).format("YYYY年MM月DD日")}function H(Y){w.value=de(w.value).add(Y,"week").toDate()}function x(Y){w.value=de(w.value).add(Y,"day").toDate()}function B(Y){Y==="today"?w.value=new Date:Y==="prev-month"?w.value=de(w.value).subtract(1,"month").toDate():Y==="next-month"?w.value=de(w.value).add(1,"month").toDate():c.value&&c.value.selectDate(Y)}async function D(){y.value=!0;try{const Y=de(w.value).subtract(1,"month").startOf("month").format("YYYY-MM-DDTHH:mm:ss[Z]"),P=de(w.value).add(1,"month").endOf("month").format("YYYY-MM-DDTHH:mm:ss[Z]"),ne=await A.get("/api/my-calendar",{params:{start:Y,end:P}});if(!ne)return;v.value=(ne.data||[]).map(we=>({id:we.id,title:we.title,start:de(we.start).local().format("YYYY-MM-DDTHH:mm:ss"),end:de(we.end).local().format("YYYY-MM-DDTHH:mm:ss"),description:we.description,location:we.location,color:we.color,readonly:we.readonly,extendedProps:{uid:we.uid,createdAt:we.created_at,updatedAt:we.updated_at}}))}catch(Y){console.error("Failed to load calendar events:",Y),b.error("加载日历事件失败")}finally{y.value=!1}}function U(Y){return v.value.filter(P=>de(P.start).format("YYYY-MM-DD")===Y)}function F(Y,P){return v.value.filter(ne=>{const we=de(ne.start).format("YYYY-MM-DD"),_e=de(ne.start).hour();return we===Y&&_e===P})}function i(Y,P){return Y.length<=P?Y:Y.substring(0,P)+"..."}function $(Y){return de(Y).format("HH:mm")}function X(Y){return de(Y).format("YYYY-MM-DD HH:mm")}function G(Y){if(Y.readonly){r.id=Y.id,r.title=Y.title,r.description=Y.description,r.start=Y.start,r.end=Y.end,r.location=Y.location,m.value=!0;return}h.value=Y,o.title=Y.title,o.description=Y.description,o.start=Y.start,o.end=Y.end,C.value=!0}function E(Y){h.value=null,u.value=[];const P=de(Y.day).hour(9).minute(0).second(0).millisecond(0),ne=P.add(1,"hour");o.title="",o.description="",o.start=P.toDate(),o.end=ne.toDate(),C.value=!0}function oe(Y,P){h.value=null,u.value=[];const ne=de(Y).hour(P).minute(0).second(0).millisecond(0),we=ne.add(1,"hour");o.title="",o.description="",o.start=ne.toDate(),o.end=we.toDate(),C.value=!0}async function Q(){try{if(v.value.length===0){b.warning("没有可导出的日历事件");return}el(v.value,`我的课程安排-${de().format("YYYY-MM-DD")}.ics`),b.success("日历导出成功")}catch(Y){console.error("导出日历失败:",Y),b.error(Y.message||"导出日历失败")}}async function re(){if(!o.title){b.warning("请输入事件标题");return}if(!o.start||!o.end){b.warning("请选择开始时间和结束时间");return}const Y=de(o.start);if(de(o.end).isBefore(Y)){b.warning("结束时间必须晚于开始时间");return}
126try{const ne={title:o.title,description:o.description,start:de(o.start).utc().toISOString(),end:de(o.end).utc().toISOString(),location:"Online Lesson"};h.value?(await A.put(`/api/my-calendar/${h.value.id}`,ne),b.success("事件更新成功")):(await A.post("/api/my-calendar",ne),b.success("事件添加成功")),C.value=!1,await D()}catch(ne){console.error("保存事件失败:",ne),b.error(h.value?"更新事件失败":"添加事件失败")}}async function me(Y){var P,ne;if(Y.raw){f.value=!0;try{const we=new FormData;we.append("image",Y.raw);const _e=await A.post("/api/calendar/recognize-image",we,{headers:{"Content-Type":"multipart/form-data"}});if(console.log("AI识别响应:",_e.data),!_e.data||!_e.data.title&&!_e.data.description&&!_e.data.start&&!_e.data.end){b.error("AI识别失败:无法从图片中识别出事件信息,请确保图片清晰且包含日历事件");return}_e.data&&_e.data.title&&(o.title=_e.data.title,console.log("设置标题:",o.title)),_e.data&&_e.data.description&&(o.description=_e.data.description,console.log("设置描述:",o.description)),_e.data&&_e.data.start&&(o.start=de(_e.data.start).toDate(),console.log("设置开始时间:",o.start)),_e.data&&_e.data.end&&(o.end=de(_e.data.end).toDate(),console.log("设置结束时间:",o.end)),console.log("当前表单数据:",o),b.success("AI识别成功,已自动填写表单")}catch(we){console.error("Failed to recognize image:",we),b.error("AI识别失败: "+(((ne=(P=we.response)==null?void 0:P.data)==null?void 0:ne.error)||we.message))}finally{f.value=!1}}}function ie(){o.title="",o.description="",o.start="",o.end=""}function ce(Y){return Y.url?Y.url:Y.raw?URL.createObjectURL(Y.raw):""}async function ke(){if(h.value)try{await A.delete(`/api/my-calendar/${h.value.id}`),b.success("事件删除成功"),C.value=!1,await D()}catch(Y){console.error("删除事件失败:",Y),b.error("删除事件失败")}}je(_,Y=>{Y&&W()});function De(){z.value=null,ve()}function ve(){M.name="",M.url="",M.username="",M.password="",M.color="#909399"}async function W(){V.value=!0;try{const Y=await A.get("/api/user/subscribed-calendars");g.value=Y.data||[]}catch(Y){console.error("Failed to load subscriptions:",Y),b.error("加载订阅日历失败")}finally{V.value=!1}}function Z(Y){z.value=Y,M.name=Y.name,M.url=Y.url,M.username=Y.username||"",M.password="",M.color=Y.color||"#909399"}async function Ve(){var Y,P;if(!M.name||!M.url){b.warning("请填写日历名称和地址");return}try{if(z.value){const ne={name:M.name,url:M.url,username:M.username,color:M.color,enabled:!0};M.password&&(ne.password=M.password),await A.put(`/api/user/subscribed-calendars/${z.value.id}`,ne),b.success("更新订阅成功")}else await A.post("/api/user/subscribed-calendars",M),b.success("添加订阅成功");z.value=null,ve(),await W(),await D()}catch(ne){console.error("Failed to save subscription:",ne),b.error(((P=(Y=ne.response)==null?void 0:Y.data)==null?void 0:P.error)||"保存订阅失败")}}async function xe(Y){try{await A.put(`/api/user/subscribed-calendars/${Y.id}`,Y),await D()}catch(P){console.error("Failed to toggle subscription:",P),b.error("更新订阅状态失败"),Y.enabled=!Y.enabled}}async function ae(Y){try{await A.put(`/api/user/subscribed-calendars/${Y.id}`,Y),await D(),b.success("颜色更新成功")}catch(P){console.error("Failed to update subscription color:",P),b.error("更新颜色失败")}}async function ee(Y){try{await A.delete(`/api/user/subscribed-calendars/${Y}`),b.success("删除订阅成功"),await W(),await D()}catch(P){console.error("Failed to delete subscription:",P),b.error("删除订阅失败")}}return(Y,P)=>{const ne=a("el-option"),we=a("el-select"),_e=a("el-button"),Se=a("el-button-group"),We=a("el-tooltip"),tt=a("el-calendar"),Xe=a("el-card"),Ge=a("el-container"),qe=a("el-descriptions-item"),lt=a("el-descriptions"),ye=a("el-dialog"),Fe=a("el-input"),le=a("el-form-item"),T=a("el-date-picker"),he=a("el-icon"),Te=a("el-upload"),Be=a("el-image"),Ue=a("el-form"),ze=a("el-color-picker"),Re=a("el-divider"),Pe=a("el-table-column"),at=a("el-switch"),bt=a("el-table"),Ze=Ee("loading");return n(),k(ue,null,[e(Ge,{class:"calendar-container"},{default:t(()=>[e(Xe,{class:"calendar-card"},{header:t(()=>[l("div",ps,[P[31]||(P[31]=l("span",null,"我的日历",-1)),l("div",ms,[e(we,{modelValue:p.value,"onUpdate:modelValue":P[0]||(P[0]=pe=>p.value=pe),onChange:j,style:{width:"100px","margin-right":"10px"}},{default:t(()=>[e(ne,{value:"month",label:"月"}),e(ne,{value:"week",label:"周"}),e(ne,{value:"day",label:"日"})]),_:1},8,["modelValue"]),e(_e,{type:"primary",onClick:P[1]||(P[1]=pe=>_.value=!0)},{default:t(()=>[...P[28]||(P[28]=[s("订阅日历",-1)])]),_:1}),e(_e,{type:"primary",onClick:D},{default:t(()=>[...P[29]||(P[29]=[s("刷新",-1)])]),_:1}),e(_e,{type:"primary",onClick:Q},{default:t(()=>[...P[30]||(P[30]=[s("导出日历",-1)])]),_:1})])])]),default:t(()=>[Me((n(),k("div",null,[e(tt,{modelValue:w.value,"onUpdate:modelValue":P[5]||(P[5]=pe=>w.value=pe)},{header:t(({date:pe})=>[l("div",vs,[e(Se,null,{default:t(()=>[e(_e,{size:"small",onClick:P[2]||(P[2]=$e=>B("prev-month"))},{default:t(()=>[...P[32]||(P[32]=[s("上一月",-1)])]),_:1}),e(_e,{size:"small",onClick:P[3]||(P[3]=$e=>B("today"))},{default:t(()=>[...P[33]||(P[33]=[s("今天",-1)])]),_:1}),e(_e,{size:"small",onClick:P[4]||(P[4]=$e=>B("next-month"))},{default:t(()=>[...P[34]||(P[34]=[s("下一月",-1)])]),_:1})]),_:1}),l("span",fs,S(pe),1)])]),"date-cell":t(({data:pe})=>[l("div",{class:"calendar-day",onClick:$e=>E(pe)},[l("div",ys,S(pe.day.split("-")[2]),1),l("div",gs,[(n(!0),k(ue,null,fe(U(pe.day),$e=>(n(),k("div",{key:$e.id,class:Ye(["calendar-event",{readonly:$e.readonly,"has-color":$e.color}]),style:ft($e.color?{"--event-color":$e.color}:{}),onClick:Oe(Ne=>G($e),["stop"])},[e(We,{content:`${$e.title}: ${$($e.start)} - ${$($e.end)}`,placement:"top"},{default:t(()=>[l("div",ws,S(i($e.title,10)),1)]),_:2}
126,1032,["content"])],14,bs))),128))])],8,_s)]),_:1},8,["modelValue"])])),[[it,p.value==="month"],[Ze,y.value]]),Me((n(),k("div",ks,[l("div",hs,[e(Se,null,{default:t(()=>[e(_e,{size:"small",onClick:P[6]||(P[6]=pe=>H(-1))},{default:t(()=>[...P[35]||(P[35]=[s("上一周",-1)])]),_:1}),e(_e,{size:"small",onClick:P[7]||(P[7]=pe=>B("today"))},{default:t(()=>[...P[36]||(P[36]=[s("今天",-1)])]),_:1}),e(_e,{size:"small",onClick:P[8]||(P[8]=pe=>H(1))},{default:t(()=>[...P[37]||(P[37]=[s("下一周",-1)])]),_:1})]),_:1}),l("span",$s,S(R()),1)]),l("div",Vs,[P[38]||(P[38]=l("div",{class:"grid-time-header"},null,-1)),(n(!0),k(ue,null,fe(I.value,pe=>(n(),k("div",{key:`header-${pe.date}`,class:"grid-day-header"},[l("div",Cs,S(pe.name),1),l("div",xs,S(pe.dateNum),1)]))),128)),(n(!0),k(ue,null,fe(se(L),pe=>(n(),k(ue,{key:pe},[l("div",Ds,S(pe)+":00",1),(n(!0),k(ue,null,fe(I.value,$e=>(n(),k("div",{key:`slot-${$e.date}-${pe}`,class:"grid-day-slot",onClick:Ne=>oe($e.date,pe)},[(n(!0),k(ue,null,fe(F($e.date,pe),Ne=>(n(),k("div",{key:Ne.id,class:Ye(["week-event",{readonly:Ne.readonly,"has-color":Ne.color}]),style:ft(Ne.color?{"--event-color":Ne.color}:{}),onClick:Oe(Lt=>G(Ne),["stop"])},[l("div",Us,S(i(Ne.title,15)),1),l("div",Is,S($(Ne.start))+" - "+S($(Ne.end)),1)],14,Ms))),128))],8,Ss))),128))],64))),128))])])),[[it,p.value==="week"],[Ze,y.value]]),Me((n(),k("div",Ts,[l("div",As,[e(Se,null,{default:t(()=>[e(_e,{size:"small",onClick:P[9]||(P[9]=pe=>x(-1))},{default:t(()=>[...P[39]||(P[39]=[s("前一天",-1)])]),_:1}),e(_e,{size:"small",onClick:P[10]||(P[10]=pe=>B("today"))},{default:t(()=>[...P[40]||(P[40]=[s("今天",-1)])]),_:1}),e(_e,{size:"small",onClick:P[11]||(P[11]=pe=>x(1))},{default:t(()=>[...P[41]||(P[41]=[s("后一天",-1)])]),_:1})]),_:1}),l("span",zs,S(K()),1)]),l("div",Ls,[P[42]||(P[42]=l("div",{class:"day-time-header"},null,-1)),P[43]||(P[43]=l("div",{class:"day-content-header"},[l("div",{class:"day-title"},"时间")],-1)),(n(!0),k(ue,null,fe(se(L),pe=>(n(),k(ue,{key:pe},[l("div",Ys,S(pe)+":00",1),l("div",{class:"day-content-slot",onClick:$e=>oe(O.value,pe)},[(n(!0),k(ue,null,fe(F(O.value,pe),$e=>(n(),k("div",{key:$e.id,class:Ye(["day-event",{readonly:$e.readonly,"has-color":$e.color}]),style:ft($e.color?{"--event-color":$e.color}:{}),onClick:Oe(Ne=>G($e),["stop"])},[l("div",Fs,S($e.title),1),l("div",Bs,S($($e.start))+" - "+S($($e.end)),1)],14,Rs))),128))],8,Es)],64))),128))])])),[[it,p.value==="day"],[Ze,y.value]])]),_:1})]),_:1}),e(ye,{modelValue:m.value,"onUpdate:modelValue":P[13]||(P[13]=pe=>m.value=pe),title:"事件详情",width:"500px"},{footer:t(()=>[l("span",Ps,[e(_e,{onClick:P[12]||(P[12]=pe=>m.value=!1)},{default:t(()=>[...P[44]||(P[44]=[s("关闭",-1)])]),_:1})])]),default:t(()=>[e(lt,{column:1,border:""},{default:t(()=>[e(qe,{label:"标题"},{default:t(()=>[s(S(r.title),1)]),_:1}),e(qe,{label:"开始时间"},{default:t(()=>[s(S(X(r.start)),1)]),_:1}),e(qe,{label:"结束时间"},{default:t(()=>[s(S(X(r.end)),1)]),_:1}),r.description?(n(),N(qe,{key:0,label:"描述"},{default:t(()=>[s(S(r.description),1)]),_:1})):te("",!0),r.location?(n(),N(qe,{key:1,label:"位置"},{default:t(()=>[s(S(r.location),1)]),_:1})):te("",!0)]),_:1})]),_:1},8,["modelValue"]),e(ye,{modelValue:C.value,"onUpdate:modelValue":P[20]||(P[20]=pe=>C.value=pe),title:h.value?"编辑事件":"添加事件",width:"500px"},{footer:t(()=>[l("span",js,[e(_e,{onClick:P[19]||(P[19]=pe=>C.value=!1)},{default:t(()=>[...P[50]||(P[50]=[s("取消",-1)])]),_:1}),h.value&&!h.value.readonly?(n(),N(_e,{key:0,onClick:ke,type:"danger"},{default:t(()=>[...P[51]||(P[51]=[s("删除",-1)])]),_:1})):te("",!0),h.value?(n(),N(_e,{key:1,type:"primary",onClick:re,disabled:h.value.readonly},{default:t(()=>[...P[52]||(P[52]=[s(" 更新 ",-1)])]),_:1},8,["disabled"])):(n(),N(_e,{key:2,type:"primary",onClick:re},{default:t(()=>[...P[53]||(P[53]=[s("添加",-1)])]),_:1}))])]),default:t(()=>[e(Ue,{model:o,"label-width":"80px"},{default:t(()=>[e(le,{label:"标题"},{default:t(()=>[e(Fe,{modelValue:o.title,"onUpdate:modelValue":P[14]||(P[14]=pe=>o.title=pe),placeholder:"请输入事件标题"},null,8,["modelValue"])]),_:1}),e(le,{label:"描述"},{default:t(()=>[e(Fe,{modelValue:o.description,"onUpdate:modelValue":P[15]||(P[15]=pe=>o.description=pe),type:"textarea",placeholder:"请输入事件描述"},null,8,["modelValue"])]),_:1}),e(le,{label:"开始时间"},{default:t(()=>[e(T,{modelValue:o.start,"onUpdate:modelValue":P[16]||(P[16]=pe=>o.start=pe),type:"datetime",format:"YYYY-MM-DD HH:mm",placeholder:"请选择开始时间",style:{width:"100%"}},null,8,["modelValue"])]),_:1}),e(le,{label:"结束时间"},{default:t(()=>[e(T,{modelValue:o.end,"onUpdate:modelValue":P[17]||(P[17]=pe=>o.end=pe),type:"datetime",format:"YYYY-MM-DD HH:mm",placeholder:"请选择结束时间",style:{width:"100%"}},null,8,["modelValue"])]),_:1}),h.value?te("",!0):(n(),N(le,{key:0,label:"上传图片"},{default:t(()=>[e(Te,{"auto-upload":!1,"on-change":me,"on-remove":ie,limit:1,accept:"image/*",drag:"",class:"calendar-image-upload","file-list":u.value,"onUpdate:fileList":P[18]||(P[18]=pe=>u.value=pe),disabled:f.value},{default:t(()=>[u.value.length===0&&!f.value?(n(),k("div",Hs,[e(he,{class:"upload-icon"},{default:t(()=>[e(se(Tt))]),_:1}),P[45]||(P[45]=l("div",{class:"upload-text"},"拖拽图片到此处或点击上传",-1)),P[46]||(P[46]=l("div",{class:"upload-hint"},"上传截图自动识别事件信息",-1))])):f.value?(n(),k("div",Os,[e(he,{class:"upload-icon is-loading"},{default:t(()=>[e(se(yl))]),_:1}),P[47]||(P[47]=l("div",{class:"upload-text"},"AI识别中...",-1)),P[48]||(P[48]=l("div",{class:"upload-hint"},"正在分析图片内容,请稍候",-1))])):te("",!0)]),_:1},8,["file-list","disabled"]),u.value.length>0&&!f.value?(n(),k("div",qs,[e(Be,{src:ce(u.value[0]),fit:"contain",class:"image-preview","preview-src-list":[ce(u.value[0])],"preview-teleported":""},{error:t(()=>[l("div",Ns,[e(he,null,{default:t(()=>[e(se(gl))]),_:1}),P[49]||(P[49]=l("span",null,"图片加载失败",-1))])]),_:1},8,["src","preview-src-list"])])):te("",!0)]),_:1}))]),_:1},8,["model"])]),_:1},8,["modelValue","title"]),e(ye,{modelValue:_.value,"onUpdate:modelValue":P[27]||(P[27]=pe=>_.value=pe),title:z.value?"编辑订阅日历":"订阅日历管理",width:"700px",onClosed:ve},{footer:t(()=>[l("span",Gs,[e(_e,{onClick:P[26]||(P[26]=pe=>_.value=!1)},{default:t(()=>[...P[58]||(P[58]=[s("关闭",-1)])]),_:1})])]),default:t(()=>[l("div",Ws,[e(Ue,{model:M,"label-width":"100px",class:"subscription-form"},{default:t(()=>[e(le,{label:"日历名称"},{default:t(()=>[e(Fe,{modelValue:M.name,"onUpdate:modelValue":P[21]||(P[21]=pe=>
126M.name=pe),placeholder:"例如:中国节假日"},null,8,["modelValue"])]),_:1}),e(le,{label:"日历地址"},{default:t(()=>[e(Fe,{modelValue:M.url,"onUpdate:modelValue":P[22]||(P[22]=pe=>M.url=pe),placeholder:"ICS 文件地址,例如:https://calendars.icloud.com/holidays/cn_zh.ics"},null,8,["modelValue"])]),_:1}),e(le,{label:"用户名"},{default:t(()=>[e(Fe,{modelValue:M.username,"onUpdate:modelValue":P[23]||(P[23]=pe=>M.username=pe),placeholder:"私有日历需要(可选)"},null,8,["modelValue"])]),_:1}),e(le,{label:"密码"},{default:t(()=>[e(Fe,{modelValue:M.password,"onUpdate:modelValue":P[24]||(P[24]=pe=>M.password=pe),type:"password",placeholder:"私有日历需要(可选)","show-password":""},null,8,["modelValue"])]),_:1}),e(le,{label:"显示颜色"},{default:t(()=>[e(ze,{modelValue:M.color,"onUpdate:modelValue":P[25]||(P[25]=pe=>M.color=pe)},null,8,["modelValue"])]),_:1}),e(le,null,{default:t(()=>[e(_e,{type:"primary",onClick:Ve},{default:t(()=>[s(S(z.value?"更新订阅":"添加订阅"),1)]),_:1}),z.value?(n(),N(_e,{key:0,onClick:De},{default:t(()=>[...P[54]||(P[54]=[s("取消",-1)])]),_:1})):te("",!0)]),_:1})]),_:1},8,["model"]),e(Re),l("div",Ks,[P[57]||(P[57]=l("h4",null,"已订阅的日历",-1)),Me((n(),N(bt,{data:g.value,style:{width:"100%"}},{default:t(()=>[e(Pe,{prop:"name",label:"名称",width:"150"}),e(Pe,{prop:"url",label:"地址","show-overflow-tooltip":""}),e(Pe,{prop:"color",label:"颜色",width:"120"},{default:t(pe=>[e(ze,{modelValue:pe.row.color,"onUpdate:modelValue":$e=>pe.row.color=$e,size:"small",onChange:$e=>ae(pe.row)},null,8,["modelValue","onUpdate:modelValue","onChange"])]),_:1}),e(Pe,{prop:"enabled",label:"状态",width:"80"},{default:t(pe=>[e(at,{modelValue:pe.row.enabled,"onUpdate:modelValue":$e=>pe.row.enabled=$e,onChange:$e=>xe(pe.row)},null,8,["modelValue","onUpdate:modelValue","onChange"])]),_:1}),e(Pe,{label:"操作",width:"150"},{default:t(pe=>[e(_e,{size:"small",onClick:$e=>Z(pe.row)},{default:t(()=>[...P[55]||(P[55]=[s("编辑",-1)])]),_:1},8,["onClick"]),e(_e,{type:"danger",size:"small",onClick:$e=>ee(pe.row.id)},{default:t(()=>[...P[56]||(P[56]=[s("删除",-1)])]),_:1},8,["onClick"])]),_:1})]),_:1},8,["data"])),[[Ze,V.value]])])])]),_:1},8,["modelValue","title"])],64)}}}),zt=Ce(Js,[["__scopeId","data-v-b1f5814e"]]),Xs={class:"exam-records"},Qs={class:"exam-header"},Zs={class:"header-actions"},er={class:"dialog-footer"},tr=ge({__name:"ExamRecords",emits:["detail","statistic"],setup(q,{emit:c}){const w=c,v=d([]),y=d(null),C=d([]),h=d([]),u=async()=>{try{const H=await A.get("/api/exam-types");h.value=H.data||[]}catch(H){console.error("Failed to load exam types:",H)}},f=(H,x)=>{const B=H?h.value.filter(D=>D.toLowerCase().includes(H.toLowerCase())).map(D=>({value:D})):h.value.map(D=>({value:D}));x(B)},m=[{label:"ID",prop:"id",width:80},{label:"年级",prop:"grade",width:120,formatter:H=>Ke[H.grade]||H.grade},{label:"考试类型",labelWidth:150,prop:"exam_type"},{label:"时间",prop:"date",formatter:H=>V(H.date)},{label:"班级排名",prop:"class_rank",width:80},{label:"年级排名",prop:"grade_rank",width:80},{label:"总分",prop:"total_score",width:100,formatter:H=>H.exam_scores&&H.exam_scores.length>0?H.exam_scores.reduce((B,D)=>B+D.score,0).toString():"-"},{label:"科目成绩",prop:"exam_scores",formatter:H=>`${H.exam_scores?H.exam_scores.length:0} 个科目`},{label:"操作",prop:"actions",kind:"slot"}],_=d(!1),p=d(!1),r=d(),o=d({exam_type:"",grade:"",date:new Date().toISOString(),class_rank:1,grade_rank:1}),g={examType:[{required:!0,message:"请输入考试类型",trigger:"blur"}],date:[{required:!0,message:"请选择考试时间",trigger:"change"}],classRank:[{required:!0,message:"请输入班级排名",trigger:"blur"},{type:"number",min:1,message:"班级排名必须大于0",trigger:"blur"}],gradeRank:[{required:!0,message:"请输入年级排名",trigger:"blur"},{type:"number",min:1,message:"年级排名必须大于0",trigger:"blur"}]},V=H=>new Date(H).toLocaleDateString("zh-CN",{year:"numeric",month:"2-digit",day:"2-digit"}),z=()=>{j.value.loadData()},M=H=>{y.value=H,w("detail",H.id,H.exam_type)},L=()=>{p.value=!1,o.value={exam_type:"",grade:"",date:new Date().toISOString(),class_rank:1,grade_rank:1},_.value=!0},I=H=>{p.value=!0,o.value={id:H.id,grade:H.grade,exam_type:H.exam_type,date:H.date,class_rank:H.class_rank,grade_rank:H.grade_rank},_.value=!0},O=()=>{_.value=!1},j=d(),R=async()=>{r.value&&await r.value.validate(async H=>{if(H){o.value.date=new Date(o.value.date).toISOString();try{if(p.value&&o.value.id){await A.put(`/api/exams/${o.value.id}`,o.value);const x=v.value.findIndex(B=>B.id===o.value.id);x!==-1&&(v.value[x]={...o.value})}else{const x=await A.post("/api/exams",o.value);v.value.unshift(x.data)}_.value=!1,b.success(p.value?"考试记录更新成功":"考试记录创建成功"),z()}catch(x){console.error(p.value?"更新考试记录失败:":"创建考试记录失败:",x),b.error(p.value?"更新考试记录失败":"创建考试记录失败")}}else console.log("表单验证失败!")})},K=async H=>{try{await et.confirm("确定要删除这条考试记录吗?此操作不可恢复","删除确认",{confirmButtonText:"确定",cancelButtonText:"取消",type:"warning"}),await A.delete(`/api/exams/${H}`),v.value=v.value.filter(x=>x.id!==H),b.success("考试记录删除成功"),z()}catch(x){console.error("删除考试记录失败:",x),b.error("删除考试记录失败")}};return be(()=>{for(const H in Ke)C.value.push({label:Ke[H],value:H});u()}),(H,x)=>{const B=a("el-option"),D=a("el-select"),U=a("el-form-item"),F=a("el-autocomplete"),i=a("el-date-picker"),$=a("el-input-number"),X=a("el-form"),G=a("el-dialog");return n(),k("div",Xs,[l("div",Qs,[x[10]||(x[10]=l("h2",null,"考试记录",-1)),l("div",Zs,[e(se(nt),{type:"primary",onClick:z},{default:t(()=>[...x[7]||(x[7]=[s("刷新",-1)])]),_:1}),e(se(nt),{type:"primary",onClick:x[0]||(x[0]=E=>w("statistic"))},{default:t(()=>[...x[8]||(x[8]=[s("查看统计",-1)])]),_:1}),e(se(nt),{type:"success",onClick:L},{default:t(()=>[...x[9]||(x[9]=[s("新增考试",-1)])]),_:1})])]),e(mt,{columns:m,dataURL:"/api/exams",ref_key:"examTableRef",ref:j},{actions:t(({row:E})=>[e(se(nt),{size:"small",type:"primary",onClick:Oe(oe=>M(E),["stop"])},{default:t(()=>[...x[11]||(x[11]=[s("详情",-1)])]),_:1},8,["onClick"]),e(se(nt),{size:"small",type:"warning",onClick:Oe(oe=>I(E),["stop"])},{default:t(()=>
126[...x[12]||(x[12]=[s("编辑",-1)])]),_:1},8,["onClick"]),e(se(nt),{size:"small",type:"danger",onClick:Oe(oe=>K(E.id),["stop"])},{default:t(()=>[...x[13]||(x[13]=[s("删除",-1)])]),_:1},8,["onClick"])]),_:1},512),e(G,{title:p.value?"编辑考试":"新增考试",modelValue:_.value,"onUpdate:modelValue":x[6]||(x[6]=E=>_.value=E),"before-close":O},{footer:t(()=>[l("span",er,[e(se(nt),{onClick:O},{default:t(()=>[...x[14]||(x[14]=[s("取消",-1)])]),_:1}),e(se(nt),{type:"primary",onClick:R},{default:t(()=>[...x[15]||(x[15]=[s("提交",-1)])]),_:1})])]),default:t(()=>[e(X,{model:o.value,rules:g,ref_key:"examFormRef",ref:r,"label-width":"120px"},{default:t(()=>[e(U,{label:"年级",prop:"grade"},{default:t(()=>[e(D,{modelValue:o.value.grade,"onUpdate:modelValue":x[1]||(x[1]=E=>o.value.grade=E),placeholder:"请选择年级",style:{width:"100%"}},{default:t(()=>[(n(!0),k(ue,null,fe(C.value,E=>(n(),N(B,{key:E.value,label:E.label,value:E.value},null,8,["label","value"]))),128))]),_:1},8,["modelValue"])]),_:1}),e(U,{label:"考试类型",prop:"exam_type"},{default:t(()=>[e(F,{modelValue:o.value.exam_type,"onUpdate:modelValue":x[2]||(x[2]=E=>o.value.exam_type=E),"fetch-suggestions":f,placeholder:"请输入或选择考试类型",style:{width:"100%"}},null,8,["modelValue"])]),_:1}),e(U,{label:"考试时间",prop:"date"},{default:t(()=>[e(i,{modelValue:o.value.date,"onUpdate:modelValue":x[3]||(x[3]=E=>o.value.date=E),type:"datetime",placeholder:"选择考试日期",format:"YYYY-MM-DDTHH:mm:ssZ","value-format":"YYYY-MM-DDTHH:mm:ssZ"},null,8,["modelValue"])]),_:1}),e(U,{label:"班级排名",prop:"class_rank"},{default:t(()=>[e($,{modelValue:o.value.class_rank,"onUpdate:modelValue":x[4]||(x[4]=E=>o.value.class_rank=E),min:1,placeholder:"班级排名"},null,8,["modelValue"])]),_:1}),e(U,{label:"年级排名",prop:"grade_rank"},{default:t(()=>[e($,{modelValue:o.value.grade_rank,"onUpdate:modelValue":x[5]||(x[5]=E=>o.value.grade_rank=E),min:1,placeholder:"年级排名"},null,8,["modelValue"])]),_:1})]),_:1},8,["model"])]),_:1},8,["title","modelValue"])])}}}),lr=Ce(tr,[["__scopeId","data-v-8d86edd1"]]),ar={id:"total-score-trend-chart",style:{height:"400px"}},or={id:"total-rank-change-chart",style:{height:"400px"}},nr={id:"items-rank-change-chart",style:{height:"400px"}},sr=ge({__name:"ExamStat",setup(q){const c=d(!1),w=d(!1),v=d(!1);let y=null,C=null,h=null;const u=d(!1);je(u,()=>{o=0,f()});const f=async()=>{await dt(),c.value=!0,w.value=!0,v.value=!0,A.get("/api/exams").then(M=>M.data).then(M=>{m(M),_(M)}).finally(()=>{c.value=!1,w.value=!1}),A.get("/api/exams/stats/subject").then(M=>M.data).then(M=>{p(new Map(Object.entries(M)))}).finally(()=>{v.value=!1})},m=M=>{const L=document.getElementById("total-rank-change-chart");if(L){y&&y.dispose(),y=ut(L);const I=[...M].sort((j,R)=>new Date(j.date).getTime()-new Date(R.date).getTime()).map(j=>({date:z(j.date),gradeRank:j.grade_rank,classRank:j.class_rank})),O={title:{text:"总分排名变化趋势"},tooltip:{trigger:"axis"},xAxis:{type:"category",data:I.map(j=>j.date)},yAxis:{type:"value",inverse:!0,name:"排名"},series:[{name:"年级排名",data:I.map(j=>j.gradeRank),type:"line",smooth:!0,itemStyle:{color:"#5470c6"},lineStyle:{color:"#5470c6"}},{name:"班级排名",data:I.map(j=>j.classRank),type:"line",smooth:!0,itemStyle:{color:"#fac858"},lineStyle:{color:"#fac858"}}],grid:{left:"3%",right:"4%",bottom:"3%",containLabel:!0},legend:{data:["年级排名","班级排名"],orient:"vertical",right:"5%",top:"center"}};y.setOption(O)}},_=M=>{const L=document.getElementById("total-score-trend-chart");if(L){h&&h.dispose(),h=ut(L);const I=[...M].sort((j,R)=>new Date(j.date).getTime()-new Date(R.date).getTime()).map(j=>{let R=0,K=0;return j.exam_scores&&j.exam_scores.forEach(H=>{R+=H.score,K+=H.full_score}),{date:z(j.date),totalScore:R,fullScore:K,scoreAs100:K>0?Math.round(R*100/K):0}}),O={title:{text:"总分趋势图"},tooltip:{trigger:"axis",formatter:j=>{if(j&&j.length>0){const R=j[0],K=I[R.dataIndex];return u.value?`${R.axisValue}<br/>总分(100分制): ${K.scoreAs100}分`:`${R.axisValue}<br/>总分: ${K.totalScore}分`}return""}},xAxis:{type:"category",data:I.map(j=>j.date)},yAxis:{type:"value",name:u.value?"分数(100分制)":"分数"},series:[{name:"总分",data:I.map(j=>u.value?j.scoreAs100:j.totalScore),type:"line",smooth:!0,itemStyle:{color:"#67C23A"},lineStyle:{color:"#67C23A"},markLine:{data:[{type:"average",name:"平均分"}],lineStyle:{color:"#F56C6C",type:"dashed"}}}],grid:{left:"3%",right:"4%",bottom:"3%",containLabel:!0}};h.setOption(O)}},p=M=>{o=0;const L=new Map;M.forEach((O,j)=>{O.forEach(R=>{var K;u.value&&(R.score=Math.round(R.score*100/R.full_score)),L.has(R.date)||L.set(R.date,[]),(K=L.get(R.date))==null||K.push(R)})});const I=[];M.forEach((O,j)=>{const R={name:j,data:O.map(K=>K.score),color:g()};I.push(R)}),V("items-rank-change-chart","各科总分变化趋势",L,I,C)},r=["#5470c6","#91cc75","#fac858","#ee6666","#73c0de","#3ba272","#fc8452","#9a60b4","#ea7ccc","#2c3e50","#27ae60","#e74c3c","#3498db","#f39c12","#8e44ad","#16a085","#d35400","#c0392b","#2980b9","#7f8c8d"];let o=0;const g=()=>{const M=r[o%r.length];return o++,M},V=(M,L,I,O,j)=>{const R=document.getElementById(M);if(R){j&&j.dispose(),j=ut(R);const K=O.map(x=>({name:x.name,data:x.data,type:"line",itemStyle:{color:x.color},lineStyle:{color:x.color}})),H={title:{text:L},tooltip:{trigger:"axis"},xAxis:{type:"category",data:[...I.keys()]},yAxis:{type:"value",name:"分数"},series:K,grid:{left:"3%",right:"4%",bottom:"3%",containLabel:!0},legend:{data:O.map(x=>x.name),orient:"vertical",right:"5%",top:"center"}};j.setOption(H)}},z=M=>new Date(M).toLocaleDateString("zh-CN",{year:"numeric",month:"2-digit",day:"2-digit"});return be(()=>{f()}),(M,L)=>{const I=a("el-switch"),O=Ee("loading");return n(),k(ue,null,[Me(l("div",ar,null,512),[[O,w.value]]),Me(l("div",or,null,512),[[O,c.value]]),e(I,{modelValue:u.value,"onUpdate:modelValue":L[0]||(L[0]=j=>u.value=j),"active-text":"100分制","inactive-text":"实际分数"},null,8,["modelValue"]),Me(l("div",nr,null,512),[[O,v.value]])],64)}}}),rr={class:"exam-summary"},ir={class:"summary-content"},ur={class:"summary-item"},dr={class:"summary-value primary"},cr={class:"summary-item"},pr={class:"summary-value"},mr={key:0,class:"summary-item"},vr=ge({__name:"ExamSubjectRecords",props:{examID:{}},setup(q){const c=q,w=d(),v=d(!1),y=d([]),C=Le(()=>y.value.reduce((g,V)=>g+(V.score||0),0)),h=Le(()=>y.value.reduce((g,V)=>g+(V.full_score||0),0)),u=Le(()=>h.value===0?0:Math.round(C.value*100/h.value)),f=g=>g>=90?"excellent":g>=80?"good":g>=60?"pass":"fail",m=g=>{y.value=g},_=[{label:"ID",prop:"id"},{label:"科目",prop:"subject",searchable:!0},{label:"满分",prop:"full_score"},{label:"考试成绩",prop:"score"},{label:"班级排名",prop:"class_rank"},{label:"年级排名",prop:"grade_rank"}],p=d(!1),r=d({subject:"",score:0,full_score:100,class_rank:-1,grade_rank:-1,exam_id:c.examID}),o=async()=>{r.value.score=Number(r.value.score),r.value.full_score=Number(r.value.full_score),r.value.class_rank=Number(r.value.class_rank),r.value.grade_rank=Number(r.value.grade_rank),await A.post(`/api/examScores/${c.examID}`,r.value),await w.value.loadData(),p.value=!1};return(g,V)=>{const z=a("el-card"),M=a("el-button"),L=a("el-option"),I=a("el-select"),O=a("el-form-item"),j=a("el-input"),R=a("el-form"),K=a("el-dialog"),H=Ee("loading");return n(),k(ue,null,[Me((n(),k("div",rr,[e(z,{shadow:"hover"},{header:t(()=>[...V[8]||(V[8]=[l("div",{class:"card-header"},[l("span",null,"考试总分")],-1)])]),default:t(()=>[l("div",ir,[l("div",ur,[V[9]||(V[9]=l("span",{class:"summary-label"},"总分:",-1)),l("span",dr,S(C.value),1)]),l("div",cr,[V[10]||(V[10]=l("span",{class:"summary-label"},"满分:",-1)),l("span",pr,S(h.value),1)]),h.value>0?(n(),k("div",mr,[V[11]||(V[11]=l("span",{class:"summary-label"},"得分率:",-1)),l("span",{class:Ye(["summary-value",f(u.value)])},S(u.value)+"%",3)])):te("",!0)])]),_:1})])),[[H,v.value]]),e(mt,{dataURL:"/api/examScores/"+c.examID,columns:_,ref_key:"tableRef",ref:w,deleteKey:"id",onDataLoaded:m},{"button-tail":t(()=>[e(M,{type:"primary",onClick:V[0]||(V[0]=x=>p.value=!0)},{default:t(()=>[...V[12]||(V[12]=[s("添加",-1)])]),_:1})]),_:1},8,["dataURL"]),e(K,{title:"添加考试记录",modelValue:p.value,"onUpdate:modelValue":V[7]||(V[7]=x=>p.value=x),"destroy-on-close":""},{footer:t(()=>[e(M,{onClick:V[6]||(V[6]=x=>p.value=!1)},{default:t(()=>[...V[13]||(V[13]=[s("取消",-1)])]),_:1}),e(M,{type:"primary",onClick:o},{default:t(()=>[...V[14]||(V[14]=[s("确定",-1)])]),_:1})]),default:t(()=>[e(R,{"label-width":"auto"},{default:t(()=>[e(O,{label:"考试科目",prop:"subject"},{default:t(()=>[e(I,{modelValue:r.value.subject,"onUpdate:modelValue":V[1]||(V[1]=x=>r.value.subject=x),placeholder:"学科"},{default:t(()=>[(n(!0),k(ue,null,fe(se($t),x=>
126(n(),N(L,{label:x,value:x,key:x},null,8,["label","value"]))),128))]),_:1},8,["modelValue"])]),_:1}),e(O,{label:"考试成绩"},{default:t(()=>[e(j,{modelValue:r.value.score,"onUpdate:modelValue":V[2]||(V[2]=x=>r.value.score=x),placeholder:"请输入考试成绩",type:"number"},null,8,["modelValue"])]),_:1}),e(O,{label:"考试满分"},{default:t(()=>[e(j,{modelValue:r.value.full_score,"onUpdate:modelValue":V[3]||(V[3]=x=>r.value.full_score=x),placeholder:"请输入考试满分",type:"number"},null,8,["modelValue"])]),_:1}),e(O,{label:"班级排名"},{default:t(()=>[e(j,{modelValue:r.value.class_rank,"onUpdate:modelValue":V[4]||(V[4]=x=>r.value.class_rank=x),placeholder:"请输入班级排名",type:"number"},null,8,["modelValue"])]),_:1}),e(O,{label:"年级排名"},{default:t(()=>[e(j,{modelValue:r.value.grade_rank,"onUpdate:modelValue":V[5]||(V[5]=x=>r.value.grade_rank=x),placeholder:"请输入年级排名",type:"number"},null,8,["modelValue"])]),_:1})]),_:1})]),_:1},8,["modelValue"])],64)}}}),fr=Ce(vr,[["__scopeId","data-v-2f9a6400"]]),_r={class:"text-large font-600 mr-3"},yr=ge({__name:"ExamManagement",setup(q){const c=d("main"),w=d(""),v=d(0),y=(u,f)=>{c.value="detail",v.value=u,w.value=f},C=()=>{c.value="statistic"},h=()=>{c.value="main"};return(u,f)=>{const m=a("el-page-header");return c.value=="main"?(n(),N(lr,{key:0,onDetail:y,onStatistic:C})):c.value=="detail"?(n(),N(m,{key:1,onBack:h},{content:t(()=>[l("span",_r,S(w.value),1)]),default:t(()=>[e(fr,{examID:v.value},null,8,["examID"])]),_:1})):c.value=="statistic"?(n(),N(m,{key:2,onBack:h},{content:t(()=>[...f[0]||(f[0]=[l("span",{class:"text-large font-600 mr-3"},"考试统计",-1)])]),default:t(()=>[e(sr)]),_:1})):te("",!0)}}}),gr={key:0},br={key:1},wr={key:2},kr={key:3},hr={key:4},$r={key:5},Vr={key:6},Cr={key:7},xr={key:8},Dr={key:9},Sr={key:10},Mr=ge({__name:"StudentDashboard",setup(q){const c=st(),w=Ie(),v=!!sessionStorage.getItem("token"),y=d("calendar"),C=d(!1);v||(y.value="dictation"),be(()=>{c.query.tab&&(y.value=c.query.tab),h(),window.addEventListener("resize",h)});function h(){C.value=window.innerWidth>768}function u(m){!v&&m!=="dictation"||(y.value=m,window.innerWidth<=768&&(C.value=!1),w.replace({query:{...c.query,tab:m}}))}function f(){C.value=!C.value}return ct(()=>{window.removeEventListener("resize",h)}),(m,_)=>{const p=a("el-icon"),r=a("el-menu-item"),o=a("el-menu"),g=a("el-aside"),V=a("el-main"),z=a("el-container");return n(),N(z,{class:"student-dashboard"},{default:t(()=>[e(g,{class:Ye(["sidebar",{"mobile-hidden":!C.value}])},{default:t(()=>[e(o,{"default-active":y.value,class:"student-menu",onSelect:u},{default:t(()=>[v?(n(),N(r,{key:0,index:"calendar"},{default:t(()=>[e(p,null,{default:t(()=>[e(se(ht))]),_:1}),_[0]||(_[0]=l("span",null,"我的日历",-1))]),_:1})):te("",!0),v?(n(),N(r,{key:1,index:"courses"},{default:t(()=>[e(p,null,{default:t(()=>[e(se(Vt))]),_:1}),_[1]||(_[1]=l("span",null,"选择课程",-1))]),_:1})):te("",!0),v?(n(),N(r,{key:2,index:"payment-records"},{default:t(()=>[e(p,null,{default:t(()=>[e(se(Kt))]),_:1}),_[2]||(_[2]=l("span",null,"缴费记录",-1))]),_:1})):te("",!0),v?(n(),N(r,{key:3,index:"class-records"},{default:t(()=>[e(p,null,{default:t(()=>[e(se(kt))]),_:1}),_[3]||(_[3]=l("span",null,"上课记录",-1))]),_:1})):te("",!0),v?(n(),N(r,{key:4,index:"my-notes"},{default:t(()=>[e(p,null,{default:t(()=>[e(se(bl))]),_:1}),_[4]||(_[4]=l("span",null,"我的笔记",-1))]),_:1})):te("",!0),v?(n(),N(r,{key:5,index:"vocabulary"},{default:t(()=>[e(p,null,{default:t(()=>[e(se(Gt))]),_:1}),_[5]||(_[5]=l("span",null,"词汇学习",-1))]),_:1})):te("",!0),e(r,{index:"dictation"},{default:t(()=>[e(p,null,{default:t(()=>[e(se(Rt))]),_:1}),_[6]||(_[6]=l("span",null,"单词听写",-1))]),_:1}),v?(n(),N(r,{key:6,index:"composition"},{default:t(()=>[e(p,null,{default:t(()=>[e(se(kt))]),_:1}),_[7]||(_[7]=l("span",null,"AI作文",-1))]),_:1})):te("",!0),v?(n(),N(r,{key:7,index:"dictionary"},{default:t(()=>[e(p,null,{default:t(()=>[e(se(Rt))]),_:1}),_[8]||(_[8]=l("span",null,"AI 字典",-1))]),_:1})):te("",!0),v?(n(),N(r,{key:8,index:"my-mistakes"},{default:t(()=>[e(p,null,{default:t(()=>[e(se(kt))]),_:1}),_[9]||(_[9]=l("span",null,"试卷错题",-1))]),_:1})):te("",!0),v?(n(),N(r,{key:9,index:"exam-management"},{default:t(()=>[e(p,null,{default:t(()=>[e(se(qt))]),_:1}),_[10]||(_[10]=l("span",null,"考试记录",-1))]),_:1})):te("",!0)]),_:1},8,["default-active"])]),_:1},8,["class"]),l("div",{class:"menu-toggle",onClick:f},[e(p,null,{default:t(()=>[e(se(At))]),_:1})]),e(V,{class:"main-content"},{default:t(()=>[y.value==="calendar"&&v?(n(),k("div",gr,[e(zt)])):y.value==="courses"&&v?(n(),k("div",br,[e(Qa)])):y.value==="payment-records"&&v?(n(),k("div",wr,[e(to)])):y.value==="class-records"&&v?(n(),k("div",kr,[e(ao)])):y.value==="my-notes"&&v?(n(),k("div",hr,[e(Zt,{"owner-role":"student"})])):y.value==="vocabulary"&&v?(n(),k("div",$r,[e(Wo)])):y.value==="dictation"?(n(),k("div",Vr,[e(Vn)])):y.value==="composition"&&v?(n(),k("div",Cr,[e(Rn)])):y.value==="dictionary"?(n(),k("div",xr,[e(yt)])):y.value==="my-mistakes"?(n(),k("div",Dr,[e(cs)])):y.value==="exam-management"&&v?(n(),k("div",Sr,[e(yr)])):te("",!0)]),_:1})]),_:1})}}}),Ur=Ce(Mr,[["__scopeId","data-v-c07f31ea"]]),Ir={key:0},Tr={key:1},Ar=ge({__name:"JoinInstitution",emits:["joined"],setup(q,{emit:c}){const w=c,v=d([]),y=d(null),C=d(!0),h=async()=>{try{const f=await A.get("/api/institutions");v.value=f.data}catch(f){console.error("Failed to fetch institutions:",f)}finally{C.value=!1}},u=async()=>
126{if(y.value)try{await A.post("/api/teacher/join-institution",{institution_id:y.value}).then(()=>{w("joined")}),b.success("成功加入机构"),y.value=null}catch(f){console.error("Failed to join institution:",f),b.warning("加入机构失败")}};return be(()=>{h()}),(f,m)=>{const _=a("el-option"),p=a("el-select"),r=a("el-col"),o=a("el-button"),g=a("el-row");return C.value?(n(),k("div",Ir,"Loading institutions...")):(n(),k("div",Tr,[e(g,null,{default:t(()=>[e(r,{span:20},{default:t(()=>[e(p,{modelValue:y.value,"onUpdate:modelValue":m[0]||(m[0]=V=>y.value=V),placeholder:"请选择机构"},{default:t(()=>[(n(!0),k(ue,null,fe(v.value,V=>(n(),N(_,{key:V.id,label:V.name,value:V.id},null,8,["label","value"]))),128))]),_:1},8,["modelValue"])]),_:1}),e(r,{span:4},{default:t(()=>[e(o,{type:"primary",onClick:u,disabled:!y.value,style:{"margin-left":"10px"}},{default:t(()=>[...m[1]||(m[1]=[s(" 加入 ",-1)])]),_:1},8,["disabled"])]),_:1})]),_:1})]))}}}),zr={class:"course-description"},Lr={class:"timeslot-form"},Yr={style:{margin:"15px 0"}},Er={key:0,class:"pagination-container"},Rr={style:{display:"flex",gap:"8px","align-items":"center"}},Fr=ge({__name:"CourseManagement",setup(q){const c=Ae({title:"",description:"",maxStudents:0,mode:"private",price:100,timeslots:[]}),w=d([]),v=d([]),y=d(!1),C=d(null),h=d(!1),u=d(),f=d([]),m=d({page:1}),_=i=>{y.value=!0,C.value=i};je(C,async i=>{const $=await A.get(`/api/teacher/courseBinding/${i}`);v.value=$.data,g(i)});const p=async()=>{try{if(!u.value||!C.value){b.error("请选择学生进行绑定");return}await A.post(`/api/teacher/courses/${C.value}/bind-student/${u.value}`,{student_id:u.value}),b.success("学生绑定成功");const i=await A.get(`/api/teacher/courseBinding/${C.value}`);v.value=i.data}catch(i){console.error("绑定学生失败:",i),b.error("绑定学生失败")}},r=async i=>{try{await A.delete(`/api/teacher/courseBinding/${C.value}/${i}`),b.success("删除学生成功");const $=await A.get(`/api/teacher/courseBinding/${C.value}`);v.value=$.data}catch($){console.error("删除学生失败:",$),b.error("删除学生失败")}};be(()=>{L(),o()});const o=async function(){try{const i=await A.get("/api/admin/students",{params:{page_disabled:1}});f.value=i.data}catch(i){console.error("加载学生列表失败:",i),b.error("加载学生列表失败")}},g=async function(i){try{const $={page:m.value.page,page_size:m.value.page_size},X=await A.get(`/api/courses/${i}/timeslots`,{params:$});m.value=X.data}catch($){console.error("加载时段列表失败:",$),b.error("加载时段列表失败")}},V=async function(i){m.value.page=i,g(C.value)},z=i=>{m.value.page_size=i,g(C.value)};async function M(){try{if(!c.title){b.error("请输入课程标题");return}const i=JSON.parse(sessionStorage.getItem("user")||"{}"),$=(i==null?void 0:i.id)||1,X=c.timeslots.filter(E=>E.range[0]&&E.range[1]).map(E=>({start:E.range[0].toISOString(),end:E.range[1].toISOString()})),G={title:c.title,description:c.description,max_students:c.maxStudents,mode:c.mode,price:c.price,timeslots:X};await A.post(`/api/teachers/${$}/courses`,G),b.success("课程创建成功"),c.title="",c.description="",c.timeslots=[],c.maxStudents=1,c.mode="private",c.price=0,L(),h.value=!1}catch(i){console.error("创建课程失败:",i),b.error("创建课程失败")}}async function L(){try{const i=JSON.parse(sessionStorage.getItem("user")||"{}"),$=(i==null?void 0:i.id)||1,X=await A.get(`/api/teachers/${$}/courses`);w.value=X.data,w.value.forEach(G=>{G.duration=1,G.studentCount=G.students?G.students.length:0}),X.data.length>0&&(C.value=X.data[0].id)}catch(i){console.error("加载课程失败:",i),b.error("加载课程失败")}}async function I(i){const $=new Date(i.startTime);$.setHours($.getHours()+i.duration),i.newRange=[i.startTime,$];try{if(!i.newRange||!i.newRange[0]||!i.newRange[1]){b.error("请选择有效的时间范围");return}const X={start:i.newRange[0].toISOString(),end:i.newRange[1].toISOString()};await A.post(`/api/courses/${i.id}/timeslots`,X),b.success("时段添加成功");const G=new Date(i.newRange[1]);G.setHours(G.getHours()+i.duration),i.startTime=G,g(C.value)}catch(X){console.error("添加时段失败:",X),b.error("添加时段失败")}}async function O(i){try{await A.delete(`/api/timeslots/${i}`),b.success("时段删除成功"),g(C.value)}catch($){console.error("删除时段失败:",$),b.error("删除时段失败")}}async function j(i){try{const $=await A.get(`/api/courses/${i.id}/students`);i.students=$.data,i.studentCount=$.data.length,i.showStudents=!0,m.value.data.forEach(X=>
126{X.student="",i.students.forEach(G=>{G.bookings.forEach(E=>{E.timeslot_id===X.id&&(X.student+=", "+G.name)})}),X.student=X.student.substring(2)})}catch($){console.error("加载学生信息失败:",$),b.error("加载学生信息失败")}}const R=async i=>{try{await A.delete(`/api/courses/${i}`),b.success("课程删除成功"),L()}catch($){console.error("删除课程失败:",$),b.error("删除课程失败")}},H=function(i){const $=new Date;return $.setHours(i),$.setMinutes(0),$.setSeconds(0),$.setMilliseconds(0),$}(10),x={shortcuts:[{text:"今天",onClick(i){const $=new Date;$.setHours(10),$.setMinutes(0),$.setSeconds(0),$.setMilliseconds(0);const X=new Date;X.setHours(X.getHours()+1),X.setMinutes(0),X.setSeconds(0),X.setMilliseconds(0),i.$emit("pick",[$,X])}},{text:"明天",onClick(i){const $=new Date;$.setDate($.getDate()+1),$.setHours(10),$.setMinutes(0),$.setSeconds(0),$.setMilliseconds(0);const X=new Date;X.setDate(X.getDate()+1),X.setHours(X.getHours()+1),X.setMinutes(0),X.setSeconds(0),X.setMilliseconds(0),i.$emit("pick",[$,X])}}],disabledDate(i){return i.getTime()<Date.now()}},B=(i,$)=>{if(i&&i[0]){const X=new Date(i[0]);if(X.setMinutes(0),X.setSeconds(0),X.setMilliseconds(0),!i[1]||i[1]&&i[1].getTime()!==X.getTime()+60*60*1e3){const G=new Date(X);G.setHours(X.getHours()+1),$.newRange=[X,G]}}},D=i=>i.getTime()<Date.now();function U(i,$,X,G){return`${de(X).local().format("MM-DD HH:mm")}`}function F(i,$){return`${de($).diff(de(i),"hour",!0)}h`}return(i,$)=>{const X=a("el-button"),G=a("el-tag"),E=a("el-date-picker"),oe=a("el-form-item"),Q=a("el-input-number"),re=a("el-form"),me=a("el-table-column"),ie=a("el-table"),ce=a("el-pagination"),ke=a("el-tab-pane"),De=a("el-tabs"),ve=a("el-card"),W=a("el-option"),Z=a("el-select"),Ve=a("el-dialog"),xe=a("el-input");return n(),k(ue,null,[e(ve,null,{default:t(()=>[$[20]||($[20]=l("h2",null,"我的课程",-1)),w.value.length===0?(n(),N(X,{key:0,type:"primary",onClick:$[0]||($[0]=ae=>h.value=!0)},{default:t(()=>[...$[12]||($[12]=[s("创建课程",-1)])]),_:1})):te("",!0),e(De,{addable:"",onTabAdd:$[1]||($[1]=ae=>h.value=!0),modelValue:C.value,"onUpdate:modelValue":$[2]||($[2]=ae=>C.value=ae)},{default:t(()=>[(n(!0),k(ue,null,fe(w.value,ae=>(n(),N(ke,{label:ae.title,key:ae.id,name:ae.id},{default:t(()=>[l("div",zr,[s(S(ae.description)+" ",1),ae.mode==="private"?(n(),N(G,{key:0,type:"danger"},{default:t(()=>[...$[13]||($[13]=[s("私密课程",-1)])]),_:1})):(n(),N(G,{key:1,type:"success"},{default:t(()=>[...$[14]||($[14]=[s("公开课程",-1)])]),_:1})),e(G,null,{default:t(()=>[s("每时段学生容量:"+S(ae.max_students)+"位",1)]),_:2},1024),e(G,{type:"info"},{default:t(()=>[s("价格:"+S(ae.price)+" 元",1)]),_:2},1024)]),l("div",Lr,[e(re,{inline:""},{default:t(()=>[e(oe,{label:"开始时间"},{default:t(()=>[e(E,{modelValue:ae.startTime,"onUpdate:modelValue":ee=>ae.startTime=ee,type:"datetime","disabled-date":D,"picker-options":x,"default-time":se(H),format:"YYYY-MM-DD HH:mm",onCalendarChange:ee=>B(ee,ae)},null,8,["modelValue","onUpdate:modelValue","default-time","onCalendarChange"])]),_:2},1024),e(oe,{label:"时长"},{default:t(()=>[e(Q,{modelValue:ae.duration,"onUpdate:modelValue":ee=>ae.duration=ee,min:1,precision:1,max:4},{suffix:t(()=>[...$[15]||($[15]=[l("span",null,"小时",-1)])]),_:1},8,["modelValue","onUpdate:modelValue"])]),_:2},1024),e(oe,null,{default:t(()=>[e(X,{type:"primary",size:"small",onClick:ee=>I(ae)},{default:t(()=>[...$[16]||($[16]=[s("添加时段",-1)])]),_:1},8,["onClick"])]),_:2},1024)]),_:2},1024)]),l("div",Yr,[e(X,{size:"small",onClick:ee=>j(ae)},{default:t(()=>[s("查看选课学生 ("+S(ae.studentCount||0)+")",1)]),_:2},1032,["onClick"]),e(X,{size:"small",onClick:ee=>_(ae.id)},{default:t(()=>[...$[17]||($[17]=[s("管理选课学生",-1)])]),_:1},8,["onClick"]),e(X,{size:"small",type:"danger",onClick:ee=>R(ae.id)},{default:t(()=>[...$[18]||($[18]=[s("删除课程",-1)])]),_:1},8,["onClick"])]),e(ie,{data:m.value?m.value.data:[],"table-layout":"auto"},{default:t(()=>[e(me,{prop:"id",label:"时段ID"}),e(me,{prop:"start",label:"时段开始",formatter:U}),e(me,{prop:"end",label:"时段结束",formatter:U}),e(me,{label:"时长",width:"80"},{default:t(ee=>[s(S(F(ee.row.start,ee.row.end)),1)]),_:1}),e(me,{prop:"student",label:"已选学生"}),e(me,{label:"操作"},{default:t(ee=>[e(X,{type:"danger",size:"small",onClick:Y=>
126O(ee.row.id)},{default:t(()=>[...$[19]||($[19]=[s("删除",-1)])]),_:1},8,["onClick"])]),_:1})]),_:1},8,["data"]),m.value&&m.value.total>m.value.page_size?(n(),k("div",Er,[e(ce,{onCurrentChange:V,onSizeChange:z,"current-page":m.value.page,"page-size":m.value.page_size,total:m.value.total,"page-sizes":[10,20,50,100],layout:"total, sizes, prev, pager, next, jumper"},null,8,["current-page","page-size","total"])])):te("",!0)]),_:2},1032,["label","name"]))),128))]),_:1},8,["modelValue"])]),_:1}),e(Ve,{title:"管理选课学生",modelValue:y.value,"onUpdate:modelValue":$[5]||($[5]=ae=>y.value=ae),width:"60%"},{footer:t(()=>[e(X,{onClick:$[4]||($[4]=ae=>y.value=!1)},{default:t(()=>[...$[23]||($[23]=[s("关闭",-1)])]),_:1})]),default:t(()=>[l("div",Rr,[e(Z,{modelValue:u.value,"onUpdate:modelValue":$[3]||($[3]=ae=>u.value=ae),placeholder:"请选添加的学生",style:{flex:"1"}},{default:t(()=>[(n(!0),k(ue,null,fe(f.value,ae=>(n(),N(W,{key:ae.id,label:ae.name,value:ae.id},null,8,["label","value"]))),128))]),_:1},8,["modelValue"]),e(X,{type:"primary",onClick:p},{default:t(()=>[...$[21]||($[21]=[s("添加",-1)])]),_:1})]),e(ie,{data:v.value,style:{width:"100%"}},{default:t(()=>[e(me,{prop:"name",label:"学生姓名",width:"150"}),e(me,{prop:"email",label:"邮箱"}),e(me,{label:"操作"},{default:t(ae=>[e(X,{type:"danger",size:"small",onClick:ee=>r(ae.row.id)},{default:t(()=>[...$[22]||($[22]=[s("删除",-1)])]),_:1},8,["onClick"])]),_:1})]),_:1},8,["data"])]),_:1},8,["modelValue"]),e(Ve,{modelValue:h.value,"onUpdate:modelValue":$[11]||($[11]=ae=>h.value=ae)},{default:t(()=>[$[25]||($[25]=l("h2",null,"创建课程",-1)),e(re,{model:c},{default:t(()=>[e(oe,{label:"标题"},{default:t(()=>[e(xe,{modelValue:c.title,"onUpdate:modelValue":$[6]||($[6]=ae=>c.title=ae)},null,8,["modelValue"])]),_:1}),e(oe,{label:"描述"},{default:t(()=>[e(xe,{modelValue:c.description,"onUpdate:modelValue":$[7]||($[7]=ae=>c.description=ae),type:"textarea"},null,8,["modelValue"])]),_:1}),e(oe,{label:"课程形式"},{default:t(()=>[e(Z,{modelValue:c.mode,"onUpdate:modelValue":$[8]||($[8]=ae=>c.mode=ae),placeholder:"选择课程形式"},{default:t(()=>[e(W,{label:"私密课程",value:"private"}),e(W,{label:"公开课程",value:"public"})]),_:1},8,["modelValue"])]),_:1}),e(oe,{label:"价格(元)"},{default:t(()=>[e(Q,{modelValue:c.price,"onUpdate:modelValue":$[9]||($[9]=ae=>c.price=ae),min:0,step:10},null,8,["modelValue"])]),_:1}),c.mode=="private"?(n(),N(oe,{key:0,label:"每时段学生容量"},{default:t(()=>[e(Q,{modelValue:c.maxStudents,"onUpdate:modelValue":$[10]||($[10]=ae=>c.maxStudents=ae),min:1,"controls-position":"right"},null,8,["modelValue"])]),_:1})):te("",!0),e(oe,null,{default:t(()=>[e(X,{type:"primary",onClick:M},{default:t(()=>[...$[24]||($[24]=[s("创建课程",-1)])]),_:1})]),_:1})]),_:1},8,["model"])]),_:1},8,["modelValue"])],64)}}}),Br={key:0},Pr=ge({__name:"UpcomingCourse",setup(q){const c=d([]),w=d(!1),v=d(new Set),y=async()=>{w.value=!0;try{const r=await A.get("/api/teacher/upcoming-classes");c.value=r.data}catch(r){console.error("加载即将开课信息失败:",r),b.error("加载即将开课信息失败")}finally{w.value=!1}};function C(){try{el(c.value),b.success("日历文件导出成功")}catch(r){b.warning(r.message||"没有可导出的课程安排")}}function h(r,o){return`${de(o).hour()-de(r).hour()}h`}function u(r,o){return`${de(r).local().format("MM-DD HH:mm")} - ${de(o).local().format("HH:mm")}`}function f(r){return["周日","周一","周二","周三","周四","周五","周六"][de(r).day()]}function m(r){v.value.has(r)?v.value.delete(r):v.value.add(r)}function _(r){let o=!1;const g=de();return c.value.forEach(V=>{if(g.isAfter(V.timeslot_start)&&g.isBefore(V.timeslot_end)){o=!0;return}}),o||v.value.has(r)}function p(r){gt.push(`/note/${r}`)}return be(()=>{y()}),(r,o)=>{const g=a("el-button"),V=a("el-table-column"),z=a("el-icon"),M=a("el-tag"),L=a("el-table"),I=a("el-card"),O=Ee("loading");return n(),N(I,null,{header:t(()=>[...o[0]||(o[0]=[l("div",{class:"card-header"},[l("span",null,"即将开课")],-1)])]),default:t(()=>[e(g,{type:"primary",onClick:y},{default:t(()=>[...o[1]||(o[1]=[s("刷新",-1)])]),_:1}),e(g,{type:"primary",onClick:C},{default:t(()=>[...o[2]||(o[2]=[s("导出为日历",-1)])]),_:1}),Me((n(),k("div",null,[e(L,{data:c.value,style:{width:"100%"},stripe:""},{default:t(()=>[e(V,{prop:"time",label:"时间",width:"180"},{default:t(j=>[s(S(u(j.row.timeslot_start,j.row.timeslot_end)),1)]),_:1}),e(V,{prop:"date",label:"日期",width:"180"},{default:t(j=>[s(S(f(j.row.timeslot_start)),1)]),_:1}),e(V,{prop:"course_name",label:"课程名称",width:"200"}),e(V,{prop:"duration",label:"时长",width:"80"},{default:t(j=>[s(S(h(j.row.timeslot_start,j.row.timeslot_end)),1)]),_:1}),e(V,{prop:"student",label:"学生姓名"},{default:t(j=>[j.row.student_name?(n(),N(M,{key:0,"disable-transitions":!0,onClick:R=>m(j.row.student_name),class:Ye([{"name-hidden":!_(j.row.student_name)},"student-name-tag"])},{default:t(()=>[_(j.row.student_name)?(n(),k("span",Br,S(j.row.student_name),1)):(n(),N(z,{key:1,class:"hidden-icon"},{default:t(()=>[e(se(wl))]),_:1}))]),_:2},1032,["onClick","class"])):(n(),N(M,{key:1,type:"info"},{default:t(()=>[...o[3]||(o[3]=[s("暂无学生",-1)])]),_:1}))]),_:1}),e(V,{prop:"actions",label:"操作"},{default:t(j=>[j.row.note_id>
1260?(n(),N(g,{key:0,type:"primary",size:"small",onClick:R=>p(j.row.note_id)},{default:t(()=>[...o[4]||(o[4]=[s("查看",-1)])]),_:1},8,["onClick"])):(n(),N(Qt,{key:1,bookingId:j.row.book_id,showContent:!1,noteId:j.row.note_id,role:"teacher"},null,8,["bookingId","noteId"]))]),_:1})]),_:1},8,["data"])])),[[O,w.value]])]),_:1})}}}),Hr=ge({__name:"MyStudent",setup(q){const c=d([]),w=d(!1);async function v(){w.value=!0;try{const y=JSON.parse(sessionStorage.getItem("user")||"{}"),C=(y==null?void 0:y.id)||1,u=(await A.get(`/api/teachers/${C}/courses`)).data,f=new Map;for(const m of u){const p=(await A.get(`/api/courses/${m.id}/students`)).data;for(const r of p)try{const o=await A.get(`/api/teacher/students/${r.id}/hours`);f.set(r.id,{id:r.id,name:r.name,email:r.email,balance:o.data.balance})}catch(o){console.error(`获取学生 ${r.id} 的剩余课时失败:`,o),f.set(r.id,{id:r.id,name:r.name,email:r.email})}}c.value=Array.from(f.values())}catch(y){console.error("加载学生统计数据失败:",y),b.error("加载学生统计数据失败")}finally{w.value=!1}}return be(()=>{v()}),(y,C)=>{const h=a("el-table-column"),u=a("el-table"),f=a("el-card"),m=Ee("loading");return n(),N(f,null,{header:t(()=>[...C[0]||(C[0]=[l("div",{class:"card-header"},[l("span",null,"学生选课统计")],-1)])]),default:t(()=>[Me((n(),N(u,{data:c.value,style:{width:"100%"}},{default:t(()=>[e(h,{prop:"name",label:"学生姓名",width:"120"}),e(h,{prop:"email",label:"邮箱"}),e(h,{prop:"balance",label:"剩余费用",width:"120"})]),_:1},8,["data"])),[[m,w.value]])]),_:1})}}}),Or={key:0},qr={key:1},Nr={key:2},jr={key:3},Wr={key:4},Kr={class:"institutions-section"},Gr={key:0},Jr={key:0},Xr={key:1},Qr={class:"institution-content"},Zr={class:"institution-name"},ei={class:"institution-email"},ti={key:5},li={key:6},ai=ge({__name:"TeacherDashboard",setup(q){de.extend(pt),de.extend(xt);const c=d("upcoming"),w=d(!1),v=d(null),y=d(!1),C=d([]),h=d(!1);function u(){y.value=!y.value}const f=d([]),m=d([]),_=d();je(v,async H=>{const x=await A.get(`/api/teacher/courseBinding/${H}`);m.value=x.data});const p=async()=>{try{if(!_.value||!v.value){b.error("请选择学生进行绑定");return}await A.post(`/api/teacher/courses/${v.value}/bind-student/${_.value}`,{student_id:_.value}),b.success("学生绑定成功");const H=await A.get(`/api/teacher/courseBinding/${v.value}`);m.value=H.data}catch(H){console.error("绑定学生失败:",H),b.error("绑定学生失败")}},r=d([]),o=d(!0),g=d(!1),V=d(null),z=d([]);function M(H){c.value=H,H==="courses"&&f.value.length===0?O():H==="institutions"&&r.value.length===0?j():H==="upcoming"&&C.value.length===0&&I(),gt.replace({query:{...K.query,tab:H}})}const L=async function(){try{const H=await A.get("/api/admin/students");z.value=H.data}catch(H){console.error("加载学生列表失败:",H),b.error("加载学生列表失败")}};async function I(){h.value=!0;try{const H=await A.get("/api/teacher/upcoming-classes");C.value=H.data}catch(H){console.error("加载即将开课信息失败:",H),b.error("加载即将开课信息失败")}finally{h.value=!1}}async function O(){try{const H=JSON.parse(sessionStorage.getItem("user")||"{}"),x=(H==null?void 0:H.id)||1,B=await A.get(`/api/teachers/${x}/courses`);f.value=B.data,f.value.forEach(D=>{D.newRange=[],D.studentCount=D.students?D.students.length:0})}catch(H){console.error("加载课程失败:",H),b.error("加载课程失败")}}async function j(){o.value=!0;try{const H=await A.get("/api/teacher/institutions");r.value=H.data}catch(H){console.error("加载机构信息失败:",H),b.error("加载机构信息失败")}finally{o.value=!1}}function R(H){V.value=H,g.value=!0}const K=st();return be(()=>{K.query.tab&&(c.value=K.query.tab),I(),L(),K.query.tab==="institutions"&&j()}),(H,x)=>{const B=a("el-icon"),D=a("el-menu-item"),U=a("el-menu"),F=a("el-aside"),i=a("el-divider"),$=a("el-button"),X=a("el-card"),G=a("el-col"),E=a("el-row"),oe=a("el-main"),Q=a("el-form-item"),re=a("el-form"),me=a("el-dialog"),ie=a("el-option"),ce=a("el-select"),ke=a("el-table-column"),De=a("el-table"),ve=a("el-container");return n(),N(ve,{class:"teacher-dashboard"},{default:t(()=>[e(F,{class:Ye(["sidebar",{"mobile-hidden":!y.value}])},{default:t(()=>[e(U,{"default-active":c.value,class:"teacher-menu",onSelect:M},{default:t(()=>[e(D,{index:"upcoming"},{default:t(()=>[e(B,null,{default:t(()=>[e(se(ht))]),_:1}),x[5]||(x[5]=l("span",null,"即将开课",-1))]),_:1}),e(D,{index:"calendar"},{default:t(()=>[e(B,null,{default:t(()=>[e(se(ht))]),_:1}),x[6]||(x[6]=l("span",null,"我的日历",-1))]),_:1}),e(D,{index:"dashboard"},{default:t(()=>[e(B,null,{default:t(()=>[e(se(kl))]),_:1}),x[7]||(x[7]=l("span",null,"教师仪表板",-1))]),_:1}),e(D,{index:"courses"},{default:t(()=>[e(B,null,{default:t(()=>[e(se(Vt))]),_:1}),x[8]||(x[8]=l("span",null,"课程管理",-1))]),_:1}),e(D,{index:"myNote"},{default:t(()=>[e(B,null,{default:t(()=>[e(se(Ut))]),_:1}),x[9]||(x[9]=l("span",null,"我的笔记",-1))]),_:1}),e(D,{index:"dictionary"},{default:t(()=>[e(B,null,{default:t(()=>[e(se(Ut))]),_:1}
126),x[10]||(x[10]=l("span",null,"AI 字典",-1))]),_:1}),e(D,{index:"institutions"},{default:t(()=>[e(B,null,{default:t(()=>[e(se(Ut))]),_:1}),x[11]||(x[11]=l("span",null,"机构管理",-1))]),_:1})]),_:1},8,["default-active"])]),_:1},8,["class"]),l("div",{class:"menu-toggle",onClick:u},[e(B,null,{default:t(()=>[e(se(At))]),_:1})]),e(oe,{class:"main-content"},{default:t(()=>[c.value==="upcoming"?(n(),k("div",Or,[e(Pr)])):c.value==="calendar"?(n(),k("div",qr,[e(zt)])):c.value==="dashboard"?(n(),k("div",Nr,[e(Hr)])):c.value==="courses"?(n(),k("div",jr,[e(Fr)])):c.value==="institutions"?(n(),k("div",Wr,[e(X,null,{default:t(()=>[x[15]||(x[15]=l("h2",null,"加入机构",-1)),e(Ar,{onJoined:j}),e(i),l("div",Kr,[x[14]||(x[14]=l("h3",null,"我的机构",-1)),o.value?(n(),k("div",Gr,"加载中...")):(n(),N(E,{key:1,gutter:20},{default:t(()=>[e(G,{span:24},{default:t(()=>{var W;return[((W=r.value)==null?void 0:W.length)===0?(n(),k("div",Jr,[...x[12]||(x[12]=[l("p",null,"您尚未加入任何机构。",-1)])])):(n(),k("div",Xr,[e(E,{gutter:20,class:"institutions-grid"},{default:t(()=>[(n(!0),k(ue,null,fe(r.value,Z=>(n(),N(G,{span:8,xs:24,key:Z.id,class:"institution-item"},{default:t(()=>[e(X,null,{default:t(()=>[l("div",Qr,[l("div",null,[l("div",Zr,S(Z.name),1),l("div",ei,S(Z.email),1),e($,{size:"small",type:"primary",onClick:Ve=>R(Z)},{default:t(()=>[...x[13]||(x[13]=[s(" 查看详情 ",-1)])]),_:1},8,["onClick"])])])]),_:2},1024)]),_:2},1024))),128))]),_:1})]))]}),_:1})]),_:1}))])]),_:1})])):c.value==="dictionary"?(n(),k("div",ti,[e(yt)])):c.value==="myNote"?(n(),k("div",li,[e(Zt,{"owner-role":"teacher"})])):te("",!0)]),_:1}),V.value?(n(),N(me,{key:0,modelValue:g.value,"onUpdate:modelValue":x[1]||(x[1]=W=>g.value=W),title:"机构详情",width:"500px"},{footer:t(()=>[e($,{onClick:x[0]||(x[0]=W=>g.value=!1)},{default:t(()=>[...x[16]||(x[16]=[s("关闭",-1)])]),_:1})]),default:t(()=>[e(re,{"label-position":"top"},{default:t(()=>[e(Q,{label:"名称"},{default:t(()=>[l("span",null,S(V.value.name),1)]),_:1}),e(Q,{label:"邮箱"},{default:t(()=>[l("span",null,S(V.value.email),1)]),_:1}),e(Q,{label:"联系方式"},{default:t(()=>[l("span",null,S(V.value.phone||"未提供"),1)]),_:1}),e(Q,{label:"备注"},{default:t(()=>[l("span",null,S(V.value.remark||"无额外信息"),1)]),_:1})]),_:1})]),_:1},8,["modelValue"])):te("",!0),e(me,{title:"管理选课学生",modelValue:w.value,"onUpdate:modelValue":x[4]||(x[4]=W=>w.value=W),width:"60%"},{footer:t(()=>[e($,{onClick:x[3]||(x[3]=W=>w.value=!1)},{default:t(()=>[...x[18]||(x[18]=[s("关闭",-1)])]),_:1})]),default:t(()=>[e(ce,{modelValue:_.value,"onUpdate:modelValue":x[2]||(x[2]=W=>_.value=W),placeholder:"请选添加的学生"},{default:t(()=>[(n(!0),k(ue,null,fe(z.value,W=>(n(),N(ie,{key:W.id,label:W.name,value:W.id},null,8,["label","value"]))),128))]),_:1},8,["modelValue"]),e($,{type:"primary",onClick:p},{default:t(()=>[...x[17]||(x[17]=[s("添加",-1)])]),_:1}),e(De,{data:m.value,style:{width:"100%"}},{default:t(()=>[e(ke,{prop:"name",label:"学生姓名",width:"150"}),e(ke,{prop:"email",label:"邮箱"})]),_:1},8,["data"])]),_:1},8,["modelValue"])]),_:1})}}}),oi=Ce(ai,[["__scopeId","data-v-1d1d51a0"]]),ni=ge({__name:"AdminDashboard",setup(q){const c=Ie(),w=st(),v=d(h(w)),y=d(!1);be(()=>{C(),window.addEventListener("resize",C)});function C(){y.value=window.innerWidth>768}function h(m){return m.path.startsWith("/admin/users")?"users":m.path.startsWith("/admin/students")?"students":m.path.startsWith("/admin/hour_records")?"hour_records":m.path.startsWith("/admin/courses")?"courses":m.path.startsWith("/admin/stats")?"stats":m.path.startsWith("/admin/mistake_browser")?"mistake_browser":m.path.startsWith("/admin/google_analytics")?"google_analytics":m.path.startsWith("/admin/advertisements")?"advertisements":m.path.startsWith("/admin/meta_tags")?"meta_tags":m.path.startsWith("/admin/vocabulary")?"vocabulary":m.path.startsWith("/admin/mcp-servers")?"mcp-servers":m.path.startsWith("/admin/system")?"system":"users"}je(w,()=>{v.value=h(w),window.innerWidth<=768&&(y.value=!1)});function u(m){m==="users"?c.push("/admin/users"):m==="students"?c.push("/admin/students"):m==="hour_records"?c.push("/admin/hour_records"):m==="courses"?c.push("/admin/courses"):m==="stats"?c.push("/admin/stats"):m==="mistake_browser"?c.push("/admin/mistake_browser"):m==="google_analytics"?c.push("/admin/google_analytics"):m==="advertisements"?c.push("/admin/advertisements"):m==="meta_tags"?c.push("/admin/meta_tags"):m==="vocabulary"?c.push("/admin/vocabulary"):m==="mcp-servers"?c.push("/admin/mcp-servers"):m==="system"&&c.push("/admin/system"),window.innerWidth<=768&&(y.value=!1)}function f(){y.value=!y.value}return ct(()=>{window.removeEventListener("resize",C)}),(m,_)=>{const p=a("el-icon"),r=a("el-menu-item"),o=a("el-menu"),g=a("el-aside"),V=a("router-view"),z=
126a("el-main"),M=a("el-container");return n(),N(M,{class:"admin-container"},{default:t(()=>[e(g,{class:Ye(["sidebar",{"mobile-hidden":!y.value}]),width:"200px"},{default:t(()=>[e(o,{"default-active":v.value,onSelect:u},{default:t(()=>[e(r,{index:"users"},{default:t(()=>[e(p,null,{default:t(()=>[e(se(_t))]),_:1}),_[0]||(_[0]=l("span",null,"用户管理",-1))]),_:1}),e(r,{index:"students"},{default:t(()=>[e(p,null,{default:t(()=>[e(se(Nt))]),_:1}),_[1]||(_[1]=l("span",null,"学生管理",-1))]),_:1}),e(r,{index:"hour_records"},{default:t(()=>[e(p,null,{default:t(()=>[e(se(Kt))]),_:1}),_[2]||(_[2]=l("span",null,"缴费统计",-1))]),_:1}),e(r,{index:"courses"},{default:t(()=>[e(p,null,{default:t(()=>[e(se(Vt))]),_:1}),_[3]||(_[3]=l("span",null,"选课管理",-1))]),_:1}),e(r,{index:"stats"},{default:t(()=>[e(p,null,{default:t(()=>[e(se(Ft))]),_:1}),_[4]||(_[4]=l("span",null,"学生统计",-1))]),_:1}),e(r,{index:"mistake_browser"},{default:t(()=>[e(p,null,{default:t(()=>[e(se(Ft))]),_:1}),_[5]||(_[5]=l("span",null,"错题浏览",-1))]),_:1}),e(r,{index:"google_analytics"},{default:t(()=>[e(p,null,{default:t(()=>[e(se(hl))]),_:1}),_[6]||(_[6]=l("span",null,"Google Analytics",-1))]),_:1}),e(r,{index:"advertisements"},{default:t(()=>[e(p,null,{default:t(()=>[e(se($l))]),_:1}),_[7]||(_[7]=l("span",null,"广告管理",-1))]),_:1}),e(r,{index:"vocabulary"},{default:t(()=>[e(p,null,{default:t(()=>[e(se(Gt))]),_:1}),_[8]||(_[8]=l("span",null,"词汇管理",-1))]),_:1}),e(r,{index:"mcp-servers"},{default:t(()=>[e(p,null,{default:t(()=>[e(se(Vl))]),_:1}),_[9]||(_[9]=l("span",null,"MCP服务器",-1))]),_:1}),e(r,{index:"meta_tags"},{default:t(()=>[e(p,null,{default:t(()=>[e(se(Cl))]),_:1}),_[10]||(_[10]=l("span",null,"Meta标签",-1))]),_:1}),e(r,{index:"system"},{default:t(()=>[e(p,null,{default:t(()=>[e(se(jt))]),_:1}),_[11]||(_[11]=l("span",null,"系统维护",-1))]),_:1})]),_:1},8,["default-active"])]),_:1},8,["class"]),l("div",{class:"menu-toggle",onClick:f},[e(p,null,{default:t(()=>[e(se(At))]),_:1})]),e(M,{class:"main-container"},{default:t(()=>[e(z,{class:"main-content"},{default:t(()=>[e(V)]),_:1})]),_:1})]),_:1})}}}),si=Ce(ni,[["__scopeId","data-v-a068a4d1"]]),ri={key:0,class:"pagination-container"},ii=ge({__name:"AdminUsers",setup(q){const c=d({name:"",email:"",phone:"",city:"",region:"",remark:"",password:"",role:"student"}),w=Ie(),v=d({page:1});async function y(){const p=await A.get("/api/admin/users",{params:{page:v.value.page,page_size:v.value.page_size}});v.value=p.data}const C=async function(p){v.value.page=p,y()},h=p=>{v.value.page_size=p,y()};be(y);function u(p){w.push(`/admin/users/${p}`)}async function f(){try{await A.post("/api/admin/users",c.value),c.value={name:"",email:"",phone:"",city:"",region:"",remark:"",password:"",role:"student"},await y(),b.success("用户创建成功")}catch{b.error("用户创建失败")}}async function m(p){try{await A.delete(`/api/admin/users/${p}`),await y(),b.success("用户删除成功")}catch{b.error("用户删除失败")}}async function _(p){const r=prompt("输入新密码");if(r)try{await A.post(`/api/admin/users/${p}/reset`,{password:r}),b.success("密码已重置")}catch{b.error("密码重置失败")}}return(p,r)=>{const o=a("el-input"),g=a("el-form-item"),V=a("el-option"),z=a("el-select"),M=a("el-button"),L=a("el-form"),I=a("el-card"),O=a("el-col"),j=a("el-table-column"),R=a("el-table"),K=a("el-pagination"),H=a("el-row");return n(),N(H,{gutter:20},{default:t(()=>[e(O,{span:6,xs:0},{default:t(()=>[e(I,null,{default:t(()=>[r[9]||(r[9]=l("h3",null,"添加用户",-1)),e(L,{model:c.value,"label-width":"auto"},{default:t(()=>[e(g,{label:"Name"},{default:t(()=>[e(o,{modelValue:c.value.name,"onUpdate:modelValue":r[0]||(r[0]=x=>c.value.name=x)},null,8,["modelValue"])]),_:1}),e(g,{label:"Email"},{default:t(()=>[e(o,{modelValue:c.value.email,"onUpdate:modelValue":r[1]||(r[1]=x=>c.value.email=x)},null,8,["modelValue"])]),_:1}),e(g,{label:"Phone"},{default:t(()=>[e(o,{modelValue:c.value.phone,"onUpdate:modelValue":r[2]||(r[2]=x=>c.value.phone=x)},null,8,["modelValue"])]),_:1}),e(g,{label:"City"},{default:t(()=>[e(o,{modelValue:c.value.city,"onUpdate:modelValue":r[3]||(r[3]=x=>c.value.city=x)},null,8,["modelValue"])]),_:1}),e(g,{label:"Region"},{default:t(()=>[e(o,{modelValue:c.value.region,"onUpdate:modelValue":r[4]||(r[4]=x=>c.value.region=x)},null,8,["modelValue"])]),_:1}),e(g,{label:"Remark"},{default:t(()=>[e(o,{modelValue:c.value.remark,"onUpdate:modelValue":r[5]||(r[5]=x=>c.value.remark=x),type:"textarea"},null,8,["modelValue"])]),_:1}),e(g,{label:"Password"},{default:t(()=>[e(o,{type:"password",modelValue:c.value.password,"onUpdate:modelValue":r[6]||(r[6]=x=>c.value.password=x)},null,8,["modelValue"])]),_:1}),e(g,{label:"Role"},{default:t(()=>[e(z,{modelValue:c.value.role,"onUpdate:modelValue":r[7]||(r[7]=x=>c.value.role=x)},{default:t(()=>[e(V,{label:"Admin",value:"admin"}),e(V,{label:"Teacher",value:"teacher"}),e(V,{label:"Student",value:"student"}),e(V,{label:"Institution",value:"institution"})]),_:1},8,["modelValue"])]),_:1}),e(g,null,{default:t(()=>[e(M,{type:"primary",onClick:f},{default:t(()=>[...r[8]||(r[8]=[s("创建",-1)])]),_:1})]),_:1})]),_:1},8,["model"])]),_:1})]),_:1}),e(O,{span:18,xs:24},{default:t(()=>[e(I,null,{default:t(()=>[r[13]||(r[13]=l("h3",null,"用户列表",-1)),e(R,{data:v.value?v.value.data:[],style:{width:"100%"}},{default:t(()=>[e(j,{prop:"id",label:"#",width:"60"}),e(j,{prop:"name",label:"Name"}),e(j,{prop:"email",label:"Email"}),e(j,{prop:"role",label:"Role"}),e(j,{label:"Actions"},{default:t(({row:x})=>[e(M,{size:"small",onClick:B=>u(x.id)},{default:t(()=>[...r[10]||(r[10]=[s("查看详情",-1)])]),_:1},8,["onClick"]),e(M,{size:"small",type:"danger",onClick:B=>m(x.id)},{default:t(()=>[...r[11]||(r[11]=[s("删除",-1)])]),_:1},8,["onClick"]),e(M,{size:"small",onClick:B=>_(x.id)},{default:t(()=>[...r[12]||(r[12]=[s("重置密码",-1)])]),_:1},8,["onClick"])]),_:1})]),_:1},8,["data"]),v.value&&v.value.total>v.value.page_size?(n(),k("div",ri,[e(K,{onCurrentChange:C,onSizeChange:h,"current-page":v.value.page,"page-size":v.value.page_size,total:v.value.total,"page-sizes":[10,20,50,100],layout:"total, sizes, prev, pager, next, jumper"},null,8,["current-page","page-size","total"])])):te("",!0)]),_:1})]),_:1})]),_:1})}}}),ui={key:0},di={key:1},ci=ge({__name:"AdminUsersDetail",setup(q){const c=st(),w=Ie(),v=d(null),y=Ae({city:"",region:""});be(async()=>{const f=c.params.id;if(!f){w.push("/admin/users");return}try{const m=await A.get(`/api/admin/users/${f}`);v.value=m.data,y.city=v.value.city||"",y.region=v.value.region||""}catch(m){console.error("获取用户信息失败:",m),b.error("获取用户信息失败"),w.push("/admin/users")}});function C(){w.go(-1)}function h(f){return f?f.toFixed(2):"0.00"}async function u(){try{const f=await A.post(`/api/admin/users/${v.value.id}/location`,{city:y.city,region:y.region});v.value=f.data,b.success("位置信息更新成功")}catch{b.error("位置信息更新失败")}}return(f,m)=>{const _=a("el-page-header"),p=a("el-descriptions-item"),r=a("el-descriptions"),o=a("el-input"),g=a("el-form-item"),V=a("el-button"),z=a("el-form"),M=a("el-card"),L=a("el-container");return n(),N(L,{style:{padding:"20px","max-width":"800px",margin:"auto"}},{default:t(()=>[e(M,null,{default:t(()=>[e(_,{onBack:C,content:"用户详情",style:{"margin-bottom":"20px"}}),v.value?(n(),k("div",ui,[e(r,{title:"用户信息",column:1,border:""},{default:t(()=>[e(p,{label:"ID"},{default:t(()=>[s(S(v.value.id),1)]),_:1}),e(p,{label:"姓名"},{default:t(()=>[s(S(v.value.name),1)]),_:1}),e(p,{label:"邮箱"},{default:t(()=>[s(S(v.value.email),1)]),_:1}),e(p,{label:"手机号"},{default:t(()=>[s(S(v.value.phone||"未填写"),1)]),_:1}),e(p,{label:"城市"},{default:t(()=>[s(S(v.value.city||"未填写"),1)]),_:1}),e(p,{label:"区域"},{default:t(()=>[s(S(v.value.region||"未填写"),1)]),_:1}),e(p,{label:"备注"},{default:t(()=>[s(S(v.value.remark||"无"),1)]),_:1}),e(p,{label:"角色"},{default:t(()=>[s(S(v.value.role),1)]),_:1}),e(p,{label:"余额"},{default:t(()=>[s(S(h(v.value.balance))+" 元",1)]),_:1})]),_:1}),e(M,{style:{"margin-top":"20px"}},{header:t(()=>[...m[2]||(m[2]=[l("div",{class:"card-header"},[l("span",null,"编辑位置信息")],-1)])]),default:t(()=>[e(z,{model:y,"label-width":"120px",onSubmit:Oe(u,["prevent"])},{default:t(()=>[e(g,{label:"城市"},{default:t(()=>[e(o,{modelValue:y.city,"onUpdate:modelValue":m[0]||(m[0]=I=>y.city=I),placeholder:"请输入城市"},null,8,["modelValue"])]),_:1}),e(g,{label:"区域"},{default:t(()=>[e(o,{modelValue:y.region,"onUpdate:modelValue":m[1]||(m[1]=I=>y.region=I),placeholder:"请输入区域"},null,8,["modelValue"])]),_:1}),e(g,null,{default:t(()=>[e(V,{type:"primary",onClick:u},{default:t(()=>[...m[3]||(m[3]=[s("更新位置信息",-1)])]),_:1})]),_:1})]),_:1},8,["model"])]),_:1})])):(n(),k("div",di,[...m[4]||(m[4]=[l("p",null,"加载中...",-1)])]))]),_:1})]),_:1})}}}),pi=ge({__name:"AdminCourses",setup(q){const c=d(!1),w=d(!1),v=d({page:1,page_size:10,total:0,data:[]}),y=d(),C=d([{label:"预约ID",prop:"booking.id"},{label:"课程名称",prop:"course.title"},{label:"教师",prop:"teacher.name"},{label:"学生",prop:"student.name",searchable:!0,searchKey:"student_name"},{label:"开始时间",prop:"timeslot.start",searchable:!0,searchKind:"date",searchKey:"start_time",formatter:M},{label:"结束时间",prop:"timeslot.end",searchable:!0,searchKind:"date",searchKey:"end_time",formatter:M},{label:"时长(小时)",prop:"duration",kind:"slot"}]),h=Ae({studentName:"",startTime:"",endTime:""});be(async()=>{await u()}),je(w,L=>{L&&(m(),p())});async function u(){try{c.value=!0;const L={page:v.value.page,page_size:v.value.page_size};h.studentName&&(L.student_name=encodeURIComponent(h.studentName)),h.startTime&&(L.start_time=h.startTime),h.endTime&&(L.end_time=h.endTime);const I=await A.get("/api/admin/bookings",{params:L});
126v.value=I.data}catch(L){console.error("Failed to load bookings:",L)}finally{c.value=!1}}const f=d([]),m=async()=>{try{const L=await A.get("/api/admin/students",{params:{page_disabled:"1"}});f.value=L.data}catch(L){console.error("Failed to load students:",L)}},_=d([]),p=async()=>{try{const L=await A.get("/api/admin/courses");_.value=L.data}catch(L){console.error("Failed to load courses:",L)}},r=d(null),o=d(null),g=d(null),V=d(1),z=async()=>{try{if(!r.value||!o.value||!g.value||!V.value){b.error("请填写完整信息");return}(await A.post("/api/admin/missingBooking",{course_id:r.value,student_id:o.value,start_time:g.value,hours:Number(V.value)})).status===201&&b.success("创建成功"),w.value=!1,await u(),await y.value.loadData()}catch{b.error("创建失败")}};function M(L,I,O){return de(O).local().format("YYYY-MM-DD HH:mm")}return(L,I)=>{const O=a("el-button"),j=a("el-option"),R=a("el-select"),K=a("el-form-item"),H=a("el-date-picker"),x=a("el-input"),B=a("el-form"),D=a("el-dialog");return n(),k(ue,null,[l("div",null,[I[7]||(I[7]=l("h3",null,"所有预约记录",-1)),e(mt,{dataURL:"/api/admin/bookings",columns:C.value,ref_key:"bookingTableRef",ref:y},{"button-tail":t(()=>[e(O,{type:"primary",onClick:I[0]||(I[0]=U=>w.value=!0)},{default:t(()=>[...I[6]||(I[6]=[s("补录",-1)])]),_:1})]),_:1},8,["columns"])]),e(D,{title:"补录",modelValue:w.value,"onUpdate:modelValue":I[5]||(I[5]=U=>w.value=U)},{default:t(()=>[e(B,{"label-width":"auto"},{default:t(()=>[e(K,{label:"课程"},{default:t(()=>[e(R,{modelValue:r.value,"onUpdate:modelValue":I[1]||(I[1]=U=>r.value=U),placeholder:"请选择课程"},{default:t(()=>[(n(!0),k(ue,null,fe(_.value,U=>(n(),N(j,{key:U.id,value:U.id,label:U.title},null,8,["value","label"]))),128))]),_:1},8,["modelValue"])]),_:1}),e(K,{label:"学生"},{default:t(()=>[e(R,{modelValue:o.value,"onUpdate:modelValue":I[2]||(I[2]=U=>o.value=U),placeholder:"请选择学生"},{default:t(()=>[(n(!0),k(ue,null,fe(f.value,U=>(n(),N(j,{key:U.id,value:U.id,label:U.name},null,8,["value","label"]))),128))]),_:1},8,["modelValue"])]),_:1}),e(K,{label:"开始时间"},{default:t(()=>[e(H,{modelValue:g.value,"onUpdate:modelValue":I[3]||(I[3]=U=>g.value=U),type:"datetime",placeholder:"选择时间"},null,8,["modelValue"])]),_:1}),e(K,{label:"时长"},{default:t(()=>[e(x,{modelValue:V.value,"onUpdate:modelValue":I[4]||(I[4]=U=>V.value=U),placeholder:"请输入时长",type:"number",min:1},null,8,["modelValue"])]),_:1}),e(K,null,{default:t(()=>[e(O,{type:"primary",onClick:z},{default:t(()=>[...I[8]||(I[8]=[s("创建",-1)])]),_:1})]),_:1})]),_:1})]),_:1},8,["modelValue"])],64)}}}),mi=ge({__name:"AdminStudentStats",setup(q){const c=d(null);let w=null;const v=d([]);async function y(){try{const u=await A.get("/api/admin/students",{params:{page_disabled:"1"}});v.value=u.data,h()}catch(u){console.error("获取学生数据失败:",u)}}function C(){c.value&&(w=ut(c.value),h())}function h(){if(!w)return;const u={title:{text:"学生余额统计"},tooltip:{trigger:"axis",axisPointer:{type:"shadow"}},grid:{left:"3%",right:"4%",bottom:"3%",containLabel:!0},xAxis:[{type:"category",data:v.value.map(f=>f.name),axisTick:{alignWithLabel:!0}}],yAxis:[{type:"value",name:"余额"}],series:[{name:"余额",type:"bar",barWidth:"60%",data:v.value.map(f=>f.balance||0),itemStyle:{color:new Ht(0,0,0,1,[{offset:0,color:"#83bff6"},{offset:.5,color:"#188df0"},{offset:1,color:"#188df0"}])},emphasis:{itemStyle:{color:new Ht(0,0,0,1,[{offset:0,color:"#2378f7"},{offset:.7,color:"#2378f7"},{offset:1,color:"#83bff6"}])}}}]};w.setOption(u)}return be(()=>{C(),y()}),window.addEventListener("resize",()=>{w&&w.resize()}),(u,f)=>{const m=a("el-card");return n(),N(m,null,{default:t(()=>[l("div",{ref_key:"chartContainer",ref:c,style:{width:"100%",height:"500px"}},null,512)]),_:1})}}}),vi={key:0,class:"pagination-container"},fi=ge({__name:"AdminStudentManagement",setup(q){const c=d({page:1}),w=d(!0),v=Ie(),y=d({sourceInviteCode:""});be(async()=>{await u()});const C=async()=>{await u()},h=()=>{y.value.sourceInviteCode="",u()};async function u(){try{w.value=!0;const M={page:c.value.page,page_size:c.value.page_size};y.value.sourceInviteCode&&(M.source_invite_code=y.value.sourceInviteCode);const L=await A.get("/api/admin/students",{params:M});c.value=L.data}
126catch(M){b.error("加载学生数据失败"),console.error(M)}finally{w.value=!1}}const f=async function(M){c.value.page=M,u()},m=M=>{c.value.page_size=M,u()};function _(M){return new Date(M).toLocaleString("zh-CN")}function p(M){v.push(`/admin/users/${M.id}`)}const r=d(),o=d({amount:100,remarks:"",paymentType:"regular"}),g=async()=>{try{const M={amount:Number(o.value.amount),remarks:o.value.remarks,payment_type:o.value.paymentType};if((await A.post(`/api/admin/users/${r.value.id}/pay`,M)).status!==200)throw new Error("缴费失败");b.success("缴费成功"),V.value=!1,await u()}catch(M){b.error("缴费失败"),console.error(M)}},V=d(!1),z=M=>{V.value=!0,r.value=M,o.value.paymentType="regular"};return(M,L)=>{const I=a("el-input"),O=a("el-form-item"),j=a("el-button"),R=a("el-form"),K=a("el-card"),H=a("el-table-column"),x=a("el-dropdown-item"),B=a("el-dropdown-menu"),D=a("el-dropdown"),U=a("el-table"),F=a("el-pagination"),i=a("el-option"),$=a("el-select"),X=a("el-dialog"),G=Ee("loading");return n(),k(ue,null,[l("div",null,[L[11]||(L[11]=l("h2",null,"学生管理",-1)),e(K,{class:"search-card"},{default:t(()=>[e(R,{model:y.value,inline:!0,onSubmit:Oe(C,["prevent"])},{default:t(()=>[e(O,{label:"注册邀请码"},{default:t(()=>[e(I,{modelValue:y.value.sourceInviteCode,"onUpdate:modelValue":L[0]||(L[0]=E=>y.value.sourceInviteCode=E),placeholder:"请输入注册邀请码",clearable:""},null,8,["modelValue"])]),_:1}),e(O,null,{default:t(()=>[e(j,{type:"primary",onClick:C},{default:t(()=>[...L[7]||(L[7]=[s("搜索",-1)])]),_:1}),e(j,{onClick:h},{default:t(()=>[...L[8]||(L[8]=[s("重置",-1)])]),_:1})]),_:1})]),_:1},8,["model"])]),_:1}),Me((n(),N(U,{data:c.value.data,style:{width:"100%"}},{default:t(()=>[e(H,{prop:"id",label:"ID",width:"80"}),e(H,{prop:"name",label:"姓名",width:"120"}),e(H,{prop:"email",label:"邮箱"}),e(H,{prop:"balance",label:"余额(元)",width:"120"}),e(H,{prop:"phone",label:"手机号",width:"120"}),e(H,{prop:"city",label:"城市",width:"100"}),e(H,{prop:"region",label:"区域",width:"100"}),e(H,{prop:"remark",label:"备注"}),e(H,{prop:"invite_code",label:"邀请码",width:"120"}),e(H,{prop:"source_invite_code",label:"注册邀请码",width:"120"}),e(H,{prop:"created_at",label:"创建时间",width:"180"},{default:t(E=>[s(S(_(E.row.created_at)),1)]),_:1}),e(H,{label:"操作",width:"220"},{default:t(E=>[e(D,{"split-button":"",type:"primary",onClick:oe=>p(E.row)},{dropdown:t(()=>[e(B,null,{default:t(()=>[e(x,{onClick:oe=>z(E.row)},{default:t(()=>[...L[9]||(L[9]=[s("缴费",-1)])]),_:1},8,["onClick"])]),_:2},1024)]),default:t(()=>[L[10]||(L[10]=s(" 查看详情 ",-1))]),_:2},1032,["onClick"])]),_:1})]),_:1},8,["data"])),[[G,w.value]]),c.value&&c.value.total>c.value.page_size?(n(),k("div",vi,[e(F,{onCurrentChange:f,onSizeChange:m,"current-page":c.value.page,"page-size":c.value.page_size,total:c.value.total,"page-sizes":[10,20,50,100],layout:"total, sizes, prev, pager, next, jumper"},null,8,["current-page","page-size","total"])])):te("",!0)]),e(X,{title:"缴费",modelValue:V.value,"onUpdate:modelValue":L[6]||(L[6]=E=>V.value=E)},{footer:t(()=>[e(j,{type:"primary",onClick:L[5]||(L[5]=E=>V.value=!1)},{default:t(()=>[...L[12]||(L[12]=[s("取消",-1)])]),_:1}),e(j,{type:"primary",onClick:g},{default:t(()=>[...L[13]||(L[13]=[s("确认缴费",-1)])]),_:1})]),default:t(()=>[e(R,{"label-width":"120px"},{default:t(()=>[e(O,{label:"学生姓名",prop:"id"},{default:t(()=>[e(I,{modelValue:r.value.name,"onUpdate:modelValue":L[1]||(L[1]=E=>r.value.name=E),readonly:""},null,8,["modelValue"])]),_:1})]),_:1}),e(R,{"label-width":"120px"},{default:t(()=>[e(O,{label:"缴费金额",prop:"amount"},{default:t(()=>[e(I,{modelValue:o.value.amount,"onUpdate:modelValue":L[2]||(L[2]=E=>o.value.amount=E),type:"number",placeholder:"请输入缴费金额"},null,8,["modelValue"])]),_:1})]),_:1}),e(R,{"label-width":"120px"},{default:t(()=>[e(O,{label:"缴费类型",prop:"paymentType"},{default:t(()=>[e($,{modelValue:o.value.paymentType,"onUpdate:modelValue":L[3]||(L[3]=E=>o.value.paymentType=E),placeholder:"请选择缴费类型"},{default:t(()=>[e(i,{label:"正常缴费",value:"regular"}),e(i,{label:"赠送金额",value:"gifted"})]),_:1},8,["modelValue"])]),_:1})]),_:1}),e(R,{"label-width":"120px"},{default:t(()=>[e(O,{label:"备注",prop:"created_at"},{default:t(()=>[e(I,{modelValue:o.value.remarks,"onUpdate:modelValue":L[4]||(L[4]=E=>o.value.remarks=E),type:"text",placeholder:"请输入备注"},null,8,["modelValue"])]),_:1})]),_:1})]),_:1},8,["modelValue"])],64)}}}),_i={class:"card-header"},yi={style:{float:"right"}},gi=ge({__name:"AdminHourRecordStats",setup(q){const c=d(null);let w=null;const v=d([]),y=d(!1),C=d("student");function h(p){return de(p).format("YYYY-MM-DD HH:mm")}async function u(){try{y.value=!0;const p=await A.get("/api/admin/all-payment-records");v.value=p.data||[],await dt(),f()}catch(p){console.error("获取课时记录失败:",p)}finally{y.value=!1}}function f(){c.value&&(w&&w.dispose(),w=ut(c.value),C.value==="student"?m():_(),window.addEventListener("resize",()=>{w==null||w.resize()}))}function m(){const p={};v.value.forEach(V=>{const z=V.student_name||"未知学生";p[z]||(p[z]={name:z,regularAmount:0,giftedAmount:0,totalAmount:0}),V.payment_type==="regular"||V.payment_type===""?p[z].regularAmount+=V.amount:V.payment_type==="gifted"&&(p[z].giftedAmount+=V.amount),p[z].totalAmount=p[z].regularAmount+p[z].giftedAmount});const r=Object.keys(p).map(V=>p[V].name),o=Object.keys(p).map(V=>p[V].totalAmount),g={tooltip:{trigger:"axis",axisPointer:{type:"shadow"},formatter:function(V){const z=V[0],M=p[z.name];return`${z.name}<br/>
127                总金额: ${M.totalAmount.toFixed(2)}<br/>
128                正常缴费: ${M.regularAmount.toFixed(2)}<br/>
129                赠送金额: ${M.giftedAmount.toFixed(2)}`}},xAxis:{type:"category",data:r},yAxis:{type:"value",name:"总金额"},series:[{data:o,type:"bar",itemStyle:{color:"#409EFF"}}]};w.setOption(g)}function _(){const p={};v.value.filter(I=>I.payment_type==="regular"||I.payment_type==="").forEach(I=>{const O=de(I.created_at).format("YYYY-MM");p[O]||(p[O]={month:O,regularAmount:0,cumulativeAmount:0}),p[O].regularAmount+=I.amount});const o=Object.keys(p).map(I=>p[I]).sort((I,O)=>I.month.localeCompare(O.month));let g=0;o.forEach(I=>{g+=I.regularAmount,I.cumulativeAmount=g});const V=o.map(I=>I.month),z=o.map(I=>I.regularAmount),M=o.map(I=>I.cumulativeAmount),L={tooltip:{trigger:"axis",axisPointer:{type:"shadow"}},legend:{data:["正常缴费金额","累计总额"]},xAxis:{type:"category",data:V},yAxis:{type:"value",name:"金额"},series:[{name:"正常缴费金额",data:z,type:"bar",itemStyle:{color:"#409EFF"}},{name:"累计总额",data:M,type:"line",smooth:!0,itemStyle:{color:"#67C23A"}}]};w.setOption(L)}return be(()=>{u()}),(p,r)=>{const o=a("el-radio-button"),g=a("el-radio-group"),V=a("el-table-column"),z=a("el-tag"),M=a("el-table"),L=a("el-card"),I=Ee("loading");return n(),k("div",null,[e(L,null,{header:t(()=>[l("div",_i,[r[3]||(r[3]=l("span",null,"缴费统计",-1)),l("div",yi,[e(g,{modelValue:C.value,"onUpdate:modelValue":r[0]||(r[0]=O=>C.value=O),onChange:f},{default:t(()=>[e(o,{label:"student"},{default:t(()=>[...r[1]||(r[1]=[s("按学生统计",-1)])]),_:1}),e(o,{label:"monthly"},{default:t(()=>[...r[2]||(r[2]=[s("按月统计",-1)])]),_:1})]),_:1},8,["modelValue"])])])]),default:t(()=>[l("div",{ref_key:"chartContainer",ref:c,style:{width:"100%",height:"400px"}},null,512),Me((n(),N(M,{data:v.value,style:{width:"100%"}},{default:t(()=>[e(V,{prop:"student_name",label:"学生姓名",width:"120"}),e(V,{prop:"created_at",label:"时间",width:"180",formatter:O=>h(O.created_at)},null,8,["formatter"]),e(V,{prop:"amount",label:"金额",width:"100"},{default:t(({row:O})=>[l("span",{class:Ye(O.amount>0?"positive":"negative")},S(O.amount>0?"+":"")+S(O.amount),3)]),_:1}),e(V,{prop:"payment_type",label:"缴费类型",width:"120"},{default:t(({row:O})=>[e(z,{type:O.payment_type==="regular"?"primary":"success"},{default:t(()=>[s(S(O.payment_type==="regular"?"正常缴费":"赠送金额"),1)]),_:2},1032,["type"])]),_:1}),e(V,{prop:"remarks",label:"备注"}),e(V,{prop:"admin_id",label:"操作员ID",width:"100"})]),_:1},8,["data"])),[[I,y.value]])]),_:1})])}}}),bi=Ce(gi,[["__scopeId","data-v-5226b420"]]),wi={key:0,class:"current-config"},ki=ge({__name:"AdminGoogleAnalytics",setup(q){const c=Ae({measurementId:""}),w=Ae({id:0,measurement_id:"",created_at:"",updated_at:""}),v=d(!1);be(()=>{y()});async function y(){try{const u=await A.get("/api/admin/google-analytics");Object.assign(w,u.data),c.measurementId=u.data.measurement_id||""}catch(u){console.error("加载配置失败:",u),b.error("加载配置失败")}}async function C(){if(!c.measurementId.trim()){b.warning("请输入 Measurement ID");return}v.value=!0;try{const u=await A.post("/api/admin/google-analytics",{measurement_id:c.measurementId});Object.assign(w,u.data),b.success("配置已保存")}catch(u){console.error("保存配置失败:",u),b.error("保存配置失败")}finally{v.value=!1}}
129function h(u){return u?new Date(u).toLocaleString("zh-CN"):""}return(u,f)=>{const m=a("el-input"),_=a("el-form-item"),p=a("el-button"),r=a("el-form"),o=a("el-card");return n(),N(o,{class:"ga-config-card"},{header:t(()=>[...f[1]||(f[1]=[l("div",{class:"card-header"},[l("span",null,"Google Analytics 配置")],-1)])]),default:t(()=>[e(r,{model:c,"label-width":"120px"},{default:t(()=>[e(_,{label:"Measurement ID"},{default:t(()=>[e(m,{modelValue:c.measurementId,"onUpdate:modelValue":f[0]||(f[0]=g=>c.measurementId=g),placeholder:"例如: G-XXXXXXXXXX",clearable:""},null,8,["modelValue"]),f[2]||(f[2]=l("div",{class:"help-text"},' 在 Google Analytics 4 中找到您的 Measurement ID。通常以 "G-" 开头。 ',-1))]),_:1}),e(_,null,{default:t(()=>[e(p,{type:"primary",onClick:C,loading:v.value},{default:t(()=>[...f[3]||(f[3]=[s(" 保存配置 ",-1)])]),_:1},8,["loading"]),e(p,{onClick:y},{default:t(()=>[...f[4]||(f[4]=[s("刷新",-1)])]),_:1})]),_:1})]),_:1},8,["model"]),w.measurement_id?(n(),k("div",wi,[f[7]||(f[7]=l("h4",null,"当前配置:",-1)),l("p",null,[f[5]||(f[5]=l("strong",null,"Measurement ID:",-1)),s(" "+S(w.measurement_id),1)]),l("p",null,[f[6]||(f[6]=l("strong",null,"更新时间:",-1)),s(" "+S(h(w.updated_at)),1)])])):te("",!0)]),_:1})}}}),hi=Ce(ki,[["__scopeId","data-v-ba72ae67"]]),$i={class:"card-header"},Vi={key:0,class:"no-data"},Ci=ge({__name:"AdvertisementManagement",setup(q){const c=d([]),w=d(!1),v=d(!1),y=d(null),C=d({title:"",content:"",image_url:"",link_url:"",position:"top",is_active:!0});be(()=>{h()});const h=async()=>{w.value=!0;try{const r=await A.get("/api/admin/advertisements");c.value=r.data}catch(r){console.error("加载广告失败:",r),b.error("加载广告失败")}finally{w.value=!1}},u=r=>de(r).format("YYYY-MM-DD HH:mm"),f=r=>{y.value=r,C.value={title:r.title,content:r.content,image_url:r.image_url||"",link_url:r.link_url||"",position:r.position||"top",is_active:r.is_active},v.value=!0},m=async r=>{try{await et.confirm("确定要删除这个广告吗?","确认删除",{confirmButtonText:"确定",cancelButtonText:"取消",type:"warning"}),await A.delete(`/api/admin/advertisements/${r}`),b.success("广告删除成功"),h()}catch(o){o!=="cancel"&&(console.error("删除广告失败:",o),b.error("删除广告失败"))}},_=async()=>{try{const r={title:C.value.title,content:C.value.content,image_url:C.value.image_url||void 0,link_url:C.value.link_url||void 0,position:C.value.position,is_active:C.value.is_active};y.value?(await A.put(`/api/admin/advertisements/${y.value.id}`,r),b.success("广告更新成功")):(await A.post("/api/admin/advertisements",r),b.success("广告创建成功")),v.value=!1,y.value=null,p(),h()}catch(r){console.error("保存广告失败:",r),b.error("保存广告失败")}},p=()=>{C.value={title:"",content:"",image_url:"",link_url:"",position:"top",is_active:!0}};return(r,o)=>{const g=a("el-button"),V=a("el-table-column"),z=a("el-tag"),M=a("el-table"),L=a("el-card"),I=a("el-input"),O=a("el-form-item"),j=a("el-option"),R=a("el-select"),K=a("el-switch"),H=a("el-form"),x=a("el-dialog"),B=Ee("loading");return n(),k(ue,null,[e(L,null,{header:t(()=>[l("div",$i,[o[10]||(o[10]=l("span",null,"广告管理",-1)),e(g,{type:"primary",onClick:o[0]||(o[0]=D=>v.value=!0)},{default:t(()=>[...o[9]||(o[9]=[s("创建广告",-1)])]),_:1})])]),default:t(()=>[Me((n(),N(M,{data:c.value,style:{width:"100%"}},{default:t(()=>[e(V,{prop:"title",label:"标题",width:"150"}),e(V,{prop:"position",label:"位置",width:"100"},{default:t(D=>[e(z,{type:D.row.position==="top"?"primary":"success"},{default:t(()=>[s(S(D.row.position),1)]),_:2},1032,["type"])]),_:1}),e(V,{label:"状态",width:"80"},{default:t(D=>[e(z,{type:D.row.is_active?"success":"danger"},{default:t(()=>[s(S(D.row.is_active?"启用":"禁用"),1)]),_:2},1032,["type"])]),_:1}),e(V,{prop:"created_at",label:"创建时间",width:"160"},{default:t(D=>[s(S(u(D.row.created_at)),1)]),_:1}),e(V,{label:"操作",fixed:"right",width:"150"},{default:t(D=>[e(g,{size:"small",onClick:U=>f(D.row)},{default:t(()=>[...o[11]||(o[11]=[s("编辑",-1)])]),_:1},8,["onClick"]),e(g,{size:"small",type:"danger",onClick:U=>m(D.row.id)},{default:t(()=>[...o[12]||(o[12]=[s("删除",-1)])]),_:1},8,["onClick"])]),_:1})]),_:1},8,["data"])),[[B,w.value]]),!w.value&&c.value.length===0?(n(),k("div",Vi," 暂无广告数据 ")):te("",!0)]),_:1}
129),e(x,{title:y.value?"编辑广告":"创建广告",modelValue:v.value,"onUpdate:modelValue":o[8]||(o[8]=D=>v.value=D),width:"500px"},{footer:t(()=>[e(g,{onClick:o[7]||(o[7]=D=>v.value=!1)},{default:t(()=>[...o[13]||(o[13]=[s("取消",-1)])]),_:1}),e(g,{type:"primary",onClick:_},{default:t(()=>[...o[14]||(o[14]=[s("保存",-1)])]),_:1})]),default:t(()=>[e(H,{model:C.value,"label-width":"80px"},{default:t(()=>[e(O,{label:"标题",required:""},{default:t(()=>[e(I,{modelValue:C.value.title,"onUpdate:modelValue":o[1]||(o[1]=D=>C.value.title=D)},null,8,["modelValue"])]),_:1}),e(O,{label:"内容"},{default:t(()=>[e(I,{modelValue:C.value.content,"onUpdate:modelValue":o[2]||(o[2]=D=>C.value.content=D),type:"textarea",rows:3,placeholder:"支持HTML格式"},null,8,["modelValue"])]),_:1}),e(O,{label:"图片URL"},{default:t(()=>[e(I,{modelValue:C.value.image_url,"onUpdate:modelValue":o[3]||(o[3]=D=>C.value.image_url=D),placeholder:"http://example.com/image.jpg"},null,8,["modelValue"])]),_:1}),e(O,{label:"链接URL"},{default:t(()=>[e(I,{modelValue:C.value.link_url,"onUpdate:modelValue":o[4]||(o[4]=D=>C.value.link_url=D),placeholder:"http://example.com"},null,8,["modelValue"])]),_:1}),e(O,{label:"显示位置"},{default:t(()=>[e(R,{modelValue:C.value.position,"onUpdate:modelValue":o[5]||(o[5]=D=>C.value.position=D),placeholder:"选择显示位置"},{default:t(()=>[e(j,{label:"顶部",value:"top"}),e(j,{label:"侧边栏",value:"sidebar"})]),_:1},8,["modelValue"])]),_:1}),e(O,{label:"是否启用"},{default:t(()=>[e(K,{modelValue:C.value.is_active,"onUpdate:modelValue":o[6]||(o[6]=D=>C.value.is_active=D)},null,8,["modelValue"])]),_:1})]),_:1},8,["model"])]),_:1},8,["title","modelValue"])],64)}}}),xi=Ce(Ci,[["__scopeId","data-v-e60fa6a3"]]),Di={class:"admin-advertisements"},Si=ge({__name:"AdminAdvertisements",setup(q){const c=Ie();function w(){c.push("/admin")}return(v,y)=>{const C=a("el-page-header");return n(),k("div",Di,[e(C,{onBack:w,title:"返回",content:"广告管理",style:{"margin-bottom":"20px"}}),e(xi)])}}}),Mi=Ce(Si,[["__scopeId","data-v-93ecb435"]]),Ui={class:"card-header"},Ii={key:0,class:"no-data"},Ti=ge({__name:"MetaTagManagement",setup(q){const c=d([]),w=d(!1),v=d(!1),y=d(null),C=d(),h=Ae({name:"",content:"",is_active:!0});be(()=>{u()});const u=async()=>{w.value=!0;try{const o=await A.get("/api/admin/meta-tags");c.value=o.data}catch(o){console.error("加载Meta标签失败:",o),b.error("加载Meta标签失败")}finally{w.value=!1}},f=o=>de(o).format("YYYY-MM-DD HH:mm"),m=o=>{y.value=o,h.name=o.name,h.content=o.content,h.is_active=o.is_active,v.value=!0},_=async o=>{try{await et.confirm("确定要删除这个Meta标签吗?","确认删除",{confirmButtonText:"确定",cancelButtonText:"取消",type:"warning"}),await A.delete(`/api/admin/meta-tags/${o}`),b.success("Meta标签删除成功"),u()}catch(g){g!=="cancel"&&(console.error("删除Meta标签失败:",g),b.error("删除Meta标签失败"))}},p=async()=>{try{const o={name:h.name,content:h.content,is_active:h.is_active};y.value?(await A.put(`/api/admin/meta-tags/${y.value.id}`,o),b.success("Meta标签更新成功")):(await A.post("/api/admin/meta-tags",o),b.success("Meta标签创建成功")),v.value=!1,y.value=null,r(),u()}catch(o){console.error("保存Meta标签失败:",o),o.response&&o.response.data&&o.response.data.error?b.error(o.response.data.error):b.error("保存Meta标签失败")}},r=()=>{h.name="",h.content="",h.is_active=!0};return(o,g)=>{const V=a("el-button"),z=a("el-table-column"),M=a("el-tag"),L=a("el-table"),I=a("el-card"),O=a("el-input"),j=a("el-form-item"),R=a("el-switch"),K=a("el-form"),H=a("el-dialog"),x=Ee("loading");return n(),k(ue,null,[e(I,null,{header:t(()=>[l("div",Ui,[g[7]||(g[7]=l("span",null,"Meta标签管理",-1)),e(V,{type:"primary",onClick:g[0]||(g[0]=B=>v.value=!0)},{default:t(()=>[...g[6]||(g[6]=[s("添加Meta标签",-1)])]),_:1})])]),default:t(()=>[Me((n(),N(L,{data:c.value,style:{width:"100%"}},{default:t(()=>[e(z,{prop:"name",label:"Name",width:"200"}),e(z,{prop:"content",label:"Content"}),e(z,{label:"状态",width:"80"},{default:t(B=>[e(M,{type:B.row.is_active?"success":"danger"},{default:t(()=>[s(S(B.row.is_active?"启用":"禁用"),1)]),_:2},1032,["type"])]),_:1}),e(z,{prop:"created_at",label:"创建时间",width:"160"},{default:t(B=>[s(S(f(B.row.created_at)),1)]),_:1}),e(z,{label:"操作",fixed:"right",width:"150"},{default:t(B=>[e(V,{size:"small",onClick:D=>m(B.row)},{default:t(()=>[...g[8]||(g[8]=[s("编辑",-1)])]),_:1},8,["onClick"]),e(V,{size:"small",type:"danger",onClick:D=>_(B.row.id)},{default:t(()=>[...g[9]||(g[9]=[s("删除",-1)])]),_:1},8,["onClick"])]),_:1})]),_:1},8,["data"])),[[x,w.value]]),!w.value&&c.value.length===0?(n(),k("div",Ii," 暂无Meta标签数据 ")):te("",!0)]),_:1}),e(H,{title:y.value?"编辑Meta标签":"添加Meta标签",modelValue:v.value,"onUpdate:modelValue":g[5]||
129(g[5]=B=>v.value=B),width:"500px"},{footer:t(()=>[e(V,{onClick:g[4]||(g[4]=B=>v.value=!1)},{default:t(()=>[...g[10]||(g[10]=[s("取消",-1)])]),_:1}),e(V,{type:"primary",onClick:p},{default:t(()=>[...g[11]||(g[11]=[s("保存",-1)])]),_:1})]),default:t(()=>[e(K,{model:h,"label-width":"80px",ref_key:"metaTagFormRef",ref:C},{default:t(()=>[e(j,{label:"Name",required:"",prop:"name"},{default:t(()=>[e(O,{modelValue:h.name,"onUpdate:modelValue":g[1]||(g[1]=B=>h.name=B),placeholder:"例如: google-adsense-account"},null,8,["modelValue"])]),_:1}),e(j,{label:"Content",required:"",prop:"content"},{default:t(()=>[e(O,{modelValue:h.content,"onUpdate:modelValue":g[2]||(g[2]=B=>h.content=B),type:"textarea",rows:3,placeholder:"例如: ca-pub-8048695856173575"},null,8,["modelValue"])]),_:1}),e(j,{label:"是否启用"},{default:t(()=>[e(R,{modelValue:h.is_active,"onUpdate:modelValue":g[3]||(g[3]=B=>h.is_active=B)},null,8,["modelValue"])]),_:1})]),_:1},8,["model"])]),_:1},8,["title","modelValue"])],64)}}}),Ai=Ce(Ti,[["__scopeId","data-v-6441185a"]]),zi={class:"admin-meta-tags"},Li=ge({__name:"AdminMetaTags",setup(q){const c=Ie();function w(){c.push("/admin")}return(v,y)=>{const C=a("el-page-header");return n(),k("div",zi,[e(C,{onBack:w,title:"返回",content:"Meta标签管理",style:{"margin-bottom":"20px"}}),e(Ai)])}}}),Yi=Ce(Li,[["__scopeId","data-v-18058d60"]]),Ei={class:"resource-info"},Ri={key:0},Fi={class:"disk-usage-container"},Bi={class:"disk-usage-text"},Pi={key:0},Hi={class:"db-file-info"},Oi={class:"download-info"},qi={class:"db-backup-info"},Ni={class:"backup-list"},ji={class:"scheduled-backup-info"},Wi={class:"db-restore-info"},Ki={class:"restore-info"},Gi={class:"email-config-info"},Ji={key:0,class:"certificate-info"},Xi={class:"certificate-paths"},Qi={class:"certificate-upload"},Zi={class:"upload-info"},eu=ge({__name:"AdminSystemMaintenance",setup(q){const c=d(""),w=d(""),v=d(""),y=d(!1),C=d(!1),h=d(!1),u=d(!1),f=d(!1),m=d(!1),_=d({}),p=d([]),r=d(""),o=d({memory:{alloc_mb:0,total_alloc_mb:0,sys_mb:0,num_gc:0},disk:{total_mb:0,used_mb:0,free_mb:0},goroutines:0}),g=d({enabled:!1,interval:24,last_run:""}),V=d({enabled:!1,smtp_host:"",smtp_port:465,username:"",password:"",from_email:"",to_email:""});be(async()=>{try{const W=sessionStorage.getItem("token");W&&(_.value={Authorization:`Bearer ${W}`});const Z=await A.get("/api/admin/system/info");c.value=Z.data.db_type,w.value=Z.data.cert_file,v.value=Z.data.key_file,c.value==="sqlite"&&(j(),H(),B()),z(),M()}catch(W){console.error("Failed to fetch system info:",W),c.value="sqlite"}});async function z(){try{const Z=(await A.get("/api/admin/system/uptime")).data.uptime,Ve=Math.floor(Z/86400),xe=Math.floor(Z%86400/3600),ae=Math.floor(Z%3600/60),ee=Math.floor(Z%60);r.value=`${Ve}天 ${xe}小时 ${ae}分钟 ${ee}秒`}catch(W){console.error("Failed to fetch system uptime:",W),r.value="无法获取"}}async function M(){try{const W=await A.get("/api/admin/system/resources");o.value=W.data}catch(W){console.error("Failed to fetch system resources:",W)}}async function L(W,Z){try{const Ve=await A.get(W,{responseType:"blob"}),xe=window.URL.createObjectURL(new Blob([Ve.data])),ae=document.createElement("a");ae.href=xe,ae.setAttribute("download",Z),document.body.appendChild(ae),ae.click(),window.URL.revokeObjectURL(xe),document.body.removeChild(ae),b.success("文件下载成功")}catch(Ve){console.error("Download failed:",Ve),b.error("文件下载失败")}}async function I(){if(c.value!=="sqlite"){b.warning("只有 SQLite 数据库支持下载");return}try{y.value=!0,await L("/api/admin/database","open_course.db")}catch(W){console.error("Download failed:",W),b.error("数据库文件下载失败")}finally{y.value=!1}}async function O(){if(c.value!=="sqlite"){b.warning("只有 SQLite 数据库支持备份");return}try{C.value=!0;const W=await A.post("/api/admin/database/backup");b.success("数据库备份创建成功: "+W.data.filename),j()}catch(W){console.error("Backup failed:",W),b.error("数据库备份创建失败")}finally{C.value=!1}}async function j(){if(c.value==="sqlite")try{h.value=!0;const W=await A.get("/api/admin/database/backups");p.value=W.data}catch(W){console.error("Failed to load backups:",W),b.error("加载备份列表失败")}finally{h.value=!1}}function R(W){if(c.value!=="sqlite"){b.warning("只有 SQLite 数据库支持此操作");return}L(`/api/admin/database/backup/${W}`,W)}async function K(W){if(c.value!=="sqlite"){b.warning("只有 SQLite 数据库支持此操作");return}try{await A.delete(`/api/admin/database/backup/${W}`),b.success("备份文件删除成功"),j()}catch(Z){console.error("Delete failed:",Z),b.error("备份文件删除失败")}}async function H(){try{const W=await A.get("/api/admin/backup-schedule");g.value=W.data}catch(W){console.error("Failed to load backup schedule:",W)}}async function x(){try{u.value=!0;const W=await A.post("/api/admin/backup-schedule",g.value);g.value=W.data,b.success("定时备份设置保存成功")}catch(W){console.error("Failed to save backup schedule:",W),b.error("定时备份设置保存失败")}finally{u.value=!1}}async function B(){try{const W=await A.get("/api/admin/email-config");V.value=W.data}catch(W){console.error("Failed to load email config:",W)}}async function D(){try{f.value=!0;const W=await A.post("/api/admin/email-config",V.value);V.value=W.data,b.success("邮件服务器设置保存成功")}catch(W){console.error("Failed to save email config:",W),b.error("邮件服务器设置保存失败")}finally{f.value=!1}}async function U(){var W,Z;try{m.value=!0,await A.post("/api/admin/test-email"),b.success("测试邮件发送成功")}catch(Ve){console.error("Failed to send test email:",Ve),b.error("测试邮件发送失败: "+(((Z=(W=Ve.response)==null?void 0:W.data)==null?void 0:Z.error)||"未知错误"))}finally{m.value=!1}}function F(W){const Z=W.name.endsWith(".db");return Z||b.error("备份文件必须是.db格式!"),Z}function i(W){b.success("数据库恢复成功,请重启服务")}function $(W){b.error("数据库恢复失败: "+(W.message||"未知错误"))}function X(W){const Z=W.type==="application/x-x509-ca-cert"||W.name.endsWith(".crt")||W.name.endsWith(".pem")||W.name.endsWith(".cert")||W.type==="";return Z||b.error("证书文件必须是.crt、.pem或.cert格式!"),Z}function G(W){const Z=W.name.endsWith(".key")||W.name.endsWith(".pem")||W.type==="";return Z||b.error("私钥文件必须是.key或.pem格式!"),Z}function E(W){b.success("证书文件上传成功"),me()}function oe(W){b.success("私钥文件上传成功"),me()}function Q(W){b.error("证书文件上传失败: "+(W.message||"未知错误"))}function re(W){b.error("私钥文件上传失败: "+(W.message||"未知错误"))}async function me(){try{const W=await A.get("/api/admin/system/info");w.value=W.data.cert_file,v.value=W.data.key_file}catch(W){console.error("Failed to fetch system info:",W)}}
129function ie(W,Z,Ve){if(Ve===0)return"0 Bytes";const xe=1024,ae=["Bytes","KB","MB","GB"],ee=Math.floor(Math.log(Ve)/Math.log(xe));return parseFloat((Ve/Math.pow(xe,ee)).toFixed(2))+" "+ae[ee]}function ce(W,Z,Ve){return new Date(Ve).toLocaleString()}function ke(){return o.value.disk.total_mb?o.value.disk.used_mb/o.value.disk.total_mb*100:0}function De(){const W=ke();return W<70?"success":W<90?"warning":"exception"}function ve(W){return`${W.toFixed(2)}%`}return(W,Z)=>{const Ve=a("el-tag"),xe=a("el-descriptions-item"),ae=a("el-progress"),ee=a("el-descriptions"),Y=a("el-button"),P=a("el-text"),ne=a("el-table-column"),we=a("el-table"),_e=a("el-switch"),Se=a("el-form-item"),We=a("el-input-number"),tt=a("el-form"),Xe=a("el-upload"),Ge=a("el-input"),qe=a("el-col"),lt=a("el-row"),ye=a("el-card"),Fe=Ee("loading");return n(),N(ye,{class:"system-info-card"},{header:t(()=>[...Z[9]||(Z[9]=[l("div",{class:"card-header"},[l("span",null,"系统维护")],-1)])]),default:t(()=>[e(ee,{column:1,border:""},{default:t(()=>[e(xe,{label:"系统运行时长"},{default:t(()=>[e(Ve,{type:"primary"},{default:t(()=>[s(S(r.value),1)]),_:1})]),_:1}),e(xe,{label:"数据库类型"},{default:t(()=>[e(Ve,{type:c.value==="sqlite"?"success":"primary"},{default:t(()=>[s(S(c.value),1)]),_:1},8,["type"])]),_:1}),e(xe,{label:"系统资源使用情况"},{default:t(()=>[l("div",Ei,[e(ee,{column:1,size:"small"},{default:t(()=>[e(xe,{label:"内存使用"},{default:t(()=>[e(Ve,{type:"primary"},{default:t(()=>{var le;return[s(S((le=o.value.memory)==null?void 0:le.sys_mb)+" MB",1)]}),_:1})]),_:1}),e(xe,{label:"GC次数"},{default:t(()=>[e(Ve,{type:"primary"},{default:t(()=>{var le;return[s(S((le=o.value.memory)==null?void 0:le.num_gc),1)]}),_:1})]),_:1}),e(xe,{label:"协程数量"},{default:t(()=>[e(Ve,{type:"primary"},{default:t(()=>[s(S(o.value.goroutines),1)]),_:1})]),_:1}),o.value.disk.total_mb?(n(),k("div",Ri,[e(xe,{label:"磁盘使用情况"},{default:t(()=>[l("div",Fi,[e(ae,{percentage:ke(),status:De(),"stroke-width":18,format:ve},null,8,["percentage","status"]),l("div",Bi,[l("span",null,"已使用: "+S(o.value.disk.used_mb)+" MB",1),l("span",null,"剩余: "+S(o.value.disk.free_mb)+" MB",1)])])]),_:1})])):te("",!0)]),_:1})])]),_:1}),c.value==="sqlite"?(n(),k("div",Pi,[e(xe,{label:"数据库文件"},{default:t(()=>[l("div",Hi,[e(Y,{type:"primary",onClick:I,loading:y.value,icon:"Download"},{default:t(()=>[...Z[10]||(Z[10]=[s(" 下载数据库文件 ",-1)])]),_:1},8,["loading"]),l("div",Oi,[e(P,{type:"info"},{default:t(()=>[...Z[11]||(Z[11]=[s("点击按钮下载当前 SQLite 数据库文件",-1)])]),_:1})])])]),_:1}),e(xe,{label:"数据库备份"},{default:t(()=>[l("div",qi,[e(Y,{type:"primary",onClick:O,loading:C.value,icon:"Upload"},{default:t(()=>[...Z[12]||(Z[12]=[s(" 创建备份 ",-1)])]),_:1},8,["loading"]),l("div",Ni,[Z[16]||(Z[16]=l("h4",null,"现有备份文件:",-1)),e(P,{type:"info",size:"small"},{default:t(()=>[...Z[13]||(Z[13]=[s("仅显示最近 10 条备份记录",-1)])]),_:1}),Me((n(),N(we,{data:p.value,style:{width:"100%","margin-top":"10px"}},{default:t(()=>[e(ne,{prop:"name",label:"文件名"}),e(ne,{prop:"size",label:"大小",formatter:ie}),e(ne,{prop:"modified",label:"修改时间",formatter:ce}),e(ne,{label:"操作"},{default:t(le=>[e(Y,{size:"small",onClick:T=>R(le.row.name)},{default:t(()=>[...Z[14]||(Z[14]=[s("下载",-1)])]),_:1},8,["onClick"]),e(Y,{size:"small",type:"danger",onClick:T=>K(le.row.name)},{default:t(()=>[...Z[15]||(Z[15]=[s("删除",-1)])]),_:1},8,["onClick"])]),_:1})]),_:1},8,["data"])),[[Fe,h.value]])])])]),_:1}),e(xe,{label:"定时备份设置"},{default:t(()=>[l("div",ji,[e(tt,{model:g.value,"label-width":"120px"},{default:t(()=>[e(Se,{label:"启用定时备份"},{default:t(()=>[e(_e,{modelValue:g.value.enabled,"onUpdate:modelValue":Z[0]||(Z[0]=le=>g.value.enabled=le)},null,8,["modelValue"])]),_:1}),e(Se,{label:"备份间隔"},{default:t(()=>[e(We,{modelValue:g.value.interval,"onUpdate:modelValue":Z[1]||(Z[1]=le=>g.value.interval=le),min:1,max:168,disabled:!g.value.enabled},null,8,["modelValue","disabled"]),Z[17]||(Z[17]=l("span",{class:"unit"},"小时",-1))]),_:1}),g.value.last_run?(n(),N(Se,{key:0,label:"上次备份时间"},{default:t(()=>[l("span",null,S(ce(null,null,g.value.last_run)),1)]),_:1})):te("",!0),e(Se,null,{default:t(()=>[e(Y,{type:"primary",onClick:x,loading:u.value},{default:t(()=>[...Z[18]||(Z[18]=[s(" 保存设置 ",-1)])]),_:1},8,["loading"])]),_:1})]),_:1},8,["model"])])]),_:1}),e(xe,{label:"数据库恢复"},{default:t(()=>[l("div",Wi,[e(Xe,{class:"backup-uploader",action:"/api/admin/database/restore",headers:_.value,"show-file-list":!1,"before-upload":F,"on-success":i,"on-error":$,name:"backup"},{default:t(()=>[e(Y,{type:"warning"},{default:t(()=>[...Z[19]||(Z[19]=[s("上传备份文件并恢复",-1)])]),_:1})]),_:1},8,["headers"]),l("div",Ki,[e(P,{type:"info"},{default:t(()=>
129[...Z[20]||(Z[20]=[s("上传SQLite备份文件以恢复数据库,恢复后需要重启服务",-1)])]),_:1})])])]),_:1})])):te("",!0),e(xe,{label:"邮件服务器设置"},{default:t(()=>[l("div",Gi,[e(tt,{model:V.value,"label-width":"120px"},{default:t(()=>[e(Se,{label:"启用邮件通知"},{default:t(()=>[e(_e,{modelValue:V.value.enabled,"onUpdate:modelValue":Z[2]||(Z[2]=le=>V.value.enabled=le)},null,8,["modelValue"])]),_:1}),e(lt,{gutter:20},{default:t(()=>[e(qe,{span:12},{default:t(()=>[e(Se,{label:"SMTP服务器"},{default:t(()=>[e(Ge,{modelValue:V.value.smtp_host,"onUpdate:modelValue":Z[3]||(Z[3]=le=>V.value.smtp_host=le),placeholder:"smtp.example.com",disabled:!V.value.enabled},null,8,["modelValue","disabled"])]),_:1})]),_:1}),e(qe,{span:12},{default:t(()=>[e(Se,{label:"SMTP端口"},{default:t(()=>[e(We,{modelValue:V.value.smtp_port,"onUpdate:modelValue":Z[4]||(Z[4]=le=>V.value.smtp_port=le),min:1,max:65535,disabled:!V.value.enabled},null,8,["modelValue","disabled"])]),_:1})]),_:1})]),_:1}),e(Se,{label:"用户名"},{default:t(()=>[e(Ge,{modelValue:V.value.username,"onUpdate:modelValue":Z[5]||(Z[5]=le=>V.value.username=le),placeholder:"[email protected]",disabled:!V.value.enabled},null,8,["modelValue","disabled"])]),_:1}),e(Se,{label:"密码"},{default:t(()=>[e(Ge,{modelValue:V.value.password,"onUpdate:modelValue":Z[6]||(Z[6]=le=>V.value.password=le),type:"password",placeholder:"SMTP密码",disabled:!V.value.enabled,"show-password":""},null,8,["modelValue","disabled"])]),_:1}),e(Se,{label:"发件人邮箱"},{default:t(()=>[e(Ge,{modelValue:V.value.from_email,"onUpdate:modelValue":Z[7]||(Z[7]=le=>V.value.from_email=le),placeholder:"[email protected]",disabled:!V.value.enabled},null,8,["modelValue","disabled"])]),_:1}),e(Se,{label:"收件人邮箱"},{default:t(()=>[e(Ge,{modelValue:V.value.to_email,"onUpdate:modelValue":Z[8]||(Z[8]=le=>V.value.to_email=le),placeholder:"[email protected]",disabled:!V.value.enabled},null,8,["modelValue","disabled"])]),_:1}),e(Se,null,{default:t(()=>[e(Y,{type:"primary",onClick:D,loading:f.value},{default:t(()=>[...Z[21]||(Z[21]=[s(" 保存设置 ",-1)])]),_:1},8,["loading"]),e(Y,{onClick:U,disabled:!V.value.enabled,loading:m.value,style:{"margin-left":"10px"}},{default:t(()=>[...Z[22]||(Z[22]=[s(" 发送测试邮件 ",-1)])]),_:1},8,["disabled","loading"])]),_:1})]),_:1},8,["model"])])]),_:1}),e(xe,{label:"SSL证书设置"},{default:t(()=>[w.value||v.value?(n(),k("div",Ji,[l("div",Xi,[l("p",null,[Z[23]||(Z[23]=l("strong",null,"证书文件:",-1)),s(" "+S(w.value||"未设置"),1)]),l("p",null,[Z[24]||(Z[24]=l("strong",null,"私钥文件:",-1)),s(" "+S(v.value||"未设置"),1)])])])):te("",!0),l("div",Qi,[e(Xe,{class:"certificate-uploader",action:"/api/admin/system/certificate",headers:_.value,"show-file-list":!1,"before-upload":X,"on-success":E,"on-error":Q,data:{type:"certificate"},name:"certificate"},{default:t(()=>[e(Y,{type:"primary"},{default:t(()=>[...Z[25]||(Z[25]=[s("上传证书文件",-1)])]),_:1})]),_:1},8,["headers"]),e(Xe,{class:"key-uploader",action:"/api/admin/system/certificate",headers:_.value,"show-file-list":!1,"before-upload":G,"on-success":oe,"on-error":re,data:{type:"key"},name:"key"},{default:t(()=>[e(Y,{type:"primary"},{default:t(()=>[...Z[26]||(Z[26]=[s("上传私钥文件",-1)])]),_:1})]),_:1},8,["headers"]),l("div",Zi,[e(P,{type:"info"},{default:t(()=>[...Z[27]||(Z[27]=[s("上传SSL证书和私钥以启用HTTPS支持",-1)])]),_:1})])])]),_:1})]),_:1})]),_:1})}}}),tu=Ce(eu,[["__scopeId","data-v-2d94ea4c"]]),lu={key:0,class:"total-count"},au={class:"import-section"},ou={class:"import-actions"},nu={key:0,class:"import-result"},su=ge({__name:"VocabularyImport",setup(q){const c=d(null),w=d(!1),v=d(null),y=d(null),C=m=>{c.value=m.raw,v.value=null},h=async()=>{try{const m=await A.get("/api/vocabulary/total-count");y.value=m.data.total}catch(m){console.error("Failed to load vocabulary count:",m),y.value=null}},u=async()=>{var m,_;if(!c.value){b.warning("请选择要导入的文件");return}w.value=!0,v.value=null;try{const p=await f(c.value),r=JSON.parse(p);await A.post("/api/vocabulary/import",r),v.value={success:!0,message:"词汇导入成功"},b.success("词汇导入成功"),await h()}catch(p){console.error("Import error:",p);let r="词汇导入失败";(_=(m=p.response)==null?void 0:m.data)!=null&&_.error?r=p.response.data.error:p.message&&(r=p.message),v.value={success:!1,message:r},b.error(r)}finally{w.value=!1}},f=m=>new Promise((_,p)=>{const r=new FileReader;r.onload=()=>_(r.result),r.onerror=p,r.readAsText(m)});return be(()=>{h()}),(m,_)=>{const p=a("el-icon"),r=a("el-upload"),o=a("el-button"),g=a("el-alert");return n(),k(ue,null,[y.value!==null?(n(),k("div",lu," 当前总词汇量: "+S(y.value),1)):te("",!0),l("div",au,[e(r,{class:"upload-demo",drag:"","auto-upload":!1,"on-change":C,"show-file-list":!0,accept:".json"},{tip:t(()=>[..._[0]||(_[0]=[l("div",{class:"el-upload__tip"}," 仅支持 JSON 格式文件 ",-1)])]),default:t(()=>[e(p,{class:"el-icon--upload"},{default:t(()=>[e(se(Tt))]),_:1}),_[1]||(_[1]=l("div",{class:"el-upload__text"},[s(" 拖拽文件到此处或 "),l("em",null,"点击上传")],-1))]),_:1}),l("div",ou,[e(o,{type:"primary",onClick:u,disabled:!c.value||w.value,loading:w.value},{default:t(()=>[s(S(w.value?"导入中...":"导入词汇"),1)]),_:1},8,["disabled","loading"])]),v.value?(n(),k("div",nu,[e(g,{type:v.value.success?"success":"error",title:v.value.message,"show-icon":""},null,8,["type","title"])])):te("",!0)])],64)}}}),ru=Ce(su,[["__scopeId","data-v-dce31f19"]]),iu={class:"vocabulary-management"},uu={class:"card-header"},du={key:1},cu={class:"definitions-input"},pu={class:"add-definition"},mu=ge({__name:"VocabularyManagement",setup(q){const c=d(),w=d([]),v=d([{prop:"word",label:"单词",searchable:!0},{prop:"grade",label:"年级",searchable:!0,width:120,kind:"slot",searchKind:"select",options:w.value},{prop:"unit",label:"单元",width:120},{prop:"label",label:"标签",width:120,searchable:!0},{prop:"actions",label:"操作",width:150,kind:"slot"}]),y=d(!1),C=d(!1),h=d(),u=d(""),f=d(!1),m=Ae({id:0,word:"",grade:"",unit:"",label:"",definitions:[]}
129),_={word:[{required:!0,message:"请输入单词",trigger:"blur"}],grade:[{required:!0,message:"请选择年级",trigger:"change"}],definitions:[{required:!0,message:"请至少添加一个定义",trigger:"blur"}]},p=()=>{u.value.trim()&&(m.definitions.push(u.value.trim()),u.value="")},r=L=>{m.definitions.splice(L,1)},o=()=>{m.id=0,m.word="",m.grade="",m.unit="",m.label="",m.definitions=[],u.value=""},g=L=>{C.value=!0,m.id=L.id,m.word=L.word,m.grade=L.grade,m.unit=L.unit,m.label=L.label,m.definitions=L.definitions?L.definitions.map(I=>I.text):[],y.value=!0},V=async L=>{try{await et.confirm(`确定要删除单词 "${L.word}" 吗?`,"删除确认",{confirmButtonText:"确定",cancelButtonText:"取消",type:"warning"}),await A.delete(`/api/vocabulary/${L.id}`),b.success("删除成功"),c.value&&c.value.loadData()}catch(I){I!=="cancel"&&(b.error("删除失败"),console.error(I))}},z=async()=>{if(h.value)try{await h.value.validate(),C.value?(await A.put(`/api/vocabulary/${m.id}`,{word:m.word,grade:m.grade,unit:m.unit,label:m.label,definitions:m.definitions}),b.success("更新成功")):(await A.post("/api/vocabulary",{word:m.word,grade:m.grade,unit:m.unit,label:m.label,definitions:m.definitions}),b.success("添加成功")),y.value=!1,o(),C.value=!1,c.value&&c.value.loadData()}catch(L){console.error(L),b.error("操作失败")}},M=()=>{y.value=!1,o(),C.value=!1,h.value&&h.value.clearValidate()};return be(()=>{for(const L in Ke)w.value.push({label:Ke[L],value:L})}),(L,I)=>{const O=a("el-button"),j=a("el-space"),R=a("el-tag"),K=a("el-card"),H=a("el-input"),x=a("el-form-item"),B=a("el-option"),D=a("el-select"),U=a("el-form"),F=a("el-dialog");return n(),k("div",iu,[e(K,null,{header:t(()=>[l("div",uu,[I[11]||(I[11]=l("span",null,"词汇管理",-1)),e(j,null,{default:t(()=>[e(O,{class:"button",type:"primary",onClick:I[0]||(I[0]=i=>y.value=!0)},{default:t(()=>[...I[9]||(I[9]=[s(" 添加词汇 ",-1)])]),_:1}),e(O,{class:"button",type:"primary",onClick:I[1]||(I[1]=i=>f.value=!0)},{default:t(()=>[...I[10]||(I[10]=[s(" 批量导入 ",-1)])]),_:1})]),_:1})])]),default:t(()=>[e(mt,{ref_key:"paginationTableRef",ref:c,dataURL:"/api/vocabulary",columns:v.value},{word:t(({row:i})=>[l("span",null,S(i.word),1)]),grade:t(({row:i})=>[e(R,{size:"small"},{default:t(()=>[s(S(se(Ke)[i.grade]||i.grade),1)]),_:2},1024)]),actions:t(({row:i})=>[e(O,{size:"small",onClick:$=>g(i)},{default:t(()=>[...I[12]||(I[12]=[s("编辑",-1)])]),_:1},8,["onClick"]),e(O,{size:"small",type:"danger",onClick:$=>V(i)},{default:t(()=>[...I[13]||(I[13]=[s("删除",-1)])]),_:1},8,["onClick"])]),_:1},8,["columns"])]),_:1}),e(F,{title:C.value?"编辑词汇":"添加词汇",modelValue:y.value,"onUpdate:modelValue":I[7]||(I[7]=i=>y.value=i),width:"600px","before-close":M},{footer:t(()=>[e(O,{onClick:M},{default:t(()=>[...I[15]||(I[15]=[s("取消",-1)])]),_:1}),e(O,{type:"primary",onClick:z},{default:t(()=>[...I[16]||(I[16]=[s("确定",-1)])]),_:1})]),default:t(()=>[e(U,{model:m,rules:_,ref_key:"formRef",ref:h,"label-width":"100px"},{default:t(()=>[e(x,{label:"单词",prop:"word"},{default:t(()=>[C.value?(n(),k("span",du,S(m.word),1)):(n(),N(H,{key:0,modelValue:m.word,"onUpdate:modelValue":I[2]||(I[2]=i=>m.word=i),placeholder:"请输入单词"},null,8,["modelValue"]))]),_:1}),e(x,{label:"年级",prop:"grade"},{default:t(()=>[e(D,{modelValue:m.grade,"onUpdate:modelValue":I[3]||(I[3]=i=>m.grade=i),placeholder:"请选择年级",style:{width:"100%"}},{default:t(()=>[(n(!0),k(ue,null,fe(w.value,i=>(n(),N(B,{key:i.value,label:i.label,value:i.value},null,8,["label","value"]))),128))]),_:1},8,["modelValue"])]),_:1}),e(x,{label:"单元",prop:"unit"},{default:t(()=>[e(H,{modelValue:m.unit,"onUpdate:modelValue":I[4]||(I[4]=i=>m.unit=i),placeholder:"请输入单元(可选)"},null,8,["modelValue"])]),_:1}),e(x,{label:"标签",prop:"label"},{default:t(()=>[e(H,{modelValue:m.label,"onUpdate:modelValue":I[5]||(I[5]=i=>m.label=i),placeholder:"请输入标签(可选)"},null,8,["modelValue"])]),_:1}),e(x,{label:"定义",prop:"definitions"},{default:t(()=>[l("div",cu,[(n(!0),k(ue,null,fe(m.definitions,(i,$)=>(n(),N(R,{key:$,closable:"",onClose:X=>r($),type:"info",style:{margin:"0 5px 5px 0"}},{default:t(()=>[s(S(i),1)]),_:2}
129,1032,["onClose"]))),128)),l("div",pu,[e(H,{modelValue:u.value,"onUpdate:modelValue":I[6]||(I[6]=i=>u.value=i),placeholder:"输入定义并按回车添加",onKeyup:Je(p,["enter"]),style:{flex:"1","margin-right":"10px"}},null,8,["modelValue"]),e(O,{onClick:p},{default:t(()=>[...I[14]||(I[14]=[s("添加",-1)])]),_:1})])])]),_:1})]),_:1},8,["model"])]),_:1},8,["title","modelValue"]),e(F,{title:"批量导入",modelValue:f.value,"onUpdate:modelValue":I[8]||(I[8]=i=>f.value=i),width:"600px"},{default:t(()=>[e(ru)]),_:1},8,["modelValue"])])}}}),vu=Ce(mu,[["__scopeId","data-v-e2dd7c2e"]]),fu={style:{color:"var(--el-text-color-secondary)","font-size":"12px","margin-left":"10px"}},_u={style:{display:"flex","justify-content":"space-between","align-items":"center"}},yu={style:{display:"flex",gap:"10px"}},gu={style:{display:"flex","justify-content":"space-between","align-items":"center"}},bu={class:"server-name"},wu={class:"server-description"},ku={class:"server-info"},hu={class:"server-actions"},$u={key:0},Vu={style:{"margin-top":"20px"}},Cu=ge({__name:"AdminMCPServers",setup(q){const c=d("my-servers"),w=d(!1),v=d(null),y=d(!1),C=d(!1),h=d(null),u=d(""),f=d({name:"",description:"",type:"custom",transport:"stdio",command:"",args:"",url:"",env_vars:"",is_enabled:!0}),m=d([]),_=d([]),p=d([{id:"filesystem",name:"Filesystem",description:"安全文件操作,支持可配置的访问控制",category:"File Systems",language:"TypeScript",official:!0,package:"@modelcontextprotocol/server-filesystem",installCommand:"npx -y @modelcontextprotocol/server-filesystem /path/to/allowed/files",transport:"stdio"},{id:"fetch",name:"Fetch",description:"网页内容获取和转换,优化 LLM 使用",category:"Developer Tools",language:"TypeScript",official:!0,package:"@modelcontextprotocol/server-fetch",installCommand:"npx -y @modelcontextprotocol/server-fetch",transport:"stdio"},{id:"github",name:"GitHub",description:"访问 GitHub API,实现项目管理",category:"Developer Tools",language:"TypeScript",official:!0,package:"@modelcontextprotocol/server-github",installCommand:"npx -y @modelcontextprotocol/server-github",transport:"stdio"},{id:"puppeteer",name:"Puppeteer",description:"浏览器自动化和网页抓取",category:"Browser Automation",language:"TypeScript",official:!0,package:"@modelcontextprotocol/server-puppeteer",installCommand:"npx -y @modelcontextprotocol/server-puppeteer",transport:"stdio"},{id:"brave-search",name:"Brave Search",description:"使用 Brave Search API 进行网络搜索",category:"Research And Data",language:"TypeScript",official:!0,package:"@modelcontextprotocol/server-brave-search",installCommand:"npx -y @modelcontextprotocol/server-brave-search",transport:"stdio"},{id:"sqlite",name:"SQLite",description:"SQLite 数据库操作",category:"Databases",language:"TypeScript",official:!0,package:"@modelcontextprotocol/server-sqlite",installCommand:"npx -y @modelcontextprotocol/server-sqlite --db-path /path/to/database.db",transport:"stdio"},{id:"redis",name:"Redis",description:"Redis 数据库访问,支持键值存储操作",category:"Databases",language:"TypeScript",official:!0,package:"@modelcontextprotocol/server-redis",installCommand:"npx -y @modelcontextprotocol/server-redis",transport:"stdio"},{id:"time",name:"Time",description:"时间和时区转换功能,支持 IANA 时区名称",category:"Developer Tools",language:"TypeScript",official:!0,package:"@modelcontextprotocol/server-time",installCommand:"npx -y @modelcontextprotocol/server-time",transport:"stdio"},{id:"sequential-thinking",name:"Sequential Thinking",description:"通过结构化思维过程实现动态和反思性问题解决",category:"Knowledge And Memory",language:"TypeScript",official:!0,package:"@modelcontextprotocol/server-sequential-thinking",installCommand:"npx -y @modelcontextprotocol/server-sequential-thinking",transport:"stdio"},{id:"memory",name:"Memory",description:"内存数据存储,用于对话上下文管理",category:"Knowledge And Memory",language:"TypeScript",official:!0,package:"@modelcontextprotocol/server-memory",installCommand:"npx -y @modelcontextprotocol/server-memory",transport:"stdio"},{id:"sentry",name:"Sentry",description:"从 Sentry.io 检索和分析错误",category:"Monitoring",language:"TypeScript",official:!0,package:"@modelcontextprotocol/server-sentry",installCommand:"npx -y @modelcontextprotocol/server-sentry",transport:"stdio"},{id:"gitlab",name:"GitLab",description:"GitLab API 集成,实现项目管理",category:"Developer Tools",language:"TypeScript",official:!0,package:"@modelcontextprotocol/server-gitlab",installCommand:"npx -y @modelcontextprotocol/server-gitlab",transport:"stdio"}]);async function r(){var F,i;try{const $=await A.get("/api/admin/mcp-servers");m.value=$.data}catch($){b.error("加载 MCP 服务器失败: "+(((i=(F=$.response)==null?void 0:F.data)==null?void 0:i.error)||$.message))}}async function o(){var F,i;
129try{const $=await A.get("/api/admin/mcp-servers/presets");_.value=$.data}catch($){b.error("加载预设服务器失败: "+(((i=(F=$.response)==null?void 0:F.data)==null?void 0:i.error)||$.message))}}function g(){f.value.type==="custom"&&(f.value.preset_id=void 0)}async function V(){const F=_.value.find(i=>i.id===f.value.preset_id);F&&(f.value.name=F.name,f.value.description=F.description,f.value.transport=F.transport)}async function z(){var F,i;try{w.value?(await A.put(`/api/admin/mcp-servers/${f.value.id}`,f.value),b.success("更新成功")):(await A.post("/api/admin/mcp-servers",f.value),b.success("创建成功")),L(),r()}catch($){b.error("操作失败: "+(((i=(F=$.response)==null?void 0:F.data)==null?void 0:i.error)||$.message))}}function M(F){w.value=!0,f.value={...F}}function L(){w.value=!1,f.value={name:"",description:"",type:"custom",transport:"stdio",command:"",args:"",url:"",env_vars:"",is_enabled:!0}}async function I(F){var i,$;v.value=F;try{const X=await A.post(`/api/admin/mcp-servers/${F}/test`);X.data.status==="active"?b.success("连接测试成功"):b.warning("连接测试失败: "+X.data.message),r()}catch(X){b.error("测试失败: "+((($=(i=X.response)==null?void 0:i.data)==null?void 0:$.error)||X.message))}finally{v.value=null}}async function O(F){var i,$;try{await A.put(`/api/admin/mcp-servers/${F.id}`,{is_enabled:F.is_enabled}),b.success(F.is_enabled?"已启用":"已禁用")}catch(X){b.error("操作失败: "+((($=(i=X.response)==null?void 0:i.data)==null?void 0:$.error)||X.message)),r()}}async function j(F){var i,$;try{await et.confirm("确定要删除这个 MCP 服务器吗?","确认",{type:"warning"}),await A.delete(`/api/admin/mcp-servers/${F}`),b.success("删除成功"),r()}catch(X){X!=="cancel"&&b.error("删除失败: "+((($=(i=X.response)==null?void 0:i.data)==null?void 0:$.error)||X.message))}}function R(F){switch(F){case"active":return"success";case"error":return"danger";case"inactive":return"info";default:return"warning"}}function K(F){return m.value.some(i=>{var $,X;return(($=i.command)==null?void 0:$.includes(F))||((X=i.args)==null?void 0:X.includes(F))})}function H(){window.open("https://mcp.so/servers","_blank")}async function x(F){var E,oe;if(K(F.package)){b.info("该服务器已添加");return}const i=F.installCommand.split(" "),$=i[0],X=i.slice(1).join(" "),G={name:F.name,description:F.description,type:"custom",transport:F.transport||"stdio",command:$,args:X,is_enabled:!0};try{await A.post("/api/admin/mcp-servers",G),b.success(`已添加 ${F.name}`),r()}catch(Q){b.error("添加失败: "+(((oe=(E=Q.response)==null?void 0:E.data)==null?void 0:oe.error)||Q.message))}}function B(F){h.value=F,y.value=!0}function D(){h.value&&(navigator.clipboard.writeText(h.value.installCommand),b.success("已复制到剪贴板"))}async function U(){var F,i;try{const $=JSON.parse(u.value);if(!$.name){b.error("JSON 缺少必需字段: name");return}const X={name:$.name,description:$.description||"",type:"custom",transport:$.transport||"stdio",command:$.command||"",args:$.args||"",url:$.url||"",env_vars:$.env_vars?JSON.stringify(typeof $.env_vars=="object"?[$.env_vars]:$.env_vars):"",is_enabled:$.is_enabled!==void 0?$.is_enabled:!0};await A.post("/api/admin/mcp-servers",X),b.success("服务器导入成功"),C.value=!1,u.value="",r()}catch($){$ instanceof SyntaxError?b.error("JSON 格式错误: "+$.message):b.error("导入失败: "+(((i=(F=$.response)==null?void 0:F.data)==null?void 0:i.error)||$.message))}}return be(()=>{r(),o()}),(F,i)=>{const $=a("el-option"),X=a("el-select"),G=a("el-form-item"),E=a("el-input"),oe=a("el-switch"),Q=a("el-button"),re=a("el-form"),me=a("el-card"),ie=a("el-col"),ce=a("el-table-column"),ke=a("el-tag"),De=a("el-table"),ve=a("el-row"),W=a("el-tab-pane"),Z=a("el-icon"),Ve=a("el-alert"),xe=a("el-empty"),ae=a("el-tabs"),ee=a("el-descriptions-item"),Y=a("el-descriptions"),P=a("el-dialog");return n(),k("div",null,[e(ae,{modelValue:c.value,"onUpdate:modelValue":i[11]||(i[11]=ne=>c.value=ne),type:"border-card"},{default:t(()=>[e(W,{label:"我的服务器",name:"my-servers"},{default:t(()=>[e(ve,{gutter:20},{default:t(()=>[e(ie,{span:8,xs:24},{default:t(()=>[e(me,null,{default:t(()=>[l("h3",null,S(w.value?"编辑 MCP 服务器":"添加 MCP 服务器"),1),e(re,{model:f.value,"label-width":"100px"},{default:t(()=>[e(G,{label:"服务器类型"},{default:t(()=>[e(X,{modelValue:f.value.type,"onUpdate:modelValue":i[0]||(i[0]=ne=>f.value.type=ne),onChange:g},{default:t(()=>[e($,{label:"预设服务器",value:"preset"}),e($,{label:"自定义服务器",value:"custom"})]),_:1},8,["modelValue"])]),_:1}
129),f.value.type==="preset"?(n(),N(G,{key:0,label:"预设服务器"},{default:t(()=>[e(X,{modelValue:f.value.preset_id,"onUpdate:modelValue":i[1]||(i[1]=ne=>f.value.preset_id=ne),onChange:V,placeholder:"选择预设服务器"},{default:t(()=>[(n(!0),k(ue,null,fe(_.value,ne=>(n(),N($,{key:ne.id,label:ne.name,value:ne.id},{default:t(()=>[l("span",null,S(ne.name),1),l("span",fu,S(ne.description),1)]),_:2},1032,["label","value"]))),128))]),_:1},8,["modelValue"])]),_:1})):te("",!0),e(G,{label:"名称"},{default:t(()=>[e(E,{modelValue:f.value.name,"onUpdate:modelValue":i[2]||(i[2]=ne=>f.value.name=ne),disabled:f.value.type==="preset"},null,8,["modelValue","disabled"])]),_:1}),e(G,{label:"描述"},{default:t(()=>[e(E,{modelValue:f.value.description,"onUpdate:modelValue":i[3]||(i[3]=ne=>f.value.description=ne),type:"textarea",disabled:f.value.type==="preset"},null,8,["modelValue","disabled"])]),_:1}),e(G,{label:"传输方式"},{default:t(()=>[e(X,{modelValue:f.value.transport,"onUpdate:modelValue":i[4]||(i[4]=ne=>f.value.transport=ne),disabled:f.value.type==="preset"},{default:t(()=>[e($,{label:"stdio",value:"stdio"}),e($,{label:"SSE",value:"sse"}),e($,{label:"WebSocket",value:"ws"})]),_:1},8,["modelValue","disabled"])]),_:1}),f.value.transport==="stdio"?(n(),k(ue,{key:1},[e(G,{label:"命令"},{default:t(()=>[e(E,{modelValue:f.value.command,"onUpdate:modelValue":i[5]||(i[5]=ne=>f.value.command=ne),disabled:f.value.type==="preset",placeholder:"如: npx"},null,8,["modelValue","disabled"])]),_:1}),e(G,{label:"参数"},{default:t(()=>[e(E,{modelValue:f.value.args,"onUpdate:modelValue":i[6]||(i[6]=ne=>f.value.args=ne),disabled:f.value.type==="preset",placeholder:"如: -y @modelcontextprotocol/server-filesystem /tmp/mcp-files"},null,8,["modelValue","disabled"])]),_:1}),e(G,{label:"环境变量"},{default:t(()=>[e(E,{modelValue:f.value.env_vars,"onUpdate:modelValue":i[7]||(i[7]=ne=>f.value.env_vars=ne),type:"textarea",disabled:f.value.type==="preset",placeholder:'JSON格式: [{"API_KEY":"xxx"}]'},null,8,["modelValue","disabled"])]),_:1})],64)):(n(),N(G,{key:2,label:"URL"},{default:t(()=>[e(E,{modelValue:f.value.url,"onUpdate:modelValue":i[8]||(i[8]=ne=>f.value.url=ne),disabled:f.value.type==="preset",placeholder:"服务器地址"},null,8,["modelValue","disabled"])]),_:1})),e(G,{label:"状态"},{default:t(()=>[e(oe,{modelValue:f.value.is_enabled,"onUpdate:modelValue":i[9]||(i[9]=ne=>f.value.is_enabled=ne),"active-text":"启用","inactive-text":"禁用"},null,8,["modelValue"])]),_:1}),e(G,null,{default:t(()=>[e(Q,{type:"primary",onClick:z},{default:t(()=>[s(S(w.value?"更新":"创建"),1)]),_:1}),w.value?(n(),N(Q,{key:0,onClick:L},{default:t(()=>[...i[19]||(i[19]=[s("取消",-1)])]),_:1})):te("",!0)]),_:1})]),_:1},8,["model"])]),_:1})]),_:1}),e(ie,{span:16,xs:24},{default:t(()=>[e(me,null,{default:t(()=>[i[23]||(i[23]=l("h3",null,"MCP 服务器列表",-1)),e(De,{data:m.value,style:{width:"100%"}},{default:t(()=>[e(ce,{prop:"id",label:"#",width:"60"}),e(ce,{prop:"name",label:"名称",width:"200"}),e(ce,{prop:"type",label:"类型",width:"100"},{default:t(({row:ne})=>[e(ke,{type:ne.type==="preset"?"success":"info",size:"small"},{default:t(()=>[s(S(ne.type==="preset"?"预设":"自定义"),1)]),_:2},1032,["type"])]),_:1}),e(ce,{prop:"transport",label:"传输",width:"80"}),e(ce,{prop:"status",label:"状态",width:"100"},{default:t(({row:ne})=>[e(ke,{type:R(ne.status),size:"small"},{default:t(()=>[s(S(ne.status||"inactive"),1)]),_:2},1032,["type"])]),_:1}),e(ce,{prop:"is_enabled",label:"启用",width:"80"},{default:t(({row:ne})=>[e(oe,{modelValue:ne.is_enabled,"onUpdate:modelValue":we=>ne.is_enabled=we,onChange:we=>O(ne)},null,8,["modelValue","onUpdate:modelValue","onChange"])]),_:1}),e(ce,{label:"操作",width:"280"},{default:t(({row:ne})=>[e(Q,{size:"small",onClick:we=>I(ne.id),loading:v.value===ne.id},{default:t(()=>[...i[20]||(i[20]=[s(" 测试连接 ",-1)])]),_:1},8,["onClick","loading"]),e(Q,{size:"small",onClick:we=>M(ne)},{default:t(()=>[...i[21]||(i[21]=[s("编辑",-1)])]),_:1},8,["onClick"]),e(Q,{size:"small",type:"danger",onClick:we=>j(ne.id)},{default:t(()=>[...i[22]||(i[22]=[s("删除",-1)])]),_:1},8,["onClick"])]),_:1})]),_:1},8,["data"])]),_:1})]),_:1})]),_:1})]),_:1}),e(W,{label:"浏览 mcp.so",name:"browse-mcpso"},{default:t(()=>[e(me,null,{header:t(()=>[l("div",_u,[i[26]||(i[26]=l("h3",null,"探索 mcp.so 服务器",-1)),l("div",yu,[e(Q,{onClick:i[10]||(i[10]=ne=>C.value=!0)},{default:t(()=>[e(Z,null,{default:t(()=>[e(se(kt))]),_:1}),i[24]||(i[24]=s(" JSON 导入 ",-1))]),_:1}),e(Q,{type:"primary",onClick:H,target:"_blank"},{default:t(()=>[e(Z,null,{default:t(()=>[e(se(Dl))]),_:1}
129),i[25]||(i[25]=s(" 访问 mcp.so ",-1))]),_:1})])])]),default:t(()=>[e(Ve,{title:"从 mcp.so 选择热门服务器快速添加",type:"info",closable:!1,style:{"margin-bottom":"20px"}},{default:t(()=>[...i[27]||(i[27]=[s(" mcp.so 是最大的 MCP 服务器注册中心,拥有超过 15,000 个服务器。下面是一些热门推荐。 ",-1)])]),_:1}),e(ve,{gutter:20},{default:t(()=>[(n(!0),k(ue,null,fe(p.value,ne=>(n(),N(ie,{key:ne.id,span:8,xs:24,style:{"margin-bottom":"20px"}},{default:t(()=>[e(me,{shadow:"hover",class:"server-card"},{header:t(()=>[l("div",gu,[l("span",bu,S(ne.name),1),e(ke,{size:"small",type:ne.official?"success":"info"},{default:t(()=>[s(S(ne.official?"官方":"社区"),1)]),_:2},1032,["type"])])]),default:t(()=>[l("div",wu,S(ne.description),1),l("div",ku,[e(ke,{size:"small",style:{"margin-right":"5px"}},{default:t(()=>[s(S(ne.category),1)]),_:2},1024),e(ke,{size:"small",type:"info"},{default:t(()=>[s(S(ne.language),1)]),_:2},1024)]),l("div",hu,[e(Q,{type:"primary",size:"small",onClick:we=>x(ne),disabled:K(ne.package)},{default:t(()=>[e(Z,null,{default:t(()=>[e(se(xl))]),_:1}),s(" "+S(K(ne.package)?"已添加":"快速添加"),1)]),_:2},1032,["onClick","disabled"]),e(Q,{size:"small",onClick:we=>B(ne)},{default:t(()=>[...i[28]||(i[28]=[s(" 详情 ",-1)])]),_:1},8,["onClick"])])]),_:2},1024)]),_:2},1024))),128))]),_:1}),p.value.length===0?(n(),N(xe,{key:0,description:"正在加载服务器列表..."})):te("",!0)]),_:1})]),_:1})]),_:1},8,["modelValue"]),e(P,{modelValue:y.value,"onUpdate:modelValue":i[15]||(i[15]=ne=>y.value=ne),title:"服务器详情",width:"600px"},{default:t(()=>[h.value?(n(),k("div",$u,[l("h3",null,S(h.value.name),1),l("p",null,S(h.value.description),1),e(Y,{column:1,border:""},{default:t(()=>[e(ee,{label:"分类"},{default:t(()=>[s(S(h.value.category),1)]),_:1}),e(ee,{label:"语言"},{default:t(()=>[s(S(h.value.language),1)]),_:1}),e(ee,{label:"官方"},{default:t(()=>[s(S(h.value.official?"是":"否"),1)]),_:1}),e(ee,{label:"安装命令"},{default:t(()=>[e(E,{modelValue:h.value.installCommand,"onUpdate:modelValue":i[12]||(i[12]=ne=>h.value.installCommand=ne),readonly:""},{append:t(()=>[e(Q,{onClick:D},{default:t(()=>[...i[29]||(i[29]=[s("复制",-1)])]),_:1})]),_:1},8,["modelValue"])]),_:1})]),_:1}),l("div",Vu,[e(Q,{type:"primary",onClick:i[13]||(i[13]=ne=>x(h.value))},{default:t(()=>[...i[30]||(i[30]=[s(" 添加到我的服务器 ",-1)])]),_:1}),e(Q,{onClick:i[14]||(i[14]=ne=>y.value=!1)},{default:t(()=>[...i[31]||(i[31]=[s("关闭",-1)])]),_:1})])])):te("",!0)]),_:1},8,["modelValue"]),e(P,{modelValue:C.value,"onUpdate:modelValue":i[18]||(i[18]=ne=>C.value=ne),title:"JSON 导入",width:"700px"},{footer:t(()=>[e(Q,{onClick:i[17]||(i[17]=ne=>C.value=!1)},{default:t(()=>[...i[33]||(i[33]=[s("取消",-1)])]),_:1}),e(Q,{type:"primary",onClick:U},{default:t(()=>[...i[34]||(i[34]=[s("导入",-1)])]),_:1})]),default:t(()=>[e(Ve,{title:"粘贴 MCP 服务器配置 JSON",type:"info",closable:!1,style:{"margin-bottom":"15px"}},{default:t(()=>[...i[32]||(i[32]=[s(" 支持从 mcp.so 或其他来源复制 MCP 服务器配置。JSON 格式示例: ",-1),l("pre",{style:{margin:"10px 0",padding:"10px",background:"#f5f5f5","border-radius":"4px","font-size":"12px"}},`{
130  "name": "My MCP Server",
131  "description": "Server description",
132  "command": "npx",
133  "args": "-y @modelcontextprotocol/server-filesystem /tmp/files",
134  "transport": "stdio",
135  "env_vars": {"API_KEY": "your-key"}
136}`,-1)])]),_:1}),e(E,{modelValue:u.value,"onUpdate:modelValue":i[16]||(i[16]=ne=>u.value=ne),type:"textarea",rows:15,placeholder:"粘贴 MCP 服务器 JSON 配置...",style:{"font-family":"monospace"}},null,8,["modelValue"])]),_:1},8,["modelValue"])])}}}),xu=Ce(Cu,[["__scopeId","data-v-3d58cb85"]]),Du={key:0},Su={key:1},Mu=ge({__name:"TeacherDetail",setup(q){de.extend(pt),de.extend(xt);const c=st(),w=Ie(),v=d(null),y=d([]);be(async()=>{const h=c.params.id;if(!h){w.push("/student");return}try{const u=await A.get(`/api/teachers/${h}`);v.value=u.data;const f=await A.get(`/api/teachers/${h}/courses`);y.value=f.data}catch(u){console.error("获取教师信息失败:",u),b.error("获取教师信息失败"),w.push("/student")}});function C(){w.go(-1)}return(h,u)=>{const f=a("el-page-header"),m=a("el-descriptions-item"),_=a("el-descriptions"),p=a("el-card"),r=a("el-container");return n(),N(r,{style:{padding:"20px","max-width":"1000px",margin:"auto"}},{default:t(()=>[e(p,null,{default:t(()=>[e(f,{onBack:C,content:"教师详情",style:{"margin-bottom":"20px"}}),v.value?(n(),k("div",Du,[e(_,{title:"教师信息",column:1,border:""},{default:t(()=>[e(m,{label:"姓名"},{default:t(()=>[s(S(v.value.name),1)]),_:1}),e(m,{label:"邮箱"},{default:t(()=>[s(S(v.value.email),1)]),_:1})]),_:1})])):(n(),k("div",Su,[...u[0]||(u[0]=[l("p",null,"加载中...",-1)])]))]),_:1})]),_:1})}}}),Uu={class:"institution-dashboard"},Iu={class:"actions-bar"},Tu={class:"stats-container"},Au={class:"chart-container"},zu={class:"teachers-list"},Lu={class:"calendar-toolbar"},Yu=["onClick"],Eu={class:"calendar-day-number"},Ru={class:"calendar-day-slots"},Fu={key:0,class:"timeslots-details"},Bu={key:0},Pu={key:1},Hu={key:2,class:"timeslots-list"},Ou={class:"timeslot-teacher"},qu={class:"timeslot-course"},Nu={class:"timeslot-time"},ju={class:"timeslot-status"},Wu={class:"dialog-footer"},Ku=ge({__name:"InstitutionDashboard",setup(q){const c=d([]),w=d(!0),v=d(null),y=d(""),C=d("");let h=null;Ie();const u=d(new Date),f=d(null),m=d([]),_=d(!1),p=d([]),r=d(!1),o=d(null),g=async()=>{try{const x=await A.get("/api/institution/teachers");c.value=x.data}catch(x){console.error("Failed to fetch teachers:",x)}finally{w.value=!1}},V=async x=>{let B;const D=sessionStorage.getItem("user");D&&(B=JSON.parse(D).id);try{const F=(await A.get(`/api/institutions/${B}/teachers/${x.id}/details`)).data;o.value={...F.user,achievement:F.details.achievement,style:F.details.style,subject:F.details.subject,background:F.details.background,link:F.details.link,role:F.role},r.value=!0}catch(U){console.error("Failed to fetch teacher details:",U),b.error("Failed to fetch teacher details")}},z=async()=>{try{const B=(await A.get("/api/institution/teacher-join-stats")).data,D=Object.keys(B).sort(),U=D.map(F=>B[F]);if(v.value){h&&h.dispose(),h=ut(v.value);const F={tooltip:{trigger:"axis"},xAxis:{type:"category",data:D},yAxis:{type:"value",minInterval:1},series:[{data:U,type:"line",smooth:!0}]};h.setOption(F)}}catch(x){console.error("Failed to fetch join stats:",x)}},M=()=>
136{if(!o.value)return;let x;const B=sessionStorage.getItem("user");B&&(x=JSON.parse(B).id),A.delete(`/api/institutions/${x}/teachers/${o.value.id}`).then(g).then(()=>{r.value=!1,b.success("成功移除教师")})},L=async()=>{if(!o.value)return;let x;const B=sessionStorage.getItem("user");B&&(x=JSON.parse(B).id);try{await A.put(`/api/institutions/${x}/teachers/${o.value.id}/details`,{achievement:o.value.achievement,style:o.value.style,subject:o.value.subject,background:o.value.background,link:o.value.link,role:o.value.role,phone:o.value.phone,email:o.value.email,city:o.value.city}),await A.post(`/api/admin/users/${o.value.id}/remark`,{remark:o.value.remark}),b.success("Teacher information saved successfully"),r.value=!1,await g()}catch(D){console.error("Failed to save teacher information:",D),b.error("Failed to save teacher information")}},I=()=>{const x=sessionStorage.getItem("user");if(x){const B=JSON.parse(x),D=`${window.location.origin}/institution/${B.id}/showcase`;window.open(D,"_blank")}};je(y,x=>{O()});const O=async()=>{try{_.value=!0;const x=await A.get("/api/institution/teachers-timeslots",{params:{teacher_id:y.value}});p.value=x.data||[],f.value=""}catch(x){console.error("Failed to fetch teachers timeslots:",x),b.error("获取教师课时信息失败")}finally{_.value=!1}},j=x=>p.value.filter(B=>de(B.start).format("YYYY-MM-DD")===x),R=x=>{f.value=x.day,K(x.day)},K=x=>{m.value=j(x)},H=x=>de(x).format("HH:mm");return be(()=>{g(),z(),O()}),(x,B)=>{const D=a("el-button"),U=a("el-tag"),F=a("el-table-column"),i=a("el-table"),$=a("el-calendar"),X=a("el-form-item"),G=a("el-input"),E=a("el-option"),oe=a("el-select"),Q=a("el-form"),re=a("el-dialog"),me=Ee("loading");return n(),k("div",Uu,[B[27]||(B[27]=l("h1",null,"Institution Dashboard",-1)),l("div",Iu,[e(D,{type:"primary",onClick:I,icon:"Share"},{default:t(()=>[...B[15]||(B[15]=[s(" 分享教师页面 ",-1)])]),_:1})]),l("div",Tu,[l("div",Au,[B[16]||(B[16]=l("h2",null,"Teacher Joining Trends",-1)),l("div",{ref_key:"chartContainer",ref:v,style:{width:"100%",height:"400px"}},null,512)]),l("div",zu,[B[21]||(B[21]=l("h2",null,"Your Teachers",-1)),Me((n(),N(i,{data:c.value,style:{width:"100%"}},{default:t(()=>[e(F,{prop:"name",label:"姓名",width:"150"},{default:t(({row:ie})=>[e(U,{onClick:ce=>{y.value=ie.id,C.value=ie.name}},{default:t(()=>[s(S(ie.name),1)]),_:2},1032,["onClick"])]),_:1}),e(F,{prop:"email",label:"Email"}),e(F,{prop:"city",label:"城市"}),e(F,{prop:"institutionRole",label:"角色"},{default:t(({row:ie})=>[ie.institutionRole==="teacher"?(n(),N(U,{key:0,type:"primary"},{default:t(()=>[...B[17]||(B[17]=[s("老师",-1)])]),_:1})):te("",!0),ie.institutionRole==="manager"?(n(),N(U,{key:1,type:"success"},{default:t(()=>[...B[18]||(B[18]=[s("管理员",-1)])]),_:1})):te("",!0),ie.institutionRole==="todo"?(n(),N(U,{key:2,type:"warning"},{default:t(()=>[...B[19]||(B[19]=[s("待审核",-1)])]),_:1})):te("",!0)]),_:1}),e(F,{label:"操作"},{default:t(({row:ie})=>[e(D,{size:"small",onClick:ce=>V(ie)},{default:t(()=>[...B[20]||(B[20]=[s("查看详情",-1)])]),_:1},8,["onClick"])]),_:1})]),_:1},8,["data"])),[[me,w.value]])])]),l("div",null,[B[23]||(B[23]=l("h2",null,"老师空闲课时查看",-1)),l("div",null,[l("div",Lu,[e(D,{onClick:B[0]||(B[0]=ie=>{y.value=""})},{default:t(()=>[...B[22]||(B[22]=[s("刷新",-1)])]),_:1}),p.value.length>0?(n(),N(U,{key:0},{default:t(()=>[s(S(p.value.length),1)]),_:1})):te("",!0),C.value!==""?(n(),N(U,{key:1,closable:"",onClose:B[1]||(B[1]=ie=>{C.value="",y.value=""})},{default:t(()=>[s(S(C.value),1)]),_:1})):te("",!0)]),e($,{modelValue:u.value,"onUpdate:modelValue":B[2]||(B[2]=ie=>u.value=ie)},{"date-cell":t(({data:ie})=>[l("div",{class:"calendar-day",onClick:ce=>R(ie)},[l("div",Eu,S(ie.day.split("-")[2]),1),l("div",Ru,[(n(!0),k(ue,null,fe(j(ie.day),ce=>(n(),k("div",{key:ce.id,class:Ye(["slot-indicator",{booked:ce.booked}])},null,2))),128))])],8,Yu)]),_:1},8,["modelValue"]),f.value?(n(),k("div",Fu,[l("h3",null,S(f.value)+" 的课时安排",1),_.value?(n(),k("div",Bu,"加载中...")):m.value.length===0?(n(),k("div",Pu,"该日期没有可用课时")):(n(),k("div",Hu,[(n(!0),k(ue,null,fe(m.value,ie=>(n(),k("div",{key:ie.id,class:Ye(["timeslot-item",{booked:ie.booked}])},[l("div",Ou,S(ie.teacherName),1),l("div",qu,S(ie.courseTitle),1),l("div",Nu,S(H(ie.start))+" - "+S(H(ie.end)),1),l("div",ju,[e(U,{type:ie.booked?"danger":"success"},{default:t(()=>[s(S(ie.booked?"已预约":"空闲"),1)]),_:2},1032,["type"])])],2))),128))]))])):te("",!0)])]),e(re,{modelValue:r.value,"onUpdate:modelValue":B[14]||(B[14]=ie=>r.value=ie),title:"老师详情",width:"50%"},{footer:t(()=>[l("span",Wu,[e(D,{onClick:B[13]||(B[13]=ie=>r.value=!1)},{default:t(()=>[...B[24]||(B[24]=[s("取消",-1)])]),_:1}),e(D,{type:"danger",onClick:M},{default:t(()=>[...B[25]||(B[25]=[s("移除",-1)])]),_:1}),e(D,{type:"primary",onClick:L},{default:t(()=>[...B[26]||(B[26]=[s("保存",-1)])]),_:1})])]),default:t(()=>[o.value?(n(),N(Q,{key:0,"label-width":"auto"},{default:t(()=>[e(X,{label:"Name"},{default:t(()=>[l("span",null,S(o.value.name),1)]),_:1}),e(X,{label:"Email"},{default:t(()=>[e(G,{modelValue:o.value.email,"onUpdate:modelValue":B[3]||(B[3]=ie=>o.value.email=ie)},null,8,["modelValue"])]),_:1}),e(X,{label:"电话"},{default:t(()=>[e(G,{modelValue:o.value.phone,"onUpdate:modelValue":B[4]||(B[4]=ie=>o.value.phone=ie)},null,8,["modelValue"])]),_:1}),e(X,{label:"城市"},{default:t(()=>[e(G,{modelValue:o.value.city,"onUpdate:modelValue":B[5]||(B[5]=ie=>o.value.city=ie)},null,8,["modelValue"])]),_:1}),e(X,{label:"角色"},{default:t(()=>[e(oe,{modelValue:o.value.role,"onUpdate:modelValue":B[6]||(B[6]=ie=>o.value.role=ie),placeholder:"Select role"},{default:t(()=>
136[e(E,{label:"老师",value:"teacher"}),e(E,{label:"管理员",value:"manager"}),e(E,{label:"待审核",value:"todo"})]),_:1},8,["modelValue"])]),_:1}),e(X,{label:"教学科目"},{default:t(()=>[e(G,{modelValue:o.value.subject,"onUpdate:modelValue":B[7]||(B[7]=ie=>o.value.subject=ie),placeholder:"教学科目"},null,8,["modelValue"])]),_:1}),e(X,{label:"教学背景"},{default:t(()=>[e(G,{modelValue:o.value.background,"onUpdate:modelValue":B[8]||(B[8]=ie=>o.value.background=ie),type:"textarea",autosize:{minRows:2,maxRows:4},placeholder:"Enter teacher's background"},null,8,["modelValue"])]),_:1}),e(X,{label:"教学风格"},{default:t(()=>[e(G,{modelValue:o.value.style,"onUpdate:modelValue":B[9]||(B[9]=ie=>o.value.style=ie),type:"textarea",autosize:{minRows:2,maxRows:4},placeholder:"Enter teacher's teaching style"},null,8,["modelValue"])]),_:1}),e(X,{label:"教学成就"},{default:t(()=>[e(G,{modelValue:o.value.achievement,"onUpdate:modelValue":B[10]||(B[10]=ie=>o.value.achievement=ie),type:"textarea",autosize:{minRows:2,maxRows:4},placeholder:"Enter teacher's achievement"},null,8,["modelValue"])]),_:1}),e(X,{label:"个人链接"},{default:t(()=>[e(G,{modelValue:o.value.link,"onUpdate:modelValue":B[11]||(B[11]=ie=>o.value.link=ie)},null,8,["modelValue"])]),_:1}),e(X,{label:"备注"},{default:t(()=>[e(G,{modelValue:o.value.remark,"onUpdate:modelValue":B[12]||(B[12]=ie=>o.value.remark=ie),type:"textarea",autosize:{minRows:2,maxRows:4},placeholder:"Enter remark for this teacher"},null,8,["modelValue"])]),_:1})]),_:1})):te("",!0)]),_:1},8,["modelValue"])])}}}),Gu=Ce(Ku,[["__scopeId","data-v-34682634"]]),Ju={class:"institution-showcase"},Xu={class:"institution-header"},Qu={class:"header-content"},Zu={class:"institution-slogan"},ed={class:"main-content"},td={key:0,class:"loading-placeholder"},ld={key:1},ad={key:0,class:"empty-state"},od={key:1,class:"teachers-grid"},nd={class:"teacher-content"},sd={class:"teacher-header"},rd={class:"teacher-avatar"},id={key:0,class:"avatar-placeholder"},ud={class:"teacher-basic-info"},dd={class:"teacher-name"},cd={class:"teacher-subject"},pd={key:0,class:"experience-tag"},md={class:"teacher-details"},vd={key:0,class:"teacher-extra-info"},fd={key:0,class:"info-item"},_d={class:"info-content"},yd={key:1,class:"info-item"},gd={class:"info-content"},bd={key:2,class:"info-item"},wd={class:"info-content"},kd={key:0,class:"teacher-location"},hd={key:0},$d={key:1},Vd={key:2},Cd={class:"teacher-id"},xd={class:"contact-section"},Dd={class:"contact-content"},Sd={class:"contact-item"},Md={class:"contact-text"},Ud={class:"contact-location"},Id={class:"contact-item"},Td={class:"contact-text"},Ad={class:"contact-phone"},zd=ge({__name:"InstitutionShowcase",setup(q){const c=st(),w=Ie(),v=d(null),y=d({name:"",remark:"",phone:""}),C=d([]),h=d([]),u=d(!0);be(()=>{const _=c.params.institutionId;_?(v.value=parseInt(_),m(),f()):w.push("/")});const f=async()=>{if(v.value)try{const _=await A.get(`/api/public/institutions/${v.value}/managers`);h.value=_.data}catch(_){console.error("获取管理人员失败:",_)}},m=async()=>{if(v.value)try{const _=await A.get(`/api/public/institutions/${v.value}`);y.value=_.data;const p=await A.get(`/api/public/institutions/${v.value}/teachers`);C.value=p.data}catch(_){console.error("获取教师列表失败:",_)}finally{u.value=!1}};return(_,p)=>{const r=a("el-icon"),o=a("el-tag");return n(),k("div",Ju,[l("header",Xu,[l("div",Qu,[p[0]||(p[0]=l("h1",{class:"institution-title"},"优秀教师团队",-1)),l("p",Zu,S(y.value.remark||"我们拥有一支经验丰富、教学水平高超的教师团队,致力于为学生提供最优质的教育服务"),1)])]),l("div",ed,[u.value?(n(),k("div",td,[...p[1]||(p[1]=[l("div",{class:"spinner"},null,-1),l("p",null,"教师信息加载中...",-1)])])):(n(),k("div",ld,[C.value.length===0?(n(),k("div",ad,[e(r,{class:"empty-icon"},{default:t(()=>[e(se(Sl))]),_:1}),p[2]||(p[2]=l("p",null,"该机构暂无教师信息",-1))])):(n(),k("div",od,[(n(!0),k(ue,null,fe(C.value,g=>(n(),k("div",{key:g.id,class:"teacher-card"},[l("div",nd,[l("div",sd,[l("div",rd,[g.avatar?te("",!0):(n(),k("div",id,[e(r,{class:"contact-icon"},{default:t(()=>[e(se(_t))]),_:1})]))]),l("div",ud,[l("h3",dd,S(g.name),1),l("p",cd,[e(o,{size:"small",class:"subject-tag"},{default:t(()=>[s(S(g.info.subject||"全科教师"),1)]),_:2},1024),g.yearsOfExperience?(n(),k("span",pd,S(g.yearsOfExperience)+"年教龄 ",1)):te("",!0)])])]),l("div",md,[g.info?(n(),k("div",vd,[g.info.background?(n(),k("div",fd,[p[3]||(p[3]=l("h4",{class:"info-title"},"教学背景",-1)),l("p",_d,S(g.info.background),1)])):te("",!0),g.info.style?(n(),k("div",yd,[p[4]||(p[4]=l("h4",{class:"info-title"},"教学风格",-1)),l("p",gd,S(g.info.style),1)])):te("",!0),g.info.achievement?(n(),k("div",bd,[p[5]||(p[5]=l("h4",{class:"info-title"}
136,"教学成果",-1)),l("p",wd,S(g.info.achievement),1)])):te("",!0)])):te("",!0)]),g.city||g.region?(n(),k("div",kd,[e(r,{class:"location-icon"},{default:t(()=>[e(se(Ml))]),_:1}),l("span",null,[g.city?(n(),k("span",hd,S(g.city),1)):te("",!0),g.city&&g.region?(n(),k("span",$d,",")):te("",!0),g.region?(n(),k("span",Vd,S(g.region),1)):te("",!0)])])):te("",!0),l("div",Cd,"#"+S(g.id),1)])]))),128))]))]))]),l("div",xd,[l("div",Dd,[p[8]||(p[8]=l("h2",{class:"section-title"},"联系我们",-1)),(n(!0),k(ue,null,fe(h.value,g=>(n(),k("div",{class:"contact-info",key:g.id},[l("div",Sd,[e(r,{class:"contact-icon"},{default:t(()=>[e(se(_t))]),_:1}),l("div",Md,[p[6]||(p[6]=l("h4",null,"地区负责人",-1)),l("p",null,S(g.name),1),l("p",Ud,S(g.city),1)])]),l("div",Id,[e(r,{class:"contact-icon"},{default:t(()=>[e(se(Ul))]),_:1}),l("div",Td,[p[7]||(p[7]=l("h4",null,"联系电话",-1)),l("p",Ad,S(g.phone),1)])])]))),128))])])])}}}),Ld=Ce(zd,[["__scopeId","data-v-3afb60ce"]]),Yd={class:"note-detail"},Ed={class:"card-header"},Rd={key:0,class:"note-display"},Fd={class:"note-info"},Bd={class:"create-time"},Pd=["innerHTML"],Hd={class:"actions"}
136,Od={key:1,class:"note-edit"},qd={class:"toolbar"},Nd={class:"actions"},jd=["data-note-title"],Wd={class:"print-header"},Kd={class:"print-metadata"},Gd=["innerHTML"],Jd=ge({__name:"NoteDetail",setup(q){const c=st(),w=Ie(),v=new Jt,y=d({id:0,content:"",is_public:!1,created_at:""}),C=d(!1),h=d({content:"",is_public:!1,fontSize:"16px"});be(()=>{u()});async function u(){try{const z=c.params.id,M=await A.get(`/api/notes/${z}`);y.value=M.data,y.value.font_size=M.data.font_size||"16px"}catch(z){console.error("Failed to load note:",z),w.back()}}function f(){w.back()}function m(){h.value.content=y.value.content,h.value.is_public=y.value.is_public,h.value.fontSize=y.value.font_size||"16px",C.value=!0}function _(){C.value=!1}async function p(){try{const z={booking_id:y.value.booking_id,content:h.value.content,is_public:h.value.is_public,font_size:h.value.fontSize};await A.put(`/api/notes/${y.value.id}`,z),y.value.content=h.value.content,y.value.is_public=h.value.is_public,y.value.font_size=h.value.fontSize,C.value=!1}catch(z){console.error("Failed to save note:",z),alert("保存笔记失败")}}async function r(){if(confirm("确定要删除这条笔记吗?"))try{await A.delete(`/api/notes/${y.value.id}`),w.back()}catch(z){console.error("Failed to delete note:",z),alert("删除笔记失败")}}function o(z){return v.render(z)}function g(z){return de(z).format("YYYY-MM-DD HH:mm")}function V(){window.print()}return(z,M)=>{const L=a("el-page-header"),I=a("el-tag"),O=a("el-button"),j=a("el-option"),R=a("el-select"),K=a("el-input"),H=a("el-form-item"),x=a("el-scrollbar"),B=a("el-radio"),D=a("el-radio-group"),U=a("el-form"),F=a("el-card");return n(),k("div",Yd,[e(F,{class:"note-card"},{header:t(()=>[l("div",Ed,[e(L,{onBack:f,content:C.value?"编辑笔记":"查看笔记"},null,8,["content"])])]),default:t(()=>[C.value?(n(),k("div",Od,[e(U,{model:h.value,"label-width":"80px",class:"note-edit-form"},{default:t(()=>[e(x,{class:"note-editor-scrollbar"},{default:t(()=>[e(H,{label:"笔记内容"},{default:t(()=>[l("div",qd,[M[6]||(M[6]=l("span",null,"字体大小: ",-1)),e(R,{modelValue:h.value.fontSize,"onUpdate:modelValue":M[0]||(M[0]=i=>h.value.fontSize=i),placeholder:"选择字体大小",size:"small",style:{width:"120px","margin-right":"10px"}},{default:t(()=>[e(j,{label:"小",value:"14px"}),e(j,{label:"中",value:"16px"}),e(j,{label:"大",value:"18px"}),e(j,{label:"超大",value:"24px"})]),_:1},8,["modelValue"])]),e(K,{modelValue:h.value.content,"onUpdate:modelValue":M[1]||(M[1]=i=>h.value.content=i),type:"textarea",autosize:"{ minRows: 10 }",style:ft({fontSize:h.value.fontSize||"16px"}),placeholder:"支持Markdown格式"},null,8,["modelValue","style"])]),_:1})]),_:1}),e(H,{label:"可见性"},{default:t(()=>[e(D,{modelValue:h.value.is_public,"onUpdate:modelValue":M[2]||(M[2]=i=>h.value.is_public=i)},{default:t(()=>[e(B,{label:!0},{default:t(()=>[...M[7]||(M[7]=[s("公开",-1)])]),_:1}),e(B,{label:!1},{default:t(()=>[...M[8]||(M[8]=[s("私有",-1)])]),_:1})]),_:1},8,["modelValue"])]),_:1})]),_:1},8,["model"]),l("div",Nd,[e(O,{onClick:_},{default:t(()=>[...M[9]||(M[9]=[s("取消",-1)])]),_:1}),e(O,{type:"primary",onClick:p},{default:t(()=>[...M[10]||(M[10]=[s("保存",-1)])]),_:1})])])):(n(),k("div",Rd,[l("div",Fd,[e(I,{type:y.value.is_public?"success":"info"},{default:t(()=>[s(S(y.value.is_public?"公开":"私有"),1)]),_:1},8,["type"]),l("span",Bd,S(g(y.value.created_at)),1)]),l("div",{class:"note-content",innerHTML:o(y.value.content)}
136,null,8,Pd),l("div",Hd,[y.value.is_editable?(n(),N(O,{key:0,type:"primary",onClick:m},{default:t(()=>[...M[3]||(M[3]=[s("编辑",-1)])]),_:1})):te("",!0),e(O,{type:"primary",onClick:V,ref:"printButton"},{default:t(()=>[...M[4]||(M[4]=[s("打印",-1)])]),_:1},512),y.value.is_editable?(n(),N(O,{key:1,type:"danger",onClick:r},{default:t(()=>[...M[5]||(M[5]=[s("删除",-1)])]),_:1})):te("",!0)])]))]),_:1}),C.value?te("",!0):(n(),k("div",{key:0,id:"print-area",class:"print-area","data-note-title":`笔记 - ${g(y.value.created_at)}`},[l("div",Wd,[M[11]||(M[11]=l("h2",null,"笔记详情",-1)),l("div",Kd,[l("span",{class:Ye(["print-tag",y.value.is_public?"public":"private"])},S(y.value.is_public?"公开":"私有"),3),l("span",null,S(g(y.value.created_at)),1)])]),l("div",{class:"print-content",innerHTML:o(y.value.content)},null,8,Gd)],8,jd))])}}}),Xd=Ce(Jd,[["__scopeId","data-v-b23d08f8"]]),Qd={class:"vocabulary-leaderboard"},Zd={class:"header"},ec={key:0,class:"loading"},tc={key:1,class:"leaderboard-container"},lc={class:"masked-name"},ac={key:2,class:"no-data"},oc=ge({__name:"VocabularyLeaderboard",setup(q){const c=Ie(),w=d([]),v=d(!0),y=()=>{c.go(-1)},C=u=>u===1?"rank-first":u===2?"rank-second":u===3?"rank-third":"rank-other",h=async()=>{try{v.value=!0;const u=await A.get("/api/vocabulary/leaderboard");w.value=u.data}catch(u){console.error("加载排行榜失败:",u)}finally{v.value=!1}};return be(()=>{h()}),(u,f)=>{const m=a("el-button"),_=a("el-spinner"),p=a("el-table-column"),r=a("el-table");return n(),k("div",Qd,[l("div",Zd,[f[1]||(f[1]=l("h2",null,"单词学习排行榜",-1)),e(m,{onClick:y,type:"primary",plain:""},{default:t(()=>[...f[0]||(f[0]=[s("返回",-1)])]),_:1})]),v.value?(n(),k("div",ec,[e(_),f[2]||(f[2]=l("p",null,"加载排行榜中...",-1))])):w.value.length>0?(n(),k("div",tc,[e(r,{data:w.value,style:{width:"100%"},stripe:""},{default:t(()=>[e(p,{prop:"rank",label:"排名",width:"80",align:"center"},{default:t(o=>[l("span",{class:Ye(C(o.$index+1))},S(o.$index+1),3)]),_:1}),e(p,{prop:"studentName",label:"用户名"},{default:t(o=>[l("span",lc,S(o.row.student_name),1)]),_:1}),e(p,{prop:"words_learned",label:"掌握单词数",align:"center"})]),_:1},8,["data"])])):(n(),k("div",ac,[...f[3]||(f[3]=[l("p",null,"暂无排行榜数据",-1)])]))])}}}),nc=Ce(oc,[["__scopeId","data-v-34cdfb3d"]]),sc={class:"leaderboard-page"},rc=ge({__name:"VocabularyLeaderboardPage",setup(q){return(c,w)=>{const v=a("el-card");return n(),k("div",sc,[e(v,null,{default:t(()=>[e(nc)]),_:1})])}}}),ic=Ce(rc,[["__scopeId","data-v-f56cf905"]]),uc={key:1,style:{"margin-top":"20px","text-align":"center"}},dc={class:"api-providers-header"},cc={key:1},pc={style:{"margin-top":"20px","text-align":"center"}},mc={class:"dialog-footer"},vc={class:"dialog-footer"},fc=ge({__name:"Profile",setup(q){const c=Ie(),w=d(null),v=d(localStorage.getItem("profile_active_tab")||"basic"),y=Ae({school:"",grade:""}),C=d(!1),h=d(),u=d([]),f=d(!1),m=d(!1),_=d(!1),p=Ae({id:0,name:"",provider:"",token:"",model:"",base_url:"",tokenLink:"",is_default:!1,model_text_to_image:"",model_vlm:""});je(()=>p.provider,F=>{F==="siliconflow"?(p.tokenLink="https://cloud.siliconflow.cn/i/Hpf6kA2O",p.base_url=p.base_url||"https://api.siliconflow.cn/v1",p.name=p.name||"我的SiliconFlow账户"):(p.model="",p.base_url="",p.tokenLink="")});const r=d(),o=d([]),g=d([]),V=d([]),z=async()=>{var F,i,$,X,G,E;try{const oe=await A.get("/api/dictionary/models?model_sub_type=chat",{params:{token:p.token,base_url:p.base_url}});o.value=oe.data.data||[]}catch(oe){console.error("Load models error:",oe),b.error("加载模型列表失败: "+(((i=(F=oe.response)==null?void 0:F.data)==null?void 0:i.error)||oe.message))}try{const oe=await A.get("/api/dictionary/models?model_sub_type=text-to-image",{params:{token:p.token,base_url:p.base_url}});g.value=oe.data.data||[]}catch(oe){console.error("Load text-to-image models error:",oe),b.error("加载文本转图片模型列表失败: "+(((X=($=oe.response)==null?void 0:$.data)==null?void 0:X.error)||oe.message))}try{const Q=(await A.get("/api/dictionary/models",{params:{token:p.token,base_url:p.base_url}})).data.data||[];V.value=Q.filter(re=>re.id.toLowerCase().includes("vlm")||re.id.toLowerCase().includes("vision")||re.id.toLowerCase().includes("qwen2-vl")||re.id.toLowerCase().includes("llava"))}catch(oe){console.error("Load VLM models error:",oe),b.error("加载视觉模型列表失败: "+(((E=(G=oe.response)==null?void 0:G.data)==null?void 0:E.error)||oe.message))}};function M(){p.token&&p.base_url&&z()}function L(){p.token&&p.base_url&&z()}be(()=>{const F=sessionStorage.getItem("user");if(!F){c.push("/login");return}try{w.value=JSON.parse(F)}catch{b.error("用户信息解析失败"),c.push("/login")}});function I(){w.value.role==="student"&&(y.school=w.value.school||"",y.grade=w.value.grade||"",C.value=!0)}async function O(){try{const F=await A.put("/api/user/student-info",y),i=sessionStorage.getItem("user");if(i){const $=JSON.parse(i);$.school=F.data.school,$.grade=F.data.grade,sessionStorage.setItem("user",JSON.stringify($)),w.value=$}C.value=!1,b.success("信息更新成功")}catch{b.error("信息更新失败")}}async function j(){f.value=!0;try{const F=await A.get("/api/user/api-providers");u.value=F.data}catch{b.error("加载AI提供商失败")}finally{f.value=!1}}function R(){_.value=!1,Object.assign(p,{id:0,name:"",provider:"",token:"",model:"",base_url:"",is_default:!1,model_text_to_image:""}),m.value=!0}function K(F){_.value=!0,Object.assign(p,F),m.value=!0}function H(F){et.confirm(`确定要删除AI提供商 "${F.name}
136" 吗?`,"确认删除",{confirmButtonText:"确定",cancelButtonText:"取消",type:"warning"}).then(async()=>{try{await A.delete(`/api/user/api-providers/${F.id}`),b.success("删除成功"),j()}catch{b.error("删除失败")}}).catch(()=>{})}async function x(){r.value&&await r.value.validate(async F=>{if(F)try{_.value?(await A.put(`/api/user/api-providers/${p.id}`,p),b.success("更新成功")):(await A.post("/api/user/api-providers",p),b.success("添加成功")),m.value=!1,j()}catch{b.error(_.value?"更新失败":"添加失败")}})}function B(F){return parseFloat(F.toFixed(2))}function D(){c.back()}const U=async()=>{var i;if(!((i=w.value)!=null&&i.invite_code)){b.error("邀请码不存在");return}const F=`${window.location.origin}/register?inviteCode=${w.value.invite_code}`;try{await navigator.clipboard.writeText(F),b.success("邀请链接已复制到剪贴板")}catch{const X=document.createElement("textarea");X.value=F,document.body.appendChild(X),X.select(),document.execCommand("copy"),document.body.removeChild(X),b.success("邀请链接已复制到剪贴板")}};return je(v,F=>{localStorage.setItem("profile_active_tab",F),F==="apiProviders"&&u.value.length===0&&j()}),(F,i)=>{const $=a("el-descriptions-item"),X=a("el-tag"),G=a("el-descriptions"),E=a("el-button"),oe=a("el-tab-pane"),Q=a("el-table-column"),re=a("el-table"),me=a("el-card"),ie=a("el-tabs"),ce=a("el-input"),ke=a("el-form-item"),De=a("el-option"),ve=a("el-select"),W=a("el-form"),Z=a("el-dialog"),Ve=a("el-link"),xe=a("el-switch"),ae=a("el-main"),ee=Ee("loading");return n(),N(ae,{class:"main-content"},{default:t(()=>[e(me,null,{header:t(()=>[...i[15]||(i[15]=[l("div",{class:"profile-header"},[l("h2",null,"个人主页")],-1)])]),default:t(()=>[e(ie,{modelValue:v.value,"onUpdate:modelValue":i[0]||(i[0]=Y=>v.value=Y),class:"profile-tabs"},{default:t(()=>[e(oe,{label:"基本信息",name:"basic"},{default:t(()=>[w.value?(n(),N(G,{key:0,column:1,border:""},{default:t(()=>[e($,{label:"姓名"},{default:t(()=>[s(S(w.value.name),1)]),_:1}),e($,{label:"邮箱"},{default:t(()=>[s(S(w.value.email),1)]),_:1}),e($,{label:"角色"},{default:t(()=>[s(S(w.value.role),1)]),_:1}),e($,{label:"我的邀请码"},{default:t(()=>[e(X,{type:"success",size:"large",onClick:U,style:{cursor:"pointer"}},{default:t(()=>[s(S(w.value.invite_code),1)]),_:1})]),_:1}),w.value.registered_by_invite_code?(n(),N($,{key:0,label:"注册邀请码"},{default:t(()=>[s(S(w.value.registered_by_invite_code),1)]),_:1})):te("",!0),e($,{label:"账户余额"},{default:t(()=>[s(S(B(w.value.balance))+" 元",1)]),_:1}),w.value.role==="student"?(n(),N($,{key:1,label:"学校"},{default:t(()=>[s(S(w.value.school||"未填写"),1)]),_:1})):te("",!0),w.value.role==="student"?(n(),N($,{key:2,label:"年级"},{default:t(()=>[s(S(w.value.grade||"未填写"),1)]),_:1})):te("",!0)]),_:1})):te("",!0),w.value&&w.value.role==="student"?(n(),k("div",uc,[e(E,{type:"primary",onClick:I},{default:t(()=>[...i[16]||(i[16]=[s("编辑学校年级信息",-1)])]),_:1})])):te("",!0)]),_:1}),e(oe,{label:"AI提供商",name:"apiProviders"},{default:t(()=>[e(me,{class:"api-providers-card"},{header:t(()=>[l("div",dc,[e(E,{type:"primary",size:"small",onClick:R},{default:t(()=>[...i[17]||(i[17]=[s("添加提供商",-1)])]),_:1})])]),default:t(()=>[Me((n(),N(re,{data:u.value,style:{width:"100%"},"empty-text":"暂无AI提供商"},{default:t(()=>[e(Q,{prop:"name",label:"名称"}),e(Q,{prop:"provider",label:"提供商"}),e(Q,{prop:"model",label:"默认模型"}),e(Q,{prop:"model_text_to_image",label:"文本转图片模型"}),e(Q,{prop:"base_url",label:"基础URL"}),e(Q,{label:"默认"},{default:t(Y=>[Y.row.is_default?(n(),N(X,{key:0,type:"success"},{default:t(()=>[...i[18]||(i[18]=[s("是",-1)])]),_:1})):(n(),k("span",cc,"-"))]),_:1}),e(Q,{label:"操作",width:"150"},{default:t(Y=>[e(E,{size:"small",onClick:P=>K(Y.row)},{default:t(()=>[...i[19]||(i[19]=[s("编辑",-1)])]),_:1},8,["onClick"]),e(E,{size:"small",type:"danger",onClick:P=>H(Y.row)},{default:t(()=>[...i[20]||(i[20]=[s("删除",-1)])]),_:1},8,["onClick"])]),_:1})]),_:1},8,["data"])),[[ee,f.value]])]),_:1})]),_:1})]),_:1},8,["modelValue"]),l("div",pc,[e(E,{onClick:D},{default:t(()=>[...i[21]||(i[21]=[s("返回",-1)])]),_:1})])]),_:1}),e(Z,{modelValue:C.value,"onUpdate:modelValue":i[4]||(i[4]=Y=>C.value=Y),title:"编辑学校年级信息",width:"500px"},{footer:t(()=>[l("span",mc,[e(E,{onClick:i[3]||(i[3]=Y=>C.value=!1)},{default:t(()=>[...i[22]||(i[22]=[s("取消",-1)])]),_:1}),e(E,{type:"primary",onClick:O},{default:t(()=>[...i[23]||(i[23]=[s("保存",-1)])]),_:1})])]),default:t(()=>[e(W,{model:y,"label-width":"100px",ref_key:"studentFormRef",ref:h},{default:t(()=>[e(ke,{label:"学校"},{default:t(()=>[e(ce,{modelValue:y.school,"onUpdate:modelValue":i[1]||(i[1]=Y=>y.school=Y),placeholder:"请输入学校名称"},null,8,["modelValue"])]),_:1}),e(ke,{label:"年级"},{default:t(()=>[e(ve,{modelValue:y.grade,"onUpdate:modelValue":i[2]||(i[2]=Y=>y.grade=Y),placeholder:"请选择年级",style:{width:"100%"}},{default:t(()=>[(n(!0),k(ue,null,fe(se(rt),Y=>(n(),N(De,{label:Y,value:Y,key:Y},null,8,["label","value"]))),128))]),_:1},8,["modelValue"])]),_:1})]),_:1},8,["model"])]),_:1},8,["modelValue"]),e(Z,{modelValue:m.value,"onUpdate:modelValue":i[14]||(i[14]=Y=>m.value=Y),title:(_.value?"编辑":"添加")+"AI提供商",width:"600px"},{footer:t(()=>[l("span",vc,[e(E,{onClick:i[13]||(i[13]=Y=>m.value=!1)},{default:t(()=>[...i[25]||(i[25]=[s("取消",-1)])]),_:1}),e(E,{type:"primary",onClick:x},{default:t(()=>[...i[26]||(i[26]=[s("保存",-1)])]),_:1})])]),default:t(()=>[e(W,{model:p,"label-width":"auto",ref_key:"providerFormRef",ref:r},{default:t(()=>[e(ke,{label:"名称",prop:"name",rules:[{required:!0,message:"请输入名称",trigger:"blur"}]},{default:t(()=>[e(ce,{modelValue:p.name,"onUpdate:modelValue":i[5]||(i[5]=Y=>
136p.name=Y),placeholder:"例如:我的OpenAI账户"},null,8,["modelValue"])]),_:1}),e(ke,{label:"提供商",prop:"provider",rules:[{required:!0,message:"请选择提供商",trigger:"change"}]},{default:t(()=>[e(ve,{modelValue:p.provider,"onUpdate:modelValue":i[6]||(i[6]=Y=>p.provider=Y),placeholder:"请选择提供商",style:{width:"100%"}},{default:t(()=>[e(De,{label:"SiliconFlow",value:"siliconflow"}),e(De,{label:"自定义",value:"custom"})]),_:1},8,["modelValue"])]),_:1}),e(ke,{label:"API密钥",prop:"token",rules:[{required:!0,message:"请输入API密钥",trigger:"blur"}]},{default:t(()=>[e(ce,{modelValue:p.token,"onUpdate:modelValue":i[7]||(i[7]=Y=>p.token=Y),type:"password",placeholder:"请输入API密钥","show-password":"",onBlur:M},null,8,["modelValue"]),p.tokenLink?(n(),N(Ve,{key:0,class:"ml-2",href:p.tokenLink,target:"_blank"},{default:t(()=>[...i[24]||(i[24]=[s(" 获取API密钥 ",-1)])]),_:1},8,["href"])):te("",!0)]),_:1}),e(ke,{label:"基础URL",prop:"base_url"},{default:t(()=>[e(ce,{modelValue:p.base_url,"onUpdate:modelValue":i[8]||(i[8]=Y=>p.base_url=Y),placeholder:"例如:https://api.siliconflow.cn/v1",onBlur:L},null,8,["modelValue"])]),_:1}),e(ke,{label:"默认模型",prop:"model"},{default:t(()=>[e(ve,{modelValue:p.model,"onUpdate:modelValue":i[9]||(i[9]=Y=>p.model=Y),placeholder:"请选择默认模型",style:{width:"100%"}},{default:t(()=>[(n(!0),k(ue,null,fe(o.value,Y=>(n(),N(De,{key:Y.id,label:Y.id,value:Y.id},null,8,["label","value"]))),128))]),_:1},8,["modelValue"])]),_:1}),e(ke,{label:"文本转图片模型",prop:"model_text_to_image"},{default:t(()=>[e(ve,{modelValue:p.model_text_to_image,"onUpdate:modelValue":i[10]||(i[10]=Y=>p.model_text_to_image=Y),placeholder:"请选择默认模型",style:{width:"100%"}},{default:t(()=>[(n(!0),k(ue,null,fe(g.value,Y=>(n(),N(De,{key:Y.id,label:Y.id,value:Y.id},null,8,["label","value"]))),128))]),_:1},8,["modelValue"])]),_:1}),e(ke,{label:"视觉识别模型(VLM)",prop:"model_vlm"},{default:t(()=>[e(ve,{modelValue:p.model_vlm,"onUpdate:modelValue":i[11]||(i[11]=Y=>p.model_vlm=Y),placeholder:"请选择VLM模型",style:{width:"100%"}},{default:t(()=>[(n(!0),k(ue,null,fe(V.value,Y=>(n(),N(De,{key:Y.id,label:Y.id,value:Y.id},null,8,["label","value"]))),128))]),_:1},8,["modelValue"])]),_:1}),e(ke,{label:"设为默认"},{default:t(()=>[e(xe,{modelValue:p.is_default,"onUpdate:modelValue":i[12]||(i[12]=Y=>p.is_default=Y)},null,8,["modelValue"])]),_:1})]),_:1},8,["model"])]),_:1},8,["modelValue","title"])]),_:1})}}}),_c=Ce(fc,[["__scopeId","data-v-9b33d142"]]),yc=q=>{dt(()=>{if(q){const c=q.innerHTML,w=document.body.innerHTML;document.body.innerHTML=`
137        <html>
138          <head>
139            <title>错题试卷</title>
140            <style>
141              body { font-family: Arial, sans-serif; font-size: 14px; }
142              .options p { margin: 5px 0; }
143              .mistake-details p { margin: 8px 0; }
144              @media print {
145                body { margin: 15px; }
146                .print-area { max-width: 100%; }
147              }
148            </style>
149          </head>
150          <body>
151            ${c}
152          </body>
153        </html>
154      `,window.print(),document.body.innerHTML=w,location.reload()}})},gc={class:"search-section"},bc={class:"card-header"},wc={class:"pagination-container"},kc=["innerHTML"],hc={key:0},$c={class:"options"},Vc=["innerHTML"],Cc=["innerHTML"],xc=["innerHTML"],Dc=["innerHTML"],Sc={key:0},Mc={key:0},Uc={class:"dialog-footer"},Ic=ge({__name:"MistakeBrowser",setup(q){const c=d(!1),w=d(!1),v=d(null),y=d([]),C=Ae({keyword:"",subject:"",question_type:"",status:"",grade:""}),h=()=>{C.keyword="",C.subject="",C.question_type="",C.status="",C.grade="",_()},u=d({data:[],total:0,page_size:0}),f=()=>{if(y.value.length===0){b.warning("请先选择要预览的错题");return}c.value=!0},m=o=>{y.value=o},_=async()=>{const o=await A.get("/api/admin/mistakes",{params:{...C,page:u.value.page,page_size:u.value.page_size}});u.value=o.data,console.log(u.value)},p=o=>{u.value.page_size=o,_()},r=o=>{u.value.page=o,_()};return be(()=>{_()}),(o,g)=>{const V=a("el-input"),z=a("el-col"),M=a("el-option"),L=a("el-select"),I=a("el-button"),O=a("el-row"),j=a("el-table-column"),R=a("el-table"),K=a("el-pagination"),H=a("el-card"),x=a("el-switch"),B=a("el-dialog");return n(),k(ue,null,[l("div",gc,[e(O,{gutter:20},{default:t(()=>[e(z,{span:4,xs:24},{default:t(()=>[e(V,{modelValue:C.keyword,"onUpdate:modelValue":g[0]||(g[0]=D=>C.keyword=D),placeholder:"知识点",clearable:"",onKeyup:Je(_,["enter"])},null,8,["modelValue"])]),_:1}),e(z,{span:4,xs:24},{default:t(()=>[e(L,{modelValue:C.grade,"onUpdate:modelValue":g[1]||(g[1]=D=>C.grade=D),placeholder:"年级",clearable:"",style:{width:"100%"},onChange:_},{default:t(()=>[(n(!0),k(ue,null,fe(se(rt),D=>(n(),N(M,{label:D,value:D,key:D},null,8,["label","value"]))),128))]),_:1},8,["modelValue"])]),_:1}),e(z,{span:4,xs:24},{default:t(()=>[e(L,{modelValue:C.subject,"onUpdate:modelValue":g[2]||(g[2]=D=>C.subject=D),placeholder:"学科",clearable:"",style:{width:"100%"},onChange:_},{default:t(()=>[(n(!0),k(ue,null,fe(se($t),D=>(n(),N(M,{label:D,value:D,key:D},null,8,["label","value"]))),128))]),_:1},8,["modelValue"])]),_:1}),e(z,{span:4,xs:24},{default:t(()=>[e(L,{modelValue:C.question_type,"onUpdate:modelValue":g[3]||(g[3]=D=>C.question_type=D),placeholder:"题型",clearable:"",style:{width:"100%"},onChange:_},{default:t(()=>[(n(!0),k(ue,null,fe(se(It),D=>(n(),N(M,{label:D,value:D,key:D},null,8,["label","value"]))),128))]),_:1},8,["modelValue"])]),_:1}),e(z,{span:8,xs:24},{default:t(()=>[e(I,{type:"primary",onClick:_},{default:t(()=>[...g[10]||(g[10]=[s("搜索",-1)])]),_:1}),e(I,{onClick:h},{default:t(()=>
154[...g[11]||(g[11]=[s("重置",-1)])]),_:1})]),_:1})]),_:1})]),e(H,null,Ot({default:t(()=>[e(R,{data:u.value.data,onSelectionChange:m,"show-overflow-tooltip":""},{default:t(()=>[e(j,{type:"selection"}),e(j,{prop:"topic",label:"知识点"}),e(j,{prop:"grade",label:"年级"}),e(j,{prop:"subject",label:"学科"}),e(j,{prop:"question_type",label:"题目类型"}),e(j,{prop:"stem",label:"题干"})]),_:1},8,["data"]),l("div",wc,[e(K,{"current-page":u.value.page,"onUpdate:currentPage":g[4]||(g[4]=D=>u.value.page=D),"page-size":u.value.page_size,"onUpdate:pageSize":g[5]||(g[5]=D=>u.value.page_size=D),"page-sizes":[10,20,50,100],total:u.value.total,layout:"total, sizes, prev, pager, next, jumper",onSizeChange:p,onCurrentChange:r},null,8,["current-page","page-size","total"])])]),_:2},[y.value.length!==0?{name:"header",fn:t(()=>[l("div",bc,[e(I,{type:"success",size:"small",onClick:f},{default:t(()=>[...g[12]||(g[12]=[s(" 生成试卷 ",-1)])]),_:1})])]),key:"0"}:void 0]),1024),e(B,{modelValue:c.value,"onUpdate:modelValue":g[9]||(g[9]=D=>c.value=D),title:"试卷预览",width:"80%",class:"preview-dialog"},{header:t(()=>[e(x,{modelValue:w.value,"onUpdate:modelValue":g[6]||(g[6]=D=>w.value=D),"active-text":"显示答案","inactive-text":"隐藏答案"},null,8,["modelValue"])]),footer:t(()=>[l("span",Uc,[e(I,{onClick:g[7]||(g[7]=D=>c.value=!1)},{default:t(()=>[...g[18]||(g[18]=[s("关闭",-1)])]),_:1}),e(I,{type:"primary",onClick:g[8]||(g[8]=D=>se(yc)(v.value))},{default:t(()=>[...g[19]||(g[19]=[s("打印试卷",-1)])]),_:1})])]),default:t(()=>[l("div",{class:"print-area",ref_key:"printAreaRef",ref:v},[g[17]||(g[17]=l("h2",{style:{"text-align":"center"}},"错题试卷",-1)),(n(!0),k(ue,null,fe(y.value,(D,U)=>(n(),k("div",{class:"mistake-item",key:D.id},[l("div",null,[s(S(U+1)+". ("+S(D.subject)+") "+S(D.question_type)+" - ",1),l("span",{innerHTML:se(Qe)(D.stem)},null,8,kc)]),D.question_type==="单选题"?(n(),k("div",hc,[l("table",$c,[l("tbody",null,[l("tr",null,[l("td",null,[g[13]||(g[13]=s("A. ",-1)),l("span",{innerHTML:se(Qe)(D.option_a)},null,8,Vc)]),l("td",null,[g[14]||(g[14]=s("B. ",-1)),l("span",{innerHTML:se(Qe)(D.option_b)},null,8,Cc)])]),l("tr",null,[l("td",null,[g[15]||(g[15]=s("C. ",-1)),l("span",{innerHTML:se(Qe)(D.option_c)},null,8,xc)]),l("td",null,[g[16]||(g[16]=s("D. ",-1)),l("span",{innerHTML:se(Qe)(D.option_d)},null,8,Dc)])])])])])):te("",!0)]))),128)),w.value?(n(),k("div",Sc,[(n(!0),k(ue,null,fe(y.value,(D,U)=>(n(),k("span",{class:"answer",key:D.id},[D.question_type==="单选题"?(n(),k("span",Mc,S(D.answer),1)):te("",!0)]))),128))])):te("",!0)],512)]),_:1},8,["modelValue"])],64)}}}),gt=dl({history:cl(),routes:[{path:"/",component:ql},{path:"/login",component:Ql},{path:"/register",component:ma},{path:"/reset-password",component:ka},{path:"/forgot-password",component:Ma},{path:"/student",component:Ur},{path:"/teacher",component:oi},{path:"/teacher/:id/detail",name:"TeacherDetail",component:Mu,props:!0},{path:"/institution",component:Gu},{path:"/institution/:institutionId/showcase",name:"InstitutionShowcase",component:Ld,props:!0},{path:"/note/:id",name:"NoteDetail",component:Xd,props:!0},{path:"/vocabulary-leaderboard",component:ic},{path:"/profile",component:_c},{path:"/calendar",component:zt},{path:"/ai-dictionary",component:yt},{path:"/admin",component:si,redirect:"/admin/users",children:[{path:"users",component:ii},{path:"users/:id",name:"AdminUserDetail",component:ci,props:!0},{path:"courses",component:pi},{path:"stats",component:mi},{path:"students",component:fi},{path:"hour_records",component:bi},{path:"google_analytics",component:hi},{path:"advertisements",component:Mi},{path:"meta_tags",component:Yi},{path:"vocabulary",component:vu},{path:"mcp-servers",component:xu},{path:"system",component:tu},{path:"mistake_browser",component:Ic}]}]});gt.beforeEach((q,c,w)=>{q.path==="/student"&&q.query.tab==="dictation"||q.path==="/reset-password"||q.path==="/forgot-password"||q.path.endsWith("/showcase")?w():q.path!=="/login"&&q.path!=="/register"&&q.path!=="/vocabulary-leaderboard"&&q.path!=="/"&&!sessionStorage.getItem("token")?w("/login"):w()});const A=Ll.create({baseURL:"/",timeout:2e4});A.interceptors.request.use(q=>{const c=sessionStorage.getItem("token");return c&&(q.headers={...q.headers||{},Authorization:`Bearer ${c}`}),q});A.interceptors.response.use(q=>q,q=>(q.response&&q.response.status===403&&(b.error("无权限访问该资源,请重新登录"),sessionStorage.removeItem("token"),sessionStorage.removeItem("user"),gt.push("/login")),Promise.reject(q)));async function Tc(){try{const q=await A.get("/api/admin/google-analytics");return q.data.measurement_id?q.data:null}catch(q){return console.error("Failed to fetch Google Analytics configuration:",q),null}}const Ac=ge({__name:"GoogleAnalytics",setup(q){let c=!1;be(async()=>
154{if(!c)try{const v=await Tc();v&&v.measurement_id&&(w(v.measurement_id),c=!0)}catch(v){console.error("Failed to initialize Google Analytics:",v)}});function w(v){const y=document.createElement("script");y.async=!0,y.src=`https://www.googletagmanager.com/gtag/js?id=${v}`,document.head.appendChild(y);const C=document.createElement("script");C.text=`
155    window.dataLayer = window.dataLayer || [];
156    function gtag(){dataLayer.push(arguments);}
157    gtag('js', new Date());
158    gtag('config', '${v}');
159  `,document.head.appendChild(C)}return(v,y)=>te("",!0)}}),zc={key:0,class:"advertisements-container"},Lc={key:0,class:"ad-header"},Yc={key:1,class:"ad-content"},Ec={key:0,class:"ad-image"},Rc=["src","alt"],Fc=["innerHTML"],Bc={key:1,class:"ad-link"},Pc=ge({__name:"Advertisement",setup(q){const c=d([]),w=d(window.innerWidth<=768),v=d(new Set),y=()=>{w.value=window.innerWidth<=768};be(async()=>{window.addEventListener("resize",y),await C()}),ct(()=>{window.removeEventListener("resize",y)});const C=async()=>{try{const f=await A.get("/api/advertisements");c.value=f.data.filter(m=>!v.value.has(m.id))}catch(f){console.error("Failed to load advertisements:",f)}},h=f=>{v.value.add(f),c.value=c.value.filter(m=>m.id!==f)},u=f=>{window.open(f,"_blank")};return setInterval(C,5*60*1e3),(f,m)=>{const _=a("el-icon"),p=a("el-button");return c.value.length>0?(n(),k("div",zc,[(n(!0),k(ue,null,fe(c.value,r=>(n(),k("div",{key:r.id,class:Ye(["advertisement-card",{mobile:w.value}])},[r.content.startsWith("<script")?te("",!0):(n(),k("div",Lc,[l("h3",null,S(r.title),1),e(p,{class:"close-btn",type:"danger",size:"small",onClick:o=>h(r.id),circle:""},{default:t(()=>[e(_,null,{default:t(()=>[e(se(Il))]),_:1})]),_:1},8,["onClick"])])),r.content.startsWith("<script")?te("",!0):(n(),k("div",Yc,[r.image_url?(n(),k("div",Ec,[l("img",{src:r.image_url,alt:r.title},null,8,Rc)])):te("",!0),l("div",{class:"ad-text",innerHTML:r.content},null,8,Fc),r.link_url?(n(),k("div",Bc,[e(p,{type:"primary",onClick:o=>u(r.link_url)},{default:t(()=>[...m[0]||(m[0]=[s("查看详情",-1)])]),_:1},8,["onClick"])])):te("",!0)]))],2))),128))])):te("",!0)}}}),Hc=Ce(Pc,[["__scopeId","data-v-092b55b5"]]),Oc={class:"ai-assistant"},qc={key:0,class:"no-provider-state"},Nc={class:"setup-hints"},jc={key:0,class:"provider-section"},Wc={key:0,class:"model-info"},Kc={class:"message-content"},Gc={key:0,class:"message-avatar"},Jc={class:"message-text"},Xc={key:0,class:"command-result"},Qc={class:"command-details"},Zc={key:1,class:"clarification-result"},ep={class:"clarification-details"},tp={key:2,class:"text-content"},lp={key:1,class:"message-avatar user"},ap={key:0,class:"message assistant"},op={class:"message-content"},np={class:"message-avatar"},sp={class:"quick-actions"},rp={class:"input-area"},ip={class:"input-actions"},up=ge({__name:"AiAssistant",props:{visible:{type:Boolean}},emits:["update:visible"],setup(q,{emit:c}){const w=Ie(),v=q,y=c,C=d(v.visible),h=d(),u=d([]),f=d([]),m=d(""),_=d(!1),p=d(!1),r=d(),o=d(!1),g=d("600px"),V=d(!1),z=d(""),M=Le(()=>h.value?u.value.find(D=>D.id===h.value):null),L=[{label:"添加成绩",prompt:"数学85分"},{label:"查看成绩",prompt:"查看今天的成绩"},{label:"添加日程",prompt:"明天下午2点开会"},{label:"查看日程",prompt:"查看今天的日程"}];je(()=>v.visible,D=>{C.value=D}),je(C,D=>{y("update:visible",D),D?(I(),window.addEventListener("resize",I)):window.removeEventListener("resize",I)});const I=()=>{o.value=window.innerWidth<=768,o.value?V.value=!0:(V.value=!1,g.value="600px")},O=async()=>{p.value=!0;try{const D=await A.get("/api/user/api-providers");u.value=D.data;const U=D.data.find(F=>F.is_default);U?h.value=U.id:D.data.length>0&&(h.value=D.data[0].id)}catch(D){console.error("Failed to load API providers:",D)}finally{p.value=!1}},j=()=>{u.value.length===0&&O(),f.value.length===0&&f.value.push({role:"assistant",content:`您好!我是 AI 智能助手,可以帮您:
160
161• 添加/修改/删除考试成绩
162• 查询考试成绩
163• 添加/查询日程安排
164• 其他系统操作
165
166请用自然语言告诉我您需要什么帮助?`})},R=()=>{dt(()=>{r.value&&(r.value.scrollTop=r.value.scrollHeight)})},K=async()=>{var U,F;const D=m.value.trim();if(!(!D||!h.value)){f.value.push({role:"user",content:D}),m.value="",R(),_.value=!0;try{const $=(await A.post("/api/ai/chat",{provider_id:h.value,message:D,history:f.value.slice(-10),conversation_id:z.value})).data;$.conversation_id&&(z.value=$.conversation_id),$.type==="command"?f.value.push({role:"assistant",type:"command",content:$.message||"操作已完成"}):$.type==="clarification"?f.value.push({role:"assistant",type:"clarification",content:$.message||"请确认您的选择"}):f.value.push({role:"assistant",content:$.message||$.response||"抱歉,我没有理解您的请求。"})}catch(i){console.error("AI chat error:",i),b.error(((F=(U=i.response)==null?void 0:U.data)==null?void 0:F.error)||"AI 助手暂时无法响应ï¼
166Œè¯·ç¨åŽå†è¯•"),f.value.push({role:"assistant",content:"抱歉,发生了错误,请稍后再试。"})}finally{_.value=!1,R()}}},H=D=>{m.value=D.prompt,K()},x=()=>{},B=()=>{C.value=!1,w.push("/profile#ai-provider")};return(D,U)=>{const F=a("el-button"),i=a("el-result"),$=a("el-alert"),X=a("el-option"),G=a("el-select"),E=a("el-tag"),oe=a("avatar"),Q=a("el-icon"),re=a("user"),me=a("el-input"),ie=a("el-dialog");return n(),N(ie,{modelValue:C.value,"onUpdate:modelValue":U[3]||(U[3]=ce=>C.value=ce),title:"AI 智能助手",width:g.value,"close-on-click-modal":!1,onOpen:j,fullscreen:V.value,class:"ai-assistant-dialog"},{default:t(()=>[l("div",Oc,[!p.value&&u.value.length===0?(n(),k("div",qc,[e(i,{icon:"warning",title:"未配置 AI 提供商","sub-title":"您需要先配置 AI 提供商才能使用智能助手功能"},{extra:t(()=>[e(F,{type:"primary",onClick:B},{default:t(()=>[...U[4]||(U[4]=[s("前往配置",-1)])]),_:1}),e(F,{onClick:U[0]||(U[0]=ce=>C.value=!1)},{default:t(()=>[...U[5]||(U[5]=[s("取消",-1)])]),_:1})]),_:1}),l("div",Nc,[U[7]||(U[7]=l("h4",null,"配置步骤:",-1)),U[8]||(U[8]=l("ol",null,[l("li",null,'点击上方"前往配置"按钮进入个人主页'),l("li",null,'在"API 提供商"部分添加您的 AI 服务配置'),l("li",null,"支持 OpenAI、SiliconFlow 等多种 AI 服务"),l("li",null,"配置完成后即可使用智能助手")],-1)),e($,{type:"info",closable:!1,"show-icon":""},{title:t(()=>[...U[6]||(U[6]=[l("div",{style:{"font-size":"13px"}},[s(" 您可以使用以下服务:"),l("br"),s(" • "),l("strong",null,"OpenAI"),s(" - 支持 GPT-4、GPT-3.5 等模型"),l("br"),s(" • "),l("strong",null,"SiliconFlow"),s(" - 国内访问友好的 AI 服务"),l("br"),s(" • 其他兼容 OpenAI API 的服务 ")],-1)])]),_:1})])])):(n(),k(ue,{key:1},[u.value.length>0?(n(),k("div",jc,[e(G,{modelValue:h.value,"onUpdate:modelValue":U[1]||(U[1]=ce=>h.value=ce),placeholder:"选择 AI 提供商",onChange:x,size:"small",style:{width:"200px"}},{default:t(()=>[(n(!0),k(ue,null,fe(u.value,ce=>(n(),N(X,{key:ce.id,label:ce.name,value:ce.id},null,8,["label","value"]))),128))]),_:1},8,["modelValue"]),M.value?(n(),k("div",Wc,[e(E,{size:"small",type:"info"},{default:t(()=>[s(S(M.value.model||"默认模型"),1)]),_:1})])):te("",!0)])):te("",!0),l("div",{class:"chat-container",ref_key:"chatContainer",ref:r},[(n(!0),k(ue,null,fe(f.value,(ce,ke)=>(n(),k("div",{key:ke,class:Ye(["message",ce.role])},[l("div",Kc,[ce.role==="assistant"?(n(),k("div",Gc,[e(Q,null,{default:t(()=>[e(oe)]),_:1})])):te("",!0),l("div",Jc,[ce.type==="command"?(n(),k("div",Xc,[e(E,{type:"success",size:"small"},{default:t(()=>[...U[9]||(U[9]=[s("已执行",-1)])]),_:1}),l("div",Qc,S(ce.content),1)])):ce.type==="clarification"?(n(),k("div",Zc,[e(E,{type:"warning",size:"small"},{default:t(()=>[...U[10]||(U[10]=[s("需要确认",-1)])]),_:1}),l("div",ep,S(ce.content),1)])):(n(),k("div",tp,S(ce.content),1))]),ce.role==="user"?(n(),k("div",lp,[e(Q,null,{default:t(()=>[e(re)]),_:1})])):te("",!0)])],2))),128)),_.value?(n(),k("div",ap,[l("div",op,[l("div",np,[e(Q,{class:"is-loading"},{default:t(()=>[e(se(_))]),_:1})]),U[11]||(U[11]=l("div",{class:"message-text"},[l("div",{class:"typing-indicator"},[l("span"),l("span"),l("span")])],-1))])])):te("",!0)],512),l("div",sp,[(n(),k(ue,null,fe(L,ce=>e(E,{key:ce.label,onClick:ke=>H(ce),class:"quick-action-tag",effect:"plain",size:"small"},{default:t(()=>[s(S(ce.label),1)]),_:2},1032,["onClick"])),64))]),l("div",rp,[e(me,{modelValue:m.value,"onUpdate:modelValue":U[2]||(U[2]=ce=>m.value=ce),type:"textarea",rows:2,placeholder:"用自然语言描述您的需求,例如:'添加一场数学考试,得分85分'...",onKeydown:Je(Oe(K,["ctrl"]),["enter"]),disabled:_.value||!h.value},null,8,["modelValue","onKeydown","disabled"]),l("div",ip,[U[13]||(U[13]=l("span",{class:"hint"},"Ctrl + Enter 发送",-1)),e(F,{type:"primary",onClick:K,loading:_.value,disabled:!m.value.trim()||!h.value,size:"small"},{default:t(()=>[...U[12]||(U[12]=[s(" 发送 ",-1)])]),_:1},8,["loading","disabled"])])])],64))])]),_:1},8,["modelValue","width","fullscreen"])}}}),dp=Ce(up,[["__scopeId","data-v-e7dec39b"]]),cp={id:"app"},pp={key:0,class:"user-info"},mp={class:"user-name"},vp=ge({__name:"App",setup(q){const c=Ie(),w=d(null),v=d(!1),y=()=>{const u=sessionStorage.getItem("token"),f=sessionStorage.getItem("user"),m=window.location.href;if(!(m.endsWith("/student?tab=dictation")||m.indexOf("/reset-password")!=-1||m.endsWith("/showcase")||window.location.pathname==="/"||window.location.pathname==="/register")){if(!u||!f){c.push("/login");return}try{w.value=JSON.parse(f)}catch{b.error("用户信息解析失败"),c.push("/login")}}};be(()=>y()),window.addEventListener("loginSuccess",()=>y());function C(){sessionStorage.removeItem("token"),sessionStorage.removeItem("user"),c.push("/")}function h(u){u==="profile"?c.push("/profile"):u==="logout"?C():u==="ai-assistant"&&(v.value=!0)}return(u,f)=>{const m=a("el-icon"),_=a("el-dropdown-item"),p=a("el-dropdown-menu"),r=a("el-dropdown"),o=a("el-button"),g=a("el-header"),V=a("router-view"),z=
166a("el-main"),M=a("el-container");return n(),k("div",cp,[e(Ac),e(Hc),u.$route.path!=="/login"&&u.$route.path!=="/"?(n(),N(M,{key:0,class:"layout-container"},{default:t(()=>[e(g,{class:"header"},{default:t(()=>[f[5]||(f[5]=l("div",{class:"logo"},"开放课程系统",-1)),w.value?(n(),k("div",pp,[e(r,{onCommand:h},{dropdown:t(()=>[e(p,null,{default:t(()=>[e(_,{command:"ai-assistant"},{default:t(()=>[e(m,null,{default:t(()=>[e(se(Tl))]),_:1}),f[1]||(f[1]=l("span",null,"AI 智能助手",-1))]),_:1}),e(_,{command:"profile"},{default:t(()=>[e(m,null,{default:t(()=>[e(se(w))]),_:1}),f[2]||(f[2]=l("span",null,"个人主页",-1))]),_:1}),e(_,{command:"logout",divided:""},{default:t(()=>[e(m,null,{default:t(()=>[e(se(Al))]),_:1}),f[3]||(f[3]=l("span",null,"退出",-1))]),_:1})]),_:1})]),default:t(()=>[l("span",mp,[s(S(w.value.name)+" ("+S(w.value.role)+") ",1),e(m,{class:"el-icon--right"},{default:t(()=>[e(se(Wt))]),_:1})])]),_:1})])):(n(),N(o,{key:1,onClick:C},{default:t(()=>[...f[4]||(f[4]=[s("首页",-1)])]),_:1}))]),_:1}),e(z,{class:"main"},{default:t(()=>[e(V)]),_:1})]),_:1})):(n(),N(V,{key:1})),e(dp,{visible:v.value,"onUpdate:visible":f[0]||(f[0]=L=>v.value=L)},null,8,["visible"])])}}});de.extend(pt);de.extend(xt);const Dt=ul(vp);Dt.use(Yl);for(const[q,c]of Object.entries(zl))Dt.component(q,c);Dt.use(gt);Dt.mount("#app");

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.