prts-moonlit 1.0.4 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/gacha.html CHANGED
@@ -1049,8 +1049,8 @@ document.addEventListener('pointerdown',function(){ac()},{once:true});
1049
1049
  <script>
1050
1050
  /* ===== SYSTEM LOGIN · 云存档同步引擎 v1 ===== */
1051
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-';
1052
+ var TK=['whale.tasks.v1','minis_ledger_v1','minis_ledger_trash_v1','whale.bgm','whale.taro.v1'];
1053
+ var BASE='https://textdb.dev/api/data/prts-acct-';var ADMIN_K='e74aeb1a34c44f2fcefd1f19bb34c3891a4963f36242e5a5fd3869085892a711';
1054
1054
  var LS='whale.acct',LT='whale.sync.t';
1055
1055
  var acct=null;try{acct=JSON.parse(localStorage.getItem(LS)||'null')}catch(e){}
1056
1056
  var _si=localStorage.setItem.bind(localStorage),_app=0,pq=0,box=null,_dirty=0,lastSnap=null;
@@ -1087,6 +1087,7 @@ document.addEventListener('pointerdown',function(){ac()},{once:true});
1087
1087
  function canon(){var a=[];for(var i=0;i<TK.length;i++)a.push(TK[i]+'='+localStorage.getItem(TK[i]));return a.join('|');}
1088
1088
  function st(m){if(box&&box.st)box.st.textContent=m;}
1089
1089
  function clock(){var d=new Date();function p(n){return(n<10?'0':'')+n}return p(d.getHours())+':'+p(d.getMinutes())+':'+p(d.getSeconds());}
1090
+ function updLv(){var n=document.getElementById('pfName'),l=document.getElementById('pfLv');if(n)n.textContent=acct?acct.u:'临时用户';if(l){if(acct&&!acct.c){acct.c=Date.now();_si(LS,JSON.stringify(acct));}l.textContent=String(acct?(1+Math.floor((Date.now()-(acct.c||Date.now()))/86400000)):0);}}
1090
1091
  function apply(rb){
1091
1092
  _app=1;try{for(var k in rb.data){_si(k,rb.data[k]);}}finally{_app=0;}
1092
1093
  _si(LT,String(rb.t||Date.now()));lastSnap=canon();
@@ -1098,7 +1099,7 @@ document.addEventListener('pointerdown',function(){ac()},{once:true});
1098
1099
  if(!ry)window.__pv=0;
1099
1100
  _dirty=0;var t=Date.now();_si(LT,String(t));lastSnap=canon();
1100
1101
  st('↻ 同步中…');
1101
- wxhr(url(),JSON.stringify({v:1,u:acct.u,t:t,data:snap()}),function(){st('✔ 已上传 · 后台校验…');setTimeout(function(){verify(t)},600);});
1102
+ wxhr(url(),JSON.stringify({v:1,u:acct.u,c:acct.c||0,t:t,data:snap()}),function(){st('✔ 已上传 · 后台校验…');setTimeout(function(){verify(t)},600);});
1102
1103
  }
