design(prototype): 设备⋮弹出菜单(重命名/强制退出/清除登录信息) + 设备管理页宽度收窄600居中
- 设备行 ⋮ 加弹出菜单(本机仅重命名/他机三项,清除为 danger),复用 .menu 原子,外部点击关闭 - 设备管理页内容 max-width:600 居中(对齐订单/账户页,不再全宽) 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:
@@ -167,6 +167,13 @@
|
||||
background:transparent; color:var(--fg3); cursor:pointer; border-radius:var(--radius-sm); }
|
||||
.dv-more:hover{ background:var(--bg-subtle); }
|
||||
.dv-more svg{ width:18px; height:18px; }
|
||||
/* 设备行 ⋮ 弹出菜单(复用 .menu / .menu-item 原子,加图标 + 危险项) */
|
||||
.dv-menu{ position:relative; display:inline-flex; }
|
||||
.dv-menu .menu{ min-width:172px; }
|
||||
.dv-menu .menu-item{ display:flex; align-items:center; gap:var(--space-2); }
|
||||
.dv-menu .menu-item svg{ width:15px; height:15px; flex:none; }
|
||||
.dv-menu .menu-item.is-danger{ color:var(--danger); }
|
||||
.dv-menu .menu-item.is-danger:hover{ background:var(--danger-subtle); }
|
||||
|
||||
/* ---- 设置视图 ---- */
|
||||
.settings-view{ padding:var(--space-5) var(--space-6) var(--space-6); max-width:none; }
|
||||
@@ -634,7 +641,7 @@
|
||||
|
||||
<!-- 设备管理视图(自账户页下钻) -->
|
||||
<section class="view" data-view="devices">
|
||||
<div class="account-view">
|
||||
<div class="account-view" style="max-width:600px; margin:0 auto">
|
||||
<button class="pv-back" id="dvBack"><svg><use href="#i-arrow-left"/></svg><span data-i18n="dev.back">返回</span></button>
|
||||
<div class="sec-label"><span data-i18n="acc.devices">设备管理</span> · <span id="devHeaderCount">1 / 5</span></div>
|
||||
<div class="card card-flush" id="deviceList" style="margin-bottom:var(--space-5)"></div>
|
||||
@@ -1139,6 +1146,8 @@ var I18N = {
|
||||
'dev.current':{zh:'本机',en:'This device'}, 'dev.remove':{zh:'移除',en:'Remove'}, 'dev.back':{zh:'返回',en:'Back'},
|
||||
'dev.lastOnline':{zh:'最后在线',en:'Last online'}, 'dev.now':{zh:'刚刚',en:'just now'},
|
||||
'dev.h2':{zh:'2 小时前',en:'2h ago'}, 'dev.yesterday':{zh:'昨天',en:'yesterday'},
|
||||
'dev.mRename':{zh:'重命名',en:'Rename'}, 'dev.mForceLogout':{zh:'强制退出',en:'Force logout'}, 'dev.mClearLogin':{zh:'清除登录信息',en:'Clear login info'},
|
||||
'dev.tRenamed':{zh:'已重命名(演示)',en:'Renamed (demo)'}, 'dev.tLoggedOut':{zh:'已强制退出(演示)',en:'Force logged out (demo)'}, 'dev.tCleared':{zh:'已清除登录信息(演示)',en:'Login info cleared (demo)'},
|
||||
'state.on':{zh:'已开启',en:'On'}, 'state.off':{zh:'跟随浅色',en:'Off'},
|
||||
'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'},
|
||||
@@ -1284,12 +1293,26 @@ function renderDevices(){
|
||||
+ '<div class="dv-trail">'+trailHtml+'</div></div>';
|
||||
}
|
||||
var curPill = '<span class="dv-cur">'+I18N['dev.current'][lang]+'</span>';
|
||||
var moreBtn = '<button class="dv-more" aria-label="more"><svg><use href="#i-more-vertical"/></svg></button>';
|
||||
// 本机(isLocal)只给「重命名」;非本机三项全给(清除=危险项)。菜单靠 #deviceList 委托处理。
|
||||
function devMenu(id, isLocal){
|
||||
function mi(act, icon, key, danger){
|
||||
return '<button class="menu-item dv-mi'+(danger?' is-danger':'')+'" data-act="'+act+'" data-dev="'+id+'">'
|
||||
+ '<svg><use href="#i-'+icon+'"/></svg><span>'+I18N[key][lang]+'</span></button>';
|
||||
}
|
||||
var items = mi('rename','pencil','dev.mRename',false);
|
||||
if(!isLocal){
|
||||
items += mi('logout','log-out','dev.mForceLogout',false)
|
||||
+ mi('clear','trash-2','dev.mClearLogin',true);
|
||||
}
|
||||
return '<span class="dv-menu"><button class="dv-more" aria-label="more" aria-expanded="false">'
|
||||
+ '<svg><use href="#i-more-vertical"/></svg></button>'
|
||||
+ '<div class="menu" hidden>'+items+'</div></span>';
|
||||
}
|
||||
var last = I18N['dev.lastOnline'][lang];
|
||||
var html = row('laptop','MacBook Pro', I18N['dev.current'][lang]+' · '+last+' '+I18N['dev.now'][lang], curPill);
|
||||
var html = row('laptop','MacBook Pro', I18N['dev.current'][lang]+' · '+last+' '+I18N['dev.now'][lang], curPill + devMenu('macbook', true));
|
||||
if(S.persp==='pro'){
|
||||
html += row('smartphone','iPhone 15', last+' '+I18N['dev.h2'][lang], moreBtn);
|
||||
html += row('monitor','iPad Air', last+' '+I18N['dev.yesterday'][lang], moreBtn);
|
||||
html += row('smartphone','iPhone 15', last+' '+I18N['dev.h2'][lang], devMenu('iphone', false));
|
||||
html += row('monitor','iPad Air', last+' '+I18N['dev.yesterday'][lang], devMenu('ipad', false));
|
||||
}
|
||||
list.innerHTML = html;
|
||||
var cnt = S.persp==='pro' ? 3 : 1;
|
||||
@@ -1512,6 +1535,36 @@ document.addEventListener('click', function(){
|
||||
if(!devMenu.hasAttribute('hidden')){ devMenu.setAttribute('hidden',''); devTrig.setAttribute('aria-expanded','false'); devSel.classList.remove('is-open'); }
|
||||
});
|
||||
|
||||
/* 设备行 ⋮ 弹出菜单:委托处理(行随语言/视角重渲,用委托绑在静态容器上) */
|
||||
(function(){
|
||||
var list = document.getElementById('deviceList');
|
||||
if(!list) return;
|
||||
function closeAll(){
|
||||
list.querySelectorAll('.dv-menu .menu').forEach(function(m){ m.setAttribute('hidden',''); });
|
||||
list.querySelectorAll('.dv-menu .dv-more').forEach(function(b){ b.setAttribute('aria-expanded','false'); });
|
||||
}
|
||||
list.addEventListener('click', function(e){
|
||||
var more = e.target.closest('.dv-more');
|
||||
if(more){
|
||||
e.stopPropagation();
|
||||
var menu = more.parentNode.querySelector('.menu');
|
||||
var willOpen = menu.hasAttribute('hidden');
|
||||
closeAll();
|
||||
if(willOpen){ menu.removeAttribute('hidden'); more.setAttribute('aria-expanded','true'); }
|
||||
return;
|
||||
}
|
||||
var mi = e.target.closest('.dv-mi');
|
||||
if(mi){
|
||||
e.stopPropagation();
|
||||
var act = mi.dataset.act;
|
||||
var key = act==='rename' ? 'dev.tRenamed' : (act==='logout' ? 'dev.tLoggedOut' : 'dev.tCleared');
|
||||
closeAll();
|
||||
pvToast(I18N[key][S.lang]);
|
||||
}
|
||||
});
|
||||
document.addEventListener('click', closeAll);
|
||||
})();
|
||||
|
||||
/* ========= 购买流程(兑换 & 购买,接入主框架内容区) ========= */
|
||||
/* 各币种一口价(pay 侧每 SKU 按结算币种各定价,不做实时汇率换算) */
|
||||
var PV_PRICES = {
|
||||
|
||||
@@ -166,6 +166,13 @@
|
||||
.icon-mini:hover{ color:var(--danger); background:var(--danger-subtle); }
|
||||
.icon-mini svg{ width:18px; height:18px; }
|
||||
.icon-mini.plain:hover{ color:var(--accent); background:var(--accent-subtle); }
|
||||
/* 设备行 ⋮ 弹出菜单(复用 .menu / .menu-item 原子 + 图标 + 危险项) */
|
||||
.dv-menu{ position:relative; display:inline-flex; }
|
||||
.dv-menu .menu{ min-width:168px; }
|
||||
.dv-menu .menu-item{ display:flex; align-items:center; gap:var(--space-2); }
|
||||
.dv-menu .menu-item svg{ width:15px; height:15px; flex:none; }
|
||||
.dv-menu .menu-item.is-danger{ color:var(--danger); }
|
||||
.dv-menu .menu-item.is-danger:hover{ background:var(--danger-subtle); }
|
||||
|
||||
.search-wrap{ position:relative; }
|
||||
.search-wrap > svg{ position:absolute; left:var(--space-4); top:50%; transform:translateY(-50%);
|
||||
@@ -989,7 +996,7 @@
|
||||
<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="devOnlineNow">当前在线</span></div>
|
||||
</div>
|
||||
<div class="dv-trail"><button class="icon-mini plain" aria-label="更多"><svg><use href="#i-more-vertical"/></svg></button></div>
|
||||
<div class="dv-trail"><span class="dv-menu"><button class="icon-mini plain dv-more" aria-label="更多" aria-expanded="false"><svg><use href="#i-more-vertical"/></svg></button><div class="menu" hidden><button class="menu-item dv-mi" data-act="rename"><svg><use href="#i-pencil"/></svg><span data-i18n="devRename">重命名</span></button></div></span></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -1002,7 +1009,7 @@
|
||||
<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="devOnlineNow">当前在线</span></div>
|
||||
</div>
|
||||
<div class="dv-trail"><button class="icon-mini plain" aria-label="更多"><svg><use href="#i-more-vertical"/></svg></button></div>
|
||||
<div class="dv-trail"><span class="dv-menu"><button class="icon-mini plain dv-more" aria-label="更多" aria-expanded="false"><svg><use href="#i-more-vertical"/></svg></button><div class="menu" hidden><button class="menu-item dv-mi" data-act="rename"><svg><use href="#i-pencil"/></svg><span data-i18n="devRename">重命名</span></button></div></span></div>
|
||||
</div>
|
||||
<div class="device-row">
|
||||
<span class="icon-box"><svg><use href="#i-laptop"/></svg></span>
|
||||
@@ -1010,7 +1017,7 @@
|
||||
<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="icon-mini plain" aria-label="更多"><svg><use href="#i-more-vertical"/></svg></button></div>
|
||||
<div class="dv-trail"><span class="dv-menu"><button class="icon-mini plain dv-more" aria-label="更多" aria-expanded="false"><svg><use href="#i-more-vertical"/></svg></button><div class="menu" hidden><button class="menu-item dv-mi" data-act="rename"><svg><use href="#i-pencil"/></svg><span data-i18n="devRename">重命名</span></button><button class="menu-item dv-mi" data-act="logout"><svg><use href="#i-log-out"/></svg><span data-i18n="devForceLogout">强制退出</span></button><button class="menu-item dv-mi is-danger" data-act="clear"><svg><use href="#i-trash-2"/></svg><span data-i18n="devClearLogin">清除登录信息</span></button></div></span></div>
|
||||
</div>
|
||||
<div class="device-row">
|
||||
<span class="icon-box"><svg><use href="#i-monitor-smartphone"/></svg></span>
|
||||
@@ -1018,7 +1025,7 @@
|
||||
<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="icon-mini plain" aria-label="更多"><svg><use href="#i-more-vertical"/></svg></button></div>
|
||||
<div class="dv-trail"><span class="dv-menu"><button class="icon-mini plain dv-more" aria-label="更多" aria-expanded="false"><svg><use href="#i-more-vertical"/></svg></button><div class="menu" hidden><button class="menu-item dv-mi" data-act="rename"><svg><use href="#i-pencil"/></svg><span data-i18n="devRename">重命名</span></button><button class="menu-item dv-mi" data-act="logout"><svg><use href="#i-log-out"/></svg><span data-i18n="devForceLogout">强制退出</span></button><button class="menu-item dv-mi is-danger" data-act="clear"><svg><use href="#i-trash-2"/></svg><span data-i18n="devClearLogin">清除登录信息</span></button></div></span></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -1181,6 +1188,8 @@ const I18N = {
|
||||
devFreeLbl:'我的设备 · 1 / 1 台', devProLbl:'我的设备 · 3 / 5 台',
|
||||
secDevices:'设备', myDevices:'我的设备', devMgmt:'设备管理',
|
||||
thisDevice:'本机', devOnlineNow:'当前在线', lastOnline:'最后在线', rel2h:'2 小时前', relYday:'昨天',
|
||||
devRename:'重命名', devForceLogout:'强制退出', devClearLogin:'清除登录信息',
|
||||
devRenamedToast:'已重命名(演示)', devLoggedOutToast:'已强制退出(演示)', devClearedToast:'已清除登录信息(演示)',
|
||||
secPref:'偏好', prefLang:'语言', prefTheme:'深色外观', prefProtocol:'协议', followLight:'跟随浅色', stateOn:'已开启',
|
||||
secMore:'更多', navDevices:'设备管理', navSettings:'设置', navRedeem:'兑换 & 购买',
|
||||
navContact:'联系我们', navWebUC:'网页用户中心', logout:'退出登录',
|
||||
@@ -1253,6 +1262,8 @@ const I18N = {
|
||||
devFreeLbl:'My devices · 1 / 1', devProLbl:'My devices · 3 / 5',
|
||||
secDevices:'Devices', myDevices:'My Devices', devMgmt:'Device management',
|
||||
thisDevice:'This device', devOnlineNow:'Online now', lastOnline:'Last online', rel2h:'2h ago', relYday:'yesterday',
|
||||
devRename:'Rename', devForceLogout:'Force logout', devClearLogin:'Clear login info',
|
||||
devRenamedToast:'Renamed (demo)', devLoggedOutToast:'Force logged out (demo)', devClearedToast:'Login info cleared (demo)',
|
||||
secPref:'Preferences', prefLang:'Language', prefTheme:'Dark appearance', prefProtocol:'Protocol', followLight:'Follow light', stateOn:'On',
|
||||
secMore:'More', navDevices:'Devices', navSettings:'Settings', navRedeem:'Redeem & Buy',
|
||||
navContact:'Contact us', navWebUC:'Web user center', logout:'Sign out',
|
||||
@@ -1918,6 +1929,32 @@ function subShow(name){
|
||||
function subOpen(name){ subShow(name); subOverlay.classList.add('is-open'); }
|
||||
function subClose(){ subOverlay.classList.remove('is-open'); }
|
||||
function subToast(msg){ const t=$('#subToast'); $('#subToastText').textContent=msg; t.classList.add('show'); clearTimeout(subToastTimer); subToastTimer=setTimeout(()=>t.classList.remove('show'),1800); }
|
||||
/* 设备行 ⋮ 弹出菜单(重命名 / 强制退出 / 清除登录信息;本机仅重命名。设备为静态屏,直接绑定) */
|
||||
(function(){
|
||||
function closeDevMenus(){
|
||||
document.querySelectorAll('#subOverlay .dv-menu .menu').forEach(m=>m.hidden=true);
|
||||
document.querySelectorAll('#subOverlay .dv-menu .dv-more').forEach(b=>b.setAttribute('aria-expanded','false'));
|
||||
}
|
||||
document.querySelectorAll('#subOverlay .dv-menu .dv-more').forEach(function(btn){
|
||||
btn.addEventListener('click', function(e){
|
||||
e.stopPropagation();
|
||||
var menu=btn.parentNode.querySelector('.menu');
|
||||
var willOpen=menu.hidden;
|
||||
closeDevMenus();
|
||||
if(willOpen){ menu.hidden=false; btn.setAttribute('aria-expanded','true'); }
|
||||
});
|
||||
});
|
||||
document.querySelectorAll('#subOverlay .dv-mi').forEach(function(it){
|
||||
it.addEventListener('click', function(e){
|
||||
e.stopPropagation();
|
||||
var act=it.dataset.act;
|
||||
var key = act==='rename' ? 'devRenamedToast' : (act==='logout' ? 'devLoggedOutToast' : 'devClearedToast');
|
||||
closeDevMenus();
|
||||
subToast(D()[key]);
|
||||
});
|
||||
});
|
||||
document.addEventListener('click', closeDevMenus);
|
||||
})();
|
||||
/* 语言切换时同步子屏标题(由 render() 调用) */
|
||||
function subLangSync(){ if(subOverlay && subOverlay.classList.contains('is-open')) subShow(subOverlay.dataset.sub||'settings'); }
|
||||
|
||||
|
||||
Reference in New Issue
Block a user