nx-sk 0.3.1 → 0.3.3

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.
@@ -1,4 +1,4 @@
1
- import{u as C,r as i,a as h,j as s,b as f,T as j,E as b,C as y,M as E}from"./index-CpF00ycO.js";function W(){var u,N,v;const{boot:r,toast:d,guard:w}=C(),[g,S]=i.useState([]),[a,k]=i.useState(null),[c,n]=i.useState({format:"both",section:"",out:"",withSecrets:!1}),[o,m]=i.useState(null),x=i.useCallback(async()=>{try{const[e,l]=await Promise.all([h("/api/sections"),h("/api/exports")]);S(e.sections),k(l)}catch(e){d(e.message,"bad")}},[d]);i.useEffect(()=>{x()},[x]),i.useEffect(()=>{const e=r==null?void 0:r.settings;e&&n(l=>({...l,format:e.exportFormat||"both",withSecrets:!!e.includeSecretsInExport,out:e.exportDir||""}))},[r]);const $=()=>({format:c.format,out:c.out.trim()||void 0,section:c.section||void 0,...c.withSecrets?{"with-secrets":!0}:{"no-secrets":!0}}),p=w(async e=>{const l=await h("/api/export",{method:"POST",body:{...$(),"dry-run":!!e}});if(e){m({title:"试运行(没有写盘)",body:s.jsx("pre",{className:"block",children:`目录: ${l.wouldWrite.dir}
1
+ import{u as C,r as i,a as h,j as s,b as f,T as j,E as b,C as y,M as E}from"./index-BnVuH1lC.js";function W(){var u,N,v;const{boot:r,toast:d,guard:w}=C(),[g,S]=i.useState([]),[a,k]=i.useState(null),[c,n]=i.useState({format:"both",section:"",out:"",withSecrets:!1}),[o,m]=i.useState(null),x=i.useCallback(async()=>{try{const[e,l]=await Promise.all([h("/api/sections"),h("/api/exports")]);S(e.sections),k(l)}catch(e){d(e.message,"bad")}},[d]);i.useEffect(()=>{x()},[x]),i.useEffect(()=>{const e=r==null?void 0:r.settings;e&&n(l=>({...l,format:e.exportFormat||"both",withSecrets:!!e.includeSecretsInExport,out:e.exportDir||""}))},[r]);const $=()=>({format:c.format,out:c.out.trim()||void 0,section:c.section||void 0,...c.withSecrets?{"with-secrets":!0}:{"no-secrets":!0}}),p=w(async e=>{const l=await h("/api/export",{method:"POST",body:{...$(),"dry-run":!!e}});if(e){m({title:"试运行(没有写盘)",body:s.jsx("pre",{className:"block",children:`目录: ${l.wouldWrite.dir}
2
2
  栏目: ${l.wouldWrite.sections} 条目: ${l.wouldWrite.entries}
3
3
  凭据: ${l.wouldWrite.withSecrets?"含明文":"已打码"}
4
4
 
@@ -1 +1 @@
1
- import{u as L,r as x,a as h,j as e,T as v,E as S,C as F,M as R}from"./index-CpF00ycO.js";const T=["text","textarea","number","date","month","bool","select","tags","secret"];function A(){const{reload:c,toast:n,guard:m,dialog:j}=L(),[i,b]=x.useState(null),[d,p]=x.useState([]),[r,u]=x.useState(null),[o,a]=x.useState(null),t=x.useCallback(async()=>{try{const[s,l]=await Promise.all([h("/api/sections"),h("/api/sections/templates")]);b(s),p(l.templates),u(null)}catch(s){u(s.message)}},[]);x.useEffect(()=>{t()},[t]);const f=m(async s=>{const l=await h(`/api/sections/${encodeURIComponent(s.id)}/dump`);a({kind:"dump",title:`${s.title}(${s.id})的全部信息`,body:e.jsx("pre",{className:"block",children:JSON.stringify(l,null,2)})})}),g=m(async s=>{const l=await h(`/api/sections/${encodeURIComponent(s.id)}`);a({kind:"edit",id:s.id,form:{title:l.title,description:l.description,order:String(l.order),titleLabel:l.titleLabel,titleField:l.titleField||""},full:l})}),y=m(async s=>{const l={id:s.id.trim(),title:s.title.trim()||s.id.trim(),template:s.template||void 0,description:s.description,order:Number(s.order)||50};await h("/api/sections",{method:"POST",body:l}),n("栏目已创建"),a(null),await t(),await c()}),k=m(async s=>{const l={title:s.form.title,description:s.form.description,order:Number(s.form.order)||50,titleLabel:s.form.titleLabel,titleField:s.form.titleField};await h(`/api/sections/${encodeURIComponent(s.id)}`,{method:"PATCH",body:l}),n("栏目已更新");const N=await h(`/api/sections/${encodeURIComponent(s.id)}`);a({...s,full:N}),await t(),await c()}),C=m(async(s,l)=>{await h(`/api/sections/${encodeURIComponent(s.id)}`,{method:"PATCH",body:{"add-field":l}}),n(`已新增字段 ${l.key}`);const N=await h(`/api/sections/${encodeURIComponent(s.id)}`);a({...s,full:N}),await t()}),w=m(async(s,l)=>{if(!await j({message:`从字段字典里删掉「${l}」?已填的值会留在条目里(只是不再显示/校验)。`,danger:!0,confirmText:"删除字段"}))return;await h(`/api/sections/${encodeURIComponent(s.id)}`,{method:"PATCH",body:{"remove-field":l}}),n(`已删字段 ${l}`);const E=await h(`/api/sections/${encodeURIComponent(s.id)}`);a({...s,full:E}),await t()}),$=m(async s=>{await j({message:`删除栏目「${s.title}」,连带其中 ${s.entries} 条条目?删除前会自动留快照。`,danger:!0,confirmText:"连带删除"})&&(await h(`/api/sections/${encodeURIComponent(s.id)}`,{method:"DELETE",body:{force:!0}}),n("栏目已删除"),await t(),await c())});return r?e.jsxs("div",{className:"pad stack",children:[e.jsx("div",{className:"bad",children:e.jsx("strong",{children:"读不到栏目"})}),e.jsx("pre",{className:"block",children:r})]}):i?e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:"toolbar rowgap pad",children:[e.jsx("strong",{children:"栏目"}),e.jsxs("span",{className:"muted",children:["共 ",i.count," 个 · 条目 ",i.totalEntries," 条"]}),e.jsx("span",{className:"grow"}),e.jsx("button",{className:"btn small ghost",onClick:t,children:"刷新"}),e.jsx("button",{className:"btn small",onClick:()=>{var s;return a({kind:"create",form:{id:"",title:"",template:((s=d[0])==null?void 0:s.id)||"",description:"",order:"50"}})},children:"新建栏目"})]}),e.jsxs("div",{className:"card",children:[e.jsx("div",{className:"colhead",children:"全部栏目"}),e.jsx("div",{className:"colbody",children:i.sections.length?i.sections.map(s=>e.jsxs("div",{className:"row",children:[e.jsx("span",{className:"name",children:s.title}),e.jsx("span",{className:"mono muted",children:s.id}),s.template?e.jsx(v,{children:s.template}):e.jsx(v,{children:"自定义"}),e.jsx("span",{className:"desc",children:s.description}),e.jsxs("span",{className:"acts",children:[e.jsxs("span",{className:"tag",children:[s.fields," 字段"]}),e.jsxs("span",{className:"tag",children:[s.entries," 条目"]}),e.jsx("button",{className:"btn small ghost",onClick:()=>f(s),children:"全部信息"}),e.jsx("button",{className:"btn small ghost",onClick:()=>g(s),children:"编辑"}),e.jsx("button",{className:"btn small ghost",onClick:()=>$(s),children:"删除"})]})]},s.id)):e.jsx(S,{children:"还没有栏目。点「新建栏目」,用内置模板(求职 / 密钥)起步。"})})]}),e.jsx("div",{className:"pad hint",children:"栏目 = 一组同构条目 + 一份字段字典。字典是数据,所以这里加一个字段,CLI 与面板立刻就都能填它。"}),e.jsx(F,{module:"sections"}),o?e.jsxs(R,{title:I(o),onClose:()=>a(null),children:[o.kind==="dump"?o.body:null,o.kind==="create"?e.jsx(U,{templates:d,form:o.form,onChange:s=>a(l=>({...l,form:{...l.form,...s}})),onSubmit:()=>{if(!/^[a-z][a-z0-9_-]{0,63}$/.test(o.form.id.trim())){n("栏目 id 必须是小写字母开头,仅含 a-z 0-9 _ -","bad");return}y(o.form)}}):null,o.kind==="edit"?e.jsx(P,{modal:o,onChange:s=>a(l=>({...l,form:{...l.form,...s}})),onSave:()=>k(o),onAddField:s=>C(o,s),onRemoveField:s=>w(o,s),onClose:()=>a(null)}):null]}):null]}):e.jsx("div",{className:"pad muted",children:"加载中…"})}function I(c){return c.kind==="dump"?c.title:c.kind==="create"?"新建栏目":`编辑栏目 ${c.id}`}function U({templates:c,form:n,onChange:m,onSubmit:j}){return e.jsxs("div",{className:"stack",children:[e.jsxs("div",{className:"grid",children:[e.jsxs("div",{className:"field",children:[e.jsxs("div",{className:"flabel",children:[e.jsx("span",{children:"栏目 id"}),e.jsx("span",{className:"fkey",children:"小写字母开头,仅 a-z 0-9 _ -"})]}),e.jsx("div",{className:"fctrl",children:e.jsx("input",{value:n.id,onChange:i=>m({id:i.target.value}),placeholder:"例如 projects"})})]}),e.jsxs("div",{className:"field",children:[e.jsx("div",{className:"flabel",children:e.jsx("span",{children:"标题"})}),e.jsx("div",{className:"fctrl",children:e.jsx("input",{value:n.title,onChange:i=>m({title:i.target.value}),placeholder:"例如 项目档案"})})]}),e.jsxs("div",{className:"field",children:[e.jsx("div",{className:"flabel",children:e.jsx("span",{children:"从模板起步"})}),e.jsx("div",{className:"fctrl",children:e.jsxs("select",{value:n.template,onChange:i=>m({template:i.target.value}),children:[e.jsx("option",{value:"",children:"(空栏目,自定义字段)"}),c.map(i=>e.jsxs("option",{value:i.id,children:[i.label,"(",i.fields," 字段)"]},i.id))]})})]}),e.jsxs("div",{className:"field",children:[e.jsxs("div",{className:"flabel",children:[e.jsx("span",{children:"排序"}),e.jsx("span",{className:"fkey",children:"越小越靠前"})]}),e.jsx("div",{className:"fctrl",children:e.jsx("input",{type:"number",value:n.order,onChange:i=>m({order:i.target.value})})})]})]}),e.jsxs("div",{className:"field wide",children:[e.jsx("div",{className:"flabel",children:e.jsx("span",{children:"描述"})}),e.jsx("div",{className:"fctrl",children:e.jsx("input",{value:n.description,onChange:i=>m({description:i.target.value})})})]}),e.jsxs("div",{className:"rowgap",children:[e.jsx("button",{className:"btn",onClick:j,children:"创建"}),e.jsx("span",{className:"hint",children:"同 id 已存在会直接报冲突,不会静默覆盖。"})]})]})}function P({modal:c,onChange:n,onSave:m,onAddField:j,onRemoveField:i,onClose:b}){var o;const[d,p]=x.useState({key:"",label:"",type:"text",group:""}),r=c.full,u=(r==null?void 0:r.groupList)||[];return e.jsxs("div",{className:"stack",children:[e.jsxs("div",{className:"grid",children:[e.jsxs("div",{className:"field",children:[e.jsx("div",{className:"flabel",children:e.jsx("span",{children:"标题"})}),e.jsx("div",{className:"fctrl",children:e.jsx("input",{value:c.form.title,onChange:a=>n({title:a.target.value})})})]}),e.jsxs("div",{className:"field",children:[e.jsx("div",{className:"flabel",children:e.jsx("span",{children:"排序"})}),e.jsx("div",{className:"fctrl",children:e.jsx("input",{type:"number",value:c.form.order,onChange:a=>n({order:a.target.value})})})]}),e.jsxs("div",{className:"field",children:[e.jsxs("div",{className:"flabel",children:[e.jsx("span",{children:"条目名字段"}),e.jsx("span",{className:"fkey",children:"列表里显示哪个字段"})]}),e.jsx("div",{className:"fctrl",children:e.jsxs("select",{value:c.form.titleField,onChange:a=>n({titleField:a.target.value}),children:[e.jsx("option",{value:"",children:"(用条目 title)"}),((r==null?void 0:r.fieldList)||[]).map(a=>e.jsxs("option",{value:a.key,children:[a.label,"(",a.key,")"]},a.key))]})})]}),e.jsxs("div",{className:"field",children:[e.jsxs("div",{className:"flabel",children:[e.jsx("span",{children:"名称标签"}),e.jsx("span",{className:"fkey",children:"新建条目时问什么"})]}),e.jsx("div",{className:"fctrl",children:e.jsx("input",{value:c.form.titleLabel,onChange:a=>n({titleLabel:a.target.value})})})]})]}),e.jsxs("div",{className:"field wide",children:[e.jsx("div",{className:"flabel",children:e.jsx("span",{children:"描述"})}),e.jsx("div",{className:"fctrl",children:e.jsx("input",{value:c.form.description,onChange:a=>n({description:a.target.value})})})]}),e.jsxs("div",{className:"rowgap",children:[e.jsx("button",{className:"btn",onClick:m,children:"保存栏目属性"}),e.jsx("button",{className:"btn ghost",onClick:b,children:"关闭"})]}),e.jsxs("div",{className:"card",style:{border:"1px solid var(--soft-2)",borderRadius:4},children:[e.jsxs("div",{className:"colhead",children:["字段字典(",((o=r==null?void 0:r.fieldList)==null?void 0:o.length)||0,")"]}),e.jsxs("div",{className:"colbody",children:[u.map(a=>e.jsxs("div",{children:[e.jsxs("div",{className:"group-title",children:[a.title,"(",a.id,")"]}),(r.fieldList||[]).filter(t=>t.group===a.id).map(t=>e.jsxs("div",{className:"row",children:[e.jsx("span",{className:"name",children:t.label}),e.jsx("span",{className:"mono muted",children:t.key}),e.jsx(v,{children:t.type}),t.sensitive?e.jsx(v,{kind:"bad",children:"密文"}):null,e.jsx("span",{className:"desc",children:t.hint||""}),e.jsx("span",{className:"acts",children:e.jsx("button",{className:"btn small ghost",onClick:()=>i(t.key),children:"删除"})})]},t.key))]},a.id)),((r==null?void 0:r.fieldList)||[]).filter(a=>!u.some(t=>t.id===a.group)).map(a=>e.jsxs("div",{className:"row",children:[e.jsx("span",{className:"name",children:a.label}),e.jsx("span",{className:"mono muted",children:a.key}),e.jsx(v,{children:a.type}),e.jsxs("span",{className:"desc",children:["分组 ",a.group,"(不在 groups 列表里)"]}),e.jsx("span",{className:"acts",children:e.jsx("button",{className:"btn small ghost",onClick:()=>i(a.key),children:"删除"})})]},a.key))]})]}),e.jsxs("div",{className:"card",style:{border:"1px solid var(--soft-2)",borderRadius:4},children:[e.jsx("div",{className:"colhead",children:"新增字段"}),e.jsxs("div",{className:"pad rowgap",children:[e.jsx("input",{style:{width:150},placeholder:"key(英文字母开头)",value:d.key,onChange:a=>p({...d,key:a.target.value})}),e.jsx("input",{style:{width:150},placeholder:"标签(中文名)",value:d.label,onChange:a=>p({...d,label:a.target.value})}),e.jsx("select",{style:{width:110},value:d.type,onChange:a=>p({...d,type:a.target.value}),children:T.map(a=>e.jsx("option",{value:a,children:a},a))}),e.jsxs("select",{style:{width:150},value:d.group,onChange:a=>p({...d,group:a.target.value}),children:[e.jsx("option",{value:"",children:"(首个分组)"}),u.map(a=>e.jsx("option",{value:a.id,children:a.title},a.id))]}),e.jsx("button",{className:"btn small",onClick:()=>{const a={key:d.key.trim(),label:d.label.trim()||d.key.trim(),type:d.type};d.group&&(a.group=d.group),j(a),p({key:"",label:"",type:"text",group:d.group})},children:"加入字典"}),e.jsx("span",{className:"hint",children:"加完立刻生效:CLI 与面板都能填它。"})]})]})]})}export{A as default};
1
+ import{u as L,r as x,a as h,j as e,T as v,E as S,C as F,M as R}from"./index-BnVuH1lC.js";const T=["text","textarea","number","date","month","bool","select","tags","secret"];function A(){const{reload:c,toast:n,guard:m,dialog:j}=L(),[i,b]=x.useState(null),[d,p]=x.useState([]),[r,u]=x.useState(null),[o,a]=x.useState(null),t=x.useCallback(async()=>{try{const[s,l]=await Promise.all([h("/api/sections"),h("/api/sections/templates")]);b(s),p(l.templates),u(null)}catch(s){u(s.message)}},[]);x.useEffect(()=>{t()},[t]);const f=m(async s=>{const l=await h(`/api/sections/${encodeURIComponent(s.id)}/dump`);a({kind:"dump",title:`${s.title}(${s.id})的全部信息`,body:e.jsx("pre",{className:"block",children:JSON.stringify(l,null,2)})})}),g=m(async s=>{const l=await h(`/api/sections/${encodeURIComponent(s.id)}`);a({kind:"edit",id:s.id,form:{title:l.title,description:l.description,order:String(l.order),titleLabel:l.titleLabel,titleField:l.titleField||""},full:l})}),y=m(async s=>{const l={id:s.id.trim(),title:s.title.trim()||s.id.trim(),template:s.template||void 0,description:s.description,order:Number(s.order)||50};await h("/api/sections",{method:"POST",body:l}),n("栏目已创建"),a(null),await t(),await c()}),k=m(async s=>{const l={title:s.form.title,description:s.form.description,order:Number(s.form.order)||50,titleLabel:s.form.titleLabel,titleField:s.form.titleField};await h(`/api/sections/${encodeURIComponent(s.id)}`,{method:"PATCH",body:l}),n("栏目已更新");const N=await h(`/api/sections/${encodeURIComponent(s.id)}`);a({...s,full:N}),await t(),await c()}),C=m(async(s,l)=>{await h(`/api/sections/${encodeURIComponent(s.id)}`,{method:"PATCH",body:{"add-field":l}}),n(`已新增字段 ${l.key}`);const N=await h(`/api/sections/${encodeURIComponent(s.id)}`);a({...s,full:N}),await t()}),w=m(async(s,l)=>{if(!await j({message:`从字段字典里删掉「${l}」?已填的值会留在条目里(只是不再显示/校验)。`,danger:!0,confirmText:"删除字段"}))return;await h(`/api/sections/${encodeURIComponent(s.id)}`,{method:"PATCH",body:{"remove-field":l}}),n(`已删字段 ${l}`);const E=await h(`/api/sections/${encodeURIComponent(s.id)}`);a({...s,full:E}),await t()}),$=m(async s=>{await j({message:`删除栏目「${s.title}」,连带其中 ${s.entries} 条条目?删除前会自动留快照。`,danger:!0,confirmText:"连带删除"})&&(await h(`/api/sections/${encodeURIComponent(s.id)}`,{method:"DELETE",body:{force:!0}}),n("栏目已删除"),await t(),await c())});return r?e.jsxs("div",{className:"pad stack",children:[e.jsx("div",{className:"bad",children:e.jsx("strong",{children:"读不到栏目"})}),e.jsx("pre",{className:"block",children:r})]}):i?e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:"toolbar rowgap pad",children:[e.jsx("strong",{children:"栏目"}),e.jsxs("span",{className:"muted",children:["共 ",i.count," 个 · 条目 ",i.totalEntries," 条"]}),e.jsx("span",{className:"grow"}),e.jsx("button",{className:"btn small ghost",onClick:t,children:"刷新"}),e.jsx("button",{className:"btn small",onClick:()=>{var s;return a({kind:"create",form:{id:"",title:"",template:((s=d[0])==null?void 0:s.id)||"",description:"",order:"50"}})},children:"新建栏目"})]}),e.jsxs("div",{className:"card",children:[e.jsx("div",{className:"colhead",children:"全部栏目"}),e.jsx("div",{className:"colbody",children:i.sections.length?i.sections.map(s=>e.jsxs("div",{className:"row",children:[e.jsx("span",{className:"name",children:s.title}),e.jsx("span",{className:"mono muted",children:s.id}),s.template?e.jsx(v,{children:s.template}):e.jsx(v,{children:"自定义"}),e.jsx("span",{className:"desc",children:s.description}),e.jsxs("span",{className:"acts",children:[e.jsxs("span",{className:"tag",children:[s.fields," 字段"]}),e.jsxs("span",{className:"tag",children:[s.entries," 条目"]}),e.jsx("button",{className:"btn small ghost",onClick:()=>f(s),children:"全部信息"}),e.jsx("button",{className:"btn small ghost",onClick:()=>g(s),children:"编辑"}),e.jsx("button",{className:"btn small ghost",onClick:()=>$(s),children:"删除"})]})]},s.id)):e.jsx(S,{children:"还没有栏目。点「新建栏目」,用内置模板(求职 / 密钥)起步。"})})]}),e.jsx("div",{className:"pad hint",children:"栏目 = 一组同构条目 + 一份字段字典。字典是数据,所以这里加一个字段,CLI 与面板立刻就都能填它。"}),e.jsx(F,{module:"sections"}),o?e.jsxs(R,{title:I(o),onClose:()=>a(null),children:[o.kind==="dump"?o.body:null,o.kind==="create"?e.jsx(U,{templates:d,form:o.form,onChange:s=>a(l=>({...l,form:{...l.form,...s}})),onSubmit:()=>{if(!/^[a-z][a-z0-9_-]{0,63}$/.test(o.form.id.trim())){n("栏目 id 必须是小写字母开头,仅含 a-z 0-9 _ -","bad");return}y(o.form)}}):null,o.kind==="edit"?e.jsx(P,{modal:o,onChange:s=>a(l=>({...l,form:{...l.form,...s}})),onSave:()=>k(o),onAddField:s=>C(o,s),onRemoveField:s=>w(o,s),onClose:()=>a(null)}):null]}):null]}):e.jsx("div",{className:"pad muted",children:"加载中…"})}function I(c){return c.kind==="dump"?c.title:c.kind==="create"?"新建栏目":`编辑栏目 ${c.id}`}function U({templates:c,form:n,onChange:m,onSubmit:j}){return e.jsxs("div",{className:"stack",children:[e.jsxs("div",{className:"grid",children:[e.jsxs("div",{className:"field",children:[e.jsxs("div",{className:"flabel",children:[e.jsx("span",{children:"栏目 id"}),e.jsx("span",{className:"fkey",children:"小写字母开头,仅 a-z 0-9 _ -"})]}),e.jsx("div",{className:"fctrl",children:e.jsx("input",{value:n.id,onChange:i=>m({id:i.target.value}),placeholder:"例如 projects"})})]}),e.jsxs("div",{className:"field",children:[e.jsx("div",{className:"flabel",children:e.jsx("span",{children:"标题"})}),e.jsx("div",{className:"fctrl",children:e.jsx("input",{value:n.title,onChange:i=>m({title:i.target.value}),placeholder:"例如 项目档案"})})]}),e.jsxs("div",{className:"field",children:[e.jsx("div",{className:"flabel",children:e.jsx("span",{children:"从模板起步"})}),e.jsx("div",{className:"fctrl",children:e.jsxs("select",{value:n.template,onChange:i=>m({template:i.target.value}),children:[e.jsx("option",{value:"",children:"(空栏目,自定义字段)"}),c.map(i=>e.jsxs("option",{value:i.id,children:[i.label,"(",i.fields," 字段)"]},i.id))]})})]}),e.jsxs("div",{className:"field",children:[e.jsxs("div",{className:"flabel",children:[e.jsx("span",{children:"排序"}),e.jsx("span",{className:"fkey",children:"越小越靠前"})]}),e.jsx("div",{className:"fctrl",children:e.jsx("input",{type:"number",value:n.order,onChange:i=>m({order:i.target.value})})})]})]}),e.jsxs("div",{className:"field wide",children:[e.jsx("div",{className:"flabel",children:e.jsx("span",{children:"描述"})}),e.jsx("div",{className:"fctrl",children:e.jsx("input",{value:n.description,onChange:i=>m({description:i.target.value})})})]}),e.jsxs("div",{className:"rowgap",children:[e.jsx("button",{className:"btn",onClick:j,children:"创建"}),e.jsx("span",{className:"hint",children:"同 id 已存在会直接报冲突,不会静默覆盖。"})]})]})}function P({modal:c,onChange:n,onSave:m,onAddField:j,onRemoveField:i,onClose:b}){var o;const[d,p]=x.useState({key:"",label:"",type:"text",group:""}),r=c.full,u=(r==null?void 0:r.groupList)||[];return e.jsxs("div",{className:"stack",children:[e.jsxs("div",{className:"grid",children:[e.jsxs("div",{className:"field",children:[e.jsx("div",{className:"flabel",children:e.jsx("span",{children:"标题"})}),e.jsx("div",{className:"fctrl",children:e.jsx("input",{value:c.form.title,onChange:a=>n({title:a.target.value})})})]}),e.jsxs("div",{className:"field",children:[e.jsx("div",{className:"flabel",children:e.jsx("span",{children:"排序"})}),e.jsx("div",{className:"fctrl",children:e.jsx("input",{type:"number",value:c.form.order,onChange:a=>n({order:a.target.value})})})]}),e.jsxs("div",{className:"field",children:[e.jsxs("div",{className:"flabel",children:[e.jsx("span",{children:"条目名字段"}),e.jsx("span",{className:"fkey",children:"列表里显示哪个字段"})]}),e.jsx("div",{className:"fctrl",children:e.jsxs("select",{value:c.form.titleField,onChange:a=>n({titleField:a.target.value}),children:[e.jsx("option",{value:"",children:"(用条目 title)"}),((r==null?void 0:r.fieldList)||[]).map(a=>e.jsxs("option",{value:a.key,children:[a.label,"(",a.key,")"]},a.key))]})})]}),e.jsxs("div",{className:"field",children:[e.jsxs("div",{className:"flabel",children:[e.jsx("span",{children:"名称标签"}),e.jsx("span",{className:"fkey",children:"新建条目时问什么"})]}),e.jsx("div",{className:"fctrl",children:e.jsx("input",{value:c.form.titleLabel,onChange:a=>n({titleLabel:a.target.value})})})]})]}),e.jsxs("div",{className:"field wide",children:[e.jsx("div",{className:"flabel",children:e.jsx("span",{children:"描述"})}),e.jsx("div",{className:"fctrl",children:e.jsx("input",{value:c.form.description,onChange:a=>n({description:a.target.value})})})]}),e.jsxs("div",{className:"rowgap",children:[e.jsx("button",{className:"btn",onClick:m,children:"保存栏目属性"}),e.jsx("button",{className:"btn ghost",onClick:b,children:"关闭"})]}),e.jsxs("div",{className:"card",style:{border:"1px solid var(--soft-2)",borderRadius:4},children:[e.jsxs("div",{className:"colhead",children:["字段字典(",((o=r==null?void 0:r.fieldList)==null?void 0:o.length)||0,")"]}),e.jsxs("div",{className:"colbody",children:[u.map(a=>e.jsxs("div",{children:[e.jsxs("div",{className:"group-title",children:[a.title,"(",a.id,")"]}),(r.fieldList||[]).filter(t=>t.group===a.id).map(t=>e.jsxs("div",{className:"row",children:[e.jsx("span",{className:"name",children:t.label}),e.jsx("span",{className:"mono muted",children:t.key}),e.jsx(v,{children:t.type}),t.sensitive?e.jsx(v,{kind:"bad",children:"密文"}):null,e.jsx("span",{className:"desc",children:t.hint||""}),e.jsx("span",{className:"acts",children:e.jsx("button",{className:"btn small ghost",onClick:()=>i(t.key),children:"删除"})})]},t.key))]},a.id)),((r==null?void 0:r.fieldList)||[]).filter(a=>!u.some(t=>t.id===a.group)).map(a=>e.jsxs("div",{className:"row",children:[e.jsx("span",{className:"name",children:a.label}),e.jsx("span",{className:"mono muted",children:a.key}),e.jsx(v,{children:a.type}),e.jsxs("span",{className:"desc",children:["分组 ",a.group,"(不在 groups 列表里)"]}),e.jsx("span",{className:"acts",children:e.jsx("button",{className:"btn small ghost",onClick:()=>i(a.key),children:"删除"})})]},a.key))]})]}),e.jsxs("div",{className:"card",style:{border:"1px solid var(--soft-2)",borderRadius:4},children:[e.jsx("div",{className:"colhead",children:"新增字段"}),e.jsxs("div",{className:"pad rowgap",children:[e.jsx("input",{style:{width:150},placeholder:"key(英文字母开头)",value:d.key,onChange:a=>p({...d,key:a.target.value})}),e.jsx("input",{style:{width:150},placeholder:"标签(中文名)",value:d.label,onChange:a=>p({...d,label:a.target.value})}),e.jsx("select",{style:{width:110},value:d.type,onChange:a=>p({...d,type:a.target.value}),children:T.map(a=>e.jsx("option",{value:a,children:a},a))}),e.jsxs("select",{style:{width:150},value:d.group,onChange:a=>p({...d,group:a.target.value}),children:[e.jsx("option",{value:"",children:"(首个分组)"}),u.map(a=>e.jsx("option",{value:a.id,children:a.title},a.id))]}),e.jsx("button",{className:"btn small",onClick:()=>{const a={key:d.key.trim(),label:d.label.trim()||d.key.trim(),type:d.type};d.group&&(a.group=d.group),j(a),p({key:"",label:"",type:"text",group:d.group})},children:"加入字典"}),e.jsx("span",{className:"hint",children:"加完立刻生效:CLI 与面板都能填它。"})]})]})]})}export{A as default};
@@ -0,0 +1,7 @@
1
+ import{j as e,u as O,r as m,a as N,b as q,E as F,C as L,T as _,M as V}from"./index-BnVuH1lC.js";function Y({def:o,value:v,onChange:u,disabled:p}){const l=o.type||"text",r=v??"";if(l==="bool"){const s=r===!0||r==="true"||r==="是";return e.jsxs("label",{className:"inline",children:[e.jsx("input",{type:"checkbox",checked:s,onChange:d=>u(d.target.checked)}),e.jsx("span",{className:"muted",children:s?"是":"否"})]})}if(l==="select"){const s=o.options||[],d=r!==""&&!s.includes(r);return e.jsxs("select",{value:d?"__custom":String(r),onChange:h=>u(h.target.value==="__custom"?"":h.target.value),children:[e.jsx("option",{value:"",children:"(未填写)"}),s.map(h=>e.jsx("option",{value:h,children:h},h)),d?e.jsxs("option",{value:"__custom",children:[String(r),"(当前值,不在候选里)"]}):null]})}if(l==="textarea")return e.jsx("textarea",{value:String(r),onChange:s=>u(s.target.value),rows:3});if(l==="tags"){const s=Array.isArray(r)?r.join("、"):String(r);return e.jsx("input",{value:s,placeholder:o.maxItems?`多个用「、」分隔,最多 ${o.maxItems} 个`:"多个用「、」分隔",onChange:d=>u(d.target.value.split(/[,,、;;]+/).map(h=>h.trim()).filter(Boolean))})}const f=l==="number"?"number":l==="date"?"date":l==="month"?"month":"text";return l==="secret"?e.jsx("input",{type:"text",value:String(r),placeholder:"密文落盘;原样保留占位则视为不修改",disabled:p,onChange:s=>u(s.target.value)}):e.jsx("input",{type:f,value:String(r),onChange:s=>u(s.target.value)})}function z({title:o,fields:v,draft:u,onPatch:p}){return e.jsxs(e.Fragment,{children:[e.jsx("div",{className:"group-title",children:o}),e.jsx("div",{className:"pad",children:e.jsx("div",{className:"grid",children:v.map(l=>e.jsxs("div",{className:`field ${l.type==="textarea"?"wide":""}`,children:[e.jsxs("div",{className:"flabel",children:[e.jsx("span",{children:l.label}),l.sensitive?e.jsx("span",{className:"tag bad",children:"密文"}):null,l.fill&&l.fill!=="normal"?e.jsx("span",{className:"tag",children:l.fillLabel||l.fill}):null,e.jsx("span",{className:"fkey",children:l.key})]}),e.jsx("div",{className:"fctrl",children:e.jsx(Y,{def:l,value:u[l.key],onChange:r=>p(l.key,r)})})]},l.key))})})]})}function G({sectionId:o,sectionTitle:v}){const{ui:u,patchUi:p,toast:l,guard:r,dialog:f,reload:s}=O(),[d,h]=m.useState(null),[E,U]=m.useState({}),[C,i]=m.useState({name:"",value:""}),k=!!u.mask,j=m.useCallback(async()=>{try{const n=`section=${encodeURIComponent(o)}${k?"&mask=1":""}`,a=await N(`/api/keys?${n}`);h(a);const x={};for(const w of a.keys)x[w.name]=w.value??"";U(x)}catch(n){l(n.message,"bad"),h(null)}},[o,k,l]);m.useEffect(()=>{j()},[j]);const A=r(async n=>{const a=E[n.name];(n.value??"")!==a&&(await N(`/api/keys/${encodeURIComponent(n.name)}`,{method:"PUT",body:{value:a,section:o}}),l(`已保存 ${n.name}`),await j())}),$=r(async(n,a)=>{const x=String(a||"").trim();if(!(!x||x===n.name)){if(d.keys.some(w=>w.name===x)){l(`已经有叫「${x}」的键了`,"bad"),await j();return}await N(`/api/entries/${encodeURIComponent(n.id)}`,{method:"PATCH",body:{title:x}}),U(w=>{const y={};for(const[D,K]of Object.entries(w))y[D===n.name?x:D]=K;return y}),l(`已重命名为 ${x}`),await j(),await s()}}),S=r(async()=>{const n=C.name.trim();if(!n){l("先填键名,例如 OPENAI_KEY","bad");return}if(d.keys.some(a=>a.name===n)){l(`已经有叫「${n}」的键了——直接在上面那行改值即可`,"bad");return}await N(`/api/keys/${encodeURIComponent(n)}`,{method:"PUT",body:{value:C.value,section:o}}),i({name:"",value:""}),l(`已新增 ${n}`),await j(),await s()}),T=r(async n=>{await f({message:`删除「${n.name}」?删除前会自动留一份整库快照在 ~/nx-sk/backup。`,danger:!0,confirmText:"删除"})&&(await N(`/api/keys/${encodeURIComponent(n.name)}`,{method:"DELETE",body:{section:o}}),l(`已删除 ${n.name}`),await j(),await s())});return d?e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:"toolbar rowgap pad",children:[e.jsx("strong",{children:v}),e.jsxs("span",{className:"muted",children:[d.count," 个键 · 名称 → 值"]}),e.jsx("span",{className:"grow"}),e.jsxs("label",{className:"inline hint",children:[e.jsx("input",{type:"checkbox",checked:k,onChange:()=>p({mask:!k})}),"打码显示(投屏/截图时用)"]}),e.jsx("button",{className:"btn small ghost",onClick:j,children:"刷新"})]}),e.jsxs("div",{className:"card",children:[e.jsxs("div",{className:"colhead",children:[e.jsx("span",{style:{width:200},children:"名称"}),e.jsx("span",{className:"grow",children:"值"})]}),e.jsxs("div",{className:"colbody",children:[d.keys.length?d.keys.map(n=>e.jsxs("div",{className:"row",children:[e.jsx("input",{className:"mono",style:{width:200},defaultValue:n.name,title:"改完按回车或点开别处即重命名",onBlur:a=>$(n,a.target.value),onKeyDown:a=>{a.key==="Enter"&&a.currentTarget.blur()}}),e.jsx("input",{className:"mono grow",value:E[n.name]??"",onChange:a=>U(x=>({...x,[n.name]:a.target.value})),onBlur:()=>A(n),onKeyDown:a=>{a.key==="Enter"&&a.currentTarget.blur()}}),e.jsxs("span",{className:"acts",children:[e.jsx(q,{className:"tag",text:E[n.name]??"",title:"点击复制值",children:"复制"}),e.jsx("button",{className:"btn small ghost",onClick:()=>T(n),children:"删除"})]})]},n.id)):e.jsx(F,{children:"还没有密钥。在下面一行填「名称 / 值」按添加,或 CLI:nx-sk key set OPENAI_KEY sk-xxx"}),e.jsxs("div",{className:"row",children:[e.jsx("input",{className:"mono",style:{width:200},placeholder:"新键名,例如 OPENAI_KEY",value:C.name,onChange:n=>i(a=>({...a,name:n.target.value})),onKeyDown:n=>{n.key==="Enter"&&S()}}),e.jsx("input",{className:"mono grow",placeholder:"值(留空也行,之后再填)",value:C.value,onChange:n=>i(a=>({...a,value:n.target.value})),onKeyDown:n=>{n.key==="Enter"&&S()}}),e.jsx("span",{className:"acts",children:e.jsx("button",{className:"btn small",onClick:S,children:"添加"})})]})]})]}),e.jsx("div",{className:"pad hint",children:"改值:直接在「值」列改完按回车(或点开别处)即保存。改键名同理。 值以密文落盘,这里显示的是原文;要打码勾上方那个框。删除前自动整库快照。"}),e.jsx(L,{module:"entries"})]}):e.jsx("div",{className:"pad muted",children:"加载中…"})}const I=o=>o==null?"":Array.isArray(o)?o.join("、"):String(o);function W({sectionId:o}){var R;const{ui:v,patchUi:u,toast:p,guard:l,dialog:r,reload:f}=O(),[s,d]=m.useState(null),[h,E]=m.useState(null),[U,C]=m.useState(!1),[i,k]=m.useState(null),[j,A]=m.useState(null),[$,S]=m.useState(""),T=!!v.mask,n=m.useCallback(async t=>{C(!0),E(null);try{const c=await N(`/api/sections/${encodeURIComponent(o)}/dump${T?"?mask=1":""}`);d(c);const b=t||v.entry,g=c.entries.find(P=>P.id===b)||c.entries[0]||null;k(g?{id:g.id,title:g.title,values:{...g.values}}:null),g&&g.id!==v.entry&&u({entry:g.id})}catch(c){E(c.message),d(null),k(null)}finally{C(!1)}},[o,T]);m.useEffect(()=>{n()},[n]);const a=m.useMemo(()=>(s==null?void 0:s.entries.find(t=>t.id===(i==null?void 0:i.id)))||null,[s,i]),x=m.useMemo(()=>s?s.groups.map(t=>({...t,fields:s.fields.filter(c=>c.group===t.id)})).filter(t=>t.fields.length):[],[s]),w=(t,c)=>k(b=>b&&{...b,values:{...b.values,[t]:c}}),y=m.useMemo(()=>{if(!i||!a)return{set:{},titleChanged:!1,count:0};const t={};for(const c of s.fields)I(a.values[c.key])!==I(i.values[c.key])&&(t[c.key]=i.values[c.key]);return{set:t,titleChanged:i.title!==a.title,count:Object.keys(t).length+(i.title!==a.title?1:0)}},[i,a,s]),D=l(async()=>{if(!i||!a)return;if(!y.count){p("没有改动");return}const t={set:y.set};y.titleChanged&&(t.title=i.title),await N(`/api/entries/${encodeURIComponent(i.id)}`,{method:"PATCH",body:t}),p(`已保存 ${y.count} 处改动`),await n(i.id),await f()}),K=l(async()=>{var P;if(!i){p("先新建一条条目","bad");return}const t=$.indexOf("=");if(t<=0){p("用 字段=值 的格式,例如 微信=zhangsan","bad");return}const c=$.slice(0,t).trim(),b=$.slice(t+1),g=await N(`/api/entries/${encodeURIComponent(i.id)}`,{method:"PATCH",body:{set:{[c]:b}}});S(""),p(`已写入 ${c}${(P=g.newFields)!=null&&P.length?"(新字段已登记)":""}`),await n(i.id),await f()}),B=l(async()=>{const t=(s==null?void 0:s.section.titleLabel)||"名称",c=await r({message:`新建「${s==null?void 0:s.section.title}」条目,${t}是?`,input:{placeholder:`例如 ${(s==null?void 0:s.section.titleField)||"名称"}`}});if(!c)return;const b={section:o,title:c};s!=null&&s.section.titleField&&(b.set={[s.section.titleField]:c});const g=await N("/api/entries",{method:"POST",body:b});p(`已新建:${g.title}`),await n(g.id),await f()}),M=l(async()=>{!a||!await r({message:`删除条目「${a.title}」?删除前会自动留一份快照在 ~/nx-sk/backup。`,danger:!0,confirmText:"删除"})||(await N(`/api/entries/${encodeURIComponent(a.id)}`,{method:"DELETE"}),p("已删除"),await n(""),await f())}),H=l(async()=>{const t=await N("/api/export",{method:"POST",body:{section:o,format:"both"}});A({title:"导出结果",body:e.jsx("pre",{className:"block",children:`目录: ${t.dir}
2
+ 格式: ${t.format}
3
+ 条目: ${t.entries}
4
+ 凭据: ${t.withSecrets?"含明文":"已打码"}
5
+
6
+ ${t.files.map(c=>`${c.path} ${c.bytes} 字节`).join(`
7
+ `)}`})})});return h?e.jsxs("div",{className:"pad stack",children:[e.jsx("div",{className:"bad",children:e.jsx("strong",{children:"栏目读不到"})}),e.jsx("pre",{className:"block",children:h}),e.jsx("div",{className:"hint",children:"如果这个栏目刚被删掉,切到「栏目」tab 看看现有栏目。"})]}):s?s.section.kv?e.jsx(G,{sectionId:o,sectionTitle:s.section.title}):e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:"toolbar rowgap pad",children:[e.jsx("strong",{children:s.section.title}),e.jsx(_,{children:s.section.id}),e.jsxs("span",{className:"muted",children:[s.count," 条 / ",s.section.fields," 字段"]}),s.section.description?e.jsx("span",{className:"desc muted nowrap grow",children:s.section.description}):e.jsx("span",{className:"grow"}),e.jsxs("label",{className:"inline hint",children:[e.jsx("input",{type:"checkbox",checked:T,onChange:()=>u({mask:!T})}),"打码显示(投屏/截图时用)"]}),e.jsx("button",{className:"btn small ghost",onClick:()=>n(),children:"刷新"}),e.jsx("button",{className:"btn small ghost",onClick:H,children:"导出本栏目"}),e.jsx("button",{className:"btn small",onClick:B,children:"新建条目"})]}),e.jsxs("div",{className:"cols",children:[e.jsx("div",{className:"col",style:{flex:"0 0 300px"},children:e.jsxs("div",{className:"card",children:[e.jsxs("div",{className:"colhead",children:["条目列表",e.jsx("span",{className:"right muted",children:s.count})]}),e.jsx("div",{className:"colbody",children:s.entries.length?s.entries.map(t=>e.jsxs("div",{className:`row selectable ${t.id===(i==null?void 0:i.id)?"selected":""}`,onClick:()=>{u({entry:t.id}),k({id:t.id,title:t.title,values:{...t.values}})},children:[e.jsx("span",{className:"name",children:t.title||"(无名)"}),e.jsx("span",{className:"acts",children:t.missing.length?e.jsxs("span",{className:"tag",children:[t.completeness.ratio,"%"]}):e.jsx("span",{className:"tag strong",children:"已填满"})})]},t.id)):e.jsxs(F,{children:["还没有条目。点右上角「新建条目」,或用 CLI:nx-sk entry add --section ",s.section.id," --set ..."]})})]})}),e.jsx("div",{className:"col",children:i?e.jsxs("div",{className:"card",children:[e.jsxs("div",{className:"colhead",children:[e.jsx("span",{className:"grow nowrap",children:(a==null?void 0:a.title)||i.title}),e.jsx("span",{className:"muted mono",children:i.id}),a?e.jsxs(_,{kind:a.missing.length?"":"strong",children:["完整度 ",a.completeness.ratio,"%"]}):null]}),e.jsxs("div",{className:"field wide pad",style:{borderBottom:"1px solid var(--soft-2)"},children:[e.jsxs("div",{className:"flabel",children:[e.jsx("span",{children:s.section.titleLabel||"名称"}),e.jsx("span",{className:"bad",children:"改动后必须保存"})]}),e.jsx("div",{className:"fctrl",children:e.jsx("input",{value:i.title,onChange:t=>k(c=>({...c,title:t.target.value}))})})]}),e.jsxs("div",{className:"rowgap",style:{padding:"6px 14px",borderBottom:"1px solid var(--soft-2)"},children:[e.jsx("input",{className:"grow",style:{minWidth:220},placeholder:"直接加字段:字段=值 (回车写入;没见过的键会自动登记)",value:$,onChange:t=>S(t.target.value),onKeyDown:t=>{t.key==="Enter"&&K()}}),e.jsx("button",{className:"btn small",onClick:K,disabled:!$.includes("="),children:"写入"})]}),x.map(t=>e.jsx(z,{title:t.title,fields:t.fields,draft:i.values,onPatch:w},t.id)),e.jsxs("div",{className:"rowgap pad",children:[e.jsxs("button",{className:"btn",onClick:D,disabled:!y.count,children:["保存",y.count?`(${y.count} 处改动)`:""]}),e.jsx("button",{className:"btn ghost",onClick:()=>n(i.id),disabled:!y.count,children:"放弃改动"}),e.jsx("button",{className:"btn ghost",onClick:M,children:"删除条目"}),a!=null&&a.missing.length?e.jsxs("span",{className:"hint",children:["模板建议里还有 ",a.missing.length," 项没填(不影响使用):",a.missing.slice(0,5).map(t=>t.label).join("、"),a.missing.length>5?"…":""]}):null,(R=a==null?void 0:a.excluded)!=null&&R.length?e.jsxs("span",{className:"hint",children:["另有 ",a.excluded.length," 项已标不填、不计入完整度:",a.excluded.slice(0,6).map(t=>t.label).join("、"),a.excluded.length>6?"…":""]}):null]})]}):e.jsx("div",{className:"card",children:e.jsx(F,{children:"左边选一条,或新建一条"})})})]}),e.jsx(L,{module:"entries"}),j?e.jsx(V,{title:j.title,onClose:()=>A(null),children:j.body}):null]}):e.jsx("div",{className:"pad muted",children:U?"加载中…":"暂无数据"})}export{W as default};
@@ -1 +1 @@
1
- import{u as b,r as d,a as k,j as s,b as r,E as F,C as I,T as $}from"./index-CpF00ycO.js";function D(){var N,v,u,g,f,w,y,S;const{boot:e,reload:t,toast:n,guard:C}=b(),[o,h]=d.useState(null),[l,i]=d.useState(null),j=typeof window>"u"?"":window.location.origin,p=typeof window>"u"?"":window.location.port||"80",m=d.useCallback(async()=>{try{const a=await k("/api/settings");h(a),i({...a.settings})}catch(a){n(a.message,"bad")}},[n]);d.useEffect(()=>{m()},[m]);const E=C(async()=>{const a={exportDir:l.exportDir,exportFormat:l.exportFormat,includeSecretsInExport:!!l.includeSecretsInExport,defaultSection:l.defaultSection},x=await k("/api/settings",{method:"PATCH",body:a});n("设置已保存"),h({...o,settings:x.set}),await t()});return!o||!l?s.jsx("div",{className:"pad muted",children:"加载中…"}):s.jsxs(s.Fragment,{children:[s.jsxs("div",{className:"toolbar rowgap pad",children:[s.jsx("strong",{children:"设置"}),s.jsx("span",{className:"muted",children:"本机配置与运行状态"}),s.jsx("span",{className:"grow"}),s.jsx("button",{className:"btn small ghost",onClick:m,children:"重新读取"})]}),s.jsxs("div",{className:"card",children:[s.jsx("div",{className:"colhead",children:"存储与运行"}),s.jsxs("div",{className:"colbody",children:[s.jsx(c,{label:"数据目录",value:e==null?void 0:e.home,copy:e==null?void 0:e.home}),s.jsx(c,{label:"store.json",value:e==null?void 0:e.storePath,copy:e==null?void 0:e.storePathRaw}),s.jsx(c,{label:"栏目 / 条目",value:e?`${e.counts.sections} / ${e.counts.entries}`:""}),s.jsx(c,{label:"命令条数",value:e?String(e.counts.commands):""}),s.jsx(c,{label:"app / node",value:e?`v${e.app.version} · node ${e.app.node} · ${e.app.platform}`:""}),s.jsx(c,{label:"环境变量覆盖",value:e?Object.entries(e.envOverrides).filter(([,a])=>a).map(([a,x])=>`${a}=${x}`).join(" ")||"(无)":""})]})]}),s.jsxs("div",{className:"card",children:[s.jsx("div",{className:"colhead",children:"密钥(密文落盘)"}),s.jsxs("div",{className:"colbody",children:[s.jsx(c,{label:"密钥来源",value:((N=e==null?void 0:e.vault)==null?void 0:N.source)==="env"?"环境变量 NX_SK_PASSPHRASE(口令不落盘)":"本机密钥文件"}),s.jsx(c,{label:"密钥文件",value:((v=e==null?void 0:e.vault)==null?void 0:v.keyFile)||((u=e==null?void 0:e.vault)==null?void 0:u.saltFile)||"",copy:((g=e==null?void 0:e.vault)==null?void 0:g.keyFile)||((f=e==null?void 0:e.vault)==null?void 0:f.saltFile)}),s.jsx("div",{className:"row",children:s.jsx("span",{className:"desc",children:(w=e==null?void 0:e.vault)==null?void 0:w.note})}),s.jsx("div",{className:"row",children:s.jsx("span",{className:"desc bad",children:"删掉密钥文件或换掉口令后,已存的密文都解不开了——导出前先确认密钥可用。"})})]})]}),s.jsxs("div",{className:"card",children:[s.jsx("div",{className:"colhead",children:"面板与 CLI"}),s.jsxs("div",{className:"colbody",children:[s.jsxs("div",{className:"row",children:[s.jsx("span",{className:"name",children:"面板地址"}),s.jsx("span",{className:"desc mono",children:j}),s.jsx("span",{className:"acts",children:s.jsx(r,{className:"mono",text:j,children:"复制"})})]}),s.jsxs("div",{className:"row",children:[s.jsx("span",{className:"name",children:"重启面板"}),s.jsx("span",{className:"desc",children:"面板本身就是 serve 提供的;改代码后重启它即可"}),s.jsx("span",{className:"acts",children:s.jsx(r,{className:"mono",text:`nx-sk serve --port ${p}`,children:`nx-sk serve --port ${p}`})})]})]})]}),s.jsxs("div",{className:"card",children:[s.jsx("div",{className:"colhead",children:"默认行为"}),s.jsxs("div",{className:"pad",children:[s.jsxs("div",{className:"grid",children:[s.jsxs("div",{className:"field",children:[s.jsx("div",{className:"flabel",children:s.jsx("span",{children:"默认导出格式"})}),s.jsx("div",{className:"fctrl",children:s.jsxs("select",{value:l.exportFormat,onChange:a=>i({...l,exportFormat:a.target.value}),children:[s.jsx("option",{value:"both",children:"JSON + Markdown"}),s.jsx("option",{value:"json",children:"仅 JSON"}),s.jsx("option",{value:"md",children:"仅 Markdown"})]})})]}),s.jsxs("div",{className:"field",children:[s.jsxs("div",{className:"flabel",children:[s.jsx("span",{children:"默认导出目录"}),s.jsx("span",{className:"fkey",children:"留空 = ~/nx-sk/export"})]}),s.jsx("div",{className:"fctrl",children:s.jsx("input",{value:l.exportDir,onChange:a=>i({...l,exportDir:a.target.value})})})]}),s.jsxs("div",{className:"field",children:[s.jsxs("div",{className:"flabel",children:[s.jsx("span",{children:"默认栏目"}),s.jsx("span",{className:"fkey",children:"CLI 未指定 --section 时的首选"})]}),s.jsx("div",{className:"fctrl",children:s.jsx("input",{value:l.defaultSection,onChange:a=>i({...l,defaultSection:a.target.value})})})]}),s.jsxs("div",{className:"field",children:[s.jsxs("div",{className:"flabel",children:[s.jsx("span",{children:"导出默认带明文密钥"}),s.jsx("span",{className:"fkey",children:"默认开;要分享出去时关掉"})]}),s.jsx("div",{className:"fctrl",children:s.jsxs("label",{className:"inline",children:[s.jsx("input",{type:"checkbox",checked:!!l.includeSecretsInExport,onChange:a=>i({...l,includeSecretsInExport:a.target.checked})}),s.jsx("span",{className:l.includeSecretsInExport?"muted":"bad",children:l.includeSecretsInExport?"开(导出文件含真实凭据,注意别外发)":"关(凭据打码后再导出)"})]})})]})]}),s.jsx("div",{className:"rowgap",style:{marginTop:8},children:s.jsx("button",{className:"btn",onClick:E,children:"保存设置"})})]})]}),s.jsxs("div",{className:"card",children:[s.jsxs("div",{className:"colhead",children:["自动快照",s.jsx("span",{className:"right muted",children:((y=e==null?void 0:e.snapshots)==null?void 0:y.length)??0})]}),s.jsxs("div",{className:"colbody",children:[s.jsx("div",{className:"row",children:s.jsx("span",{className:"desc",children:"每次删除条目 / 栏目、修改设置前,都会在 ~/nx-sk/backup 留一份可回滚的整库快照。"})}),(S=e==null?void 0:e.snapshots)!=null&&S.length?e.snapshots.map(a=>s.jsxs("div",{className:"row",children:[s.jsx("span",{className:"mono name",children:a.name}),s.jsx("span",{className:"desc",children:a.at}),s.jsx("span",{className:"acts",children:s.jsxs("span",{className:"tag",children:[Math.ceil(a.bytes/1024)," KB"]})})]},a.name)):s.jsx(F,{children:"还没有快照。"})]})]}),e!=null&&e.migration?s.jsxs("div",{className:"card",children:[s.jsx("div",{className:"colhead",children:"数据迁移"}),s.jsxs("div",{className:"colbody",children:[s.jsx("div",{className:"row",children:s.jsxs("span",{className:"desc",children:["store 已从 v",e.migration.from," 迁到 v",e.migration.to,":密钥栏目字段 ",e.migration.fieldsBefore," → ",e.migration.fieldsAfter,",",e.migration.entries," 条条目"]})}),s.jsxs("div",{className:"row",children:[s.jsx("span",{className:"desc",children:"迁移前的原始文件"}),s.jsx("span",{className:"acts",children:s.jsx(r,{className:"mono",text:e.migration.snapshotRaw||"",children:e.migration.snapshot})})]}),e.migration.legacyValuesKept?s.jsx("div",{className:"row",children:s.jsxs("span",{className:"desc",children:["另保留了 ",e.migration.legacyValuesKept," 个旧字段的值(不再显示,但没删)"]})}):null]})]}):null,e!=null&&e.corrupt?s.jsxs("div",{className:"card",children:[s.jsx("div",{className:"colhead",children:"上次读取异常"}),s.jsx("div",{className:"colbody",children:s.jsx("div",{className:"row",children:s.jsxs("span",{className:"desc bad",children:["store.json 解析失败,已挪到 ",e.corrupt.to,"(原文件没有被覆盖)"]})})})]}):null,s.jsx(I,{module:"settings"})]})}function c({label:e,value:t,copy:n}){return s.jsxs("div",{className:"row",children:[s.jsx("span",{className:"name",children:e}),s.jsx("span",{className:"desc mono",children:t||"(空)"}),n?s.jsx("span",{className:"acts",children:s.jsx(r,{className:"mono",text:n,children:"复制"})}):s.jsx($,{children:" "})]})}export{D as default};
1
+ import{u as b,r as d,a as k,j as s,b as r,E as F,C as I,T as $}from"./index-BnVuH1lC.js";function D(){var N,v,u,g,f,w,y,S;const{boot:e,reload:t,toast:n,guard:C}=b(),[o,h]=d.useState(null),[l,i]=d.useState(null),j=typeof window>"u"?"":window.location.origin,p=typeof window>"u"?"":window.location.port||"80",m=d.useCallback(async()=>{try{const a=await k("/api/settings");h(a),i({...a.settings})}catch(a){n(a.message,"bad")}},[n]);d.useEffect(()=>{m()},[m]);const E=C(async()=>{const a={exportDir:l.exportDir,exportFormat:l.exportFormat,includeSecretsInExport:!!l.includeSecretsInExport,defaultSection:l.defaultSection},x=await k("/api/settings",{method:"PATCH",body:a});n("设置已保存"),h({...o,settings:x.set}),await t()});return!o||!l?s.jsx("div",{className:"pad muted",children:"加载中…"}):s.jsxs(s.Fragment,{children:[s.jsxs("div",{className:"toolbar rowgap pad",children:[s.jsx("strong",{children:"设置"}),s.jsx("span",{className:"muted",children:"本机配置与运行状态"}),s.jsx("span",{className:"grow"}),s.jsx("button",{className:"btn small ghost",onClick:m,children:"重新读取"})]}),s.jsxs("div",{className:"card",children:[s.jsx("div",{className:"colhead",children:"存储与运行"}),s.jsxs("div",{className:"colbody",children:[s.jsx(c,{label:"数据目录",value:e==null?void 0:e.home,copy:e==null?void 0:e.home}),s.jsx(c,{label:"store.json",value:e==null?void 0:e.storePath,copy:e==null?void 0:e.storePathRaw}),s.jsx(c,{label:"栏目 / 条目",value:e?`${e.counts.sections} / ${e.counts.entries}`:""}),s.jsx(c,{label:"命令条数",value:e?String(e.counts.commands):""}),s.jsx(c,{label:"app / node",value:e?`v${e.app.version} · node ${e.app.node} · ${e.app.platform}`:""}),s.jsx(c,{label:"环境变量覆盖",value:e?Object.entries(e.envOverrides).filter(([,a])=>a).map(([a,x])=>`${a}=${x}`).join(" ")||"(无)":""})]})]}),s.jsxs("div",{className:"card",children:[s.jsx("div",{className:"colhead",children:"密钥(密文落盘)"}),s.jsxs("div",{className:"colbody",children:[s.jsx(c,{label:"密钥来源",value:((N=e==null?void 0:e.vault)==null?void 0:N.source)==="env"?"环境变量 NX_SK_PASSPHRASE(口令不落盘)":"本机密钥文件"}),s.jsx(c,{label:"密钥文件",value:((v=e==null?void 0:e.vault)==null?void 0:v.keyFile)||((u=e==null?void 0:e.vault)==null?void 0:u.saltFile)||"",copy:((g=e==null?void 0:e.vault)==null?void 0:g.keyFile)||((f=e==null?void 0:e.vault)==null?void 0:f.saltFile)}),s.jsx("div",{className:"row",children:s.jsx("span",{className:"desc",children:(w=e==null?void 0:e.vault)==null?void 0:w.note})}),s.jsx("div",{className:"row",children:s.jsx("span",{className:"desc bad",children:"删掉密钥文件或换掉口令后,已存的密文都解不开了——导出前先确认密钥可用。"})})]})]}),s.jsxs("div",{className:"card",children:[s.jsx("div",{className:"colhead",children:"面板与 CLI"}),s.jsxs("div",{className:"colbody",children:[s.jsxs("div",{className:"row",children:[s.jsx("span",{className:"name",children:"面板地址"}),s.jsx("span",{className:"desc mono",children:j}),s.jsx("span",{className:"acts",children:s.jsx(r,{className:"mono",text:j,children:"复制"})})]}),s.jsxs("div",{className:"row",children:[s.jsx("span",{className:"name",children:"重启面板"}),s.jsx("span",{className:"desc",children:"面板本身就是 serve 提供的;改代码后重启它即可"}),s.jsx("span",{className:"acts",children:s.jsx(r,{className:"mono",text:`nx-sk serve --port ${p}`,children:`nx-sk serve --port ${p}`})})]})]})]}),s.jsxs("div",{className:"card",children:[s.jsx("div",{className:"colhead",children:"默认行为"}),s.jsxs("div",{className:"pad",children:[s.jsxs("div",{className:"grid",children:[s.jsxs("div",{className:"field",children:[s.jsx("div",{className:"flabel",children:s.jsx("span",{children:"默认导出格式"})}),s.jsx("div",{className:"fctrl",children:s.jsxs("select",{value:l.exportFormat,onChange:a=>i({...l,exportFormat:a.target.value}),children:[s.jsx("option",{value:"both",children:"JSON + Markdown"}),s.jsx("option",{value:"json",children:"仅 JSON"}),s.jsx("option",{value:"md",children:"仅 Markdown"})]})})]}),s.jsxs("div",{className:"field",children:[s.jsxs("div",{className:"flabel",children:[s.jsx("span",{children:"默认导出目录"}),s.jsx("span",{className:"fkey",children:"留空 = ~/nx-sk/export"})]}),s.jsx("div",{className:"fctrl",children:s.jsx("input",{value:l.exportDir,onChange:a=>i({...l,exportDir:a.target.value})})})]}),s.jsxs("div",{className:"field",children:[s.jsxs("div",{className:"flabel",children:[s.jsx("span",{children:"默认栏目"}),s.jsx("span",{className:"fkey",children:"CLI 未指定 --section 时的首选"})]}),s.jsx("div",{className:"fctrl",children:s.jsx("input",{value:l.defaultSection,onChange:a=>i({...l,defaultSection:a.target.value})})})]}),s.jsxs("div",{className:"field",children:[s.jsxs("div",{className:"flabel",children:[s.jsx("span",{children:"导出默认带明文密钥"}),s.jsx("span",{className:"fkey",children:"默认开;要分享出去时关掉"})]}),s.jsx("div",{className:"fctrl",children:s.jsxs("label",{className:"inline",children:[s.jsx("input",{type:"checkbox",checked:!!l.includeSecretsInExport,onChange:a=>i({...l,includeSecretsInExport:a.target.checked})}),s.jsx("span",{className:l.includeSecretsInExport?"muted":"bad",children:l.includeSecretsInExport?"开(导出文件含真实凭据,注意别外发)":"关(凭据打码后再导出)"})]})})]})]}),s.jsx("div",{className:"rowgap",style:{marginTop:8},children:s.jsx("button",{className:"btn",onClick:E,children:"保存设置"})})]})]}),s.jsxs("div",{className:"card",children:[s.jsxs("div",{className:"colhead",children:["自动快照",s.jsx("span",{className:"right muted",children:((y=e==null?void 0:e.snapshots)==null?void 0:y.length)??0})]}),s.jsxs("div",{className:"colbody",children:[s.jsx("div",{className:"row",children:s.jsx("span",{className:"desc",children:"每次删除条目 / 栏目、修改设置前,都会在 ~/nx-sk/backup 留一份可回滚的整库快照。"})}),(S=e==null?void 0:e.snapshots)!=null&&S.length?e.snapshots.map(a=>s.jsxs("div",{className:"row",children:[s.jsx("span",{className:"mono name",children:a.name}),s.jsx("span",{className:"desc",children:a.at}),s.jsx("span",{className:"acts",children:s.jsxs("span",{className:"tag",children:[Math.ceil(a.bytes/1024)," KB"]})})]},a.name)):s.jsx(F,{children:"还没有快照。"})]})]}),e!=null&&e.migration?s.jsxs("div",{className:"card",children:[s.jsx("div",{className:"colhead",children:"数据迁移"}),s.jsxs("div",{className:"colbody",children:[s.jsx("div",{className:"row",children:s.jsxs("span",{className:"desc",children:["store 已从 v",e.migration.from," 迁到 v",e.migration.to,":密钥栏目字段 ",e.migration.fieldsBefore," → ",e.migration.fieldsAfter,",",e.migration.entries," 条条目"]})}),s.jsxs("div",{className:"row",children:[s.jsx("span",{className:"desc",children:"迁移前的原始文件"}),s.jsx("span",{className:"acts",children:s.jsx(r,{className:"mono",text:e.migration.snapshotRaw||"",children:e.migration.snapshot})})]}),e.migration.legacyValuesKept?s.jsx("div",{className:"row",children:s.jsxs("span",{className:"desc",children:["另保留了 ",e.migration.legacyValuesKept," 个旧字段的值(不再显示,但没删)"]})}):null]})]}):null,e!=null&&e.corrupt?s.jsxs("div",{className:"card",children:[s.jsx("div",{className:"colhead",children:"上次读取异常"}),s.jsx("div",{className:"colbody",children:s.jsx("div",{className:"row",children:s.jsxs("span",{className:"desc bad",children:["store.json 解析失败,已挪到 ",e.corrupt.to,"(原文件没有被覆盖)"]})})})]}):null,s.jsx(I,{module:"settings"})]})}function c({label:e,value:t,copy:n}){return s.jsxs("div",{className:"row",children:[s.jsx("span",{className:"name",children:e}),s.jsx("span",{className:"desc mono",children:t||"(空)"}),n?s.jsx("span",{className:"acts",children:s.jsx(r,{className:"mono",text:n,children:"复制"})}):s.jsx($,{children:" "})]})}export{D as default};
@@ -4,7 +4,7 @@
4
4
  <meta charset="utf-8" />
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1" />
6
6
  <title>nx-sk · 个人资源管理器</title>
7
- <script type="module" crossorigin src="/assets/index-CpF00ycO.js"></script>
7
+ <script type="module" crossorigin src="/assets/index-BnVuH1lC.js"></script>
8
8
  <link rel="stylesheet" crossorigin href="/assets/index-CwF5hM2v.css">
9
9
  </head>
10
10
  <body>