1 line
7.0 KiB
JavaScript
1 line
7.0 KiB
JavaScript
import{C as e,G as t,J as n,L as r,N as i,O as a,S as o,U as s,V as c,_ as l,b as u,c as d,g as f,j as p,m,n as h,p as g,r as _,t as v,u as y,z as b}from"./ui-BjxGELcM.js";import{n as x,t as S}from"./user-round-BD5O3Mh0.js";import{t as C}from"./shield-check-CU6M0J1d.js";import{n as w}from"./index-BsK239Bd.js";var T=[[`path`,{d:`M20 13c0 5-3.5 7.5-7.66 8.95a1 1 0 0 1-.67-.01C7.5 20.5 4 18 4 13V6a1 1 0 0 1 1-1c2 0 4.5-1.2 6.24-2.72a1.17 1.17 0 0 1 1.52 0C14.51 3.81 17 5 19 5a1 1 0 0 1 1 1z`,key:`oel41y`}]],E=e=>r(l,t(e,{iconNode:T,name:`shield`})),D=a(`<div class="flex flex-wrap items-start justify-between gap-4"><div><p class="mono-label text-muted-foreground">users / rbac</p><h1 class="display mt-2 text-4xl sm:text-5xl">用户与角色</h1><p class="mt-3 max-w-xl text-sm text-muted-foreground">基于 Casbin RBAC + 状态管理。对标 SyncTV Root/Admin 分层:仅 Root 可授予 Root;Admin 仅可管理 Viewer/Publisher;封禁用户无法登录与刷新。</p></div><div class="flex items-center gap-2">`),O=a(`<span class="flex items-center gap-2">当前账号已被封禁,部分操作将受限。请联系超管解封。`),k=a(`<div class="flex items-center gap-2 px-5 py-8 text-sm text-muted-foreground">暂无用户数据`),A=a(`<div class="border border-line bg-card/50"><div class="hidden grid-cols-[minmax(0,1fr)_7rem_7rem_16rem] gap-4 border-b border-line/80 px-5 py-3 sm:grid"><span class="micro-label text-muted-foreground">username</span><span class="micro-label text-muted-foreground">role</span><span class="micro-label text-muted-foreground">status</span><span class="micro-label text-right text-muted-foreground">action`),j=a(`<div class="mx-auto max-w-[1400px] space-y-8 px-4 py-8 sm:px-6 sm:py-10">`),M=a(`<span class="flex items-center gap-2">无权限:需要 user:list(管理员及以上)`),N=a(`<span class="inline-flex size-1.5 rounded-full bg-amber-500">`),P=a(`<div><div class="flex min-w-0 items-center gap-3"><span></span><div class=min-w-0><p class="flex items-center gap-2 truncate font-mono text-sm font-medium"></p><p class="micro-label mt-1 text-muted-foreground"></p></div></div><div></div><div class="flex items-center justify-end gap-2">`),F=a(`<span class="flex items-center gap-1 text-xs text-muted-foreground/60">无权操作`),I={root:{label:`超管`,badge:`border-amber-500/40 bg-amber-500/10 text-amber-600`,avatar:`border-amber-500/40 bg-amber-500/10 text-amber-600`},admin:{label:`管理员`,badge:`border-acid-magenta/30 bg-acid-magenta/10 text-acid-magenta`,avatar:`border-acid-magenta/40 bg-acid-magenta/10 text-acid-magenta`},publisher:{label:`发布者`,badge:`border-warning/30 bg-warning/10 text-warning`,avatar:`border-warning/40 bg-warning/10 text-warning`},viewer:{label:`观看者`,badge:`border-acid-cyan/30 bg-acid-cyan/10 text-acid-cyan`,avatar:`border-acid-cyan/40 bg-acid-cyan/10 text-acid-cyan`},guest:{label:`访客`,badge:`border-line bg-transparent text-muted-foreground`,avatar:`border-line bg-muted text-muted-foreground`}};function L(e){return e===`root`?[`viewer`,`publisher`,`admin`,`root`]:e===`admin`?[`viewer`,`publisher`]:[]}var R=()=>{let[t,a]=s([]),[l,T]=s(``),[R,z]=s(``),B=async()=>{try{let e=await f.listUsers();a(e.users||[]),T(``)}catch(e){T(String(e?.message||e))}};b(()=>{g.can(`user:list`)&&B()}),n(()=>{g.isAuthed()&&B()});let V=async(e,t)=>{z(e);try{await f.updateUserRole(e,t),a(n=>n.map(n=>n.username===e?{...n,role:t}:n)),T(``)}catch(e){T(String(e?.message||e))}finally{z(``)}},H=async e=>{let t=e.status===`banned`;if(confirm(t?`解封 ${e.username} ?`:`封禁 ${e.username} ? 封禁后该用户将无法登录`)){z(e.username);try{t?await f.unbanUser(e.username):await f.banUser(e.username),await B()}catch(e){T(String(e?.message||e))}finally{z(``)}}},U=()=>g.role(),W=e=>{let t=U();return t===`root`?e.role!==`root`:t===`admin`?e.role===`viewer`||e.role===`publisher`:!1};return(()=>{var n=j();return o(n,r(d,{get children(){var t=D(),n=t.firstChild.nextSibling;return o(n,r(h,{variant:`outline`,class:`gap-1`,get children(){return[r(E,{class:`size-3`}),e(()=>m.user()?.username||`guest`),` · `,e(()=>U())]}}),null),o(n,r(_,{variant:`outline`,class:`h-8`,onClick:B,get disabled(){return!!R()},children:`刷新`}),null),t}}),null),o(n,r(i,{get when(){return g.isBanned()},get children(){return r(v,{tone:`error`,get children(){var e=O(),t=e.firstChild;return o(e,r(w,{class:`size-4`}),t),e}})}}),null),o(n,r(i,{get when(){return g.can(`user:list`)},get fallback(){return r(v,{tone:`warning`,get children(){var e=M(),t=e.firstChild;return o(e,r(x,{class:`size-4`}),t),e}})},get children(){return r(d,{delay:1,get children(){var n=A(),a=n.firstChild;return o(n,r(i,{get when(){return l()},get children(){return r(v,{tone:`error`,class:`border-x-0 border-t-0`,get children(){return l()}})}}),a),o(n,r(p,{get each(){return t()},children:(n,a)=>{let s=I[n.role]||I.guest,l=n.status===`banned`,d=L(U()),f=g.can(`user:manage`)&&g.canManage(n.role)&&d.length>0;return(()=>{var p=P(),m=p.firstChild,v=m.firstChild,b=v.nextSibling.firstChild,x=b.nextSibling,C=m.nextSibling,w=C.nextSibling;return o(v,()=>(n.username[0]??`?`).toUpperCase()),o(b,()=>n.username,null),o(b,r(i,{get when(){return n.role===`root`},get children(){return N()}}),null),o(x,()=>s.label),o(p,r(h,{get class(){return s.badge},get children(){return n.role}}),C),o(C,r(i,{when:l,get fallback(){return r(h,{variant:`outline`,class:`border-success/30 text-success`,children:`active`})},get children(){return r(h,{variant:`outline`,class:`border-destructive/40 bg-destructive/10 text-destructive`,children:`banned`})}})),o(w,r(i,{when:f,get fallback(){return(()=>{var e=F(),t=e.firstChild;return o(e,r(S,{class:`size-3.5`}),t),e})()},get children(){return r(y,{class:`w-28`,get value(){return n.role},get"aria-label"(){return`调整 ${n.username} 的角色`},onChange:e=>V(n.username,e),get options(){return d.map(e=>({value:e,label:e}))},get disabled(){return!!R()||l}})}}),null),o(w,r(i,{get when(){return e(()=>!!g.can(`user:manage`))()&&W(n)},get children(){return r(_,{variant:l?`outline`:`ghost`,class:`h-7 px-2 text-xs ${l?`border-success/30 text-success hover:bg-success/10`:`text-destructive hover:bg-destructive/10`}`,get disabled(){return R()===n.username},onClick:()=>H(n),children:l?`解封`:`封禁`})}}),null),c(e=>{var n=`grid grid-cols-1 items-center gap-3 px-5 py-4 sm:grid-cols-[minmax(0,1fr)_7rem_7rem_16rem] sm:gap-4 ${a()<t().length-1?`border-b border-line/70`:``} ${l?`bg-destructive/5`:``}`,r=`flex size-8 shrink-0 items-center justify-center border font-mono text-xs font-bold ${s.avatar}`;return n!==e.e&&u(p,e.e=n),r!==e.t&&u(v,e.t=r),e},{e:void 0,t:void 0}),p})()}}),null),o(n,r(i,{get when(){return e(()=>t().length===0)()&&!l()},get children(){var e=k(),t=e.firstChild;return o(e,r(C,{class:`size-4 text-success`}),t),e}}),null),n}})}}),null),o(n,r(v,{tone:`info`,class:`text-xs leading-relaxed`,children:`提示:Root 拥有全部权限且可封禁/解封任意非 Root 用户;Admin 仅可调整 viewer/publisher 并封禁同级以下用户;被封禁者即使持有有效 JWT 也会在鉴权校验时被拒绝(后端 VerifyToken 拦截)。`}),null),n})()};export{R as Users}; |