prts-moonlit 1.0.0 → 1.0.2
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/gacha.html +189 -5
- package/index.html +193 -9
- package/ledger.html +190 -6
- package/package.json +2 -2
package/gacha.html
CHANGED
|
@@ -1030,14 +1030,198 @@ document.addEventListener('pointerdown',function(){ac()},{once:true});
|
|
|
1030
1030
|
function kick(){if(ctx&&ctx.state!=='running'&&ctx.resume){try{ctx.resume()}catch(e){}}if(!want||playing())return;if(bURL)ensure();else pend=1}
|
|
1031
1031
|
document.addEventListener('pointerdown',kick,true);
|
|
1032
1032
|
au.addEventListener('playing',function(){document.removeEventListener('pointerdown',kick,true)});
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1033
|
+
var _ld=0;
|
|
1034
|
+
function loadBgm(){if(_ld)return;_ld=1;
|
|
1035
|
+
fetch('bgm.mp3').then(function(r){return r.arrayBuffer()}).then(function(a){
|
|
1036
|
+
abuf=a;bURL=URL.createObjectURL(new Blob([a],{type:'audio/mpeg'}));
|
|
1037
|
+
if(elemTried&&want){warmOnly=1;toWA()}
|
|
1038
|
+
if(want&&!playing()){pend=0;ensure()}
|
|
1039
|
+
}).catch(function(){});
|
|
1040
|
+
}
|
|
1041
|
+
setTimeout(loadBgm,2500);
|
|
1042
|
+
document.addEventListener('pointerdown',loadBgm,true);
|
|
1038
1043
|
if(want){setTimeout(function(){if(!playing()&&bURL){ensure()}},400)}
|
|
1039
1044
|
window.__bgmFade=function(){savePos();try{if(node&&gn){var g0=gn.gain.value,t0=Date.now();var iv=setInterval(function(){var k=Math.max(0,1-(Date.now()-t0)/500);gn.gain.value=g0*k;if(k<=0)clearInterval(iv)},60)}}catch(e){}};
|
|
1040
1045
|
})();
|
|
1041
1046
|
</script>
|
|
1047
|
+
|
|
1048
|
+
<!-- ===== SYSTEM LOGIN 云存档 ===== -->
|
|
1049
|
+
<script>
|
|
1050
|
+
/* ===== SYSTEM LOGIN · 云存档同步引擎 v1 ===== */
|
|
1051
|
+
(function(){
|
|
1052
|
+
var TK=['whale.tasks.v1','minis_ledger_v1','minis_ledger_trash_v1','whale.bgm'];
|
|
1053
|
+
var BASE='https://textdb.dev/api/data/prts-acct-';
|
|
1054
|
+
var LS='whale.acct',LT='whale.sync.t';
|
|
1055
|
+
var acct=null;try{acct=JSON.parse(localStorage.getItem(LS)||'null')}catch(e){}
|
|
1056
|
+
var _si=localStorage.setItem.bind(localStorage),_app=0,pq=0,box=null,_dirty=0;
|
|
1057
|
+
|
|
1058
|
+
function sha(msg){
|
|
1059
|
+
function r(v,n){return (v>>>n)|(v<<(32-n));}
|
|
1060
|
+
var i,j,K=[],H=[0x6a09e667,0xbb67ae85,0x3c6ef372,0xa54ff53a,0x510e527f,0x9b05688c,0x1f83d9ab,0x5be0cd19],W=new Array(64),ml=msg.length*8;
|
|
1061
|
+
(function(){var p=2;function pr(x){for(var d=2;d*d<=x;d++){if(x%d===0)return false}return true;}
|
|
1062
|
+
while(K.length<64){if(pr(p)){K.push(Math.floor(Math.pow(p,1/3)*4294967296)%4294967296);}p++;}})();
|
|
1063
|
+
var b=[];
|
|
1064
|
+
for(i=0;i<msg.length;i++){var c=msg.charCodeAt(i);
|
|
1065
|
+
if(c<128)b.push(c);
|
|
1066
|
+
else if(c<2048){b.push(192|(c>>6),128|(c&63));}
|
|
1067
|
+
else{b.push(224|(c>>12),128|((c>>6)&63),128|(c&63));}}
|
|
1068
|
+
b.push(0x80);while(b.length%64!==56)b.push(0);
|
|
1069
|
+
for(i=7;i>=0;i--)b.push(Math.floor(ml/Math.pow(2,i*8))&255);
|
|
1070
|
+
for(i=0;i<b.length;i+=64){
|
|
1071
|
+
for(j=0;j<16;j++)W[j]=(b[i+j*4]<<24)|(b[i+j*4+1]<<16)|(b[i+j*4+2]<<8)|b[i+j*4+3];
|
|
1072
|
+
for(j=16;j<64;j++){var s0=r(W[j-15],7)^r(W[j-15],18)^(W[j-15]>>>3),s1=r(W[j-2],17)^r(W[j-2],19)^(W[j-2]>>>10);W[j]=(W[j-16]+s0+W[j-7]+s1)|0;}
|
|
1073
|
+
var a=H[0],bb=H[1],cc=H[2],d=H[3],e=H[4],f=H[5],g=H[6],h=H[7];
|
|
1074
|
+
for(j=0;j<64;j++){
|
|
1075
|
+
var S1=r(e,6)^r(e,11)^r(e,25),ch=(e&f)^(~e&g),t1=(h+S1+ch+K[j]+W[j])|0,
|
|
1076
|
+
S0=r(a,2)^r(a,13)^r(a,22),mj=(a&bb)^(a&cc)^(bb&cc),t2=(S0+mj)|0;
|
|
1077
|
+
h=g;g=f;f=e;e=(d+t1)|0;d=cc;cc=bb;bb=a;a=(t1+t2)|0;
|
|
1078
|
+
}
|
|
1079
|
+
H[0]=(H[0]+a)|0;H[1]=(H[1]+bb)|0;H[2]=(H[2]+cc)|0;H[3]=(H[3]+d)|0;H[4]=(H[4]+e)|0;H[5]=(H[5]+f)|0;H[6]=(H[6]+g)|0;H[7]=(H[7]+h)|0;
|
|
1080
|
+
}
|
|
1081
|
+
var o='';for(i=0;i<8;i++)o+=('00000000'+(H[i]>>>0).toString(16)).slice(-8);
|
|
1082
|
+
return o;
|
|
1083
|
+
}
|
|
1084
|
+
function snap(){var d={};for(var i=0;i<TK.length;i++){var v=localStorage.getItem(TK[i]);if(v!==null)d[TK[i]]=v;}return d;}
|
|
1085
|
+
function url(){return BASE+acct.k;}
|
|
1086
|
+
function st(m){if(box&&box.st)box.st.textContent=m;}
|
|
1087
|
+
function clock(){var d=new Date();function p(n){return(n<10?'0':'')+n}return p(d.getHours())+':'+p(d.getMinutes());}
|
|
1088
|
+
function apply(rb){
|
|
1089
|
+
_app=1;try{for(var k in rb.data){_si(k,rb.data[k]);}}finally{_app=0;}
|
|
1090
|
+
_si(LT,String(rb.t||Date.now()));
|
|
1091
|
+
st('✔ 已从云端同步 '+clock()+',即将刷新…');
|
|
1092
|
+
setTimeout(function(){location.reload();},800);
|
|
1093
|
+
}
|
|
1094
|
+
function push(){
|
|
1095
|
+
if(!acct||!acct.k)return;
|
|
1096
|
+
_dirty=0;var t=Date.now();_si(LT,String(t));
|
|
1097
|
+
st('↻ 同步中…');
|
|
1098
|
+
fetch(url(),{method:'POST',mode:'no-cors',body:JSON.stringify({v:1,u:acct.u,t:t,data:snap()})})
|
|
1099
|
+
.then(function(){setTimeout(function(){verify(t)},1800);})
|
|
1100
|
+
.catch(function(){st('⚠ 云同步暂不可用(可用存档码手动搬)');});
|
|
1101
|
+
}
|
|
1102
|
+
function verify(t){
|
|
1103
|
+
fetch(url()+'?ts='+Date.now()).then(function(r){return r.text()}).then(function(x){
|
|
1104
|
+
x=(x||'').replace(/=$/,'');
|
|
1105
|
+
try{var rb=JSON.parse(x);if(rb.t===t){st('✔ 已同步 '+clock());return;}}catch(e){}
|
|
1106
|
+
if(!window.__pv){window.__pv=1;setTimeout(function(){window.__pv=0;push();},1500);}
|
|
1107
|
+
else{st('⚠ 云端回读不一致,稍后自动重试');}
|
|
1108
|
+
}).catch(function(){st('⚠ 校验失败(可能网络受限)');});
|
|
1109
|
+
}
|
|
1110
|
+
function pull(manual){
|
|
1111
|
+
if(!acct||!acct.k)return;
|
|
1112
|
+
fetch(url()+'?ts='+Date.now()).then(function(r){return r.text()}).then(function(x){
|
|
1113
|
+
x=(x||'').replace(/=$/,'');
|
|
1114
|
+
if(!x){if(manual)st('☁ 云端暂时没有存档——点「立即同步」上传本机数据');return;}
|
|
1115
|
+
var rb;try{rb=JSON.parse(x)}catch(e){st('⚠ 云端数据格式异常');return;}
|
|
1116
|
+
var lt=Number(localStorage.getItem(LT)||0);
|
|
1117
|
+
if((rb.t||0)>lt){
|
|
1118
|
+
var same=1;for(var kk in rb.data){if(localStorage.getItem(kk)!==rb.data[kk]){same=0;break;}}
|
|
1119
|
+
if(same){_si(LT,String(rb.t));if(manual)st('✔ 已是最新 '+clock());}
|
|
1120
|
+
else{apply(rb);}
|
|
1121
|
+
}
|
|
1122
|
+
else if(manual){
|
|
1123
|
+
var same2=1;for(var k2 in rb.data){if(localStorage.getItem(k2)!==rb.data[k2]){same2=0;break;}}
|
|
1124
|
+
if(same2){st('✔ 已是最新 '+clock());}else{push();}
|
|
1125
|
+
}
|
|
1126
|
+
else{st('✔ 已是云端最新');}
|
|
1127
|
+
}).catch(function(){st('⚠ 云端连接失败');});
|
|
1128
|
+
}
|
|
1129
|
+
function logout(){localStorage.removeItem(LS);acct=null;}
|
|
1130
|
+
var CSS='.acWrap{position:fixed;inset:0;z-index:9998;background:rgba(3,6,14,.66);display:none;align-items:center;justify-content:center}.acWrap.on{display:flex}'+
|
|
1131
|
+
'.acBox{width:min(86vw,360px);max-height:86vh;overflow:auto;background:rgba(7,12,24,.97);border:2px solid #4cc9ff;box-shadow:6px 6px 0 rgba(18,115,200,.45);padding:16px;font-family:ui-monospace,Menlo,monospace;color:#eef7ff}'+
|
|
1132
|
+
'.acBox h3{margin:0 0 4px;font-size:15px;letter-spacing:.12em;color:#8fe0ff}.acBox .sub{font-size:10px;opacity:.65;margin-bottom:10px}'+
|
|
1133
|
+
'.acBox input{width:100%;box-sizing:border-box;background:#0a1322;border:1.5px solid #2b4a66;color:#eef7ff;font-family:inherit;font-size:13px;padding:8px;margin:5px 0}'+
|
|
1134
|
+
'.acBox button{background:#0a1322;border:1.5px solid #4cc9ff;color:#4cc9ff;font-family:inherit;font-size:12px;padding:7px 10px;margin:6px 6px 0 0;cursor:pointer;letter-spacing:.08em}'+
|
|
1135
|
+
'.acBox button.pri{background:#4cc9ff;color:#06121f;font-weight:700}'+
|
|
1136
|
+
'.acBox .st{font-size:11px;margin-top:10px;min-height:14px;color:#9fe9a0;line-height:1.5;word-break:break-all}'+
|
|
1137
|
+
'.acBox textarea{width:100%;box-sizing:border-box;height:70px;background:#0a1322;border:1.5px solid #2b4a66;color:#9fd8ff;font-size:10px;font-family:inherit;margin-top:8px;display:none}'+
|
|
1138
|
+
'.acBox textarea.on{display:block}';
|
|
1139
|
+
var sEl=document.createElement('style');sEl.textContent=CSS;document.head.appendChild(sEl);
|
|
1140
|
+
var wrap=document.createElement('div');wrap.className='acWrap';document.body.appendChild(wrap);
|
|
1141
|
+
function esc(s){return String(s).replace(/[<>&"]/g,function(c){return{'<':'<','>':'>','&':'&','"':'"'}[c]})}
|
|
1142
|
+
function render(){
|
|
1143
|
+
var h='<div class="acBox"><h3>SYSTEM LOGIN · 云存档</h3><div class="sub">同一账号 · 多设备同步(鱼干/任务/券/小账本)</div>';
|
|
1144
|
+
if(acct){
|
|
1145
|
+
h+='<div style="font-size:12px;margin:6px 0 2px">当前账号:<b style="color:#ffd23f">'+esc(acct.u)+'</b></div>'+
|
|
1146
|
+
'<button class="pri" id="acSync">↻ 立即同步</button><button id="acOut">退出登录</button>';
|
|
1147
|
+
}else{
|
|
1148
|
+
h+='<input id="acU" placeholder="用户名(自己起,例如 yanliang27)" autocomplete="username">'+
|
|
1149
|
+
'<input id="acP" type="password" placeholder="密码(≥4位,丢了找不回!)" autocomplete="current-password">'+
|
|
1150
|
+
'<button class="pri" id="acGo">登录 / 创建</button>';
|
|
1151
|
+
}
|
|
1152
|
+
h+='<button id="acExp">📤 存档码</button><button id="acImp">📥 导入</button>'+
|
|
1153
|
+
'<div class="st" id="acSt"></div><textarea id="acTa" spellcheck="false"></textarea>'+
|
|
1154
|
+
'<div style="font-size:10px;opacity:.5;margin-top:9px;line-height:1.5">密钥由「用户名+密码」派生;同一账号在任意设备登录即接回数据。忘记密码=新仓库(旧数据找不回)</div>'+
|
|
1155
|
+
'<button id="acX" style="border-color:#2b4a66;color:#8ea6bf;margin-top:10px">关闭 / CLOSE</button></div>';
|
|
1156
|
+
wrap.innerHTML=h;
|
|
1157
|
+
box={st:wrap.querySelector('#acSt'),ta:wrap.querySelector('#acTa')};
|
|
1158
|
+
bind();
|
|
1159
|
+
}
|
|
1160
|
+
function bind(){
|
|
1161
|
+
var g=function(id){return wrap.querySelector(id)};
|
|
1162
|
+
var go=g('#acGo');
|
|
1163
|
+
if(go)go.onclick=function(){
|
|
1164
|
+
var b=go,u=(g('#acU').value||'').trim(),p=g('#acP').value||'';
|
|
1165
|
+
if(u.length<2||p.length<4){st('用户名≥2位、密码≥4位哦');return;}
|
|
1166
|
+
var k=sha('prts-moonlit|'+u+'|'+p);
|
|
1167
|
+
if(b.getAttribute('data-mode')==='create'){
|
|
1168
|
+
acct={u:u,k:k};_si(LS,JSON.stringify(acct));_si(LT,String(Date.now()));
|
|
1169
|
+
st('✦ 仓库已创建,正在上传本机数据…');render();push();return;
|
|
1170
|
+
}
|
|
1171
|
+
st('↻ 查找云端仓库…');
|
|
1172
|
+
fetch(BASE+k+'?ts='+Date.now()).then(function(r){return r.text()}).then(function(x){
|
|
1173
|
+
x=(x||'').replace(/=$/,'');
|
|
1174
|
+
if(x&&x.length>2){
|
|
1175
|
+
acct={u:u,k:k};_si(LS,JSON.stringify(acct));
|
|
1176
|
+
var rb=null;try{rb=JSON.parse(x)}catch(e){}
|
|
1177
|
+
if(rb&&(rb.t||0)>Number(localStorage.getItem(LT)||0)){apply(rb);}
|
|
1178
|
+
else{_si(LT,String((rb&&rb.t)||Date.now()));st('✔ 已登录,云端仓库已连接 '+clock());render();}
|
|
1179
|
+
}else{
|
|
1180
|
+
b.setAttribute('data-mode','create');b.textContent='✦ 没找到仓库——点此以本机数据创建';
|
|
1181
|
+
st('(如果是新账号,创建后本机数据会上传成初始存档)');
|
|
1182
|
+
}
|
|
1183
|
+
}).catch(function(){st('⚠ 云端连接失败,稍后再试');});
|
|
1184
|
+
};
|
|
1185
|
+
var sy=g('#acSync');if(sy)sy.onclick=function(){pull(true)};
|
|
1186
|
+
var o=g('#acOut');if(o)o.onclick=function(){
|
|
1187
|
+
if(o.getAttribute('data-c')){logout();st('已退出登录(本机数据保留)');render();}
|
|
1188
|
+
else{o.setAttribute('data-c','1');o.textContent='⚠ 再点一次 = 退出登录';}};
|
|
1189
|
+
var e1=g('#acExp');if(e1)e1.onclick=function(){
|
|
1190
|
+
var b=JSON.stringify({v:1,u:acct?acct.u:'anon',t:Date.now(),data:snap()});
|
|
1191
|
+
var ta=g('#acTa');ta.classList.add('on');
|
|
1192
|
+
ta.value=btoa(unescape(encodeURIComponent(b)));ta.select();
|
|
1193
|
+
st('已生成存档码——全选复制保存,换设备时用「导入」');};
|
|
1194
|
+
var i1=g('#acImp');if(i1)i1.onclick=function(){
|
|
1195
|
+
var ta=g('#acTa');ta.classList.add('on');
|
|
1196
|
+
if(i1.getAttribute('data-c')){
|
|
1197
|
+
var v=ta.value.trim();
|
|
1198
|
+
if(!v){st('先把存档码粘到下面框里');return;}
|
|
1199
|
+
try{var rb=JSON.parse(decodeURIComponent(escape(atob(v))));apply(rb);}
|
|
1200
|
+
catch(e){st('⚠ 存档码无效');}
|
|
1201
|
+
return;}
|
|
1202
|
+
i1.setAttribute('data-c','1');ta.value='';
|
|
1203
|
+
st('把另一台设备的存档码粘到下方,再点一次「导入」');};
|
|
1204
|
+
var x=g('#acX');if(x)x.onclick=function(){wrap.classList.remove('on')};
|
|
1205
|
+
wrap.onclick=function(e){if(e.target===wrap)wrap.classList.remove('on')};
|
|
1206
|
+
}
|
|
1207
|
+
function open(){render();wrap.classList.add('on')}
|
|
1208
|
+
var _orig=localStorage.setItem;
|
|
1209
|
+
localStorage.setItem=function(k,v){_orig.call(localStorage,k,v);if(!_app&&acct&&acct.k&&TK.indexOf(k)>=0&&k!==LT){_dirty=1;clearTimeout(pq);pq=setTimeout(push,2200);}};
|
|
1210
|
+
window.addEventListener('pagehide',function(){
|
|
1211
|
+
if(acct&&acct.k&&_dirty){try{_dirty=0;_si(LT,String(Date.now()));
|
|
1212
|
+
fetch(url(),{method:'POST',mode:'no-cors',keepalive:true,body:JSON.stringify({v:1,u:acct.u,t:Date.now(),data:snap()})});}catch(e){}}
|
|
1213
|
+
});
|
|
1214
|
+
document.addEventListener('visibilitychange',function(){if(!document.hidden&&acct&&acct.k){pull(false);}});
|
|
1215
|
+
var btn=document.createElement('div');
|
|
1216
|
+
var ci=document.querySelector('.corner-ics');
|
|
1217
|
+
if(ci){btn.className='ci';btn.textContent='@';ci.appendChild(btn);}
|
|
1218
|
+
else{btn.textContent='@';btn.style.cssText='position:fixed;right:14px;bottom:60px;z-index:120;width:38px;height:38px;display:flex;align-items:center;justify-content:center;border:2px solid #4cc9ff;background:rgba(7,12,24,.92);color:#4cc9ff;font-size:17px;cursor:pointer;user-select:none;box-shadow:3px 3px 0 rgba(0,0,0,.45)';document.body.appendChild(btn);}
|
|
1219
|
+
btn.id='acctBtn';btn.title='云存档';
|
|
1220
|
+
if(acct)btn.style.background='rgba(76,201,255,.28)';
|
|
1221
|
+
btn.addEventListener('click',open);
|
|
1222
|
+
if(acct&&acct.k){setTimeout(function(){pull(false);},1600);}
|
|
1223
|
+
window.__shaT=sha;
|
|
1224
|
+
})();
|
|
1225
|
+
</script>
|
|
1042
1226
|
</body>
|
|
1043
1227
|
</html>
|
package/index.html
CHANGED
|
@@ -679,11 +679,16 @@ img.av{filter:saturate(1.1) contrast(1.05) -webkit-user-drag:none}
|
|
|
679
679
|
function kick(){if(ctx&&ctx.state!=='running'&&ctx.resume){try{ctx.resume()}catch(e){}}if(!want||playing())return;if(bURL)ensure();else pend=1}
|
|
680
680
|
document.addEventListener('pointerdown',kick,true);
|
|
681
681
|
au.addEventListener('playing',function(){document.removeEventListener('pointerdown',kick,true)});
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
682
|
+
var _ld=0;
|
|
683
|
+
function loadBgm(){if(_ld)return;_ld=1;
|
|
684
|
+
fetch('bgm.mp3').then(function(r){return r.arrayBuffer()}).then(function(a){
|
|
685
|
+
abuf=a;bURL=URL.createObjectURL(new Blob([a],{type:'audio/mpeg'}));
|
|
686
|
+
if(elemTried&&want){warmOnly=1;toWA()}
|
|
687
|
+
if(want&&!playing()){pend=0;ensure()}
|
|
688
|
+
}).catch(function(){});
|
|
689
|
+
}
|
|
690
|
+
setTimeout(loadBgm,2500);
|
|
691
|
+
document.addEventListener('pointerdown',loadBgm,true);
|
|
687
692
|
if(want){setTimeout(function(){if(!playing()&&bURL){ensure()}},400)}
|
|
688
693
|
window.__bgmFade=function(){savePos();try{if(node&&gn){var g0=gn.gain.value,t0=Date.now();var iv=setInterval(function(){var k=Math.max(0,1-(Date.now()-t0)/500);gn.gain.value=g0*k;if(k<=0)clearInterval(iv)},60)}}catch(e){}};
|
|
689
694
|
})();
|
|
@@ -2250,8 +2255,8 @@ V.ledger=function(){LG.load();LG.paint()};
|
|
|
2250
2255
|
/* ================= 战绩数据(WHALE_STATS)=================
|
|
2251
2256
|
本块由 /var/minis/shared/whale/sync_record_stats.py 从 战绩簿 自动生成。
|
|
2252
2257
|
更新流程:改 shared/whale/战绩.md → 跑 sync_record_stats.py → 本块自动重写 */
|
|
2253
|
-
/*WHALE_STATS:BEGIN —— 由 sync_record_stats.py 自动生成于 2026-09-27
|
|
2254
|
-
var WHALE_STATS={"updated":"2026-09-27","stats":[["报备次数","
|
|
2258
|
+
/*WHALE_STATS:BEGIN —— 由 sync_record_stats.py 自动生成于 2026-09-27 02:16;改数据请改 战绩.md 后重跑本脚本 */
|
|
2259
|
+
var WHALE_STATS={"updated":"2026-09-27","stats":[["报备次数","6"],["累计抽数","22,613"],["累计六星","681"],["综合出率","3.012%"],["违约","0 次"],["单发最欧","1 抽"]],"reports":[{"d":"2026-09-26","pool":"池子未确认(主人「好像半周年」)","n":"10,000","six":"288","rate":"2.88%","gap":"34.7 抽","note":"✅ 数据有效——6★ 基础率与池子无关;理论 2.889% / 34.61 抽,偏差仅 −0.009pp ✅ 后来由数字反推:2.88% 更贴近非联动池(2.889%)而非联动池(3.00%)→ 主人的直觉正确"},{"d":"2026-09-26","pool":"彩虹六号联动(井 5/120)","n":"10,000","six":"321","rate":"3.21%","gap":"31.1 抽","note":"联动池理论 ~3.02%(含 120 硬保底),+1.1σ ✓ 正常;最欧 1 抽(一发入魂);5★ 767 个 = 7.67%(理论 8%,−3.7σ ⚠️ 偏门样本或抄录误差;20 万抽对照实测 7.985%,系统无问题)"},{"d":"2026-09-26","pool":"标准寻访(模拟器一键报备)","n":"13","six":"1","rate":"7.69%","gap":"13.0 抽","note":"🍀 唯一一彩恰落第 13 抽(未触软保底,纯运气);期望 0.26~0.38 个 → +1~1.5σ 小欧;5★×2(期望 1.04)"},{"d":"2026-09-26","pool":"P3R 联动(井 15/120)","n":"600","six":"16","rate":"2.67%","gap":"36.6 抽","note":"联动池理论 ~3.02%(含 120 硬保底);期望 18.12 个 → −0.51σ 正常波动(略非);5★ 45 个 = 7.50%(理论 8%,−0.45σ);最非 66 抽(未触软保底)· 最欧 4 抽;注:16 个六星里若有 UP 需主人补报是哪位干员"},{"d":"2026-09-27","pool":"标准寻访(模拟器)","n":"1,500","six":"37","rate":"2.47%","gap":"39.1 抽","note":"标准池理论 ~2.89%(2% 基础+软保底),期望 43.3 个 → −0.97σ 正常偏非;5★ 127 个 = 8.47%(理论 8%,+0.67σ ✓);最非 70 抽(刷新最非记录,前值 66,仍未触 99 硬保底)· 最欧 2 抽(单发总记录仍是 1 抽)"},{"d":"2026-09-27","pool":"Ave Mujica 联动(井 59/120)","n":"500","six":"18","rate":"3.60%","gap":"24.5 抽","note":"联动池理论 ~3.02%(含 120 硬保底),期望 15.1 个 → +0.76σ 正常偏欧;5★ 27 个 = 5.40%(理论 8%,−2.14σ ⚠️ 五星大非号角);最非 58 抽 · 最欧 2 抽(单发总记录仍 1 抽)"},{"d":"2026-09-26","pool":"彩虹六号联动(1 亿抽大样本)","n":"100,000,000","six":"3,036,676","rate":"3.03668%","gap":"—","note":"五批 × 2000 万,共约 76 秒。保底触发 248,381 次(0.248%)。概率再分配账目精确守恒:6★ 多出 +1.03668pp = 5★ −0.0193pp + 4★ −0.13008pp + 3★ −0.8873pp"}],"mine":[{"d":"2026-09-26","pool":"Ave Mujica 联动","n":"120","got":"丰川祥子(6★)","note":"踩中 120 硬保底最后一抽"},{"d":"2026-09-26","pool":"中坚寻访","n":"550","got":"斯卡蒂(6★)","note":"无 UP 无井,纯抽;期望 1660"},{"d":"2026-09-26","pool":"周年限定","n":"70","got":"可露希尔 + 凯尔希·思衡托","note":"70 抽两个六星,全 UP 组"}]};
|
|
2255
2260
|
/*WHALE_STATS:END*/
|
|
2256
2261
|
|
|
2257
2262
|
/* ================= VIEW: RECORDS(战绩)================= */
|
|
@@ -2658,8 +2663,8 @@ document.addEventListener('pointerdown',function(){ac()},{once:true});
|
|
|
2658
2663
|
|
|
2659
2664
|
/* ================= INIT ================= */
|
|
2660
2665
|
$('#home').classList.add('on');applyCrt();
|
|
2661
|
-
['hero','crew','card','boy','fig','face','grn','taro','scene'].forEach(function(n){
|
|
2662
|
-
var i=new Image();i.src='assets/'+n+'.jpg';});
|
|
2666
|
+
setTimeout(function(){['hero','crew','card','boy','fig','face','grn','taro','scene'].forEach(function(n){
|
|
2667
|
+
var i=new Image();i.src='assets/'+n+'.jpg';});},4000);
|
|
2663
2668
|
mkDeco();buildMenu();syncRes();updTopStats();setInterval(updTopStats,5000);pulse();
|
|
2664
2669
|
requestAnimationFrame(loop);
|
|
2665
2670
|
boot();
|
|
@@ -2753,5 +2758,184 @@ boot();
|
|
|
2753
2758
|
})();
|
|
2754
2759
|
</script>
|
|
2755
2760
|
<div style="position:fixed;left:10px;bottom:5px;font-size:9px;letter-spacing:.14em;color:#4cc9ff;opacity:.5;z-index:45;font-family:ui-monospace,Menlo,monospace;pointer-events:none">BUILD v25</div>
|
|
2761
|
+
|
|
2762
|
+
<!-- ===== SYSTEM LOGIN 云存档 ===== -->
|
|
2763
|
+
<script>
|
|
2764
|
+
/* ===== SYSTEM LOGIN · 云存档同步引擎 v1 ===== */
|
|
2765
|
+
(function(){
|
|
2766
|
+
var TK=['whale.tasks.v1','minis_ledger_v1','minis_ledger_trash_v1','whale.bgm'];
|
|
2767
|
+
var BASE='https://textdb.dev/api/data/prts-acct-';
|
|
2768
|
+
var LS='whale.acct',LT='whale.sync.t';
|
|
2769
|
+
var acct=null;try{acct=JSON.parse(localStorage.getItem(LS)||'null')}catch(e){}
|
|
2770
|
+
var _si=localStorage.setItem.bind(localStorage),_app=0,pq=0,box=null,_dirty=0;
|
|
2771
|
+
|
|
2772
|
+
function sha(msg){
|
|
2773
|
+
function r(v,n){return (v>>>n)|(v<<(32-n));}
|
|
2774
|
+
var i,j,K=[],H=[0x6a09e667,0xbb67ae85,0x3c6ef372,0xa54ff53a,0x510e527f,0x9b05688c,0x1f83d9ab,0x5be0cd19],W=new Array(64),ml=msg.length*8;
|
|
2775
|
+
(function(){var p=2;function pr(x){for(var d=2;d*d<=x;d++){if(x%d===0)return false}return true;}
|
|
2776
|
+
while(K.length<64){if(pr(p)){K.push(Math.floor(Math.pow(p,1/3)*4294967296)%4294967296);}p++;}})();
|
|
2777
|
+
var b=[];
|
|
2778
|
+
for(i=0;i<msg.length;i++){var c=msg.charCodeAt(i);
|
|
2779
|
+
if(c<128)b.push(c);
|
|
2780
|
+
else if(c<2048){b.push(192|(c>>6),128|(c&63));}
|
|
2781
|
+
else{b.push(224|(c>>12),128|((c>>6)&63),128|(c&63));}}
|
|
2782
|
+
b.push(0x80);while(b.length%64!==56)b.push(0);
|
|
2783
|
+
for(i=7;i>=0;i--)b.push(Math.floor(ml/Math.pow(2,i*8))&255);
|
|
2784
|
+
for(i=0;i<b.length;i+=64){
|
|
2785
|
+
for(j=0;j<16;j++)W[j]=(b[i+j*4]<<24)|(b[i+j*4+1]<<16)|(b[i+j*4+2]<<8)|b[i+j*4+3];
|
|
2786
|
+
for(j=16;j<64;j++){var s0=r(W[j-15],7)^r(W[j-15],18)^(W[j-15]>>>3),s1=r(W[j-2],17)^r(W[j-2],19)^(W[j-2]>>>10);W[j]=(W[j-16]+s0+W[j-7]+s1)|0;}
|
|
2787
|
+
var a=H[0],bb=H[1],cc=H[2],d=H[3],e=H[4],f=H[5],g=H[6],h=H[7];
|
|
2788
|
+
for(j=0;j<64;j++){
|
|
2789
|
+
var S1=r(e,6)^r(e,11)^r(e,25),ch=(e&f)^(~e&g),t1=(h+S1+ch+K[j]+W[j])|0,
|
|
2790
|
+
S0=r(a,2)^r(a,13)^r(a,22),mj=(a&bb)^(a&cc)^(bb&cc),t2=(S0+mj)|0;
|
|
2791
|
+
h=g;g=f;f=e;e=(d+t1)|0;d=cc;cc=bb;bb=a;a=(t1+t2)|0;
|
|
2792
|
+
}
|
|
2793
|
+
H[0]=(H[0]+a)|0;H[1]=(H[1]+bb)|0;H[2]=(H[2]+cc)|0;H[3]=(H[3]+d)|0;H[4]=(H[4]+e)|0;H[5]=(H[5]+f)|0;H[6]=(H[6]+g)|0;H[7]=(H[7]+h)|0;
|
|
2794
|
+
}
|
|
2795
|
+
var o='';for(i=0;i<8;i++)o+=('00000000'+(H[i]>>>0).toString(16)).slice(-8);
|
|
2796
|
+
return o;
|
|
2797
|
+
}
|
|
2798
|
+
function snap(){var d={};for(var i=0;i<TK.length;i++){var v=localStorage.getItem(TK[i]);if(v!==null)d[TK[i]]=v;}return d;}
|
|
2799
|
+
function url(){return BASE+acct.k;}
|
|
2800
|
+
function st(m){if(box&&box.st)box.st.textContent=m;}
|
|
2801
|
+
function clock(){var d=new Date();function p(n){return(n<10?'0':'')+n}return p(d.getHours())+':'+p(d.getMinutes());}
|
|
2802
|
+
function apply(rb){
|
|
2803
|
+
_app=1;try{for(var k in rb.data){_si(k,rb.data[k]);}}finally{_app=0;}
|
|
2804
|
+
_si(LT,String(rb.t||Date.now()));
|
|
2805
|
+
st('✔ 已从云端同步 '+clock()+',即将刷新…');
|
|
2806
|
+
setTimeout(function(){location.reload();},800);
|
|
2807
|
+
}
|
|
2808
|
+
function push(){
|
|
2809
|
+
if(!acct||!acct.k)return;
|
|
2810
|
+
_dirty=0;var t=Date.now();_si(LT,String(t));
|
|
2811
|
+
st('↻ 同步中…');
|
|
2812
|
+
fetch(url(),{method:'POST',mode:'no-cors',body:JSON.stringify({v:1,u:acct.u,t:t,data:snap()})})
|
|
2813
|
+
.then(function(){setTimeout(function(){verify(t)},1800);})
|
|
2814
|
+
.catch(function(){st('⚠ 云同步暂不可用(可用存档码手动搬)');});
|
|
2815
|
+
}
|
|
2816
|
+
function verify(t){
|
|
2817
|
+
fetch(url()+'?ts='+Date.now()).then(function(r){return r.text()}).then(function(x){
|
|
2818
|
+
x=(x||'').replace(/=$/,'');
|
|
2819
|
+
try{var rb=JSON.parse(x);if(rb.t===t){st('✔ 已同步 '+clock());return;}}catch(e){}
|
|
2820
|
+
if(!window.__pv){window.__pv=1;setTimeout(function(){window.__pv=0;push();},1500);}
|
|
2821
|
+
else{st('⚠ 云端回读不一致,稍后自动重试');}
|
|
2822
|
+
}).catch(function(){st('⚠ 校验失败(可能网络受限)');});
|
|
2823
|
+
}
|
|
2824
|
+
function pull(manual){
|
|
2825
|
+
if(!acct||!acct.k)return;
|
|
2826
|
+
fetch(url()+'?ts='+Date.now()).then(function(r){return r.text()}).then(function(x){
|
|
2827
|
+
x=(x||'').replace(/=$/,'');
|
|
2828
|
+
if(!x){if(manual)st('☁ 云端暂时没有存档——点「立即同步」上传本机数据');return;}
|
|
2829
|
+
var rb;try{rb=JSON.parse(x)}catch(e){st('⚠ 云端数据格式异常');return;}
|
|
2830
|
+
var lt=Number(localStorage.getItem(LT)||0);
|
|
2831
|
+
if((rb.t||0)>lt){
|
|
2832
|
+
var same=1;for(var kk in rb.data){if(localStorage.getItem(kk)!==rb.data[kk]){same=0;break;}}
|
|
2833
|
+
if(same){_si(LT,String(rb.t));if(manual)st('✔ 已是最新 '+clock());}
|
|
2834
|
+
else{apply(rb);}
|
|
2835
|
+
}
|
|
2836
|
+
else if(manual){
|
|
2837
|
+
var same2=1;for(var k2 in rb.data){if(localStorage.getItem(k2)!==rb.data[k2]){same2=0;break;}}
|
|
2838
|
+
if(same2){st('✔ 已是最新 '+clock());}else{push();}
|
|
2839
|
+
}
|
|
2840
|
+
else{st('✔ 已是云端最新');}
|
|
2841
|
+
}).catch(function(){st('⚠ 云端连接失败');});
|
|
2842
|
+
}
|
|
2843
|
+
function logout(){localStorage.removeItem(LS);acct=null;}
|
|
2844
|
+
var CSS='.acWrap{position:fixed;inset:0;z-index:9998;background:rgba(3,6,14,.66);display:none;align-items:center;justify-content:center}.acWrap.on{display:flex}'+
|
|
2845
|
+
'.acBox{width:min(86vw,360px);max-height:86vh;overflow:auto;background:rgba(7,12,24,.97);border:2px solid #4cc9ff;box-shadow:6px 6px 0 rgba(18,115,200,.45);padding:16px;font-family:ui-monospace,Menlo,monospace;color:#eef7ff}'+
|
|
2846
|
+
'.acBox h3{margin:0 0 4px;font-size:15px;letter-spacing:.12em;color:#8fe0ff}.acBox .sub{font-size:10px;opacity:.65;margin-bottom:10px}'+
|
|
2847
|
+
'.acBox input{width:100%;box-sizing:border-box;background:#0a1322;border:1.5px solid #2b4a66;color:#eef7ff;font-family:inherit;font-size:13px;padding:8px;margin:5px 0}'+
|
|
2848
|
+
'.acBox button{background:#0a1322;border:1.5px solid #4cc9ff;color:#4cc9ff;font-family:inherit;font-size:12px;padding:7px 10px;margin:6px 6px 0 0;cursor:pointer;letter-spacing:.08em}'+
|
|
2849
|
+
'.acBox button.pri{background:#4cc9ff;color:#06121f;font-weight:700}'+
|
|
2850
|
+
'.acBox .st{font-size:11px;margin-top:10px;min-height:14px;color:#9fe9a0;line-height:1.5;word-break:break-all}'+
|
|
2851
|
+
'.acBox textarea{width:100%;box-sizing:border-box;height:70px;background:#0a1322;border:1.5px solid #2b4a66;color:#9fd8ff;font-size:10px;font-family:inherit;margin-top:8px;display:none}'+
|
|
2852
|
+
'.acBox textarea.on{display:block}';
|
|
2853
|
+
var sEl=document.createElement('style');sEl.textContent=CSS;document.head.appendChild(sEl);
|
|
2854
|
+
var wrap=document.createElement('div');wrap.className='acWrap';document.body.appendChild(wrap);
|
|
2855
|
+
function esc(s){return String(s).replace(/[<>&"]/g,function(c){return{'<':'<','>':'>','&':'&','"':'"'}[c]})}
|
|
2856
|
+
function render(){
|
|
2857
|
+
var h='<div class="acBox"><h3>SYSTEM LOGIN · 云存档</h3><div class="sub">同一账号 · 多设备同步(鱼干/任务/券/小账本)</div>';
|
|
2858
|
+
if(acct){
|
|
2859
|
+
h+='<div style="font-size:12px;margin:6px 0 2px">当前账号:<b style="color:#ffd23f">'+esc(acct.u)+'</b></div>'+
|
|
2860
|
+
'<button class="pri" id="acSync">↻ 立即同步</button><button id="acOut">退出登录</button>';
|
|
2861
|
+
}else{
|
|
2862
|
+
h+='<input id="acU" placeholder="用户名(自己起,例如 yanliang27)" autocomplete="username">'+
|
|
2863
|
+
'<input id="acP" type="password" placeholder="密码(≥4位,丢了找不回!)" autocomplete="current-password">'+
|
|
2864
|
+
'<button class="pri" id="acGo">登录 / 创建</button>';
|
|
2865
|
+
}
|
|
2866
|
+
h+='<button id="acExp">📤 存档码</button><button id="acImp">📥 导入</button>'+
|
|
2867
|
+
'<div class="st" id="acSt"></div><textarea id="acTa" spellcheck="false"></textarea>'+
|
|
2868
|
+
'<div style="font-size:10px;opacity:.5;margin-top:9px;line-height:1.5">密钥由「用户名+密码」派生;同一账号在任意设备登录即接回数据。忘记密码=新仓库(旧数据找不回)</div>'+
|
|
2869
|
+
'<button id="acX" style="border-color:#2b4a66;color:#8ea6bf;margin-top:10px">关闭 / CLOSE</button></div>';
|
|
2870
|
+
wrap.innerHTML=h;
|
|
2871
|
+
box={st:wrap.querySelector('#acSt'),ta:wrap.querySelector('#acTa')};
|
|
2872
|
+
bind();
|
|
2873
|
+
}
|
|
2874
|
+
function bind(){
|
|
2875
|
+
var g=function(id){return wrap.querySelector(id)};
|
|
2876
|
+
var go=g('#acGo');
|
|
2877
|
+
if(go)go.onclick=function(){
|
|
2878
|
+
var b=go,u=(g('#acU').value||'').trim(),p=g('#acP').value||'';
|
|
2879
|
+
if(u.length<2||p.length<4){st('用户名≥2位、密码≥4位哦');return;}
|
|
2880
|
+
var k=sha('prts-moonlit|'+u+'|'+p);
|
|
2881
|
+
if(b.getAttribute('data-mode')==='create'){
|
|
2882
|
+
acct={u:u,k:k};_si(LS,JSON.stringify(acct));_si(LT,String(Date.now()));
|
|
2883
|
+
st('✦ 仓库已创建,正在上传本机数据…');render();push();return;
|
|
2884
|
+
}
|
|
2885
|
+
st('↻ 查找云端仓库…');
|
|
2886
|
+
fetch(BASE+k+'?ts='+Date.now()).then(function(r){return r.text()}).then(function(x){
|
|
2887
|
+
x=(x||'').replace(/=$/,'');
|
|
2888
|
+
if(x&&x.length>2){
|
|
2889
|
+
acct={u:u,k:k};_si(LS,JSON.stringify(acct));
|
|
2890
|
+
var rb=null;try{rb=JSON.parse(x)}catch(e){}
|
|
2891
|
+
if(rb&&(rb.t||0)>Number(localStorage.getItem(LT)||0)){apply(rb);}
|
|
2892
|
+
else{_si(LT,String((rb&&rb.t)||Date.now()));st('✔ 已登录,云端仓库已连接 '+clock());render();}
|
|
2893
|
+
}else{
|
|
2894
|
+
b.setAttribute('data-mode','create');b.textContent='✦ 没找到仓库——点此以本机数据创建';
|
|
2895
|
+
st('(如果是新账号,创建后本机数据会上传成初始存档)');
|
|
2896
|
+
}
|
|
2897
|
+
}).catch(function(){st('⚠ 云端连接失败,稍后再试');});
|
|
2898
|
+
};
|
|
2899
|
+
var sy=g('#acSync');if(sy)sy.onclick=function(){pull(true)};
|
|
2900
|
+
var o=g('#acOut');if(o)o.onclick=function(){
|
|
2901
|
+
if(o.getAttribute('data-c')){logout();st('已退出登录(本机数据保留)');render();}
|
|
2902
|
+
else{o.setAttribute('data-c','1');o.textContent='⚠ 再点一次 = 退出登录';}};
|
|
2903
|
+
var e1=g('#acExp');if(e1)e1.onclick=function(){
|
|
2904
|
+
var b=JSON.stringify({v:1,u:acct?acct.u:'anon',t:Date.now(),data:snap()});
|
|
2905
|
+
var ta=g('#acTa');ta.classList.add('on');
|
|
2906
|
+
ta.value=btoa(unescape(encodeURIComponent(b)));ta.select();
|
|
2907
|
+
st('已生成存档码——全选复制保存,换设备时用「导入」');};
|
|
2908
|
+
var i1=g('#acImp');if(i1)i1.onclick=function(){
|
|
2909
|
+
var ta=g('#acTa');ta.classList.add('on');
|
|
2910
|
+
if(i1.getAttribute('data-c')){
|
|
2911
|
+
var v=ta.value.trim();
|
|
2912
|
+
if(!v){st('先把存档码粘到下面框里');return;}
|
|
2913
|
+
try{var rb=JSON.parse(decodeURIComponent(escape(atob(v))));apply(rb);}
|
|
2914
|
+
catch(e){st('⚠ 存档码无效');}
|
|
2915
|
+
return;}
|
|
2916
|
+
i1.setAttribute('data-c','1');ta.value='';
|
|
2917
|
+
st('把另一台设备的存档码粘到下方,再点一次「导入」');};
|
|
2918
|
+
var x=g('#acX');if(x)x.onclick=function(){wrap.classList.remove('on')};
|
|
2919
|
+
wrap.onclick=function(e){if(e.target===wrap)wrap.classList.remove('on')};
|
|
2920
|
+
}
|
|
2921
|
+
function open(){render();wrap.classList.add('on')}
|
|
2922
|
+
var _orig=localStorage.setItem;
|
|
2923
|
+
localStorage.setItem=function(k,v){_orig.call(localStorage,k,v);if(!_app&&acct&&acct.k&&TK.indexOf(k)>=0&&k!==LT){_dirty=1;clearTimeout(pq);pq=setTimeout(push,2200);}};
|
|
2924
|
+
window.addEventListener('pagehide',function(){
|
|
2925
|
+
if(acct&&acct.k&&_dirty){try{_dirty=0;_si(LT,String(Date.now()));
|
|
2926
|
+
fetch(url(),{method:'POST',mode:'no-cors',keepalive:true,body:JSON.stringify({v:1,u:acct.u,t:Date.now(),data:snap()})});}catch(e){}}
|
|
2927
|
+
});
|
|
2928
|
+
document.addEventListener('visibilitychange',function(){if(!document.hidden&&acct&&acct.k){pull(false);}});
|
|
2929
|
+
var btn=document.createElement('div');
|
|
2930
|
+
var ci=document.querySelector('.corner-ics');
|
|
2931
|
+
if(ci){btn.className='ci';btn.textContent='@';ci.appendChild(btn);}
|
|
2932
|
+
else{btn.textContent='@';btn.style.cssText='position:fixed;right:14px;bottom:60px;z-index:120;width:38px;height:38px;display:flex;align-items:center;justify-content:center;border:2px solid #4cc9ff;background:rgba(7,12,24,.92);color:#4cc9ff;font-size:17px;cursor:pointer;user-select:none;box-shadow:3px 3px 0 rgba(0,0,0,.45)';document.body.appendChild(btn);}
|
|
2933
|
+
btn.id='acctBtn';btn.title='云存档';
|
|
2934
|
+
if(acct)btn.style.background='rgba(76,201,255,.28)';
|
|
2935
|
+
btn.addEventListener('click',open);
|
|
2936
|
+
if(acct&&acct.k){setTimeout(function(){pull(false);},1600);}
|
|
2937
|
+
window.__shaT=sha;
|
|
2938
|
+
})();
|
|
2939
|
+
</script>
|
|
2756
2940
|
</body>
|
|
2757
2941
|
</html>
|
package/ledger.html
CHANGED
|
@@ -793,7 +793,7 @@ window.LEDGER_BACKUP = [];
|
|
|
793
793
|
function goHome() {
|
|
794
794
|
try{window.__bgmFade&&window.__bgmFade()}catch(e){}
|
|
795
795
|
var p = location.pathname || '';
|
|
796
|
-
var u = 'index.html';
|
|
796
|
+
var u = /\/akp3\//.test(p) ? 'index.html' : 'index.html';
|
|
797
797
|
setTimeout(function () { location.href = u; }, 380);
|
|
798
798
|
}
|
|
799
799
|
|
|
@@ -990,14 +990,198 @@ window.LEDGER_BACKUP = [];
|
|
|
990
990
|
function kick(){if(ctx&&ctx.state!=='running'&&ctx.resume){try{ctx.resume()}catch(e){}}if(!want||playing())return;if(bURL)ensure();else pend=1}
|
|
991
991
|
document.addEventListener('pointerdown',kick,true);
|
|
992
992
|
au.addEventListener('playing',function(){document.removeEventListener('pointerdown',kick,true)});
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
993
|
+
var _ld=0;
|
|
994
|
+
function loadBgm(){if(_ld)return;_ld=1;
|
|
995
|
+
fetch('bgm.mp3').then(function(r){return r.arrayBuffer()}).then(function(a){
|
|
996
|
+
abuf=a;bURL=URL.createObjectURL(new Blob([a],{type:'audio/mpeg'}));
|
|
997
|
+
if(elemTried&&want){warmOnly=1;toWA()}
|
|
998
|
+
if(want&&!playing()){pend=0;ensure()}
|
|
999
|
+
}).catch(function(){});
|
|
1000
|
+
}
|
|
1001
|
+
setTimeout(loadBgm,2500);
|
|
1002
|
+
document.addEventListener('pointerdown',loadBgm,true);
|
|
998
1003
|
if(want){setTimeout(function(){if(!playing()&&bURL){ensure()}},400)}
|
|
999
1004
|
window.__bgmFade=function(){savePos();try{if(node&&gn){var g0=gn.gain.value,t0=Date.now();var iv=setInterval(function(){var k=Math.max(0,1-(Date.now()-t0)/500);gn.gain.value=g0*k;if(k<=0)clearInterval(iv)},60)}}catch(e){}};
|
|
1000
1005
|
})();
|
|
1001
1006
|
</script>
|
|
1007
|
+
|
|
1008
|
+
<!-- ===== SYSTEM LOGIN 云存档 ===== -->
|
|
1009
|
+
<script>
|
|
1010
|
+
/* ===== SYSTEM LOGIN · 云存档同步引擎 v1 ===== */
|
|
1011
|
+
(function(){
|
|
1012
|
+
var TK=['whale.tasks.v1','minis_ledger_v1','minis_ledger_trash_v1','whale.bgm'];
|
|
1013
|
+
var BASE='https://textdb.dev/api/data/prts-acct-';
|
|
1014
|
+
var LS='whale.acct',LT='whale.sync.t';
|
|
1015
|
+
var acct=null;try{acct=JSON.parse(localStorage.getItem(LS)||'null')}catch(e){}
|
|
1016
|
+
var _si=localStorage.setItem.bind(localStorage),_app=0,pq=0,box=null,_dirty=0;
|
|
1017
|
+
|
|
1018
|
+
function sha(msg){
|
|
1019
|
+
function r(v,n){return (v>>>n)|(v<<(32-n));}
|
|
1020
|
+
var i,j,K=[],H=[0x6a09e667,0xbb67ae85,0x3c6ef372,0xa54ff53a,0x510e527f,0x9b05688c,0x1f83d9ab,0x5be0cd19],W=new Array(64),ml=msg.length*8;
|
|
1021
|
+
(function(){var p=2;function pr(x){for(var d=2;d*d<=x;d++){if(x%d===0)return false}return true;}
|
|
1022
|
+
while(K.length<64){if(pr(p)){K.push(Math.floor(Math.pow(p,1/3)*4294967296)%4294967296);}p++;}})();
|
|
1023
|
+
var b=[];
|
|
1024
|
+
for(i=0;i<msg.length;i++){var c=msg.charCodeAt(i);
|
|
1025
|
+
if(c<128)b.push(c);
|
|
1026
|
+
else if(c<2048){b.push(192|(c>>6),128|(c&63));}
|
|
1027
|
+
else{b.push(224|(c>>12),128|((c>>6)&63),128|(c&63));}}
|
|
1028
|
+
b.push(0x80);while(b.length%64!==56)b.push(0);
|
|
1029
|
+
for(i=7;i>=0;i--)b.push(Math.floor(ml/Math.pow(2,i*8))&255);
|
|
1030
|
+
for(i=0;i<b.length;i+=64){
|
|
1031
|
+
for(j=0;j<16;j++)W[j]=(b[i+j*4]<<24)|(b[i+j*4+1]<<16)|(b[i+j*4+2]<<8)|b[i+j*4+3];
|
|
1032
|
+
for(j=16;j<64;j++){var s0=r(W[j-15],7)^r(W[j-15],18)^(W[j-15]>>>3),s1=r(W[j-2],17)^r(W[j-2],19)^(W[j-2]>>>10);W[j]=(W[j-16]+s0+W[j-7]+s1)|0;}
|
|
1033
|
+
var a=H[0],bb=H[1],cc=H[2],d=H[3],e=H[4],f=H[5],g=H[6],h=H[7];
|
|
1034
|
+
for(j=0;j<64;j++){
|
|
1035
|
+
var S1=r(e,6)^r(e,11)^r(e,25),ch=(e&f)^(~e&g),t1=(h+S1+ch+K[j]+W[j])|0,
|
|
1036
|
+
S0=r(a,2)^r(a,13)^r(a,22),mj=(a&bb)^(a&cc)^(bb&cc),t2=(S0+mj)|0;
|
|
1037
|
+
h=g;g=f;f=e;e=(d+t1)|0;d=cc;cc=bb;bb=a;a=(t1+t2)|0;
|
|
1038
|
+
}
|
|
1039
|
+
H[0]=(H[0]+a)|0;H[1]=(H[1]+bb)|0;H[2]=(H[2]+cc)|0;H[3]=(H[3]+d)|0;H[4]=(H[4]+e)|0;H[5]=(H[5]+f)|0;H[6]=(H[6]+g)|0;H[7]=(H[7]+h)|0;
|
|
1040
|
+
}
|
|
1041
|
+
var o='';for(i=0;i<8;i++)o+=('00000000'+(H[i]>>>0).toString(16)).slice(-8);
|
|
1042
|
+
return o;
|
|
1043
|
+
}
|
|
1044
|
+
function snap(){var d={};for(var i=0;i<TK.length;i++){var v=localStorage.getItem(TK[i]);if(v!==null)d[TK[i]]=v;}return d;}
|
|
1045
|
+
function url(){return BASE+acct.k;}
|
|
1046
|
+
function st(m){if(box&&box.st)box.st.textContent=m;}
|
|
1047
|
+
function clock(){var d=new Date();function p(n){return(n<10?'0':'')+n}return p(d.getHours())+':'+p(d.getMinutes());}
|
|
1048
|
+
function apply(rb){
|
|
1049
|
+
_app=1;try{for(var k in rb.data){_si(k,rb.data[k]);}}finally{_app=0;}
|
|
1050
|
+
_si(LT,String(rb.t||Date.now()));
|
|
1051
|
+
st('✔ 已从云端同步 '+clock()+',即将刷新…');
|
|
1052
|
+
setTimeout(function(){location.reload();},800);
|
|
1053
|
+
}
|
|
1054
|
+
function push(){
|
|
1055
|
+
if(!acct||!acct.k)return;
|
|
1056
|
+
_dirty=0;var t=Date.now();_si(LT,String(t));
|
|
1057
|
+
st('↻ 同步中…');
|
|
1058
|
+
fetch(url(),{method:'POST',mode:'no-cors',body:JSON.stringify({v:1,u:acct.u,t:t,data:snap()})})
|
|
1059
|
+
.then(function(){setTimeout(function(){verify(t)},1800);})
|
|
1060
|
+
.catch(function(){st('⚠ 云同步暂不可用(可用存档码手动搬)');});
|
|
1061
|
+
}
|
|
1062
|
+
function verify(t){
|
|
1063
|
+
fetch(url()+'?ts='+Date.now()).then(function(r){return r.text()}).then(function(x){
|
|
1064
|
+
x=(x||'').replace(/=$/,'');
|
|
1065
|
+
try{var rb=JSON.parse(x);if(rb.t===t){st('✔ 已同步 '+clock());return;}}catch(e){}
|
|
1066
|
+
if(!window.__pv){window.__pv=1;setTimeout(function(){window.__pv=0;push();},1500);}
|
|
1067
|
+
else{st('⚠ 云端回读不一致,稍后自动重试');}
|
|
1068
|
+
}).catch(function(){st('⚠ 校验失败(可能网络受限)');});
|
|
1069
|
+
}
|
|
1070
|
+
function pull(manual){
|
|
1071
|
+
if(!acct||!acct.k)return;
|
|
1072
|
+
fetch(url()+'?ts='+Date.now()).then(function(r){return r.text()}).then(function(x){
|
|
1073
|
+
x=(x||'').replace(/=$/,'');
|
|
1074
|
+
if(!x){if(manual)st('☁ 云端暂时没有存档——点「立即同步」上传本机数据');return;}
|
|
1075
|
+
var rb;try{rb=JSON.parse(x)}catch(e){st('⚠ 云端数据格式异常');return;}
|
|
1076
|
+
var lt=Number(localStorage.getItem(LT)||0);
|
|
1077
|
+
if((rb.t||0)>lt){
|
|
1078
|
+
var same=1;for(var kk in rb.data){if(localStorage.getItem(kk)!==rb.data[kk]){same=0;break;}}
|
|
1079
|
+
if(same){_si(LT,String(rb.t));if(manual)st('✔ 已是最新 '+clock());}
|
|
1080
|
+
else{apply(rb);}
|
|
1081
|
+
}
|
|
1082
|
+
else if(manual){
|
|
1083
|
+
var same2=1;for(var k2 in rb.data){if(localStorage.getItem(k2)!==rb.data[k2]){same2=0;break;}}
|
|
1084
|
+
if(same2){st('✔ 已是最新 '+clock());}else{push();}
|
|
1085
|
+
}
|
|
1086
|
+
else{st('✔ 已是云端最新');}
|
|
1087
|
+
}).catch(function(){st('⚠ 云端连接失败');});
|
|
1088
|
+
}
|
|
1089
|
+
function logout(){localStorage.removeItem(LS);acct=null;}
|
|
1090
|
+
var CSS='.acWrap{position:fixed;inset:0;z-index:9998;background:rgba(3,6,14,.66);display:none;align-items:center;justify-content:center}.acWrap.on{display:flex}'+
|
|
1091
|
+
'.acBox{width:min(86vw,360px);max-height:86vh;overflow:auto;background:rgba(7,12,24,.97);border:2px solid #4cc9ff;box-shadow:6px 6px 0 rgba(18,115,200,.45);padding:16px;font-family:ui-monospace,Menlo,monospace;color:#eef7ff}'+
|
|
1092
|
+
'.acBox h3{margin:0 0 4px;font-size:15px;letter-spacing:.12em;color:#8fe0ff}.acBox .sub{font-size:10px;opacity:.65;margin-bottom:10px}'+
|
|
1093
|
+
'.acBox input{width:100%;box-sizing:border-box;background:#0a1322;border:1.5px solid #2b4a66;color:#eef7ff;font-family:inherit;font-size:13px;padding:8px;margin:5px 0}'+
|
|
1094
|
+
'.acBox button{background:#0a1322;border:1.5px solid #4cc9ff;color:#4cc9ff;font-family:inherit;font-size:12px;padding:7px 10px;margin:6px 6px 0 0;cursor:pointer;letter-spacing:.08em}'+
|
|
1095
|
+
'.acBox button.pri{background:#4cc9ff;color:#06121f;font-weight:700}'+
|
|
1096
|
+
'.acBox .st{font-size:11px;margin-top:10px;min-height:14px;color:#9fe9a0;line-height:1.5;word-break:break-all}'+
|
|
1097
|
+
'.acBox textarea{width:100%;box-sizing:border-box;height:70px;background:#0a1322;border:1.5px solid #2b4a66;color:#9fd8ff;font-size:10px;font-family:inherit;margin-top:8px;display:none}'+
|
|
1098
|
+
'.acBox textarea.on{display:block}';
|
|
1099
|
+
var sEl=document.createElement('style');sEl.textContent=CSS;document.head.appendChild(sEl);
|
|
1100
|
+
var wrap=document.createElement('div');wrap.className='acWrap';document.body.appendChild(wrap);
|
|
1101
|
+
function esc(s){return String(s).replace(/[<>&"]/g,function(c){return{'<':'<','>':'>','&':'&','"':'"'}[c]})}
|
|
1102
|
+
function render(){
|
|
1103
|
+
var h='<div class="acBox"><h3>SYSTEM LOGIN · 云存档</h3><div class="sub">同一账号 · 多设备同步(鱼干/任务/券/小账本)</div>';
|
|
1104
|
+
if(acct){
|
|
1105
|
+
h+='<div style="font-size:12px;margin:6px 0 2px">当前账号:<b style="color:#ffd23f">'+esc(acct.u)+'</b></div>'+
|
|
1106
|
+
'<button class="pri" id="acSync">↻ 立即同步</button><button id="acOut">退出登录</button>';
|
|
1107
|
+
}else{
|
|
1108
|
+
h+='<input id="acU" placeholder="用户名(自己起,例如 yanliang27)" autocomplete="username">'+
|
|
1109
|
+
'<input id="acP" type="password" placeholder="密码(≥4位,丢了找不回!)" autocomplete="current-password">'+
|
|
1110
|
+
'<button class="pri" id="acGo">登录 / 创建</button>';
|
|
1111
|
+
}
|
|
1112
|
+
h+='<button id="acExp">📤 存档码</button><button id="acImp">📥 导入</button>'+
|
|
1113
|
+
'<div class="st" id="acSt"></div><textarea id="acTa" spellcheck="false"></textarea>'+
|
|
1114
|
+
'<div style="font-size:10px;opacity:.5;margin-top:9px;line-height:1.5">密钥由「用户名+密码」派生;同一账号在任意设备登录即接回数据。忘记密码=新仓库(旧数据找不回)</div>'+
|
|
1115
|
+
'<button id="acX" style="border-color:#2b4a66;color:#8ea6bf;margin-top:10px">关闭 / CLOSE</button></div>';
|
|
1116
|
+
wrap.innerHTML=h;
|
|
1117
|
+
box={st:wrap.querySelector('#acSt'),ta:wrap.querySelector('#acTa')};
|
|
1118
|
+
bind();
|
|
1119
|
+
}
|
|
1120
|
+
function bind(){
|
|
1121
|
+
var g=function(id){return wrap.querySelector(id)};
|
|
1122
|
+
var go=g('#acGo');
|
|
1123
|
+
if(go)go.onclick=function(){
|
|
1124
|
+
var b=go,u=(g('#acU').value||'').trim(),p=g('#acP').value||'';
|
|
1125
|
+
if(u.length<2||p.length<4){st('用户名≥2位、密码≥4位哦');return;}
|
|
1126
|
+
var k=sha('prts-moonlit|'+u+'|'+p);
|
|
1127
|
+
if(b.getAttribute('data-mode')==='create'){
|
|
1128
|
+
acct={u:u,k:k};_si(LS,JSON.stringify(acct));_si(LT,String(Date.now()));
|
|
1129
|
+
st('✦ 仓库已创建,正在上传本机数据…');render();push();return;
|
|
1130
|
+
}
|
|
1131
|
+
st('↻ 查找云端仓库…');
|
|
1132
|
+
fetch(BASE+k+'?ts='+Date.now()).then(function(r){return r.text()}).then(function(x){
|
|
1133
|
+
x=(x||'').replace(/=$/,'');
|
|
1134
|
+
if(x&&x.length>2){
|
|
1135
|
+
acct={u:u,k:k};_si(LS,JSON.stringify(acct));
|
|
1136
|
+
var rb=null;try{rb=JSON.parse(x)}catch(e){}
|
|
1137
|
+
if(rb&&(rb.t||0)>Number(localStorage.getItem(LT)||0)){apply(rb);}
|
|
1138
|
+
else{_si(LT,String((rb&&rb.t)||Date.now()));st('✔ 已登录,云端仓库已连接 '+clock());render();}
|
|
1139
|
+
}else{
|
|
1140
|
+
b.setAttribute('data-mode','create');b.textContent='✦ 没找到仓库——点此以本机数据创建';
|
|
1141
|
+
st('(如果是新账号,创建后本机数据会上传成初始存档)');
|
|
1142
|
+
}
|
|
1143
|
+
}).catch(function(){st('⚠ 云端连接失败,稍后再试');});
|
|
1144
|
+
};
|
|
1145
|
+
var sy=g('#acSync');if(sy)sy.onclick=function(){pull(true)};
|
|
1146
|
+
var o=g('#acOut');if(o)o.onclick=function(){
|
|
1147
|
+
if(o.getAttribute('data-c')){logout();st('已退出登录(本机数据保留)');render();}
|
|
1148
|
+
else{o.setAttribute('data-c','1');o.textContent='⚠ 再点一次 = 退出登录';}};
|
|
1149
|
+
var e1=g('#acExp');if(e1)e1.onclick=function(){
|
|
1150
|
+
var b=JSON.stringify({v:1,u:acct?acct.u:'anon',t:Date.now(),data:snap()});
|
|
1151
|
+
var ta=g('#acTa');ta.classList.add('on');
|
|
1152
|
+
ta.value=btoa(unescape(encodeURIComponent(b)));ta.select();
|
|
1153
|
+
st('已生成存档码——全选复制保存,换设备时用「导入」');};
|
|
1154
|
+
var i1=g('#acImp');if(i1)i1.onclick=function(){
|
|
1155
|
+
var ta=g('#acTa');ta.classList.add('on');
|
|
1156
|
+
if(i1.getAttribute('data-c')){
|
|
1157
|
+
var v=ta.value.trim();
|
|
1158
|
+
if(!v){st('先把存档码粘到下面框里');return;}
|
|
1159
|
+
try{var rb=JSON.parse(decodeURIComponent(escape(atob(v))));apply(rb);}
|
|
1160
|
+
catch(e){st('⚠ 存档码无效');}
|
|
1161
|
+
return;}
|
|
1162
|
+
i1.setAttribute('data-c','1');ta.value='';
|
|
1163
|
+
st('把另一台设备的存档码粘到下方,再点一次「导入」');};
|
|
1164
|
+
var x=g('#acX');if(x)x.onclick=function(){wrap.classList.remove('on')};
|
|
1165
|
+
wrap.onclick=function(e){if(e.target===wrap)wrap.classList.remove('on')};
|
|
1166
|
+
}
|
|
1167
|
+
function open(){render();wrap.classList.add('on')}
|
|
1168
|
+
var _orig=localStorage.setItem;
|
|
1169
|
+
localStorage.setItem=function(k,v){_orig.call(localStorage,k,v);if(!_app&&acct&&acct.k&&TK.indexOf(k)>=0&&k!==LT){_dirty=1;clearTimeout(pq);pq=setTimeout(push,2200);}};
|
|
1170
|
+
window.addEventListener('pagehide',function(){
|
|
1171
|
+
if(acct&&acct.k&&_dirty){try{_dirty=0;_si(LT,String(Date.now()));
|
|
1172
|
+
fetch(url(),{method:'POST',mode:'no-cors',keepalive:true,body:JSON.stringify({v:1,u:acct.u,t:Date.now(),data:snap()})});}catch(e){}}
|
|
1173
|
+
});
|
|
1174
|
+
document.addEventListener('visibilitychange',function(){if(!document.hidden&&acct&&acct.k){pull(false);}});
|
|
1175
|
+
var btn=document.createElement('div');
|
|
1176
|
+
var ci=document.querySelector('.corner-ics');
|
|
1177
|
+
if(ci){btn.className='ci';btn.textContent='@';ci.appendChild(btn);}
|
|
1178
|
+
else{btn.textContent='@';btn.style.cssText='position:fixed;right:14px;bottom:60px;z-index:120;width:38px;height:38px;display:flex;align-items:center;justify-content:center;border:2px solid #4cc9ff;background:rgba(7,12,24,.92);color:#4cc9ff;font-size:17px;cursor:pointer;user-select:none;box-shadow:3px 3px 0 rgba(0,0,0,.45)';document.body.appendChild(btn);}
|
|
1179
|
+
btn.id='acctBtn';btn.title='云存档';
|
|
1180
|
+
if(acct)btn.style.background='rgba(76,201,255,.28)';
|
|
1181
|
+
btn.addEventListener('click',open);
|
|
1182
|
+
if(acct&&acct.k){setTimeout(function(){pull(false);},1600);}
|
|
1183
|
+
window.__shaT=sha;
|
|
1184
|
+
})();
|
|
1185
|
+
</script>
|
|
1002
1186
|
</body>
|
|
1003
1187
|
</html>
|
package/package.json
CHANGED