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 +1 -1
- package/dist/style.css +1 -1
- package/lib/index.d.ts +15 -0
- package/lib/index.js +397 -300
- package/lib/synclib/imgSync.d.ts +29 -0
- package/lib/synclib/pageSync.d.ts +29 -0
- package/lib/task/imgs.d.ts +8 -0
- package/lib/task/index.d.ts +8 -0
- package/lib/task/modules.d.ts +49 -0
- package/lib/task/pages.d.ts +8 -0
- package/lib/wiki/wikicore.d.ts +2 -18
- package/package.json +1 -1
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: () =>
|
|
34
|
-
apply: () =>
|
|
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
|
|
40
|
-
var
|
|
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
|
|
165
|
-
var
|
|
166
|
-
logsUrl:
|
|
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
|
|
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
|
-
|
|
171
|
+
import_koishi2.Logger.targets.push(target);
|
|
194
172
|
ctx.on("dispose", () => {
|
|
195
|
-
const index =
|
|
196
|
-
if (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(
|
|
177
|
+
__name(apply, "apply");
|
|
200
178
|
|
|
201
179
|
// src/service/router.ts
|
|
202
|
-
var
|
|
203
|
-
var
|
|
204
|
-
main_site:
|
|
205
|
-
bwiki_site:
|
|
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
|
|
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(
|
|
209
|
+
__name(apply2, "apply");
|
|
232
210
|
|
|
233
|
-
// src/task/
|
|
234
|
-
var
|
|
211
|
+
// src/task/index.ts
|
|
212
|
+
var import_koishi9 = require("koishi");
|
|
235
213
|
|
|
236
|
-
// src/
|
|
214
|
+
// src/task/pages.ts
|
|
237
215
|
var import_koishi6 = require("koishi");
|
|
238
216
|
|
|
239
|
-
// src/
|
|
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,
|
|
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,
|
|
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,
|
|
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/
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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/
|
|
682
|
-
var
|
|
683
|
-
|
|
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
|
|
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
|
|
908
|
-
|
|
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
|
-
|
|
718
|
+
pageTitle,
|
|
915
719
|
"sync-bot"
|
|
916
720
|
).then(() => {
|
|
917
721
|
session.send(
|
|
918
|
-
`✅
|
|
722
|
+
`✅ 已尝试同步页面:${pageTitle},请前往控制台查看:${config.logsUrl}`
|
|
919
723
|
);
|
|
920
724
|
}).catch((err) => {
|
|
921
|
-
session.send(`❌
|
|
922
|
-
log.error(
|
|
725
|
+
session.send(`❌ 同步页面失败:${pageTitle}`);
|
|
726
|
+
log.error(`,错误信息:${err}`);
|
|
923
727
|
});
|
|
924
728
|
});
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
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
|
-
|
|
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
|
-
|
|
764
|
+
`🚀 开始同步所有图片,任务耗时较长,请前往控制台查看:${config.logsUrl}`
|
|
936
765
|
);
|
|
937
|
-
|
|
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
|
-
|
|
941
|
-
|
|
942
|
-
|
|
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
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
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.
|
|
956
|
-
|
|
957
|
-
|
|
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
|
-
|
|
960
|
-
|
|
961
|
-
|
|
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
|
-
}
|
|
964
|
-
session.send(
|
|
965
|
-
|
|
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
|
-
|
|
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(
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
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
|
-
|
|
981
|
-
|
|
982
|
-
|
|
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(
|
|
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
|
|
990
|
-
var
|
|
991
|
-
domain:
|
|
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
|
|
1176
|
-
|
|
1177
|
-
|
|
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,
|
|
1181
|
-
prod: (0,
|
|
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(
|
|
1187
|
-
ctx.plugin(apply4, config);
|
|
1284
|
+
ctx.plugin(apply6, config);
|
|
1188
1285
|
ctx.plugin(queryWiki, config);
|
|
1189
1286
|
}
|
|
1190
|
-
__name(
|
|
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;
|
package/lib/wiki/wikicore.d.ts
CHANGED
|
@@ -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
|
* 登录机器人
|