1 line
28 KiB
JavaScript
1 line
28 KiB
JavaScript
import{B as e,C as t,E as n,H as r,K as i,M as a,P as o,R as s,S as c,V as l,W as u,_ as d,d as f,h as p,k as m,m as h,n as g,o as _,r as v,t as y,v as b,w as x,x as S}from"./ui-CzB-gjVP.js";import{n as C,t as w}from"./eye-DaP7VxYZ.js";import{i as T,n as E,r as D,t as O}from"./users-D7ZZ6mzL.js";import{t as k}from"./hash-ORiZzY9V.js";import{t as A}from"./log-out-BSFDyM4m.js";import{t as j}from"./message-square-1ZGuav88.js";import{t as M}from"./radio-tower-UMy9OSpZ.js";import{n as N,t as ee}from"./user-round-BkRPX9Ri.js";import{t as P}from"./shield-check-PAk2q1NC.js";import{t as F}from"./video-C1co3G53.js";import{n as I,r as L}from"./index-D9mHcT7c.js";var R=[[`path`,{d:`M2.586 17.414A2 2 0 0 0 2 18.828V21a1 1 0 0 0 1 1h3a1 1 0 0 0 1-1v-1a1 1 0 0 1 1-1h1a1 1 0 0 0 1-1v-1a1 1 0 0 1 1-1h.172a2 2 0 0 0 1.414-.586l.814-.814a6.5 6.5 0 1 0-4-4z`,key:`1s6t7t`}],[`circle`,{cx:`16.5`,cy:`7.5`,r:`.5`,fill:`currentColor`,key:`w0ekpg`}]],z=e=>s(b,i(e,{iconNode:R,name:`key-round`})),te=[[`path`,{d:`M12.83 2.18a2 2 0 0 0-1.66 0L2.6 6.08a1 1 0 0 0 0 1.83l8.58 3.91a2 2 0 0 0 1.66 0l8.58-3.9a1 1 0 0 0 0-1.83z`,key:`zw3jo`}],[`path`,{d:`M2 12a1 1 0 0 0 .58.91l8.6 3.91a2 2 0 0 0 1.65 0l8.58-3.9A1 1 0 0 0 22 12`,key:`1wduqc`}],[`path`,{d:`M2 17a1 1 0 0 0 .58.91l8.6 3.91a2 2 0 0 0 1.65 0l8.58-3.9A1 1 0 0 0 22 17`,key:`kqbvx6`}]],B=e=>s(b,i(e,{iconNode:te,name:`layers`})),V=[[`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`}]],ne=e=>s(b,i(e,{iconNode:V,name:`refresh-cw`})),H=[[`path`,{d:`M15.2 3a2 2 0 0 1 1.4.6l3.8 3.8a2 2 0 0 1 .6 1.4V19a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2z`,key:`1c8476`}],[`path`,{d:`M17 21v-7a1 1 0 0 0-1-1H8a1 1 0 0 0-1 1v7`,key:`1ydtos`}],[`path`,{d:`M7 3v4a1 1 0 0 0 1 1h7`,key:`t51u73`}]],U=e=>s(b,i(e,{iconNode:H,name:`save`})),W=[[`path`,{d:`M9.671 4.136a2.34 2.34 0 0 1 4.659 0 2.34 2.34 0 0 0 3.319 1.915 2.34 2.34 0 0 1 2.33 4.033 2.34 2.34 0 0 0 0 3.831 2.34 2.34 0 0 1-2.33 4.033 2.34 2.34 0 0 0-3.319 1.915 2.34 2.34 0 0 1-4.659 0 2.34 2.34 0 0 0-3.32-1.915 2.34 2.34 0 0 1-2.33-4.033 2.34 2.34 0 0 0 0-3.831A2.34 2.34 0 0 1 6.35 6.051a2.34 2.34 0 0 0 3.319-1.915`,key:`1i5ecw`}],[`circle`,{cx:`12`,cy:`12`,r:`3`,key:`1v7zrd`}]],G=e=>s(b,i(e,{iconNode:W,name:`settings`})),K=[[`path`,{d:`M10 5H3`,key:`1qgfaw`}],[`path`,{d:`M12 19H3`,key:`yhmn1j`}],[`path`,{d:`M14 3v4`,key:`1sua03`}],[`path`,{d:`M16 17v4`,key:`1q0r14`}],[`path`,{d:`M21 12h-9`,key:`1o4lsq`}],[`path`,{d:`M21 19h-5`,key:`1rlt1p`}],[`path`,{d:`M21 5h-7`,key:`1oszz2`}],[`path`,{d:`M8 10v4`,key:`tgpxqk`}],[`path`,{d:`M8 12H3`,key:`a7s4jb`}]],q=e=>s(b,i(e,{iconNode:K,name:`sliders-horizontal`})),J=[[`path`,{d:`M10 11v6`,key:`nco0om`}],[`path`,{d:`M14 11v6`,key:`outv1u`}],[`path`,{d:`M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6`,key:`miytrc`}],[`path`,{d:`M3 6h18`,key:`d0wm0j`}],[`path`,{d:`M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2`,key:`e791ji`}]],Y=e=>s(b,i(e,{iconNode:J,name:`trash-2`})),X=m(`<div class="flex flex-wrap gap-1.5">`),Z=m(`<button type=button>`),re=[{path:`overview`,label:`概览`,icon:B,perms:[`room:list`]},{path:`rooms`,label:`房间`,icon:M,perms:[`room:manage`]},{path:`permissions`,label:`权限`,icon:z,perms:[`room:manage`]},{path:`system`,label:`系统`,icon:G,perms:[`system:manage`,`config:read`]}];function ie(e){L();let i=l(()=>re.filter(e=>e.perms.some(e=>h.can(e))||h.isAdminOrAbove()));return(()=>{var o=X();return t(o,s(a,{get each(){return i()},children:i=>{let a=i.icon,o=()=>e.value===i.path;return(()=>{var c=Z();return c.$$click=()=>e.onChange(i.path),t(c,s(a,{class:`size-3.5`}),null),t(c,()=>i.label,null),r(e=>{var t=`inline-flex h-9 items-center gap-1.5 border px-3 text-xs font-medium transition-colors ${o()?`border-line bg-acid-lime text-black`:`border-line bg-card text-muted-foreground hover:bg-accent`}`,r=o()?`page`:void 0;return t!==e.e&&S(c,e.e=t),r!==e.t&&n(c,`aria-current`,e.t=r),e},{e:void 0,t:void 0}),c})()}})),o})()}c([`click`]);var ae=m(`<div>`),oe=m(`<p class="mt-3 max-w-2xl text-sm text-muted-foreground">`),se=m(`<div class="flex shrink-0 items-center gap-2">`),ce=m(`<div class="flex flex-wrap items-start justify-between gap-4"><div class="min-w-0 flex-1"><p class="mono-label text-muted-foreground">manage / console</p><h1 class="display mt-2 text-4xl sm:text-5xl">`);function le(e){return(()=>{var n=ae();return t(n,()=>e.children),r(()=>S(n,`mx-auto max-w-[1400px] space-y-6 px-4 py-8 sm:px-6 sm:py-10 ${e.class??``}`)),n})()}function ue(e){return(()=>{var n=ce(),r=n.firstChild,i=r.firstChild.nextSibling;return t(i,()=>e.title),t(r,s(o,{get when(){return e.description},get children(){var n=oe();return t(n,()=>e.description),n}}),null),t(n,s(o,{get when(){return e.actions},get children(){var n=se();return t(n,()=>e.actions),n}}),null),n})()}var de=m(`<p class="mt-1 text-xs text-muted-foreground">`),fe=m(`<div class="relative border border-line bg-card/60 p-4"><div class="flex items-start justify-between gap-3"><div><p class="micro-label text-muted-foreground"></p><p class="display mt-2 text-3xl"></p></div><span class="flex size-8 items-center justify-center border border-line bg-background text-muted-foreground">`),pe=m(`<p class="py-6 text-center text-sm text-muted-foreground">暂无房间数据`),me=m(`<div class=space-y-6><div class="grid gap-4 sm:grid-cols-2 lg:grid-cols-4"></div><div class="grid gap-4 lg:grid-cols-3"><div class="border border-line bg-card/50 p-4 lg:col-span-2"><div class="flex items-center justify-between gap-3"><h3 class=font-semibold>房间分发状态</h3><span class="mono-label text-muted-foreground"> rooms</span></div><div class="mt-4 space-y-2"></div></div><div class="border border-line bg-card/50 p-4"><h3 class=font-semibold>后端能力</h3><div class="mt-4 space-y-2">`),he=m(`<div class="flex items-center justify-between gap-3 border border-line/60 bg-background/50 px-3 py-2.5"><div class="flex min-w-0 items-center gap-2.5"><span class="truncate font-mono text-sm"></span></div><div class="flex items-center gap-3 text-xs text-muted-foreground"><span class="hidden sm:inline"> 成员</span><span> targets`),ge=m(`<div class="flex items-center justify-between border border-line/60 px-3 py-2.5"><span class="font-mono text-xs uppercase">`);function Q(e){let n=e.icon;return(()=>{var r=fe(),i=r.firstChild.firstChild,a=i.firstChild,c=a.nextSibling,l=i.nextSibling;return t(a,()=>e.label),t(c,()=>e.value),t(i,s(o,{get when(){return e.hint},get children(){var n=de();return t(n,()=>e.hint),n}}),null),t(l,s(n,{class:`size-4`})),r})()}function _e(e){let n=()=>e.overview,r=()=>e.rooms;return(()=>{var e=me(),i=e.firstChild,c=i.nextSibling.firstChild,l=c.firstChild,u=l.firstChild.nextSibling,d=u.firstChild,f=l.nextSibling,p=c.nextSibling.firstChild.nextSibling;return t(i,s(Q,{label:`房间总数`,get value(){return n()?.rooms_total??`-`},get hint(){return`${n()?.rooms_live??0} 个正在直播`},icon:B}),null),t(i,s(Q,{label:`在线房间`,get value(){return n()?.rooms_live??`-`},hint:`有推流目标的房间`,icon:F}),null),t(i,s(Q,{label:`房间成员`,get value(){return n()?.members_total??`-`},hint:`所有房间成员汇总`,icon:O}),null),t(i,s(Q,{label:`系统用户`,get value(){return n()?.users_total??`-`},hint:`已注册账号`,icon:P}),null),t(u,()=>r().length,d),t(f,s(a,{get each(){return r().slice(0,6)},children:e=>(()=>{var n=he(),r=n.firstChild,i=r.firstChild,a=r.nextSibling.firstChild,o=a.firstChild,c=a.nextSibling,l=c.firstChild;return t(r,s(_,{get active(){return e.live}}),i),t(i,()=>e.room.name),t(r,s(g,{get variant(){return e.live?`success`:`muted`},class:`hidden sm:inline-flex`,get children(){return e.live?`LIVE`:`IDLE`}}),null),t(a,()=>e.member_count,o),t(c,()=>e.targets?.length??0,l),n})()}),null),t(f,s(o,{get when(){return r().length===0},get children(){return pe()}}),null),t(p,s(a,{get each(){return n()?.backends||[]},children:e=>(()=>{var n=ge(),r=n.firstChild;return t(r,()=>e.name||e.kind),t(n,s(g,{get variant(){return e.configured?`success`:`muted`},get children(){return e.configured?`已配置`:`未配置`}}),null),n})()})),e})()}var $=[`send_chat`,`view_chat_history`,`view_members`,`subscribe`,`watch_room`,`publish`,`stop_stream`,`broadcast`,`manage_members`,`add_members`,`remove_members`,`manage_permissions`,`manage_room`,`delete_room`,`delete_chat_messages`,`control_stream`],ve={send_chat:`发弹幕`,view_chat_history:`看记录`,view_members:`看成员`,subscribe:`拉流`,watch_room:`监听`,publish:`推流`,stop_stream:`停播`,broadcast:`广播`,manage_members:`管成员`,add_members:`邀成员`,remove_members:`踢人`,manage_permissions:`管权限`,manage_room:`管房间`,delete_room:`删房间`,delete_chat_messages:`删消息`,control_stream:`控流`},ye={creator:{label:`房主`,color:`border-amber-400/40 bg-amber-400/10 text-amber-600`},admin:{label:`管理员`,color:`border-acid-magenta/30 bg-acid-magenta/10 text-acid-magenta`},member:{label:`成员`,color:`border-acid-cyan/30 bg-acid-cyan/10 text-acid-cyan`},guest:{label:`访客`,color:`border-line bg-muted text-muted-foreground`},root:{label:`超管`,color:`border-amber-500/40 bg-amber-500/10 text-amber-600`},viewer:{label:`观看者`,color:`border-acid-cyan/30 bg-acid-cyan/10 text-acid-cyan`},publisher:{label:`发布者`,color:`border-warning/30 bg-warning/10 text-warning`}},be=m(`<div class="border border-line bg-card/60 p-4"><div class="flex flex-wrap items-start justify-between gap-3"><div class=min-w-0><p class="mono-label text-muted-foreground">room / </p><h3 class="display mt-1 truncate text-2xl"></h3></div></div><div class="mt-4 grid gap-3 sm:grid-cols-2"><div class=space-y-1.5><label class=label>描述</label><input class=field></div><div class=space-y-1.5><label class=label>人数上限</label><input class="field field-mono"></div></div><div class="mt-3 flex flex-wrap gap-2">`),xe=m(`<div class="border border-line bg-card/50"><div class="flex items-center justify-between border-b border-line/80 px-4 py-3"><h4 class=font-semibold>成员 </h4></div><div class="divide-y divide-line/60">`),Se=m(`<div class="mt-4 grid gap-4 sm:grid-cols-2"><label class="flex items-center justify-between gap-3 border border-line bg-background px-3 py-2.5"><span class="flex items-center gap-2 text-sm"> 聊天</span><input type=checkbox></label><label class="flex items-center justify-between gap-3 border border-line bg-background px-3 py-2.5"><span class="flex items-center gap-2 text-sm"> 访客加入</span><input type=checkbox></label><label class="flex items-center justify-between gap-3 border border-line bg-background px-3 py-2.5"><span class="flex items-center gap-2 text-sm"> 需审批</span><input type=checkbox></label><label class="flex items-center justify-between gap-3 border border-line bg-background px-3 py-2.5"><span class="flex items-center gap-2 text-sm"> 公开</span><input type=checkbox>`),Ce=m(`<div class="border border-line bg-card/50 p-4"><h4 class="flex items-center gap-2 font-semibold">房间设置`),we=m(`<div class="grid gap-4 lg:grid-cols-3"><div class="lg:col-span-1 space-y-4"><div class="border border-line bg-card/60 p-4"><h3 class=font-semibold>创建房间</h3><div class="mt-4 space-y-3"><div class=space-y-1.5><label class=label>房间名 *</label><div class="flex items-center gap-2 border border-line bg-background px-3 py-2 focus-within:border-ring"><input class="w-full bg-transparent font-mono text-sm outline-none"placeholder="如 live-101"></div></div><div class=space-y-1.5><label class=label>描述</label><input class=field placeholder=一句话介绍></div><div class="grid grid-cols-2 gap-3"><div class=space-y-1.5><label class=label>可见性</label></div><div class=space-y-1.5><label class=label>人数上限</label><input class="field field-mono"></div></div><div class=space-y-1.5><label class=label>房间密码(可选)</label><div class="flex items-center gap-2 border border-line bg-background px-3 py-2 focus-within:border-ring"><input class="w-full bg-transparent font-mono text-sm outline-none"placeholder=留空为无密码><button type=button class=text-muted-foreground></button></div></div></div></div><div class="border border-line bg-card/50"><div class="flex items-center justify-between border-b border-line/80 px-4 py-3"><h3 class=font-semibold>房间列表</h3><span class="mono-label text-muted-foreground"></span></div><div class="max-h-[480px] overflow-auto"></div></div></div><div class="space-y-4 lg:col-span-2">`),Te=m(`<button type=button><div class=min-w-0><p class="truncate font-mono text-sm font-medium"></p><p class="truncate text-xs text-muted-foreground"></p></div><div class="flex shrink-0 flex-col items-end gap-1"><span class="micro-label text-muted-foreground"> 成员`),Ee=m(`<div class="border border-dashed border-line p-8 text-center text-sm text-muted-foreground">选择一个房间以管理`),De=m(`<div class="flex flex-wrap items-center gap-3 px-4 py-3"><span></span><div class="min-w-0 flex-1"><p class="truncate font-mono text-sm font-medium"></p><p class="micro-label truncate text-muted-foreground">`),Oe=m(`<p class="mt-3 text-sm text-muted-foreground">加载中…`);function ke(e){return(()=>{var i=we(),c=i.firstChild,l=c.firstChild,u=l.firstChild.nextSibling,d=u.firstChild,p=d.firstChild.nextSibling,m=p.firstChild,h=d.nextSibling,y=h.firstChild.nextSibling,b=h.nextSibling,x=b.firstChild;x.firstChild;var O=x.nextSibling.firstChild.nextSibling,A=b.nextSibling.firstChild.nextSibling,M=A.firstChild,P=M.nextSibling,F=l.nextSibling.firstChild,L=F.firstChild.nextSibling,R=F.nextSibling,z=c.nextSibling;return t(p,s(k,{class:`size-4 shrink-0 text-muted-foreground`}),m),m.$$input=t=>e.setNewRoom({name:t.currentTarget.value}),y.$$input=t=>e.setNewRoom({desc:t.currentTarget.value}),t(x,s(f,{get value(){return e.newRoom.isPublic?`public`:`private`},onChange:t=>e.setNewRoom({isPublic:t===`public`}),options:[{value:`public`,label:`公开`},{value:`private`,label:`私密`}]}),null),O.$$input=t=>e.setNewRoom({max:t.currentTarget.value}),t(A,s(D,{class:`size-4 shrink-0 text-muted-foreground`}),M),M.$$input=t=>e.setNewRoom({pwd:t.currentTarget.value}),P.$$click=()=>e.setNewRoom({showPwd:!e.newRoom.showPwd}),t(P,s(o,{get when(){return e.newRoom.showPwd},get fallback(){return s(w,{class:`size-4`})},get children(){return s(C,{class:`size-4`})}})),t(u,s(v,{class:`w-full`,get onClick(){return e.onCreate},get disabled(){return e.loading||!e.newRoom.name.trim()},get children(){return[s(E,{class:`size-4`}),`创建房间`]}}),null),t(L,()=>e.rooms.length),t(R,s(a,{get each(){return e.rooms},children:n=>(()=>{var i=Te(),a=i.firstChild,o=a.firstChild,c=o.nextSibling,l=a.nextSibling,u=l.firstChild,d=u.firstChild;return i.$$click=()=>e.onSelectRoom(n.room.name),t(o,()=>n.room.name),t(c,()=>n.room.description||`—`),t(l,s(_,{get active(){return n.live}}),u),t(u,()=>n.member_count,d),r(()=>S(i,`flex w-full items-center justify-between gap-3 border-b border-line/60 px-4 py-3 text-left hover:bg-accent/40 ${e.selectedRoom===n.room.name?`bg-acid-lime/10`:``}`)),i})()})),t(z,s(o,{get when(){return e.selectedRoom},get fallback(){return Ee()},get children(){return[(()=>{var n=be(),i=n.firstChild,a=i.firstChild.firstChild;a.firstChild;var o=a.nextSibling,c=i.nextSibling,l=c.firstChild,u=l.firstChild.nextSibling,d=l.nextSibling.firstChild.nextSibling,f=c.nextSibling;return t(a,()=>e.selectedRoom,null),t(o,()=>e.editingRoom?.display_name||e.selectedRoom),t(i,s(g,{get variant(){return e.editingRoom?.is_public?`success`:`warning`},get children(){return e.editingRoom?.is_public?`公开`:`私密`}}),null),u.$$input=t=>e.setEdit({desc:t.currentTarget.value}),d.$$input=t=>e.setEdit({max:t.currentTarget.value}),t(f,s(v,{class:`gap-1.5`,get onClick(){return e.onSave},get children(){return[s(U,{class:`size-4`}),`保存`]}}),null),t(f,s(v,{variant:`danger`,class:`gap-1.5`,onClick:()=>e.onDelete(e.selectedRoom),get children(){return[s(Y,{class:`size-4`}),`删除`]}}),null),r(()=>u.value=e.edit.desc),r(()=>d.value=e.edit.max),n})(),(()=>{var n=xe(),i=n.firstChild,c=i.firstChild;c.firstChild;var l=i.nextSibling;return t(c,()=>e.members.length,null),t(l,s(a,{get each(){return e.members},children:n=>(()=>{var i=De(),a=i.firstChild,c=a.nextSibling.firstChild,l=c.nextSibling;return t(a,()=>(n.username[0]||`?`).toUpperCase()),t(c,()=>n.username),t(l,()=>n.effective_permissions?.join(`, `)||``),t(i,s(f,{class:`w-28`,get value(){return n.role},onChange:t=>e.onChangeRole(e.selectedRoom,n.username,t),options:[{value:`creator`,label:`房主`},{value:`admin`,label:`管理员`},{value:`member`,label:`成员`},{value:`guest`,label:`访客`}]}),null),t(i,s(o,{get when(){return n.role!==`creator`},get children(){return s(v,{variant:`ghost`,class:`h-8 px-2 text-destructive`,onClick:()=>e.onKick(e.selectedRoom,n.username),get children(){return s(I,{class:`size-4`})}})}}),null),r(()=>S(a,`flex size-8 items-center justify-center border font-mono text-xs font-bold ${ye[n.role]?.color||``}`)),i})()})),n})(),(()=>{var n=Ce(),i=n.firstChild,a=i.firstChild;return t(i,s(q,{class:`size-4`}),a),t(n,s(o,{get when(){return e.roomSettings},get fallback(){return Oe()},get children(){return[(()=>{var n=Se(),i=n.firstChild,a=i.firstChild,o=a.firstChild,c=a.nextSibling,l=i.nextSibling,u=l.firstChild,d=u.firstChild,f=u.nextSibling,p=l.nextSibling,m=p.firstChild,h=m.firstChild,g=m.nextSibling,_=p.nextSibling.firstChild,v=_.firstChild,y=_.nextSibling;return t(a,s(j,{class:`size-4 text-muted-foreground`}),o),c.$$input=t=>e.setRoomSettings({...e.roomSettings,chat_enabled:t.currentTarget.checked}),t(u,s(ee,{class:`size-4 text-muted-foreground`}),d),f.$$input=t=>e.setRoomSettings({...e.roomSettings,allow_guest_join:t.currentTarget.checked}),t(m,s(N,{class:`size-4 text-muted-foreground`}),h),g.$$input=t=>e.setRoomSettings({...e.roomSettings,require_approval:t.currentTarget.checked}),t(_,s(T,{class:`size-4 text-muted-foreground`}),v),y.$$input=t=>e.setRoomSettings({...e.roomSettings,is_public:t.currentTarget.checked}),r(()=>c.checked=!!e.roomSettings?.chat_enabled),r(()=>f.checked=!!e.roomSettings?.allow_guest_join),r(()=>g.checked=!!e.roomSettings?.require_approval),r(()=>y.checked=!!e.roomSettings?.is_public),n})(),s(v,{class:`mt-4 gap-1.5`,get onClick(){return e.onSaveSettings},get children(){return[s(U,{class:`size-4`}),`保存设置`]}})]}}),null),n})()]}})),r(()=>n(M,`type`,e.newRoom.showPwd?`text`:`password`)),r(()=>m.value=e.newRoom.name),r(()=>y.value=e.newRoom.desc),r(()=>O.value=e.newRoom.max),r(()=>M.value=e.newRoom.pwd),i})()}c([`input`,`click`]);var Ae=m(`<div class=overflow-auto><table class="w-full min-w-[900px] border-collapse"><thead><tr class="border-b border-line bg-muted/20"><th class="px-3 py-2 text-left text-xs font-mono text-muted-foreground">成员 / 角色</th></tr></thead><tbody>`),je=m(`<div class=space-y-4><div class="border border-line bg-card/60 p-4"><h3 class=font-semibold>角色默认权限</h3><p class="mt-1 text-xs text-muted-foreground">Creator 全量 · Guest 只读,个人覆盖 added/removed 生效。</p><div class="mt-4 overflow-auto"><table class="w-full min-w-[520px] border-collapse text-xs"><thead><tr class="border-b border-line"><th class="px-2 py-2 text-left font-mono text-muted-foreground">permission</th></tr></thead><tbody></tbody></table></div></div><div class="border border-line bg-card/50"><div class="flex flex-wrap items-center justify-between gap-3 border-b border-line/80 px-4 py-3"><h3 class=font-semibold>成员生效权限 · `),Me=m(`<th class="px-2 py-2 text-center font-mono text-muted-foreground">`),Ne=m(`<tr class="border-b border-line/60"><td class="px-2 py-2 font-mono">`),Pe=m(`<td class="px-2 py-2 text-center">`),Fe=m(`<span class="inline-flex size-2 bg-acid-lime">`),Ie=m(`<span class="inline-flex size-2 border border-line">`),Le=m(`<p class="px-4 py-8 text-center text-sm text-muted-foreground">请选择房间`),Re=m(`<th class="px-1 py-2 text-center text-[10px] font-mono text-muted-foreground">`),ze=m(`<tr class="border-b border-line/40"><td class="px-3 py-2"><div class="flex items-center gap-2"><span class="font-mono text-xs font-medium">`),Be=m(`<td class="px-1 py-1 text-center"><button type=button>`);function Ve(e){return(()=>{var n=je(),r=n.firstChild,i=r.firstChild.nextSibling.nextSibling.firstChild.firstChild,c=i.firstChild;c.firstChild;var l=i.nextSibling,u=r.nextSibling,d=u.firstChild,p=d.firstChild;return p.firstChild,t(c,s(a,{each:[`creator`,`admin`,`member`,`guest`],children:e=>(()=>{var n=Me();return t(n,e),n})()}),null),t(l,s(a,{each:$,children:n=>(()=>{var r=Ne(),i=r.firstChild;return t(i,()=>ve[n]||n),t(r,s(a,{each:[`creator`,`admin`,`member`,`guest`],children:r=>{let i=e.permDefs?.roles?.[r]?.perms?.includes(n);return(()=>{var e=Pe();return t(e,i?Fe():Ie()),e})()}}),null),r})()})),t(p,()=>e.selectedRoom||`未选择`,null),t(d,s(f,{get value(){return e.selectedRoom},get onChange(){return e.onSelectRoom},get options(){return e.rooms.map(e=>({value:e.room.name,label:e.room.name}))},class:`w-48`}),null),t(u,s(o,{get when(){return e.selectedRoom},get fallback(){return Le()},get children(){var n=Ae(),r=n.firstChild.firstChild,i=r.firstChild;i.firstChild;var o=r.nextSibling;return t(i,s(a,{each:$,children:e=>(()=>{var n=Re();return t(n,()=>ve[e]||e),n})()}),null),t(o,s(a,{get each(){return e.members},children:n=>(()=>{var r=ze(),i=r.firstChild.firstChild,o=i.firstChild;return t(o,()=>n.username),t(i,s(g,{get class(){return`text-[10px] ${ye[n.role]?.color||``}`},get children(){return n.role}}),null),t(r,s(a,{each:$,children:r=>{let i=n.effective_permissions?.includes(r),a=n.role===`creator`;return(()=>{var o=Be(),s=o.firstChild;return s.$$click=()=>e.onTogglePerm(e.selectedRoom,n.username,r,!!i),s.disabled=a,S(s,`inline-flex size-6 items-center justify-center border text-[10px] ${i?`border-acid-lime bg-acid-lime text-black`:`border-line bg-background text-muted-foreground hover:border-ring`} ${a?`opacity-50`:``}`),t(s,i?`✓`:``),o})()}}),null),r})()})),n}}),null),n})()}c([`click`]);var He=m(`<div class=space-y-4><div class="grid gap-4 lg:grid-cols-2"><div class="border border-line bg-card/60 p-4"><h3 class="flex items-center gap-2 font-semibold">系统与 SFU</h3><div class="mt-4 space-y-3 text-sm"><div class="flex items-center justify-between border border-line bg-background px-3 py-2.5"><span class=text-muted-foreground>HTTP 端口</span><span class=font-mono>8088</span></div><div class="flex items-center justify-between border border-line bg-background px-3 py-2.5"><span class=text-muted-foreground>gRPC</span><span class=font-mono>9090</span></div></div></div><div class="border border-line bg-card/60 p-4"><h3 class="flex items-center gap-2 font-semibold">安全与策略</h3><div class="mt-4 space-y-2 text-xs leading-relaxed text-muted-foreground"><p><span class="font-mono text-foreground">JWT_SECRET</span> 需显式配置;推流 token<span class="font-mono text-foreground"> HS256</span> 签发。</p><p>私密房间支持密码;<span class="font-mono text-foreground">is_public</span> 与<span class="font-mono text-foreground"> allow_guest_join</span> 联动。</p></div></div></div><div class="border border-line bg-card/50 p-4"><h3 class=font-semibold>快捷操作</h3><div class="mt-4 flex flex-wrap gap-2">`),Ue=m(`<div class="flex items-center justify-between border border-line bg-background px-3 py-2.5"><span class="flex items-center gap-2">`);function We(e){return(()=>{var n=He(),r=n.firstChild,i=r.firstChild,o=i.firstChild,c=o.firstChild,l=o.nextSibling;l.firstChild.nextSibling;var u=i.nextSibling.firstChild,d=u.firstChild,f=r.nextSibling.firstChild.nextSibling;return t(o,s(G,{class:`size-4`}),c),t(l,s(a,{get each(){return e.overview?.backends||[]},children:e=>(()=>{var n=Ue(),r=n.firstChild;return t(r,s(M,{class:`size-4 text-muted-foreground`}),null),t(r,()=>e.name||e.kind,null),t(n,s(g,{get variant(){return e.configured?`success`:`muted`},get children(){return e.configured?`已配置`:`未配置`}}),null),n})()}),null),t(u,s(z,{class:`size-4`}),d),t(f,s(v,{variant:`ghost`,onClick:()=>window.open(`/api/config`,`_blank`),get children(){return[s(T,{class:`size-4`}),`/api/config`]}}),null),t(f,s(v,{variant:`ghost`,onClick:()=>{localStorage.clear(),location.reload()},get children(){return[s(A,{class:`size-4`}),`清理缓存`]}}),null),n})()}var Ge=m(`<span class="flex items-center gap-2">`),Ke=m(`<button class="text-xs underline">关闭`),qe=()=>{let[n,r]=u(`overview`),[i,a]=u(null),[c,l]=u([]),[f,m]=u(null),[_,b]=u(``),[S,C]=u([]),[w,T]=u(``),[E,D]=u(!1),[O,k]=u(``),[A,j]=u(``),[M,ee]=u(!0),[F,I]=u(`100`),[L,R]=u(``),[z,te]=u(!1),[B,V]=u(null),[H,U]=u(``),[W,G]=u(``),[K,q]=u(null),J=async()=>{try{let e=await d.manageOverview();a(e)}catch(e){T(String(e?.message||e))}},Y=async()=>{try{let e=await d.manageRooms();l(e.rooms||[]),!_()&&e.rooms?.length&&b(e.rooms[0].room.name)}catch(e){T(String(e?.message||e))}},X=async()=>{try{let e=await d.managePermMatrix();m(e)}catch{}},Z=async e=>{if(e)try{let t=await d.manageMembers(e);C(t.members||[]);let n=await d.manageRoomDetail(e);V(n.room),U(n.room.description||``),G(String(n.room.max_members||100)),q(n.room.settings||null)}catch(e){T(String(e?.message||e))}};e(()=>{J(),Y(),X()}),e(()=>{let e=_();e&&(n()===`rooms`||n()===`permissions`)&&Z(e)});let re=async()=>{let e=O().trim();if(e){D(!0);try{await d.manageCreateRoom({name:e,description:A().trim()||void 0,is_public:M(),max_members:parseInt(F())||100,password:L().trim()||void 0}),k(``),j(``),R(``),await Y(),await J()}catch(e){T(String(e?.message||e))}finally{D(!1)}}},ae=async()=>{let e=_();if(!(!e||!B()))try{await d.manageUpdateRoom(e,{description:H(),max_members:parseInt(W())||void 0,is_public:B().is_public}),await Y(),await Z(e)}catch(e){T(String(e?.message||e))}},oe=async e=>{if(confirm(`删除房间 ${e} ?`))try{await d.manageDeleteRoom(e),await Y(),await J()}catch(e){T(String(e?.message||e))}},se=async(e,t,n)=>{try{await d.manageUpdateMemberRole(e,t,n),await Z(e)}catch(e){T(String(e?.message||e))}},ce=async(e,t)=>{if(confirm(`踢出 ${t} ?`))try{await d.manageKickMember(e,t),await Z(e)}catch(e){T(String(e?.message||e))}},de=async(e,t,n,r)=>{let i=1<<$.indexOf(n),a=S().find(e=>e.username===t);if(!a)return;let o=Number(a.added||0),s=Number(a.removed||0);r?(o&=~i,s|=i):(o|=i,s&=~i);try{await d.manageUpdateMemberPerms(e,t,o,s,!1),await Z(e)}catch(e){T(String(e?.message||e))}},fe=async()=>{let e=_();if(!(!e||!K()))try{await d.manageUpdateRoomSettings(e,K()),await Z(e)}catch(e){T(String(e?.message||e))}};return s(le,{get children(){return[s(ue,{title:`管理控制台`,description:`统一管理房间、角色与权限。房主全量,管理员/成员/访客基于角色默认值 + 个人覆盖计算生效权限。`,get actions(){return[s(g,{variant:`outline`,class:`gap-1.5`,get children(){return[s(P,{class:`size-3.5`}),x(()=>p.user()?.username||`guest`),` · `,x(()=>h.role())]}}),s(v,{variant:`ghost`,class:`h-9 gap-1.5`,onClick:()=>{J(),Y(),_()&&Z(_())},get children(){return[s(ne,{class:`size-4`}),`刷新`]}})]}}),s(o,{get when(){return w()},get children(){return s(y,{tone:`error`,class:`flex items-center justify-between gap-3`,get children(){return[(()=>{var e=Ge();return t(e,s(N,{class:`size-4`}),null),t(e,w,null),e})(),(()=>{var e=Ke();return e.$$click=()=>T(``),e})()]}})}}),s(ie,{get value(){return n()},onChange:r}),s(o,{get when(){return n()===`overview`},get children(){return s(_e,{get overview(){return i()},get rooms(){return c()}})}}),s(o,{get when(){return n()===`rooms`},get children(){return s(ke,{get rooms(){return c()},get selectedRoom(){return _()},onSelectRoom:b,get members(){return S()},get editingRoom(){return B()},get roomSettings(){return K()},setRoomSettings:q,get newRoom(){return{name:O(),desc:A(),isPublic:M(),max:F(),pwd:L(),showPwd:z()}},setNewRoom:e=>{e.name!==void 0&&k(e.name),e.desc!==void 0&&j(e.desc),e.isPublic!==void 0&&ee(e.isPublic),e.max!==void 0&&I(e.max),e.pwd!==void 0&&R(e.pwd),e.showPwd!==void 0&&te(e.showPwd)},get edit(){return{desc:H(),max:W()}},setEdit:e=>{e.desc!==void 0&&U(e.desc),e.max!==void 0&&G(e.max)},get loading(){return E()},onCreate:re,onSave:ae,onDelete:oe,onChangeRole:se,onKick:ce,onSaveSettings:fe})}}),s(o,{get when(){return n()===`permissions`},get children(){return s(Ve,{get rooms(){return c()},get selectedRoom(){return _()},onSelectRoom:b,get members(){return S()},get permDefs(){return f()},onTogglePerm:de})}}),s(o,{get when(){return n()===`system`},get children(){return s(We,{get overview(){return i()}})}})]}})};c([`click`]);export{qe as Manage}; |