1 line
28 KiB
JavaScript
1 line
28 KiB
JavaScript
import{B as e,C as t,G as n,L as r,N as i,O as a,S as o,T as s,U as c,V as l,_ as u,a as d,b as f,g as p,j as m,m as h,n as g,p as _,r as v,t as y,u as b,x,z as S}from"./ui-BjxGELcM.js";import{n as C,t as w}from"./eye-8xrL_Squ.js";import{t as T}from"./globe-Cy3sFr4f.js";import{t as E}from"./hash-Dadu1FEQ.js";import{n as D,r as O,t as k}from"./users-D75l7xkO.js";import{t as A}from"./log-out-BYvt6A8x.js";import{t as j}from"./message-square-DGTwCJY8.js";import{t as M}from"./radio-tower-Dfdb9MI0.js";import{n as N,t as ee}from"./user-round-BD5O3Mh0.js";import{t as P}from"./shield-check-CU6M0J1d.js";import{t as F}from"./video-02fL9iqS.js";import{n as I,r as L}from"./index-BsK239Bd.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=>r(u,n(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=>r(u,n(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=>r(u,n(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=>r(u,n(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=>r(u,n(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=>r(u,n(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=>r(u,n(e,{iconNode:J,name:`trash-2`})),X=a(`<div class="flex flex-wrap gap-1.5">`),Z=a(`<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(t){L();let n=e(()=>re.filter(e=>e.perms.some(e=>_.can(e))||_.isAdminOrAbove()));return(()=>{var e=X();return o(e,r(m,{get each(){return n()},children:e=>{let n=e.icon,i=()=>t.value===e.path;return(()=>{var a=Z();return a.$$click=()=>t.onChange(e.path),o(a,r(n,{class:`size-3.5`}),null),o(a,()=>e.label,null),l(e=>{var t=`inline-flex h-9 items-center gap-1.5 border px-3 text-xs font-medium transition-colors ${i()?`border-line bg-acid-lime text-black`:`border-line bg-card text-muted-foreground hover:bg-accent`}`,n=i()?`page`:void 0;return t!==e.e&&f(a,e.e=t),n!==e.t&&s(a,`aria-current`,e.t=n),e},{e:void 0,t:void 0}),a})()}})),e})()}x([`click`]);var ae=a(`<div>`),oe=a(`<p class="mt-3 max-w-2xl text-sm text-muted-foreground">`),se=a(`<div class="flex shrink-0 items-center gap-2">`),ce=a(`<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 t=ae();return o(t,()=>e.children),l(()=>f(t,`mx-auto max-w-[1400px] space-y-6 px-4 py-8 sm:px-6 sm:py-10 ${e.class??``}`)),t})()}function ue(e){return(()=>{var t=ce(),n=t.firstChild,a=n.firstChild.nextSibling;return o(a,()=>e.title),o(n,r(i,{get when(){return e.description},get children(){var t=oe();return o(t,()=>e.description),t}}),null),o(t,r(i,{get when(){return e.actions},get children(){var t=se();return o(t,()=>e.actions),t}}),null),t})()}var de=a(`<p class="mt-1 text-xs text-muted-foreground">`),fe=a(`<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=a(`<p class="py-6 text-center text-sm text-muted-foreground">暂无房间数据`),me=a(`<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=a(`<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=a(`<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 t=e.icon;return(()=>{var n=fe(),a=n.firstChild.firstChild,s=a.firstChild,c=s.nextSibling,l=a.nextSibling;return o(s,()=>e.label),o(c,()=>e.value),o(a,r(i,{get when(){return e.hint},get children(){var t=de();return o(t,()=>e.hint),t}}),null),o(l,r(t,{class:`size-4`})),n})()}function _e(e){let t=()=>e.overview,n=()=>e.rooms;return(()=>{var e=me(),a=e.firstChild,s=a.nextSibling.firstChild,c=s.firstChild,l=c.firstChild.nextSibling,u=l.firstChild,f=c.nextSibling,p=s.nextSibling.firstChild.nextSibling;return o(a,r(Q,{label:`房间总数`,get value(){return t()?.rooms_total??`-`},get hint(){return`${t()?.rooms_live??0} 个正在直播`},icon:B}),null),o(a,r(Q,{label:`在线房间`,get value(){return t()?.rooms_live??`-`},hint:`有推流目标的房间`,icon:F}),null),o(a,r(Q,{label:`房间成员`,get value(){return t()?.members_total??`-`},hint:`所有房间成员汇总`,icon:k}),null),o(a,r(Q,{label:`系统用户`,get value(){return t()?.users_total??`-`},hint:`已注册账号`,icon:P}),null),o(l,()=>n().length,u),o(f,r(m,{get each(){return n().slice(0,6)},children:e=>(()=>{var t=he(),n=t.firstChild,i=n.firstChild,a=n.nextSibling.firstChild,s=a.firstChild,c=a.nextSibling,l=c.firstChild;return o(n,r(d,{get active(){return e.live}}),i),o(i,()=>e.room.name),o(n,r(g,{get variant(){return e.live?`success`:`muted`},class:`hidden sm:inline-flex`,get children(){return e.live?`LIVE`:`IDLE`}}),null),o(a,()=>e.member_count,s),o(c,()=>e.targets?.length??0,l),t})()}),null),o(f,r(i,{get when(){return n().length===0},get children(){return pe()}}),null),o(p,r(m,{get each(){return t()?.backends||[]},children:e=>(()=>{var t=ge(),n=t.firstChild;return o(n,()=>e.name||e.kind),o(t,r(g,{get variant(){return e.configured?`success`:`muted`},get children(){return e.configured?`已配置`:`未配置`}}),null),t})()})),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=a(`<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=a(`<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=a(`<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=a(`<div class="border border-line bg-card/50 p-4"><h4 class="flex items-center gap-2 font-semibold">房间设置`),we=a(`<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=a(`<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=a(`<div class="border border-dashed border-line p-8 text-center text-sm text-muted-foreground">选择一个房间以管理`),De=a(`<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=a(`<p class="mt-3 text-sm text-muted-foreground">加载中…`);function ke(e){return(()=>{var t=we(),n=t.firstChild,a=n.firstChild,c=a.firstChild.nextSibling,u=c.firstChild,p=u.firstChild.nextSibling,h=p.firstChild,_=u.nextSibling,y=_.firstChild.nextSibling,x=_.nextSibling,S=x.firstChild;S.firstChild;var k=S.nextSibling.firstChild.nextSibling,A=x.nextSibling.firstChild.nextSibling,M=A.firstChild,P=M.nextSibling,F=a.nextSibling.firstChild,L=F.firstChild.nextSibling,R=F.nextSibling,z=n.nextSibling;return o(p,r(E,{class:`size-4 shrink-0 text-muted-foreground`}),h),h.$$input=t=>e.setNewRoom({name:t.currentTarget.value}),y.$$input=t=>e.setNewRoom({desc:t.currentTarget.value}),o(S,r(b,{get value(){return e.newRoom.isPublic?`public`:`private`},onChange:t=>e.setNewRoom({isPublic:t===`public`}),options:[{value:`public`,label:`公开`},{value:`private`,label:`私密`}]}),null),k.$$input=t=>e.setNewRoom({max:t.currentTarget.value}),o(A,r(O,{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}),o(P,r(i,{get when(){return e.newRoom.showPwd},get fallback(){return r(w,{class:`size-4`})},get children(){return r(C,{class:`size-4`})}})),o(c,r(v,{class:`w-full`,get onClick(){return e.onCreate},get disabled(){return e.loading||!e.newRoom.name.trim()},get children(){return[r(D,{class:`size-4`}),`创建房间`]}}),null),o(L,()=>e.rooms.length),o(R,r(m,{get each(){return e.rooms},children:t=>(()=>{var n=Te(),i=n.firstChild,a=i.firstChild,s=a.nextSibling,c=i.nextSibling,u=c.firstChild,p=u.firstChild;return n.$$click=()=>e.onSelectRoom(t.room.name),o(a,()=>t.room.name),o(s,()=>t.room.description||`—`),o(c,r(d,{get active(){return t.live}}),u),o(u,()=>t.member_count,p),l(()=>f(n,`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===t.room.name?`bg-acid-lime/10`:``}`)),n})()})),o(z,r(i,{get when(){return e.selectedRoom},get fallback(){return Ee()},get children(){return[(()=>{var t=be(),n=t.firstChild,i=n.firstChild.firstChild;i.firstChild;var a=i.nextSibling,s=n.nextSibling,c=s.firstChild,u=c.firstChild.nextSibling,d=c.nextSibling.firstChild.nextSibling,f=s.nextSibling;return o(i,()=>e.selectedRoom,null),o(a,()=>e.editingRoom?.display_name||e.selectedRoom),o(n,r(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}),o(f,r(v,{class:`gap-1.5`,get onClick(){return e.onSave},get children(){return[r(U,{class:`size-4`}),`保存`]}}),null),o(f,r(v,{variant:`danger`,class:`gap-1.5`,onClick:()=>e.onDelete(e.selectedRoom),get children(){return[r(Y,{class:`size-4`}),`删除`]}}),null),l(()=>u.value=e.edit.desc),l(()=>d.value=e.edit.max),t})(),(()=>{var t=xe(),n=t.firstChild,a=n.firstChild;a.firstChild;var s=n.nextSibling;return o(a,()=>e.members.length,null),o(s,r(m,{get each(){return e.members},children:t=>(()=>{var n=De(),a=n.firstChild,s=a.nextSibling.firstChild,c=s.nextSibling;return o(a,()=>(t.username[0]||`?`).toUpperCase()),o(s,()=>t.username),o(c,()=>t.effective_permissions?.join(`, `)||``),o(n,r(b,{class:`w-28`,get value(){return t.role},onChange:n=>e.onChangeRole(e.selectedRoom,t.username,n),options:[{value:`creator`,label:`房主`},{value:`admin`,label:`管理员`},{value:`member`,label:`成员`},{value:`guest`,label:`访客`}]}),null),o(n,r(i,{get when(){return t.role!==`creator`},get children(){return r(v,{variant:`ghost`,class:`h-8 px-2 text-destructive`,onClick:()=>e.onKick(e.selectedRoom,t.username),get children(){return r(I,{class:`size-4`})}})}}),null),l(()=>f(a,`flex size-8 items-center justify-center border font-mono text-xs font-bold ${ye[t.role]?.color||``}`)),n})()})),t})(),(()=>{var t=Ce(),n=t.firstChild,a=n.firstChild;return o(n,r(q,{class:`size-4`}),a),o(t,r(i,{get when(){return e.roomSettings},get fallback(){return Oe()},get children(){return[(()=>{var t=Se(),n=t.firstChild,i=n.firstChild,a=i.firstChild,s=i.nextSibling,c=n.nextSibling,u=c.firstChild,d=u.firstChild,f=u.nextSibling,p=c.nextSibling,m=p.firstChild,h=m.firstChild,g=m.nextSibling,_=p.nextSibling.firstChild,v=_.firstChild,y=_.nextSibling;return o(i,r(j,{class:`size-4 text-muted-foreground`}),a),s.$$input=t=>e.setRoomSettings({...e.roomSettings,chat_enabled:t.currentTarget.checked}),o(u,r(ee,{class:`size-4 text-muted-foreground`}),d),f.$$input=t=>e.setRoomSettings({...e.roomSettings,allow_guest_join:t.currentTarget.checked}),o(m,r(N,{class:`size-4 text-muted-foreground`}),h),g.$$input=t=>e.setRoomSettings({...e.roomSettings,require_approval:t.currentTarget.checked}),o(_,r(T,{class:`size-4 text-muted-foreground`}),v),y.$$input=t=>e.setRoomSettings({...e.roomSettings,is_public:t.currentTarget.checked}),l(()=>s.checked=!!e.roomSettings?.chat_enabled),l(()=>f.checked=!!e.roomSettings?.allow_guest_join),l(()=>g.checked=!!e.roomSettings?.require_approval),l(()=>y.checked=!!e.roomSettings?.is_public),t})(),r(v,{class:`mt-4 gap-1.5`,get onClick(){return e.onSaveSettings},get children(){return[r(U,{class:`size-4`}),`保存设置`]}})]}}),null),t})()]}})),l(()=>s(M,`type`,e.newRoom.showPwd?`text`:`password`)),l(()=>h.value=e.newRoom.name),l(()=>y.value=e.newRoom.desc),l(()=>k.value=e.newRoom.max),l(()=>M.value=e.newRoom.pwd),t})()}x([`input`,`click`]);var Ae=a(`<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=a(`<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=a(`<th class="px-2 py-2 text-center font-mono text-muted-foreground">`),Ne=a(`<tr class="border-b border-line/60"><td class="px-2 py-2 font-mono">`),Pe=a(`<td class="px-2 py-2 text-center">`),Fe=a(`<span class="inline-flex size-2 bg-acid-lime">`),Ie=a(`<span class="inline-flex size-2 border border-line">`),Le=a(`<p class="px-4 py-8 text-center text-sm text-muted-foreground">请选择房间`),Re=a(`<th class="px-1 py-2 text-center text-[10px] font-mono text-muted-foreground">`),ze=a(`<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=a(`<td class="px-1 py-1 text-center"><button type=button>`);function Ve(e){return(()=>{var t=je(),n=t.firstChild,a=n.firstChild.nextSibling.nextSibling.firstChild.firstChild,s=a.firstChild;s.firstChild;var c=a.nextSibling,l=n.nextSibling,u=l.firstChild,d=u.firstChild;return d.firstChild,o(s,r(m,{each:[`creator`,`admin`,`member`,`guest`],children:e=>(()=>{var t=Me();return o(t,e),t})()}),null),o(c,r(m,{each:$,children:t=>(()=>{var n=Ne(),i=n.firstChild;return o(i,()=>ve[t]||t),o(n,r(m,{each:[`creator`,`admin`,`member`,`guest`],children:n=>{let r=e.permDefs?.roles?.[n]?.perms?.includes(t);return(()=>{var e=Pe();return o(e,r?Fe():Ie()),e})()}}),null),n})()})),o(d,()=>e.selectedRoom||`未选择`,null),o(u,r(b,{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),o(l,r(i,{get when(){return e.selectedRoom},get fallback(){return Le()},get children(){var t=Ae(),n=t.firstChild.firstChild,i=n.firstChild;i.firstChild;var a=n.nextSibling;return o(i,r(m,{each:$,children:e=>(()=>{var t=Re();return o(t,()=>ve[e]||e),t})()}),null),o(a,r(m,{get each(){return e.members},children:t=>(()=>{var n=ze(),i=n.firstChild.firstChild,a=i.firstChild;return o(a,()=>t.username),o(i,r(g,{get class(){return`text-[10px] ${ye[t.role]?.color||``}`},get children(){return t.role}}),null),o(n,r(m,{each:$,children:n=>{let r=t.effective_permissions?.includes(n),i=t.role===`creator`;return(()=>{var a=Be(),s=a.firstChild;return s.$$click=()=>e.onTogglePerm(e.selectedRoom,t.username,n,!!r),s.disabled=i,f(s,`inline-flex size-6 items-center justify-center border text-[10px] ${r?`border-acid-lime bg-acid-lime text-black`:`border-line bg-background text-muted-foreground hover:border-ring`} ${i?`opacity-50`:``}`),o(s,r?`✓`:``),a})()}}),null),n})()})),t}}),null),t})()}x([`click`]);var He=a(`<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=a(`<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 t=He(),n=t.firstChild,i=n.firstChild,a=i.firstChild,s=a.firstChild,c=a.nextSibling;c.firstChild.nextSibling;var l=i.nextSibling.firstChild,u=l.firstChild,d=n.nextSibling.firstChild.nextSibling;return o(a,r(G,{class:`size-4`}),s),o(c,r(m,{get each(){return e.overview?.backends||[]},children:e=>(()=>{var t=Ue(),n=t.firstChild;return o(n,r(M,{class:`size-4 text-muted-foreground`}),null),o(n,()=>e.name||e.kind,null),o(t,r(g,{get variant(){return e.configured?`success`:`muted`},get children(){return e.configured?`已配置`:`未配置`}}),null),t})()}),null),o(l,r(z,{class:`size-4`}),u),o(d,r(v,{variant:`ghost`,onClick:()=>window.open(`/api/config`,`_blank`),get children(){return[r(T,{class:`size-4`}),`/api/config`]}}),null),o(d,r(v,{variant:`ghost`,onClick:()=>{localStorage.clear(),location.reload()},get children(){return[r(A,{class:`size-4`}),`清理缓存`]}}),null),t})()}var Ge=a(`<span class="flex items-center gap-2">`),Ke=a(`<button class="text-xs underline">关闭`),qe=()=>{let[e,n]=c(`overview`),[a,s]=c(null),[l,u]=c([]),[d,f]=c(null),[m,b]=c(``),[x,C]=c([]),[w,T]=c(``),[E,D]=c(!1),[O,k]=c(``),[A,j]=c(``),[M,ee]=c(!0),[F,I]=c(`100`),[L,R]=c(``),[z,te]=c(!1),[B,V]=c(null),[H,U]=c(``),[W,G]=c(``),[K,q]=c(null),J=async()=>{try{let e=await p.manageOverview();s(e)}catch(e){T(String(e?.message||e))}},Y=async()=>{try{let e=await p.manageRooms();u(e.rooms||[]),!m()&&e.rooms?.length&&b(e.rooms[0].room.name)}catch(e){T(String(e?.message||e))}},X=async()=>{try{let e=await p.managePermMatrix();f(e)}catch{}},Z=async e=>{if(e)try{let t=await p.manageMembers(e);C(t.members||[]);let n=await p.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))}};S(()=>{J(),Y(),X()}),S(()=>{let t=m();t&&(e()===`rooms`||e()===`permissions`)&&Z(t)});let re=async()=>{let e=O().trim();if(e){D(!0);try{await p.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=m();if(!(!e||!B()))try{await p.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 p.manageDeleteRoom(e),await Y(),await J()}catch(e){T(String(e?.message||e))}},se=async(e,t,n)=>{try{await p.manageUpdateMemberRole(e,t,n),await Z(e)}catch(e){T(String(e?.message||e))}},ce=async(e,t)=>{if(confirm(`踢出 ${t} ?`))try{await p.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=x().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 p.manageUpdateMemberPerms(e,t,o,s,!1),await Z(e)}catch(e){T(String(e?.message||e))}},fe=async()=>{let e=m();if(!(!e||!K()))try{await p.manageUpdateRoomSettings(e,K()),await Z(e)}catch(e){T(String(e?.message||e))}};return r(le,{get children(){return[r(ue,{title:`管理控制台`,description:`统一管理房间、角色与权限。房主全量,管理员/成员/访客基于角色默认值 + 个人覆盖计算生效权限。`,get actions(){return[r(g,{variant:`outline`,class:`gap-1.5`,get children(){return[r(P,{class:`size-3.5`}),t(()=>h.user()?.username||`guest`),` · `,t(()=>_.role())]}}),r(v,{variant:`ghost`,class:`h-9 gap-1.5`,onClick:()=>{J(),Y(),m()&&Z(m())},get children(){return[r(ne,{class:`size-4`}),`刷新`]}})]}}),r(i,{get when(){return w()},get children(){return r(y,{tone:`error`,class:`flex items-center justify-between gap-3`,get children(){return[(()=>{var e=Ge();return o(e,r(N,{class:`size-4`}),null),o(e,w,null),e})(),(()=>{var e=Ke();return e.$$click=()=>T(``),e})()]}})}}),r(ie,{get value(){return e()},onChange:n}),r(i,{get when(){return e()===`overview`},get children(){return r(_e,{get overview(){return a()},get rooms(){return l()}})}}),r(i,{get when(){return e()===`rooms`},get children(){return r(ke,{get rooms(){return l()},get selectedRoom(){return m()},onSelectRoom:b,get members(){return x()},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})}}),r(i,{get when(){return e()===`permissions`},get children(){return r(Ve,{get rooms(){return l()},get selectedRoom(){return m()},onSelectRoom:b,get members(){return x()},get permDefs(){return d()},onTogglePerm:de})}}),r(i,{get when(){return e()===`system`},get children(){return r(We,{get overview(){return a()}})}})]}})};x([`click`]);export{qe as Manage}; |