design(prototype): 设备超限整合为全窗口挡板 overlay + 演示语言控件改 6 语言下拉
- 设备超限从脱离主窗口的独立静态帧 → 盖满可交互窗口的根级 overlay(还原真实 client 登录后挡板),桌面+移动,演示控制触发 - 顶栏演示段 LANGUAGE 从中/EN 两档 seg → 6 语言 langsel 下拉(与 Settings 一致;非中英回退英文内容) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013nMthbVEmQquxBRKb9Fj8u
This commit is contained in:
@@ -42,7 +42,7 @@
|
||||
/* ============ 桌面窗口框 ============ */
|
||||
.win{ width:980px; max-width:100%; height:640px; border-radius:16px; overflow:hidden;
|
||||
display:flex; background:var(--bg); border:1px solid var(--border-strong);
|
||||
box-shadow:var(--shadow-xl); }
|
||||
box-shadow:var(--shadow-xl); position:relative; }
|
||||
|
||||
/* 左侧栏 */
|
||||
.side{ width:210px; flex:none; background:var(--bg-subtle); border-right:1px solid var(--border);
|
||||
@@ -304,10 +304,19 @@
|
||||
.login-form{ flex:1; display:flex; flex-direction:column; justify-content:center; padding:var(--space-8); gap:var(--space-4); }
|
||||
.login-form h3{ font-family:var(--font-display); font-weight:700; font-size:20px; color:var(--fg1); margin:0 0 var(--space-2); }
|
||||
|
||||
/* 设备超限挡板帧 */
|
||||
.limit-win{ width:460px; max-width:100%; margin:0 auto; background:var(--bg); border:1px solid var(--border-strong);
|
||||
/* 设备超限挡板 overlay(登录后根级挡板,盖满整窗;对齐 device_limit_screen.dart) */
|
||||
.dl-overlay{ position:absolute; inset:0; z-index:60; background:var(--overlay);
|
||||
display:none; align-items:center; justify-content:center; padding:var(--space-6); }
|
||||
.dl-overlay.is-open{ display:flex; }
|
||||
.limit-win{ position:relative; width:460px; max-width:100%; max-height:100%; overflow:auto;
|
||||
background:var(--bg); border:1px solid var(--border-strong);
|
||||
border-radius:16px; box-shadow:var(--shadow-xl); padding:var(--space-8) var(--space-6) var(--space-6);
|
||||
display:flex; flex-direction:column; text-align:center; }
|
||||
.limit-close{ position:absolute; top:var(--space-4); right:var(--space-4); width:32px; height:32px;
|
||||
display:flex; align-items:center; justify-content:center; border:none; background:transparent;
|
||||
color:var(--fg3); cursor:pointer; border-radius:var(--radius-md); }
|
||||
.limit-close:hover{ background:var(--bg-subtle); color:var(--fg1); }
|
||||
.limit-close svg{ width:18px; height:18px; }
|
||||
.limit-ic{ width:44px; height:44px; margin:0 auto var(--space-3); color:var(--accent); }
|
||||
.limit-title{ font-family:var(--font-display); font-weight:700; font-size:20px; color:var(--fg1); }
|
||||
.limit-desc{ font-size:14px; color:var(--fg2); line-height:1.5; margin-top:8px; }
|
||||
@@ -363,17 +372,27 @@
|
||||
<div class="demo-grp"><span class="lbl" data-i18n="demo.theme">主题</span>
|
||||
<span class="seg" id="themeSeg"><button data-theme="light" data-i18n="demo.light">明</button><button data-theme="dark" data-i18n="demo.dark">暗</button></span></div>
|
||||
<div class="demo-grp"><span class="lbl" data-i18n="demo.lang">语言</span>
|
||||
<span class="seg" id="langSeg"><button data-lang="zh">中</button><button data-lang="en">EN</button></span></div>
|
||||
<span class="langsel" id="demoLang"><button class="langsel-trigger" id="demoLangTrig" aria-expanded="false"><span id="demoLangLabel">简体中文</span><svg><use href="#i-chevron-down"/></svg></button>
|
||||
<div class="menu" id="demoLangMenu" hidden>
|
||||
<button class="menu-item" data-langlabel="简体中文" data-lang="zh">简体中文</button>
|
||||
<button class="menu-item" data-langlabel="English" data-lang="en">English</button>
|
||||
<button class="menu-item" data-langlabel="日本語" data-lang="en">日本語</button>
|
||||
<button class="menu-item" data-langlabel="한국어" data-lang="en">한국어</button>
|
||||
<button class="menu-item" data-langlabel="Русский" data-lang="en">Русский</button>
|
||||
<button class="menu-item" data-langlabel="Español" data-lang="en">Español</button>
|
||||
</div></span></div>
|
||||
<div class="demo-grp"><span class="lbl" data-i18n="demo.persp">视角</span>
|
||||
<span class="seg" id="perspSeg"><button data-persp="free" data-i18n="plan.free">免费版</button><button data-persp="pro">PRO</button></span></div>
|
||||
<div class="demo-grp"><span class="lbl" data-i18n="demo.upd">更新条</span>
|
||||
<span class="seg" id="updSeg"><button data-upd="on" data-i18n="demo.show">显</button><button data-upd="off" data-i18n="demo.hide">隐</button></span></div>
|
||||
<div class="demo-grp"><span class="lbl" data-i18n="demo.gate">挡板</span>
|
||||
<span class="seg" id="gateSeg"><button id="dlGateBtn" data-i18n="demo.deviceLimit">设备超限</button></span></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="wrap">
|
||||
<p class="lead">
|
||||
单窗口可交互桌面客户端(<code>980×640</code>)。左侧栏切视图、连接键状态机、设置开关真能开关、语言中/EN 单显切换、视角 免费版/PRO 切换。品牌区与底部会员卡均可进账户。顶栏演示控制段与设置页开关双向联动。登录与设备超限另附独立静态帧。
|
||||
单窗口可交互桌面客户端(<code>980×640</code>)。左侧栏切视图、连接键状态机、设置开关真能开关、语言中/EN 单显切换、视角 免费版/PRO 切换。品牌区与底部会员卡均可进账户。顶栏演示控制段与设置页开关双向联动;「挡板」段可唤出登录后设备超限挡板(盖满整窗、可关闭)。登录另附独立静态帧。
|
||||
</p>
|
||||
|
||||
<div class="stage">
|
||||
@@ -930,6 +949,35 @@
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 登录后设备超限挡板 overlay(根级、盖满整窗;演示控制「挡板 · 设备超限」触发) -->
|
||||
<div class="dl-overlay" id="dlOverlay">
|
||||
<div class="limit-win">
|
||||
<button class="limit-close" id="dlClose" aria-label="关闭"><svg><use href="#i-x"/></svg></button>
|
||||
<svg class="limit-ic"><use href="#i-monitor-smartphone"/></svg>
|
||||
<div class="limit-title" data-i18n="dl.title">设备数已达上限</div>
|
||||
<div class="limit-desc" data-i18n="dl.desc">你的套餐最多 5 台设备,请移除一台以继续。</div>
|
||||
<button class="limit-remove js-dl-close"><svg><use href="#i-clock"/></svg><span data-i18n="dl.remove">移除最久未用</span></button>
|
||||
<div class="limit-list">
|
||||
<div class="device-row">
|
||||
<svg class="dv-lead"><use href="#i-smartphone"/></svg>
|
||||
<div class="dv-body"><div class="dv-name">iPhone 15</div><div class="dv-sub"><span data-i18n="dev.lastOnline">最后在线</span> <span data-i18n="dev.h2">2 小时前</span></div></div>
|
||||
<div class="dv-trail"><button class="btn btn-danger js-dl-close" data-i18n="dev.remove">移除</button></div>
|
||||
</div>
|
||||
<div class="device-row">
|
||||
<svg class="dv-lead"><use href="#i-laptop"/></svg>
|
||||
<div class="dv-body"><div class="dv-name">MacBook Pro</div><div class="dv-sub"><span class="dv-cur" data-i18n="dev.current">本机</span></div></div>
|
||||
<div class="dv-trail"></div>
|
||||
</div>
|
||||
<div class="device-row">
|
||||
<svg class="dv-lead"><use href="#i-monitor"/></svg>
|
||||
<div class="dv-body"><div class="dv-name">iPad Air</div><div class="dv-sub"><span data-i18n="dev.lastOnline">最后在线</span> <span data-i18n="dev.yesterday">昨天</span></div></div>
|
||||
<div class="dv-trail"><button class="btn btn-danger js-dl-close" data-i18n="dev.remove">移除</button></div>
|
||||
</div>
|
||||
</div>
|
||||
<button class="limit-logout js-dl-close" data-i18n="dl.logout">退出登录</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -962,34 +1010,6 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 独立静态帧:设备超限挡板(对齐 device_limit_screen.dart) -->
|
||||
<div class="frame-wrap">
|
||||
<div class="frame-cap"><span class="n">设备超限</span><span data-i18n="dl.frame">登录后设备数超上限挡板</span><span class="frame-note" data-i18n="login.note">(独立静态屏,不并入交互窗口)</span></div>
|
||||
<div class="limit-win">
|
||||
<svg class="limit-ic"><use href="#i-monitor-smartphone"/></svg>
|
||||
<div class="limit-title" data-i18n="dl.title">设备数已达上限</div>
|
||||
<div class="limit-desc" data-i18n="dl.desc">你的套餐最多 5 台设备,请移除一台以继续。</div>
|
||||
<button class="limit-remove"><svg><use href="#i-clock"/></svg><span data-i18n="dl.remove">移除最久未用</span></button>
|
||||
<div class="limit-list">
|
||||
<div class="device-row">
|
||||
<svg class="dv-lead"><use href="#i-smartphone"/></svg>
|
||||
<div class="dv-body"><div class="dv-name">iPhone 15</div><div class="dv-sub"><span data-i18n="dev.lastOnline">最后在线</span> <span data-i18n="dev.h2">2 小时前</span></div></div>
|
||||
<div class="dv-trail"><button class="btn btn-danger" data-i18n="dev.remove">移除</button></div>
|
||||
</div>
|
||||
<div class="device-row">
|
||||
<svg class="dv-lead"><use href="#i-laptop"/></svg>
|
||||
<div class="dv-body"><div class="dv-name">MacBook Pro</div><div class="dv-sub"><span class="dv-cur" data-i18n="dev.current">本机</span></div></div>
|
||||
<div class="dv-trail"></div>
|
||||
</div>
|
||||
<div class="device-row">
|
||||
<svg class="dv-lead"><use href="#i-monitor"/></svg>
|
||||
<div class="dv-body"><div class="dv-name">iPad Air</div><div class="dv-sub"><span data-i18n="dev.lastOnline">最后在线</span> <span data-i18n="dev.yesterday">昨天</span></div></div>
|
||||
<div class="dv-trail"><button class="btn btn-danger" data-i18n="dev.remove">移除</button></div>
|
||||
</div>
|
||||
</div>
|
||||
<button class="limit-logout" data-i18n="dl.logout">退出登录</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
@@ -1079,7 +1099,6 @@ var I18N = {
|
||||
'contact.email':{zh:'邮箱客服',en:'Email support'}, 'contact.web':{zh:'官网',en:'Website'},
|
||||
'contact.hoursTitle':{zh:'服务时间',en:'Support hours'}, 'contact.hours':{zh:'每日 9:00 – 24:00 (GMT+8)',en:'Daily 9:00 – 24:00 (GMT+8)'},
|
||||
'ub.title':{zh:'发现新版本 v2.5.0,建议更新',en:'New version v2.5.0 available'}, 'ub.cta':{zh:'立即更新',en:'Update'},
|
||||
'dl.frame':{zh:'登录后设备数超上限挡板',en:'Post-login device limit gate'},
|
||||
'dl.title':{zh:'设备数已达上限',en:'Device limit reached'},
|
||||
'dl.desc':{zh:'你的套餐最多 5 台设备,请移除一台以继续。',en:'Your plan allows up to 5 devices. Remove one to continue.'},
|
||||
'dl.remove':{zh:'移除最久未用',en:'Remove least recently used'}, 'dl.logout':{zh:'退出登录',en:'Sign out'},
|
||||
@@ -1090,6 +1109,7 @@ var I18N = {
|
||||
'demo.theme':{zh:'主题',en:'Theme'}, 'demo.light':{zh:'明',en:'Light'}, 'demo.dark':{zh:'暗',en:'Dark'},
|
||||
'demo.lang':{zh:'语言',en:'Language'}, 'demo.persp':{zh:'视角',en:'Perspective'},
|
||||
'demo.upd':{zh:'更新条',en:'Banner'}, 'demo.show':{zh:'显',en:'On'}, 'demo.hide':{zh:'隐',en:'Off'},
|
||||
'demo.gate':{zh:'挡板',en:'Gate'}, 'demo.deviceLimit':{zh:'设备超限',en:'Device limit'},
|
||||
'login.frame':{zh:'分屏卡 · 品牌左 / 表单右',en:'Split card · brand left / form right'},
|
||||
'login.note':{zh:'(独立静态屏,不并入交互窗口)',en:'(standalone static screen, outside the interactive window)'},
|
||||
'login.slogan':{zh:'极速畅连 · 稳定加速线路<br>隐私保护 · 全程无日志',en:'Fast & stable lines<br>Privacy protected · No logs'},
|
||||
@@ -1304,7 +1324,8 @@ function renderStatsChart(){
|
||||
function syncSegs(){
|
||||
document.querySelectorAll('#themeSeg button').forEach(function(b){ b.classList.toggle('is-active', b.dataset.theme===S.theme); });
|
||||
var _tbi=document.getElementById('tbThemeIcon'); if(_tbi) _tbi.setAttribute('href', S.theme==='dark'?'#i-sun':'#i-moon');
|
||||
document.querySelectorAll('#langSeg button').forEach(function(b){ b.classList.toggle('is-active', b.dataset.lang===S.lang); });
|
||||
document.getElementById('demoLangLabel').textContent = S.langLabel;
|
||||
document.querySelectorAll('#demoLangMenu .menu-item').forEach(function(m){ m.classList.toggle('is-selected', m.dataset.langlabel===S.langLabel); });
|
||||
document.querySelectorAll('#perspSeg button').forEach(function(b){ b.classList.toggle('is-active', b.dataset.persp===S.persp); });
|
||||
document.querySelectorAll('#updSeg button').forEach(function(b){ b.classList.toggle('is-active', (b.dataset.upd==='on')===S.upd); });
|
||||
document.querySelectorAll('[data-toggle="dark"]').forEach(function(t){ t.classList.toggle('is-on', S.theme==='dark'); });
|
||||
@@ -1361,12 +1382,25 @@ document.querySelectorAll('.server-row').forEach(function(row){
|
||||
document.querySelectorAll('#themeSeg button').forEach(function(b){ b.addEventListener('click', function(){ applyTheme(b.dataset.theme); }); });
|
||||
var _tbt=document.getElementById('tbTheme'); if(_tbt) _tbt.addEventListener('click', function(){ applyTheme(S.theme==='dark'?'light':'dark'); });
|
||||
/* 顶栏语言段控(中/EN 驱动实际 i18n;同步 langsel) */
|
||||
document.querySelectorAll('#langSeg button').forEach(function(b){
|
||||
b.addEventListener('click', function(){
|
||||
S.lang=b.dataset.lang; S.langLabel = (S.lang==='zh') ? '简体中文' : 'English';
|
||||
var demoLang = document.getElementById('demoLang');
|
||||
var demoLangMenu = document.getElementById('demoLangMenu');
|
||||
var demoLangTrig = document.getElementById('demoLangTrig');
|
||||
demoLangTrig.addEventListener('click', function(e){
|
||||
e.stopPropagation();
|
||||
var open = demoLangMenu.hasAttribute('hidden');
|
||||
if(open){ demoLangMenu.removeAttribute('hidden'); demoLangTrig.setAttribute('aria-expanded','true'); demoLang.classList.add('is-open'); }
|
||||
else { demoLangMenu.setAttribute('hidden',''); demoLangTrig.setAttribute('aria-expanded','false'); demoLang.classList.remove('is-open'); }
|
||||
});
|
||||
document.querySelectorAll('#demoLangMenu .menu-item').forEach(function(m){
|
||||
m.addEventListener('click', function(){
|
||||
S.langLabel = m.dataset.langlabel; S.lang = m.dataset.lang; // 非中文词典的语言回退英文内容
|
||||
demoLangMenu.setAttribute('hidden',''); demoLangTrig.setAttribute('aria-expanded','false'); demoLang.classList.remove('is-open');
|
||||
applyLang(); syncSegs();
|
||||
});
|
||||
});
|
||||
document.addEventListener('click', function(){
|
||||
if(!demoLangMenu.hasAttribute('hidden')){ demoLangMenu.setAttribute('hidden',''); demoLangTrig.setAttribute('aria-expanded','false'); demoLang.classList.remove('is-open'); }
|
||||
});
|
||||
/* 顶栏视角段控 */
|
||||
document.querySelectorAll('#perspSeg button').forEach(function(b){
|
||||
b.addEventListener('click', function(){
|
||||
@@ -1380,6 +1414,17 @@ document.querySelectorAll('#updSeg button').forEach(function(b){
|
||||
});
|
||||
document.getElementById('updClose').addEventListener('click', function(){ S.upd=false; applyUpd(); });
|
||||
|
||||
/* ========= 登录后设备超限挡板 overlay(演示:开/关,不真删设备) ========= */
|
||||
(function(){
|
||||
var ov=document.getElementById('dlOverlay'), btn=document.getElementById('dlGateBtn');
|
||||
if(!ov) return;
|
||||
function open(){ ov.classList.add('is-open'); if(btn) btn.classList.add('is-active'); }
|
||||
function close(){ ov.classList.remove('is-open'); if(btn) btn.classList.remove('is-active'); }
|
||||
if(btn) btn.addEventListener('click', function(){ ov.classList.contains('is-open') ? close() : open(); });
|
||||
var x=document.getElementById('dlClose'); if(x) x.addEventListener('click', close);
|
||||
ov.querySelectorAll('.js-dl-close').forEach(function(el){ el.addEventListener('click', close); });
|
||||
})();
|
||||
|
||||
/* 设置/账户开关(深色 ↔ 主题双向联动;其余独立开关) */
|
||||
document.querySelectorAll('.toggle').forEach(function(t){
|
||||
t.addEventListener('click', function(){
|
||||
|
||||
@@ -207,6 +207,11 @@
|
||||
font-family:var(--font-sans); font-size:var(--text-sm); font-weight:600;
|
||||
padding:var(--space-3); margin-top:var(--space-3); }
|
||||
|
||||
/* 设备超限挡板 overlay(登录后根级挡板,盖满 App 窗口;演示控制「挡板」触发) */
|
||||
#deviceLimitOverlay{ position:absolute; left:0; right:0; top:30px; bottom:0; z-index:45;
|
||||
background:var(--bg); display:none; flex-direction:column; }
|
||||
#deviceLimitOverlay.is-open{ display:flex; }
|
||||
|
||||
/* 购买流程覆盖层(从账户页「兑换 & 购买」进入;移植 purchase.html 状态机,命名空间 .pur-*) */
|
||||
#purchaseOverlay{ position:absolute; left:0; right:0; top:30px; bottom:0; z-index:45;
|
||||
background:var(--bg); display:none; flex-direction:column; }
|
||||
@@ -373,9 +378,16 @@
|
||||
</div>
|
||||
<div class="demo-grp">
|
||||
<span class="gl" data-i18n="demoLang">语言</span>
|
||||
<div class="seg" id="segLang">
|
||||
<button data-v="zh">中文</button>
|
||||
<button data-v="en">EN</button>
|
||||
<div class="langsel" id="demoLang">
|
||||
<button class="langsel-trigger" id="demoLangTrigger" aria-expanded="false"><span id="demoLangLabel">简体中文</span><svg><use href="#i-chevron-down"/></svg></button>
|
||||
<div class="menu" id="demoLangMenu" hidden>
|
||||
<button class="menu-item is-selected" data-lang="zh" data-label="简体中文">简体中文</button>
|
||||
<button class="menu-item" data-lang="en" data-label="English">English</button>
|
||||
<button class="menu-item" data-lang="ja" data-label="日本語">日本語</button>
|
||||
<button class="menu-item" data-lang="ko" data-label="한국어">한국어</button>
|
||||
<button class="menu-item" data-lang="ru" data-label="Русский">Русский</button>
|
||||
<button class="menu-item" data-lang="es" data-label="Español">Español</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="demo-grp">
|
||||
@@ -392,13 +404,17 @@
|
||||
<button data-v="hide" data-i18n="segHide">隐藏</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="demo-grp">
|
||||
<span class="gl" data-i18n="demoGate">挡板</span>
|
||||
<div class="seg"><button id="dlGateBtn" data-i18n="demoDeviceLimit">设备超限</button></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="wrap">
|
||||
<p class="lead">
|
||||
单机可交互原型:底部四 Tab、连接键三态状态机(未连接 → 连接中 → 已连接)、
|
||||
节点选择联动、套餐视角切换。全部复用 <code>../atoms.css</code> 原子,vanilla JS 无依赖。用顶栏右侧演示控制段切主题 / 语言 / 视角 / 更新提示。
|
||||
节点选择联动、套餐视角切换。全部复用 <code>../atoms.css</code> 原子,vanilla JS 无依赖。用顶栏右侧演示控制段切主题 / 语言 / 视角 / 更新提示,「挡板」可唤出登录后设备超限挡板(盖满 App 窗口、可关闭)。
|
||||
</p>
|
||||
|
||||
<div class="stage">
|
||||
@@ -1013,6 +1029,45 @@
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 登录后设备超限挡板 overlay(根级、盖满 App 窗口;演示控制「挡板 · 设备超限」触发) -->
|
||||
<div id="deviceLimitOverlay">
|
||||
<div class="dl-body">
|
||||
<div class="dl-hero">
|
||||
<span class="dl-ic"><svg><use href="#i-monitor-smartphone"/></svg></span>
|
||||
<div class="dl-title" data-i18n="dlTitle">设备数已达上限</div>
|
||||
<div class="dl-desc" data-i18n="dlDesc">你的账户最多可同时登录 5 台设备,请移除一台后继续。</div>
|
||||
</div>
|
||||
<button class="dl-outline js-dl-close"><svg><use href="#i-clock"/></svg><span data-i18n="dlRemoveLru">移除最久未用</span></button>
|
||||
<div class="dl-list">
|
||||
<div class="device-row">
|
||||
<span class="icon-box"><svg><use href="#i-smartphone"/></svg></span>
|
||||
<div class="dv-body">
|
||||
<div class="dv-name">iPhone 15<span class="dv-badge" data-i18n="thisDevice">本机</span></div>
|
||||
<div class="dv-sub"><span class="status-dot is-online"></span><span data-i18n="dlOnline">在线</span></div>
|
||||
</div>
|
||||
<div class="dv-trail"></div>
|
||||
</div>
|
||||
<div class="device-row">
|
||||
<span class="icon-box"><svg><use href="#i-laptop"/></svg></span>
|
||||
<div class="dv-body">
|
||||
<div class="dv-name">MacBook Pro</div>
|
||||
<div class="dv-sub"><span class="status-dot is-offline"></span><span><span data-i18n="lastOnline">最后在线</span> <span data-i18n="rel2h">2 小时前</span></span></div>
|
||||
</div>
|
||||
<div class="dv-trail"><button class="dl-rm js-dl-close" data-i18n="dlRemove">移除</button></div>
|
||||
</div>
|
||||
<div class="device-row">
|
||||
<span class="icon-box"><svg><use href="#i-monitor-smartphone"/></svg></span>
|
||||
<div class="dv-body">
|
||||
<div class="dv-name">iPad Air</div>
|
||||
<div class="dv-sub"><span class="status-dot is-offline"></span><span><span data-i18n="lastOnline">最后在线</span> <span data-i18n="relYday">昨天</span></span></div>
|
||||
</div>
|
||||
<div class="dv-trail"><button class="dl-rm js-dl-close" data-i18n="dlRemove">移除</button></div>
|
||||
</div>
|
||||
</div>
|
||||
<button class="dl-logout js-dl-close" data-i18n="logout">退出登录</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1088,63 +1143,6 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 静态设备超限挡板屏(不入状态机) -->
|
||||
<div class="frame-wrap">
|
||||
<div class="frame-cap"><span class="n">静态</span>设备超限挡板 · #16</div>
|
||||
<div class="phone">
|
||||
<div class="status-bar">
|
||||
<span class="sb-time">9:41</span>
|
||||
<div class="sb-right">
|
||||
<span class="sb-sig"><i></i><i></i><i></i><i></i></span>
|
||||
<svg><use href="#i-wifi"/></svg>
|
||||
<span class="sb-bat"><i></i></span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="dl-body">
|
||||
<div class="dl-hero">
|
||||
<span class="dl-ic"><svg><use href="#i-monitor-smartphone"/></svg></span>
|
||||
<div class="dl-title">设备数已达上限</div>
|
||||
<div class="dl-desc">你的账户最多可同时登录 5 台设备,请移除一台后继续。</div>
|
||||
</div>
|
||||
<button class="dl-outline"><svg><use href="#i-clock"/></svg>移除最久未用</button>
|
||||
<div class="dl-list">
|
||||
<div class="device-row">
|
||||
<span class="icon-box"><svg><use href="#i-smartphone"/></svg></span>
|
||||
<div class="dv-body">
|
||||
<div class="dv-name">iPhone 15<span class="dv-badge">本机</span></div>
|
||||
<div class="dv-sub"><span class="status-dot is-online"></span><span>在线</span></div>
|
||||
</div>
|
||||
<div class="dv-trail"></div>
|
||||
</div>
|
||||
<div class="device-row">
|
||||
<span class="icon-box"><svg><use href="#i-laptop"/></svg></span>
|
||||
<div class="dv-body">
|
||||
<div class="dv-name">MacBook Pro</div>
|
||||
<div class="dv-sub"><span class="status-dot is-offline"></span><span>最后在线 2 小时前</span></div>
|
||||
</div>
|
||||
<div class="dv-trail"><button class="dl-rm">移除</button></div>
|
||||
</div>
|
||||
<div class="device-row">
|
||||
<span class="icon-box"><svg><use href="#i-monitor-smartphone"/></svg></span>
|
||||
<div class="dv-body">
|
||||
<div class="dv-name">iPad Air</div>
|
||||
<div class="dv-sub"><span class="status-dot is-offline"></span><span>最后在线 昨天</span></div>
|
||||
</div>
|
||||
<div class="dv-trail"><button class="dl-rm">移除</button></div>
|
||||
</div>
|
||||
<div class="device-row">
|
||||
<span class="icon-box"><svg><use href="#i-laptop"/></svg></span>
|
||||
<div class="dv-body">
|
||||
<div class="dv-name">Windows PC</div>
|
||||
<div class="dv-sub"><span class="status-dot is-offline"></span><span>最后在线 3 天前</span></div>
|
||||
</div>
|
||||
<div class="dv-trail"><button class="dl-rm">移除</button></div>
|
||||
</div>
|
||||
</div>
|
||||
<button class="dl-logout">退出登录</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1154,6 +1152,8 @@ const I18N = {
|
||||
zh:{
|
||||
brandName:'穿山甲', brandLatin:'Pangolin',
|
||||
demoTheme:'主题', demoLang:'语言', demoView:'视角', demoUpdate:'更新',
|
||||
demoGate:'挡板', demoDeviceLimit:'设备超限',
|
||||
dlTitle:'设备数已达上限', dlDesc:'你的账户最多可同时登录 5 台设备,请移除一台后继续。', dlRemoveLru:'移除最久未用', dlRemove:'移除', dlOnline:'在线',
|
||||
segLight:'明', segDark:'暗', segFree:'免费版', segPro:'PRO',
|
||||
segShow:'显示', segHide:'隐藏',
|
||||
navConnect:'连接', navNodes:'节点', navStats:'统计', navAccount:'账户',
|
||||
@@ -1223,6 +1223,8 @@ const I18N = {
|
||||
en:{
|
||||
brandName:'Pangolin', brandLatin:'',
|
||||
demoTheme:'Theme', demoLang:'Language', demoView:'View', demoUpdate:'Update',
|
||||
demoGate:'Gate', demoDeviceLimit:'Device limit',
|
||||
dlTitle:'Device limit reached', dlDesc:'Your account allows up to 5 devices at once. Remove one to continue.', dlRemoveLru:'Remove least recently used', dlRemove:'Remove', dlOnline:'Online',
|
||||
segLight:'Light', segDark:'Dark', segFree:'Free', segPro:'PRO',
|
||||
segShow:'Show', segHide:'Hide',
|
||||
navConnect:'Connect', navNodes:'Nodes', navStats:'Stats', navAccount:'Account',
|
||||
@@ -1521,7 +1523,7 @@ function render(){
|
||||
$('#themeSub').textContent = dark ? D().stateOn : D().followLight;
|
||||
|
||||
// seg 同步
|
||||
syncSeg('#segLang', state.lang);
|
||||
syncDemoLang();
|
||||
syncSeg('#segPersona', state.persona);
|
||||
syncSeg('#segTheme', state.theme);
|
||||
syncSeg('#segUpdate', state.update);
|
||||
@@ -1607,10 +1609,23 @@ $('#themeToggle').addEventListener('click', ()=>applyTheme(state.theme==='dark'?
|
||||
|
||||
// 演示控制段(主题 / 语言 / 视角 / 额度 / 更新)
|
||||
$('#segTheme').addEventListener('click', e=>{ const b=e.target.closest('button'); if(b) applyTheme(b.dataset.v); });
|
||||
$('#segLang').addEventListener('click', e=>{ const b=e.target.closest('button'); if(b){ state.lang=b.dataset.v; syncAcctLang(); render(); } });
|
||||
const demoLang=$('#demoLang'), demoMenu=$('#demoLangMenu'), demoTrigger=$('#demoLangTrigger');
|
||||
demoTrigger.addEventListener('click', e=>{ e.stopPropagation(); const open=demoMenu.hidden; demoMenu.hidden=!open; demoTrigger.setAttribute('aria-expanded', String(open)); });
|
||||
document.addEventListener('click', ()=>{ demoMenu.hidden=true; demoTrigger.setAttribute('aria-expanded','false'); });
|
||||
demoMenu.addEventListener('click', e=>{ const it=e.target.closest('.menu-item'); if(!it) return; e.stopPropagation(); demoMenu.querySelectorAll('.menu-item').forEach(m=>m.classList.toggle('is-selected', m===it)); $('#demoLangLabel').textContent=it.dataset.label; demoMenu.hidden=true; demoTrigger.setAttribute('aria-expanded','false'); if(it.dataset.lang==='zh'||it.dataset.lang==='en'){ state.lang=it.dataset.lang; syncAcctLang(); render(); } });
|
||||
$('#segPersona').addEventListener('click', e=>{ const b=e.target.closest('button'); if(b){ state.persona=b.dataset.v; render(); } });
|
||||
$('#segUpdate').addEventListener('click', e=>{ const b=e.target.closest('button'); if(b){ state.update=b.dataset.v; render(); } });
|
||||
|
||||
// 登录后设备超限挡板 overlay(演示:开/关,不真删设备)
|
||||
(()=>{
|
||||
const ov=$('#deviceLimitOverlay'), btn=$('#dlGateBtn');
|
||||
if(!ov) return;
|
||||
const open=()=>{ ov.classList.add('is-open'); if(btn) btn.classList.add('is-active'); };
|
||||
const close=()=>{ ov.classList.remove('is-open'); if(btn) btn.classList.remove('is-active'); };
|
||||
if(btn) btn.addEventListener('click', ()=> ov.classList.contains('is-open') ? close() : open());
|
||||
ov.querySelectorAll('.js-dl-close').forEach(el=> el.addEventListener('click', close));
|
||||
})();
|
||||
|
||||
// 语言段变更时,账户语言下拉标签跟随(仅中/英)
|
||||
function syncAcctLang(){
|
||||
const map={zh:'简体中文', en:'English'};
|
||||
@@ -1618,6 +1633,13 @@ function syncAcctLang(){
|
||||
$('#acctLangLabel').textContent=label;
|
||||
acctMenu.querySelectorAll('.menu-item').forEach(m=>m.classList.toggle('is-selected', m.dataset.lang===state.lang));
|
||||
}
|
||||
// 演示控制段的语言下拉标签跟随全局 lang(仅中/英有词典,其余选中即回退英文内容)
|
||||
function syncDemoLang(){
|
||||
const map={zh:'简体中文', en:'English'};
|
||||
const label=map[state.lang]; if(!label) return;
|
||||
const el=document.getElementById('demoLangLabel'); if(el) el.textContent=label;
|
||||
document.querySelectorAll('#demoLangMenu .menu-item').forEach(m=>m.classList.toggle('is-selected', m.dataset.lang===state.lang));
|
||||
}
|
||||
|
||||
// 登录 / 注册 段控切换(静态帧)
|
||||
$('#authSeg').addEventListener('click', e=>{ const b=e.target.closest('.auth-seg-btn'); if(b){ state.authMode=b.dataset.auth; renderAuth(); } });
|
||||
|
||||
Reference in New Issue
Block a user