fix(proxy): 添加规则「规则类型」改 chip 选择器(替原生 select)
原生 <select> 展开的是 OS 原生下拉(深色蓝高亮),浏览器不让改样式、与暖色设计 系统冲突(铁律 §14 禁原生默认外观)。改为设计一致的可选 chip 组: 域名后缀 / 域名 / IP-CIDR / GeoSite / GeoIP,选中=accent-subtle 底 + clay 字。两端同步。 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01A79VtQA1BwTuQN1ThpvYpo
This commit is contained in:
@@ -316,6 +316,13 @@
|
||||
.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; }
|
||||
/* 分流规则:类型选择 chip 组(替代原生 select,设计一致) */
|
||||
.rt-chips{ display:flex; flex-wrap:wrap; gap:var(--space-2); }
|
||||
.rt-chip{ padding:7px 13px; border-radius:var(--radius-full); border:1px solid var(--border);
|
||||
background:var(--surface); color:var(--fg2); font-size:13px; font-family:inherit; cursor:pointer;
|
||||
transition:background var(--dur-fast) var(--ease-out), color var(--dur-fast) var(--ease-out); }
|
||||
.rt-chip:hover{ border-color:var(--accent-border); }
|
||||
.rt-chip.is-active{ background:var(--accent-subtle); border-color:var(--accent-border); color:var(--accent); font-weight:600; }
|
||||
.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);
|
||||
@@ -2062,18 +2069,19 @@ var _rtBack=document.getElementById('rtBack'); if(_rtBack) _rtBack.addEventListe
|
||||
win.innerHTML='<button class="limit-close" id="rtAddClose" aria-label="'+_t('关闭','Close')+'"><svg><use href="#i-x"/></svg></button>'
|
||||
+'<div class="limit-title">'+_t('添加规则','Add rule')+'</div>'
|
||||
+'<div style="text-align:left;margin-top:18px;display:flex;flex-direction:column;gap:14px">'
|
||||
+'<label style="display:flex;flex-direction:column;gap:6px;font-size:13px;color:var(--fg2)"><span>'+_t('规则类型','Match type')+'</span>'
|
||||
+'<select id="rtAddType" style="'+INP+'"><option value="domain_suffix">'+_t('域名后缀','Domain suffix')+'</option><option value="domain">'+_t('域名(精确)','Domain (exact)')+'</option><option value="ip_cidr">IP-CIDR</option><option value="geosite">GeoSite '+_t('规则集','rule-set')+'</option><option value="geoip">GeoIP</option></select></label>'
|
||||
+'<div style="display:flex;flex-direction:column;gap:8px"><span style="font-size:13px;color:var(--fg2)">'+_t('规则类型','Match type')+'</span>'
|
||||
+'<div class="rt-chips" id="rtAddType"><button class="rt-chip is-active" data-type="domain_suffix">'+_t('域名后缀','Domain suffix')+'</button><button class="rt-chip" data-type="domain">'+_t('域名(精确)','Domain (exact)')+'</button><button class="rt-chip" data-type="ip_cidr">IP-CIDR</button><button class="rt-chip" data-type="geosite">GeoSite</button><button class="rt-chip" data-type="geoip">GeoIP</button></div></div>'
|
||||
+'<label style="display:flex;flex-direction:column;gap:6px;font-size:13px;color:var(--fg2)"><span>'+_t('目标','Target')+'</span><input id="rtAddVal" style="'+INP+'" placeholder="'+_t('如 example.com','e.g. example.com')+'"></label>'
|
||||
+'<div style="display:flex;flex-direction:column;gap:6px"><span style="font-size:13px;color:var(--fg2)">'+_t('动作','Action')+'</span>'
|
||||
+'<div class="segswitch" id="rtActSeg"><button class="segswitch-opt is-active" data-act="direct"><span>'+_t('直连','Direct')+'</span></button><button class="segswitch-opt" data-act="proxy"><span>'+_t('走隧道','Tunnel')+'</span></button><button class="segswitch-opt" data-act="reject"><span>'+_t('拒绝','Reject')+'</span></button></div></div>'
|
||||
+'</div>'
|
||||
+'<div style="display:flex;gap:12px;margin-top:22px"><button class="btn btn-ghost" id="rtAddCancel" style="flex:1">'+_t('取消','Cancel')+'</button><button class="btn btn-subtle" id="rtAddOk" style="flex:1">'+_t('添加','Add')+'</button></div>';
|
||||
var act='direct';
|
||||
var act='direct', type='domain_suffix';
|
||||
win.querySelectorAll('#rtAddType .rt-chip').forEach(function(b){ b.addEventListener('click',function(){ type=b.dataset.type; win.querySelectorAll('#rtAddType .rt-chip').forEach(function(x){ x.classList.toggle('is-active',x===b); }); }); });
|
||||
win.querySelectorAll('#rtActSeg button').forEach(function(b){ b.addEventListener('click',function(){ act=b.dataset.act; win.querySelectorAll('#rtActSeg button').forEach(function(x){ x.classList.toggle('is-active',x===b); }); }); });
|
||||
win.querySelector('#rtAddClose').addEventListener('click',function(){ closeModal('rtAddModal'); });
|
||||
win.querySelector('#rtAddCancel').addEventListener('click',function(){ closeModal('rtAddModal'); });
|
||||
win.querySelector('#rtAddOk').addEventListener('click',function(){ var v=(win.querySelector('#rtAddVal').value||'').trim(); if(!v){ win.querySelector('#rtAddVal').focus(); return; } addRuleRow(win.querySelector('#rtAddType').value,v,act,true); closeModal('rtAddModal'); });
|
||||
win.querySelector('#rtAddOk').addEventListener('click',function(){ var v=(win.querySelector('#rtAddVal').value||'').trim(); if(!v){ win.querySelector('#rtAddVal').focus(); return; } addRuleRow(type,v,act,true); closeModal('rtAddModal'); });
|
||||
openModal('rtAddModal');
|
||||
}
|
||||
|
||||
|
||||
@@ -224,6 +224,10 @@
|
||||
.rt-sheet.is-open{ display:flex; }
|
||||
.rt-win{ background:var(--surface); border-radius:var(--radius-lg); padding:20px; width:100%;
|
||||
max-width:340px; max-height:86%; overflow:auto; box-shadow:var(--shadow-lg); position:relative; }
|
||||
.rt-chips{ display:flex; flex-wrap:wrap; gap:var(--space-2); }
|
||||
.rt-chip{ padding:7px 13px; border-radius:var(--radius-full); border:1px solid var(--border);
|
||||
background:var(--bg-subtle); color:var(--fg2); font-size:13px; font-family:inherit; cursor:pointer; }
|
||||
.rt-chip.is-active{ background:var(--accent-subtle); border-color:var(--accent-border); color:var(--accent); font-weight:600; }
|
||||
|
||||
/* 购买流程覆盖层(从账户页「兑换 & 购买」进入;移植 purchase.html 状态机,命名空间 .pur-*) */
|
||||
#purchaseOverlay{ position:absolute; left:0; right:0; top:30px; bottom:0; z-index:45;
|
||||
@@ -2486,16 +2490,17 @@ $('#rowRouting').addEventListener('click', ()=>{ subOpen('routing'); renderRouti
|
||||
const win=document.getElementById('rtAddWin');
|
||||
win.innerHTML='<div style="display:flex;align-items:center;justify-content:space-between;margin-bottom:16px"><b style="font-family:var(--font-display);font-size:18px">'+_t('添加规则','Add rule')+'</b><button class="btn btn-ghost" id="rtAddClose" style="padding:6px"><svg style="width:20px;height:20px"><use href="#i-x"/></svg></button></div>'
|
||||
+'<div style="display:flex;flex-direction:column;gap:14px">'
|
||||
+'<label style="display:flex;flex-direction:column;gap:6px;font-size:13px;color:var(--fg2)"><span>'+_t('规则类型','Match type')+'</span><select id="rtAddType" style="'+INP+'"><option value="domain_suffix">'+_t('域名后缀','Domain suffix')+'</option><option value="domain">'+_t('域名(精确)','Domain (exact)')+'</option><option value="ip_cidr">IP-CIDR</option><option value="geosite">GeoSite '+_t('规则集','rule-set')+'</option><option value="geoip">GeoIP</option></select></label>'
|
||||
+'<div style="display:flex;flex-direction:column;gap:8px"><span style="font-size:13px;color:var(--fg2)">'+_t('规则类型','Match type')+'</span><div class="rt-chips" id="rtAddType"><button class="rt-chip is-active" data-type="domain_suffix">'+_t('域名后缀','Domain suffix')+'</button><button class="rt-chip" data-type="domain">'+_t('域名(精确)','Domain (exact)')+'</button><button class="rt-chip" data-type="ip_cidr">IP-CIDR</button><button class="rt-chip" data-type="geosite">GeoSite</button><button class="rt-chip" data-type="geoip">GeoIP</button></div></div>'
|
||||
+'<label style="display:flex;flex-direction:column;gap:6px;font-size:13px;color:var(--fg2)"><span>'+_t('目标','Target')+'</span><input id="rtAddVal" style="'+INP+'" placeholder="'+_t('如 example.com','e.g. example.com')+'"></label>'
|
||||
+'<div style="display:flex;flex-direction:column;gap:6px"><span style="font-size:13px;color:var(--fg2)">'+_t('动作','Action')+'</span><div class="segswitch" id="rtActSeg"><button class="segswitch-opt is-active" data-act="direct"><span>'+_t('直连','Direct')+'</span></button><button class="segswitch-opt" data-act="proxy"><span>'+_t('走隧道','Tunnel')+'</span></button><button class="segswitch-opt" data-act="reject"><span>'+_t('拒绝','Reject')+'</span></button></div></div>'
|
||||
+'</div>'
|
||||
+'<div style="display:flex;gap:10px;margin-top:20px"><button class="btn btn-ghost" id="rtAddCancel" style="flex:1">'+_t('取消','Cancel')+'</button><button class="btn btn-subtle" id="rtAddOk" style="flex:1">'+_t('添加','Add')+'</button></div>';
|
||||
let act='direct';
|
||||
let act='direct', type='domain_suffix';
|
||||
win.querySelectorAll('#rtAddType .rt-chip').forEach(b=>b.addEventListener('click',()=>{ type=b.dataset.type; win.querySelectorAll('#rtAddType .rt-chip').forEach(x=>x.classList.toggle('is-active',x===b)); }));
|
||||
win.querySelectorAll('#rtActSeg button').forEach(b=>b.addEventListener('click',()=>{ act=b.dataset.act; win.querySelectorAll('#rtActSeg button').forEach(x=>x.classList.toggle('is-active',x===b)); }));
|
||||
win.querySelector('#rtAddClose').addEventListener('click',()=>closeM('rtAddModal'));
|
||||
win.querySelector('#rtAddCancel').addEventListener('click',()=>closeM('rtAddModal'));
|
||||
win.querySelector('#rtAddOk').addEventListener('click',()=>{ const v=(win.querySelector('#rtAddVal').value||'').trim(); if(!v){ win.querySelector('#rtAddVal').focus(); return; } addRuleRow(win.querySelector('#rtAddType').value,v,act,true); closeM('rtAddModal'); });
|
||||
win.querySelector('#rtAddOk').addEventListener('click',()=>{ const v=(win.querySelector('#rtAddVal').value||'').trim(); if(!v){ win.querySelector('#rtAddVal').focus(); return; } addRuleRow(type,v,act,true); closeM('rtAddModal'); });
|
||||
openM('rtAddModal');
|
||||
}
|
||||
function openImport(){
|
||||
|
||||
Reference in New Issue
Block a user