wwt-platform 1.1.11 → 1.1.13

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.
Files changed (3) hide show
  1. package/package.json +1 -1
  2. package/platform.html +149 -4
  3. package/tools.json +16 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wwt-platform",
3
- "version": "1.1.11",
3
+ "version": "1.1.13",
4
4
  "description": "WWT 工作平台 - 平台本体与工具清单分发",
5
5
  "files": [
6
6
  "platform.html",
package/platform.html CHANGED
@@ -591,6 +591,49 @@ const COLORS=['#1a6fd4','#14915b','#6b46d4','#c47f00','#d92b2b','#0891b2','#7c3a
591
591
  const CAT_ICONS={销售:'💰',入库:'📦',出库:'🚛',维修:'🔧',调拨:'🔄',对账:'📋',往来账:'📒',凭证:'🧾',其他:'📂'};
592
592
  const CAT_COLORS={销售:'#1a6fd4',入库:'#14915b',出库:'#0891b2',维修:'#c47f00',调拨:'#6b46d4',对账:'#7c3aed',往来账:'#b45309',凭证:'#d92b2b',其他:'#5b656f'};
593
593
 
594
+ // ── 免安装 exe 模式 ──────────────────────────────────────────
595
+ // 启动器注入 window.__WWT_SERVER__ 时,平台和工具都由本地服务下发。
596
+ // 关键收益:平台与工具同源(http://127.0.0.1),iframe 里 localStorage /
597
+ // IndexedDB 全部可用;工具也不再依赖写死的本地路径。
598
+ const SRV = (typeof window!=='undefined' && window.__WWT_SERVER__) || null;
599
+ const SRV_MODE = !!(SRV && SRV.base);
600
+
601
+ // 从本地服务同步工具列表(服务端为准,用户自己上传的工具保留)
602
+ async function syncServerTools(){
603
+ if(!SRV_MODE) return false;
604
+ try{
605
+ const r = await fetch(SRV.base + '/api/tools', {cache:'no-store'});
606
+ const j = await r.json();
607
+ if(!j || !Array.isArray(j.tools)) return false;
608
+
609
+ // 保留用户自己上传的工具(有 fileId 且不是服务端下发的)
610
+ const keep = [];
611
+ (ST.modules||[]).forEach(m => (m.tools||[]).forEach(t => {
612
+ if(t.fileId && !t.skey) keep.push({mod:m.id, tool:t});
613
+ }));
614
+
615
+ (ST.modules||[]).forEach(m => {
616
+ m.tools = (m.tools||[]).filter(t => t.fileId && !t.skey);
617
+ });
618
+
619
+ j.tools.forEach(t => {
620
+ // 未安装的不进模块列表 —— 否则用户点开会看到「工具尚未安装」却没有安装入口。
621
+ // 它们会出现在「检查更新 → 🆕 发现新工具」里,那里有安装按钮。
622
+ if(!t.installed) return;
623
+ const mod = (ST.modules||[]).find(x => x.id === t.module) || ST.modules[0];
624
+ if(!mod) return;
625
+ mod.tools.push({
626
+ id:'srv_'+t.key, name:t.name, desc:t.desc, tag:t.tag||'HTML',
627
+ skey:t.key, local:false, mkey:t.key, installed:true, ver:t.ver
628
+ });
629
+ });
630
+
631
+ ST.__srv = {manifestVer:j.manifestVer, manifestSrc:j.manifestSrc, launcher:j.launcher};
632
+ save(); renderNav();
633
+ return true;
634
+ }catch(e){ return false; }
635
+ }
636
+
594
637
  function initST(){return{modules:[
595
638
  {id:'fin',name:'财务',desc:'财务对账、核销、凭证管理等工具集',icon:'💰',color:'#1a6fd4',open:true,tools:[
596
639
  {id:'t1',name:'往来款项两清工具',desc:'自动对账核销,支持 Excel 导入',tag:'HTML',path:'C:/Users/Administrator/Desktop/往来款项两清工具.html',local:true},
@@ -735,6 +778,11 @@ function openTool(tid,mid){
735
778
  openServiceTool(tool,mod);return;
736
779
  }
737
780
 
781
+ // ── exe 模式:工具由本地服务下发(同源 → 存储、Worker、下载全部正常)──
782
+ if(tool.skey && SRV_MODE){
783
+ openServerTool(tool,mod);return;
784
+ }
785
+
738
786
  // ── 本地/上传型工具多重开预警 ──
739
787
  warnIfToolOpenInOtherTab(tool);markToolOpen(tool);
740
788
 
@@ -785,6 +833,30 @@ function markToolOpen(tool){
785
833
  window.addEventListener('pagehide',onUnload);
786
834
  }
787
835
 
836
+ // ── exe 模式:打开由本地服务下发的工具 ──────────────────────────────
837
+ // 平台与工具同源(http://127.0.0.1:端口),因此界面里的一切存储能力都正常,
838
+ // 不再出现 file:// / blob:null 下 localStorage 被禁的问题
839
+ function openServerTool(tool,mod){
840
+ hideAll();curPage='tool-'+tool.id;setTxt('ttag',tool.name);
841
+ const url = SRV.base + '/tool/' + tool.skey;
842
+ let fp=$id('fp-'+tool.id);
843
+ if(!fp){
844
+ fp=mk('div','fpage');fp.id='fp-'+tool.id;
845
+ fp.innerHTML=`
846
+ <div class="frame-hd">
847
+ <button class="back-btn" onclick="showModPage('${mod.id}')">← 返回${esc(mod.name)}模块</button>
848
+ <h3>${esc(tool.name)}</h3>
849
+ <div style="display:flex;gap:8px">
850
+ <button class="btn sm" onclick="(function(){const f=$id('ifr-${tool.id}');if(f){const s=f.src;f.src='';f.src=s;}})()">↻ 刷新</button>
851
+ <button class="btn sm" onclick="window.open('${url}','_blank')">⧉ 新窗口</button>
852
+ </div>
853
+ </div>
854
+ <div class="frame-box"><iframe id="ifr-${tool.id}" src="${url}"></iframe></div>`;
855
+ $id('main').appendChild(fp);
856
+ }
857
+ fp.classList.add('on');renderNav();
858
+ }
859
+
788
860
  // ── 上传型工具:从 IndexedDB 读回文件内容,动态生成 blob 地址 ────────────────
789
861
  async function openUploadedTool(tool,mod){
790
862
  warnIfToolOpenInOtherTab(tool);
@@ -1357,7 +1429,7 @@ function doAddMod(){
1357
1429
  // ═══════════════════════════════════════════════════════════
1358
1430
  // 平台更新(方案B:平台 + 内置工具统一检查)
1359
1431
  // ═══════════════════════════════════════════════════════════
1360
- const PLATFORM_VER = '1.1.11';
1432
+ const PLATFORM_VER = '1.1.13';
1361
1433
  const NPM_PKG = 'wwt-platform'; // NPM 包名(主力分发源)
1362
1434
  const GITEE_TOKEN_KEY = 'wwt_gitee_token';
1363
1435
  const GITEE_TOKEN_DEF = 'e45883b9c89b8d9689746ce42bbc2b0b';
@@ -1382,7 +1454,7 @@ const SOURCES = [
1382
1454
  // 更新清单:每个条目 = 一个可更新对象(平台或工具)
1383
1455
  // 这是「离线兜底种子」——联网时会与远程 tools.json 合并,远程为准
1384
1456
  const UPD_REG_DEF = [
1385
- {key:'platform', name:'WWT 工作平台', cur:'1.1.11', repo:GITEE_PLATFORM_REPO, verFile:'version.js', appFile:'app.js', pat:'__WWT_PLATFORM_VER', kind:'platform'},
1457
+ {key:'platform', name:'WWT 工作平台', cur:'1.1.13', repo:GITEE_PLATFORM_REPO, verFile:'version.js', appFile:'app.js', pat:'__WWT_PLATFORM_VER', kind:'platform'},
1386
1458
  {key:'erp-recon', name:'ERP 对账工具', cur:'V1.0.2',repo:'wwtmrhu/erp-recon', verFile:'version.js', appFile:'app.js', pat:'__ERP_LATEST_VER'},
1387
1459
  {key:'erp-tool', name:'ERP 对账单生成匹配', cur:'1.0.0', repo:'wwtmrhu/erp-tool', verFile:'version.js', appFile:'app.js', pat:'__ERP_LATEST_VER'},
1388
1460
  {key:'voucher', name:'WWT 凭证工具', cur:'P1.2.12',repo:'wwtmrhu/certificate-generation', verFile:'dist/version.json', appFile:'', pat:'ver', appUrl:true}
@@ -1664,6 +1736,12 @@ async function downloadToolContent(it) {
1664
1736
  async function installTool(key) {
1665
1737
  const it = UPD_REG.find(x => x.key === key);
1666
1738
  if (!it) { toast('找不到该工具', 'err'); return; }
1739
+
1740
+ // exe 模式下工具由本地服务托管在磁盘上,安装必须走服务端。
1741
+ // 若走下面的浏览器端分支,会往 IndexedDB 另存一份,而清单里那条服务端工具
1742
+ // 依然在列表里 —— 结果是模块里出现两个同名工具,其中一个点开报「尚未安装」。
1743
+ if (SRV_MODE) return installToolViaServer(it);
1744
+
1667
1745
  toast('正在下载「' + it.name + '」…', 'info');
1668
1746
  try {
1669
1747
  const html = await downloadToolContent(it);
@@ -1688,6 +1766,26 @@ async function installTool(key) {
1688
1766
  }
1689
1767
  }
1690
1768
 
1769
+ // exe 模式:交给本地服务安装(下载 → 写入数据目录 → 平台重新同步)
1770
+ async function installToolViaServer(it) {
1771
+ toast('正在由本地服务下载「' + it.name + '」…', 'info');
1772
+ try {
1773
+ const r = await fetch(SRV.base + '/api/install?key=' + encodeURIComponent(it.key),
1774
+ {cache:'no-store'});
1775
+ const j = await r.json();
1776
+ if (!j.ok) throw new Error(j.error || '安装失败');
1777
+ await syncServerTools(); // 重新拉工具列表,装好的工具会出现在对应模块
1778
+ refreshNewTools();
1779
+ renderNav();
1780
+ if (curPage === 'home') renderHomeMods();
1781
+ toast('✓ 「' + it.name + '」已安装完成', 'ok');
1782
+ return true;
1783
+ } catch(e) {
1784
+ toast('安装失败:' + e.message, 'err');
1785
+ return false;
1786
+ }
1787
+ }
1788
+
1691
1789
  // 把已有界面工具与注册表关联(按名称匹配)
1692
1790
  function linkExistingTools() {
1693
1791
  let changed = false;
@@ -1996,9 +2094,47 @@ function b64ToBytes(b64) {
1996
2094
  return bytes;
1997
2095
  }
1998
2096
 
2097
+ // exe 模式下的更新:全部交给本地服务完成
2098
+ // 工具 → 服务下载后写入数据目录,平台界面立即生效,无需手动替换文件
2099
+ // 平台 → 服务下载新版 platform.html 到数据目录,下次启动自动采用
2100
+ async function doUpdateViaServer(key, it) {
2101
+ const body = $id('upd-body');
2102
+ const setMsg = (t, bg, color) => {
2103
+ const html = '<div id="upd-prog" style="margin-top:10px;padding:10px 14px;background:'
2104
+ + (bg || 'var(--bg)') + ';border-radius:8px;font-size:13px;color:' + (color || 'var(--text-2)') + '">' + t + '</div>';
2105
+ const old = $id('upd-prog');
2106
+ if (old) old.outerHTML = html; else body.insertAdjacentHTML('beforeend', html);
2107
+ };
2108
+
2109
+ const isPlat = key === 'platform';
2110
+ setMsg('⏳ 正在由本地服务下载「' + esc(it.name) + '」最新版…');
2111
+ try {
2112
+ const url = SRV.base + (isPlat ? '/api/update-platform' : '/api/install?key=' + encodeURIComponent(key));
2113
+ const r = await fetch(url, {cache:'no-store'});
2114
+ const j = await r.json();
2115
+ if (!j.ok) throw new Error(j.error || '更新失败');
2116
+
2117
+ markUpdatedSilent(key, it.manifestVer || it.cur);
2118
+ if (!isPlat) await syncServerTools(); // 工具装好后重建界面
2119
+ renderUpdList();
2120
+
2121
+ setMsg('✅ 「' + esc(it.name) + '」已更新完成'
2122
+ + (isPlat ? ',<b>重新打开浏览器页面即可生效</b>(数据不受影响)。'
2123
+ : ',本地服务已直接装好,<b>无需手动替换任何文件</b>。'),
2124
+ '#f0fdf4', 'var(--green)');
2125
+ toast('✓ 「' + it.name + '」已更新', 'ok');
2126
+ } catch(e) {
2127
+ setMsg('❌ 更新失败:' + esc(e.message), '#fef2f2', 'var(--red)');
2128
+ }
2129
+ }
2130
+
1999
2131
  async function doUpdateOne(key) {
2000
2132
  const it = UPD_REG.find(x=>x.key===key);
2001
2133
  if (!it) return;
2134
+
2135
+ // exe 模式:交给本地服务处理
2136
+ if (SRV_MODE) return await doUpdateViaServer(key, it);
2137
+
2002
2138
  const body = $id('upd-body');
2003
2139
  const prog = '<div id="upd-prog" style="margin-top:10px;padding:10px 14px;background:var(--bg);border-radius:8px;font-size:13px;color:var(--text-2)">⏳ 正在下载「'+esc(it.name)+'」最新版…</div>';
2004
2140
  // 已有进度条就更新,没有就追加
@@ -2086,10 +2222,19 @@ function _init(){
2086
2222
  }
2087
2223
  }
2088
2224
  }
2225
+ // exe 模式:启动后从本地服务同步工具列表(服务端为准),再重绘界面
2226
+ function _boot(){
2227
+ _init();
2228
+ if(SRV_MODE){
2229
+ syncServerTools().then(ok=>{
2230
+ if(ok){ renderNav(); if(curPage==='home') renderHomeMods(); }
2231
+ });
2232
+ }
2233
+ }
2089
2234
  if(document.readyState==='loading'){
2090
- document.addEventListener('DOMContentLoaded',_init);
2235
+ document.addEventListener('DOMContentLoaded',_boot);
2091
2236
  }else{
2092
- _init();
2237
+ _boot();
2093
2238
  }
2094
2239
  </script>
2095
2240
  </body>
package/tools.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "schema": 1,
3
- "platform": "1.1.11",
3
+ "platform": "1.1.13",
4
4
  "updatedAt": "2026-09-10",
5
5
  "note": "WWT 工作平台工具清单。新增/修改工具只需改这个文件并发布新版本,用户端自动同步,无需重新分发平台。",
6
6
  "tools": [
@@ -77,6 +77,21 @@
77
77
  "pat": "ver",
78
78
  "appUrl": true
79
79
  }
80
+ },
81
+ {
82
+ "key": "income",
83
+ "name": "收入统计明细生成器",
84
+ "module": "ana",
85
+ "desc": "按月生成收入统计与明细表(维修/销售分板块),导出 Excel",
86
+ "ver": "1.0.2",
87
+ "type": "html",
88
+ "tag": "HTML",
89
+ "path": "C:/Users/Administrator/Desktop/收入统计明细生成器.html",
90
+ "src": {
91
+ "type": "npm",
92
+ "pkg": "income-stat-report",
93
+ "file": "income-stat-report.html"
94
+ }
80
95
  }
81
96
  ]
82
97
  }