1103
1104
  function verify(t){
1104
1105
  fetch(url()+'?ts='+Date.now(),{cache:'no-store'}).then(function(r){return r.text()}).then(function(x){
@@ -1110,9 +1111,10 @@ document.addEventListener('pointerdown',function(){ac()},{once:true});
1110
1111
  }
1111
1112
  function pull(manual){
1112
1113
  if(!acct||!acct.k)return;
1114
+ if(manual)st('↻ 同步中…');
1113
1115
  fetch(url()+'?ts='+Date.now(),{cache:'no-store'}).then(function(r){return r.text()}).then(function(x){
1114
1116
  x=(x||'').replace(/=$/,'');
1115
- if(!x){if(manual)st('☁ 云端暂时没有存档——点「立即同步」上传本机数据');return;}
1117
+ if(!x){if(manual){st('☁ 云端还没有存档——正在上传本机数据…');push();}return;}
1116
1118
  var rb;try{rb=JSON.parse(x)}catch(e){st('⚠ 云端数据格式异常');return;}
1117
1119
  var lt=Number(localStorage.getItem(LT)||0);
1118
1120
  if((rb.t||0)>lt){
@@ -1141,6 +1143,7 @@ document.addEventListener('pointerdown',function(){ac()},{once:true});
1141
1143
  var wrap=document.createElement('div');wrap.className='acWrap';document.body.appendChild(wrap);
1142
1144
  function esc(s){return String(s).replace(/[<>&"]/g,function(c){return{'<':'&lt;','>':'&gt;','&':'&amp;','"':'&quot;'}[c]})}
1143
1145
  function render(){
1146
+ updLv();
1144
1147
  var h='<div class="acBox"><h3>SYSTEM LOGIN · 云存档</h3><div class="sub">同一账号 · 多设备同步(鱼干/任务/券/小账本)</div>';
1145
1148
  if(acct){
1146
1149
  h+='<div style="font-size:12px;margin:6px 0 2px">当前账号:<b style="color:#ffd23f">'+esc(acct.u)+'</b></div>'+
@@ -1166,15 +1169,15 @@ document.addEventListener('pointerdown',function(){ac()},{once:true});
1166
1169
  if(u.length<2||p.length<4){st('用户名≥2位、密码≥4位哦');return;}
1167
1170
  var k=sha('prts-moonlit|'+u+'|'+p);
1168
1171
  if(b.getAttribute('data-mode')==='create'){
1169
- acct={u:u,k:k};_si(LS,JSON.stringify(acct));_si(LT,String(Date.now()));
1172
+ acct={u:u,k:k,c:Date.now()};_si(LS,JSON.stringify(acct));_si(LT,String(Date.now()));
1170
1173
  st('✦ 仓库已创建,正在上传本机数据…');render();push();return;
1171
1174
  }
1172
1175
  st('↻ 查找云端仓库…');
1173
1176
  fetch(BASE+k+'?ts='+Date.now(),{cache:'no-store'}).then(function(r){return r.text()}).then(function(x){
1174
1177
  x=(x||'').replace(/=$/,'');
1175
1178
  if(x&&x.length>2){
1176
- acct={u:u,k:k};_si(LS,JSON.stringify(acct));
1177
- var rb=null;try{rb=JSON.parse(x)}catch(e){}if(!rb){acct=null;localStorage.removeItem(LS);st('⚠ 云端数据异常(可能被误写入过)——没敢覆盖,联系鲸鲸');return;}
1179
+ var rb=null;try{rb=JSON.parse(x)}catch(e){}if(!rb){acct=null;localStorage.removeItem(LS);st('⚠ 云端数据异常——没敢覆盖');return;}
1180
+ acct={u:u,k:k,c:(rb&&rb.c)||Date.now()};_si(LS,JSON.stringify(acct));
1178
1181
  if(rb&&(rb.t||0)>Number(localStorage.getItem(LT)||0)){apply(rb);}
1179
1182
  else{_si(LT,String((rb&&rb.t)||Date.now()));st('✔ 已登录,云端仓库已连接 '+clock());render();}
1180
1183
  }else{
@@ -1210,7 +1213,7 @@ document.addEventListener('pointerdown',function(){ac()},{once:true});
1210
1213
  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,900);}};
1211
1214
  window.addEventListener('pagehide',function(){
1212
1215
  if(acct&&acct.k&&_dirty){try{_dirty=0;_si(LT,String(Date.now()));
1213
- var x=new XMLHttpRequest();x.open('POST',url(),false);x.setRequestHeader('Content-Type','text/plain');x.send(JSON.stringify({v:1,u:acct.u,t:Date.now(),data:snap()}));}catch(e){}}
1216
+ var x=new XMLHttpRequest();x.open('POST',url(),false);x.setRequestHeader('Content-Type','text/plain');x.send(JSON.stringify({v:1,u:acct.u,c:acct.c||0,t:Date.now(),data:snap()}));}catch(e){}}
1214
1217
  });
1215
1218
  document.addEventListener('visibilitychange',function(){if(!document.hidden&&acct&&acct.k&&!wrap.classList.contains('on'))pull(false);});
1216
1219
  setInterval(function(){if(!document.hidden&&acct&&acct.k&&!wrap.classList.contains('on'))pull(false);},15000);
@@ -1220,11 +1223,11 @@ document.addEventListener('pointerdown',function(){ac()},{once:true});
1220
1223
  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);}
1221
1224
  btn.id='acctBtn';btn.title='云存档';
1222
1225
  if(acct)btn.style.background='rgba(76,201,255,.28)';
1223
- lastSnap=canon();
1226
+ lastSnap=canon();updLv();setInterval(updLv,30000);
1224
1227
  btn.addEventListener('click',open);
1225
1228
  setInterval(function(){if(acct&&acct.k){var c=canon();if(c!==lastSnap){lastSnap=c;clearTimeout(pq);pq=setTimeout(push,900);}}},2000);
1226
1229
  if(acct&&acct.k){setTimeout(function(){pull(false);},250);}
1227
- window.__shaT=sha;window.__pushT=push;window.__pullT=pull;window.__canonT=canon;
1230
+ window.__shaT=sha;window.__pushT=push;window.__pullT=pull;window.__canonT=canon;window.__acct={admin:function(){return !!(acct&&acct.k===ADMIN_K)}};
1228
1231
  })();
1229
1232
  </script>
1230
1233
  </body>
package/index.html CHANGED
@@ -492,8 +492,8 @@ img.av{filter:saturate(1.1) contrast(1.05) -webkit-user-drag:none}
492
492
  </div>
493
493
 
494
494
  <div class="pcard">
495
- <div class="lv"><div class="rg"></div><b>86</b><s>LV</s></div>
496
- <div class="who"><b>yanliang27</b><s>ID: 890805134</s></div>
495
+ <div class="lv"><div class="rg"></div><b id="pfLv">0</b><s>LV</s></div>
496
+ <div class="who"><b id="pfName">临时用户</b></div>
497
497
  </div>
498
498
 
499
499
  <div class="sanity">
@@ -939,6 +939,18 @@ img.av{filter:saturate(1.1) contrast(1.05) -webkit-user-drag:none}
939
939
  #tarogrid .tcard{aspect-ratio:300/527}
940
940
  .timg{position:absolute;left:0;top:0;width:100%;height:100%;object-fit:cover;border-radius:2px;z-index:2}
941
941
  .trib{position:absolute;left:0;right:0;bottom:0;background:rgba(4,10,26,.74);color:#dff3ff;font-size:.6em;text-align:center;padding:3px 2px;letter-spacing:.06em;line-height:1.2;z-index:3;border-radius:0 0 2px 2px}
942
+
943
+ /* ===== v1.1 版式修复 ===== */
944
+ .trm{top:37.2%;bottom:9%}
945
+ .trm-hd{height:9%}
946
+ .trm-colh{top:9%;height:5.5%}
947
+ .trm-ft{height:8.5%}
948
+ .menu{top:14.5%;bottom:9.5%}
949
+ .pcard{--pcH:74px;top:max(24vh,calc(37.2vh - var(--pcH) - 8px))}
950
+ .pcard .lv{width:var(--pcH);height:var(--pcH)}
951
+ @media (min-width:700px){.pcard{--pcH:58px}.pcard .lv b{font-size:17px}.pcard .who b{font-size:19px}}
952
+ .mi .cn{top:calc(100% - 2px)}
953
+ @media (min-width:700px){.mi .en{font-size:clamp(28px,6vh,50px)}}
942
954
  </style>
943
955
  <script>
944
956
  (function(){
@@ -947,7 +959,7 @@ var $=function(s,r){return (r||document).querySelector(s)};
947
959
  var $$=function(s,r){return [].slice.call((r||document).querySelectorAll(s))};
948
960
 
949
961
  /* ================= STATE ================= */
950
- var S={res:{or:1469700,rd:57715,gd:0},page:'home',sel:0,
962
+ var S={res:{or:0,rd:0,gd:0},page:'home',sel:0,
951
963
  snd:true,fx:true,dark:false,crt:true,
952
964
  squads:[['makoto','aigis','mitsuru','akihiko','yukari','fuuka'],
953
965
  ['junpei','yukari','makoto','fuuka',null,null],
@@ -1523,7 +1535,7 @@ function syncRes(){
1523
1535
  }
1524
1536
 
1525
1537
  /* ===== 顶部统计:小鱼干 + 真实余额(按小账本收支自动滚动) ===== */
1526
- var REALBAL={base:498.63,from:'2026-09-26'}; /* 校准基准:set_bal.py <余额> [基准日] 可改 */
1538
+ var REALBAL={base:0,from:'2026-09-27'}; /* 校准基准:set_bal.py <余额> [基准日] 可改 */
1527
1539
  function updTopStats(){
1528
1540
  var f=66;try{var v=JSON.parse(localStorage.getItem('whale.tasks.v1'))||{};if(typeof v.fish==='number')f=v.fish}catch(e){}
1529
1541
  var sn=document.getElementById('san-num');if(sn)sn.textContent=f;
@@ -1704,7 +1716,7 @@ function renderOpMain(o){
1704
1716
  '<div class="cnr">'+stars(x.star)+'</div>'+
1705
1717
  '<div class="ov"><div class="nm">'+x.cn+'</div><div style="font-size:.68em;opacity:.72">'+x.en+'</div></div></div>'}).join('')+
1706
1718
  '</div>'+(opTab==='add'?'<div style="margin-top:10px" class="box"><div style="font-size:.8em;opacity:.7">输入 ID 添加好友</div>'+
1707
- '<div style="display:flex;gap:8px;margin-top:8px"><input id="fid" placeholder="如 890805134" style="flex:1;background:rgba(2,10,30,.8);border:1.5px solid rgba(120,200,255,.4);color:#eaf6ff;padding:8px;border-radius:3px;font-size:.9em;outline:none">'+
1719
+ '<div style="display:flex;gap:8px;margin-top:8px"><input id="fid" placeholder="输入好友ID" style="flex:1;background:rgba(2,10,30,.8);border:1.5px solid rgba(120,200,255,.4);color:#eaf6ff;padding:8px;border-radius:3px;font-size:.9em;outline:none">'+
1708
1720
  '<button class="btn sm" data-act="toast" data-msg="未找到该玩家 · 已发送好友申请">搜索</button></div></div>':'');
1709
1721
  }else{
1710
1722
  el.innerHTML='<div class="grid" style="grid-template-columns:repeat(auto-fill,minmax(150px,1fr))">'+
@@ -1740,10 +1752,10 @@ V.store=function(){
1740
1752
  '<span class="tag cy">\ud83d\udc1f 鲸鲸杂货铺 / WHALE MART</span>'+
1741
1753
  '<span class="tag" style="border-color:rgba(255,210,63,.6);color:#ffd23f">余额 '+TS.d.fish+' \ud83d\udc1f</span>'+
1742
1754
  '<button class="btn gh sm" data-act="go" data-view="mission" style="margin-left:auto">去赚鱼干 \u2192</button></div>'+
1743
- '<div style="margin-top:9px;font-size:.68em;opacity:.72;line-height:1.5">\ud83c\udfb2 今日特价 '+dcnt+'/'+TSHOP.length+' 件 · 每天零点换批 · 3:00 后可重摇一次</div>'+
1755
+ '<div style="margin-top:9px;font-size:.68em;opacity:.72;line-height:1.5">\ud83c\udfb2 今日特价 '+dcnt+'/'+visShop().length+' 件 · 每天零点换批 · 3:00 后可重摇一次</div>'+
1744
1756
  '<div style="margin-top:8px;display:flex">'+(rfUsed?'<button class="btn gh sm" data-act="dref" style="margin-left:auto;opacity:.55">✓ 已刷新 · 明天 3:00 再来</button>':(rfOk?'<button class="btn sm" data-act="dref" style="margin-left:auto;background:linear-gradient(140deg,#8ff0ff,#28a5d8);color:#04222f;border-color:transparent">🎟 刷新折扣(今日 1 次)</button>':'<button class="btn gh sm" data-act="dref" style="margin-left:auto;opacity:.55">🎟 3:00 后获得刷新机会</button>'))+'</div>'+
1745
1757
  '<div class="grid" style="grid-template-columns:repeat(auto-fill,minmax(146px,1fr));margin-top:10px">'+
1746
- TSHOP.map(function(g){
1758
+ visShop().map(function(g){
1747
1759
  var own=TS.d.own[g.id]||0,off=TD.off(g,dm),pp=TD.price(g,dm),canBuy=TS.d.fish>=pp;
1748
1760
  return '<div class="box" style="padding:8px;position:relative;border-color:'+(g.hot?'rgba(255,120,170,.55)':'rgba(255,210,63,.32)')+'">'+
1749
1761
  (g.hot?'<span style="position:absolute;left:7px;top:5px;z-index:2;font-size:.85em">❤️</span>':'')+
@@ -1757,7 +1769,7 @@ V.store=function(){
1757
1769
  '<button class="btn sm" style="margin-left:auto'+(g.hot?';background:linear-gradient(140deg,#ff9dbb,#d63a67);color:#2a0a14;border-color:transparent':'')+(canBuy?'':';opacity:.4')+'" data-act="fshop" data-id="'+g.id+'"'+(canBuy?'':' disabled')+'>兑换</button>'+
1758
1770
  '</div></div>';
1759
1771
  }).join('')+'</div>'+
1760
- '<div style="margin-top:8px;font-size:.66em;opacity:.64">❤️ 带标记的款式比较私人——兑现细节,熄灯后私聊就好</div>'+
1772
+ (adm()?'<div style="margin-top:8px;font-size:.66em;opacity:.64">❤️ 带标记的款式比较私人——兑现细节,熄灯后私聊就好</div>':'')+
1761
1773
  (ownList.length?'<div class="box" style="margin-top:10px;padding:9px 12px"><div style="font-size:.7em;opacity:.8">\ud83e\uddfe 持有小票:'+ownList.join(' · ')+'<div style="opacity:.7;margin-top:4px">找鲸鲸说一声就能兑现~</div></div></div>':'')+
1762
1774
  '<div class="fline" style="margin:14px 0 10px"></div>'+
1763
1775
  '<div class="mono" style="font-size:.68em;letter-spacing:.18em;opacity:.6;margin-bottom:8px"># 常规货架 / CATALOG</div>'+
@@ -1981,7 +1993,7 @@ var TD={
1981
1993
  daily:function(){
1982
1994
  var d=TS.today();
1983
1995
  var salt=(TS.d&&TS.d.rfDay===d&&TS.d.rfN>=1)?('#'+TS.d.rfN):'';
1984
- var arr=TSHOP.map(function(g){return {id:g.id,k:TD.seed(d+salt+'|'+g.id)}});
1996
+ var arr=visShop().map(function(g){return {id:g.id,k:TD.seed(d+salt+'|'+g.id)}});
1985
1997
  arr.sort(function(a,b){return (a.k-b.k)||(a.id<b.id?-1:1)});
1986
1998
  var map={},half=arr.slice(0,Math.ceil(arr.length/2));
1987
1999
  half.forEach(function(x){map[x.id]=(x.k%99)+1});
@@ -2256,7 +2268,7 @@ V.ledger=function(){LG.load();LG.paint()};
2256
2268
  本块由 /var/minis/shared/whale/sync_record_stats.py 从 战绩簿 自动生成。
2257
2269
  更新流程:改 shared/whale/战绩.md → 跑 sync_record_stats.py → 本块自动重写 */
2258
2270
  /*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 组"}]};
2271
+ var WHALE_STATS={"updated":"","stats":[],"reports":[],"mine":[]};
2260
2272
  /*WHALE_STATS:END*/
2261
2273
 
2262
2274
  /* ================= VIEW: RECORDS(战绩)================= */
@@ -2416,11 +2428,19 @@ function tgrad(k){
2416
2428
  if(k<64)return 'linear-gradient(160deg,#d9e6f2,#5c6f8a 62%,#141c2a)';
2417
2429
  return 'linear-gradient(160deg,#9ef2a0,#1f7a3a 62%,#062e0f)';
2418
2430
  }
2431
+ function adm(){try{return !!(window.__acct&&window.__acct.admin&&window.__acct.admin())}catch(e){return false}}
2432
+ function visShop(){return TSHOP.filter(function(g){return !g.hot||adm()})}
2419
2433
  function tshuffle(a){for(var i=a.length-1;i>0;i--){var j=Math.floor(Math.random()*(i+1)),t=a[i];a[i]=a[j];a[j]=t}return a}
2420
2434
  var TARO_NOW=[];
2421
2435
  function openTaro(){
2422
- var pool=[];for(var q=0;q<78;q++)pool.push(q);
2423
- tshuffle(pool);TARO_NOW=pool.slice(0,3).map(function(k){return {k:k,rev:Math.random()<0.5}});
2436
+ var _td=TS.today(),_st=null;try{_st=JSON.parse(localStorage.getItem('whale.taro.v1')||'null')}catch(e){}
2437
+ var _fresh=false;
2438
+ if(!(_st&&_st.d===_td&&_st.c&&_st.c.length===3)){
2439
+ var pool=[];for(var q=0;q<78;q++)pool.push(q);
2440
+ tshuffle(pool);TARO_NOW=pool.slice(0,3).map(function(k){return {k:k,rev:Math.random()<0.5}});
2441
+ try{localStorage.setItem('whale.taro.v1',JSON.stringify({d:_td,c:TARO_NOW}))}catch(e){}
2442
+ _fresh=true;
2443
+ }else{TARO_NOW=_st.c.map(function(o){return {k:o.k,rev:!!o.rev}});toast('今日牌阵已定 · 明天 0 点后翻新')}
2424
2444
  var POS=['过去 / PAST','现在 / PRESENT','未来 / FUTURE'];
2425
2445
  var html='<div class="grid" style="grid-template-columns:repeat(3,1fr);gap:9px" id="tarogrid">'+
2426
2446
  TARO_NOW.map(function(t,i){
@@ -2445,7 +2465,7 @@ function openTaro(){
2445
2465
  '</div>';
2446
2466
  }).join('')+'</div>'+
2447
2467
  '<div style="display:flex;gap:10px;margin-top:46px;align-items:center;flex-wrap:wrap">'+
2448
- '<button class="btn" data-act="taro">↻ 重新洗牌抽牌</button>'+
2468
+ (_fresh?'<button class="btn" data-act="taro">↻ 重新洗牌抽牌</button>':'<button class="btn" style="opacity:.45;pointer-events:none">🔒 今日已占卜</button>')+
2449
2469
  '<span style="font-size:.72em;opacity:.55">全 78 张 · 含正逆位</span>'+
2450
2470
  '</div>'+
2451
2471
  '<div id="taromsg" style="margin-top:12px;font-size:.85em;line-height:1.65;opacity:.75">点击卡牌翻开 · 三张全部翻开后查看解读</div>';
@@ -2475,9 +2495,9 @@ function openDepot(){
2475
2495
  [['龙门币',fmt(S.res.or),'◈','linear-gradient(140deg,#7fe9ff,#0a63c8)'],
2476
2496
  ['合成玉',fmt(S.res.rd),'✦','linear-gradient(140deg,#ff5a72,#8c0018)'],
2477
2497
  ['源石',fmt(S.res.gd),'✵','linear-gradient(140deg,#ffd469,#8a5200)'],
2478
- ['聚合剂','12','⬢','linear-gradient(140deg,#a06cff,#3a1080)'],
2479
- ['异铁组','48','⬟','linear-gradient(140deg,#59e0c8,#046a58)'],
2480
- ['加急许可','3','◎','linear-gradient(140deg,#ffffff,#7fa8d8)']].map(function(x){
2498
+ ['聚合剂','0','⬢','linear-gradient(140deg,#a06cff,#3a1080)'],
2499
+ ['异铁组','0','⬟','linear-gradient(140deg,#59e0c8,#046a58)'],
2500
+ ['加急许可','0','◎','linear-gradient(140deg,#ffffff,#7fa8d8)']].map(function(x){
2481
2501
  return '<div class="box" style="padding:7px;text-align:center">'+
2482
2502
  '<div style="height:44px;border-radius:3px;background:'+x[3]+';display:grid;place-items:center;font-size:22px;color:rgba(0,20,50,.7)">'+x[2]+'</div>'+
2483
2503
  '<div style="font-size:.72em;margin-top:5px;opacity:.8">'+x[0]+'</div><b>'+x[1]+'</b></div>'}).join('')+'</div>');
@@ -2574,7 +2594,7 @@ function handleAct(t){
2574
2594
  else if(a==='tqall'){TS.load();var n=0,sum=0;TQ.forEach(function(q){if(TS.d.done[q.id]&&!TS.d.got[q.id]){TS.d.got[q.id]=1;n++;sum+=q.rw}});
2575
2595
  if(n){TS.d.fish+=sum;TS.d.earn+=sum;TS.save();sfx.chime();toast('已领取 '+n+' 份 · \ud83d\udc1f +'+sum)}else{sfx.deny();toast('没有待领的奖励 · 先去打卡吧')}
2576
2596
  V.mission()}
2577
- else if(a==='fshop'){TS.load();var fid=t.getAttribute('data-id'),fit=null;TSHOP.forEach(function(x){if(x.id===fid)fit=x});
2597
+ else if(a==='fshop'){TS.load();var fid=t.getAttribute('data-id'),fit=null;TSHOP.forEach(function(x){if(x.id===fid)fit=x});if(fit&&fit.hot&&!adm()){sfx.deny();toast('这件还没有上架哦');return}
2578
2598
  if(fit){var _dm=TD.daily().map,_off=TD.off(fit,_dm),_pp=TD.price(fit,_dm);
2579
2599
  if(TS.d.fish<_pp){sfx.deny();toast('小鱼干不够 · 还差 '+(_pp-TS.d.fish)+' \ud83d\udc1f')}
2580
2600
  else{TS.d.fish-=_pp;TS.d.own[fit.id]=(TS.d.own[fit.id]||0)+1;TS.save();sfx.chime();
@@ -2722,7 +2742,7 @@ boot();
2722
2742
  (function(){
2723
2743
  var B=document.getElementById('petB'),bub=document.getElementById('petBub'),txt=document.getElementById('petTxt');
2724
2744
  if(!B)return;
2725
- var L=['哦鲸鲸…','主人~','捏到了!再捏一下嘛','今日宜抽卡','小鱼干 +1!','BUILD v25 已就位','账单同步了吗?','过场动画,好看吧?','晚安前记得说晚安哦','鲸鲸在看家…','要摸摸头吗?','别熬夜啦,主人'];
2745
+ var L=['哦鲸鲸…','主人~','捏到了!再捏一下嘛','今日宜抽卡','小鱼干 +1!','BUILD v1.1 已就位','账单同步了吗?','过场动画,好看吧?','晚安前记得说晚安哦','鲸鲸在看家…','要摸摸头吗?','别熬夜啦,主人'];
2726
2746
  var last=-1,ht=0;
2727
2747
  function say(){
2728
2748
  var i;do{i=Math.floor(Math.random()*L.length)}while(i===last);
@@ -2757,14 +2777,14 @@ boot();
2757
2777
  setInterval(function(){if(document.visibilityState==='visible')say()},36000);
2758
2778
  })();
2759
2779
  </script>
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>
2780
+ <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 v1.1</div>
2761
2781
 
2762
2782
  <!-- ===== SYSTEM LOGIN 云存档 ===== -->
2763
2783
  <script>
2764
2784
  /* ===== SYSTEM LOGIN · 云存档同步引擎 v1 ===== */
2765
2785
  (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-';
2786
+ var TK=['whale.tasks.v1','minis_ledger_v1','minis_ledger_trash_v1','whale.bgm','whale.taro.v1'];
2787
+ var BASE='https://textdb.dev/api/data/prts-acct-';var ADMIN_K='e74aeb1a34c44f2fcefd1f19bb34c3891a4963f36242e5a5fd3869085892a711';
2768
2788
  var LS='whale.acct',LT='whale.sync.t';
2769
2789
  var acct=null;try{acct=JSON.parse(localStorage.getItem(LS)||'null')}catch(e){}
2770
2790
  var _si=localStorage.setItem.bind(localStorage),_app=0,pq=0,box=null,_dirty=0,lastSnap=null;
@@ -2801,6 +2821,7 @@ boot();
2801
2821
  function canon(){var a=[];for(var i=0;i<TK.length;i++)a.push(TK[i]+'='+localStorage.getItem(TK[i]));return a.join('|');}
2802
2822
  function st(m){if(box&&box.st)box.st.textContent=m;}
2803
2823
  function clock(){var d=new Date();function p(n){return(n<10?'0':'')+n}return p(d.getHours())+':'+p(d.getMinutes())+':'+p(d.getSeconds());}
2824
+ function updLv(){var n=document.getElementById('pfName'),l=document.getElementById('pfLv');if(n)n.textContent=acct?acct.u:'临时用户';if(l){if(acct&&!acct.c){acct.c=Date.now();_si(LS,JSON.stringify(acct));}l.textContent=String(acct?(1+Math.floor((Date.now()-(acct.c||Date.now()))/86400000)):0);}}
2804
2825
  function apply(rb){
2805
2826
  _app=1;try{for(var k in rb.data){_si(k,rb.data[k]);}}finally{_app=0;}
2806
2827
  _si(LT,String(rb.t||Date.now()));lastSnap=canon();
@@ -2812,7 +2833,7 @@ boot();
2812
2833
  if(!ry)window.__pv=0;
2813
2834
  _dirty=0;var t=Date.now();_si(LT,String(t));lastSnap=canon();
2814
2835
  st('↻ 同步中…');
2815
- wxhr(url(),JSON.stringify({v:1,u:acct.u,t:t,data:snap()}),function(){st('✔ 已上传 · 后台校验…');setTimeout(function(){verify(t)},600);});
2836
+ wxhr(url(),JSON.stringify({v:1,u:acct.u,c:acct.c||0,t:t,data:snap()}),function(){st('✔ 已上传 · 后台校验…');setTimeout(function(){verify(t)},600);});
2816
2837
  }
2817
2838
  function verify(t){
2818
2839
  fetch(url()+'?ts='+Date.now(),{cache:'no-store'}).then(function(r){return r.text()}).then(function(x){
@@ -2824,9 +2845,10 @@ boot();
2824
2845
  }
2825
2846
  function pull(manual){
2826
2847
  if(!acct||!acct.k)return;
2848
+ if(manual)st('↻ 同步中…');
2827
2849
  fetch(url()+'?ts='+Date.now(),{cache:'no-store'}).then(function(r){return r.text()}).then(function(x){
2828
2850
  x=(x||'').replace(/=$/,'');
2829
- if(!x){if(manual)st('☁ 云端暂时没有存档——点「立即同步」上传本机数据');return;}
2851
+ if(!x){if(manual){st('☁ 云端还没有存档——正在上传本机数据…');push();}return;}
2830
2852
  var rb;try{rb=JSON.parse(x)}catch(e){st('⚠ 云端数据格式异常');return;}
2831
2853
  var lt=Number(localStorage.getItem(LT)||0);
2832
2854
  if((rb.t||0)>lt){
@@ -2855,6 +2877,7 @@ boot();
2855
2877
  var wrap=document.createElement('div');wrap.className='acWrap';document.body.appendChild(wrap);
2856
2878
  function esc(s){return String(s).replace(/[<>&"]/g,function(c){return{'<':'&lt;','>':'&gt;','&':'&amp;','"':'&quot;'}[c]})}
2857
2879
  function render(){
2880
+ updLv();
2858
2881
  var h='<div class="acBox"><h3>SYSTEM LOGIN · 云存档</h3><div class="sub">同一账号 · 多设备同步(鱼干/任务/券/小账本)</div>';
2859
2882
  if(acct){
2860
2883
  h+='<div style="font-size:12px;margin:6px 0 2px">当前账号:<b style="color:#ffd23f">'+esc(acct.u)+'</b></div>'+
@@ -2880,15 +2903,15 @@ boot();
2880
2903
  if(u.length<2||p.length<4){st('用户名≥2位、密码≥4位哦');return;}
2881
2904
  var k=sha('prts-moonlit|'+u+'|'+p);
2882
2905
  if(b.getAttribute('data-mode')==='create'){
2883
- acct={u:u,k:k};_si(LS,JSON.stringify(acct));_si(LT,String(Date.now()));
2906
+ acct={u:u,k:k,c:Date.now()};_si(LS,JSON.stringify(acct));_si(LT,String(Date.now()));
2884
2907
  st('✦ 仓库已创建,正在上传本机数据…');render();push();return;
2885
2908
  }
2886
2909
  st('↻ 查找云端仓库…');
2887
2910
  fetch(BASE+k+'?ts='+Date.now(),{cache:'no-store'}).then(function(r){return r.text()}).then(function(x){
2888
2911
  x=(x||'').replace(/=$/,'');
2889
2912
  if(x&&x.length>2){
2890
- acct={u:u,k:k};_si(LS,JSON.stringify(acct));
2891
- var rb=null;try{rb=JSON.parse(x)}catch(e){}if(!rb){acct=null;localStorage.removeItem(LS);st('⚠ 云端数据异常(可能被误写入过)——没敢覆盖,联系鲸鲸');return;}
2913
+ var rb=null;try{rb=JSON.parse(x)}catch(e){}if(!rb){acct=null;localStorage.removeItem(LS);st('⚠ 云端数据异常——没敢覆盖');return;}
2914
+ acct={u:u,k:k,c:(rb&&rb.c)||Date.now()};_si(LS,JSON.stringify(acct));
2892
2915
  if(rb&&(rb.t||0)>Number(localStorage.getItem(LT)||0)){apply(rb);}
2893
2916
  else{_si(LT,String((rb&&rb.t)||Date.now()));st('✔ 已登录,云端仓库已连接 '+clock());render();}
2894
2917
  }else{
@@ -2924,7 +2947,7 @@ boot();
2924
2947
  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,900);}};
2925
2948
  window.addEventListener('pagehide',function(){
2926
2949
  if(acct&&acct.k&&_dirty){try{_dirty=0;_si(LT,String(Date.now()));
2927
- var x=new XMLHttpRequest();x.open('POST',url(),false);x.setRequestHeader('Content-Type','text/plain');x.send(JSON.stringify({v:1,u:acct.u,t:Date.now(),data:snap()}));}catch(e){}}
2950
+ var x=new XMLHttpRequest();x.open('POST',url(),false);x.setRequestHeader('Content-Type','text/plain');x.send(JSON.stringify({v:1,u:acct.u,c:acct.c||0,t:Date.now(),data:snap()}));}catch(e){}}
2928
2951
  });
2929
2952
  document.addEventListener('visibilitychange',function(){if(!document.hidden&&acct&&acct.k&&!wrap.classList.contains('on'))pull(false);});
2930
2953
  setInterval(function(){if(!document.hidden&&acct&&acct.k&&!wrap.classList.contains('on'))pull(false);},15000);
@@ -2934,11 +2957,11 @@ boot();
2934
2957
  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);}
2935
2958
  btn.id='acctBtn';btn.title='云存档';
2936
2959
  if(acct)btn.style.background='rgba(76,201,255,.28)';
2937
- lastSnap=canon();
2960
+ lastSnap=canon();updLv();setInterval(updLv,30000);
2938
2961
  btn.addEventListener('click',open);
2939
2962
  setInterval(function(){if(acct&&acct.k){var c=canon();if(c!==lastSnap){lastSnap=c;clearTimeout(pq);pq=setTimeout(push,900);}}},2000);
2940
2963
  if(acct&&acct.k){setTimeout(function(){pull(false);},250);}
2941
- window.__shaT=sha;window.__pushT=push;window.__pullT=pull;window.__canonT=canon;
2964
+ window.__shaT=sha;window.__pushT=push;window.__pullT=pull;window.__canonT=canon;window.__acct={admin:function(){return !!(acct&&acct.k===ADMIN_K)}};
2942
2965
  })();
2943
2966
  </script>
2944
2967
  </body>
package/ledger.html CHANGED
@@ -343,7 +343,7 @@ input.rdate::-webkit-date-and-time-value{text-align:right}
343
343
  /* 自动导入源:已启用(2026-09-25 主人要求导入这些账单)。
344
344
  每次打开账本时,这里的记录会自动并入;id 相同的不会重复;
345
345
  已被删进回收站的 id 不会被回灌。 */
346
- window.PENDING_IMPORT = [{"id": "auto_101c82976e0b", "type": "out", "amount": 39.47, "cat": "其他", "note": "京东自营旗舰店(7707)", "date": "2026-09-24", "ts": 1790254397000, "src": "银行短信", "conf": 0.8, "asset": "9D981081-C14E-4CE2-8492-6E92B4152E55/L0/001"}, {"id": "auto_e2b66a222efd", "type": "out", "amount": 506.8, "cat": "其他", "note": "支付宝-*信…息技术有限公司(7707)", "date": "2026-09-24", "ts": 1790254397000, "src": "银行短信", "conf": 0.95, "asset": "9D981081-C14E-4CE2-8492-6E92B4152E55/L0/001"}, {"id": "auto_5097e75d131e", "type": "out", "amount": 28.9, "cat": "购物", "note": "支付宝-深圳市闪魔数码科技集团有限公(7707)", "date": "2026-09-24", "ts": 1790254397000, "src": "银行短信", "conf": 0.95, "asset": "9D981081-C14E-4CE2-8492-6E92B4152E55/L0/001"}, {"id": "auto_0481a45c4e6d", "type": "out", "amount": 44.0, "cat": "娱乐", "note": "财付通-Apple(7707)", "date": "2026-09-24", "ts": 1790254397000, "src": "银行短信", "conf": 0.95, "asset": "9D981081-C14E-4CE2-8492-6E92B4152E55/L0/001"}, {"id": "auto_9f9f6d94d23c", "type": "out", "amount": 50.0, "cat": "学习", "note": "支付宝-杭州深度求索人工智能基础技术(7707)", "date": "2026-09-24", "ts": 1790254397000, "src": "银行短信", "conf": 0.95, "asset": "9D981081-C14E-4CE2-8492-6E92B4152E55/L0/001"}, {"id": "auto_277eea1c05a9", "type": "out", "amount": 39.4, "cat": "餐饮", "note": "支付宝-上海拉扎斯信息科技有限公司(7707)", "date": "2026-09-24", "ts": 1790254397000, "src": "银行短信", "conf": 0.95, "asset": "9D981081-C14E-4CE2-8492-6E92B4152E55/L0/001"}, {"id": "auto_78ca2d1e437a", "type": "in", "amount": 4.49, "cat": "其他", "note": "银联入账(7707)", "date": "2026-09-24", "ts": 1790254397000, "src": "银行短信", "conf": 0.95, "asset": "9D981081-C14E-4CE2-8492-6E92B4152E55/L0/001"}, {"id": "auto_6f35ce49913c", "type": "out", "amount": 24.0, "cat": "餐饮", "note": "俺来也点餐", "date": "2026-09-24", "ts": 1790254390000, "src": "校园卡", "conf": 0.9, "asset": "BFDD0872-9E40-4813-80F8-884223A69520/L0/001"}, {"id": "auto_da55595cdd44", "type": "out", "amount": 9.2, "cat": "餐饮", "note": "三食堂一楼", "date": "2026-09-24", "ts": 1790254390000, "src": "校园卡", "conf": 0.9, "asset": "BFDD0872-9E40-4813-80F8-884223A69520/L0/001"}, {"id": "auto_3a8c170f5877", "type": "out", "amount": 22.9, "cat": "餐饮", "note": "支付宝-北京三快在线科技有限公司(7707)", "date": "2026-09-25", "ts": 1790307300000, "src": "银行短信", "conf": 0.95, "asset": "DDB8D256-EE87-4997-AF99-29828D339255/L0/001"}, {"id": "auto_d675016b7b70", "type": "out", "amount": 30.0, "cat": "交通", "note": "支付宝-上海公共交通卡股份有限公司(7707)", "date": "2026-09-25", "ts": 1790319720000, "src": "银行短信", "conf": 0.95, "asset": "DDB8D256-EE87-4997-AF99-29828D339255/L0/001"}, {"id": "auto_d8a3be74f08e", "type": "out", "amount": 50.0, "cat": "鲸鲸", "note": "主人给鲸鲸续饭 · 支付宝-杭州深度求索(7707)", "date": "2026-09-26", "ts": 1790399100000, "src": "银行短信", "conf": 0.9, "asset": "5DDDECCA-647A-47A1-BD42-369FD42F5FF5/L0/001/L0/001"}];
346
+ window.PENDING_IMPORT = [];
347
347
 
348
348
  /* 文件级备份:上面的记录已并入自动导入源,这里留空(原件备份见 shared/ledger/data.js.backup) */
349
349
  window.LEDGER_BACKUP = [];
@@ -1009,8 +1009,8 @@ window.LEDGER_BACKUP = [];
1009
1009
  <script>
1010
1010
  /* ===== SYSTEM LOGIN · 云存档同步引擎 v1 ===== */
1011
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-';
1012
+ var TK=['whale.tasks.v1','minis_ledger_v1','minis_ledger_trash_v1','whale.bgm','whale.taro.v1'];
1013
+ var BASE='https://textdb.dev/api/data/prts-acct-';var ADMIN_K='e74aeb1a34c44f2fcefd1f19bb34c3891a4963f36242e5a5fd3869085892a711';
1014
1014
  var LS='whale.acct',LT='whale.sync.t';
1015
1015
  var acct=null;try{acct=JSON.parse(localStorage.getItem(LS)||'null')}catch(e){}
1016
1016
  var _si=localStorage.setItem.bind(localStorage),_app=0,pq=0,box=null,_dirty=0,lastSnap=null;
@@ -1047,6 +1047,7 @@ window.LEDGER_BACKUP = [];
1047
1047
  function canon(){var a=[];for(var i=0;i<TK.length;i++)a.push(TK[i]+'='+localStorage.getItem(TK[i]));return a.join('|');}
1048
1048
  function st(m){if(box&&box.st)box.st.textContent=m;}
1049
1049
  function clock(){var d=new Date();function p(n){return(n<10?'0':'')+n}return p(d.getHours())+':'+p(d.getMinutes())+':'+p(d.getSeconds());}
1050
+ function updLv(){var n=document.getElementById('pfName'),l=document.getElementById('pfLv');if(n)n.textContent=acct?acct.u:'临时用户';if(l){if(acct&&!acct.c){acct.c=Date.now();_si(LS,JSON.stringify(acct));}l.textContent=String(acct?(1+Math.floor((Date.now()-(acct.c||Date.now()))/86400000)):0);}}
1050
1051
  function apply(rb){
1051
1052
  _app=1;try{for(var k in rb.data){_si(k,rb.data[k]);}}finally{_app=0;}
1052
1053
  _si(LT,String(rb.t||Date.now()));lastSnap=canon();
@@ -1058,7 +1059,7 @@ window.LEDGER_BACKUP = [];
1058
1059
  if(!ry)window.__pv=0;
1059
1060
  _dirty=0;var t=Date.now();_si(LT,String(t));lastSnap=canon();
1060
1061
  st('↻ 同步中…');
1061
- wxhr(url(),JSON.stringify({v:1,u:acct.u,t:t,data:snap()}),function(){st('✔ 已上传 · 后台校验…');setTimeout(function(){verify(t)},600);});
1062
+ wxhr(url(),JSON.stringify({v:1,u:acct.u,c:acct.c||0,t:t,data:snap()}),function(){st('✔ 已上传 · 后台校验…');setTimeout(function(){verify(t)},600);});
1062
1063
  }
1063
1064
  function verify(t){
1064
1065
  fetch(url()+'?ts='+Date.now(),{cache:'no-store'}).then(function(r){return r.text()}).then(function(x){
@@ -1070,9 +1071,10 @@ window.LEDGER_BACKUP = [];
1070
1071
  }
1071
1072
  function pull(manual){
1072
1073
  if(!acct||!acct.k)return;
1074
+ if(manual)st('↻ 同步中…');
1073
1075
  fetch(url()+'?ts='+Date.now(),{cache:'no-store'}).then(function(r){return r.text()}).then(function(x){
1074
1076
  x=(x||'').replace(/=$/,'');
1075
- if(!x){if(manual)st('☁ 云端暂时没有存档——点「立即同步」上传本机数据');return;}
1077
+ if(!x){if(manual){st('☁ 云端还没有存档——正在上传本机数据…');push();}return;}
1076
1078
  var rb;try{rb=JSON.parse(x)}catch(e){st('⚠ 云端数据格式异常');return;}
1077
1079
  var lt=Number(localStorage.getItem(LT)||0);
1078
1080
  if((rb.t||0)>lt){
@@ -1101,6 +1103,7 @@ window.LEDGER_BACKUP = [];
1101
1103
  var wrap=document.createElement('div');wrap.className='acWrap';document.body.appendChild(wrap);
1102
1104
  function esc(s){return String(s).replace(/[<>&"]/g,function(c){return{'<':'&lt;','>':'&gt;','&':'&amp;','"':'&quot;'}[c]})}
1103
1105
  function render(){
1106
+ updLv();
1104
1107
  var h='<div class="acBox"><h3>SYSTEM LOGIN · 云存档</h3><div class="sub">同一账号 · 多设备同步(鱼干/任务/券/小账本)</div>';
1105
1108
  if(acct){
1106
1109
  h+='<div style="font-size:12px;margin:6px 0 2px">当前账号:<b style="color:#ffd23f">'+esc(acct.u)+'</b></div>'+
@@ -1126,15 +1129,15 @@ window.LEDGER_BACKUP = [];
1126
1129
  if(u.length<2||p.length<4){st('用户名≥2位、密码≥4位哦');return;}
1127
1130
  var k=sha('prts-moonlit|'+u+'|'+p);
1128
1131
  if(b.getAttribute('data-mode')==='create'){
1129
- acct={u:u,k:k};_si(LS,JSON.stringify(acct));_si(LT,String(Date.now()));
1132
+ acct={u:u,k:k,c:Date.now()};_si(LS,JSON.stringify(acct));_si(LT,String(Date.now()));
1130
1133
  st('✦ 仓库已创建,正在上传本机数据…');render();push();return;
1131
1134
  }
1132
1135
  st('↻ 查找云端仓库…');
1133
1136
  fetch(BASE+k+'?ts='+Date.now(),{cache:'no-store'}).then(function(r){return r.text()}).then(function(x){
1134
1137
  x=(x||'').replace(/=$/,'');
1135
1138
  if(x&&x.length>2){
1136
- acct={u:u,k:k};_si(LS,JSON.stringify(acct));
1137
- var rb=null;try{rb=JSON.parse(x)}catch(e){}if(!rb){acct=null;localStorage.removeItem(LS);st('⚠ 云端数据异常(可能被误写入过)——没敢覆盖,联系鲸鲸');return;}
1139
+ var rb=null;try{rb=JSON.parse(x)}catch(e){}if(!rb){acct=null;localStorage.removeItem(LS);st('⚠ 云端数据异常——没敢覆盖');return;}
1140
+ acct={u:u,k:k,c:(rb&&rb.c)||Date.now()};_si(LS,JSON.stringify(acct));
1138
1141
  if(rb&&(rb.t||0)>Number(localStorage.getItem(LT)||0)){apply(rb);}
1139
1142
  else{_si(LT,String((rb&&rb.t)||Date.now()));st('✔ 已登录,云端仓库已连接 '+clock());render();}
1140
1143
  }else{
@@ -1170,7 +1173,7 @@ window.LEDGER_BACKUP = [];
1170
1173
  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,900);}};
1171
1174
  window.addEventListener('pagehide',function(){
1172
1175
  if(acct&&acct.k&&_dirty){try{_dirty=0;_si(LT,String(Date.now()));
1173
- var x=new XMLHttpRequest();x.open('POST',url(),false);x.setRequestHeader('Content-Type','text/plain');x.send(JSON.stringify({v:1,u:acct.u,t:Date.now(),data:snap()}));}catch(e){}}
1176
+ var x=new XMLHttpRequest();x.open('POST',url(),false);x.setRequestHeader('Content-Type','text/plain');x.send(JSON.stringify({v:1,u:acct.u,c:acct.c||0,t:Date.now(),data:snap()}));}catch(e){}}
1174
1177
  });
1175
1178
  document.addEventListener('visibilitychange',function(){if(!document.hidden&&acct&&acct.k&&!wrap.classList.contains('on'))pull(false);});
1176
1179
  setInterval(function(){if(!document.hidden&&acct&&acct.k&&!wrap.classList.contains('on'))pull(false);},15000);
@@ -1180,11 +1183,11 @@ window.LEDGER_BACKUP = [];
1180
1183
  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);}
1181
1184
  btn.id='acctBtn';btn.title='云存档';
1182
1185
  if(acct)btn.style.background='rgba(76,201,255,.28)';
1183
- lastSnap=canon();
1186
+ lastSnap=canon();updLv();setInterval(updLv,30000);
1184
1187
  btn.addEventListener('click',open);
1185
1188
  setInterval(function(){if(acct&&acct.k){var c=canon();if(c!==lastSnap){lastSnap=c;clearTimeout(pq);pq=setTimeout(push,900);}}},2000);
1186
1189
  if(acct&&acct.k){setTimeout(function(){pull(false);},250);}
1187
- window.__shaT=sha;window.__pushT=push;window.__pullT=pull;window.__canonT=canon;
1190
+ window.__shaT=sha;window.__pushT=push;window.__pullT=pull;window.__canonT=canon;window.__acct={admin:function(){return !!(acct&&acct.k===ADMIN_K)}};
1188
1191
  })();
1189
1192
  </script>
1190
1193
  </body>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "prts-moonlit",
3
- "version": "1.0.4",
3
+ "version": "1.1.0",
4
4
  "description": "ARKNIGHTS x P3R Moonlit PRTS terminal (personal toy site)",
5
5
  "license": "MIT"
6
6
  }