dsh-boot-suite 2.15.17 → 2.16.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/CHANGELOG.md +25 -0
- package/lib/client.js +5 -5
- package/lib/splash.js +45 -1
- package/package.json +1 -1
- package/templates/division-bigfish-codex/app.js +147 -32
- package/templates/division-bigfish-codex/assets/voice-login.wav +0 -0
- package/templates/division-bigfish-codex/config.js +10 -7
- package/templates/division-bigfish-codex/index.html +14 -1
- package/templates/division-bigfish-codex/render.html +14 -1
- package/templates/division-bigfish-codex/style.css +27 -0
- package/templates/division-bigfish-codex/template.json +10 -10
- package/templates/whale-girl-scan-4k/template.json +2 -2
- package/templates/whale-girl-scan-4k-h264/assets/whale-girl-scan-4k-h264.mp4 +0 -0
- package/templates/whale-girl-scan-4k-h264/template.json +104 -0
- package/test/smoke-package.mjs +51 -2
- package/test/smoke-wallpaper-client.mjs +1 -1
- package/tools/build-release.mjs +1 -1
- package/tools/install.ps1 +41 -0
- package/tools/make-upgrade-helper.mjs +1 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,28 @@
|
|
|
1
|
+
## [2.16.2] — 2026-11-03
|
|
2
|
+
|
|
3
|
+
- **安装器代理加固**:开着代理安装时,pnpm 访问 npm registry 可能长时间卡在 [2/3](用户实测等很久无响应,关代理马上恢复)。现在会先检测并提示(5 秒后自动继续),同时把 pnpm 的 fetch 超时收紧到 30 秒、失败后自动用国内镜像重试一次。
|
|
4
|
+
- **桌面升级助手**增加提示:卡在第二步时关掉代理再双击一次。
|
|
5
|
+
- **修复「鲸鱼娘扫描睁眼(4K H.264)」没有出现在第二幕下拉**:新增的 4K H.264 模板没加进「正式模板」白名单,会被当成测试类模板藏起来;现已补进白名单。
|
|
6
|
+
- 版本号 2.16.2,构建号 cw-68。
|
|
7
|
+
|
|
8
|
+
## [2.16.1] — 2026-11-03
|
|
9
|
+
|
|
10
|
+
- **新增第二幕模板「鲸鱼娘扫描睁眼(4K H.264)」**:把原 4K 视频转码为 H.264 High 8bit(3840×2160 / 24fps / 约 9.6 Mbps,8.4MB),兼容性最好;部分机器没有 AV1 硬解、4K AV1 会走 CPU 软解导致掉帧,可改用本版。
|
|
11
|
+
- **原 4K 模板改名**为「鲸鱼娘扫描睁眼(4K AV1)」,描述里注明 AV1 编码与掉帧时的替代方案。
|
|
12
|
+
- **第二幕视频诊断**:诊断日志新增 `video meta`(分辨率/时长)与 `video stats`(实测帧率、丢帧数/总帧数、是否被暂停),4K 掉帧问题可以直接看日志定位。
|
|
13
|
+
- **省电暂停自动恢复**:Chromium 会把不可见的静音视频暂停省电(video-only background media paused to save power),现在检测到暂停会自动恢复,不再表现为卡住/掉帧。
|
|
14
|
+
- **消除 play() 噪音**:第二幕被跳过/收尾时 `play()` 的未捕获 promise 报错不再写进诊断日志。
|
|
15
|
+
- 版本号 2.16.1,构建号 cw-67。
|
|
16
|
+
|
|
17
|
+
## [2.16.0] — 2026-11-02
|
|
18
|
+
|
|
19
|
+
- **全景大肥鱼新增第二节登录 ID 动画**:第一节(登录 ID 段)延长到约 5.8s、只保留「检测到新的特工登录」;第二节 5s 登录动画,「WELCOME TO DEEPSEEK HARNESS」乱码→逐字、橙色扫描线从上往下、「正在登录:自定义用户名」按贝塞尔曲线平滑居中、用户名破解式逐字出现(最多 20 字符,过滤系统冲突符号)。
|
|
20
|
+
- **登录段新增第二段配音**:`Agent ID confirmed.` / 中文「特工身份确认。」,并复用「图标 + DSH + 波形 + 中文」整行;登录段内其它语音按新时间轴后移,第三节 0–100 保持不变。
|
|
21
|
+
- **配音串行播放(修叠音)**:第三节是 1.5x 加速段,音频按真实时长播放,上一句没播完不再启动下一句(此前 line1 尾巴会和 line2 重叠约 0.8s);重连后的 line2/line3/orig3 同样串行。
|
|
22
|
+
- **彩蛋尾部等待(修截断)**:动画临近结束时触发掉线彩蛋,会等当前配音(含 orig3 最后一句)播完再弹出,动画收尾也会等彩蛋语音播完,不再硬切。
|
|
23
|
+
- 总时长 33.4s(原 30.92s,给最后一句留足播完时间),登录框整体缩到原 1/3;模板名仍为「全景大肥鱼-含彩蛋版」。
|
|
24
|
+
- 版本号 2.16.0,构建号 cw-66。
|
|
25
|
+
|
|
1
26
|
## [2.15.17] — 2026-11-02
|
|
2
27
|
|
|
3
28
|
- **字幕不再提前消失**:每句配音的中文台词与波形改为跟随该句音频的真实播放时钟(Audio 元素的 currentTime / ended),不再按动画时间轴推算;即使主线程卡顿导致音频晚开始,字幕也会和语音同时出现、同时结束。
|
package/lib/client.js
CHANGED
|
@@ -269,7 +269,7 @@ window.__ModuleLoader__.load({
|
|
|
269
269
|
—— 桌面端走浏览器半侧自举时没有 1,就靠这一条
|
|
270
270
|
3) 下面这个常量:两份都没拿到时的兜底,别让面板显示 undefined
|
|
271
271
|
版本号本身只在 lib/index.js 里读一次,这里不重复维护。 */
|
|
272
|
-
var FALLBACK_VERSION = '2.
|
|
272
|
+
var FALLBACK_VERSION = '2.16.2'
|
|
273
273
|
/* 手动选包成功后置 true:让还在后台跑的“浏览器下载监听”不要再弹第二次更新器 */
|
|
274
274
|
var __manualUpdateApplied = false
|
|
275
275
|
function readInjectedVersion() {
|
|
@@ -903,7 +903,7 @@ window.__ModuleLoader__.load({
|
|
|
903
903
|
/* v2.14.0:模板分类。正式下拉只放「正式模板」;其余归到「测试类模板」。
|
|
904
904
|
默认:内置模板里只有 archive-warm(第一幕)与 whale-girl-scan / -4k(第二幕)算正式;
|
|
905
905
|
用户本地导入的算正式;被手动「归类」或「移出」的以配置为准。 */
|
|
906
|
-
var PROD_TEMPLATES = { template: { 'archive-warm': 1 }, act2: { 'whale-girl-scan': 1, 'whale-girl-scan-4k': 1 } }
|
|
906
|
+
var PROD_TEMPLATES = { template: { 'archive-warm': 1 }, act2: { 'whale-girl-scan': 1, 'whale-girl-scan-4k': 1, 'whale-girl-scan-4k-h264': 1 } }
|
|
907
907
|
function findTemplate(id) {
|
|
908
908
|
for (var fi = 0; fi < (templates || []).length; fi++) if (templates[fi] && templates[fi].id === id) return templates[fi]
|
|
909
909
|
return null
|
|
@@ -1253,8 +1253,8 @@ window.__ModuleLoader__.load({
|
|
|
1253
1253
|
? h('div', { className: '__ss_group' },
|
|
1254
1254
|
h('div', { className: '__ss_groupTitle' }, '全景大肥鱼-含彩蛋版 · 专属文案'),
|
|
1255
1255
|
h('div', { className: '__ss_hint' }, '只对第一幕「全景大肥鱼-含彩蛋版」生效;留空则用模板自带默认值。'),
|
|
1256
|
-
h(Field, { label: '连接用户名', hint: '
|
|
1257
|
-
h(TextInput, { value: draft.bigfishUsername || '', maxLength:
|
|
1256
|
+
h(Field, { label: '连接用户名', hint: '动画提示条和登录动画里的用户名;最多 20 个字符,\\ / : * ? " < > | 等特殊符号会被忽略。' },
|
|
1257
|
+
h(TextInput, { value: draft.bigfishUsername || '', maxLength: 20, onChange: (v) => set('bigfishUsername', Array.from(String(v || '').replace(/[\\/:*?"<>|]/g, '').replace(/\s+/g, ' ').trim()).slice(0, 20).join('')) })
|
|
1258
1258
|
),
|
|
1259
1259
|
h(Field, { label: '提示条标题' },
|
|
1260
1260
|
h(TextInput, { value: draft.bigfishTitle || '', maxLength: 60, onChange: (v) => set('bigfishTitle', v) })
|
|
@@ -2022,7 +2022,7 @@ window.__ModuleLoader__.load({
|
|
|
2022
2022
|
/* 每次改客户端就把这个号 +1。
|
|
2023
2023
|
有了它在控制台一眼就能判断"浏览器里跑的是不是最新那份" ——
|
|
2024
2024
|
排查问题时,分不清是代码问题还是旧包,会白猜一轮。 */
|
|
2025
|
-
var BUILD = 'cw-
|
|
2025
|
+
var BUILD = 'cw-68'
|
|
2026
2026
|
|
|
2027
2027
|
function log() {
|
|
2028
2028
|
try {
|
package/lib/splash.js
CHANGED
|
@@ -2476,10 +2476,54 @@
|
|
|
2476
2476
|
vnode.addEventListener('play', function () { diagRun('video play ' + vfile + ' vids=' + videoCount()) })
|
|
2477
2477
|
vnode.addEventListener('ended', function () { diagRun('video ended ' + vfile) })
|
|
2478
2478
|
vnode.addEventListener('error', function () { diagRun('video error ' + vfile) })
|
|
2479
|
+
/* v2.16.1:第二幕视频诊断(分辨率/时长/实测帧率/丢帧)+ 省电暂停自动恢复 + play() 失败静默 */
|
|
2480
|
+
vnode.addEventListener('loadedmetadata', function () {
|
|
2481
|
+
diagRun('video meta ' + vfile + ' ' + vnode.videoWidth + 'x' + vnode.videoHeight + ' dur=' + (isFinite(vnode.duration) ? vnode.duration.toFixed(2) : '?'))
|
|
2482
|
+
})
|
|
2483
|
+
var vResumeTimer = null
|
|
2484
|
+
vnode.addEventListener('pause', function () {
|
|
2485
|
+
/* Chromium 会把不可见的静音视频暂停省电;只要还在第二幕里就拉回来,避免“卡住/掉帧” */
|
|
2486
|
+
if (vnode.ended || !vnode.isConnected || vResumeTimer) return
|
|
2487
|
+
vResumeTimer = setTimeout(function () {
|
|
2488
|
+
vResumeTimer = null
|
|
2489
|
+
if (!vnode.isConnected || vnode.ended || !vnode.paused) return
|
|
2490
|
+
try { var vpR = vnode.play(); if (vpR && vpR.catch) vpR.catch(function () {}) } catch (eR) { /* noop */ }
|
|
2491
|
+
}, 260)
|
|
2492
|
+
})
|
|
2479
2493
|
placeLayer(vnode, tlNumber(L.pos && L.pos[0], 640), tlNumber(L.pos && L.pos[1], 360), vw, vh)
|
|
2480
2494
|
stage.appendChild(vnode)
|
|
2481
2495
|
diagRun('video append ' + vfile + ' vids=' + videoCount())
|
|
2482
|
-
try {
|
|
2496
|
+
try {
|
|
2497
|
+
var vp0 = vnode.play()
|
|
2498
|
+
if (vp0 && vp0.catch) vp0.catch(function () {})
|
|
2499
|
+
} catch (ePlay) { /* autoplay blocked */ }
|
|
2500
|
+
if (vnode.requestVideoFrameCallback) {
|
|
2501
|
+
var vFrames = 0, vT0 = 0
|
|
2502
|
+
var onVFrame = function (now) {
|
|
2503
|
+
if (!vnode.isConnected) return
|
|
2504
|
+
if (!vT0) { vT0 = now; vFrames = 0 }
|
|
2505
|
+
vFrames += 1
|
|
2506
|
+
if (now - vT0 < 1200) {
|
|
2507
|
+
try { vnode.requestVideoFrameCallback(onVFrame) } catch (eF) { /* noop */ }
|
|
2508
|
+
return
|
|
2509
|
+
}
|
|
2510
|
+
var vq = null
|
|
2511
|
+
try { vq = vnode.getVideoPlaybackQuality() } catch (eQ) { /* noop */ }
|
|
2512
|
+
var vFps = vT0 ? Math.round(vFrames * 1000 / (now - vT0)) : 0
|
|
2513
|
+
diagRun('video stats ' + vfile + ' ' + vnode.videoWidth + 'x' + vnode.videoHeight + ' fps=' + vFps +
|
|
2514
|
+
' dropped=' + (vq ? vq.droppedVideoFrames : '?') + '/' + (vq ? vq.totalVideoFrames : '?') +
|
|
2515
|
+
' paused=' + vnode.paused)
|
|
2516
|
+
}
|
|
2517
|
+
try { vnode.requestVideoFrameCallback(onVFrame) } catch (eF0) { /* noop */ }
|
|
2518
|
+
} else {
|
|
2519
|
+
setTimeout(function () {
|
|
2520
|
+
if (!vnode.isConnected) return
|
|
2521
|
+
var vq2 = null
|
|
2522
|
+
try { if (vnode.getVideoPlaybackQuality) vq2 = vnode.getVideoPlaybackQuality() } catch (eQ2) { /* noop */ }
|
|
2523
|
+
diagRun('video stats ' + vfile + ' ' + vnode.videoWidth + 'x' + vnode.videoHeight +
|
|
2524
|
+
' dropped=' + (vq2 ? vq2.droppedVideoFrames : '?') + '/' + (vq2 ? vq2.totalVideoFrames : '?'))
|
|
2525
|
+
}, 1500)
|
|
2526
|
+
}
|
|
2483
2527
|
nodes.push({ def: L, node: vnode, video: vnode })
|
|
2484
2528
|
continue
|
|
2485
2529
|
}
|
package/package.json
CHANGED
|
@@ -46,12 +46,145 @@ function renderVoiceRow(g,se,h,sub,visible){
|
|
|
46
46
|
g.style.opacity=visible;
|
|
47
47
|
if(se){if(se.textContent!==sub)se.textContent=sub||'';se.setAttribute('x',String(subX));se.setAttribute('y',String(baseY));se.setAttribute('text-anchor','start');se.setAttribute('dominant-baseline','central');se.setAttribute('font-size',String(subFs));se.style.opacity=(visible&&sub)?1:0}
|
|
48
48
|
}
|
|
49
|
+
var loginStart=+(cfg.loginStart!=null?cfg.loginStart:cfg.loadingStart),loginDur=Math.max(0,+(cfg.loginDur||0)),loginEnd=loginStart+loginDur;
|
|
50
|
+
function voiceVT(x){if(x<loginEnd)return Math.max(0,x-(+cfg.startAt||0));return 11.6+(x-cfg.loadingStart)/1.5}
|
|
51
|
+
/* ===== v2.16.0:登录 ID 动画(WELCOME TO DEEPSEEK HARNESS + 正在登录:用户名) ===== */
|
|
52
|
+
var LOGIN=(function(){
|
|
53
|
+
var el=$('login'),l1=$('login-line1'),l2=$('login-line2'),track=$('login-l2-track'),head=$('login-l2-head'),scanText=$('login-scan-text'),scanWrap=scanText?scanText.parentNode:null,scanBar=$('login-scan-bar'),colon=$('login-colon'),nameEl=$('login-name'),caret=$('login-caret'),meta=$('login-name-meta');
|
|
54
|
+
if(!el||!l1||!l2||!track||!head||!scanText||!nameEl)return null;
|
|
55
|
+
var L1='WELCOME TO DEEPSEEK HARNESS';
|
|
56
|
+
var POOL='ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789#%&@$*+-=/<>[]{}';
|
|
57
|
+
/* 5s 版:第一行 0.18~1.2s、扫描 1.28~1.73s、冒号 1.76~1.88s、用户名 1.94~4.34s、停留到 5s */
|
|
58
|
+
var L1_START=0.18,L1_SPAN=0.72,L1_FLICK=0.3;
|
|
59
|
+
var L2_START=1.28,L2_SCAN=0.45,COLON_AT=1.76,COLON_DUR=0.12,NAME_AT=1.94,NAME_DUR=2.4,SLIDE_DUR=0.62;
|
|
60
|
+
function mulberry32(a){return function(){a|=0;a=a+0x6D2B79F5|0;var t=Math.imul(a^a>>>15,1|a);t=t+Math.imul(t^t>>>7,61|t)^t;return((t^t>>>14)>>>0)/4294967296}}
|
|
61
|
+
/* 用户名安全化:去掉控制符/双向控制符与 \ / : * ? " < > |,合并空白,最多 20 个字符(按码点计)。 */
|
|
62
|
+
function sanitize(raw){
|
|
63
|
+
var s=String(raw==null?'':raw).replace(/[\u0000-\u001F\u007F\u200B-\u200F\u2028-\u202E\uFEFF]/g,'').replace(/[\\/:*?"<>|]/g,'').replace(/\s+/g,' ').trim();
|
|
64
|
+
var cp=Array.from(s);if(cp.length>20)cp=cp.slice(0,20);
|
|
65
|
+
return cp.join('');
|
|
66
|
+
}
|
|
67
|
+
function esc(ch){return ch===' '?' ':ch.replace(/[&<>]/g,function(c){return {'&':'&','<':'<','>':'>'}[c]})}
|
|
68
|
+
var rnd=mulberry32(20261102),l1c=null,order=[],nameChars=[],nmc=null,settles=[],rates=[],builtName=null,HEAD_W=0,NAME_W=0,measuredKey='';
|
|
69
|
+
function rebuild(name){
|
|
70
|
+
var s=sanitize(name)||'AGENT';
|
|
71
|
+
if(s===builtName)return;
|
|
72
|
+
builtName=s;
|
|
73
|
+
l1.innerHTML=L1.split('').map(function(ch){return '<span class="l1c">'+(ch===' '?' ':ch)+'</span>'}).join('');
|
|
74
|
+
l1c=l1.children;
|
|
75
|
+
var idx=[];for(var i=0;i<L1.length;i++)idx.push(i);
|
|
76
|
+
for(var j=idx.length-1;j>0;j--){var k=Math.floor(rnd()*(j+1));var tmp=idx[j];idx[j]=idx[k];idx[k]=tmp}
|
|
77
|
+
order=new Array(L1.length);idx.forEach(function(v,rank){order[v]=rank});
|
|
78
|
+
nameChars=Array.from(s);
|
|
79
|
+
nameEl.innerHTML=nameChars.map(function(ch){return '<span class="nmc">'+esc(ch)+'</span>'}).join('');
|
|
80
|
+
nmc=nameEl.children;
|
|
81
|
+
settles=nameChars.map(function(){return rnd()});
|
|
82
|
+
rates=nameChars.map(function(){return 12+rnd()*22});
|
|
83
|
+
/* 按最终字符宽度定宽,乱码阶段不会因为字宽变化而抖动 */
|
|
84
|
+
for(var m=0;m<nmc.length;m++){nmc[m].style.width=(nmc[m].getBoundingClientRect().width+0.6)+'px';}
|
|
85
|
+
measuredKey='';measure();
|
|
86
|
+
colon.style.opacity='0';caret.style.opacity='0';scanBar.style.opacity='0';if(scanWrap)scanWrap.style.setProperty('--p','0%');
|
|
87
|
+
if(meta)meta.textContent='AUTH MODULE v2.16';
|
|
88
|
+
}
|
|
89
|
+
function measure(){
|
|
90
|
+
var fs=parseFloat(getComputedStyle(l2).fontSize)||17;
|
|
91
|
+
var key=fs.toFixed(2)+'|'+Math.round(l2.clientWidth);
|
|
92
|
+
if(key===measuredKey)return;
|
|
93
|
+
measuredKey=key;
|
|
94
|
+
HEAD_W=head.getBoundingClientRect().width;
|
|
95
|
+
NAME_W=nameEl.getBoundingClientRect().width;
|
|
96
|
+
}
|
|
97
|
+
/* 三次贝塞尔缓动(cubic-bezier(.22,1,.36,1)),用于「正在登录」平滑左移 */
|
|
98
|
+
function bezier(p){
|
|
99
|
+
p=Math.max(0,Math.min(1,p));
|
|
100
|
+
var x1=.22,y1=1,x2=.36,y2=1;
|
|
101
|
+
var t=p;
|
|
102
|
+
for(var i=0;i<4;i++){
|
|
103
|
+
var mt=1-t;
|
|
104
|
+
var x=3*mt*mt*t*x1+3*mt*t*t*x2+t*t*t;
|
|
105
|
+
var dx=3*mt*mt*x1+6*mt*t*(x2-x1)+3*t*t*(1-x2);
|
|
106
|
+
if(Math.abs(dx)<1e-6)break;
|
|
107
|
+
t=Math.max(0,Math.min(1,t-(x-p)/dx));
|
|
108
|
+
}
|
|
109
|
+
var m2=1-t;
|
|
110
|
+
return 3*m2*m2*t*y1+3*m2*t*t*y2+t*t*t;
|
|
111
|
+
}
|
|
112
|
+
function render(lt,name){
|
|
113
|
+
rebuild(name);measure();
|
|
114
|
+
var n=l1c.length;
|
|
115
|
+
for(var i=0;i<n;i++){
|
|
116
|
+
var st=L1_START+(order[i]/Math.max(1,n-1))*L1_SPAN,en=st+L1_FLICK,c=l1c[i],final=L1[i];
|
|
117
|
+
if(lt<st){c.textContent=POOL[(i*131+Math.floor(lt*26)*17)%POOL.length];c.style.opacity=String(0.05+0.22*Math.max(0,Math.sin(lt*11+i)));}
|
|
118
|
+
else if(lt<en){c.textContent=POOL[(i*97+Math.floor(lt*30)*31)%POOL.length];c.style.opacity=String(0.25+0.75*((lt-st)/L1_FLICK));}
|
|
119
|
+
else{c.textContent=final===' '?'\u00a0':final;c.style.opacity='1';}
|
|
120
|
+
}
|
|
121
|
+
l1.style.opacity=String(0.9+0.1*Math.abs(Math.sin(lt*13)));
|
|
122
|
+
var p=Math.max(0,Math.min(1,(lt-L2_START)/L2_SCAN));
|
|
123
|
+
if(scanWrap)scanWrap.style.setProperty('--p',(p*100).toFixed(2)+'%');
|
|
124
|
+
scanBar.style.top=(p*100).toFixed(2)+'%';
|
|
125
|
+
if(lt>=L2_START-0.03&<<=L2_START+L2_SCAN)scanBar.style.opacity='1';
|
|
126
|
+
else if(lt>L2_START+L2_SCAN)scanBar.style.opacity=String(Math.max(0,1-(lt-(L2_START+L2_SCAN))/0.12));
|
|
127
|
+
else scanBar.style.opacity='0';
|
|
128
|
+
colon.style.opacity=String(Math.max(0,Math.min(1,(lt-COLON_AT)/COLON_DUR)));
|
|
129
|
+
for(var j=0;j<nmc.length;j++){
|
|
130
|
+
var cs=NAME_AT+0.04+settles[j]*NAME_DUR,e2=nmc[j];
|
|
131
|
+
if(lt<NAME_AT){e2.style.opacity='0';continue;}
|
|
132
|
+
if(lt<cs){e2.textContent=POOL[(j*73+Math.floor(lt*rates[j])*29)%POOL.length];e2.style.opacity=String(0.55+0.25*Math.abs(Math.sin(lt*rates[j])));e2.classList.remove('settled');}
|
|
133
|
+
else{e2.textContent=nameChars[j]===' '?'\u00a0':nameChars[j];e2.style.opacity='1';e2.classList.add('settled');}
|
|
134
|
+
}
|
|
135
|
+
caret.style.opacity=(lt>=NAME_AT&&(Math.floor((lt-NAME_AT)*2.6)%2===0))?'1':'0';
|
|
136
|
+
/* 用户名出现时整行按贝塞尔曲线平移,避免「正在登录」瞬移 */
|
|
137
|
+
var W=l2.clientWidth||1;
|
|
138
|
+
var xHead=Math.max(0,(W-HEAD_W)/2);
|
|
139
|
+
var xFull=Math.max(0,(W-(HEAD_W+NAME_W))/2);
|
|
140
|
+
var k=lt<NAME_AT?0:bezier((lt-NAME_AT)/SLIDE_DUR);
|
|
141
|
+
track.style.transform='translateX('+(xHead+(xFull-xHead)*k).toFixed(2)+'px)';
|
|
142
|
+
}
|
|
143
|
+
return {render:render,sanitize:sanitize};
|
|
144
|
+
})();
|
|
145
|
+
function hideLogin(){var el=$('login'),sc=$('scene');if(el)el.classList.remove('on');if(sc)sc.style.opacity='1';}
|
|
146
|
+
|
|
147
|
+
function voiceState(VT,rt){
|
|
148
|
+
let vh=null,vOn=false,sub="";
|
|
149
|
+
const cueOn=!!(window.__DSH_CUE__&&performance.now()<(window.__DSH_CUE_UNTIL__||0));
|
|
150
|
+
if(cueOn){
|
|
151
|
+
sub=window.__DSH_CUE__;
|
|
152
|
+
vh=Array.from({length:20},(_,k)=>4+Math.min(360,Math.abs(Math.sin(rt*7+k*0.55))*300));
|
|
153
|
+
vOn=true;
|
|
154
|
+
}else{
|
|
155
|
+
const vsched=(window.__VSCHED__&&window.__VSCHED__.length)?window.__VSCHED__:(window.VOICE_SCHED||[]).map(function(x){var atV=voiceVT(x.at);return{key:x.key,at:atV,dur:(x.at>=loginEnd?x.dur/1.5:x.dur)};});
|
|
156
|
+
const audioOn=!!window.__DSH_AUDIO_ON__, avNow=window.__DSH_ACTIVE_VOICE__||'', aNow=+window.__DSH_AUDIO_T__||0, aPlaying=!!window.__DSH_AUDIO_PLAYING__;
|
|
157
|
+
for(const x of vsched){
|
|
158
|
+
let vt=null;
|
|
159
|
+
if(audioOn){if(avNow===x.key&&aPlaying)vt=Math.max(0,aNow);}
|
|
160
|
+
else if(VT>=x.at-0.02&&VT<x.at+x.dur)vt=VT-x.at;
|
|
161
|
+
if(vt==null)continue;
|
|
162
|
+
sub=(cfg.voice&&cfg.voice.subs&&cfg.voice.subs[x.key])||"";
|
|
163
|
+
const e=(window.VOICE_ENV||{})[x.key];
|
|
164
|
+
if(e&&e.length){vh=Array.from({length:20},(_,k)=>{const st=Math.max(0,vt-(19-k)*0.055);const fi=st/0.008;const ai=Math.min(e.length-1,Math.floor(fi));const af=fi-Math.floor(fi);const a=((e[ai]||0)*(1-af)+(e[Math.min(e.length-1,ai+1)]||0)*af);return 4+Math.min(360,Math.pow(Math.max(0,a),0.9)*360)});vOn=true;}
|
|
165
|
+
else{vh=Array.from({length:20},(_,k)=>4+Math.min(360,Math.abs(Math.sin(vt*7+k*0.55))*300));vOn=true;}
|
|
166
|
+
break;
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
return {h:vh||Array(20).fill(4),sub:sub,on:vOn};
|
|
170
|
+
}
|
|
49
171
|
function render(){
|
|
50
|
-
const m=HUDMotion.state(t,cfg.loadingStart),loading=m.load,p=progress(t);
|
|
51
|
-
lastLoaded=m.load;
|
|
52
|
-
/* v2.15.12:结尾等配音时 t 冻结在 duration,波形/圆环改用连续时钟 rt,动画不中断 */
|
|
53
172
|
const waitSec=((window.__VTIME__==null)&&window.__WAIT_START__>0&&t>=cfg.duration-0.03)?(performance.now()-window.__WAIT_START__)/1000:0;
|
|
54
173
|
const rt=t+waitSec;
|
|
174
|
+
let VT=(window.__VTIME__!=null)?+window.__VTIME__:voiceVT(t);VT+=waitSec;
|
|
175
|
+
const vs=voiceState(VT,rt);
|
|
176
|
+
/* v2.16.0:登录动画期间只驱动登录层,主场景淡出;台词走同一套「图标+DSH+波形+字幕」行 */
|
|
177
|
+
if(loginDur>0&&t>=loginStart&&t<loginEnd){
|
|
178
|
+
var lg=$('login'),sc=$('scene');if(sc)sc.style.opacity='0';if(lg)lg.classList.add('on');
|
|
179
|
+
if(LOGIN)LOGIN.render(t-loginStart,cfg.username);
|
|
180
|
+
renderVoiceRow($('login-voice'),$('login-voice-sub'),vs.h,vs.sub,vs.on?1:0);
|
|
181
|
+
lastLoaded=false;
|
|
182
|
+
$('seek').value=t;$('time').textContent=(t-(+cfg.startAt||0)).toFixed(2)+' / '+(cfg.duration-(+cfg.startAt||0)).toFixed(2)+' s';
|
|
183
|
+
return;
|
|
184
|
+
}
|
|
185
|
+
hideLogin();
|
|
186
|
+
const m=HUDMotion.state(t,cfg.loadingStart),loading=m.load,p=progress(t);
|
|
187
|
+
lastLoaded=m.load;
|
|
55
188
|
$('rings').style.opacity=m.opacity;$('rings').removeAttribute('transform');
|
|
56
189
|
$('outer').setAttribute('transform',`scale(${m.outerScale}) rotate(${rt*5})`);$('outer').style.opacity=m.outerOpacity;
|
|
57
190
|
$('ticks').setAttribute('transform',`scale(${m.outerScale*m.outerPulse})`);$('ticks').style.opacity=m.outerOpacity;
|
|
@@ -68,30 +201,7 @@ function render(){
|
|
|
68
201
|
$('status').textContent=loading?'加载中':'连接中:'+cfg.username;$('status').style.opacity=m.opacity*m.labelOpacity;
|
|
69
202
|
$('statusArrow').style.opacity=m.opacity*m.labelOpacity;
|
|
70
203
|
$('statusDots').style.opacity=m.opacity*m.labelOpacity*(.35+.65*Math.abs(Math.sin(rt*4)));
|
|
71
|
-
|
|
72
|
-
/* v2.15.14:重连接提示音独占一整行(图标+DSH+波形+中文),播完才恢复后续配音 */
|
|
73
|
-
const cueOn=!!(window.__DSH_CUE__&&performance.now()<(window.__DSH_CUE_UNTIL__||0));
|
|
74
|
-
if(cueOn){
|
|
75
|
-
sub=window.__DSH_CUE__;
|
|
76
|
-
vh=Array.from({length:20},(_,k)=>4+Math.min(360,Math.abs(Math.sin(rt*7+k*0.55))*300));
|
|
77
|
-
vOn=true;
|
|
78
|
-
}else{
|
|
79
|
-
const vsched=(window.__VSCHED__&&window.__VSCHED__.length)?window.__VSCHED__:(window.VOICE_SCHED||[]).map(function(s){var atV=(s.at<=9.2)?s.at-3.4:5.8+(s.at-9.2)/1.5;return{key:s.key,at:atV,dur:s.dur};});
|
|
80
|
-
/* v2.15.17:有配音时,字幕/波形只跟「真正在播的那句」走(音频时钟),
|
|
81
|
-
避免时间轴窗口结束得比语音早、字幕提前消失。静音模式仍按时间轴显示。 */
|
|
82
|
-
const audioOn=!!window.__DSH_AUDIO_ON__, avNow=window.__DSH_ACTIVE_VOICE__||'', aNow=+window.__DSH_AUDIO_T__||0, aPlaying=!!window.__DSH_AUDIO_PLAYING__;
|
|
83
|
-
for(const s of vsched){
|
|
84
|
-
let vt=null;
|
|
85
|
-
if(audioOn){if(avNow===s.key&&aPlaying)vt=Math.max(0,aNow);}
|
|
86
|
-
else if(VT>=s.at-0.02&&VT<s.at+s.dur)vt=VT-s.at;
|
|
87
|
-
if(vt==null)continue;
|
|
88
|
-
sub=(cfg.voice&&cfg.voice.subs&&cfg.voice.subs[s.key])||"";
|
|
89
|
-
const e=(window.VOICE_ENV||{})[s.key];
|
|
90
|
-
if(e&&e.length){vh=Array.from({length:20},(_,k)=>{const st=Math.max(0,vt-(19-k)*0.055);const fi=st/0.008;const ai=Math.min(e.length-1,Math.floor(fi));const af=fi-Math.floor(fi);const a=((e[ai]||0)*(1-af)+(e[Math.min(e.length-1,ai+1)]||0)*af);return 4+Math.min(360,Math.pow(Math.max(0,a),0.9)*360)});vOn=true;}
|
|
91
|
-
break;
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
const h=vh||Array(20).fill(4);const voiceVisible=vOn?1:0;renderVoiceRow($('voice'),$('subtitle'),h,sub,voiceVisible);$('seek').value=t;$('time').textContent=(t-(+cfg.startAt||0)).toFixed(2)+' / '+(cfg.duration-(+cfg.startAt||0)).toFixed(2)+' s';
|
|
204
|
+
renderVoiceRow($('voice'),$('subtitle'),vs.h,vs.sub,vs.on?1:0);$('seek').value=t;$('time').textContent=(t-(+cfg.startAt||0)).toFixed(2)+' / '+(cfg.duration-(+cfg.startAt||0)).toFixed(2)+' s';
|
|
95
205
|
}
|
|
96
206
|
function syncAudio(){if(!env)return;const at=t- +$('voiceStart').value;if(at<0||at>=env.duration){audio.pause();return}if(Math.abs(audio.currentTime-at)>.12)audio.currentTime=at;if(playing&&audio.paused)audio.play().catch(()=>{$('audioInfo').textContent='请点击播放以启用音频。'});if(!playing)audio.pause()}
|
|
97
207
|
function play(){if(t>=cfg.duration)t=+cfg.startAt||0;playing=true;last=performance.now();$('play').textContent='暂停';syncAudio()}
|
|
@@ -128,12 +238,12 @@ $('prevFrame').onclick=()=>{pause();seek(t-1/60)};$('nextFrame').onclick=()=>{pa
|
|
|
128
238
|
function voiceDuck(on){try{if(parent&&parent!==window)parent.postMessage({type:'dsh-startup-voice',on:!!on},'*')}catch(e){}}
|
|
129
239
|
/* v2.15.10:彩蛋弹出时请宿主截断 BGM;重连后请宿主重新播 */
|
|
130
240
|
function bgmSig(on){try{if(parent&&parent!==window)parent.postMessage({type:'dsh-startup-bgm',on:!!on},'*')}catch(e){}}
|
|
131
|
-
var sched=vc.sched||[[4.6,'orig1',2.65],[8.
|
|
241
|
+
var sched=vc.sched||[[4.6,'orig1',2.65],[9.8,'login',1.79],[14.5,'line1',3.375],[18.4,'line2',3.232],[25.0,'line3',3.300],[30.45,'orig3',2.77]];
|
|
132
242
|
var eggLineAt=+(vc.eggLineAt!=null?vc.eggLineAt:2.0), eggReplayWait=+(vc.eggReplayWait!=null?vc.eggReplayWait:2.0), line4Dur=+(vc.line4Dur||1.911);
|
|
133
243
|
var aud={},played={},activeVoice=null,cueGate=false,cueFailTimer=null;window.__DSH_AUDIO_ON__=!mute;window.__DSH_ACTIVE_VOICE__='';window.__DSH_AUDIO_T__=-1;window.__DSH_AUDIO_PLAYING__=false;
|
|
134
244
|
sched.forEach(function(e){var k=e[1];if(!mute&&vc[k]){var a=new Audio(vc[k]);a.preload='auto';a.volume=voiceVol;a.addEventListener('ended',function(){if(activeVoice===k){activeVoice=null;window.__DSH_ACTIVE_VOICE__='';}window.__DSH_AUDIO_PLAYING__=false;window.__DSH_AUDIO_T__=-1;voiceDuck(false)});aud[k]=a;played[k]=false;}});
|
|
135
245
|
if(!mute&&vc.reconnect){var rc=new Audio(vc.reconnect);rc.preload='auto';rc.volume=voiceVol;rc.addEventListener('ended',function(){if(activeVoice==='reconnect'){activeVoice=null;window.__DSH_ACTIVE_VOICE__=''}window.__DSH_CUE__='';window.__DSH_CUE_UNTIL__=0;cueGate=false;voiceDuck(false)});aud.reconnect=rc;played.reconnect=true;}
|
|
136
|
-
/* v2.15.14
|
|
246
|
+
/* v2.15.14:重连接提示音独占一整行;重连提示音只播自己这一行;播完(ended)才解除 cueGate,后续 line2/line3/orig3 才允许开始 */
|
|
137
247
|
function playReconnectCue(){if(mute||!aud.reconnect)return;cueGate=true;setTimeout(function(){try{attachVoiceFx('reconnect');aud.reconnect.currentTime=0;aud.reconnect.play().catch(function(){})}catch(e){}activeVoice='reconnect';window.__DSH_ACTIVE_VOICE__='';var txt=(cfg.voice&&cfg.voice.subs&&cfg.voice.subs.reconnect)||'';var d=isFinite(aud.reconnect.duration)&&aud.reconnect.duration>0?aud.reconnect.duration:2.82;window.__DSH_CUE__=txt;window.__DSH_CUE_UNTIL__=performance.now()+d*1000+150;voiceDuck(true);if(cueFailTimer)clearTimeout(cueFailTimer);
|
|
138
248
|
/* 兜底:音频若因自动播放策略被拒,ended 不会触发;到时强制解除门控,避免后续配音全被卡住 */
|
|
139
249
|
cueFailTimer=setTimeout(function(){if(activeVoice==='reconnect'){activeVoice=null;window.__DSH_ACTIVE_VOICE__='';window.__DSH_CUE__='';window.__DSH_CUE_UNTIL__=0;cueGate=false;voiceDuck(false)}},d*1000+1500)},500)}
|
|
@@ -240,13 +350,18 @@ $('prevFrame').onclick=()=>{pause();seek(t-1/60)};$('nextFrame').onclick=()=>{pa
|
|
|
240
350
|
让字幕与波形以音频时钟为准,而不是按时间轴推算。 */
|
|
241
351
|
var __av=activeVoice?aud[activeVoice]:null;
|
|
242
352
|
if(__av){window.__DSH_AUDIO_T__=+__av.currentTime||0;window.__DSH_AUDIO_DUR__=+__av.duration||0;window.__DSH_AUDIO_PLAYING__=!__av.paused&&!__av.ended;}
|
|
243
|
-
if(playing&&!cueGate){
|
|
353
|
+
if(playing&&!cueGate){
|
|
354
|
+
/* v2.16.0:配音串行播放——上一句没播完(ended/pause)不启动下一句。
|
|
355
|
+
原因:第三节是 1.5x 加速段,时间轴会比真实音频快,按时间轴 forEach 会让 line1 尾巴和 line2 叠在一起。 */
|
|
356
|
+
var __busy=!!(activeVoice&&aud[activeVoice]&&!aud[activeVoice].paused&&!aud[activeVoice].ended);
|
|
357
|
+
if(!__busy){var __next=null;sched.forEach(function(e){if(!__next&&t>=e[0]&&!played[e[1]])__next=e;});if(__next)playKey(__next[1]);}
|
|
358
|
+
}
|
|
244
359
|
/* v2.15.16:掉线彩蛋若正好赶上某句配音,先等这句播完再弹出,避免语音和字幕被硬切断(有兜底超时)。 */
|
|
245
360
|
if(!rolled&&playing&&!shown&&t>=eggAt){
|
|
246
361
|
if(!hit){rolled=true;}
|
|
247
362
|
else if(!eggWait&&activeVoice&&aud[activeVoice]&&!aud[activeVoice].paused&&!aud[activeVoice].ended){
|
|
248
363
|
var eggA=aud[activeVoice], eggLeft=(+eggA.duration||0)-(+eggA.currentTime||0);
|
|
249
|
-
if(isFinite(eggLeft)&&eggLeft>0.05&&
|
|
364
|
+
if(isFinite(eggLeft)&&eggLeft>0.05&&eggLeft<=6){
|
|
250
365
|
eggWait=true;
|
|
251
366
|
(function(a){
|
|
252
367
|
var fired=false,fin=function(){if(fired)return;fired=true;eggWait=false;eggWaitTimer=null;rolled=true;showEgg();};
|
|
@@ -257,7 +372,7 @@ $('prevFrame').onclick=()=>{pause();seek(t-1/60)};$('nextFrame').onclick=()=>{pa
|
|
|
257
372
|
} else if(!eggWait){rolled=true;showEgg();}
|
|
258
373
|
}
|
|
259
374
|
if(shown){eggVoice();}
|
|
260
|
-
if(!shown&&t>=cfg.duration-0.02){if(!waitStart){waitStart=performance.now();window.__WAIT_START__=waitStart;}var waitVoice=(!mute&&aud.orig3&&!v3Ended&&(performance.now()-waitStart<4000));if(!waitVoice)flashDone();}
|
|
375
|
+
if(!shown&&!eggWait&&t>=cfg.duration-0.02){if(!waitStart){waitStart=performance.now();window.__WAIT_START__=waitStart;}var waitVoice=(!mute&&aud.orig3&&!v3Ended&&(performance.now()-waitStart<4000));if(!waitVoice)flashDone();}
|
|
261
376
|
}
|
|
262
377
|
requestAnimationFrame(watch);
|
|
263
378
|
})();
|
|
Binary file
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// 全景大肥鱼-含彩蛋版 · 可编辑代码动画参数(Lead 2026-11-
|
|
1
|
+
// 全景大肥鱼-含彩蛋版 · 可编辑代码动画参数(Lead 2026-11-02 更新:三段时间轴 + 登录 ID 动画)
|
|
2
2
|
window.CONFIG={
|
|
3
3
|
username:'人类与AI的日常',
|
|
4
4
|
title:'什么是「模板」?',
|
|
@@ -10,15 +10,18 @@ window.CONFIG={
|
|
|
10
10
|
{title:'想自己改?',description:'打开模板编辑器,标题、正文、连接用户名都能改,保存后下次启动生效。'},
|
|
11
11
|
{title:'怎么跳过?',description:'等进度条走完会自动进入聊天;想提前进,按 Esc 或点右上角「跳过」。'}
|
|
12
12
|
],
|
|
13
|
-
duration:
|
|
13
|
+
duration:33.4,
|
|
14
14
|
startAt:3.4,
|
|
15
|
-
|
|
15
|
+
/* 第一节:3.4 → 9.2s(约 5s 可见);第二节登录动画:9.2 → 14.2s(5s);第三节读取 0–100:14.2 → 30.92s。 */
|
|
16
|
+
loginStart:9.2,
|
|
17
|
+
loginDur:5.0,
|
|
18
|
+
loadingStart:14.2,
|
|
16
19
|
voiceY:908,
|
|
17
20
|
voiceWidth:520,
|
|
18
|
-
speedStart:
|
|
21
|
+
speedStart:14.2,
|
|
19
22
|
speed:1.5,
|
|
20
|
-
speedEnd:
|
|
23
|
+
speedEnd:30.45,
|
|
21
24
|
egg:{}, // v2.15.10:掉线时机在「进度 0–100%」之间随机(app.js 按 loadingStart~speedEnd 计算)
|
|
22
|
-
voice:{subs:{orig1:'警告:检测到新特工登录。',line1:'战术模块传输中,请稍候。',line2:'装备与技能配置已验证。倒计时十秒。',line3:'网络同步完成。正在移交权限。',line4:'警告:特工已离线。',reconnect:'检测到特工重新连接。',orig3:'欢迎回来,特工。很高兴再次见到你。'},orig1:'assets/voice-orig1.wav',line1:'assets/voice-line1.wav',line2:'assets/voice-line2.wav',line3:'assets/voice-line3.wav',orig3:'assets/voice-orig3.wav',line4:'assets/voice-line4.wav',reconnect:'assets/voice-reconnect.wav',sched:[[4.6,'orig1',2.65],[8.
|
|
23
|
-
progress:[[
|
|
25
|
+
voice:{subs:{orig1:'警告:检测到新特工登录。',login:'特工身份确认。',line1:'战术模块传输中,请稍候。',line2:'装备与技能配置已验证。倒计时十秒。',line3:'网络同步完成。正在移交权限。',line4:'警告:特工已离线。',reconnect:'检测到特工重新连接。',orig3:'欢迎回来,特工。很高兴再次见到你。'},orig1:'assets/voice-orig1.wav',login:'assets/voice-login.wav',line1:'assets/voice-line1.wav',line2:'assets/voice-line2.wav',line3:'assets/voice-line3.wav',orig3:'assets/voice-orig3.wav',line4:'assets/voice-line4.wav',reconnect:'assets/voice-reconnect.wav',sched:[[4.6,'orig1',2.65],[9.8,'login',1.79],[14.5,'line1',3.375],[18.4,'line2',3.232],[25.0,'line3',3.300],[30.45,'orig3',2.77]],eggLineAt: 1.0,line4Dur:1.911},
|
|
26
|
+
progress:[[14.2,0],[15,0],[15.9,0],[16.5,10],[17,29],[18,41],[19,43],[20,43],[25,43],[26,46],[27,51],[28,55],[29,59],[30,63],[30.4,64],[30.45,100],[30.92,100],[33.4,100]]
|
|
24
27
|
};
|
|
@@ -1 +1,14 @@
|
|
|
1
|
-
<!doctype html><html lang="zh-CN"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>全境封锁 · 可编辑代码动画</title><link rel="stylesheet" href="style.css"><style id="dsh-embed-style">html.embed,html.embed body{width:100%;height:100%;margin:0;overflow:hidden;background:#000}html.embed main{display:block!important;width:100%;height:100%}html.embed aside{display:none!important}html.embed #stage{width:100%;height:100%}html.embed #scene{width:100%;height:100%;display:block}</style></head><body><main><div id="stage"><svg id="scene" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1920 1080"><g id="tip"><path d="M615 222v-22q15-17 30 0v22zM620 201h20v18h-20zM626 189h9" fill="none" stroke="#aaa" stroke-width="2"/><text id="title" x="657" y="219" fill="#ccc" font-size="27"></text><path d="M606 232H1316M606 299H1316" stroke="#252525"/><foreignObject x="621" y="240" width="683" height="58"><div xmlns="http://www.w3.org/1999/xhtml" id="description"></div></foreignObject><path d="M596 256v19M1324 256v19" stroke="#999" stroke-width="2"/><rect x="624" y="313" width="45" height="16" fill="#555"/><text x="631" y="324" font-size="13" fill="#ccc">▏</text><text x="681" y="329" font-size="18" fill="#999">下一则</text><g id="pages"></g></g><g transform="translate(960 540)"><g id="rings"><circle id="pulse" r="10" fill="none" stroke="#70491a" stroke-width="2"/><circle id="pulseTrail" r="10" fill="none" stroke="#30250d" stroke-width="9"/><circle id="outerPulse" r="210" fill="none" stroke="#89521b" stroke-width="1"/><g id="ticks"></g><g id="outer"></g><g id="middle"></g><g id="inner"></g><g id="markers"></g><path id="progressArc" fill="none" stroke="#f29420" stroke-width="16"/><circle r="68" fill="none" stroke="#50340b" stroke-width="2"/></g><text id="percent" text-anchor="middle" y="9" fill="#bcbcbc" font-size="29" font-weight="300"></text></g><path id="statusArrow" d="M958 810l5 7 5-7" fill="#555"/><text id="status" x="960" y="853" text-anchor="middle" fill="#757575" font-size="25"></text><g id="statusDots" fill="#888"><rect x="951" y="792" width="3" height="3"/><rect x="960" y="787" width="3" height="3"/><rect x="967" y="796" width="3" height="3"/></g><g id="voice"></g><text id="subtitle" x="960" y="944" text-anchor="middle" fill="#e9d6b8" font-size="24" letter-spacing="1" opacity="0" style="transition:opacity .22s ease;pointer-events:none"></text></svg></div><aside><h1>可编辑代码动画</h1><label>连接用户名<input id="username"></label><label>提示标题<input id="heading"></label><label>提示正文<textarea id="body" rows="4"></textarea></label><div class="buttons"><button id="play">播放</button><button id="restart">从头播放</button><button id="fullscreen">全屏</button></div><label><span id="time">0.00 / 25.90 秒</span><input id="seek" type="range" min="0" max="25.9" step="0.016667" value="0"></label><div class="buttons"><button id="connection">查看连接阶段</button><button id="loading">查看加载阶段</button><button id="prevFrame">上一帧</button><button id="nextFrame">下一帧</button></div><hr><label>导入语音<input id="file" type="file" accept="audio/*"></label><label>语音开始时间(秒)<input id="voiceStart" type="number" min="0" step="0.1" value="9.2"></label><label>语音框距“加载中”的间隔<input id="gap" type="range" min="12" max="100" step="1" value="55"></label><p id="audioInfo">尚未导入语音,波形静止。语音框在加载阶段出现。</p><div class="buttons"><button id="save">保存设置 JSON</button><button id="reset">恢复默认</button></div><p>文字即时生效并保存在当前浏览器。时间轴、圆环和刻度均由参数生成。</p></aside></main><audio id="audio"></audio><div id="egg" aria-hidden="true"><img id="egg-bg" src="assets/egg-bg.png" alt=""><div id="egg-veil"></div><div id="egg-card" role="alertdialog"><div class="egg-head"><span class="egg-badge">!</span><span class="egg-title">错误</span></div><div class="egg-msg">《战术大肥鱼®》服务目前无法使用,请点击重试按钮。<div class="egg-code"><span>DELTA</span><span>C-0-1302</span></div></div><div class="egg-actions"><button id="egg-retry" type="button">重新连接</button></div></div></div><
|
|
1
|
+
<!doctype html><html lang="zh-CN"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>全境封锁 · 可编辑代码动画</title><link rel="stylesheet" href="style.css"><style id="dsh-embed-style">html.embed,html.embed body{width:100%;height:100%;margin:0;overflow:hidden;background:#000}html.embed main{display:block!important;width:100%;height:100%}html.embed aside{display:none!important}html.embed #stage{width:100%;height:100%}html.embed #scene{width:100%;height:100%;display:block}</style></head><body><main><div id="stage"><svg id="scene" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1920 1080"><g id="tip"><path d="M615 222v-22q15-17 30 0v22zM620 201h20v18h-20zM626 189h9" fill="none" stroke="#aaa" stroke-width="2"/><text id="title" x="657" y="219" fill="#ccc" font-size="27"></text><path d="M606 232H1316M606 299H1316" stroke="#252525"/><foreignObject x="621" y="240" width="683" height="58"><div xmlns="http://www.w3.org/1999/xhtml" id="description"></div></foreignObject><path d="M596 256v19M1324 256v19" stroke="#999" stroke-width="2"/><rect x="624" y="313" width="45" height="16" fill="#555"/><text x="631" y="324" font-size="13" fill="#ccc">▏</text><text x="681" y="329" font-size="18" fill="#999">下一则</text><g id="pages"></g></g><g transform="translate(960 540)"><g id="rings"><circle id="pulse" r="10" fill="none" stroke="#70491a" stroke-width="2"/><circle id="pulseTrail" r="10" fill="none" stroke="#30250d" stroke-width="9"/><circle id="outerPulse" r="210" fill="none" stroke="#89521b" stroke-width="1"/><g id="ticks"></g><g id="outer"></g><g id="middle"></g><g id="inner"></g><g id="markers"></g><path id="progressArc" fill="none" stroke="#f29420" stroke-width="16"/><circle r="68" fill="none" stroke="#50340b" stroke-width="2"/></g><text id="percent" text-anchor="middle" y="9" fill="#bcbcbc" font-size="29" font-weight="300"></text></g><path id="statusArrow" d="M958 810l5 7 5-7" fill="#555"/><text id="status" x="960" y="853" text-anchor="middle" fill="#757575" font-size="25"></text><g id="statusDots" fill="#888"><rect x="951" y="792" width="3" height="3"/><rect x="960" y="787" width="3" height="3"/><rect x="967" y="796" width="3" height="3"/></g><g id="voice"></g><text id="subtitle" x="960" y="944" text-anchor="middle" fill="#e9d6b8" font-size="24" letter-spacing="1" opacity="0" style="transition:opacity .22s ease;pointer-events:none"></text></svg></div><aside><h1>可编辑代码动画</h1><label>连接用户名<input id="username"></label><label>提示标题<input id="heading"></label><label>提示正文<textarea id="body" rows="4"></textarea></label><div class="buttons"><button id="play">播放</button><button id="restart">从头播放</button><button id="fullscreen">全屏</button></div><label><span id="time">0.00 / 25.90 秒</span><input id="seek" type="range" min="0" max="25.9" step="0.016667" value="0"></label><div class="buttons"><button id="connection">查看连接阶段</button><button id="loading">查看加载阶段</button><button id="prevFrame">上一帧</button><button id="nextFrame">下一帧</button></div><hr><label>导入语音<input id="file" type="file" accept="audio/*"></label><label>语音开始时间(秒)<input id="voiceStart" type="number" min="0" step="0.1" value="9.2"></label><label>语音框距“加载中”的间隔<input id="gap" type="range" min="12" max="100" step="1" value="55"></label><p id="audioInfo">尚未导入语音,波形静止。语音框在加载阶段出现。</p><div class="buttons"><button id="save">保存设置 JSON</button><button id="reset">恢复默认</button></div><p>文字即时生效并保存在当前浏览器。时间轴、圆环和刻度均由参数生成。</p></aside></main><audio id="audio"></audio><div id="egg" aria-hidden="true"><img id="egg-bg" src="assets/egg-bg.png" alt=""><div id="egg-veil"></div><div id="egg-card" role="alertdialog"><div class="egg-head"><span class="egg-badge">!</span><span class="egg-title">错误</span></div><div class="egg-msg">《战术大肥鱼®》服务目前无法使用,请点击重试按钮。<div class="egg-code"><span>DELTA</span><span>C-0-1302</span></div></div><div class="egg-actions"><button id="egg-retry" type="button">重新连接</button></div></div></div><div id="login" aria-hidden="true">
|
|
2
|
+
<div class="login-grid"></div>
|
|
3
|
+
<div class="login-scanlines"></div>
|
|
4
|
+
<div class="login-frame">
|
|
5
|
+
<div class="login-meta"><span>DSH // SECURE ACCESS</span><span>CHANNEL 02 · AUTH</span></div>
|
|
6
|
+
<div id="login-line1" class="login-line1"></div>
|
|
7
|
+
<div id="login-line2" class="login-line2">
|
|
8
|
+
<span id="login-l2-track" class="login-l2-track"><span id="login-l2-head" class="login-l2-head"><span class="login-scan-wrap"><span id="login-scan-text">正在登录</span><i id="login-scan-bar"></i></span><span id="login-colon">:</span></span><span id="login-name"></span><i id="login-caret"></i></span>
|
|
9
|
+
</div>
|
|
10
|
+
<div class="login-meta login-foot"><span>AUTH MODULE v2.16</span><span>DEEPSEEK HARNESS</span></div>
|
|
11
|
+
</div>
|
|
12
|
+
<svg id="login-voice-layer" class="login-voice-layer" viewBox="0 0 1920 1080" preserveAspectRatio="xMidYMid slice" aria-hidden="true"><g id="login-voice"></g><text id="login-voice-sub" fill="#e9d6b8" font-family="'DIN Alternate','Bahnschrift','Microsoft YaHei',sans-serif"></text></svg>
|
|
13
|
+
</div>
|
|
14
|
+
<script src="config.js"></script><script src="voice.js"></script><script src="voice-env.js"></script><script src="motion.js"></script><script src="app.js"></script><script>/* DSH_EMBED_PATCH */ (function(){try{var t=window.__DSH_STARTUP_TEMPLATE__||null;var embedded=(window.self!==window.top)||(t&&t.id==="division-bigfish-codex");if(!embedded)return;document.documentElement.classList.add("embed");function setv(id,v){if(!v)return;var el=document.getElementById(id);if(el){el.value=v;el.dispatchEvent(new Event("input",{bubbles:true}));}}if(t){setv("username",t.bigfishUsername);setv("heading",t.bigfishTitle);setv("body",t.bigfishDesc);}var n=0;var iv=setInterval(function(){n++;var b=document.getElementById("play");if(b){b.click();clearInterval(iv);}else if(n>60){clearInterval(iv);}},100);}catch(e){}})();</script></body></html>
|
|
@@ -1 +1,14 @@
|
|
|
1
|
-
<!doctype html><html lang="zh-CN"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>全境封锁 · 可编辑代码动画</title><link rel="stylesheet" href="style.css"><style>html,body{overflow:hidden;background:#000}main{display:block!important}aside{display:none!important}#stage{width:100vw;height:100vh;display:grid;place-items:center;background:#000}svg{width:100vw!important;height:100vh!important;max-height:none!important;display:block}</style></head><body><main><div id="stage"><svg id="scene" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1920 1080"><g id="tip"><path d="M615 222v-22q15-17 30 0v22zM620 201h20v18h-20zM626 189h9" fill="none" stroke="#aaa" stroke-width="2"/><text id="title" x="657" y="219" fill="#ccc" font-size="27"></text><path d="M606 232H1316M606 299H1316" stroke="#252525"/><foreignObject x="621" y="240" width="683" height="58"><div xmlns="http://www.w3.org/1999/xhtml" id="description"></div></foreignObject><path d="M596 256v19M1324 256v19" stroke="#999" stroke-width="2"/><rect x="624" y="313" width="45" height="16" fill="#555"/><text x="631" y="324" font-size="13" fill="#ccc">▏</text><text x="681" y="329" font-size="18" fill="#999">下一则</text><g id="pages"></g></g><g transform="translate(960 540)"><g id="rings"><circle id="pulse" r="10" fill="none" stroke="#70491a" stroke-width="2"/><circle id="pulseTrail" r="10" fill="none" stroke="#30250d" stroke-width="9"/><circle id="outerPulse" r="210" fill="none" stroke="#89521b" stroke-width="1"/><g id="ticks"></g><g id="outer"></g><g id="middle"></g><g id="inner"></g><g id="markers"></g><path id="progressArc" fill="none" stroke="#f29420" stroke-width="16"/><circle r="68" fill="none" stroke="#50340b" stroke-width="2"/></g><text id="percent" text-anchor="middle" y="9" fill="#bcbcbc" font-size="29" font-weight="300"></text></g><path id="statusArrow" d="M958 810l5 7 5-7" fill="#555"/><text id="status" x="960" y="853" text-anchor="middle" fill="#757575" font-size="25"></text><g id="statusDots" fill="#888"><rect x="951" y="792" width="3" height="3"/><rect x="960" y="787" width="3" height="3"/><rect x="967" y="796" width="3" height="3"/></g><g id="voice"></g></svg></div><aside><h1>可编辑代码动画</h1><label>连接用户名<input id="username"></label><label>提示标题<input id="heading"></label><label>提示正文<textarea id="body" rows="4"></textarea></label><div class="buttons"><button id="play">播放</button><button id="restart">从头播放</button><button id="fullscreen">全屏</button></div><label><span id="time">0.00 / 25.90 秒</span><input id="seek" type="range" min="0" max="25.9" step="0.016667" value="0"></label><div class="buttons"><button id="connection">查看连接阶段</button><button id="loading">查看加载阶段</button><button id="prevFrame">上一帧</button><button id="nextFrame">下一帧</button></div><hr><label>导入语音<input id="file" type="file" accept="audio/*"></label><label>语音开始时间(秒)<input id="voiceStart" type="number" min="0" step="0.1" value="9.2"></label><label>语音框距“加载中”的间隔<input id="gap" type="range" min="12" max="100" step="1" value="55"></label><p id="audioInfo">尚未导入语音,波形静止。语音框在加载阶段出现。</p><div class="buttons"><button id="save">保存设置 JSON</button><button id="reset">恢复默认</button></div><p>文字即时生效并保存在当前浏览器。时间轴、圆环和刻度均由参数生成。</p></aside></main><audio id="audio"></audio><div id="egg" aria-hidden="true"><img id="egg-bg" src="assets/egg-bg.png" alt=""><div id="egg-veil"></div><div id="egg-card" role="alertdialog"><div class="egg-head"><span class="egg-badge">!</span><span class="egg-title">错误</span></div><div class="egg-msg">《战术大肥鱼®》服务目前无法使用,请点击重试按钮。<div class="egg-code"><span>DELTA</span><span>C-0-1302</span></div></div><div class="egg-actions"><button id="egg-retry" type="button">重新连接</button></div></div></div><
|
|
1
|
+
<!doctype html><html lang="zh-CN"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>全境封锁 · 可编辑代码动画</title><link rel="stylesheet" href="style.css"><style>html,body{overflow:hidden;background:#000}main{display:block!important}aside{display:none!important}#stage{width:100vw;height:100vh;display:grid;place-items:center;background:#000}svg{width:100vw!important;height:100vh!important;max-height:none!important;display:block}</style></head><body><main><div id="stage"><svg id="scene" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1920 1080"><g id="tip"><path d="M615 222v-22q15-17 30 0v22zM620 201h20v18h-20zM626 189h9" fill="none" stroke="#aaa" stroke-width="2"/><text id="title" x="657" y="219" fill="#ccc" font-size="27"></text><path d="M606 232H1316M606 299H1316" stroke="#252525"/><foreignObject x="621" y="240" width="683" height="58"><div xmlns="http://www.w3.org/1999/xhtml" id="description"></div></foreignObject><path d="M596 256v19M1324 256v19" stroke="#999" stroke-width="2"/><rect x="624" y="313" width="45" height="16" fill="#555"/><text x="631" y="324" font-size="13" fill="#ccc">▏</text><text x="681" y="329" font-size="18" fill="#999">下一则</text><g id="pages"></g></g><g transform="translate(960 540)"><g id="rings"><circle id="pulse" r="10" fill="none" stroke="#70491a" stroke-width="2"/><circle id="pulseTrail" r="10" fill="none" stroke="#30250d" stroke-width="9"/><circle id="outerPulse" r="210" fill="none" stroke="#89521b" stroke-width="1"/><g id="ticks"></g><g id="outer"></g><g id="middle"></g><g id="inner"></g><g id="markers"></g><path id="progressArc" fill="none" stroke="#f29420" stroke-width="16"/><circle r="68" fill="none" stroke="#50340b" stroke-width="2"/></g><text id="percent" text-anchor="middle" y="9" fill="#bcbcbc" font-size="29" font-weight="300"></text></g><path id="statusArrow" d="M958 810l5 7 5-7" fill="#555"/><text id="status" x="960" y="853" text-anchor="middle" fill="#757575" font-size="25"></text><g id="statusDots" fill="#888"><rect x="951" y="792" width="3" height="3"/><rect x="960" y="787" width="3" height="3"/><rect x="967" y="796" width="3" height="3"/></g><g id="voice"></g><text id="subtitle" x="960" y="944" text-anchor="middle" fill="#e9d6b8" font-size="24" letter-spacing="1" opacity="0" style="transition:opacity .22s ease;pointer-events:none"></text></svg></div><aside><h1>可编辑代码动画</h1><label>连接用户名<input id="username"></label><label>提示标题<input id="heading"></label><label>提示正文<textarea id="body" rows="4"></textarea></label><div class="buttons"><button id="play">播放</button><button id="restart">从头播放</button><button id="fullscreen">全屏</button></div><label><span id="time">0.00 / 25.90 秒</span><input id="seek" type="range" min="0" max="25.9" step="0.016667" value="0"></label><div class="buttons"><button id="connection">查看连接阶段</button><button id="loading">查看加载阶段</button><button id="prevFrame">上一帧</button><button id="nextFrame">下一帧</button></div><hr><label>导入语音<input id="file" type="file" accept="audio/*"></label><label>语音开始时间(秒)<input id="voiceStart" type="number" min="0" step="0.1" value="9.2"></label><label>语音框距“加载中”的间隔<input id="gap" type="range" min="12" max="100" step="1" value="55"></label><p id="audioInfo">尚未导入语音,波形静止。语音框在加载阶段出现。</p><div class="buttons"><button id="save">保存设置 JSON</button><button id="reset">恢复默认</button></div><p>文字即时生效并保存在当前浏览器。时间轴、圆环和刻度均由参数生成。</p></aside></main><audio id="audio"></audio><div id="egg" aria-hidden="true"><img id="egg-bg" src="assets/egg-bg.png" alt=""><div id="egg-veil"></div><div id="egg-card" role="alertdialog"><div class="egg-head"><span class="egg-badge">!</span><span class="egg-title">错误</span></div><div class="egg-msg">《战术大肥鱼®》服务目前无法使用,请点击重试按钮。<div class="egg-code"><span>DELTA</span><span>C-0-1302</span></div></div><div class="egg-actions"><button id="egg-retry" type="button">重新连接</button></div></div></div><div id="login" aria-hidden="true">
|
|
2
|
+
<div class="login-grid"></div>
|
|
3
|
+
<div class="login-scanlines"></div>
|
|
4
|
+
<div class="login-frame">
|
|
5
|
+
<div class="login-meta"><span>DSH // SECURE ACCESS</span><span>CHANNEL 02 · AUTH</span></div>
|
|
6
|
+
<div id="login-line1" class="login-line1"></div>
|
|
7
|
+
<div id="login-line2" class="login-line2">
|
|
8
|
+
<span id="login-l2-track" class="login-l2-track"><span id="login-l2-head" class="login-l2-head"><span class="login-scan-wrap"><span id="login-scan-text">正在登录</span><i id="login-scan-bar"></i></span><span id="login-colon">:</span></span><span id="login-name"></span><i id="login-caret"></i></span>
|
|
9
|
+
</div>
|
|
10
|
+
<div class="login-meta login-foot"><span>AUTH MODULE v2.16</span><span>DEEPSEEK HARNESS</span></div>
|
|
11
|
+
</div>
|
|
12
|
+
<svg id="login-voice-layer" class="login-voice-layer" viewBox="0 0 1920 1080" preserveAspectRatio="xMidYMid slice" aria-hidden="true"><g id="login-voice"></g><text id="login-voice-sub" fill="#e9d6b8" font-family="'DIN Alternate','Bahnschrift','Microsoft YaHei',sans-serif"></text></svg>
|
|
13
|
+
</div>
|
|
14
|
+
<script src="config.js"></script><script src="voice.js"></script><script src="voice-env.js"></script><script src="motion.js"></script><script src="app.js"></script><script>(function(){var q=new URLSearchParams(location.search);setTimeout(function(){var A=window.__DSH_APP__,s=document.getElementById('seek');if(!A)return;window.__HOLD__=parseFloat(q.get('hold')||'0')||0;window.__VTIME__=q.has('vtime')?parseFloat(q.get('vtime')):null;window.__VSCHED__=q.has('demo')?[{key:'reconnect',at:10.7333,dur:2.821},{key:'line3',at:14.054,dur:3.3},{key:'orig3',at:21.5667,dur:2.77}]:null;window.__DEMO_SCHED__=null;var tv=parseFloat(q.get('t')||'0');if(s){s.value=Math.max(0,Math.min(25.9,tv));s.dispatchEvent(new Event('input',{bubbles:true}));}A.pause();if(q.has('egg')){var et=parseFloat(q.get('eggt')||'0');if(A.eggFrame)A.eggFrame(et);}else if(q.has('play')){A.play();}},240);})();</script></body></html>
|
|
@@ -16,3 +16,30 @@
|
|
|
16
16
|
#egg-retry{min-width:280px;padding:14px 26px;background:#15171a;border:1px solid rgba(255,255,255,.35);color:#e8e8e8;font-size:20px;letter-spacing:4px;cursor:pointer}
|
|
17
17
|
#egg-retry:hover{border-color:#f09a2e;color:#fff;background:#1b1d21}
|
|
18
18
|
body.egg-on #skip{display:none!important}
|
|
19
|
+
|
|
20
|
+
/* ===== v2.16.0:登录 ID 动画(整体缩到原来的 1/3) ===== */
|
|
21
|
+
#scene{transition:opacity .35s ease}
|
|
22
|
+
#login{position:fixed;inset:0;z-index:70;display:none;overflow:hidden;background:radial-gradient(700px 410px at 50% 42%,#0b0a08 0%,#050505 58%,#000 100%);opacity:0;transition:opacity .35s ease;pointer-events:none}
|
|
23
|
+
#login.on{display:block;opacity:1}
|
|
24
|
+
.login-grid{position:absolute;inset:0;background-image:linear-gradient(rgba(240,138,29,.055) 1px,transparent 1px),linear-gradient(90deg,rgba(240,138,29,.055) 1px,transparent 1px);background-size:48px 48px;-webkit-mask-image:radial-gradient(circle at 50% 45%,#000 0%,transparent 72%);mask-image:radial-gradient(circle at 50% 45%,#000 0%,transparent 72%);pointer-events:none}
|
|
25
|
+
.login-scanlines{position:absolute;inset:0;background:repeating-linear-gradient(to bottom,rgba(0,0,0,.22) 0 1px,transparent 1px 3px);pointer-events:none;opacity:.45}
|
|
26
|
+
.login-frame{position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);width:min(500px,92vw);text-align:center;font-family:'Consolas','Courier New','Microsoft YaHei',monospace;color:#f08a1d}
|
|
27
|
+
.login-frame:before,.login-frame:after{content:'';position:absolute;width:18px;height:18px;border:1px solid rgba(240,138,29,.5);pointer-events:none}
|
|
28
|
+
.login-frame:before{left:-10px;top:-10px;border-right:0;border-bottom:0}
|
|
29
|
+
.login-frame:after{right:-10px;bottom:-10px;border-left:0;border-top:0}
|
|
30
|
+
.login-meta{display:flex;justify-content:space-between;font-size:clamp(5px,0.5vw,9px);letter-spacing:.22em;color:rgba(240,138,29,.55);text-transform:uppercase}
|
|
31
|
+
.login-line1{margin:clamp(6px,1vh,13px) 0 clamp(5px,.8vh,10px);font-size:clamp(9px,1.4vw,27px);font-weight:700;letter-spacing:.03em;white-space:nowrap;color:#f7a23a;text-shadow:0 0 7px rgba(240,138,29,.3)}
|
|
32
|
+
.login-line1 .l1c{display:inline-block;min-width:.32em}
|
|
33
|
+
.login-line2{position:relative;height:1.5em;font-size:clamp(7px,.9vw,17.3px);letter-spacing:.02em;white-space:nowrap;color:#ffb04d;text-shadow:0 0 6px rgba(240,138,29,.3)}
|
|
34
|
+
.login-l2-track{position:absolute;left:0;top:0;display:inline-flex;align-items:baseline;white-space:nowrap;will-change:transform}
|
|
35
|
+
.login-l2-head{display:inline-flex;align-items:baseline}
|
|
36
|
+
.login-scan-wrap{position:relative;display:inline-block;--p:0%;line-height:1}
|
|
37
|
+
#login-scan-text{display:inline-block;line-height:1;-webkit-mask-image:linear-gradient(to bottom,#000 0 var(--p),transparent var(--p));mask-image:linear-gradient(to bottom,#000 0 var(--p),transparent var(--p))}
|
|
38
|
+
#login-scan-bar{position:absolute;left:-3%;width:106%;height:1px;top:0;background:#ffb04d;box-shadow:0 0 5px 1px rgba(240,138,29,.85);pointer-events:none;opacity:0}
|
|
39
|
+
#login-colon{opacity:0}
|
|
40
|
+
#login-name{color:#f08a1d;display:inline-block;white-space:nowrap}
|
|
41
|
+
.login-line2 .nmc{display:inline-block;text-align:center;vertical-align:baseline;line-height:1}
|
|
42
|
+
.login-line2 .nmc.settled{color:#ffc36b}
|
|
43
|
+
#login-caret{display:inline-block;width:.09em;height:.9em;background:#f08a1d;margin-left:.08em;opacity:0;transform:translateY(.08em)}
|
|
44
|
+
.login-foot{margin-top:clamp(8px,1.4vh,18px);color:rgba(240,138,29,.45)}
|
|
45
|
+
.login-voice-layer{position:absolute;inset:0;width:100%;height:100%;pointer-events:none;z-index:2}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
{
|
|
2
|
-
"schemaVersion": 1,
|
|
3
|
-
"id": "division-bigfish-codex",
|
|
4
|
-
"name": "全景大肥鱼-含彩蛋版",
|
|
5
|
-
"engine": "iframe",
|
|
6
|
-
"entry": "index.html",
|
|
7
|
-
"author": "LeeRolling",
|
|
8
|
-
"description": "全景大肥鱼风格的代码动画(含掉线彩蛋),五句配音可配效果。",
|
|
9
|
-
"duration":
|
|
10
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"schemaVersion": 1,
|
|
3
|
+
"id": "division-bigfish-codex",
|
|
4
|
+
"name": "全景大肥鱼-含彩蛋版",
|
|
5
|
+
"engine": "iframe",
|
|
6
|
+
"entry": "index.html",
|
|
7
|
+
"author": "LeeRolling",
|
|
8
|
+
"description": "全景大肥鱼风格的代码动画(含掉线彩蛋),五句配音可配效果。",
|
|
9
|
+
"duration": 33.4
|
|
10
|
+
}
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schemaVersion": 1,
|
|
3
3
|
"id": "whale-girl-scan-4k",
|
|
4
|
-
"name": "鲸鱼娘扫描睁眼(4K)",
|
|
4
|
+
"name": "鲸鱼娘扫描睁眼(4K AV1)",
|
|
5
5
|
"author": "素材:NativeDog1/dsh-boot-animation(BSD-3-Clause);8K 超分:1catmint1/dsh-boot-animation-8k;模板维护:LeeRolling",
|
|
6
6
|
"homepage": "https://github.com/LeeRolling/dsh-boot-suite",
|
|
7
7
|
"license": "BSD-3-Clause",
|
|
8
8
|
"version": "1.0.0",
|
|
9
|
-
"description": "鲸鱼娘「DeepSeek娘扫描睁眼」4K 版(3840×2160,7
|
|
9
|
+
"description": "鲸鱼娘「DeepSeek娘扫描睁眼」4K 版(3840×2160,7 秒,AV1 编码),全屏播放 + 淡入淡出。AV1 在部分机器上没有硬解、会走 CPU 软解导致掉帧;遇到掉帧请改用「鲸鱼娘扫描睁眼(4K H.264)」或 2K 版。由社区作者 1catmint1 的 8K 超分版下采样而来(8K 源:https://github.com/1catmint1/dsh-boot-animation-8k ,BSD-3-Clause);原片:NativeDog1/dsh-boot-animation(BSD-3-Clause)。桌面版建议用本 4K 版或 2K 版,8K 版在桌面端有内存崩溃风险,仅建议网页端/收藏使用。",
|
|
10
10
|
"tags": [
|
|
11
11
|
"anime",
|
|
12
12
|
"whale",
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schemaVersion": 1,
|
|
3
|
+
"id": "whale-girl-scan-4k-h264",
|
|
4
|
+
"name": "鲸鱼娘扫描睁眼(4K H.264)",
|
|
5
|
+
"author": "素材:NativeDog1/dsh-boot-animation(BSD-3-Clause);8K 超分:1catmint1/dsh-boot-animation-8k;模板维护:LeeRolling",
|
|
6
|
+
"homepage": "https://github.com/LeeRolling/dsh-boot-suite",
|
|
7
|
+
"license": "BSD-3-Clause",
|
|
8
|
+
"version": "1.0.0",
|
|
9
|
+
"description": "鲸鱼娘「DeepSeek娘扫描睁眼」4K H.264 版(3840×2160,24fps,7 秒,H.264 High 8bit 约 9.6Mbps),全屏播放 + 淡入淡出。由社区作者 1catmint1 的 8K 超分版下采样后转码为 H.264,兼容性最好:AV1 无硬解的机器(如部分 4K 掉帧环境)可改用本版。8K 源:https://github.com/1catmint1/dsh-boot-animation-8k (BSD-3-Clause);原片:NativeDog1/dsh-boot-animation(BSD-3-Clause)。",
|
|
10
|
+
"tags": [
|
|
11
|
+
"anime",
|
|
12
|
+
"whale",
|
|
13
|
+
"video",
|
|
14
|
+
"cinematic"
|
|
15
|
+
],
|
|
16
|
+
"duration": 7200,
|
|
17
|
+
"theme": {
|
|
18
|
+
"accent": "#4d6bfe",
|
|
19
|
+
"glitchA": "#ff3b30",
|
|
20
|
+
"glitchB": "#2971b8"
|
|
21
|
+
},
|
|
22
|
+
"segments": [
|
|
23
|
+
{
|
|
24
|
+
"name": "扫描 · 睁眼",
|
|
25
|
+
"from": 0,
|
|
26
|
+
"to": 7200
|
|
27
|
+
}
|
|
28
|
+
],
|
|
29
|
+
"layers": [
|
|
30
|
+
{
|
|
31
|
+
"id": "bg",
|
|
32
|
+
"type": "panel",
|
|
33
|
+
"pos": [
|
|
34
|
+
640,
|
|
35
|
+
360
|
|
36
|
+
],
|
|
37
|
+
"panelW": 1280,
|
|
38
|
+
"panelH": 720,
|
|
39
|
+
"fill": "#000000",
|
|
40
|
+
"radius": 0,
|
|
41
|
+
"keyframes": [
|
|
42
|
+
{
|
|
43
|
+
"t": 0,
|
|
44
|
+
"opacity": 1
|
|
45
|
+
}
|
|
46
|
+
]
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
"id": "whale",
|
|
50
|
+
"type": "video",
|
|
51
|
+
"pos": [
|
|
52
|
+
640,
|
|
53
|
+
360
|
|
54
|
+
],
|
|
55
|
+
"videoW": 1280,
|
|
56
|
+
"videoH": 720,
|
|
57
|
+
"src": "whale-girl-scan-4k-h264.mp4",
|
|
58
|
+
"keyframes": [
|
|
59
|
+
{
|
|
60
|
+
"t": 0,
|
|
61
|
+
"opacity": 1
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
"t": 7200,
|
|
65
|
+
"opacity": 1
|
|
66
|
+
}
|
|
67
|
+
]
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
"id": "credit",
|
|
71
|
+
"type": "text",
|
|
72
|
+
"text": "WHALE GIRL · NATIVEDOG1/DSH-BOOT-ANIMATION · 8K SOURCE: 1CATMINT1 · BSD-3-CLAUSE",
|
|
73
|
+
"pos": [
|
|
74
|
+
640,
|
|
75
|
+
360
|
|
76
|
+
],
|
|
77
|
+
"align": "center",
|
|
78
|
+
"font": {
|
|
79
|
+
"size": 9,
|
|
80
|
+
"weight": 400,
|
|
81
|
+
"tracking": 0.18
|
|
82
|
+
},
|
|
83
|
+
"color": "rgba(139,232,255,.55)",
|
|
84
|
+
"keyframes": [
|
|
85
|
+
{
|
|
86
|
+
"t": 0,
|
|
87
|
+
"opacity": 0,
|
|
88
|
+
"offsetY": 318
|
|
89
|
+
},
|
|
90
|
+
{
|
|
91
|
+
"t": 600,
|
|
92
|
+
"opacity": 1,
|
|
93
|
+
"offsetY": 318
|
|
94
|
+
},
|
|
95
|
+
{
|
|
96
|
+
"t": 7200,
|
|
97
|
+
"opacity": 1,
|
|
98
|
+
"offsetY": 318
|
|
99
|
+
}
|
|
100
|
+
]
|
|
101
|
+
}
|
|
102
|
+
],
|
|
103
|
+
"effects": []
|
|
104
|
+
}
|
package/test/smoke-package.mjs
CHANGED
|
@@ -113,12 +113,61 @@ if (/resetPlayedAfter\(cfg\.loadingStart\)/.test(bigfishApp)) throw new Error('
|
|
|
113
113
|
if (!bigfishApp.includes('cueFailTimer')) throw new Error('重连提示音缺少播放失败的兜底解除门控')
|
|
114
114
|
/* v2.15.15:重连提示音也要走插件的配音效果;line3 顺延,避免和 line2 叠音 */
|
|
115
115
|
if (!bigfishApp.includes("attachVoiceFx('reconnect')")) throw new Error('重连提示音未接入配音效果')
|
|
116
|
-
if (!bigfishApp.includes("[
|
|
117
|
-
if (!bigfishCfg.includes("[
|
|
116
|
+
if (!bigfishApp.includes("[25.0,'line3',3.300]")) throw new Error('app.js 默认时间线未把 line3 顺延到 25.0s')
|
|
117
|
+
if (!bigfishCfg.includes("[25.0,'line3',3.300]")) throw new Error('config.js 时间线未把 line3 顺延到 25.0s')
|
|
118
118
|
/* v2.15.16:掉线彩蛋等当前配音播完再弹出,不硬切语音/字幕 */
|
|
119
119
|
if (!bigfishApp.includes('掉线彩蛋若正好赶上某句配音')) throw new Error('app.js 缺少彩蛋等待当前配音播完的逻辑')
|
|
120
120
|
if (!bigfishApp.includes('eggWait=true')) throw new Error('app.js 缺少 eggWait 等待状态')
|
|
121
121
|
/* v2.15.17:字幕/波形跟随配音真实播放时钟 */
|
|
122
122
|
if (!bigfishApp.includes('__DSH_AUDIO_T__')) throw new Error('app.js 缺少配音真实时钟镜像 __DSH_AUDIO_T__')
|
|
123
123
|
if (!bigfishApp.includes('function eggVoice(){')) throw new Error('app.js 彩蛋字幕未改为音频时钟驱动')
|
|
124
|
+
/* v2.16.0:配音串行播放 + 彩蛋尾部等待(1.5x 加速段避免叠音、最后一句不被截断) */
|
|
125
|
+
if (!bigfishApp.includes('配音串行播放')) throw new Error('app.js 缺少配音串行播放(防叠音)')
|
|
126
|
+
if (!bigfishApp.includes('!__busy')) throw new Error('app.js 未按前一句播完再启动下一句')
|
|
127
|
+
if (!bigfishApp.includes('eggLeft<=6')) throw new Error('app.js 彩蛋等待条件未覆盖动画尾部')
|
|
128
|
+
if (!bigfishApp.includes('!shown&&!eggWait')) throw new Error('app.js 动画收尾未等待彩蛋语音播完')
|
|
129
|
+
|
|
130
|
+
/* v2.16.0:第一节延长 5s + 插入登录 ID 动画;读取段整体后移 */
|
|
131
|
+
if (!bigfishCfg.includes('loginStart:9.2')) throw new Error('config.js 缺少 loginStart=9.2')
|
|
132
|
+
if (!bigfishCfg.includes('loginDur:5.0')) throw new Error('config.js 缺少 loginDur=5.0')
|
|
133
|
+
if (!bigfishCfg.includes("sched:[[4.6,'orig1',2.65],[9.8,'login',1.79],[14.5,'line1',3.375],[18.4,'line2',3.232],[25.0,'line3',3.300],[30.45,'orig3',2.77]]")) throw new Error('config.js 配音时间线未按三段时间轴重排')
|
|
134
|
+
if (!bigfishApp.includes("[14.5,'line1',3.375],[18.4,'line2',3.232]")) throw new Error('app.js 默认配音时间线未同步')
|
|
135
|
+
if (!bigfishApp.includes('var LOGIN=')) throw new Error('app.js 缺少登录 ID 动画模块')
|
|
136
|
+
if (!bigfishApp.includes('voiceVT')) throw new Error('app.js 缺少静音模式的配音时间轴换算 voiceVT')
|
|
137
|
+
if (!bigfishApp.includes('sanitize')) throw new Error('app.js 缺少用户名安全化处理')
|
|
138
|
+
if (!bigfishHtml.includes('id="login"') || !bigfishHtml.includes('id="login-line1"')) throw new Error('index.html 缺少登录 ID 动画节点')
|
|
139
|
+
if (!bigfishHtml.includes('login-scan-text') || !bigfishHtml.includes('login-name')) throw new Error('index.html 缺少登录动画扫描/用户名节点')
|
|
140
|
+
if (Number(tplJson.duration) !== 33.4) throw new Error('template.json duration 未更新为 33.4')
|
|
141
|
+
/* v2.16.0 第二版:5s 登录段、整体 1/3 尺寸、贝塞尔平移、第二段配音 */
|
|
142
|
+
if (!bigfishCfg.includes("login:'assets/voice-login.wav'")) throw new Error('config.js 缺少第二段登录配音资源')
|
|
143
|
+
if (!bigfishCfg.includes("login:'特工身份确认。'")) throw new Error('config.js 缺少登录配音中文字幕')
|
|
144
|
+
if (!fs.existsSync(path.join(root, 'templates/division-bigfish-codex/assets/voice-login.wav'))) throw new Error('缺少第二段登录配音 voice-login.wav')
|
|
145
|
+
if (!bigfishHtml.includes('login-l2-track')) throw new Error('index.html 缺少贝塞尔平移轨道 login-l2-track')
|
|
146
|
+
if (!bigfishHtml.includes('login-voice-layer')) throw new Error('index.html 缺少登录段配音行图层 login-voice-layer')
|
|
147
|
+
if (!bigfishApp.includes('function bezier(')) throw new Error('app.js 缺少贝塞尔缓动实现')
|
|
148
|
+
if (!bigfishApp.includes("track.style.transform='translateX('")) throw new Error('app.js 未用 track 平移实现平滑过渡')
|
|
149
|
+
if (!bigfishApp.includes("renderVoiceRow($('login-voice')")) throw new Error('app.js 登录段未使用配音行 renderVoiceRow')
|
|
150
|
+
if (!skipCss.includes('width:min(500px,92vw)')) throw new Error('style.css 登录框未缩到 1/3 尺寸')
|
|
151
|
+
|
|
152
|
+
/* v2.16.1:4K AV1 改名 + 新增 4K H.264 模板 + 第二幕视频诊断/暂停恢复 */
|
|
153
|
+
const tpl4k = JSON.parse(fs.readFileSync(path.join(root, 'templates/whale-girl-scan-4k/template.json'), 'utf8'))
|
|
154
|
+
if (tpl4k.name !== '鲸鱼娘扫描睁眼(4K AV1)') throw new Error('4K AV1 模板名称未更新')
|
|
155
|
+
const tpl4kh = JSON.parse(fs.readFileSync(path.join(root, 'templates/whale-girl-scan-4k-h264/template.json'), 'utf8'))
|
|
156
|
+
if (tpl4kh.name !== '鲸鱼娘扫描睁眼(4K H.264)') throw new Error('缺少 4K H.264 模板名称')
|
|
157
|
+
if (!fs.existsSync(path.join(root, 'templates/whale-girl-scan-4k-h264/assets/whale-girl-scan-4k-h264.mp4'))) throw new Error('缺少 4K H.264 视频文件')
|
|
158
|
+
const splashSrc = fs.readFileSync(path.join(root, 'lib/splash.js'), 'utf8')
|
|
159
|
+
if (!splashSrc.includes('video stats ')) throw new Error('splash.js 缺少第二幕视频丢帧统计')
|
|
160
|
+
if (!splashSrc.includes('video meta ')) throw new Error('splash.js 缺少第二幕视频分辨率日志')
|
|
161
|
+
if (!splashSrc.includes('vResumeTimer')) throw new Error('splash.js 缺少省电暂停自动恢复')
|
|
162
|
+
if (!splashSrc.includes('vp0.catch')) throw new Error('splash.js 未静默 play() 失败')
|
|
163
|
+
/* v2.16.2:新增 4K H.264 必须算「正式模板」,否则第二幕下拉里看不到 */
|
|
164
|
+
const clientSrc = fs.readFileSync(path.join(root, 'lib/client.js'), 'utf8')
|
|
165
|
+
if (!clientSrc.includes("'whale-girl-scan-4k-h264': 1")) throw new Error('client.js 的正式模板白名单缺少 4K H.264')
|
|
166
|
+
/* v2.16.2:安装器代理加固 */
|
|
167
|
+
const installPs1V2162 = fs.readFileSync(path.join(root, 'tools/install.ps1'), 'utf8')
|
|
168
|
+
if (!installPs1V2162.includes('Get-ProxyInfo')) throw new Error('install.ps1 缺少代理探测')
|
|
169
|
+
if (!installPs1V2162.includes('npm_config_fetch_timeout')) throw new Error('install.ps1 缺少 pnpm 网络超时设置')
|
|
170
|
+
if (!installPs1V2162.includes('registry.npmmirror.com')) throw new Error('install.ps1 缺少国内镜像重试')
|
|
171
|
+
const helperGen = fs.readFileSync(path.join(root, 'tools/make-upgrade-helper.mjs'), 'utf8')
|
|
172
|
+
if (!helperGen.includes('turn off any proxy')) throw new Error('升级助手缺少代理提示')
|
|
124
173
|
console.log('ok package.json version=' + pkg.version + ',无 BOM,关键文件齐全(含更新前回滚 checkpoint)');
|
|
@@ -463,7 +463,7 @@ ok(intervals.every((t) => t.cleared) || intervals.length === 0, '旧的 interval
|
|
|
463
463
|
intervals.map((t) => (t.cleared ? 'cleared' : 'live')).join(','))
|
|
464
464
|
|
|
465
465
|
console.log('\n=== ⑦ v2.13.0 测试钩子 / BUILD ===')
|
|
466
|
-
ok(mod.__BUILD === 'cw-
|
|
466
|
+
ok(mod.__BUILD === 'cw-68', '__BUILD = cw-68(排查浏览器跑的是不是新包)', String(mod.__BUILD))
|
|
467
467
|
ok(mod.__VIDEO_ID === 'dsh-cw-video', '__VIDEO_ID = dsh-cw-video', String(mod.__VIDEO_ID))
|
|
468
468
|
ok(typeof mod.__startShuffle === 'function', '__startShuffle 导出')
|
|
469
469
|
ok(typeof mod.__stopShuffle === 'function', '__stopShuffle 导出')
|
package/tools/build-release.mjs
CHANGED
|
@@ -8,7 +8,7 @@ const stage = fs.mkdtempSync(path.join(os.tmpdir(), 'dsh-release-'));
|
|
|
8
8
|
const out = path.join(root, '..', '03-发布包', 'dsh-boot-suite-win.zip');
|
|
9
9
|
/* code-motion:另一条工作线(动效研究/验证)的文档与媒体,不属于插件本体,发布包不打包 */
|
|
10
10
|
/* docs:主线(编辑器重制/风格库/演示素材)文档与媒体,体积可能非常大(GB 级),不属于插件运行必需,发布包不打包 */
|
|
11
|
-
const skip = new Set(['.git', 'node_modules', '08-备份', 'code-motion', 'docs']);
|
|
11
|
+
const skip = new Set(['.git', 'node_modules', '08-备份', 'code-motion', 'docs', '02-文档', '03-发布包']);
|
|
12
12
|
function copy(src, dst) {
|
|
13
13
|
fs.mkdirSync(dst, { recursive: true });
|
|
14
14
|
for (const e of fs.readdirSync(src, { withFileTypes: true })) {
|
package/tools/install.ps1
CHANGED
|
@@ -22,6 +22,20 @@ $ErrorActionPreference = 'Stop'
|
|
|
22
22
|
function Say($m) { Write-Host $m }
|
|
23
23
|
function Die($m) { Write-Host ('[x] ' + $m) -ForegroundColor Red; exit 1 }
|
|
24
24
|
|
|
25
|
+
# v2.16.2:代理探测。开着代理时 pnpm 访问 npm registry 可能长时间卡住(用户实测第二步无响应)。
|
|
26
|
+
function Get-ProxyInfo {
|
|
27
|
+
$marks = @()
|
|
28
|
+
foreach ($n in @('HTTP_PROXY','HTTPS_PROXY','ALL_PROXY','http_proxy','https_proxy','all_proxy')) {
|
|
29
|
+
$v = [Environment]::GetEnvironmentVariable($n)
|
|
30
|
+
if ($v) { $marks += ($n + '=' + $v) }
|
|
31
|
+
}
|
|
32
|
+
try {
|
|
33
|
+
$reg = Get-ItemProperty 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Internet Settings' -ErrorAction Stop
|
|
34
|
+
if ($reg.ProxyEnable -eq 1 -and $reg.ProxyServer) { $marks += ('系统代理=' + $reg.ProxyServer) }
|
|
35
|
+
} catch {}
|
|
36
|
+
return ($marks -join ';')
|
|
37
|
+
}
|
|
38
|
+
|
|
25
39
|
$RepoRoot = Split-Path -Parent $PSScriptRoot
|
|
26
40
|
if (-not (Test-Path (Join-Path $RepoRoot 'package.json'))) { Die ('这不像插件目录:' + $RepoRoot) }
|
|
27
41
|
if (-not (Test-Path (Join-Path $RepoRoot 'lib\index.js'))) { Die '源码不完整(缺 lib\index.js),你下载的可能是残缺的压缩包' }
|
|
@@ -319,6 +333,22 @@ foreach ($profile in $targets) {
|
|
|
319
333
|
}
|
|
320
334
|
|
|
321
335
|
Say ' [2/3] 安装本插件(link 方式,改代码即生效)…'
|
|
336
|
+
$proxyInfo = Get-ProxyInfo
|
|
337
|
+
if ($proxyInfo -and -not $ManualMode) {
|
|
338
|
+
Say ''
|
|
339
|
+
Say ' [提示] 检测到代理:' + $proxyInfo
|
|
340
|
+
Say ' 已知问题:开着代理时,安装这一步(pnpm 访问 npm registry)可能长时间卡住。'
|
|
341
|
+
Say ' 如果卡住超过 2 分钟:按 Ctrl+C 关窗口 → 暂时关闭代理 → 重新双击本助手。'
|
|
342
|
+
Say ' 也可以把 registry.npmjs.org 设为直连/绕过代理。'
|
|
343
|
+
Say ''
|
|
344
|
+
for ($pi = 5; $pi -ge 1; $pi--) { Write-Host (' 5 秒后继续…(' + $pi + ')'); Start-Sleep -Seconds 1 }
|
|
345
|
+
}
|
|
346
|
+
$prevFetchTimeout = [Environment]::GetEnvironmentVariable('npm_config_fetch_timeout')
|
|
347
|
+
$prevFetchRetries = [Environment]::GetEnvironmentVariable('npm_config_fetch_retries')
|
|
348
|
+
if (-not $ManualMode) {
|
|
349
|
+
$env:npm_config_fetch_timeout = '30000'
|
|
350
|
+
$env:npm_config_fetch_retries = '2'
|
|
351
|
+
}
|
|
322
352
|
if ($ManualMode) {
|
|
323
353
|
Install-Manual $profileDir
|
|
324
354
|
} else {
|
|
@@ -328,6 +358,15 @@ foreach ($profile in $targets) {
|
|
|
328
358
|
try { $outAdd = (& $dsh plugin --profile $profile add $spec 2>&1 | Out-String) } catch { $outAdd = $_.Exception.Message }
|
|
329
359
|
if ($outAdd.Trim()) { $outAdd.Trim().Split([char]10) | ForEach-Object { ' ' + $_ } }
|
|
330
360
|
$addExit = $LASTEXITCODE
|
|
361
|
+
if ($addExit -ne 0) {
|
|
362
|
+
Say ' 第一次安装没成功,改用 npm 国内镜像重试一次…'
|
|
363
|
+
$prevRegistry = [Environment]::GetEnvironmentVariable('npm_config_registry')
|
|
364
|
+
$env:npm_config_registry = 'https://registry.npmmirror.com'
|
|
365
|
+
try { $outAdd = (& $dsh plugin --profile $profile add $spec 2>&1 | Out-String) } catch { $outAdd = $_.Exception.Message }
|
|
366
|
+
$addExit = $LASTEXITCODE
|
|
367
|
+
if ($outAdd.Trim()) { $outAdd.Trim().Split([char]10) | ForEach-Object { ' ' + $_ } }
|
|
368
|
+
if ($prevRegistry) { $env:npm_config_registry = $prevRegistry } else { Remove-Item Env:npm_config_registry -ErrorAction SilentlyContinue }
|
|
369
|
+
}
|
|
331
370
|
$ErrorActionPreference = $eapAdd
|
|
332
371
|
$installedOk = Test-InstalledOk $profileDir
|
|
333
372
|
if ($addExit -ne 0 -or $outAdd -match 'managed exclusively' -or -not $installedOk) {
|
|
@@ -342,6 +381,8 @@ foreach ($profile in $targets) {
|
|
|
342
381
|
if (Test-InstalledOk $profileDir) { $addExit = 0 } else { $addExit = 1 }
|
|
343
382
|
}
|
|
344
383
|
}
|
|
384
|
+
if ($prevFetchTimeout) { $env:npm_config_fetch_timeout = $prevFetchTimeout } else { Remove-Item Env:npm_config_fetch_timeout -ErrorAction SilentlyContinue }
|
|
385
|
+
if ($prevFetchRetries) { $env:npm_config_fetch_retries = $prevFetchRetries } else { Remove-Item Env:npm_config_fetch_retries -ErrorAction SilentlyContinue }
|
|
345
386
|
if (-not (Test-InstalledOk $profileDir)) {
|
|
346
387
|
Say ' [x] 安装后校验失败:profile 里没有可用的 dsh-boot-suite'
|
|
347
388
|
Say ' (bundles 里不会添加它,避免 DSH 启动时加载一个不存在的插件)'
|
|
@@ -61,6 +61,7 @@ const lines = [
|
|
|
61
61
|
'echo ============================================================',
|
|
62
62
|
`echo Install dsh-boot-suite v${version} from this staged package.`,
|
|
63
63
|
'echo IMPORTANT: fully quit DeepSeek Harness first (window + tray).',
|
|
64
|
+
'echo If it hangs at step 2: close this window, turn off any proxy, then double-click again.',
|
|
64
65
|
'echo ============================================================',
|
|
65
66
|
'echo.',
|
|
66
67
|
`powershell -NoProfile -ExecutionPolicy Bypass -File "${pkgInstall}"`,
|