koishi-plugin-oni-sync-bot 0.4.1 → 0.5.1

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/dist/index.js CHANGED
@@ -1 +1 @@
1
- import{defineComponent as P,ref as D,watch as G,onMounted as H,resolveComponent as p,openBlock as _,createBlock as L,withCtx as d,createVNode as a,createElementBlock as v,Fragment as S,renderList as I,createElementVNode as t,toDisplayString as g,computed as X,reactive as j,createCommentVNode as C,normalizeClass as O,createTextVNode as x,unref as K}from"vue";import{store as Q,Time as J,message as q}from"@koishijs/client";const Z="yyyy-MM-dd hh:mm:ss",ee=P({__name:"page",setup(l){const n=D(),s=D([]);function o(c){const r=J.template(Z,new Date(c.timestamp)),e=c.type.toUpperCase(),i=c.content.replace(/\u001b\[[0-9;]*m/g,"");return`[${r}] [${e}] ${i}`}G(()=>Q.onilogs,c=>{c&&(s.value=c.map(o))},{deep:true,immediate:true});const m=()=>{n.value&&(n.value.scrollTop=n.value.scrollHeight)};return G(()=>s.value.length,()=>{setTimeout(m,0)}),H(()=>{m()}),(c,r)=>{const e=p("k-card"),i=p("k-layout");return _(),L(i,null,{default:d(()=>[a(e,{class:"log-container",ref_key:"scrollRef",ref:n},{default:d(()=>[(_(true),v(S,null,I(s.value,(f,u)=>(_(),v("div",{key:u,class:"log-line"},[t("pre",null,g(f),1)]))),128))]),_:1},512)]),_:1})}}}),F=(l,n)=>{const s=l.__vccOpts||l;for(const[o,m]of n)s[o]=m;return s},te=F(ee,[["__scopeId","data-v-361e99da"]]),A=10,se=2e4,oe=1.33,k={steamEngine:2e3,oilEngine:200,hydrogenEngine:500,biodieselEngine:200,CommandModule:200,RoboPilotCommandModule:200,SolidBooster:1e3,LiquidFuelTank:100,OxidizerTank:100,OxidizerTankLiquid:100,CargoBay:2e3,GasCargoBay:2e3,LiquidCargoBay:2e3,SpecialCargoBay:2e3,TouristModule:200,ResearchModule:200,person:30},V={steam:20,oil:40,hydrogen:60,biodiesel:50,booster:12e3},W={steam:900,fuel:900,oxygen:2700},le={steam:"steamEngine",oil:"oilEngine",hydrogen:"hydrogenEngine",biodiesel:"biodieselEngine"},ae={ResearchModule:"研究舱",CargoBay:"固体货舱",GasCargoBay:"气体货舱",LiquidCargoBay:"液体货舱",SpecialCargoBay:"生物货舱",TouristModule:"观光舱",RoboPilotCommandModule:"机器驾驶舱"};function U(l){return Math.ceil(Math.max(l,Math.pow(l/300,3.2)))}function ne(l){const n={};for(const[s,o]of Object.entries(l))typeof o=="number"&&o>=0&&(n[s]=o);return n}function ie(l){let n=k.CommandModule;for(const s in l)Object.prototype.hasOwnProperty.call(l,s)&&(n+=(k[s]||0)*l[s]);return n}function z(l){return l.length===0?[]:(l.sort((n,s)=>n.weight-s.weight),[l[0]])}function re(l,n){l+=k.steamEngine;const s=[];for(let o=0;o<=A;o++){const m=l+k.SolidBooster*o,c=V.booster*o;for(let r=0;r<=W.steam;r++){const e=m+r,i=c+V.steam*r,f=U(e),u=i-f;if(u>=n){s.push({capacity:r,booster:o,weight:e,mergedDistance:i,punish:f,finalDistance:u});break}}}return z(s)}function de(l,n,s,o,m,c,r,e){const i=Math.ceil(l/W.fuel),f=Math.ceil(l/W.oxygen),u=e==="liquid"?k.OxidizerTankLiquid:k.OxidizerTank,y=s+k.LiquidFuelTank*i+u*f,h=l*2,B=y+h,M=Math.floor(o+m*l*c),R=U(B),E=M-R;return E<r?{isValid:false}:{isValid:true,solution:{capacity:l,booster:n,fuelCount:i,oxygenCount:f,dryWeight:y,wetWeight:h,weight:B,mergedDistance:M,punish:R,finalDistance:E}}}function ce(l,n,s,o,m){const c=V[l],r=o==="liquid"?oe:1;n+=k[le[l]];const e=[];for(let i=0;i<=A;i++){const f=n+k.SolidBooster*i,u=V.booster*i;for(let y=0;y<=se;y+=10){const h=de(y,i,f,u,c,r,s,o);if(h.isValid){e.push(h.solution);break}}}if(e.length===0)return[];if(!m){const i=new Map;for(const f of e){const u=f.fuelCount;(!i.has(u)||i.get(u).weight>f.weight)&&i.set(u,f)}return z(Array.from(i.values()))}return z(e)}function ue(l){const{type:n,distance:s,oxygenType:o,allowWaste:m,...c}=l,r=ne(c),e=ie(r);return n==="steam"?re(e,s):ce(n,e,s,o,m)}const pe={class:"rocket-calculator sci-fi-bg"},me={class:"content-layout"},fe={class:"config-section"},_e={class:"distance-control"},ge={class:"distance-step-selector"},ve={class:"distance-input-wrapper"},ye={class:"distance-value"},be={class:"oxidizer-hint"},Ce={class:"config-section"},ke={class:"modules-grid"},he={class:"module-header"},xe={class:"module-name"},Ee={key:0,class:"empty-state"},Me={key:1,class:"empty-state"},Te={class:"key-stats"},Be={class:"stat-item primary"},Re={class:"stat-value"},we={class:"stat-item success"},Se={class:"stat-value"},Le={class:"stat-item warning"},Ve={class:"stat-value"},Oe={class:"detail-stats"},qe={class:"detail-grid"},De={class:"detail-item"},Ie={class:"detail-label"},We={class:"detail-value"},ze={class:"detail-item"},Fe={class:"detail-value"},Ne={key:0,class:"detail-item"},Ge={class:"detail-value"},Pe={key:1,class:"detail-item"},Ae={class:"detail-value"},Ue={class:"data-table-section"},$e={class:"table-wrapper"},Ye=P({__name:"calculator",setup(l){const n=X(()=>{const r=[];for(let e=1e4;e<=19e4;e+=1e4)r.push(e);return r}),s=j({type:"steam",distance:1e4,oxygenType:"solid",allowWaste:false,ResearchModule:0,CargoBay:0,GasCargoBay:0,LiquidCargoBay:0,SpecialCargoBay:0,TouristModule:0,RoboPilotCommandModule:0}),o=D(null),m=()=>{try{const r=ue(s);o.value=r,r.length>0?q.success("解算完成!已收敛到最优解"):q.warning("解算失败,无解空间")}catch(r){q.error("解算器异常"),console.error(r)}},c=()=>{s.type="steam",s.distance=1e4,s.oxygenType="solid",s.ResearchModule=0,s.CargoBay=0,s.GasCargoBay=0,s.LiquidCargoBay=0,s.SpecialCargoBay=0,s.TouristModule=0,s.RoboPilotCommandModule=0,o.value=null};return(r,e)=>{const i=p("el-option"),f=p("el-select"),u=p("el-form-item"),y=p("el-button"),h=p("el-radio-button"),B=p("el-radio-group"),M=p("el-form"),R=p("el-input-number"),E=p("k-card"),N=p("el-divider"),T=p("el-table-column"),$=p("el-table");return _(),v("div",pe,[C(" 背景装饰网格 "),e[32]||(e[32]=t("div",{class:"grid-overlay"},null,-1)),a(E,{class:"header-card sci-fi-card"},{default:d(()=>[e[29]||(e[29]=t("div",{class:"header-glow"},null,-1)),e[30]||(e[30]=t("h1",{class:"sci-fi-title"},"ONI ROCKET CALCULATOR",-1)),e[31]||(e[31]=t("p",{class:"sci-fi-subtitle"},"缺氧火箭最优配置解算系统 · 基于官方物理引擎",-1)),t("div",me,[C(" 输入控制台 "),a(E,{class:"form-card sci-fi-card"},{default:d(()=>[e[9]||(e[9]=t("div",{class:"card-header-line"},null,-1)),C(" 主配置 "),t("div",fe,[e[6]||(e[6]=t("h3",{class:"section-title"},"【核心参数】",-1)),a(M,{model:s,size:"large",class:"sci-fi-form","label-position":"top"},{default:d(()=>[a(u,{label:"引擎类型"},{default:d(()=>[a(f,{modelValue:s.type,"onUpdate:modelValue":e[0]||(e[0]=b=>s.type=b),style:{width:"100%"},class:"sci-fi-select"},{default:d(()=>[a(i,{label:"蒸汽引擎",value:"steam"}),a(i,{label:"石油引擎",value:"oil"}),a(i,{label:"液氢引擎",value:"hydrogen"}),a(i,{label:"生物柴油引擎",value:"biodiesel"})]),_:1},8,["modelValue"])]),_:1}),a(u,{label:"目标轨道"},{default:d(()=>[t("div",_e,[C(" 10000km 一档的步进选择器 "),t("div",ge,[(_(true),v(S,null,I(n.value,b=>(_(),L(y,{key:b,class:O(["step-btn",{active:s.distance===b}]),onClick:w=>s.distance=b},{default:d(()=>[x(g(b/1e3)+"k ",1)]),_:2},1032,["class","onClick"]))),128))]),t("div",ve,[e[2]||(e[2]=t("span",{class:"distance-label"},"当前:",-1)),t("span",ye,g(s.distance.toLocaleString()),1),e[3]||(e[3]=t("span",{class:"unit"},"km",-1))])])]),_:1}),s.type!=="steam"?(_(),L(u,{key:0,label:"氧化剂"},{default:d(()=>[a(B,{modelValue:s.oxygenType,"onUpdate:modelValue":e[1]||(e[1]=b=>s.oxygenType=b),class:"sci-fi-radio-group"},{default:d(()=>[a(h,{label:"solid"},{default:d(()=>[...e[4]||(e[4]=[x("氧石",-1)])]),_:1}),a(h,{label:"liquid"},{default:d(()=>[...e[5]||(e[5]=[x("液氧",-1)])]),_:1})]),_:1},8,["modelValue"]),t("div",be,[t("span",{class:O(["hint-item",{active:s.oxygenType==="solid"}])},"1.0x 效率",2),t("span",{class:O(["hint-item",{active:s.oxygenType==="liquid"}])},"1.33x 效率",2)])]),_:1})):C("v-if",true)]),_:1},8,["model"])]),e[10]||(e[10]=t("div",{class:"divider-line"},null,-1)),C(" 可选模块 "),t("div",Ce,[e[8]||(e[8]=t("h3",{class:"section-title"},"【载荷配置】",-1)),a(M,{model:s,size:"large",class:"modules-form","label-position":"top"},{default:d(()=>[t("div",ke,[(_(true),v(S,null,I(K(ae),(b,w)=>(_(),v("div",{key:w,class:"module-item"},[t("div",he,[t("span",xe,g(b),1)]),a(R,{modelValue:s[w],"onUpdate:modelValue":Y=>s[w]=Y,min:0,max:20,class:"module-input"},null,8,["modelValue","onUpdate:modelValue"])]))),128))]),a(u,{class:"calculate-btn-wrapper"},{default:d(()=>[a(y,{onClick:m,class:"sci-fi-calculate-btn"},{default:d(()=>[...e[7]||(e[7]=[t("span",{class:"btn-text"},"▶ 执行解算",-1),t("span",{class:"btn-glow"},null,-1)])]),_:1})]),_:1})]),_:1},8,["model"])])]),_:1}),C(" 结果显示面板 "),a(E,{class:"result-card sci-fi-card"},{default:d(()=>[e[28]||(e[28]=t("div",{class:"card-header-line"},null,-1)),o.value?o.value.length===0?(_(),v("div",Me,[e[13]||(e[13]=t("div",{class:"empty-icon"},"⚠️",-1)),e[14]||(e[14]=t("p",{class:"empty-text error"},"解算失败",-1)),e[15]||(e[15]=t("p",{class:"empty-hint"},"无法找到满足条件的配置,请尝试减少载荷",-1)),a(y,{onClick:c,class:"sci-fi-reset-btn"},{default:d(()=>[...e[12]||(e[12]=[x("重置参数",-1)])]),_:1})])):(_(),v(S,{key:2},[e[27]||(e[27]=t("div",{class:"result-header"},[t("h3",{class:"result-title"},"✅ 最优解算结果"),t("div",{class:"result-status"},[t("span",{class:"status-dot"}),t("span",null,"CONVERGED")])],-1)),t("div",Te,[t("div",Be,[e[17]||(e[17]=t("div",{class:"stat-label"},"总起飞重量",-1)),t("div",Re,[x(g(o.value[0].weight.toLocaleString())+" ",1),e[16]||(e[16]=t("span",{class:"stat-unit"},"kg",-1))])]),t("div",we,[e[19]||(e[19]=t("div",{class:"stat-label"},"预计射程",-1)),t("div",Se,[x(g(o.value[0].finalDistance.toLocaleString())+" ",1),e[18]||(e[18]=t("span",{class:"stat-unit"},"km",-1))])]),t("div",Le,[e[21]||(e[21]=t("div",{class:"stat-label"},"质量惩罚",-1)),t("div",Ve,[x(g(o.value[0].punish.toLocaleString())+" ",1),e[20]||(e[20]=t("span",{class:"stat-unit"},"km",-1))])])]),a(N,{class:"sci-fi-divider"}),t("div",Oe,[e[25]||(e[25]=t("h4",{class:"detail-title"},"【配置详情】",-1)),t("div",qe,[t("div",De,[t("span",Ie,g(s.type==="steam"?"蒸汽填充量":"燃料填充量"),1),t("span",We,g(o.value[0].capacity.toLocaleString())+" kg",1)]),t("div",ze,[e[22]||(e[22]=t("span",{class:"detail-label"},"助推器数量",-1)),t("span",Fe,g(o.value[0].booster)+" 个",1)]),o.value[0].fuelCount!==void 0?(_(),v("div",Ne,[e[23]||(e[23]=t("span",{class:"detail-label"},"燃料舱数量",-1)),t("span",Ge,g(o.value[0].fuelCount)+" 个",1)])):C("v-if",true),o.value[0].oxygenCount!==void 0?(_(),v("div",Pe,[e[24]||(e[24]=t("span",{class:"detail-label"},"氧化剂舱数量",-1)),t("span",Ae,g(o.value[0].oxygenCount)+" 个",1)])):C("v-if",true)])]),a(N,{class:"sci-fi-divider"}),t("div",Ue,[e[26]||(e[26]=t("h4",{class:"detail-title"},"【原始数据】",-1)),t("div",$e,[a($,{data:o.value,stripe:"",class:"sci-fi-table"},{default:d(()=>[a(T,{prop:"weight",label:"总重(kg)",sortable:""}),a(T,{prop:"finalDistance",label:"射程(km)",sortable:""}),a(T,{prop:"booster",label:"助推器"}),a(T,{prop:"fuelCount",label:"燃料舱"}),a(T,{prop:"oxygenCount",label:"氧化剂舱"})]),_:1},8,["data"])])])],64)):(_(),v("div",Ee,[...e[11]||(e[11]=[t("div",{class:"scan-line"},null,-1),t("div",{class:"empty-icon"},"📡",-1),t("p",{class:"empty-text"},"等待输入参数...",-1),t("p",{class:"empty-hint"},"请配置核心参数与载荷",-1)])]))]),_:1})])]),_:1})])}}}),He=F(Ye,[["__scopeId","data-v-3e8f9409"]]),Xe={};function je(l,n){const s=p("k-slot"),o=p("el-scrollbar"),m=p("k-layout");return _(),L(m,null,{default:d(()=>[a(o,{class:"scrollbar"},{default:d(()=>[a(s,{name:"calculator"})]),_:1})]),_:1})}const Ke=F(Xe,[["render",je],["__scopeId","data-v-e3ac158b"]]),Ze=l=>{l.page({name:"同步机器人",path:"/onilogs",component:te,fields:["onilogs"]}),l.page({name:"火箭计算器",path:"/calculator",component:Ke}),l.slot({type:"calculator",component:He})};export{Ze as default};
1
+ import{defineComponent as Y,ref as M,watch as N,onMounted as K,resolveComponent as b,openBlock as g,createBlock as I,withCtx as v,createVNode as d,createElementBlock as C,Fragment as V,renderList as z,createElementVNode as e,toDisplayString as f,computed as D,reactive as Q,createCommentVNode as _,normalizeClass as S,createTextVNode as x,unref as J,withDirectives as H,vModelText as Z,vModelSelect as ee}from"vue";import{store as U,Time as te,message as P,send as se}from"@koishijs/client";const oe="yyyy-MM-dd hh:mm:ss",le=Y({__name:"page",setup(l){const i=M(),s=M([]);function o(m){const r=te.template(oe,new Date(m.timestamp)),t=m.type.toUpperCase(),u=m.content.replace(/\u001b\[[0-9;]*m/g,"");return`[${r}] [${t}] ${u}`}N(()=>U.onilogs,m=>{m&&(s.value=m.map(o))},{deep:true,immediate:true});const p=()=>{i.value&&(i.value.scrollTop=i.value.scrollHeight)};return N(()=>s.value.length,()=>{setTimeout(p,0)}),K(()=>{p()}),(m,r)=>{const t=b("k-card"),u=b("k-layout");return g(),I(u,null,{default:v(()=>[d(t,{class:"log-container",ref_key:"scrollRef",ref:i},{default:v(()=>[(g(true),C(V,null,z(s.value,(k,y)=>(g(),C("div",{key:y,class:"log-line"},[e("pre",null,f(k),1)]))),128))]),_:1},512)]),_:1})}}}),O=(l,i)=>{const s=l.__vccOpts||l;for(const[o,p]of i)s[o]=p;return s},ae=O(le,[["__scopeId","data-v-361e99da"]]),X=10,ne=2e4,ie=1.33,E={steamEngine:2e3,oilEngine:200,hydrogenEngine:500,biodieselEngine:200,CommandModule:200,RoboPilotCommandModule:200,SolidBooster:1e3,LiquidFuelTank:100,OxidizerTank:100,OxidizerTankLiquid:100,CargoBay:2e3,GasCargoBay:2e3,LiquidCargoBay:2e3,SpecialCargoBay:2e3,TouristModule:200,ResearchModule:200,person:30},W={steam:20,oil:40,hydrogen:60,biodiesel:50,booster:12e3},F={steam:900,fuel:900,oxygen:2700},ce={steam:"steamEngine",oil:"oilEngine",hydrogen:"hydrogenEngine",biodiesel:"biodieselEngine"},de={ResearchModule:"研究舱",CargoBay:"固体货舱",GasCargoBay:"气体货舱",LiquidCargoBay:"液体货舱",SpecialCargoBay:"生物货舱",TouristModule:"观光舱",RoboPilotCommandModule:"机器驾驶舱"};function j(l){return Math.ceil(Math.max(l,Math.pow(l/300,3.2)))}function re(l){const i={};for(const[s,o]of Object.entries(l))typeof o=="number"&&o>=0&&(i[s]=o);return i}function ue(l){let i=E.CommandModule;for(const s in l)Object.prototype.hasOwnProperty.call(l,s)&&(i+=(E[s]||0)*l[s]);return i}function G(l){return l.length===0?[]:(l.sort((i,s)=>i.weight-s.weight),[l[0]])}function pe(l,i){l+=E.steamEngine;const s=[];for(let o=0;o<=X;o++){const p=l+E.SolidBooster*o,m=W.booster*o;for(let r=0;r<=F.steam;r++){const t=p+r,u=m+W.steam*r,k=j(t),y=u-k;if(y>=i){s.push({capacity:r,booster:o,weight:t,mergedDistance:u,punish:k,finalDistance:y});break}}}return G(s)}function me(l,i,s,o,p,m,r,t){const u=Math.ceil(l/F.fuel),k=Math.ceil(l/F.oxygen),y=t==="liquid"?E.OxidizerTankLiquid:E.OxidizerTank,h=s+E.LiquidFuelTank*u+y*k,w=l*2,L=h+w,B=Math.floor(o+p*l*m),R=j(L),$=B-R;return $<r?{isValid:false}:{isValid:true,solution:{capacity:l,booster:i,fuelCount:u,oxygenCount:k,dryWeight:h,wetWeight:w,weight:L,mergedDistance:B,punish:R,finalDistance:$}}}function ve(l,i,s,o,p){const m=W[l],r=o==="liquid"?ie:1;i+=E[ce[l]];const t=[];for(let u=0;u<=X;u++){const k=i+E.SolidBooster*u,y=W.booster*u;for(let h=0;h<=ne;h+=10){const w=me(h,u,k,y,m,r,s,o);if(w.isValid){t.push(w.solution);break}}}if(t.length===0)return[];if(!p){const u=new Map;for(const k of t){const y=k.fuelCount;(!u.has(y)||u.get(y).weight>k.weight)&&u.set(y,k)}return G(Array.from(u.values()))}return G(t)}function _e(l){const{type:i,distance:s,oxygenType:o,allowWaste:p,...m}=l,r=re(m),t=ue(r);return i==="steam"?pe(t,s):ve(i,t,s,o,p)}const fe={class:"rocket-calculator sci-fi-bg"},ge={class:"content-layout"},ye={class:"config-section"},be={class:"distance-control"},ke={class:"distance-step-selector"},Ce={class:"distance-input-wrapper"},he={class:"distance-value"},we={class:"oxidizer-hint"},Te={class:"config-section"},Se={class:"modules-grid"},$e={class:"module-header"},xe={class:"module-name"},Me={key:0,class:"empty-state"},Ee={key:1,class:"empty-state"},Be={class:"key-stats"},Le={class:"stat-item primary"},Re={class:"stat-value"},De={class:"stat-item success"},Ve={class:"stat-value"},Ie={class:"stat-item warning"},Oe={class:"stat-value"},qe={class:"detail-stats"},ze={class:"detail-grid"},We={class:"detail-item"},Ae={class:"detail-label"},Pe={class:"detail-value"},Ne={class:"detail-item"},Ue={class:"detail-value"},Fe={key:0,class:"detail-item"},Ge={class:"detail-value"},Ye={key:1,class:"detail-item"},He={class:"detail-value"},Xe={class:"data-table-section"},je={class:"table-wrapper"},Ke=Y({__name:"calculator",setup(l){const i=D(()=>{const r=[];for(let t=1e4;t<=19e4;t+=1e4)r.push(t);return r}),s=Q({type:"steam",distance:1e4,oxygenType:"solid",allowWaste:false,ResearchModule:0,CargoBay:0,GasCargoBay:0,LiquidCargoBay:0,SpecialCargoBay:0,TouristModule:0,RoboPilotCommandModule:0}),o=M(null),p=()=>{try{const r=_e(s);o.value=r,r.length>0?P.success("解算完成!已收敛到最优解"):P.warning("解算失败,无解空间")}catch(r){P.error("解算器异常"),console.error(r)}},m=()=>{s.type="steam",s.distance=1e4,s.oxygenType="solid",s.ResearchModule=0,s.CargoBay=0,s.GasCargoBay=0,s.LiquidCargoBay=0,s.SpecialCargoBay=0,s.TouristModule=0,s.RoboPilotCommandModule=0,o.value=null};return(r,t)=>{const u=b("el-option"),k=b("el-select"),y=b("el-form-item"),h=b("el-button"),w=b("el-radio-button"),L=b("el-radio-group"),B=b("el-form"),R=b("el-input-number"),$=b("k-card"),q=b("el-divider"),c=b("el-table-column"),n=b("el-table");return g(),C("div",fe,[_(" 背景装饰网格 "),t[32]||(t[32]=e("div",{class:"grid-overlay"},null,-1)),d($,{class:"header-card sci-fi-card"},{default:v(()=>[t[29]||(t[29]=e("div",{class:"header-glow"},null,-1)),t[30]||(t[30]=e("h1",{class:"sci-fi-title"},"ONI ROCKET CALCULATOR",-1)),t[31]||(t[31]=e("p",{class:"sci-fi-subtitle"},"缺氧火箭最优配置解算系统 · 基于官方物理引擎",-1)),e("div",ge,[_(" 输入控制台 "),d($,{class:"form-card sci-fi-card"},{default:v(()=>[t[9]||(t[9]=e("div",{class:"card-header-line"},null,-1)),_(" 主配置 "),e("div",ye,[t[6]||(t[6]=e("h3",{class:"section-title"},"【核心参数】",-1)),d(B,{model:s,size:"large",class:"sci-fi-form","label-position":"top"},{default:v(()=>[d(y,{label:"引擎类型"},{default:v(()=>[d(k,{modelValue:s.type,"onUpdate:modelValue":t[0]||(t[0]=a=>s.type=a),style:{width:"100%"},class:"sci-fi-select"},{default:v(()=>[d(u,{label:"蒸汽引擎",value:"steam"}),d(u,{label:"石油引擎",value:"oil"}),d(u,{label:"液氢引擎",value:"hydrogen"}),d(u,{label:"生物柴油引擎",value:"biodiesel"})]),_:1},8,["modelValue"])]),_:1}),d(y,{label:"目标轨道"},{default:v(()=>[e("div",be,[_(" 10000km 一档的步进选择器 "),e("div",ke,[(g(true),C(V,null,z(i.value,a=>(g(),I(h,{key:a,class:S(["step-btn",{active:s.distance===a}]),onClick:T=>s.distance=a},{default:v(()=>[x(f(a/1e3)+"k ",1)]),_:2},1032,["class","onClick"]))),128))]),e("div",Ce,[t[2]||(t[2]=e("span",{class:"distance-label"},"当前:",-1)),e("span",he,f(s.distance.toLocaleString()),1),t[3]||(t[3]=e("span",{class:"unit"},"km",-1))])])]),_:1}),s.type!=="steam"?(g(),I(y,{key:0,label:"氧化剂"},{default:v(()=>[d(L,{modelValue:s.oxygenType,"onUpdate:modelValue":t[1]||(t[1]=a=>s.oxygenType=a),class:"sci-fi-radio-group"},{default:v(()=>[d(w,{label:"solid"},{default:v(()=>[...t[4]||(t[4]=[x("氧石",-1)])]),_:1}),d(w,{label:"liquid"},{default:v(()=>[...t[5]||(t[5]=[x("液氧",-1)])]),_:1})]),_:1},8,["modelValue"]),e("div",we,[e("span",{class:S(["hint-item",{active:s.oxygenType==="solid"}])},"1.0x 效率",2),e("span",{class:S(["hint-item",{active:s.oxygenType==="liquid"}])},"1.33x 效率",2)])]),_:1})):_("v-if",true)]),_:1},8,["model"])]),t[10]||(t[10]=e("div",{class:"divider-line"},null,-1)),_(" 可选模块 "),e("div",Te,[t[8]||(t[8]=e("h3",{class:"section-title"},"【载荷配置】",-1)),d(B,{model:s,size:"large",class:"modules-form","label-position":"top"},{default:v(()=>[e("div",Se,[(g(true),C(V,null,z(J(de),(a,T)=>(g(),C("div",{key:T,class:"module-item"},[e("div",$e,[e("span",xe,f(a),1)]),d(R,{modelValue:s[T],"onUpdate:modelValue":A=>s[T]=A,min:0,max:20,class:"module-input"},null,8,["modelValue","onUpdate:modelValue"])]))),128))]),d(y,{class:"calculate-btn-wrapper"},{default:v(()=>[d(h,{onClick:p,class:"sci-fi-calculate-btn"},{default:v(()=>[...t[7]||(t[7]=[e("span",{class:"btn-text"},"▶ 执行解算",-1),e("span",{class:"btn-glow"},null,-1)])]),_:1})]),_:1})]),_:1},8,["model"])])]),_:1}),_(" 结果显示面板 "),d($,{class:"result-card sci-fi-card"},{default:v(()=>[t[28]||(t[28]=e("div",{class:"card-header-line"},null,-1)),o.value?o.value.length===0?(g(),C("div",Ee,[t[13]||(t[13]=e("div",{class:"empty-icon"},"⚠️",-1)),t[14]||(t[14]=e("p",{class:"empty-text error"},"解算失败",-1)),t[15]||(t[15]=e("p",{class:"empty-hint"},"无法找到满足条件的配置,请尝试减少载荷",-1)),d(h,{onClick:m,class:"sci-fi-reset-btn"},{default:v(()=>[...t[12]||(t[12]=[x("重置参数",-1)])]),_:1})])):(g(),C(V,{key:2},[t[27]||(t[27]=e("div",{class:"result-header"},[e("h3",{class:"result-title"},"✅ 最优解算结果"),e("div",{class:"result-status"},[e("span",{class:"status-dot"}),e("span",null,"CONVERGED")])],-1)),e("div",Be,[e("div",Le,[t[17]||(t[17]=e("div",{class:"stat-label"},"总起飞重量",-1)),e("div",Re,[x(f(o.value[0].weight.toLocaleString())+" ",1),t[16]||(t[16]=e("span",{class:"stat-unit"},"kg",-1))])]),e("div",De,[t[19]||(t[19]=e("div",{class:"stat-label"},"预计射程",-1)),e("div",Ve,[x(f(o.value[0].finalDistance.toLocaleString())+" ",1),t[18]||(t[18]=e("span",{class:"stat-unit"},"km",-1))])]),e("div",Ie,[t[21]||(t[21]=e("div",{class:"stat-label"},"质量惩罚",-1)),e("div",Oe,[x(f(o.value[0].punish.toLocaleString())+" ",1),t[20]||(t[20]=e("span",{class:"stat-unit"},"km",-1))])])]),d(q,{class:"sci-fi-divider"}),e("div",qe,[t[25]||(t[25]=e("h4",{class:"detail-title"},"【配置详情】",-1)),e("div",ze,[e("div",We,[e("span",Ae,f(s.type==="steam"?"蒸汽填充量":"燃料填充量"),1),e("span",Pe,f(o.value[0].capacity.toLocaleString())+" kg",1)]),e("div",Ne,[t[22]||(t[22]=e("span",{class:"detail-label"},"助推器数量",-1)),e("span",Ue,f(o.value[0].booster)+" 个",1)]),o.value[0].fuelCount!==void 0?(g(),C("div",Fe,[t[23]||(t[23]=e("span",{class:"detail-label"},"燃料舱数量",-1)),e("span",Ge,f(o.value[0].fuelCount)+" 个",1)])):_("v-if",true),o.value[0].oxygenCount!==void 0?(g(),C("div",Ye,[t[24]||(t[24]=e("span",{class:"detail-label"},"氧化剂舱数量",-1)),e("span",He,f(o.value[0].oxygenCount)+" 个",1)])):_("v-if",true)])]),d(q,{class:"sci-fi-divider"}),e("div",Xe,[t[26]||(t[26]=e("h4",{class:"detail-title"},"【原始数据】",-1)),e("div",je,[d(n,{data:o.value,stripe:"",class:"sci-fi-table"},{default:v(()=>[d(c,{prop:"weight",label:"总重(kg)",sortable:""}),d(c,{prop:"finalDistance",label:"射程(km)",sortable:""}),d(c,{prop:"booster",label:"助推器"}),d(c,{prop:"fuelCount",label:"燃料舱"}),d(c,{prop:"oxygenCount",label:"氧化剂舱"})]),_:1},8,["data"])])])],64)):(g(),C("div",Me,[...t[11]||(t[11]=[e("div",{class:"scan-line"},null,-1),e("div",{class:"empty-icon"},"📡",-1),e("p",{class:"empty-text"},"等待输入参数...",-1),e("p",{class:"empty-hint"},"请配置核心参数与载荷",-1)])]))]),_:1})])]),_:1})])}}}),Qe=O(Ke,[["__scopeId","data-v-3e8f9409"]]),Je={};function Ze(l,i){const s=b("k-slot"),o=b("el-scrollbar"),p=b("k-layout");return g(),I(p,null,{default:v(()=>[d(o,{class:"scrollbar"},{default:v(()=>[d(s,{name:"calculator"})]),_:1})]),_:1})}const et=O(Je,[["render",Ze],["__scopeId","data-v-e3ac158b"]]),tt={};function st(l,i){const s=b("k-slot"),o=b("el-scrollbar"),p=b("k-layout");return g(),I(p,null,{default:v(()=>[d(o,{class:"scrollbar"},{default:v(()=>[d(s,{name:"wikimodule"})]),_:1})]),_:1})}const ot=O(tt,[["render",st],["__scopeId","data-v-8201028f"]]),lt={class:"page-container"},at={class:"search-bar"},nt={class:"content-wrap"},it={class:"main-card"},ct={class:"card-header"},dt={class:"header-count"},rt={class:"list-wrap"},ut={key:0,class:"empty-state"},pt={class:"item-content"},mt=["href"],vt={class:"item-meta"},_t={class:"meta-tag"},ft={class:"meta-tag"},gt={class:"item-actions"},yt=["onClick","disabled"],bt={class:"card-footer"},kt={class:"pagination-group"},Ct=["disabled"],ht={class:"page-text"},wt=["disabled"],Tt={class:"sidebar-card"},St={class:"sidebar-menu"},$t=Y({__name:"wikimodule",setup(l){const i=D(()=>U.moduleManager||[]),s=M(""),o=M(false),p=M("all"),m=M(1),r=M(50),t=M({show:false,message:"",type:"success"});let u=null;const k=D(()=>i.value.filter(c=>!c.syncStatus).length),y=D(()=>{let c=i.value;if(p.value==="synced"?c=c.filter(n=>n.syncStatus):p.value==="unsynced"&&(c=c.filter(n=>!n.syncStatus)),s.value){const n=s.value.toLowerCase();c=c.filter(a=>a.pageTitle.toLowerCase().includes(n))}return c}),h=D(()=>Math.ceil(y.value.length/r.value)||1),w=D(()=>{const c=(m.value-1)*r.value;return y.value.slice(c,c+r.value)});N([p,s],()=>{m.value=1});const L=c=>`https://zh.kleiwikigg.org/${encodeURIComponent(c)}`,B=c=>c?new Date(c).toLocaleString("zh-CN"):"-",R=c=>c?Date.now()-new Date(c).getTime()>1e3*60*60*24*30:false,$=(c,n="success")=>{u&&clearTimeout(u),t.value={show:true,message:c,type:n},u=setTimeout(()=>{t.value.show=false},3e3)},q=async c=>{if(!c.syncStatus){o.value=true;try{const n=c.pageid;await se("module-sync/update",{pageid:n,operator:"Console-Admin"});const a=U.moduleManager;if(a&&Array.isArray(a)){const T=a.find(A=>A.pageid===n);T&&(T.syncStatus=true,T.lastEditTime=new Date().toISOString(),T.user="Console-Admin")}$("✅ 已标记为已同步")}catch(n){console.error(n),$("❌ 操作失败,请重试","error")}finally{o.value=false}}};return(c,n)=>(g(),C("div",lt,[_(" 顶部标题 "),n[10]||(n[10]=e("h1",{class:"page-title"},"📦 模块同步管理",-1)),_(" 搜索栏 "),e("div",at,[H(e("input",{"onUpdate:modelValue":n[0]||(n[0]=a=>s.value=a),class:"search-input",placeholder:"搜索模块名称..."},null,512),[[Z,s.value]])]),_(" 主内容区(左侧列表+右侧筛选栏) "),e("div",nt,[_(" 左侧主卡片 "),e("div",it,[_(" 卡片头部 - 剩余未同步数量放在顶部 "),e("div",ct,[e("span",dt,[n[7]||(n[7]=x(" 🔴 剩余 ",-1)),e("strong",null,f(k.value),1),x(" 个未同步模块 | 总计 "+f(i.value.length)+" 个模块 ",1)])]),_(" 列表区域 "),e("div",rt,[!w.value||w.value.length===0?(g(),C("div",ut," 暂无匹配的数据,请调整搜索或筛选条件 ")):_("v-if",true),(g(true),C(V,null,z(w.value,a=>(g(),C("div",{key:a.pageid,class:S(["todo-item",{"item-synced":a.syncStatus,"item-unsynced":!a.syncStatus}])},[_(" 左侧内容 "),e("div",pt,[e("a",{href:L(a.pageTitle),target:"_blank",class:"item-title"},f(a.pageTitle),9,mt),e("div",vt,[e("span",_t,"ID: "+f(a.pageid),1),e("span",ft,"编辑者: "+f(a.user),1),e("span",{class:S(["meta-tag",{stale:R(a.lastEditTime)}])}," 🕐 "+f(B(a.lastEditTime)),3)])]),_(" 右侧操作区 "),e("div",gt,[e("span",{class:S(["status-badge",a.syncStatus?"status-on":"status-off"])},f(a.syncStatus?"✅ 已同步":"⏸️ 未同步"),3),_(" 按钮文字改为“标记同步”,点击直接触发,不再弹窗 "),e("button",{class:"btn-mark-sync",onClick:T=>q(a),disabled:a.syncStatus},f(a.syncStatus?"已处理":"✅ 标记同步"),9,yt)])],2))),128))]),_(" 底部分页 "),e("div",bt,[e("div",kt,[e("button",{class:"btn-page",onClick:n[1]||(n[1]=a=>m.value--),disabled:m.value<=1},"← 上一页",8,Ct),e("span",ht,"第 "+f(m.value)+" 页 / 共 "+f(h.value)+" 页",1),e("button",{class:"btn-page",onClick:n[2]||(n[2]=a=>m.value++),disabled:m.value>=h.value},"下一页 →",8,wt),H(e("select",{class:"page-size-select","onUpdate:modelValue":n[3]||(n[3]=a=>r.value=a)},[...n[8]||(n[8]=[e("option",{value:20},"20条/页",-1),e("option",{value:50},"50条/页",-1),e("option",{value:100},"100条/页",-1)])],512),[[ee,r.value,void 0,{number:true}]])])])]),_(" 右侧筛选操作栏 "),e("div",Tt,[n[9]||(n[9]=e("div",{class:"sidebar-header"}," 筛选✨ ",-1)),e("div",St,[e("button",{class:S(["menu-item",{active:p.value==="all"}]),onClick:n[4]||(n[4]=a=>p.value="all")}," 全部 ",2),e("button",{class:S(["menu-item",{active:p.value==="synced"}]),onClick:n[5]||(n[5]=a=>p.value="synced")}," 已同步 ",2),e("button",{class:S(["menu-item",{active:p.value==="unsynced"}]),onClick:n[6]||(n[6]=a=>p.value="unsynced")}," 未同步 ",2)])])]),_(" Toast 提示 "),t.value.show?(g(),C("div",{key:0,class:S(["toast",t.value.type])},f(t.value.message),3)):_("v-if",true)]))}}),xt=O($t,[["__scopeId","data-v-f5f301cb"]]),Bt=l=>{l.page({name:"同步机器人",path:"/onilogs",component:ae,fields:["onilogs"]}),l.page({name:"火箭计算器",path:"/calculator",component:et}),l.page({name:"wiki模块同步状态",path:"/wikimodules",fields:["moduleManager"],component:ot}),l.slot({type:"calculator",component:Qe}),l.slot({type:"wikimodule",component:xt})};export{Bt as default};
package/dist/style.css CHANGED
@@ -1 +1 @@
1
- .log-container[data-v-361e99da]{width:100%;height:100%;overflow-y:auto;padding:12px;font-family:monospace;background:#1e1e1e;color:#d4d4d4}.log-line[data-v-361e99da]{line-height:1.5;font-size:13px}pre[data-v-361e99da]{margin:0;font-family:inherit;white-space:pre-wrap;word-break:break-all}[data-v-3e8f9409]{box-sizing:border-box}.rocket-calculator[data-v-3e8f9409]{max-width:800px;margin:0 auto;padding:20px;box-sizing:border-box;position:relative;min-height:100vh;overflow-x:hidden}.sci-fi-bg[data-v-3e8f9409]{background:linear-gradient(135deg,#0a0e27,#1a1f3a,#0f172a);color:#e0e7ff}.grid-overlay[data-v-3e8f9409]{position:fixed;top:0;left:0;right:0;bottom:0;background-image:linear-gradient(rgba(0,255,255,.03) 1px,transparent 1px),linear-gradient(90deg,rgba(0,255,255,.03) 1px,transparent 1px);background-size:40px 40px;pointer-events:none;z-index:0}.sci-fi-card[data-v-3e8f9409]{background:#0f172af2;-webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px);border:1px solid rgba(0,255,255,.2);box-shadow:0 0 20px #00ffff1a,inset 0 0 20px #00000080;position:relative;overflow:visible;z-index:1}.sci-fi-card[data-v-3e8f9409] .k-card__body{padding:24px}.card-header-line[data-v-3e8f9409]{position:absolute;top:0;left:0;right:0;height:2px;background:linear-gradient(90deg,transparent,#00ffff,#8b5cf6,transparent);animation:lineGlow-3e8f9409 3s ease-in-out infinite;z-index:1}@keyframes lineGlow-3e8f9409{0%,to{opacity:.5}50%{opacity:1}}.header-card[data-v-3e8f9409]{margin-bottom:24px;text-align:center;position:relative;z-index:10;margin-top:8px}.header-glow[data-v-3e8f9409]{position:absolute;top:-50%;left:50%;transform:translate(-50%);width:200%;height:100%;background:radial-gradient(ellipse,rgba(139,92,246,.15) 0%,transparent 70%);pointer-events:none;z-index:-1}.sci-fi-title[data-v-3e8f9409]{margin:0 0 8px;font-size:28px;font-weight:800;letter-spacing:4px;color:#0ff;background:linear-gradient(90deg,#0ff,#8b5cf6,#0ff);background-size:200% auto;-webkit-background-clip:text;background-clip:text;-webkit-text-fill-color:transparent;animation:titleShine-3e8f9409 4s linear infinite;position:relative;z-index:2;text-shadow:0 0 30px rgba(0,255,255,.3);line-height:1.4}@keyframes titleShine-3e8f9409{0%{background-position:0% center}to{background-position:200% center}}.sci-fi-subtitle[data-v-3e8f9409]{margin:0;color:#64748b;font-size:13px;letter-spacing:2px;text-transform:uppercase;position:relative;z-index:2;line-height:1.5}.content-layout[data-v-3e8f9409]{display:flex;flex-direction:column;gap:24px;position:relative;z-index:1}.config-section[data-v-3e8f9409]{margin-bottom:20px;position:relative;z-index:1}.section-title[data-v-3e8f9409]{margin:0 0 20px;font-size:14px;color:#0ff;letter-spacing:2px;font-weight:600}.distance-control[data-v-3e8f9409]{width:100%}.distance-step-selector[data-v-3e8f9409]{display:grid;grid-template-columns:repeat(5,1fr);gap:8px;margin-bottom:16px}.step-btn[data-v-3e8f9409]{margin:0;background:#0000004d;border:1px solid rgba(0,255,255,.2);color:#94a3b8;padding:8px 4px;font-size:12px;font-weight:600;transition:all .2s ease;white-space:nowrap}.step-btn[data-v-3e8f9409]:hover{border-color:#00ffff80;color:#0ff;transform:translateY(-1px)}.step-btn.active[data-v-3e8f9409]{background:#00ffff26;border-color:#0ff;color:#0ff;box-shadow:0 0 15px #00ffff4d}.distance-input-wrapper[data-v-3e8f9409]{display:flex;align-items:center;justify-content:center;gap:8px;padding:12px;background:#0000004d;border:1px solid rgba(139,92,246,.3);border-radius:4px}.distance-label[data-v-3e8f9409]{color:#64748b;font-size:13px}.distance-value[data-v-3e8f9409]{font-size:20px;font-weight:800;color:#8b5cf6}.unit[data-v-3e8f9409]{color:#8b5cf6;font-weight:600;font-size:14px}.modules-grid[data-v-3e8f9409]{display:grid;grid-template-columns:1fr 1fr;gap:12px}.module-item[data-v-3e8f9409]{background:#00ffff0d;border:1px solid rgba(0,255,255,.1);padding:12px;border-radius:4px;transition:all .3s ease;display:flex;flex-direction:column;gap:8px}.module-item[data-v-3e8f9409]:hover{border-color:#00ffff4d;background:#00ffff14}.module-name[data-v-3e8f9409]{font-size:13px;color:#94a3b8}.module-input[data-v-3e8f9409]{width:100%}.module-input[data-v-3e8f9409] .el-input__wrapper{background:#0000004d;border:1px solid rgba(0,255,255,.2);box-shadow:none;padding:4px 6px}.module-input[data-v-3e8f9409] .el-input__inner{text-align:center;color:#0ff;font-weight:700;font-size:16px}.module-input[data-v-3e8f9409] .el-input-number__decrease,.module-input[data-v-3e8f9409] .el-input-number__increase{background:#0ff3;color:#0ff;border-color:#00ffff4d;font-weight:800;font-size:16px;transition:all .2s ease}.module-input[data-v-3e8f9409] .el-input-number__decrease:hover,.module-input[data-v-3e8f9409] .el-input-number__increase:hover{background:#0ff6;color:#fff}.module-input[data-v-3e8f9409] .el-input-number__decrease.is-disabled,.module-input[data-v-3e8f9409] .el-input-number__increase.is-disabled{background:#0003;color:#475569;border-color:#ffffff1a}.calculate-btn-wrapper[data-v-3e8f9409]{margin-top:24px;margin-bottom:0}.sci-fi-calculate-btn[data-v-3e8f9409]{width:100%;height:50px;background:linear-gradient(135deg,#0ff,#8b5cf6);border:none;color:#0a0e27;font-weight:800;font-size:16px;letter-spacing:2px;position:relative;overflow:hidden;transition:all .3s ease}.sci-fi-calculate-btn[data-v-3e8f9409]:hover{transform:translateY(-2px);box-shadow:0 10px 30px #00ffff4d}.btn-text[data-v-3e8f9409]{position:relative;z-index:1}.btn-glow[data-v-3e8f9409]{position:absolute;top:0;left:-100%;width:100%;height:100%;background:linear-gradient(90deg,transparent,rgba(255,255,255,.4),transparent);animation:btnScan-3e8f9409 2s ease-in-out infinite}@keyframes btnScan-3e8f9409{0%{left:-100%}to{left:100%}}.sci-fi-radio-group[data-v-3e8f9409]{width:100%;display:flex}.sci-fi-radio-group[data-v-3e8f9409] .el-radio-button{flex:1}.sci-fi-radio-group[data-v-3e8f9409] .el-radio-button__inner{width:100%;background:#0000004d;border:1px solid rgba(0,255,255,.2);color:#94a3b8;font-weight:600;padding:12px 10px;transition:all .2s ease}.sci-fi-radio-group[data-v-3e8f9409] .el-radio-button__inner:hover{color:#0ff;border-color:#0ff6}.sci-fi-radio-group[data-v-3e8f9409] .el-radio-button__orig-radio:checked+.el-radio-button__inner{background:#00ffff26;border-color:#0ff;color:#0ff;box-shadow:0 0 15px #0ff3}.oxidizer-hint[data-v-3e8f9409]{display:flex;justify-content:space-around;margin-top:8px}.hint-item[data-v-3e8f9409]{font-size:12px;color:#64748b;transition:all .2s ease}.hint-item.active[data-v-3e8f9409]{color:#0ff;font-weight:600}.divider-line[data-v-3e8f9409]{height:1px;background:linear-gradient(90deg,transparent,rgba(0,255,255,.3),transparent);margin:24px 0}.result-header[data-v-3e8f9409]{display:flex;justify-content:space-between;align-items:center;margin-bottom:24px;flex-wrap:wrap;gap:8px}.result-title[data-v-3e8f9409]{margin:0;font-size:18px;color:#0ff;letter-spacing:2px}.result-status[data-v-3e8f9409]{display:flex;align-items:center;gap:8px;font-size:12px;color:#67c23a;letter-spacing:1px}.status-dot[data-v-3e8f9409]{width:8px;height:8px;background:#67c23a;border-radius:50%;animation:statusPulse-3e8f9409 2s ease-in-out infinite}@keyframes statusPulse-3e8f9409{0%,to{box-shadow:0 0 #67c23a66}50%{box-shadow:0 0 0 8px #67c23a00}}.key-stats[data-v-3e8f9409]{display:grid;grid-template-columns:repeat(3,1fr);gap:16px;margin-bottom:24px}.stat-item[data-v-3e8f9409]{background:#0000004d;border:1px solid rgba(255,255,255,.1);padding:16px;text-align:center;position:relative}.stat-item.primary[data-v-3e8f9409]{border-color:#0ff6;box-shadow:0 0 20px #00ffff1a}.stat-item.success[data-v-3e8f9409]{border-color:#67c23a66;box-shadow:0 0 20px #67c23a1a}.stat-item.warning[data-v-3e8f9409]{border-color:#e6a23c66;box-shadow:0 0 20px #e6a23c1a}.stat-label[data-v-3e8f9409]{font-size:12px;color:#64748b;margin-bottom:8px;text-transform:uppercase;letter-spacing:1px}.stat-value[data-v-3e8f9409]{font-size:24px;font-weight:800}.stat-item.primary .stat-value[data-v-3e8f9409]{color:#0ff}.stat-item.success .stat-value[data-v-3e8f9409]{color:#67c23a}.stat-item.warning .stat-value[data-v-3e8f9409]{color:#e6a23c}.stat-unit[data-v-3e8f9409]{font-size:14px;opacity:.7}.detail-title[data-v-3e8f9409]{margin:0 0 16px;font-size:14px;color:#8b5cf6;letter-spacing:2px}.detail-grid[data-v-3e8f9409]{display:grid;grid-template-columns:repeat(2,1fr);gap:12px}.detail-item[data-v-3e8f9409]{display:flex;justify-content:space-between;align-items:center;background:#0003;padding:12px 16px;border-left:3px solid #8b5cf6;gap:8px}.detail-label[data-v-3e8f9409]{font-size:13px;color:#94a3b8}.detail-value[data-v-3e8f9409]{font-size:16px;font-weight:700;color:#e0e7ff;text-align:right}.sci-fi-divider[data-v-3e8f9409]{border-color:#00ffff1a;margin:24px 0}.table-wrapper[data-v-3e8f9409]{width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch}.sci-fi-table[data-v-3e8f9409]{background:#0003;min-width:500px}.sci-fi-table[data-v-3e8f9409] .el-table__header-wrapper{background:#00ffff0d}.sci-fi-table[data-v-3e8f9409] .el-table th{background:transparent;color:#0ff;border-color:#00ffff1a}.sci-fi-table[data-v-3e8f9409] .el-table td{border-color:#ffffff0d}.sci-fi-table[data-v-3e8f9409] .el-table--striped .el-table__body tr.el-table__row--striped{background:#0000001a}.empty-state[data-v-3e8f9409]{text-align:center;padding:60px 20px;position:relative}.scan-line[data-v-3e8f9409]{position:absolute;top:0;left:0;right:0;height:2px;background:linear-gradient(90deg,transparent,rgba(0,255,255,.5),transparent);animation:scanMove-3e8f9409 3s linear infinite}@keyframes scanMove-3e8f9409{0%{top:0;opacity:0}10%{opacity:1}90%{opacity:1}to{top:100%;opacity:0}}.empty-icon[data-v-3e8f9409]{font-size:48px;margin-bottom:16px}.empty-text[data-v-3e8f9409]{font-size:16px;color:#64748b;margin:0 0 8px;letter-spacing:1px}.empty-text.error[data-v-3e8f9409]{color:#f87171}.empty-hint[data-v-3e8f9409]{font-size:13px;color:#475569;margin:0 0 24px;line-height:1.5}.sci-fi-reset-btn[data-v-3e8f9409]{background:#8b5cf633;border:1px solid #8b5cf6;color:#8b5cf6}.sci-fi-reset-btn[data-v-3e8f9409]:hover{background:#8b5cf64d;color:#a78bfa}.sci-fi-form[data-v-3e8f9409] .el-form-item__label{color:#94a3b8;font-weight:600;padding-bottom:6px;line-height:1.4}.sci-fi-select[data-v-3e8f9409] .el-input__wrapper{background:#0000004d;border:1px solid rgba(0,255,255,.2);box-shadow:none}.sci-fi-select[data-v-3e8f9409] .el-input__wrapper:hover{border-color:#0ff6}.sci-fi-select[data-v-3e8f9409] .el-input__wrapper.is-focus{border-color:#0ff;box-shadow:0 0 10px #0ff3}@media screen and (max-width: 600px){.rocket-calculator[data-v-3e8f9409]{padding:12px}.sci-fi-title[data-v-3e8f9409]{font-size:20px;letter-spacing:2px}.sci-fi-card[data-v-3e8f9409] .k-card__body{padding:16px}.key-stats[data-v-3e8f9409],.modules-grid[data-v-3e8f9409],.detail-grid[data-v-3e8f9409]{grid-template-columns:1fr}.distance-step-selector[data-v-3e8f9409]{grid-template-columns:repeat(3,1fr)}}.scrollbar[data-v-e3ac158b]{background:linear-gradient(135deg,#0a0e27,#1a1f3a,#0f172a);color:#e0e7ff}
1
+ .log-container[data-v-361e99da]{width:100%;height:100%;overflow-y:auto;padding:12px;font-family:monospace;background:#1e1e1e;color:#d4d4d4}.log-line[data-v-361e99da]{line-height:1.5;font-size:13px}pre[data-v-361e99da]{margin:0;font-family:inherit;white-space:pre-wrap;word-break:break-all}[data-v-3e8f9409]{box-sizing:border-box}.rocket-calculator[data-v-3e8f9409]{max-width:800px;margin:0 auto;padding:20px;box-sizing:border-box;position:relative;min-height:100vh;overflow-x:hidden}.sci-fi-bg[data-v-3e8f9409]{background:linear-gradient(135deg,#0a0e27,#1a1f3a,#0f172a);color:#e0e7ff}.grid-overlay[data-v-3e8f9409]{position:fixed;top:0;left:0;right:0;bottom:0;background-image:linear-gradient(rgba(0,255,255,.03) 1px,transparent 1px),linear-gradient(90deg,rgba(0,255,255,.03) 1px,transparent 1px);background-size:40px 40px;pointer-events:none;z-index:0}.sci-fi-card[data-v-3e8f9409]{background:#0f172af2;-webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px);border:1px solid rgba(0,255,255,.2);box-shadow:0 0 20px #00ffff1a,inset 0 0 20px #00000080;position:relative;overflow:visible;z-index:1}.sci-fi-card[data-v-3e8f9409] .k-card__body{padding:24px}.card-header-line[data-v-3e8f9409]{position:absolute;top:0;left:0;right:0;height:2px;background:linear-gradient(90deg,transparent,#00ffff,#8b5cf6,transparent);animation:lineGlow-3e8f9409 3s ease-in-out infinite;z-index:1}@keyframes lineGlow-3e8f9409{0%,to{opacity:.5}50%{opacity:1}}.header-card[data-v-3e8f9409]{margin-bottom:24px;text-align:center;position:relative;z-index:10;margin-top:8px}.header-glow[data-v-3e8f9409]{position:absolute;top:-50%;left:50%;transform:translate(-50%);width:200%;height:100%;background:radial-gradient(ellipse,rgba(139,92,246,.15) 0%,transparent 70%);pointer-events:none;z-index:-1}.sci-fi-title[data-v-3e8f9409]{margin:0 0 8px;font-size:28px;font-weight:800;letter-spacing:4px;color:#0ff;background:linear-gradient(90deg,#0ff,#8b5cf6,#0ff);background-size:200% auto;-webkit-background-clip:text;background-clip:text;-webkit-text-fill-color:transparent;animation:titleShine-3e8f9409 4s linear infinite;position:relative;z-index:2;text-shadow:0 0 30px rgba(0,255,255,.3);line-height:1.4}@keyframes titleShine-3e8f9409{0%{background-position:0% center}to{background-position:200% center}}.sci-fi-subtitle[data-v-3e8f9409]{margin:0;color:#64748b;font-size:13px;letter-spacing:2px;text-transform:uppercase;position:relative;z-index:2;line-height:1.5}.content-layout[data-v-3e8f9409]{display:flex;flex-direction:column;gap:24px;position:relative;z-index:1}.config-section[data-v-3e8f9409]{margin-bottom:20px;position:relative;z-index:1}.section-title[data-v-3e8f9409]{margin:0 0 20px;font-size:14px;color:#0ff;letter-spacing:2px;font-weight:600}.distance-control[data-v-3e8f9409]{width:100%}.distance-step-selector[data-v-3e8f9409]{display:grid;grid-template-columns:repeat(5,1fr);gap:8px;margin-bottom:16px}.step-btn[data-v-3e8f9409]{margin:0;background:#0000004d;border:1px solid rgba(0,255,255,.2);color:#94a3b8;padding:8px 4px;font-size:12px;font-weight:600;transition:all .2s ease;white-space:nowrap}.step-btn[data-v-3e8f9409]:hover{border-color:#00ffff80;color:#0ff;transform:translateY(-1px)}.step-btn.active[data-v-3e8f9409]{background:#00ffff26;border-color:#0ff;color:#0ff;box-shadow:0 0 15px #00ffff4d}.distance-input-wrapper[data-v-3e8f9409]{display:flex;align-items:center;justify-content:center;gap:8px;padding:12px;background:#0000004d;border:1px solid rgba(139,92,246,.3);border-radius:4px}.distance-label[data-v-3e8f9409]{color:#64748b;font-size:13px}.distance-value[data-v-3e8f9409]{font-size:20px;font-weight:800;color:#8b5cf6}.unit[data-v-3e8f9409]{color:#8b5cf6;font-weight:600;font-size:14px}.modules-grid[data-v-3e8f9409]{display:grid;grid-template-columns:1fr 1fr;gap:12px}.module-item[data-v-3e8f9409]{background:#00ffff0d;border:1px solid rgba(0,255,255,.1);padding:12px;border-radius:4px;transition:all .3s ease;display:flex;flex-direction:column;gap:8px}.module-item[data-v-3e8f9409]:hover{border-color:#00ffff4d;background:#00ffff14}.module-name[data-v-3e8f9409]{font-size:13px;color:#94a3b8}.module-input[data-v-3e8f9409]{width:100%}.module-input[data-v-3e8f9409] .el-input__wrapper{background:#0000004d;border:1px solid rgba(0,255,255,.2);box-shadow:none;padding:4px 6px}.module-input[data-v-3e8f9409] .el-input__inner{text-align:center;color:#0ff;font-weight:700;font-size:16px}.module-input[data-v-3e8f9409] .el-input-number__decrease,.module-input[data-v-3e8f9409] .el-input-number__increase{background:#0ff3;color:#0ff;border-color:#00ffff4d;font-weight:800;font-size:16px;transition:all .2s ease}.module-input[data-v-3e8f9409] .el-input-number__decrease:hover,.module-input[data-v-3e8f9409] .el-input-number__increase:hover{background:#0ff6;color:#fff}.module-input[data-v-3e8f9409] .el-input-number__decrease.is-disabled,.module-input[data-v-3e8f9409] .el-input-number__increase.is-disabled{background:#0003;color:#475569;border-color:#ffffff1a}.calculate-btn-wrapper[data-v-3e8f9409]{margin-top:24px;margin-bottom:0}.sci-fi-calculate-btn[data-v-3e8f9409]{width:100%;height:50px;background:linear-gradient(135deg,#0ff,#8b5cf6);border:none;color:#0a0e27;font-weight:800;font-size:16px;letter-spacing:2px;position:relative;overflow:hidden;transition:all .3s ease}.sci-fi-calculate-btn[data-v-3e8f9409]:hover{transform:translateY(-2px);box-shadow:0 10px 30px #00ffff4d}.btn-text[data-v-3e8f9409]{position:relative;z-index:1}.btn-glow[data-v-3e8f9409]{position:absolute;top:0;left:-100%;width:100%;height:100%;background:linear-gradient(90deg,transparent,rgba(255,255,255,.4),transparent);animation:btnScan-3e8f9409 2s ease-in-out infinite}@keyframes btnScan-3e8f9409{0%{left:-100%}to{left:100%}}.sci-fi-radio-group[data-v-3e8f9409]{width:100%;display:flex}.sci-fi-radio-group[data-v-3e8f9409] .el-radio-button{flex:1}.sci-fi-radio-group[data-v-3e8f9409] .el-radio-button__inner{width:100%;background:#0000004d;border:1px solid rgba(0,255,255,.2);color:#94a3b8;font-weight:600;padding:12px 10px;transition:all .2s ease}.sci-fi-radio-group[data-v-3e8f9409] .el-radio-button__inner:hover{color:#0ff;border-color:#0ff6}.sci-fi-radio-group[data-v-3e8f9409] .el-radio-button__orig-radio:checked+.el-radio-button__inner{background:#00ffff26;border-color:#0ff;color:#0ff;box-shadow:0 0 15px #0ff3}.oxidizer-hint[data-v-3e8f9409]{display:flex;justify-content:space-around;margin-top:8px}.hint-item[data-v-3e8f9409]{font-size:12px;color:#64748b;transition:all .2s ease}.hint-item.active[data-v-3e8f9409]{color:#0ff;font-weight:600}.divider-line[data-v-3e8f9409]{height:1px;background:linear-gradient(90deg,transparent,rgba(0,255,255,.3),transparent);margin:24px 0}.result-header[data-v-3e8f9409]{display:flex;justify-content:space-between;align-items:center;margin-bottom:24px;flex-wrap:wrap;gap:8px}.result-title[data-v-3e8f9409]{margin:0;font-size:18px;color:#0ff;letter-spacing:2px}.result-status[data-v-3e8f9409]{display:flex;align-items:center;gap:8px;font-size:12px;color:#67c23a;letter-spacing:1px}.status-dot[data-v-3e8f9409]{width:8px;height:8px;background:#67c23a;border-radius:50%;animation:statusPulse-3e8f9409 2s ease-in-out infinite}@keyframes statusPulse-3e8f9409{0%,to{box-shadow:0 0 #67c23a66}50%{box-shadow:0 0 0 8px #67c23a00}}.key-stats[data-v-3e8f9409]{display:grid;grid-template-columns:repeat(3,1fr);gap:16px;margin-bottom:24px}.stat-item[data-v-3e8f9409]{background:#0000004d;border:1px solid rgba(255,255,255,.1);padding:16px;text-align:center;position:relative}.stat-item.primary[data-v-3e8f9409]{border-color:#0ff6;box-shadow:0 0 20px #00ffff1a}.stat-item.success[data-v-3e8f9409]{border-color:#67c23a66;box-shadow:0 0 20px #67c23a1a}.stat-item.warning[data-v-3e8f9409]{border-color:#e6a23c66;box-shadow:0 0 20px #e6a23c1a}.stat-label[data-v-3e8f9409]{font-size:12px;color:#64748b;margin-bottom:8px;text-transform:uppercase;letter-spacing:1px}.stat-value[data-v-3e8f9409]{font-size:24px;font-weight:800}.stat-item.primary .stat-value[data-v-3e8f9409]{color:#0ff}.stat-item.success .stat-value[data-v-3e8f9409]{color:#67c23a}.stat-item.warning .stat-value[data-v-3e8f9409]{color:#e6a23c}.stat-unit[data-v-3e8f9409]{font-size:14px;opacity:.7}.detail-title[data-v-3e8f9409]{margin:0 0 16px;font-size:14px;color:#8b5cf6;letter-spacing:2px}.detail-grid[data-v-3e8f9409]{display:grid;grid-template-columns:repeat(2,1fr);gap:12px}.detail-item[data-v-3e8f9409]{display:flex;justify-content:space-between;align-items:center;background:#0003;padding:12px 16px;border-left:3px solid #8b5cf6;gap:8px}.detail-label[data-v-3e8f9409]{font-size:13px;color:#94a3b8}.detail-value[data-v-3e8f9409]{font-size:16px;font-weight:700;color:#e0e7ff;text-align:right}.sci-fi-divider[data-v-3e8f9409]{border-color:#00ffff1a;margin:24px 0}.table-wrapper[data-v-3e8f9409]{width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch}.sci-fi-table[data-v-3e8f9409]{background:#0003;min-width:500px}.sci-fi-table[data-v-3e8f9409] .el-table__header-wrapper{background:#00ffff0d}.sci-fi-table[data-v-3e8f9409] .el-table th{background:transparent;color:#0ff;border-color:#00ffff1a}.sci-fi-table[data-v-3e8f9409] .el-table td{border-color:#ffffff0d}.sci-fi-table[data-v-3e8f9409] .el-table--striped .el-table__body tr.el-table__row--striped{background:#0000001a}.empty-state[data-v-3e8f9409]{text-align:center;padding:60px 20px;position:relative}.scan-line[data-v-3e8f9409]{position:absolute;top:0;left:0;right:0;height:2px;background:linear-gradient(90deg,transparent,rgba(0,255,255,.5),transparent);animation:scanMove-3e8f9409 3s linear infinite}@keyframes scanMove-3e8f9409{0%{top:0;opacity:0}10%{opacity:1}90%{opacity:1}to{top:100%;opacity:0}}.empty-icon[data-v-3e8f9409]{font-size:48px;margin-bottom:16px}.empty-text[data-v-3e8f9409]{font-size:16px;color:#64748b;margin:0 0 8px;letter-spacing:1px}.empty-text.error[data-v-3e8f9409]{color:#f87171}.empty-hint[data-v-3e8f9409]{font-size:13px;color:#475569;margin:0 0 24px;line-height:1.5}.sci-fi-reset-btn[data-v-3e8f9409]{background:#8b5cf633;border:1px solid #8b5cf6;color:#8b5cf6}.sci-fi-reset-btn[data-v-3e8f9409]:hover{background:#8b5cf64d;color:#a78bfa}.sci-fi-form[data-v-3e8f9409] .el-form-item__label{color:#94a3b8;font-weight:600;padding-bottom:6px;line-height:1.4}.sci-fi-select[data-v-3e8f9409] .el-input__wrapper{background:#0000004d;border:1px solid rgba(0,255,255,.2);box-shadow:none}.sci-fi-select[data-v-3e8f9409] .el-input__wrapper:hover{border-color:#0ff6}.sci-fi-select[data-v-3e8f9409] .el-input__wrapper.is-focus{border-color:#0ff;box-shadow:0 0 10px #0ff3}@media screen and (max-width: 600px){.rocket-calculator[data-v-3e8f9409]{padding:12px}.sci-fi-title[data-v-3e8f9409]{font-size:20px;letter-spacing:2px}.sci-fi-card[data-v-3e8f9409] .k-card__body{padding:16px}.key-stats[data-v-3e8f9409],.modules-grid[data-v-3e8f9409],.detail-grid[data-v-3e8f9409]{grid-template-columns:1fr}.distance-step-selector[data-v-3e8f9409]{grid-template-columns:repeat(3,1fr)}}.scrollbar[data-v-e3ac158b]{background:linear-gradient(135deg,#0a0e27,#1a1f3a,#0f172a);color:#e0e7ff}.page-container[data-v-f5f301cb]{font-family:PingFang SC,Microsoft YaHei,-apple-system,BlinkMacSystemFont,sans-serif;background-color:#e8f4f8;background-image:radial-gradient(#d0e2e9 10%,transparent 11%),radial-gradient(#d0e2e9 10%,transparent 11%);background-size:30px 30px;background-position:0 0,15px 15px;min-height:100vh;padding:30px 20px;box-sizing:border-box}.page-title[data-v-f5f301cb]{text-align:center;font-size:42px;font-weight:800;color:#333;margin:0 0 20px;letter-spacing:2px;text-shadow:2px 2px 0 #ffffff}.search-bar[data-v-f5f301cb]{max-width:1000px;margin:0 auto 30px}.search-input[data-v-f5f301cb]{width:100%;box-sizing:border-box;padding:18px 22px;font-size:18px;border:3px solid #333333;border-radius:16px;background:#fff;box-shadow:4px 4px #333;outline:none;transition:all .2s ease}.search-input[data-v-f5f301cb]:focus{transform:translate(2px,2px);box-shadow:2px 2px #333}.search-input[data-v-f5f301cb]::placeholder{color:#999}.content-wrap[data-v-f5f301cb]{display:flex;gap:20px;max-width:1100px;margin:0 auto;align-items:flex-start}.main-card[data-v-f5f301cb]{flex:1;min-width:0;background:#fff;border:3px solid #333333;border-radius:18px;box-shadow:6px 6px #333;overflow:hidden}.card-header[data-v-f5f301cb]{background:#8dd7d0;padding:14px 24px;border-bottom:3px solid #333333}.header-count[data-v-f5f301cb]{font-size:16px;color:#333;font-weight:500}.header-count strong[data-v-f5f301cb]{font-size:20px;color:#c0392b}.list-wrap[data-v-f5f301cb]{padding:24px;min-height:300px}.empty-state[data-v-f5f301cb]{text-align:center;padding:60px 20px;color:#666;font-size:16px}.todo-item[data-v-f5f301cb]{border:3px solid #333333;border-radius:16px;padding:18px 22px;margin-bottom:16px;box-shadow:4px 4px #333;display:flex;justify-content:space-between;align-items:center;gap:20px;transition:all .2s ease}.todo-item[data-v-f5f301cb]:last-child{margin-bottom:0}.todo-item[data-v-f5f301cb]:hover{transform:translate(2px,2px);box-shadow:2px 2px #333}.item-unsynced[data-v-f5f301cb]{background:#f8f3e6}.item-synced[data-v-f5f301cb]{background:#d4f1f0;opacity:.9}.item-content[data-v-f5f301cb]{flex:1;min-width:0}.item-title[data-v-f5f301cb]{display:block;font-size:17px;font-weight:600;color:#333;text-decoration:none;margin-bottom:8px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.item-title[data-v-f5f301cb]:hover{color:#569edf;text-decoration:underline}.item-meta[data-v-f5f301cb]{display:flex;gap:16px;flex-wrap:wrap}.meta-tag[data-v-f5f301cb]{font-size:13px;color:#666}.meta-tag.stale[data-v-f5f301cb]{color:#e07a5f;font-weight:500}.item-actions[data-v-f5f301cb]{display:flex;align-items:center;gap:12px;flex-shrink:0}.status-badge[data-v-f5f301cb]{padding:6px 12px;border-radius:10px;border:2px solid #333;font-size:13px;font-weight:600;box-shadow:2px 2px #333}.status-on[data-v-f5f301cb]{background:#d4edda;color:#155724}.status-off[data-v-f5f301cb]{background:#f8d7da;color:#721c24}button[data-v-f5f301cb]{cursor:pointer;border-radius:10px;border:2px solid #333333;font-weight:600;transition:all .2s ease;box-shadow:2px 2px #333}button[data-v-f5f301cb]:hover:not(:disabled){transform:translate(1px,1px);box-shadow:1px 1px #333}button[data-v-f5f301cb]:disabled{opacity:.6;cursor:not-allowed;background:#e0e0e0;color:#999}.btn-mark-sync[data-v-f5f301cb]{padding:7px 14px;font-size:14px;background:#b5e48c;color:#2d5016}.btn-mark-sync[data-v-f5f301cb]:hover:not(:disabled){background:#90d26d}.card-footer[data-v-f5f301cb]{background:#fff;padding:16px 24px;border-top:3px solid #333333;display:flex;justify-content:center;align-items:center}.pagination-group[data-v-f5f301cb]{display:flex;align-items:center;gap:12px}.btn-page[data-v-f5f301cb]{padding:6px 12px;font-size:14px;background:#ffd6e0;color:#333}.page-text[data-v-f5f301cb]{font-size:14px;color:#666}.page-size-select[data-v-f5f301cb]{padding:6px 8px;border:2px solid #333;border-radius:8px;background:#fff;font-weight:500;box-shadow:2px 2px #333;outline:none}.sidebar-card[data-v-f5f301cb]{width:180px;flex-shrink:0;background:#fff;border:3px solid #333333;border-radius:16px;box-shadow:6px 6px #333;overflow:hidden;position:sticky;top:20px}.sidebar-header[data-v-f5f301cb]{background:#8dd7d0;padding:12px;text-align:center;font-size:18px;font-weight:700;color:#333;border-bottom:3px solid #333}.sidebar-menu[data-v-f5f301cb]{display:flex;flex-direction:column}.menu-item[data-v-f5f301cb]{padding:12px 16px;background:#fff;border:none;border-radius:0;box-shadow:none;border-bottom:2px solid #f0f0f0;font-size:15px;transition:all .2s}.menu-item[data-v-f5f301cb]:last-child{border-bottom:none}.menu-item[data-v-f5f301cb]:hover{background:#f0f8ff;transform:none;box-shadow:none}.menu-item.active[data-v-f5f301cb]{background:#8dd7d0;color:#333;font-weight:700}.toast[data-v-f5f301cb]{position:fixed;top:30px;left:50%;transform:translate(-50%);padding:14px 24px;border-radius:12px;border:3px solid #333;box-shadow:4px 4px #333;color:#333;font-weight:600;font-size:15px;z-index:9999;animation:toastDown-f5f301cb .3s ease-out}.toast.success[data-v-f5f301cb]{background:#d4edda}.toast.error[data-v-f5f301cb]{background:#f8d7da}@keyframes toastDown-f5f301cb{0%{transform:translate(-50%,-20px);opacity:0}to{transform:translate(-50%);opacity:1}}
package/lib/index.d.ts CHANGED
@@ -1,7 +1,22 @@
1
1
  import { Context, Schema } from "koishi";
2
+ import { Mwn } from "mwn";
2
3
  export declare const name = "oni-sync-bot";
3
4
  export declare const inject: string[];
4
5
  export interface Config {
6
+ ggUsername: string;
7
+ ggPassword: string;
8
+ bwikiusername: string;
9
+ bwikipassword: string;
10
+ domain: string;
11
+ logsUrl: string;
12
+ }
13
+ declare module "koishi" {
14
+ interface Context {
15
+ wikibot: {
16
+ wikigg: Mwn;
17
+ bwiki: Mwn;
18
+ };
19
+ }
5
20
  }
6
21
  export declare const Config: Schema<Config>;
7
22
  export declare function apply(ctx: Context, config: Config): void;
package/lib/index.js CHANGED
@@ -30,17 +30,16 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
30
30
  // src/index.ts
31
31
  var src_exports = {};
32
32
  __export(src_exports, {
33
- Config: () => Config6,
34
- apply: () => apply5,
33
+ Config: () => Config8,
34
+ apply: () => apply7,
35
35
  inject: () => inject,
36
36
  name: () => name
37
37
  });
38
38
  module.exports = __toCommonJS(src_exports);
39
- var import_koishi10 = require("koishi");
40
- var import_path = require("path");
39
+ var import_koishi11 = require("koishi");
40
+ var import_path2 = require("path");
41
41
 
42
42
  // src/wiki/wikicore.ts
43
- var import_koishi2 = require("koishi");
44
43
  var import_mwn = require("mwn");
45
44
 
46
45
  // src/utils/tools.ts
@@ -91,27 +90,6 @@ __name(generatePinyinInfo, "generatePinyinInfo");
91
90
  var logger = new import_koishi.Logger("oni-sync");
92
91
 
93
92
  // src/wiki/wikicore.ts
94
- var Config = import_koishi2.Schema.object({
95
- ggUsername: import_koishi2.Schema.string().description("WIKIGG 用户名").default("1"),
96
- ggPassword: import_koishi2.Schema.string().description("WIKIGG 密码").default("1"),
97
- bwikiusername: import_koishi2.Schema.string().description("bwiki用户名").default("1"),
98
- bwikipassword: import_koishi2.Schema.string().description("bwiki密码").default("1"),
99
- domain: import_koishi2.Schema.string().description("你的短链域名(必填,如:klei.vip)").default("klei.vip"),
100
- logsUrl: import_koishi2.Schema.string().description("日志查看地址").default("https://klei.vip/onilogs")
101
- });
102
- function apply(ctx, config) {
103
- const sitesConfig = getSitesConfig(config);
104
- ctx.on("ready", async () => {
105
- const wikiggBot = await login(sitesConfig.gg);
106
- const bwikiBot = await login(sitesConfig.bwiki);
107
- ctx.wikibot = { wikigg: wikiggBot, bwiki: bwikiBot };
108
- });
109
- ctx.on("dispose", () => {
110
- logger.warn("⚠️ 插件已卸载,ctx.wikibot清除...");
111
- ctx.wikibot = void 0;
112
- });
113
- }
114
- __name(apply, "apply");
115
93
  async function login(siteConfig) {
116
94
  const bot = new import_mwn.Mwn({
117
95
  apiUrl: siteConfig.api,
@@ -161,9 +139,9 @@ __name(getSitesConfig, "getSitesConfig");
161
139
 
162
140
  // src/service/logspush.ts
163
141
  var import_plugin_console = require("@koishijs/plugin-console");
164
- var import_koishi3 = require("koishi");
165
- var Config2 = import_koishi3.Schema.object({
166
- logsUrl: import_koishi3.Schema.string().description("日志查看地址").default("https://klei.vip/onilogs")
142
+ var import_koishi2 = require("koishi");
143
+ var Config = import_koishi2.Schema.object({
144
+ logsUrl: import_koishi2.Schema.string().description("日志查看地址").default("https://klei.vip/onilogs")
167
145
  });
168
146
  var logBuffer = [];
169
147
  var PublicLogProvider = class extends import_plugin_console.DataService {
@@ -177,7 +155,7 @@ var PublicLogProvider = class extends import_plugin_console.DataService {
177
155
  return logBuffer;
178
156
  }
179
157
  };
180
- function apply2(ctx, config) {
158
+ function apply(ctx, config) {
181
159
  ctx.plugin(PublicLogProvider);
182
160
  const target = {
183
161
  colors: 0,
@@ -190,21 +168,21 @@ function apply2(ctx, config) {
190
168
  ctx.get("console")?.patch("onilogs", logBuffer);
191
169
  }, "record")
192
170
  };
193
- import_koishi3.Logger.targets.push(target);
171
+ import_koishi2.Logger.targets.push(target);
194
172
  ctx.on("dispose", () => {
195
- const index = import_koishi3.Logger.targets.indexOf(target);
196
- if (index > -1) import_koishi3.Logger.targets.splice(index, 1);
173
+ const index = import_koishi2.Logger.targets.indexOf(target);
174
+ if (index > -1) import_koishi2.Logger.targets.splice(index, 1);
197
175
  });
198
176
  }
199
- __name(apply2, "apply");
177
+ __name(apply, "apply");
200
178
 
201
179
  // src/service/router.ts
202
- var import_koishi4 = require("koishi");
203
- var Config3 = import_koishi4.Schema.object({
204
- main_site: import_koishi4.Schema.string().description("主站域名(必填,如:oxygennotincluded.wiki.gg)").default("oxygennotincluded.wiki.gg/zh"),
205
- bwiki_site: import_koishi4.Schema.string().description("镜像站域名(必填,如:wiki.biligame.com)").default("wiki.biligame.com/oni")
180
+ var import_koishi3 = require("koishi");
181
+ var Config2 = import_koishi3.Schema.object({
182
+ main_site: import_koishi3.Schema.string().description("主站域名(必填,如:oxygennotincluded.wiki.gg)").default("oxygennotincluded.wiki.gg/zh"),
183
+ bwiki_site: import_koishi3.Schema.string().description("镜像站域名(必填,如:wiki.biligame.com)").default("wiki.biligame.com/oni")
206
184
  });
207
- function apply3(ctx, config) {
185
+ function apply2(ctx, config) {
208
186
  ctx.server.get("/gg/:id", async (router) => {
209
187
  const pageId = Number(router.params.id);
210
188
  if (isNaN(pageId)) return router.body = "❌ 无效的页面ID,必须为数字!";
@@ -228,16 +206,19 @@ function apply3(ctx, config) {
228
206
  router.redirect(targetUrl);
229
207
  });
230
208
  }
231
- __name(apply3, "apply");
209
+ __name(apply2, "apply");
232
210
 
233
- // src/task/sync.ts
234
- var import_koishi8 = require("koishi");
211
+ // src/task/index.ts
212
+ var import_koishi9 = require("koishi");
235
213
 
236
- // src/sync/pageSync.ts
214
+ // src/task/pages.ts
237
215
  var import_koishi6 = require("koishi");
238
216
 
239
- // src/sync/imgSync.ts
217
+ // src/synclib/pageSync.ts
240
218
  var import_koishi5 = require("koishi");
219
+
220
+ // src/synclib/imgSync.ts
221
+ var import_koishi4 = require("koishi");
241
222
  var import_node_fetch = __toESM(require("node-fetch"));
242
223
  var import_form_data = __toESM(require("form-data"));
243
224
  var CONFIG = {
@@ -391,13 +372,13 @@ async function syncAllImages(sourceBot, targetBot) {
391
372
  if (!result.success) {
392
373
  failCount++;
393
374
  failedImages.push(fileName);
394
- await (0, import_koishi5.sleep)(CONFIG.SYNC_INTERVAL_FAILED);
375
+ await (0, import_koishi4.sleep)(CONFIG.SYNC_INTERVAL_FAILED);
395
376
  } else {
396
377
  successCount++;
397
378
  if (result.reason === "ignored" || result.reason === "no_change") {
398
379
  skipCount++;
399
380
  }
400
- await (0, import_koishi5.sleep)(CONFIG.SYNC_INTERVAL_SUCCESS);
381
+ await (0, import_koishi4.sleep)(CONFIG.SYNC_INTERVAL_SUCCESS);
401
382
  }
402
383
  }
403
384
  if (failedImages.length > 0) {
@@ -418,7 +399,7 @@ async function syncAllImages(sourceBot, targetBot) {
418
399
  stillFailed.push(fileName);
419
400
  logger.info(`[SyncAllImg] ❌ 重试失败: ${fileName}`);
420
401
  }
421
- await (0, import_koishi5.sleep)(CONFIG.SYNC_INTERVAL_SUCCESS);
402
+ await (0, import_koishi4.sleep)(CONFIG.SYNC_INTERVAL_SUCCESS);
422
403
  }
423
404
  if (stillFailed.length > 0) {
424
405
  logger.info(`
@@ -443,7 +424,7 @@ async function syncAllImages(sourceBot, targetBot) {
443
424
  }
444
425
  __name(syncAllImages, "syncAllImages");
445
426
 
446
- // src/sync/pageSync.ts
427
+ // src/synclib/pageSync.ts
447
428
  var CONFIG2 = {
448
429
  IGNORED_PAGES: /* @__PURE__ */ new Set(["教程", "MediaWiki:Common.css"]),
449
430
  SYNC_INTERVAL_SUCCESS: 500,
@@ -505,13 +486,13 @@ async function processPageWithStats(oldSite, newSite, pageTitle, user, stats, fa
505
486
  if (!syncResult.success) {
506
487
  stats.failCount++;
507
488
  failedPages.push(pageTitle);
508
- await (0, import_koishi6.sleep)(CONFIG2.SYNC_INTERVAL_FAILED);
489
+ await (0, import_koishi5.sleep)(CONFIG2.SYNC_INTERVAL_FAILED);
509
490
  } else {
510
491
  stats.successCount++;
511
492
  if (syncResult.reason === "ignored" || syncResult.reason === "no_change") {
512
493
  stats.skipCount++;
513
494
  }
514
- await (0, import_koishi6.sleep)(CONFIG2.SYNC_INTERVAL_SUCCESS);
495
+ await (0, import_koishi5.sleep)(CONFIG2.SYNC_INTERVAL_SUCCESS);
515
496
  }
516
497
  }
517
498
  __name(processPageWithStats, "processPageWithStats");
@@ -587,11 +568,11 @@ async function syncPages(oldSite, newSite) {
587
568
  stats.skipCount++;
588
569
  }
589
570
  logger.info(`[SyncAllPages] ✅ 页面 ${pageTitle} 重试成功`);
590
- await (0, import_koishi6.sleep)(CONFIG2.SYNC_INTERVAL_SUCCESS);
571
+ await (0, import_koishi5.sleep)(CONFIG2.SYNC_INTERVAL_SUCCESS);
591
572
  } else {
592
573
  stillFailed.push(pageTitle);
593
574
  logger.info(`[SyncAllPages] ❌ 页面 ${pageTitle} 再次失败`);
594
- await (0, import_koishi6.sleep)(CONFIG2.SYNC_INTERVAL_FAILED);
575
+ await (0, import_koishi5.sleep)(CONFIG2.SYNC_INTERVAL_FAILED);
595
576
  }
596
577
  }
597
578
  }
@@ -660,11 +641,11 @@ async function incrementalUpdate(oldSite, newSite) {
660
641
  CONFIG2.INCREMENTAL_USER
661
642
  );
662
643
  }
663
- await (0, import_koishi6.sleep)(CONFIG2.SYNC_INTERVAL_SUCCESS);
644
+ await (0, import_koishi5.sleep)(CONFIG2.SYNC_INTERVAL_SUCCESS);
664
645
  } catch (error) {
665
646
  const errMsg = error instanceof Error ? error.message : String(error);
666
647
  logger.error(`[增量更新流程] ❌ 处理 ${title} 时出错:`, errMsg);
667
- await (0, import_koishi6.sleep)(CONFIG2.SYNC_INTERVAL_FAILED);
648
+ await (0, import_koishi5.sleep)(CONFIG2.SYNC_INTERVAL_FAILED);
668
649
  }
669
650
  }
670
651
  }
@@ -678,178 +659,12 @@ async function incrementalUpdate(oldSite, newSite) {
678
659
  }
679
660
  __name(incrementalUpdate, "incrementalUpdate");
680
661
 
681
- // src/sync/moduleSync.ts
682
- var import_koishi7 = require("koishi");
683
- var CONFIG3 = {
684
- MODLE_NAMESPACE: 828,
685
- // 模块命名空间 (注意:这里原代码拼写为 MODLE,保留原样)
686
- IGNORED_MODULES: [],
687
- // 忽略的模块列表
688
- SYNC_INTERVAL_SUCCESS: 500,
689
- // 同步成功后等待时间(毫秒)
690
- SYNC_INTERVAL_FAILED: 1e3
691
- // 同步失败后等待时间(毫秒)
692
- };
693
- async function syncSingleModule(oldSite, newSite, moduleTitle, user) {
694
- if (CONFIG3.IGNORED_MODULES.includes(moduleTitle)) {
695
- logger.info(`[SyncModule] 🚫 模块 ${moduleTitle} 在忽略列表中,跳过`);
696
- return { success: true, reason: "ignored" };
697
- }
698
- try {
699
- logger.info(`[SyncModule] 🔍 开始获取模块 ${moduleTitle} 的内容`);
700
- let targetTitle = moduleTitle;
701
- if (/^Dev:/i.test(moduleTitle)) {
702
- const subPageName = moduleTitle.replace(/^Dev:/i, "");
703
- targetTitle = `Module:Dev/${subPageName}`;
704
- logger.info(
705
- `[SyncModule] 🔀 检测到 Dev 命名空间,路径映射: ${moduleTitle} -> ${targetTitle}`
706
- );
707
- }
708
- const [oldContent, newContent] = await Promise.all([
709
- getAndProcessPageContent(oldSite, moduleTitle),
710
- getAndProcessPageContent(newSite, targetTitle)
711
- ]);
712
- if (oldContent === newContent) {
713
- logger.info(`[SyncModule] 🟡 模块 ${moduleTitle} 内容未改变,跳过`);
714
- return { success: true, reason: "no_change" };
715
- }
716
- await newSite.save(
717
- targetTitle,
718
- oldContent,
719
- `由:${user || "同步坤器人手动"} 触发更改,此时同步`
720
- );
721
- logger.info(`[SyncModule] ✅ 模块 ${moduleTitle} 同步成功`);
722
- return { success: true, reason: "synced" };
723
- } catch (error) {
724
- const errMsg = error.message || String(error);
725
- logger.error(`[SyncModule] ❌ 模块 ${moduleTitle} 同步失败:`, errMsg);
726
- return { success: false, reason: errMsg };
727
- }
728
- }
729
- __name(syncSingleModule, "syncSingleModule");
730
- async function getAllModules(site) {
731
- logger.info(
732
- `[SyncAllModules] 📥 开始获取原站点所有模块(命名空间${CONFIG3.MODLE_NAMESPACE})`
733
- );
734
- const allModules = [];
735
- const queryGen = site.continuedQueryGen({
736
- action: "query",
737
- list: "allpages",
738
- apnamespace: CONFIG3.MODLE_NAMESPACE,
739
- // 模块命名空间
740
- aplimit: "max",
741
- apdir: "ascending"
742
- });
743
- for await (const res of queryGen) {
744
- const moduleTitles = res.query?.allpages?.map((page) => page.title) || [];
745
- allModules.push(...moduleTitles);
746
- logger.info(`[SyncAllModules] 📄 已获取 ${allModules.length} 个模块`);
747
- }
748
- logger.info(
749
- `[SyncAllModules] 📊 原站点总计获取到 ${allModules.length} 个模块`
750
- );
751
- return allModules;
752
- }
753
- __name(getAllModules, "getAllModules");
754
- async function syncModules(oldSite, newSite) {
755
- try {
756
- const oldModuleList = await getAllModules(oldSite);
757
- const total = oldModuleList.length;
758
- console.log(oldModuleList);
759
- if (total === 0) {
760
- logger.info(`[SyncAllModules] 📭 原站点无模块可同步,结束`);
761
- return;
762
- }
763
- let successCount = 0;
764
- let failCount = 0;
765
- let skipCount = 0;
766
- const failedModules = [];
767
- logger.info(`[SyncAllModules] 🚦 开始批量同步,总计 ${total} 个模块`);
768
- for (let index = 0; index < total; index++) {
769
- const moduleTitle = oldModuleList[index];
770
- const current = index + 1;
771
- const remaining = total - current;
772
- const progress = (current / total * 100).toFixed(1);
773
- logger.info(
774
- `
775
- [SyncAllModules] 📈 进度 [${current}/${total}] (${progress}%) - 处理 ${moduleTitle} | 剩余 ${remaining} 个`
776
- );
777
- const syncResult = await syncSingleModule(
778
- oldSite,
779
- newSite,
780
- moduleTitle,
781
- "同步坤器人"
782
- );
783
- if (!syncResult.success) {
784
- failCount++;
785
- failedModules.push(moduleTitle);
786
- await (0, import_koishi7.sleep)(CONFIG3.SYNC_INTERVAL_FAILED);
787
- } else {
788
- successCount++;
789
- if (syncResult.reason === "ignored" || syncResult.reason === "no_change") {
790
- skipCount++;
791
- }
792
- await (0, import_koishi7.sleep)(CONFIG3.SYNC_INTERVAL_SUCCESS);
793
- }
794
- }
795
- if (failedModules.length > 0) {
796
- logger.info(
797
- `
798
- [SyncAllModules] 🔄 ===== 开始重试 ${failedModules.length} 个失败模块 =====`
799
- );
800
- const stillFailed = [];
801
- for (const moduleTitle of failedModules) {
802
- logger.info(`
803
- [SyncAllModules] 🔁 重试中: ${moduleTitle}`);
804
- const syncResult = await syncSingleModule(
805
- oldSite,
806
- newSite,
807
- moduleTitle,
808
- "同步坤器人"
809
- );
810
- if (syncResult.success) {
811
- successCount++;
812
- failCount--;
813
- if (syncResult.reason === "ignored" || syncResult.reason === "no_change") {
814
- skipCount++;
815
- }
816
- logger.info(`[SyncAllModules] ✅ 模块 ${moduleTitle} 重试成功`);
817
- await (0, import_koishi7.sleep)(CONFIG3.SYNC_INTERVAL_SUCCESS);
818
- } else {
819
- stillFailed.push(moduleTitle);
820
- logger.info(`[SyncAllModules] ❌ 模块 ${moduleTitle} 再次失败`);
821
- await (0, import_koishi7.sleep)(CONFIG3.SYNC_INTERVAL_FAILED);
822
- }
823
- }
824
- logger.info(`
825
- [SyncAllModules] 📋 ===== 最终同步报告 =====`);
826
- if (stillFailed.length > 0) {
827
- logger.info(`❌ 以下模块经过重试仍然失败,请手动检查:`);
828
- stillFailed.forEach((title, idx) => {
829
- logger.info(` ${idx + 1}. ${title}`);
830
- });
831
- } else {
832
- logger.info(`🎉 所有模块同步成功(含重试)!`);
833
- }
834
- }
835
- logger.info(`
836
- [SyncAllModules] 🎯 同步完成!`);
837
- logger.info(`├─ 总计:${total} 个模块`);
838
- logger.info(`├─ 成功:${successCount} 个(含跳过 ${skipCount} 个)`);
839
- logger.info(`└─ 失败:${failCount} 个`);
840
- } catch (error) {
841
- logger.error(`[SyncAllModules] 💥 批量同步流程异常终止:`, error);
842
- throw error;
843
- }
844
- }
845
- __name(syncModules, "syncModules");
846
-
847
- // src/task/sync.ts
848
- var Config4 = import_koishi8.Schema.object({
849
- logsUrl: import_koishi8.Schema.string().description("日志查看地址").default("https://klei.vip/onilogs")
662
+ // src/task/pages.ts
663
+ var Config3 = import_koishi6.Schema.object({
664
+ logsUrl: import_koishi6.Schema.string().description("日志查看地址").default("https://klei.vip/onilogs")
850
665
  });
851
- function apply4(ctx, config) {
852
- const log = ctx.logger("sync-task");
666
+ function apply3(ctx, config) {
667
+ const log = ctx.logger("sync-task-page");
853
668
  ctx.on("ready", async () => {
854
669
  logger.info("定时同步任务已准备就绪");
855
670
  ctx.cron("15 * * * *", async () => {
@@ -863,14 +678,6 @@ function apply4(ctx, config) {
863
678
  ctx.logger.error(`,错误信息:${err}`);
864
679
  });
865
680
  });
866
- ctx.cron("30 8 * * 3", async () => {
867
- await syncAllImages(ctx.wikibot.wikigg, ctx.wikibot.bwiki).then(() => {
868
- logger.info("自动任务:尝试同步所有图片,从 WIKIGG 到 bwiki");
869
- }).catch((err) => {
870
- logger.error(`同步所有图片失败`);
871
- ctx.logger.error(`,错误信息:${err}`);
872
- });
873
- });
874
681
  });
875
682
  ctx.command("sync.incrementalUpdate", "获取3h内的编辑并尝试更新", {
876
683
  authority: 2
@@ -904,91 +711,366 @@ function apply4(ctx, config) {
904
711
  log.error(`同步所有页面失败,错误信息:${err}`);
905
712
  });
906
713
  });
907
- ctx.command("sync.module <moduleTitle:string>", "同步指定模块", {
908
- authority: 2
909
- }).action(async ({ session }, moduleTitle) => {
910
- await session.send(`✅ 同步中,请前往控制台查看:${config.logsUrl}`);
911
- await syncSingleModule(
714
+ ctx.command("sync <pageTitle:string>", "同步指定页面", { authority: 2 }).action(async ({ session }, pageTitle) => {
715
+ await syncSinglePage(
912
716
  ctx.wikibot.wikigg,
913
717
  ctx.wikibot.bwiki,
914
- moduleTitle,
718
+ pageTitle,
915
719
  "sync-bot"
916
720
  ).then(() => {
917
721
  session.send(
918
- `✅ 已尝试同步模块:${moduleTitle},请前往控制台查看:${config.logsUrl}`
722
+ `✅ 已尝试同步页面:${pageTitle},请前往控制台查看:${config.logsUrl}`
919
723
  );
920
724
  }).catch((err) => {
921
- session.send(`❌ 同步模块失败:${moduleTitle}`);
922
- log.error(`错误信息:${err}`);
725
+ session.send(`❌ 同步页面失败:${pageTitle}`);
726
+ log.error(`,错误信息:${err}`);
923
727
  });
924
728
  });
925
- ctx.command("sync.allmodules", "同步所有模块", { authority: 2 }).action(async ({ session }) => {
926
- await session.send(
927
- `🚀 开始同步所有模块,任务耗时较长,请前往控制台查看:${config.logsUrl}`
928
- );
929
- await syncModules(ctx.wikibot.wikigg, ctx.wikibot.bwiki).then(() => {
930
- session.send(
931
- `✅ 已尝试同步所有模块,请前往控制台查看:${config.logsUrl}`
729
+ }
730
+ __name(apply3, "apply");
731
+
732
+ // src/task/imgs.ts
733
+ var import_koishi7 = require("koishi");
734
+ var Config4 = import_koishi7.Schema.object({
735
+ logsUrl: import_koishi7.Schema.string().description("日志查看地址").default("https://klei.vip/onilogs")
736
+ });
737
+ function apply4(ctx, config) {
738
+ ctx.on("ready", async () => {
739
+ ctx.cron("30 8 * * 3", async () => {
740
+ await syncAllImages(ctx.wikibot.wikigg, ctx.wikibot.bwiki).then(() => {
741
+ logger.info("自动任务:尝试同步所有图片,从 WIKIGG 到 bwiki");
742
+ }).catch((err) => {
743
+ logger.error(`同步所有图片失败`);
744
+ ctx.logger.error(`,错误信息:${err}`);
745
+ });
746
+ });
747
+ ctx.command("sync.img <imgTitle:string>", "同步指定图片", { authority: 2 }).action(async ({ session }, imgTitle) => {
748
+ await session.send(
749
+ `🚀 开始同步,任务可能耗时较长,请前往控制台查看:${config.logsUrl}`
932
750
  );
933
- }).catch((err) => {
751
+ await syncSingleImage(
752
+ ctx.wikibot.wikigg,
753
+ ctx.wikibot.bwiki,
754
+ `${imgTitle.startsWith("File:") ? "" : "File:"}${imgTitle}`
755
+ ).then(() => {
756
+ session.send(`✅ 已尝试同步图片:${imgTitle}`);
757
+ }).catch((err) => {
758
+ session.send(`❌ 同步图片失败:${imgTitle}`);
759
+ ctx.logger.error(`同步图片失败:${imgTitle},错误信息:${err}`);
760
+ });
761
+ });
762
+ ctx.command("sync.allimgs", "同步所有图片", { authority: 2 }).action(async ({ session }) => {
934
763
  session.send(
935
- `❌ 同步所有模块失败,请前往控制台查看日志:${config.logsUrl}`
764
+ `🚀 开始同步所有图片,任务耗时较长,请前往控制台查看:${config.logsUrl}`
936
765
  );
937
- log.error(`同步所有模块失败,错误信息:${err}`);
766
+ await syncAllImages(ctx.wikibot.wikigg, ctx.wikibot.bwiki).then(() => {
767
+ session.send(
768
+ `✅ 已尝试同步所有图片,请前往控制台查看:${config.logsUrl}`
769
+ );
770
+ }).catch((err) => {
771
+ session.send(
772
+ `❌ 同步所有图片失败,请前往控制台查看日志:${config.logsUrl}`
773
+ );
774
+ ctx.logger.error(`同步所有图片失败,错误信息:${err}`);
775
+ });
938
776
  });
939
777
  });
940
- ctx.command("sync.img <imgTitle:string>", "同步指定图片", { authority: 2 }).action(async ({ session }, imgTitle) => {
941
- await session.send(
942
- `🚀 开始同步,任务可能耗时较长,请前往控制台查看:${config.logsUrl}`
778
+ }
779
+ __name(apply4, "apply");
780
+
781
+ // src/task/modules.ts
782
+ var import_koishi8 = require("koishi");
783
+ var import_plugin_console2 = require("@koishijs/plugin-console");
784
+ var import_path = require("path");
785
+ var ModuleManagerService = class extends import_plugin_console2.DataService {
786
+ static {
787
+ __name(this, "ModuleManagerService");
788
+ }
789
+ constructor(ctx) {
790
+ super(ctx, "moduleManager");
791
+ }
792
+ async get() {
793
+ return await this.ctx.database.get(
794
+ "moduleinfo",
795
+ {},
796
+ { sort: { pageid: "asc" } }
943
797
  );
944
- await syncSingleImage(
945
- ctx.wikibot.wikigg,
946
- ctx.wikibot.bwiki,
947
- `${imgTitle.startsWith("File:") ? "" : "File:"}${imgTitle}`
948
- ).then(() => {
949
- session.send(`✅ 已尝试同步图片:${imgTitle}`);
950
- }).catch((err) => {
951
- session.send(`❌ 同步图片失败:${imgTitle}`);
952
- log.error(`同步图片失败:${imgTitle},错误信息:${err}`);
798
+ }
799
+ };
800
+ var Config5 = import_koishi8.Schema.object({
801
+ logsUrl: import_koishi8.Schema.string().description("日志查看地址").default("https://klei.vip/onilogs"),
802
+ syncCron: import_koishi8.Schema.string().description("定时同步Cron表达式").default("0 2 * * *"),
803
+ concurrency: import_koishi8.Schema.number().description("并发请求数").default(3),
804
+ requestDelay: import_koishi8.Schema.number().description("请求间隔(ms)").default(100)
805
+ });
806
+ async function fetchModulePages(ctx) {
807
+ const modulePages = [];
808
+ try {
809
+ for await (const batch of ctx.wikibot.wikigg.continuedQueryGen({
810
+ action: "query",
811
+ generator: "allpages",
812
+ gapnamespace: 828,
813
+ gaplimit: "max"
814
+ })) {
815
+ const pages = batch.query?.pages;
816
+ if (pages) modulePages.push(...pages);
817
+ }
818
+ } catch (err) {
819
+ logger.error("获取模块页面列表失败", err);
820
+ throw err;
821
+ }
822
+ logger.info(`共获取到 ${modulePages.length} 个模块页面`);
823
+ return modulePages;
824
+ }
825
+ __name(fetchModulePages, "fetchModulePages");
826
+ async function fetchPageRevision(ctx, page) {
827
+ try {
828
+ const res = await ctx.wikibot.wikigg.query({
829
+ action: "query",
830
+ prop: "revisions",
831
+ pageids: page.pageid,
832
+ rvprop: "timestamp|user",
833
+ rvlimit: "1",
834
+ rvdir: "older"
953
835
  });
836
+ const pageInfo = res.query?.pages?.[0];
837
+ const lastRevision = pageInfo?.revisions?.[0];
838
+ if (!lastRevision) {
839
+ return {
840
+ pageid: page.pageid,
841
+ pageTitle: page.title,
842
+ user: "unknown",
843
+ lastEditTime: /* @__PURE__ */ new Date(),
844
+ syncStatus: false
845
+ // 默认为未同步
846
+ };
847
+ }
848
+ return {
849
+ pageid: page.pageid,
850
+ pageTitle: page.title,
851
+ user: lastRevision.user,
852
+ lastEditTime: new Date(lastRevision.timestamp),
853
+ syncStatus: false
854
+ // 拉取时默认为未同步
855
+ };
856
+ } catch (err) {
857
+ logger.error(`获取页面 ${page.title} 修订信息失败: ${err}`);
858
+ return {
859
+ pageid: page.pageid,
860
+ pageTitle: page.title,
861
+ user: "",
862
+ lastEditTime: /* @__PURE__ */ new Date(),
863
+ syncStatus: false
864
+ };
865
+ }
866
+ }
867
+ __name(fetchPageRevision, "fetchPageRevision");
868
+ async function syncModules(ctx, rawConfig) {
869
+ const config = {
870
+ concurrency: 3,
871
+ requestDelay: 100,
872
+ ...rawConfig
873
+ };
874
+ const modulePages = await fetchModulePages(ctx);
875
+ if (modulePages.length === 0)
876
+ return { success: 0, skipped: 0, failed: 0, failedPages: [] };
877
+ const existingData = await ctx.database.get("moduleinfo", {});
878
+ const existingMap = new Map(existingData.map((item) => [item.pageid, item]));
879
+ const moduleDataToUpsert = [];
880
+ const failedPages = [];
881
+ let updatedCount = 0;
882
+ let skippedCount = 0;
883
+ const totalBatches = Math.ceil(modulePages.length / config.concurrency);
884
+ for (let i = 0; i < modulePages.length; i += config.concurrency) {
885
+ const batch = modulePages.slice(i, i + config.concurrency);
886
+ const currentBatch = Math.floor(i / config.concurrency) + 1;
887
+ if (currentBatch % 20 === 0 || currentBatch === 1) {
888
+ logger.info(`处理进度: ${currentBatch}/${totalBatches}`);
889
+ }
890
+ const batchResults = await Promise.all(
891
+ batch.map(async (page) => {
892
+ const data = await fetchPageRevision(ctx, page);
893
+ await new Promise((r) => setTimeout(r, config.requestDelay));
894
+ return data;
895
+ })
896
+ );
897
+ for (const newData of batchResults) {
898
+ const existing = existingMap.get(newData.pageid);
899
+ if (!existing) {
900
+ moduleDataToUpsert.push(newData);
901
+ updatedCount++;
902
+ } else {
903
+ if (newData.lastEditTime.getTime() > existing.lastEditTime.getTime()) {
904
+ moduleDataToUpsert.push(newData);
905
+ updatedCount++;
906
+ } else {
907
+ skippedCount++;
908
+ }
909
+ }
910
+ if (!newData.syncStatus) failedPages.push(newData.pageTitle);
911
+ }
912
+ }
913
+ logger.info(`处理完毕,更新 ${updatedCount} 条,跳过 ${skippedCount} 条`);
914
+ try {
915
+ if (moduleDataToUpsert.length > 0) {
916
+ await ctx.database.upsert("moduleinfo", moduleDataToUpsert);
917
+ logger.info("数据库写入成功");
918
+ const svc = ctx.services?.moduleManager;
919
+ if (svc) svc.refresh();
920
+ }
921
+ } catch (dbErr) {
922
+ logger.error("数据库写入失败", dbErr);
923
+ throw dbErr;
924
+ }
925
+ return {
926
+ success: updatedCount,
927
+ skipped: skippedCount,
928
+ failed: failedPages.length,
929
+ failedPages
930
+ };
931
+ }
932
+ __name(syncModules, "syncModules");
933
+ function apply5(ctx, config) {
934
+ ctx.model.extend(
935
+ "moduleinfo",
936
+ {
937
+ pageid: "integer",
938
+ pageTitle: "string",
939
+ user: "string",
940
+ lastEditTime: "date",
941
+ syncStatus: "boolean"
942
+ },
943
+ { primary: "pageid" }
944
+ );
945
+ ctx.plugin(ModuleManagerService);
946
+ ctx.console.addEntry({
947
+ dev: (0, import_path.resolve)(__dirname, "../client/index.ts"),
948
+ prod: (0, import_path.resolve)(__dirname, "../dist")
954
949
  });
955
- ctx.command("sync.allimgs", "同步所有图片", { authority: 2 }).action(async ({ session }) => {
956
- session.send(
957
- `🚀 开始同步所有图片,任务耗时较长,请前往控制台查看:${config.logsUrl}`
950
+ ctx.console.addListener("module-sync/update", async (payload) => {
951
+ const { pageid, operator } = payload;
952
+ const exists = await ctx.database.get("moduleinfo", { pageid });
953
+ if (exists.length === 0) {
954
+ return { success: false, message: "Page not found" };
955
+ }
956
+ await ctx.database.set(
957
+ "moduleinfo",
958
+ { pageid },
959
+ {
960
+ syncStatus: true,
961
+ // 强制已同步
962
+ lastEditTime: /* @__PURE__ */ new Date(),
963
+ // 强制当前时间
964
+ user: operator || "Console-Admin"
965
+ // 操作人
966
+ }
958
967
  );
959
- await syncAllImages(ctx.wikibot.wikigg, ctx.wikibot.bwiki).then(() => {
960
- session.send(
961
- `✅ 已尝试同步所有图片,请前往控制台查看:${config.logsUrl}`
968
+ const svc = ctx.services?.moduleManager;
969
+ if (svc) svc.refresh();
970
+ return { success: true };
971
+ });
972
+ ctx.console.addListener("module-sync/trigger", async () => {
973
+ syncModules(ctx, config);
974
+ return { success: true, message: "Started" };
975
+ });
976
+ ctx.on("ready", () => {
977
+ logger.info(`[oni-sync] 插件已就绪`);
978
+ const cronExpr = config.syncCron || "0 2 * * *";
979
+ ctx.cron(cronExpr, async () => {
980
+ logger.info("开始定时同步...");
981
+ try {
982
+ const result = await syncModules(ctx, config);
983
+ logger.info(
984
+ `定时同步完成 | 更新: ${result.success}, 跳过: ${result.skipped}`
985
+ );
986
+ } catch (err) {
987
+ logger.error("定时同步失败", err);
988
+ }
989
+ });
990
+ });
991
+ ctx.command("sync.module", "同步模块数据", { authority: 2 }).action(async ({ session }) => {
992
+ await session.send("正在同步中...");
993
+ try {
994
+ const result = await syncModules(ctx, config);
995
+ await session.send(
996
+ `✅ 同步完成
997
+ 更新: ${result.success}
998
+ 跳过: ${result.skipped}
999
+ 失败: ${result.failed}`
962
1000
  );
963
- }).catch((err) => {
964
- session.send(
965
- `❌ 同步所有图片失败,请前往控制台查看日志:${config.logsUrl}`
1001
+ } catch (err) {
1002
+ await session.send("❌ 同步失败");
1003
+ }
1004
+ });
1005
+ ctx.command("sync.module.mark <pageid:number>", "标记模块为已同步", {
1006
+ authority: 2
1007
+ }).action(async ({ session }, pageid) => {
1008
+ const exists = await ctx.database.get("moduleinfo", { pageid });
1009
+ if (exists.length === 0) return `❌ 未找到 ID 为 ${pageid} 的模块`;
1010
+ try {
1011
+ const operatorName = session.username || session.userId || "Lori";
1012
+ await ctx.database.set(
1013
+ "moduleinfo",
1014
+ { pageid },
1015
+ {
1016
+ syncStatus: true,
1017
+ // 强制已同步
1018
+ lastEditTime: /* @__PURE__ */ new Date(),
1019
+ // 强制当前时间
1020
+ user: operatorName
1021
+ // 操作人
1022
+ }
966
1023
  );
967
- log.error(`同步所有图片失败,错误信息:${err}`);
968
- });
1024
+ const svc = ctx.services?.moduleManager;
1025
+ if (svc) svc.refresh();
1026
+ return `✅ 已标记为同步 (操作人: ${operatorName})`;
1027
+ } catch (e) {
1028
+ return "❌ 设置失败";
1029
+ }
969
1030
  });
970
- ctx.command("sync <pageTitle:string>", "同步指定页面", { authority: 2 }).action(async ({ session }, pageTitle) => {
971
- await syncSinglePage(
972
- ctx.wikibot.wikigg,
973
- ctx.wikibot.bwiki,
974
- pageTitle,
975
- "sync-bot"
976
- ).then(() => {
977
- session.send(
978
- `✅ 已尝试同步页面:${pageTitle},请前往控制台查看:${config.logsUrl}`
1031
+ ctx.command(
1032
+ "sync.module.status <pageid:number> <status:boolean>",
1033
+ "手动切换模块同步状态",
1034
+ { authority: 2 }
1035
+ ).action(async ({ session }, pageid, status) => {
1036
+ const exists = await ctx.database.get("moduleinfo", { pageid });
1037
+ if (exists.length === 0) return `❌ 未找到 ID 为 ${pageid} 的模块`;
1038
+ try {
1039
+ await ctx.database.set(
1040
+ "moduleinfo",
1041
+ { pageid },
1042
+ {
1043
+ syncStatus: status
1044
+ // 仅修改状态
1045
+ // 不修改时间和用户
1046
+ }
979
1047
  );
980
- }).catch((err) => {
981
- session.send(`❌ 同步页面失败:${pageTitle}`);
982
- log.error(`,错误信息:${err}`);
983
- });
1048
+ const svc = ctx.services?.moduleManager;
1049
+ if (svc) svc.refresh();
1050
+ return `✅ 状态已设为: ${status ? "已同步" : "未同步"}`;
1051
+ } catch (e) {
1052
+ return "❌ 设置失败";
1053
+ }
984
1054
  });
985
1055
  }
986
- __name(apply4, "apply");
1056
+ __name(apply5, "apply");
1057
+
1058
+ // src/task/index.ts
1059
+ var Config6 = import_koishi9.Schema.object({
1060
+ logsUrl: import_koishi9.Schema.string().description("日志查看地址").default("https://klei.vip/onilogs")
1061
+ });
1062
+ function apply6(ctx, config) {
1063
+ logger.info("同步任务模块已加载");
1064
+ ctx.plugin(apply3);
1065
+ ctx.plugin(apply4);
1066
+ ctx.plugin(apply5);
1067
+ }
1068
+ __name(apply6, "apply");
987
1069
 
988
1070
  // src/wiki/querywiki.ts
989
- var import_koishi9 = require("koishi");
990
- var Config5 = import_koishi9.Schema.object({
991
- domain: import_koishi9.Schema.string().description("你的短链域名(必填,如:klei.vip)").default("klei.vip")
1071
+ var import_koishi10 = require("koishi");
1072
+ var Config7 = import_koishi10.Schema.object({
1073
+ domain: import_koishi10.Schema.string().description("你的短链域名(必填,如:klei.vip)").default("klei.vip")
992
1074
  });
993
1075
  function queryWiki(ctx, config) {
994
1076
  const log = ctx.logger("querywiki");
@@ -1172,22 +1254,37 @@ __name(queryWiki, "queryWiki");
1172
1254
  // src/index.ts
1173
1255
  var name = "oni-sync-bot";
1174
1256
  var inject = ["console", "database", "server", "cron"];
1175
- var Config6 = import_koishi10.Schema.object({});
1176
- function apply5(ctx, config) {
1177
- const log = ctx.logger("oni-sync");
1257
+ var Config8 = import_koishi11.Schema.object({
1258
+ ggUsername: import_koishi11.Schema.string().description("WIKIGG 用户名").default("1"),
1259
+ ggPassword: import_koishi11.Schema.string().description("WIKIGG 密码").default("1"),
1260
+ bwikiusername: import_koishi11.Schema.string().description("bwiki用户名").default("1"),
1261
+ bwikipassword: import_koishi11.Schema.string().description("bwiki密码").default("1"),
1262
+ domain: import_koishi11.Schema.string().description("你的短链域名(必填,如:klei.vip)").default("klei.vip"),
1263
+ logsUrl: import_koishi11.Schema.string().description("日志查看地址").default("https://klei.vip/onilogs")
1264
+ });
1265
+ function apply7(ctx, config) {
1178
1266
  ctx.inject(["console"], (ctx2) => {
1179
1267
  ctx2.console.addEntry({
1180
- dev: (0, import_path.resolve)(__dirname, "../client/index.ts"),
1181
- prod: (0, import_path.resolve)(__dirname, "../dist")
1268
+ dev: (0, import_path2.resolve)(__dirname, "../client/index.ts"),
1269
+ prod: (0, import_path2.resolve)(__dirname, "../dist")
1182
1270
  });
1183
1271
  });
1272
+ const sitesConfig = getSitesConfig(config);
1273
+ ctx.on("ready", async () => {
1274
+ const wikiggBot = await login(sitesConfig.gg);
1275
+ const bwikiBot = await login(sitesConfig.bwiki);
1276
+ ctx.wikibot = { wikigg: wikiggBot, bwiki: bwikiBot };
1277
+ });
1278
+ ctx.on("dispose", () => {
1279
+ logger.warn("⚠️ 插件已卸载,ctx.wikibot清除...");
1280
+ ctx.wikibot = void 0;
1281
+ });
1184
1282
  ctx.plugin(apply, config);
1185
1283
  ctx.plugin(apply2, config);
1186
- ctx.plugin(apply3, config);
1187
- ctx.plugin(apply4, config);
1284
+ ctx.plugin(apply6, config);
1188
1285
  ctx.plugin(queryWiki, config);
1189
1286
  }
1190
- __name(apply5, "apply");
1287
+ __name(apply7, "apply");
1191
1288
  // Annotate the CommonJS export names for ESM import in node:
1192
1289
  0 && (module.exports = {
1193
1290
  Config,
@@ -0,0 +1,29 @@
1
+ import { Mwn } from "mwn";
2
+ export declare const CONFIG: {
3
+ IGNORED_IMAGES: any[];
4
+ SYNC_INTERVAL_SUCCESS: number;
5
+ SYNC_INTERVAL_FAILED: number;
6
+ UPLOAD_COMMENT: string;
7
+ UPLOAD_TEXT: string;
8
+ };
9
+ interface ImageInfo {
10
+ url: string;
11
+ sha1: string;
12
+ size?: number;
13
+ }
14
+ /**
15
+ * 获取图片的原始URL和SHA1
16
+ */
17
+ declare function getImageInfo(site: Mwn, fileName: string): Promise<ImageInfo | null>;
18
+ /**
19
+ * 同步单个图片
20
+ */
21
+ declare function syncSingleImage(sourceBot: Mwn, targetBot: Mwn, fileName: string): Promise<{
22
+ success: boolean;
23
+ reason?: string;
24
+ }>;
25
+ /**
26
+ * 批量同步所有图片(带失败重试)
27
+ */
28
+ declare function syncAllImages(sourceBot: Mwn, targetBot: Mwn): Promise<void>;
29
+ export { syncSingleImage, syncAllImages, getImageInfo };
@@ -0,0 +1,29 @@
1
+ import { Mwn } from "mwn";
2
+ /**
3
+ * 单页面同步
4
+ * @param oldSite 源站点机器人实例
5
+ * @param newSite 目标站点机器人实例
6
+ * @param pageTitle 同步的标题
7
+ * @param user 触发更改的用户
8
+ * @returns success: boolean;reason: string;
9
+ }
10
+ */
11
+ declare function syncSinglePage(oldSite: Mwn, newSite: Mwn, pageTitle: string, user: string): Promise<{
12
+ success: boolean;
13
+ reason: string;
14
+ }>;
15
+ /**
16
+ * 同步所有页面
17
+ * @param oldSite 源站点机器人实例
18
+ * @param newSite 目标站点机器人实例
19
+ * @returns null
20
+ */
21
+ declare function syncPages(oldSite: Mwn, newSite: Mwn): Promise<void>;
22
+ /**
23
+ * 增量更新
24
+ * @param oldSite 源站点机器人实例
25
+ * @param newSite 目标站点机器人实例
26
+ * @param config KOISHI用户配置的项
27
+ */
28
+ declare function incrementalUpdate(oldSite: Mwn, newSite: Mwn): Promise<void>;
29
+ export { syncSinglePage, syncPages, incrementalUpdate };
@@ -0,0 +1,8 @@
1
+ import { Context, Schema } from "koishi";
2
+ export declare const name = "synctask_imgs";
3
+ export declare const usage = "\u56FE\u7247\u540C\u6B65\u4EFB\u52A1";
4
+ export interface Config {
5
+ logsUrl: string;
6
+ }
7
+ export declare const Config: Schema<Config>;
8
+ export default function apply(ctx: Context, config: Config): void;
@@ -0,0 +1,8 @@
1
+ import { Context, Schema } from "koishi";
2
+ export declare const name = "synctask";
3
+ export declare const usage = "\u540C\u6B65\u4EFB\u52A1";
4
+ export interface Config {
5
+ logsUrl: string;
6
+ }
7
+ export declare const Config: Schema<Config>;
8
+ export default function apply(ctx: Context, config: Config): void;
@@ -0,0 +1,49 @@
1
+ import { Context, Schema } from "koishi";
2
+ import { DataService } from "@koishijs/plugin-console";
3
+ export declare const name = "synctask_modules";
4
+ export declare const usage = "\u540C\u6B65\u6A21\u5757";
5
+ export declare const inject: string[];
6
+ interface IModuleData {
7
+ pageid: number;
8
+ pageTitle: string;
9
+ user: string;
10
+ lastEditTime: Date;
11
+ syncStatus: boolean;
12
+ }
13
+ export interface Config {
14
+ logsUrl: string;
15
+ syncCron?: string;
16
+ concurrency?: number;
17
+ requestDelay?: number;
18
+ }
19
+ declare module "@koishijs/plugin-console" {
20
+ namespace Console {
21
+ interface Services {
22
+ moduleManager: ModuleManagerService;
23
+ }
24
+ }
25
+ interface Events {
26
+ "module-sync/update"(payload: {
27
+ pageid: number;
28
+ operator?: string;
29
+ }): Promise<{
30
+ success: boolean;
31
+ }>;
32
+ "module-sync/trigger"(): Promise<{
33
+ success: boolean;
34
+ message: string;
35
+ }>;
36
+ }
37
+ }
38
+ declare module "koishi" {
39
+ interface Tables {
40
+ moduleinfo: IModuleData;
41
+ }
42
+ }
43
+ declare class ModuleManagerService extends DataService<IModuleData[]> {
44
+ constructor(ctx: Context);
45
+ get(): Promise<import("minato").FlatPick<IModuleData, any>[]>;
46
+ }
47
+ export declare const Config: Schema<Config>;
48
+ export default function apply(ctx: Context, config: Config): void;
49
+ export {};
@@ -0,0 +1,8 @@
1
+ import { Context, Schema } from "koishi";
2
+ export declare const name = "synctask_pages";
3
+ export declare const usage = "\u9875\u9762\u540C\u6B65\u4EFB\u52A1";
4
+ export interface Config {
5
+ logsUrl: string;
6
+ }
7
+ export declare const Config: Schema<Config>;
8
+ export default function apply(ctx: Context, config: Config): void;
@@ -1,24 +1,8 @@
1
- import { Context, Schema } from "koishi";
2
1
  import { Mwn } from "mwn";
2
+ import { Config } from "..";
3
+ import { Context } from "koishi";
3
4
  export declare const name = "wikicore";
4
5
  export declare const usage = "wikicore";
5
- declare module "koishi" {
6
- interface Context {
7
- wikibot: {
8
- wikigg: Mwn;
9
- bwiki: Mwn;
10
- };
11
- }
12
- }
13
- export interface Config {
14
- ggUsername: string;
15
- ggPassword: string;
16
- bwikiusername: string;
17
- bwikipassword: string;
18
- domain: string;
19
- logsUrl: string;
20
- }
21
- export declare const Config: Schema<Config>;
22
6
  export default function apply(ctx: Context, config: Config): void;
23
7
  /**
24
8
  * 登录机器人
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "koishi-plugin-oni-sync-bot",
3
3
  "description": "缺氧Wiki站镜像点同步-测试",
4
- "version": "0.4.1",
4
+ "version": "0.5.1",
5
5
  "main": "lib/index.js",
6
6
  "typings": "lib/index.d.ts",
7
7
  "files": [