const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/index-i50OZQTj.js","assets/index-D9E2kUSE.css"])))=>i.map(i=>d[i]); import{c as u,u as me,d as ue,$ as he,f as I,a0 as q,r as i,g as x,j as e,E as T,B as t,a1 as W,m,k as Z,a2 as pe,T as J,P as ve,I as b,l as je,H as Y,a3 as ge,a4 as ye,a5 as be,a6 as fe,a7 as ke,a8 as Ne,a9 as Ce,aa as _e,ab as we}from"./index-i50OZQTj.js";import{C as ee,a as se,b as ae}from"./card-D8TWS3Zn.js";/** * @license lucide-react v0.475.0 - ISC * * This source code is licensed under the ISC license. * See the LICENSE file in the root directory of this source tree. */const ze=[["path",{d:"M20 6 9 17l-5-5",key:"1gmf2c"}]],te=u("Check",ze);/** * @license lucide-react v0.475.0 - ISC * * This source code is licensed under the ISC license. * See the LICENSE file in the root directory of this source tree. */const Se=[["rect",{width:"14",height:"14",x:"8",y:"8",rx:"2",ry:"2",key:"17jyea"}],["path",{d:"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2",key:"zix9uf"}]],Me=u("Copy",Se);/** * @license lucide-react v0.475.0 - ISC * * This source code is licensed under the ISC license. * See the LICENSE file in the root directory of this source tree. */const Ee=[["path",{d:"M3 12a9 9 0 0 1 9-9 9.75 9.75 0 0 1 6.74 2.74L21 8",key:"v9h5vc"}],["path",{d:"M21 3v5h-5",key:"1q7to0"}],["path",{d:"M21 12a9 9 0 0 1-9 9 9.75 9.75 0 0 1-6.74-2.74L3 16",key:"3uifl3"}],["path",{d:"M8 16H3v5",key:"1cv678"}]],Fe=u("RefreshCw",Ee);/** * @license lucide-react v0.475.0 - ISC * * This source code is licensed under the ISC license. * See the LICENSE file in the root directory of this source tree. */const Ie=[["path",{d:"M2 9a3 3 0 0 1 0 6v2a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2v-2a3 3 0 0 1 0-6V7a2 2 0 0 0-2-2H4a2 2 0 0 0-2 2Z",key:"qn84l0"}],["path",{d:"m9 12 2 2 4-4",key:"dzmm74"}]],qe=u("TicketCheck",Ie);/** * @license lucide-react v0.475.0 - ISC * * This source code is licensed under the ISC license. * See the LICENSE file in the root directory of this source tree. */const Te=[["path",{d:"m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3",key:"wmoenq"}],["path",{d:"M12 9v4",key:"juzpu7"}],["path",{d:"M12 17h.01",key:"p32p05"}]],ne=u("TriangleAlert",Te);/** * @license lucide-react v0.475.0 - ISC * * This source code is licensed under the ISC license. * See the LICENSE file in the root directory of this source tree. */const De=[["path",{d:"M18 21a8 8 0 0 0-16 0",key:"3ypg7q"}],["circle",{cx:"10",cy:"8",r:"5",key:"o932ke"}],["path",{d:"M22 20c0-3.37-2-6.5-4-8a5 5 0 0 0-.45-8.3",key:"10s06x"}]],ie=u("UsersRound",De);function Pe({i:r}){return r.used_by&&r.holder_gone?e.jsx(m,{color:"var(--danger)",children:"已销户"}):r.used_by?e.jsx(m,{color:"var(--text-3)",children:"已使用"}):r.valid?e.jsx(m,{color:"var(--success)",children:"可用"}):e.jsx(m,{color:"var(--warning)",children:"已停用"})}function Ke(){var V,G,X,U;const r=me(),D=ue(),l=he(),f=I({queryKey:["me-admin"],queryFn:async()=>(await Ce(()=>import("./index-i50OZQTj.js").then(a=>a.an),__vite__mapDeps([0,1]))).serverMe(l),enabled:!!q()}),k=I({queryKey:["admin-users"],queryFn:()=>_e(l),enabled:!!q()}),N=I({queryKey:["admin-invites"],queryFn:()=>we(l),enabled:!!q()}),[P,d]=i.useState(""),[re,R]=i.useState(null),[le,C]=i.useState(!1),[v,_]=i.useState(""),[Q,w]=i.useState(""),[de,h]=i.useState(null),[z,S]=i.useState(""),[c,ce]=i.useState("all"),[n,j]=i.useState(null),[K,M]=i.useState(""),[oe,g]=i.useState(!1),y=()=>{r.invalidateQueries({queryKey:["admin-invites"]})},o=s=>d(s.message||"操作失败"),O=x({mutationFn:()=>Ne(l),onSuccess:s=>{var a,p;g(!1),d(""),D("success","演示账号已重建:"+(((a=s.seeded)==null?void 0:a.footprints)??0)+" 条记录 + "+(((p=s.seeded)==null?void 0:p.semesters)??0)+" 学期"),r.invalidateQueries({queryKey:["admin-users"]})},onError:o}),A=x({mutationFn:s=>ke(s,l),onSuccess:s=>{r.invalidateQueries({queryKey:["admin-users"]}),j(null),M(""),d(""),D("success","用户「"+s.username+"」及其全部数据已删除")},onError:o}),L=x({mutationFn:()=>ge(5,l),onSuccess:s=>{y(),d(""),navigator.clipboard.writeText(s.codes.join(` `)).catch(()=>{})},onError:o}),E=x({mutationFn:()=>ye(v.trim(),Q.trim(),l),onSuccess:()=>{y(),C(!1),_(""),w(""),d("")},onError:o}),F=x({mutationFn:s=>be(s.id,s.patch,l),onSuccess:()=>{y(),h(null),d("")},onError:o}),xe=x({mutationFn:s=>fe(s,l),onSuccess:()=>{y(),d("")},onError:o}),$=i.useMemo(()=>{var s;return((s=N.data)==null?void 0:s.invites)??[]},[N.data]),B=i.useMemo(()=>$.filter(s=>c==="valid"?s.valid&&!s.used_by:c==="used"?!!s.used_by&&!s.holder_gone:c==="gone"?!!s.used_by&&!!s.holder_gone:c==="disabled"?!s.valid&&!s.used_by:!0),[$,c]);if(f.data&&!f.data.is_admin)return e.jsx(T,{title:"需要管理员账号",description:"当前登录账号不是管理员。"});const H=s=>{navigator.clipboard.writeText(s.code),R(s.id),setTimeout(()=>R(a=>a===s.id?null:a),1500)};return e.jsxs("div",{className:"mx-auto max-w-[1080px] px-3 py-4 sm:px-6 sm:py-5",children:[e.jsxs("div",{className:"mb-4 flex items-center justify-between",children:[e.jsx("h2",{className:"text-[15px] font-semibold text-ink-1",children:"管理"}),e.jsxs("div",{className:"flex gap-2",children:[e.jsxs(t,{variant:"secondary",onClick:()=>g(!0),children:[e.jsx(ie,{size:13})," 重建演示账号"]}),e.jsxs(t,{variant:"secondary",onClick:()=>{r.invalidateQueries()},children:[e.jsx(Fe,{size:13})," 刷新"]})]})]}),P&&e.jsxs("div",{className:"mb-3 flex items-center justify-between rounded-md border border-danger/30 bg-danger-subtle px-3 py-2 text-[12px] text-danger",children:[e.jsx("span",{children:P}),e.jsx("button",{className:"rounded p-0.5 hover:bg-surface-3",onClick:()=>d(""),"aria-label":"关闭",children:e.jsx(W,{size:13})})]}),e.jsxs(ee,{children:[e.jsx(se,{title:"用户管理("+(((V=k.data)==null?void 0:V.total)??0)+")",extra:e.jsx(ie,{size:14,className:"text-ink-3"})}),e.jsx(ae,{className:"p-0",children:e.jsxs("div",{className:"divide-y divide-line",children:[(((G=k.data)==null?void 0:G.users)??[]).map(s=>{var p;const a=String(s.id)===String(((p=f.data)==null?void 0:p.user_id)??"");return e.jsxs("div",{className:"flex items-center gap-3 px-4 py-2.5",children:[e.jsxs("div",{className:"min-w-0 flex-1",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("span",{className:"truncate text-[13px] font-medium text-ink-1",children:s.username}),s.is_admin&&e.jsx(m,{color:"var(--brand-text)",children:"管理员"}),a&&e.jsx(m,{color:"var(--text-3)",children:"当前登录"})]}),e.jsxs("div",{className:"num mt-0.5 text-[11px] text-ink-3",children:[Z(s.created_at)," · 记录 ",s.records," · 附件 ",s.attachments,"(",pe(s.attachment_bytes||0),")"]})]}),!a&&e.jsxs(t,{size:"sm",variant:"ghost",className:"text-danger hover:bg-danger-subtle",onClick:()=>{j({id:s.id,username:s.username}),M("")},children:[e.jsx(J,{size:13})," 删除"]})]},s.id)}),!(((X=k.data)==null?void 0:X.users)??[]).length&&e.jsx(T,{title:"暂无用户"})]})})]}),e.jsxs(ee,{children:[e.jsx(se,{title:"邀请码("+(((U=N.data)==null?void 0:U.total)??0)+")",extra:e.jsxs("div",{className:"flex gap-1.5",children:[e.jsxs(t,{size:"sm",variant:"secondary",onClick:()=>{C(s=>!s),d("")},children:[e.jsx(ve,{size:13})," 新建"]}),e.jsx(t,{size:"sm",variant:"primary",disabled:L.isPending,onClick:()=>L.mutate(),children:"批量生成 5 个"})]})}),e.jsxs(ae,{className:"p-0",children:[le&&e.jsxs("div",{className:"flex flex-wrap items-end gap-2 border-b border-line bg-surface-2 px-4 py-3",children:[e.jsxs("label",{className:"flex flex-col gap-1",children:[e.jsx("span",{className:"text-[11px] font-medium text-ink-3",children:"邀请码(4-32 位字母数字-_)"}),e.jsx(b,{className:"w-[210px]",value:v,placeholder:"如 XIONG-2025",onChange:s=>_(s.target.value)})]}),e.jsxs("label",{className:"flex flex-col gap-1",children:[e.jsx("span",{className:"text-[11px] font-medium text-ink-3",children:"备注(可选)"}),e.jsx(b,{className:"w-[180px]",value:Q,placeholder:"发给谁 / 用途",onChange:s=>w(s.target.value),onKeyDown:s=>{s.key==="Enter"&&v.trim()&&E.mutate()}})]}),e.jsxs("div",{className:"flex gap-1.5 pb-0.5",children:[e.jsx(t,{size:"sm",variant:"primary",disabled:!v.trim()||E.isPending,onClick:()=>E.mutate(),children:"创建"}),e.jsx(t,{size:"sm",variant:"ghost",onClick:()=>{C(!1),_(""),w("")},children:"取消"})]})]}),e.jsx("div",{className:"flex gap-1 border-b border-line px-4 py-2 text-[12px]",children:[["all","全部"],["valid","可用"],["used","已使用"],["gone","已销户"],["disabled","已停用"]].map(([s,a])=>e.jsx("button",{className:"rounded-md px-2.5 py-1 transition-colors "+(c===s?"bg-brand-subtle font-medium text-brand-text":"text-ink-3 hover:bg-surface-3"),onClick:()=>ce(s),children:a},s))}),B.length?e.jsx("div",{className:"divide-y divide-line max-h-[430px] overflow-y-auto",children:B.map(s=>e.jsxs("div",{className:"flex flex-wrap items-center gap-2 px-4 py-2.5 text-[12.5px]",children:[e.jsx("button",{className:"num shrink-0 cursor-pointer rounded-sm bg-surface-3 px-1.5 py-0.5 font-mono text-[12px] text-ink-1 transition-colors hover:bg-brand-subtle hover:text-brand-text",title:"点击复制",onClick:()=>H(s),children:re===s.id?e.jsxs("span",{className:"inline-flex items-center gap-1 text-success",children:[e.jsx(te,{size:11}),"已复制"]}):s.code}),e.jsx(Pe,{i:s}),de===s.id?e.jsxs("span",{className:"ml-1 flex min-w-0 flex-1 items-center gap-1",children:[e.jsx(b,{className:"h-7 flex-1 text-[12px]",value:z,autoFocus:!0,placeholder:"备注(64 字以内)",onChange:a=>S(a.target.value),onKeyDown:a=>{a.key==="Enter"&&F.mutate({id:s.id,patch:{remark:z}}),a.key==="Escape"&&h(null)}}),e.jsx(t,{size:"icon-sm",variant:"ghost","aria-label":"保存备注",className:"text-success",onClick:()=>F.mutate({id:s.id,patch:{remark:z}}),children:e.jsx(te,{size:13})}),e.jsx(t,{size:"icon-sm",variant:"ghost","aria-label":"取消",className:"text-ink-3",onClick:()=>h(null),children:e.jsx(W,{size:13})})]}):e.jsx("button",{className:"min-w-0 flex-1 truncate text-left text-[12px] text-ink-3 hover:text-ink-2",title:s.remark?"点击编辑备注":s.created_by_name?"由 "+s.created_by_name+" 创建 · 点击添加备注":"点击添加备注",onClick:()=>{h(s.id),S(s.remark??"")},children:s.remark||(s.created_by_name?"由 "+s.created_by_name+" 创建":e.jsx("span",{className:"opacity-60",children:"添加备注…"}))}),s.used_by_name&&e.jsxs("span",{className:"shrink-0 text-ink-3",children:["被 ",s.used_by_name," 使用于 ",Z(s.used_at)]}),e.jsxs("span",{className:"ml-auto flex shrink-0 items-center gap-0.5",children:[e.jsx(t,{size:"icon-sm",variant:"ghost","aria-label":"复制",className:"text-ink-3",onClick:()=>H(s),children:e.jsx(Me,{size:13})}),!s.used_by&&e.jsxs(e.Fragment,{children:[e.jsx(t,{size:"icon-sm",variant:"ghost","aria-label":"编辑备注",className:"text-ink-3",onClick:()=>{h(s.id),S(s.remark??"")},children:e.jsx(je,{size:13})}),e.jsx(t,{size:"sm",variant:"ghost",className:s.valid?"text-ink-3 hover:text-warning":"text-ink-3 hover:text-success",onClick:()=>F.mutate({id:s.id,patch:{valid:!s.valid}}),children:s.valid?"停用":"启用"})]}),e.jsx(t,{size:"icon-sm",variant:"ghost","aria-label":"删除",className:"text-ink-3 hover:text-danger",onClick:()=>{window.confirm("删除邀请码 "+s.code+"?此操作不可恢复。")&&xe.mutate(s.id)},children:e.jsx(J,{size:13})})]})]},s.id))}):e.jsx(T,{icon:e.jsx(qe,{size:32,strokeWidth:1.5}),title:"暂无符合条件的邀请码",description:"新建自定义邀请码,或批量生成后发给需要注册的用户。"})]})]}),e.jsx(Y,{open:!!n,onClose:()=>j(null),width:460,title:"删除用户(高危操作)",footer:e.jsxs(e.Fragment,{children:[e.jsx(t,{variant:"ghost",onClick:()=>j(null),children:"取消"}),e.jsxs(t,{variant:"primary",className:"!bg-danger !text-white",disabled:K!==(n==null?void 0:n.username)||A.isPending,onClick:()=>n&&A.mutate(n.id),children:[e.jsx(ne,{size:13})," 永久删除"]})]}),children:e.jsxs("div",{className:"flex flex-col gap-3 text-[12.5px]",children:[e.jsxs("div",{className:"flex items-start gap-2 rounded-md border border-danger/30 bg-danger-subtle px-3 py-2.5 text-danger",children:[e.jsx(ne,{size:15,className:"mt-0.5 shrink-0"}),e.jsxs("div",{children:[e.jsx("b",{children:"此操作不可撤销!"}),"将永久删除用户「",n==null?void 0:n.username,"」的全部数据:",e.jsxs("ul",{className:"mt-1 list-disc pl-4 text-[12px] leading-relaxed",children:[e.jsx("li",{children:"账号与登录会话(所有设备将被登出)"}),e.jsx("li",{children:"全部记录、成绩、维度与统计数据"}),e.jsx("li",{children:"全部附件文件(服务器本地与图床 COS 上的副本)"})]})]})]}),e.jsxs("div",{children:[e.jsxs("div",{className:"mb-1.5 text-ink-2",children:["请输入用户名 ",e.jsx("b",{className:"text-danger",children:n==null?void 0:n.username})," 以确认:"]}),e.jsx(b,{value:K,onChange:s=>M(s.target.value),placeholder:(n==null?void 0:n.username)??"",autoFocus:!0})]})]})}),e.jsx(Y,{open:oe,onClose:()=>g(!1),width:440,title:"重建演示账号",footer:e.jsxs(e.Fragment,{children:[e.jsx(t,{variant:"ghost",onClick:()=>g(!1),children:"取消"}),e.jsx(t,{variant:"primary",disabled:O.isPending,onClick:()=>O.mutate(),children:"重建并重新播种"})]}),children:e.jsxs("div",{className:"text-[12.5px] leading-relaxed text-ink-2",children:["将",e.jsx("b",{children:"删除现有 demo 账号及其全部数据"}),",然后重新创建并播种全套虚拟演示数据 (个人信息档案、25 条足迹(含 10 项竞赛获奖与证书附件)、4 学期学科成绩、简历内容)。",e.jsx("div",{className:"mt-2 text-ink-3",children:"demo / demo1234 · 仅影响演示账号,其他用户不受影响。"})]})})]})}export{Ke as AdminPage};