mn-ws 0.2.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/ws.mjs +0 -0
- package/dist/core/bridge.d.ts +11 -4
- package/dist/core/bridge.d.ts.map +1 -1
- package/dist/core/bridge.js +5 -3
- package/dist/core/bridge.js.map +1 -1
- package/dist/core/config.d.ts +41 -0
- package/dist/core/config.d.ts.map +1 -1
- package/dist/core/config.js +53 -0
- package/dist/core/config.js.map +1 -1
- package/dist/core/controller.d.ts +11 -2
- package/dist/core/controller.d.ts.map +1 -1
- package/dist/core/controller.js +36 -7
- package/dist/core/controller.js.map +1 -1
- package/dist/modules/bridge/index.d.ts +43 -0
- package/dist/modules/bridge/index.d.ts.map +1 -1
- package/dist/modules/bridge/index.js +25 -1
- package/dist/modules/bridge/index.js.map +1 -1
- package/dist/modules/bridge/service.d.ts +30 -0
- package/dist/modules/bridge/service.d.ts.map +1 -1
- package/dist/modules/bridge/service.js +81 -3
- package/dist/modules/bridge/service.js.map +1 -1
- package/dist/runtime/registry.d.ts +43 -0
- package/dist/runtime/registry.d.ts.map +1 -1
- package/dist/web/public/assets/{CliHints-BOxU-Duc.js → CliHints-pV4HIvlV.js} +1 -1
- package/dist/web/public/assets/{index-BTRKdMIW.js → index-XCFB6TU2.js} +2 -2
- package/dist/web/public/assets/{view-CEQ2uPxE.js → view-CjO3P1zR.js} +1 -1
- package/dist/web/public/assets/view-DyibLWt9.js +1 -0
- package/dist/web/public/index.html +1 -1
- package/package.json +18 -18
- package/dist/web/public/assets/view-CE4tnCuy.js +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
import{r as f,j as e,u as E,a as G,b as H,C as I,T as L,c as F}from"./index-BTRKdMIW.js";import{C as R}from"./CliHints-BOxU-Duc.js";const O=()=>({groups:[],hidden:[],order:[]});function V(s){return{groups:((s==null?void 0:s.navGroups)||[]).map(n=>({title:String(n.title||""),views:[...n.views||[]]})),hidden:[...(s==null?void 0:s.navHidden)||[]],order:[...(s==null?void 0:s.navOrder)||[]]}}function B(s){return{navGroups:s.groups.map(n=>({title:n.title.trim(),views:[...n.views]})),navHidden:[...s.hidden],navOrder:[...s.order]}}const _=(s,n)=>JSON.stringify(s)!==JSON.stringify(n),A=(s,n="")=>({...s,groups:[...s.groups,{title:n,views:[]}]}),J=(s,n)=>({...s,groups:s.groups.filter((r,t)=>t!==n)}),q=(s,n,r)=>({...s,groups:s.groups.map((t,o)=>o===n?{...t,title:r}:t)});function z(s,n,r){const t=n+r;if(t<0||t>=s.groups.length)return s;const o=[...s.groups],i=o[n],c=o[t];return!i||!c?s:(o[n]=c,o[t]=i,{...s,groups:o})}function K(s,n,r=[]){const t=s.hidden.indexOf(n);if(t>=0)return{kind:"hidden",index:t};const o=s.groups.findIndex(i=>i.views.includes(n));if(o>=0){const i=s.groups[o];return{kind:"group",gi:o,index:i.views.indexOf(n)}}return{kind:"pool",index:P(s,r).indexOf(n)}}function T(s,n){const r=s.order.filter(o=>n.includes(o)),t=n.filter(o=>!r.includes(o));return[...r,...t]}function Y(s,n,r,t,o=[]){if(t==null)return null;const i=K(s,n,o);return r.kind===i.kind&&(r.kind!=="group"||i.kind==="group"&&r.gi===i.gi)&&typeof i.index=="number"&&i.index<t?t-1:t}function M(s,n,r,t=null,o=[]){const i=s.groups.map(g=>({...g,views:g.views.filter(j=>j!==n)})),c=s.hidden.filter(g=>g!==n),p={...s,groups:i,hidden:c,order:s.order.filter(g=>g!==n)};if(r.kind==="hidden")return{...p,hidden:[...c,n]};if(r.kind==="pool"){const g=x=>!i.some(b=>b.views.includes(x))&&!c.includes(x),j=T(p,o).filter(x=>x!==n&&g(x)),y=t===null?j.length:Math.max(0,Math.min(t,j.length));return{...p,order:[...j.slice(0,y),n,...j.slice(y)]}}const m=i[r.gi];if(!m)return s;const k=t===null?m.views.length:Math.max(0,Math.min(t,m.views.length)),N=[...m.views.slice(0,k),n,...m.views.slice(k)];return{...p,groups:i.map((g,j)=>j===r.gi?{...m,views:N}:g)}}const Q=(s,n,r=[])=>M(s,n,{kind:"pool"},null,r),U=s=>s.groups.flatMap(n=>n.views),P=(s,n)=>{const r=new Set([...U(s),...s.hidden]);return T(s,n).filter(t=>!r.has(t))};function W(s,n){const r=new Set(n),t=[],o=new Map;s.groups.forEach((i,c)=>{const p=i.title.trim()||`第 ${c+1} 个分组`;i.title.trim()||t.push({field:`groups.${c}.title`,message:`${p}:每个分组都要有组名`}),i.views.length||t.push({field:`groups.${c}.views`,message:`${p}:还没有页面——加一个,或删掉这个分组`});for(const m of i.views){if(!r.has(m)){t.push({field:`groups.${c}.views.${m}`,message:`${p}:页面 ${m} 已不存在,请移出`});continue}const k=o.get(m);if(k!==void 0){t.push({field:`groups.${c}.views.${m}`,message:`页面 ${m} 同时出现在「${k}」与「${p}」里——一个页面只能属于一个分组`});continue}o.set(m,p)}});for(const i of s.hidden)r.has(i)||t.push({field:`hidden.${i}`,message:`要隐藏的页面 ${i} 已不存在`});for(const i of s.order)r.has(i)||t.push({field:`order.${i}`,message:`平铺顺序里的页面 ${i} 已不存在`});return t}function X({sections:s,value:n,onChange:r}){const[t,o]=f.useState(null),[i,c]=f.useState(null),p=s.map(a=>a.id),m=a=>s.find(l=>l.id===a)||null,k=a=>{if(a==="pool")return{kind:"pool"};if(a==="hidden")return{kind:"hidden"};const l=Number(a.slice(1));return Number.isFinite(l)?{kind:"group",gi:l}:null},N=(t==null?void 0:t.kind)==="view"?t.vid:null,g=()=>{o(null),c(null)},j=a=>c(l=>l&&l.key===a.key&&l.index===a.index&&l.group===a.group?l:a),y=()=>{if((t==null?void 0:t.kind)==="view"&&i){const a=k(i.key);if(a){const l=Y(n,t.vid,a,i.index,p),h=M(n,t.vid,a,l,p);h!==n&&r(h)}}g()},x=(a,l="")=>({className:`${l} ${(i==null?void 0:i.key)===a&&!i.group?"drop-target":""}`,onDragOver:h=>{N&&(h.preventDefault(),j({key:a,index:null}))},onDragLeave:h=>{const u=h.relatedTarget;(!u||!h.currentTarget.contains(u))&&c(v=>(v==null?void 0:v.key)===a?null:v)},onDrop:h=>{h.preventDefault(),y()}}),b=(a,l,h)=>({onDragOver:u=>{if(!N||(u.preventDefault(),u.stopPropagation(),N===l))return;const v=u.currentTarget.getBoundingClientRect(),w=u.clientY>v.top+v.height/2;j({key:a,index:h+(w?1:0)})},onDrop:u=>{u.preventDefault(),u.stopPropagation(),y()},onDragStart:()=>o({kind:"view",vid:l})}),$=(a,l,h)=>{const v=(i==null?void 0:i.key)===a&&!i.group?i.index===null?l.length:i.index:null;return e.jsxs("div",{className:"nav-list",children:[v===0&&e.jsx(S,{}),l.map((w,d)=>e.jsxs(f.Fragment,{children:[e.jsx(Z,{section:m(w),vid:w,dragging:N===w,...b(a,w,d),onDragEnd:g,actions:h(w)}),v===d+1&&e.jsx(S,{})]},w))]})},C=(a,l)=>e.jsxs("div",{className:"row",children:[e.jsx("span",{className:"desc",children:l}),(i==null?void 0:i.key)===a&&!i.group&&e.jsx(S,{})]}),D=P(n,p);return e.jsxs("div",{className:"stack",children:[e.jsxs("section",{...x("pool","nav-pool"),children:[e.jsx("div",{className:"hint",children:"平铺:不进分组也不隐藏的页面,直接显示头部(拖到这里 = 移出分组 / 取消隐藏)"}),D.length?$("pool",D,()=>null):C("pool","没有平铺的页面。")]}),n.groups.map((a,l)=>{const h=`g${l}`;return e.jsxs("section",{...x(h,"card nav-group"),children:[e.jsxs("div",{className:`colhead ${(i==null?void 0:i.key)===h&&i.group?"drop-target":""}`,onDragOver:u=>{(t==null?void 0:t.kind)==="group"&&(u.preventDefault(),j({key:h,index:null,group:!0}))},onDrop:u=>{u.preventDefault(),(t==null?void 0:t.kind)==="group"&&t.gi!==l&&r(z(n,t.gi,l-t.gi)),g()},children:[e.jsx("span",{className:"grip",title:"拖动调整分组顺序",draggable:!0,onDragStart:()=>o({kind:"group",gi:l}),onDragEnd:g}),e.jsx("input",{className:"nav-title",placeholder:"组名,如「求职」",value:a.title,onChange:u=>r(q(n,l,u.target.value))}),e.jsxs("span",{className:"muted",children:[a.views.length," 个页面"]}),e.jsx("span",{className:"right rowgap",children:e.jsx("button",{className:"btn small ghost",onClick:()=>r(J(n,l)),children:"删除组"})})]}),a.views.length?$(h,a.views,u=>e.jsx("button",{className:"btn small ghost",onClick:()=>r(Q(n,u,p)),children:"移出"})):C(h,"空分组——把页面拖进来。")]},l)}),e.jsxs("section",{...x("hidden","card nav-group nav-hidden"),children:[e.jsxs("div",{className:"colhead",children:["隐藏",e.jsxs("span",{className:"muted",children:[n.hidden.length," 个页面"]}),e.jsx("span",{className:"right muted",children:"不进头部 · 深链仍可用"})]}),n.hidden.length?$("hidden",n.hidden,()=>null):C("hidden","没有隐藏的页面——把不常用的拖进来。")]}),e.jsxs("div",{className:"rowgap",children:[e.jsx("button",{className:"btn",onClick:()=>r(A(n)),children:"新增分组"}),e.jsx("span",{className:"hint",children:"组顺序 = 头部显示顺序;组内顺序 = 展开列表顺序"})]})]})}function S(){return e.jsx("div",{className:"drop-ind","aria-hidden":"true"})}function Z({section:s,vid:n,dragging:r,actions:t,onDragStart:o,onDragEnd:i,onDragOver:c,onDrop:p}){return e.jsxs("div",{className:`row nav-row ${r?"dragging":""}`,onDragOver:c,onDrop:p,children:[e.jsx("span",{className:"grip",title:"拖动:换位 / 换容器",draggable:!0,onDragStart:o,onDragEnd:i}),e.jsx("span",{className:"name",children:s?s.title:`页面已删除(${n})`}),e.jsx("span",{className:"desc",children:s?n:"保存前请移出"}),e.jsx("span",{className:"acts",children:t})]})}const ee=`mn-ws setting set --set 'navGroups=[{"title":"求职","views":["home"]}]' / --set navHidden=home / --set navOrder=["home"]`;function te(){const{boot:s,client:n,settings:r,refreshSettings:t}=E(),o=G(),i=H(),[c,p]=f.useState(""),[m,k]=f.useState(!1),[N,g]=f.useState(null),[j,y]=f.useState(!1),[x,b]=f.useState(O()),[$,C]=f.useState(O()),D=f.useMemo(()=>((r==null?void 0:r.views)||[]).map(d=>({id:d.id,title:d.title})),[r]),a=f.useMemo(()=>D.map(d=>d.id),[D]);f.useEffect(()=>{if(!r)return;const d=V(r.settings);b(d),C(d)},[r]);const l=f.useMemo(()=>W(x,a),[x,a]),h=_(x,$);async function u(){if(!c.trim()){o("请先填写名字");return}y(!0);try{const d=await n["home.greet"]({name:c.trim(),loud:m});g(d)}catch(d){o(String((d==null?void 0:d.message)||d))}finally{y(!1)}}const v=()=>i(async()=>{if(l.length){o(`保存失败:${l[0].message}`);return}await F("/api/settings",{method:"PATCH",body:{set:B(x)}}),await t(),o("设置已保存")}),w=()=>b(structuredClone($));return e.jsxs("div",{className:"stack",style:{padding:16},children:[e.jsxs("div",{className:"card",children:[e.jsx("div",{className:"colhead",children:"问候(演示动作)"}),e.jsxs("div",{style:{padding:14},children:[e.jsxs("div",{className:"toolbar",children:[e.jsx("input",{value:c,placeholder:"你的名字",onChange:d=>p(d.target.value),onKeyDown:d=>{d.key==="Enter"&&u()}}),e.jsxs("label",{style:{display:"inline-flex",gap:6,alignItems:"center"},children:[e.jsx("input",{type:"checkbox",checked:m,onChange:d=>k(d.target.checked)}),"大声"]}),e.jsx("button",{className:"btn",disabled:j,onClick:()=>void u(),children:j?"问候中…":"打招呼"})]}),N&&e.jsxs("div",{style:{marginTop:12},children:[e.jsx("strong",{children:N.greeting}),e.jsxs("div",{className:"muted",style:{marginTop:4},children:["第 ",N.count," 次 · ",N.at]})]})]})]}),e.jsxs("div",{className:"card",children:[e.jsx("div",{className:"colhead",children:"运行信息"}),e.jsxs("dl",{className:"kv",children:[e.jsxs("div",{className:"kv-row",children:[e.jsx("dt",{children:"应用"}),e.jsx("dd",{children:s?`${s.app.name} v${s.app.version}`:"加载中…"})]}),e.jsxs("div",{className:"kv-row",children:[e.jsx("dt",{children:"存储"}),e.jsx("dd",{children:e.jsx(I,{text:(s==null?void 0:s.storePath)||"",children:(s==null?void 0:s.storePath)||"…"})})]}),e.jsxs("div",{className:"kv-row",children:[e.jsx("dt",{children:"环境变量"}),e.jsx("dd",{children:s==null?void 0:s.storeEnv})]})]})]}),e.jsxs("div",{className:"card",children:[e.jsxs("div",{className:"colhead",children:["外观",e.jsx("span",{className:"right muted",children:"色彩主题 · 点击即保存"})]}),e.jsx("div",{style:{padding:12},className:"stack",children:e.jsxs("div",{className:"toolbar",children:[e.jsx(L,{}),e.jsxs("span",{className:"muted",children:["浅色 / 深色 / 跟随系统(深色下自动切换为暗色 token);CLI 等价:",e.jsx("code",{children:"mn-ws setting set --key theme --value dark"})]})]})})]}),e.jsxs("div",{className:"card",children:[e.jsxs("div",{className:"colhead",children:["栏目管理",e.jsxs("span",{className:"right muted",children:["头部显示 ",a.length-x.hidden.length," 个 · 隐藏 ",x.hidden.length," 个",x.groups.length?` · ${x.groups.length} 个分组`:""]})]}),e.jsxs("div",{style:{padding:12},className:"stack",children:[e.jsxs("div",{className:"toolbar",children:[e.jsxs("span",{className:"muted",children:["拖动就是把结构摆成你要的样子:页面可以拖进分组、组内换位、拖回平铺区即移出;拖分组把手换分组顺序。 被隐藏的页面只是头部不显示入口,用 ",e.jsx("code",{children:"#/页面id"})," 直达仍然可用。"]}),e.jsx("span",{className:"right rowgap",children:h?e.jsxs(e.Fragment,{children:[e.jsx("span",{className:"tag",children:"有未保存的改动"}),e.jsx("button",{className:"btn small",onClick:()=>{v()},children:"保存"}),e.jsx("button",{className:"btn small ghost",onClick:w,children:"放弃改动"})]}):e.jsx("span",{className:"muted",children:"已保存"})})]}),e.jsx(X,{sections:D,value:x,onChange:b}),l.map(d=>e.jsxs("div",{className:"bad",children:["· ",d.message]},d.field))]})]}),e.jsxs("div",{className:"muted",style:{padding:"0 2px"},children:["CLI 等价:",e.jsx("code",{children:ee})]}),e.jsx(R,{module:"home"})]})}export{te as default};
|
|
1
|
+
import{r as f,j as e,u as E,a as G,b as H,C as I,T as L,c as F}from"./index-XCFB6TU2.js";import{C as R}from"./CliHints-pV4HIvlV.js";const O=()=>({groups:[],hidden:[],order:[]});function V(s){return{groups:((s==null?void 0:s.navGroups)||[]).map(n=>({title:String(n.title||""),views:[...n.views||[]]})),hidden:[...(s==null?void 0:s.navHidden)||[]],order:[...(s==null?void 0:s.navOrder)||[]]}}function B(s){return{navGroups:s.groups.map(n=>({title:n.title.trim(),views:[...n.views]})),navHidden:[...s.hidden],navOrder:[...s.order]}}const _=(s,n)=>JSON.stringify(s)!==JSON.stringify(n),A=(s,n="")=>({...s,groups:[...s.groups,{title:n,views:[]}]}),J=(s,n)=>({...s,groups:s.groups.filter((r,t)=>t!==n)}),q=(s,n,r)=>({...s,groups:s.groups.map((t,o)=>o===n?{...t,title:r}:t)});function z(s,n,r){const t=n+r;if(t<0||t>=s.groups.length)return s;const o=[...s.groups],i=o[n],c=o[t];return!i||!c?s:(o[n]=c,o[t]=i,{...s,groups:o})}function K(s,n,r=[]){const t=s.hidden.indexOf(n);if(t>=0)return{kind:"hidden",index:t};const o=s.groups.findIndex(i=>i.views.includes(n));if(o>=0){const i=s.groups[o];return{kind:"group",gi:o,index:i.views.indexOf(n)}}return{kind:"pool",index:P(s,r).indexOf(n)}}function T(s,n){const r=s.order.filter(o=>n.includes(o)),t=n.filter(o=>!r.includes(o));return[...r,...t]}function Y(s,n,r,t,o=[]){if(t==null)return null;const i=K(s,n,o);return r.kind===i.kind&&(r.kind!=="group"||i.kind==="group"&&r.gi===i.gi)&&typeof i.index=="number"&&i.index<t?t-1:t}function M(s,n,r,t=null,o=[]){const i=s.groups.map(g=>({...g,views:g.views.filter(j=>j!==n)})),c=s.hidden.filter(g=>g!==n),p={...s,groups:i,hidden:c,order:s.order.filter(g=>g!==n)};if(r.kind==="hidden")return{...p,hidden:[...c,n]};if(r.kind==="pool"){const g=x=>!i.some(b=>b.views.includes(x))&&!c.includes(x),j=T(p,o).filter(x=>x!==n&&g(x)),y=t===null?j.length:Math.max(0,Math.min(t,j.length));return{...p,order:[...j.slice(0,y),n,...j.slice(y)]}}const m=i[r.gi];if(!m)return s;const k=t===null?m.views.length:Math.max(0,Math.min(t,m.views.length)),N=[...m.views.slice(0,k),n,...m.views.slice(k)];return{...p,groups:i.map((g,j)=>j===r.gi?{...m,views:N}:g)}}const Q=(s,n,r=[])=>M(s,n,{kind:"pool"},null,r),U=s=>s.groups.flatMap(n=>n.views),P=(s,n)=>{const r=new Set([...U(s),...s.hidden]);return T(s,n).filter(t=>!r.has(t))};function W(s,n){const r=new Set(n),t=[],o=new Map;s.groups.forEach((i,c)=>{const p=i.title.trim()||`第 ${c+1} 个分组`;i.title.trim()||t.push({field:`groups.${c}.title`,message:`${p}:每个分组都要有组名`}),i.views.length||t.push({field:`groups.${c}.views`,message:`${p}:还没有页面——加一个,或删掉这个分组`});for(const m of i.views){if(!r.has(m)){t.push({field:`groups.${c}.views.${m}`,message:`${p}:页面 ${m} 已不存在,请移出`});continue}const k=o.get(m);if(k!==void 0){t.push({field:`groups.${c}.views.${m}`,message:`页面 ${m} 同时出现在「${k}」与「${p}」里——一个页面只能属于一个分组`});continue}o.set(m,p)}});for(const i of s.hidden)r.has(i)||t.push({field:`hidden.${i}`,message:`要隐藏的页面 ${i} 已不存在`});for(const i of s.order)r.has(i)||t.push({field:`order.${i}`,message:`平铺顺序里的页面 ${i} 已不存在`});return t}function X({sections:s,value:n,onChange:r}){const[t,o]=f.useState(null),[i,c]=f.useState(null),p=s.map(a=>a.id),m=a=>s.find(l=>l.id===a)||null,k=a=>{if(a==="pool")return{kind:"pool"};if(a==="hidden")return{kind:"hidden"};const l=Number(a.slice(1));return Number.isFinite(l)?{kind:"group",gi:l}:null},N=(t==null?void 0:t.kind)==="view"?t.vid:null,g=()=>{o(null),c(null)},j=a=>c(l=>l&&l.key===a.key&&l.index===a.index&&l.group===a.group?l:a),y=()=>{if((t==null?void 0:t.kind)==="view"&&i){const a=k(i.key);if(a){const l=Y(n,t.vid,a,i.index,p),h=M(n,t.vid,a,l,p);h!==n&&r(h)}}g()},x=(a,l="")=>({className:`${l} ${(i==null?void 0:i.key)===a&&!i.group?"drop-target":""}`,onDragOver:h=>{N&&(h.preventDefault(),j({key:a,index:null}))},onDragLeave:h=>{const u=h.relatedTarget;(!u||!h.currentTarget.contains(u))&&c(v=>(v==null?void 0:v.key)===a?null:v)},onDrop:h=>{h.preventDefault(),y()}}),b=(a,l,h)=>({onDragOver:u=>{if(!N||(u.preventDefault(),u.stopPropagation(),N===l))return;const v=u.currentTarget.getBoundingClientRect(),w=u.clientY>v.top+v.height/2;j({key:a,index:h+(w?1:0)})},onDrop:u=>{u.preventDefault(),u.stopPropagation(),y()},onDragStart:()=>o({kind:"view",vid:l})}),$=(a,l,h)=>{const v=(i==null?void 0:i.key)===a&&!i.group?i.index===null?l.length:i.index:null;return e.jsxs("div",{className:"nav-list",children:[v===0&&e.jsx(S,{}),l.map((w,d)=>e.jsxs(f.Fragment,{children:[e.jsx(Z,{section:m(w),vid:w,dragging:N===w,...b(a,w,d),onDragEnd:g,actions:h(w)}),v===d+1&&e.jsx(S,{})]},w))]})},C=(a,l)=>e.jsxs("div",{className:"row",children:[e.jsx("span",{className:"desc",children:l}),(i==null?void 0:i.key)===a&&!i.group&&e.jsx(S,{})]}),D=P(n,p);return e.jsxs("div",{className:"stack",children:[e.jsxs("section",{...x("pool","nav-pool"),children:[e.jsx("div",{className:"hint",children:"平铺:不进分组也不隐藏的页面,直接显示头部(拖到这里 = 移出分组 / 取消隐藏)"}),D.length?$("pool",D,()=>null):C("pool","没有平铺的页面。")]}),n.groups.map((a,l)=>{const h=`g${l}`;return e.jsxs("section",{...x(h,"card nav-group"),children:[e.jsxs("div",{className:`colhead ${(i==null?void 0:i.key)===h&&i.group?"drop-target":""}`,onDragOver:u=>{(t==null?void 0:t.kind)==="group"&&(u.preventDefault(),j({key:h,index:null,group:!0}))},onDrop:u=>{u.preventDefault(),(t==null?void 0:t.kind)==="group"&&t.gi!==l&&r(z(n,t.gi,l-t.gi)),g()},children:[e.jsx("span",{className:"grip",title:"拖动调整分组顺序",draggable:!0,onDragStart:()=>o({kind:"group",gi:l}),onDragEnd:g}),e.jsx("input",{className:"nav-title",placeholder:"组名,如「求职」",value:a.title,onChange:u=>r(q(n,l,u.target.value))}),e.jsxs("span",{className:"muted",children:[a.views.length," 个页面"]}),e.jsx("span",{className:"right rowgap",children:e.jsx("button",{className:"btn small ghost",onClick:()=>r(J(n,l)),children:"删除组"})})]}),a.views.length?$(h,a.views,u=>e.jsx("button",{className:"btn small ghost",onClick:()=>r(Q(n,u,p)),children:"移出"})):C(h,"空分组——把页面拖进来。")]},l)}),e.jsxs("section",{...x("hidden","card nav-group nav-hidden"),children:[e.jsxs("div",{className:"colhead",children:["隐藏",e.jsxs("span",{className:"muted",children:[n.hidden.length," 个页面"]}),e.jsx("span",{className:"right muted",children:"不进头部 · 深链仍可用"})]}),n.hidden.length?$("hidden",n.hidden,()=>null):C("hidden","没有隐藏的页面——把不常用的拖进来。")]}),e.jsxs("div",{className:"rowgap",children:[e.jsx("button",{className:"btn",onClick:()=>r(A(n)),children:"新增分组"}),e.jsx("span",{className:"hint",children:"组顺序 = 头部显示顺序;组内顺序 = 展开列表顺序"})]})]})}function S(){return e.jsx("div",{className:"drop-ind","aria-hidden":"true"})}function Z({section:s,vid:n,dragging:r,actions:t,onDragStart:o,onDragEnd:i,onDragOver:c,onDrop:p}){return e.jsxs("div",{className:`row nav-row ${r?"dragging":""}`,onDragOver:c,onDrop:p,children:[e.jsx("span",{className:"grip",title:"拖动:换位 / 换容器",draggable:!0,onDragStart:o,onDragEnd:i}),e.jsx("span",{className:"name",children:s?s.title:`页面已删除(${n})`}),e.jsx("span",{className:"desc",children:s?n:"保存前请移出"}),e.jsx("span",{className:"acts",children:t})]})}const ee=`mn-ws setting set --set 'navGroups=[{"title":"求职","views":["home"]}]' / --set navHidden=home / --set navOrder=["home"]`;function te(){const{boot:s,client:n,settings:r,refreshSettings:t}=E(),o=G(),i=H(),[c,p]=f.useState(""),[m,k]=f.useState(!1),[N,g]=f.useState(null),[j,y]=f.useState(!1),[x,b]=f.useState(O()),[$,C]=f.useState(O()),D=f.useMemo(()=>((r==null?void 0:r.views)||[]).map(d=>({id:d.id,title:d.title})),[r]),a=f.useMemo(()=>D.map(d=>d.id),[D]);f.useEffect(()=>{if(!r)return;const d=V(r.settings);b(d),C(d)},[r]);const l=f.useMemo(()=>W(x,a),[x,a]),h=_(x,$);async function u(){if(!c.trim()){o("请先填写名字");return}y(!0);try{const d=await n["home.greet"]({name:c.trim(),loud:m});g(d)}catch(d){o(String((d==null?void 0:d.message)||d))}finally{y(!1)}}const v=()=>i(async()=>{if(l.length){o(`保存失败:${l[0].message}`);return}await F("/api/settings",{method:"PATCH",body:{set:B(x)}}),await t(),o("设置已保存")}),w=()=>b(structuredClone($));return e.jsxs("div",{className:"stack",style:{padding:16},children:[e.jsxs("div",{className:"card",children:[e.jsx("div",{className:"colhead",children:"问候(演示动作)"}),e.jsxs("div",{style:{padding:14},children:[e.jsxs("div",{className:"toolbar",children:[e.jsx("input",{value:c,placeholder:"你的名字",onChange:d=>p(d.target.value),onKeyDown:d=>{d.key==="Enter"&&u()}}),e.jsxs("label",{style:{display:"inline-flex",gap:6,alignItems:"center"},children:[e.jsx("input",{type:"checkbox",checked:m,onChange:d=>k(d.target.checked)}),"大声"]}),e.jsx("button",{className:"btn",disabled:j,onClick:()=>void u(),children:j?"问候中…":"打招呼"})]}),N&&e.jsxs("div",{style:{marginTop:12},children:[e.jsx("strong",{children:N.greeting}),e.jsxs("div",{className:"muted",style:{marginTop:4},children:["第 ",N.count," 次 · ",N.at]})]})]})]}),e.jsxs("div",{className:"card",children:[e.jsx("div",{className:"colhead",children:"运行信息"}),e.jsxs("dl",{className:"kv",children:[e.jsxs("div",{className:"kv-row",children:[e.jsx("dt",{children:"应用"}),e.jsx("dd",{children:s?`${s.app.name} v${s.app.version}`:"加载中…"})]}),e.jsxs("div",{className:"kv-row",children:[e.jsx("dt",{children:"存储"}),e.jsx("dd",{children:e.jsx(I,{text:(s==null?void 0:s.storePath)||"",children:(s==null?void 0:s.storePath)||"…"})})]}),e.jsxs("div",{className:"kv-row",children:[e.jsx("dt",{children:"环境变量"}),e.jsx("dd",{children:s==null?void 0:s.storeEnv})]})]})]}),e.jsxs("div",{className:"card",children:[e.jsxs("div",{className:"colhead",children:["外观",e.jsx("span",{className:"right muted",children:"色彩主题 · 点击即保存"})]}),e.jsx("div",{style:{padding:12},className:"stack",children:e.jsxs("div",{className:"toolbar",children:[e.jsx(L,{}),e.jsxs("span",{className:"muted",children:["浅色 / 深色 / 跟随系统(深色下自动切换为暗色 token);CLI 等价:",e.jsx("code",{children:"mn-ws setting set --key theme --value dark"})]})]})})]}),e.jsxs("div",{className:"card",children:[e.jsxs("div",{className:"colhead",children:["栏目管理",e.jsxs("span",{className:"right muted",children:["头部显示 ",a.length-x.hidden.length," 个 · 隐藏 ",x.hidden.length," 个",x.groups.length?` · ${x.groups.length} 个分组`:""]})]}),e.jsxs("div",{style:{padding:12},className:"stack",children:[e.jsxs("div",{className:"toolbar",children:[e.jsxs("span",{className:"muted",children:["拖动就是把结构摆成你要的样子:页面可以拖进分组、组内换位、拖回平铺区即移出;拖分组把手换分组顺序。 被隐藏的页面只是头部不显示入口,用 ",e.jsx("code",{children:"#/页面id"})," 直达仍然可用。"]}),e.jsx("span",{className:"right rowgap",children:h?e.jsxs(e.Fragment,{children:[e.jsx("span",{className:"tag",children:"有未保存的改动"}),e.jsx("button",{className:"btn small",onClick:()=>{v()},children:"保存"}),e.jsx("button",{className:"btn small ghost",onClick:w,children:"放弃改动"})]}):e.jsx("span",{className:"muted",children:"已保存"})})]}),e.jsx(X,{sections:D,value:x,onChange:b}),l.map(d=>e.jsxs("div",{className:"bad",children:["· ",d.message]},d.field))]})]}),e.jsxs("div",{className:"muted",style:{padding:"0 2px"},children:["CLI 等价:",e.jsx("code",{children:ee})]}),e.jsx(R,{module:"home"})]})}export{te as default};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{u as B,r as n,j as s}from"./index-XCFB6TU2.js";import{C as F}from"./CliHints-pV4HIvlV.js";function H(){const{client:l}=B(),[a,L]=n.useState(null),[h,$]=n.useState(null),[x,A]=n.useState(null),[g,v]=n.useState([]),[d,r]=n.useState(!1),[N,c]=n.useState(""),m=n.useCallback(async()=>{try{const e=await l["bridge.status"]({}),t=await l["bridge.apps"]({});L(e),$(t)}catch(e){c(String((e==null?void 0:e.message)||e))}},[l]),j=n.useCallback(async()=>{try{const e=await l["auth.list"]({});v(e.accounts)}catch{v([])}},[l]);n.useEffect(()=>{m(),j();const e=window.setInterval(()=>{m()},3e3);return()=>window.clearInterval(e)},[m,j]);async function p(e){r(!0),c("");try{await e(),await m(),await j()}catch(t){c(String((t==null?void 0:t.message)||t))}finally{r(!1)}}const o=(h==null?void 0:h.configured)??[],b=(h==null?void 0:h.candidates)??[],w=new Set(o.map(e=>e.app)),[y,k]=n.useState(""),[f,C]=n.useState(""),[S,I]=n.useState("");async function u(){const e=y.trim();if(!e){c("要先给应用起个名字");return}const t=Number(f.trim());r(!0),c("");try{const i=await l["bridge.apps.add"]({name:e,port:Number.isFinite(t)&&t>0?t:void 0,title:S.trim()||void 0});if(!i.ok){c(i.error||"注册失败");return}k(""),C(""),I(""),await m()}catch(i){c(String((i==null?void 0:i.message)||i))}finally{r(!1)}}async function D(e){r(!0),c("");try{const t=await l["bridge.apps.remove"]({name:e});if(!t.ok){c(t.error||"移除失败");return}await m()}catch(t){c(String((t==null?void 0:t.message)||t))}finally{r(!1)}}async function E(e,t){const i=new Set(w);t?i.add(e):i.delete(e),await p(()=>l["bridge.whitelist.set"]({apps:[...i].join(",")}))}async function K(){r(!0);try{const e=await l["bridge.catalog"]({});A(e)}catch(e){c(String((e==null?void 0:e.message)||e))}finally{r(!1)}}const M={idle:"未启动",connecting:"连接中",connected:"已连接(注册中)",registered:"已注册",reconnecting:"重连中",stopped:"已停止",shutdown:"服务端要求下线",error:"出错"};return s.jsxs("div",{className:"stack",style:{padding:16},children:[s.jsxs("div",{className:"card",children:[s.jsxs("div",{className:"colhead",children:["连接状态",s.jsxs("span",{className:"right muted",children:["CLI 等价:",s.jsx("code",{children:"mn-ws status"})]})]}),s.jsxs("dl",{className:"kv",children:[s.jsxs("div",{className:"kv-row",children:[s.jsx("dt",{children:"状态"}),s.jsxs("dd",{children:[s.jsx("strong",{children:a?M[a.state]||a.state:"…"}),a!=null&&a.retryInMs?`(${Math.round(a.retryInMs/1e3)}s 后重试)`:"",a!=null&&a.reason?` · ${a.reason}`:""]})]}),s.jsxs("div",{className:"kv-row",children:[s.jsx("dt",{children:"server"}),s.jsx("dd",{children:(a==null?void 0:a.url)||"…"})]}),s.jsxs("div",{className:"kv-row",children:[s.jsx("dt",{children:"本机标识"}),s.jsx("dd",{children:(a==null?void 0:a.clientId)||"…"})]}),s.jsxs("div",{className:"kv-row",children:[s.jsx("dt",{children:"身份"}),s.jsxs("dd",{children:[(a==null?void 0:a.identity)||"…",a!=null&&a.loggedIn?`(${a.via==="cli"?"复用 CLI 登录态":"面板登录"})`:""]})]})]}),s.jsxs("div",{className:"toolbar",style:{padding:12},children:[s.jsx("button",{className:"btn",disabled:d,onClick:()=>void p(()=>l["bridge.start"]({})),children:"起桥"}),s.jsx("button",{className:"btn ghost",disabled:d,onClick:()=>void p(()=>l["bridge.stop"]({})),children:"停桥"}),s.jsx("button",{className:"btn ghost",disabled:d,onClick:()=>void K(),children:"拉远端目录"})]}),N&&s.jsx("div",{className:"bad",style:{padding:"0 14px 12px"},children:N})]}),s.jsxs("div",{className:"card",children:[s.jsxs("div",{className:"colhead",children:["白名单",s.jsxs("span",{className:"right muted",children:["CLI 等价:",s.jsx("code",{children:"mn-ws apps set --apps nx-kv,nx-rh"})]})]}),s.jsxs("div",{style:{padding:12},className:"stack",children:[s.jsx("div",{className:"muted",children:"只有勾上的应用会被桥。端口在监听 ≠ 可以桥 —— 白名单说了算, 否则扫到端口就自动开桥等于把整台机器暴露出去。"}),o.length>0&&s.jsxs("div",{className:"stack",children:[s.jsx("div",{className:"muted",children:"已桥接:"}),o.map(e=>s.jsxs("label",{style:{display:"inline-flex",gap:6,alignItems:"center"},children:[s.jsx("input",{type:"checkbox",checked:!0,disabled:!0,readOnly:!0}),s.jsxs("span",{children:[e.app," ",s.jsx("span",{className:"muted",children:e.port??"—"})," ",e.title&&e.title!==e.app?s.jsx("span",{className:"muted",children:e.title}):null," ",e.alive?s.jsx("span",{className:"tag",children:"在监听"}):s.jsx("span",{className:"tag warn",children:"未运行"}),e.custom?s.jsx("span",{className:"tag",children:"自定义"}):null]})]},e.app))]}),b.length>0&&s.jsxs("div",{className:"stack",children:[s.jsx("div",{className:"muted",children:"本机在跑、还没桥:"}),b.map(e=>s.jsxs("label",{style:{display:"inline-flex",gap:6,alignItems:"center"},children:[s.jsx("input",{type:"checkbox",checked:w.has(e.app),disabled:d,onChange:t=>{E(e.app,t.target.checked)}}),s.jsxs("span",{children:[e.app," ",s.jsx("span",{className:"muted",children:e.port})," ",e.title]})]},e.app))]}),o.length>0&&s.jsx("div",{className:"toolbar",children:o.map(e=>e.custom?s.jsxs("button",{className:"btn small ghost",disabled:d,onClick:()=>{D(e.app)},children:["移除 ",e.app]},e.app):s.jsxs("button",{className:"btn small ghost",disabled:d,onClick:()=>{E(e.app,!1)},children:["取消 ",e.app]},e.app))})]})]}),s.jsxs("div",{className:"card",children:[s.jsxs("div",{className:"colhead",children:["动态注册",s.jsxs("span",{className:"right muted",children:["CLI 等价:",s.jsx("code",{children:"mn-ws apps add my-api --port 9999"})]})]}),s.jsxs("div",{style:{padding:12},className:"stack",children:[s.jsxs("div",{className:"muted",children:["已知表里没有的服务也能被桥出去:给它起个**路由标识**(小写字母开头, 只含小写字母/数字/连字符)和端口,它就进白名单,随注册帧上报给 server 半 —— 别的客户端从目录里看到之后,用 ",s.jsx("code",{children:"X-Nx-App: <名字>"})," 就能打过来。"]}),s.jsxs("div",{className:"toolbar",children:[s.jsx("input",{value:y,placeholder:"路由标识,如 my-api",onChange:e=>k(e.target.value),onKeyDown:e=>{e.key==="Enter"&&u()}}),s.jsx("input",{value:f,placeholder:"端口,如 9999",onChange:e=>C(e.target.value),onKeyDown:e=>{e.key==="Enter"&&u()}}),s.jsx("input",{value:S,placeholder:"显示名(可选)",onChange:e=>I(e.target.value),onKeyDown:e=>{e.key==="Enter"&&u()}}),s.jsx("button",{className:"btn",disabled:d,onClick:()=>{u()},children:"注册"})]}),o.filter(e=>e.custom).length>0&&s.jsxs("div",{className:"muted",children:["已注册的自定义应用:",o.filter(e=>e.custom).map(e=>` ${e.app}(${e.port??"?"})`).join("")]})]})]}),x&&s.jsxs("div",{className:"card",children:[s.jsxs("div",{className:"colhead",children:["远端目录",s.jsxs("span",{className:"right muted",children:["CLI 等价:",s.jsx("code",{children:"mn-ws catalog"})]})]}),x.ok?s.jsx("dl",{className:"kv",children:x.apps.map(e=>s.jsxs("div",{className:"kv-row",children:[s.jsx("dt",{children:e.app}),s.jsxs("dd",{children:[e.title," ",s.jsx("span",{className:"muted",children:e.port??"—"})," · ",e.bridgeId]})]},e.app))}):s.jsxs("div",{className:"bad",style:{padding:14},children:["拉目录失败:",x.error]})]}),s.jsxs("div",{className:"card",children:[s.jsxs("div",{className:"colhead",children:["账号",s.jsxs("span",{className:"right muted",children:["CLI 等价:",s.jsx("code",{children:"mn-ws auth list"})," / ",s.jsx("code",{children:"mn-ws auth switch <账号>"})]})]}),s.jsx("div",{style:{padding:12},className:"stack",children:g.length===0?s.jsxs("div",{className:"muted",children:["本机还没有已存账号。登录一次:",s.jsx("code",{children:"mn-ws auth login"})]}):s.jsxs(s.Fragment,{children:[g.map(e=>s.jsxs("div",{className:"toolbar",children:[s.jsxs("span",{children:[e.label,e.active?s.jsx("span",{className:"tag",children:"当前"}):null,e.expired?s.jsx("span",{className:"tag warn",children:"已过期"}):null]}),!e.active&&s.jsx("button",{className:"btn small ghost",disabled:d,onClick:()=>{p(()=>l["auth.switch"]({account:e.key}))},children:"切到它"})]},e.key)),s.jsx("div",{className:"toolbar",children:s.jsx("button",{className:"btn small ghost",disabled:d,onClick:()=>{p(()=>l["auth.logout"]({}))},children:"退出当前账号"})})]})})]}),s.jsx(F,{module:"bridge"})]})}export{H as default};
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
<link rel="icon" type="image/png" sizes="16x16" href="/favicon-16.png">
|
|
11
11
|
<link rel="icon" type="image/x-icon" href="/favicon.ico">
|
|
12
12
|
<link rel="apple-touch-icon" href="/logo-rounded.png">
|
|
13
|
-
<script type="module" crossorigin src="/assets/index-
|
|
13
|
+
<script type="module" crossorigin src="/assets/index-XCFB6TU2.js"></script>
|
|
14
14
|
<link rel="stylesheet" crossorigin href="/assets/index-BjGe8ggI.css">
|
|
15
15
|
</head>
|
|
16
16
|
<body>
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mn-ws",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "HTTP 与 WebSocket 双向桥的客户端半:把本机 nx 服务桥给远端 HTTP 客户端",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -19,25 +19,11 @@
|
|
|
19
19
|
"bin",
|
|
20
20
|
"assets"
|
|
21
21
|
],
|
|
22
|
-
"scripts": {
|
|
23
|
-
"start": "pnpm build && node bin/ws.mjs serve",
|
|
24
|
-
"dev": "node --import tsx scripts/dev.mjs",
|
|
25
|
-
"dev:serve": "node --import tsx src/runtime/cli.ts serve --no-open",
|
|
26
|
-
"link:local": "node scripts/link-local.mjs",
|
|
27
|
-
"unlink:local": "node scripts/link-local.mjs --unlink",
|
|
28
|
-
"build": "tsc -b tsconfig.node.json && vite build",
|
|
29
|
-
"typecheck": "tsc -b tsconfig.node.json tsconfig.web.json",
|
|
30
|
-
"lint": "eslint .",
|
|
31
|
-
"test:smoke": "node tests/smoke.mjs",
|
|
32
|
-
"test:unit": "node --import tsx --test \"tests/unit/*.test.ts\" \"tests/unit/*.test.mjs\"",
|
|
33
|
-
"test:e2e": "node tests/e2e-remote.js",
|
|
34
|
-
"test": "pnpm run lint && pnpm run typecheck && pnpm run build && pnpm run test:smoke && pnpm run test:unit"
|
|
35
|
-
},
|
|
36
22
|
"dependencies": {
|
|
37
|
-
"mn-ws-server": "workspace:*",
|
|
38
23
|
"react": "^19.0.0",
|
|
39
24
|
"react-dom": "^19.0.0",
|
|
40
|
-
"ws": "^8.18.0"
|
|
25
|
+
"ws": "^8.18.0",
|
|
26
|
+
"mn-ws-server": "0.3.0"
|
|
41
27
|
},
|
|
42
28
|
"devDependencies": {
|
|
43
29
|
"@types/node": "^22.10.0",
|
|
@@ -62,5 +48,19 @@
|
|
|
62
48
|
"homepage": "https://github.com/On-DevPlan/mn-ws#readme",
|
|
63
49
|
"bugs": {
|
|
64
50
|
"url": "https://github.com/On-DevPlan/mn-ws/issues"
|
|
51
|
+
},
|
|
52
|
+
"scripts": {
|
|
53
|
+
"start": "pnpm build && node bin/ws.mjs serve",
|
|
54
|
+
"dev": "node --import tsx scripts/dev.mjs",
|
|
55
|
+
"dev:serve": "node --import tsx src/runtime/cli.ts serve --no-open",
|
|
56
|
+
"link:local": "node scripts/link-local.mjs",
|
|
57
|
+
"unlink:local": "node scripts/link-local.mjs --unlink",
|
|
58
|
+
"build": "tsc -b tsconfig.node.json && vite build",
|
|
59
|
+
"typecheck": "tsc -b tsconfig.node.json tsconfig.web.json",
|
|
60
|
+
"lint": "eslint .",
|
|
61
|
+
"test:smoke": "node tests/smoke.mjs",
|
|
62
|
+
"test:unit": "node --import tsx --test \"tests/unit/*.test.ts\" \"tests/unit/*.test.mjs\"",
|
|
63
|
+
"test:e2e": "node tests/e2e-remote.js",
|
|
64
|
+
"test": "pnpm run lint && pnpm run typecheck && pnpm run build && pnpm run test:smoke && pnpm run test:unit"
|
|
65
65
|
}
|
|
66
|
-
}
|
|
66
|
+
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{u as S,r as d,j as s}from"./index-BTRKdMIW.js";import{C as L}from"./CliHints-BOxU-Duc.js";function M(){const{client:l}=S(),[a,y]=d.useState(null),[t,k]=d.useState(null),[o,f]=d.useState(null),[g,u]=d.useState([]),[n,h]=d.useState(!1),[v,x]=d.useState(""),m=d.useCallback(async()=>{try{const e=await l["bridge.status"]({}),c=await l["bridge.apps"]({});y(e),k(c)}catch(e){x(String((e==null?void 0:e.message)||e))}},[l]),j=d.useCallback(async()=>{try{const e=await l["auth.list"]({});u(e.accounts)}catch{u([])}},[l]);d.useEffect(()=>{m(),j();const e=window.setInterval(()=>{m()},3e3);return()=>window.clearInterval(e)},[m,j]);async function i(e){h(!0),x("");try{await e(),await m(),await j()}catch(c){x(String((c==null?void 0:c.message)||c))}finally{h(!1)}}const r=(t==null?void 0:t.configured)??[],N=(t==null?void 0:t.candidates)??[],b=new Set(r.map(e=>e.app));async function w(e,c){const p=new Set(b);c?p.add(e):p.delete(e),await i(()=>l["bridge.whitelist.set"]({apps:[...p].join(",")}))}async function C(){h(!0);try{const e=await l["bridge.catalog"]({});f(e)}catch(e){x(String((e==null?void 0:e.message)||e))}finally{h(!1)}}const I={idle:"未启动",connecting:"连接中",connected:"已连接(注册中)",registered:"已注册",reconnecting:"重连中",stopped:"已停止",shutdown:"服务端要求下线",error:"出错"};return s.jsxs("div",{className:"stack",style:{padding:16},children:[s.jsxs("div",{className:"card",children:[s.jsxs("div",{className:"colhead",children:["连接状态",s.jsxs("span",{className:"right muted",children:["CLI 等价:",s.jsx("code",{children:"mn-ws status"})]})]}),s.jsxs("dl",{className:"kv",children:[s.jsxs("div",{className:"kv-row",children:[s.jsx("dt",{children:"状态"}),s.jsxs("dd",{children:[s.jsx("strong",{children:a?I[a.state]||a.state:"…"}),a!=null&&a.retryInMs?`(${Math.round(a.retryInMs/1e3)}s 后重试)`:"",a!=null&&a.reason?` · ${a.reason}`:""]})]}),s.jsxs("div",{className:"kv-row",children:[s.jsx("dt",{children:"server"}),s.jsx("dd",{children:(a==null?void 0:a.url)||"…"})]}),s.jsxs("div",{className:"kv-row",children:[s.jsx("dt",{children:"本机标识"}),s.jsx("dd",{children:(a==null?void 0:a.clientId)||"…"})]}),s.jsxs("div",{className:"kv-row",children:[s.jsx("dt",{children:"身份"}),s.jsxs("dd",{children:[(a==null?void 0:a.identity)||"…",a!=null&&a.loggedIn?`(${a.via==="cli"?"复用 CLI 登录态":"面板登录"})`:""]})]})]}),s.jsxs("div",{className:"toolbar",style:{padding:12},children:[s.jsx("button",{className:"btn",disabled:n,onClick:()=>void i(()=>l["bridge.start"]({})),children:"起桥"}),s.jsx("button",{className:"btn ghost",disabled:n,onClick:()=>void i(()=>l["bridge.stop"]({})),children:"停桥"}),s.jsx("button",{className:"btn ghost",disabled:n,onClick:()=>void C(),children:"拉远端目录"})]}),v&&s.jsx("div",{className:"bad",style:{padding:"0 14px 12px"},children:v})]}),s.jsxs("div",{className:"card",children:[s.jsxs("div",{className:"colhead",children:["白名单",s.jsxs("span",{className:"right muted",children:["CLI 等价:",s.jsx("code",{children:"mn-ws apps set --apps nx-kv,nx-rh"})]})]}),s.jsxs("div",{style:{padding:12},className:"stack",children:[s.jsx("div",{className:"muted",children:"只有勾上的应用会被桥。端口在监听 ≠ 可以桥 —— 白名单说了算, 否则扫到端口就自动开桥等于把整台机器暴露出去。"}),r.length>0&&s.jsxs("div",{className:"stack",children:[s.jsx("div",{className:"muted",children:"已桥接:"}),r.map(e=>s.jsxs("label",{style:{display:"inline-flex",gap:6,alignItems:"center"},children:[s.jsx("input",{type:"checkbox",checked:!0,disabled:!0,readOnly:!0}),s.jsxs("span",{children:[e.app," ",s.jsx("span",{className:"muted",children:e.port??"—"})," ",e.alive?s.jsx("span",{className:"tag",children:"在监听"}):s.jsx("span",{className:"tag warn",children:"未运行"})]})]},e.app))]}),N.length>0&&s.jsxs("div",{className:"stack",children:[s.jsx("div",{className:"muted",children:"本机在跑、还没桥:"}),N.map(e=>s.jsxs("label",{style:{display:"inline-flex",gap:6,alignItems:"center"},children:[s.jsx("input",{type:"checkbox",checked:b.has(e.app),disabled:n,onChange:c=>{w(e.app,c.target.checked)}}),s.jsxs("span",{children:[e.app," ",s.jsx("span",{className:"muted",children:e.port})," ",e.title]})]},e.app))]}),r.length>0&&s.jsx("div",{className:"toolbar",children:r.map(e=>s.jsxs("button",{className:"btn small ghost",disabled:n,onClick:()=>{w(e.app,!1)},children:["取消 ",e.app]},e.app))})]})]}),o&&s.jsxs("div",{className:"card",children:[s.jsxs("div",{className:"colhead",children:["远端目录",s.jsxs("span",{className:"right muted",children:["CLI 等价:",s.jsx("code",{children:"mn-ws catalog"})]})]}),o.ok?s.jsx("dl",{className:"kv",children:o.apps.map(e=>s.jsxs("div",{className:"kv-row",children:[s.jsx("dt",{children:e.app}),s.jsxs("dd",{children:[e.title," ",s.jsx("span",{className:"muted",children:e.port??"—"})," · ",e.bridgeId]})]},e.app))}):s.jsxs("div",{className:"bad",style:{padding:14},children:["拉目录失败:",o.error]})]}),s.jsxs("div",{className:"card",children:[s.jsxs("div",{className:"colhead",children:["账号",s.jsxs("span",{className:"right muted",children:["CLI 等价:",s.jsx("code",{children:"mn-ws auth list"})," / ",s.jsx("code",{children:"mn-ws auth switch <账号>"})]})]}),s.jsx("div",{style:{padding:12},className:"stack",children:g.length===0?s.jsxs("div",{className:"muted",children:["本机还没有已存账号。登录一次:",s.jsx("code",{children:"mn-ws auth login"})]}):s.jsxs(s.Fragment,{children:[g.map(e=>s.jsxs("div",{className:"toolbar",children:[s.jsxs("span",{children:[e.label,e.active?s.jsx("span",{className:"tag",children:"当前"}):null,e.expired?s.jsx("span",{className:"tag warn",children:"已过期"}):null]}),!e.active&&s.jsx("button",{className:"btn small ghost",disabled:n,onClick:()=>{i(()=>l["auth.switch"]({account:e.key}))},children:"切到它"})]},e.key)),s.jsx("div",{className:"toolbar",children:s.jsx("button",{className:"btn small ghost",disabled:n,onClick:()=>{i(()=>l["auth.logout"]({}))},children:"退出当前账号"})})]})})]}),s.jsx(L,{module:"bridge"})]})}export{M as default};
|