Files
pangolin/docs/configurable-proxy-prototype.html
T
wangjia 9772db7d12
ci-pangolin / Redline Scan — 脱敏 (UI 文案) (pull_request) Successful in 17s
ci-pangolin / Cleartext Scan — Android 禁明文 (pull_request) Successful in 16s
ci-pangolin / Portable SQL — 可移植性 (mysql/sqlite) (pull_request) Successful in 17s
ci-pangolin / Golden — 视觉回归 (全量:components/auth/desktop/tablet) (pull_request) Failing after 11m38s
ci-pangolin / Go — integration (mysql/redis testcontainers) (pull_request) Failing after 11m49s
ci-pangolin / E2E Smoke — L4 进程级端到端 (pull_request) Failing after 11m58s
ci-pangolin / Go — build + test (pull_request) Failing after 12m8s
ci-pangolin / DS-flow — 原型/跨端同源/代码色单源闸 (pull_request) Failing after 12m20s
ci-pangolin / Codegen Drift — token 生成物未漂移 (pull_request) Failing after 12m30s
ci-pangolin / Flutter — analyze + test (pull_request) Failing after 12m39s
ci-pangolin / OpenAPI Sync Check (pull_request) Failing after 12m48s
ci-pangolin / Lint — shellcheck (pull_request) Failing after 12m56s
docs(configurable-proxy): 加桌面端(macOS/Windows)设置窗口原型
移动三屏之外补桌面端:左侧栏 + 规则表格(内联编辑/拖动排序)+ 右侧实时预览
生成的 sing-box route.rules。两端共用同一套服务端 per-user 路由档案。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01A79VtQA1BwTuQN1ThpvYpo
2026-07-27 00:41:12 +08:00

320 lines
22 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!doctype html>
<html lang="zh-CN">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Pangolin 可配置分流 · 原型</title>
<style>
:root{
--bg:#0f1117; --panel:#171a22; --panel2:#1d2129; --fg:#e6e8ee; --fg2:#a8afbd;
--accent:#e0884f; --accent2:#5fb0c9; --ok:#5ec27a; --bad:#e06a6a; --warn:#e0b84f;
--border:#262b36; --sans:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"PingFang SC","Microsoft YaHei",sans-serif;
--mono:"SF Mono",ui-monospace,Menlo,Consolas,monospace;
}
@media (prefers-color-scheme: light){
:root{--bg:#f4f5f8;--panel:#fff;--panel2:#eef0f4;--fg:#1a1d24;--fg2:#5a6172;--border:#dde0e7}
}
:root[data-theme="dark"]{--bg:#0f1117;--panel:#171a22;--panel2:#1d2129;--fg:#e6e8ee;--fg2:#a8afbd;--border:#262b36}
:root[data-theme="light"]{--bg:#f4f5f8;--panel:#fff;--panel2:#eef0f4;--fg:#1a1d24;--fg2:#5a6172;--border:#dde0e7}
*{box-sizing:border-box}
body{margin:0;background:var(--bg);color:var(--fg);font-family:var(--sans);line-height:1.6;font-size:15px}
.wrap{max-width:1180px;margin:0 auto;padding:32px 20px 80px}
h1{font-size:24px;margin:0 0 4px}
.lead{color:var(--fg2);margin:0 0 28px;font-size:14.5px}
h2{font-size:17px;color:var(--accent);border-bottom:1px solid var(--border);padding-bottom:6px;margin:38px 0 16px}
.cols{display:flex;gap:34px;flex-wrap:wrap;align-items:flex-start}
.note{flex:1;min-width:280px}
.note h3{font-size:15px;color:var(--accent2);margin:18px 0 6px}
.note p{color:var(--fg2);font-size:14px;margin:6px 0}
.tag{display:inline-block;font-size:11px;padding:1px 8px;border-radius:20px;font-family:var(--mono);vertical-align:middle}
.t-direct{background:rgba(94,194,122,.16);color:var(--ok)}
.t-proxy{background:rgba(224,136,79,.18);color:var(--accent)}
.t-reject{background:rgba(224,106,106,.16);color:var(--bad)}
.t-sys{background:rgba(95,176,201,.14);color:var(--accent2)}
code{font-family:var(--mono);font-size:.87em;background:var(--panel2);padding:1px 6px;border-radius:5px;color:#f0d9c4}
/* phone frame */
.phones{display:flex;gap:26px;flex-wrap:wrap}
.phone{width:330px;background:#000;border-radius:38px;padding:11px;box-shadow:0 12px 40px rgba(0,0,0,.5);flex:0 0 auto}
.screen{background:var(--bg);border-radius:28px;overflow:hidden;height:686px;display:flex;flex-direction:column;border:1px solid var(--border)}
.statusbar{height:26px;display:flex;align-items:center;justify-content:space-between;padding:0 20px;font-size:12px;color:var(--fg2);font-weight:600}
.navbar{display:flex;align-items:center;gap:10px;padding:8px 16px 12px;border-bottom:1px solid var(--border)}
.navbar .back{color:var(--accent);font-size:20px}
.navbar .title{font-size:17px;font-weight:700}
.navbar .add{margin-left:auto;color:var(--accent);font-size:22px;font-weight:300}
.body{flex:1;overflow-y:auto;padding:14px 14px 20px}
.caption{font-size:11.5px;color:var(--fg2);text-transform:uppercase;letter-spacing:.5px;margin:16px 4px 7px}
.card{background:var(--panel);border:1px solid var(--border);border-radius:14px;overflow:hidden}
.segment{display:flex;background:var(--panel2);border-radius:11px;padding:3px;margin:2px}
.segment div{flex:1;text-align:center;font-size:13px;padding:7px 0;border-radius:8px;color:var(--fg2);font-weight:600}
.segment div.on{background:var(--accent);color:#1a1206}
.row{display:flex;align-items:center;gap:11px;padding:12px 14px;border-bottom:1px solid var(--border)}
.row:last-child{border-bottom:none}
.row .grip{color:var(--fg2);font-size:15px;opacity:.6}
.row .main{flex:1;min-width:0}
.row .rt{font-size:14px;font-weight:600;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.row .rsub{font-size:11.5px;color:var(--fg2);font-family:var(--mono);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.toggle{width:40px;height:24px;border-radius:20px;background:var(--accent);position:relative;flex:0 0 auto}
.toggle.off{background:var(--panel2)}
.toggle::after{content:"";position:absolute;top:2px;left:18px;width:20px;height:20px;border-radius:50%;background:#fff;transition:.2s}
.toggle.off::after{left:2px}
.rowlabel{flex:1;font-size:14px}
.rowval{font-size:13px;color:var(--fg2);font-family:var(--mono)}
.lock{font-size:11px;color:var(--fg2)}
.addbtn{text-align:center;color:var(--accent);font-size:14px;font-weight:600;padding:13px}
.hint{font-size:11.5px;color:var(--fg2);padding:8px 6px;line-height:1.5}
/* modal mock (add rule) */
.sheet{background:var(--panel);border:1px solid var(--border);border-radius:18px;overflow:hidden}
.sheet .sh{padding:12px 16px;border-bottom:1px solid var(--border);display:flex;align-items:center}
.sheet .sh .c{color:var(--fg2);font-size:14px}
.sheet .sh .t{flex:1;text-align:center;font-weight:700;font-size:15px}
.sheet .sh .s{color:var(--accent);font-size:14px;font-weight:700}
.field{padding:12px 16px;border-bottom:1px solid var(--border)}
.field .fl{font-size:11.5px;color:var(--fg2);margin-bottom:6px}
.field .fv{font-size:15px}
.chips{display:flex;gap:8px;flex-wrap:wrap}
.chip{font-size:12.5px;padding:6px 12px;border-radius:9px;background:var(--panel2);color:var(--fg2);border:1px solid transparent}
.chip.on{background:rgba(224,136,79,.16);color:var(--accent);border-color:var(--accent)}
.inp{background:var(--panel2);border:1px solid var(--border);border-radius:9px;padding:9px 11px;font-family:var(--mono);font-size:14px;color:var(--fg)}
table{border-collapse:collapse;width:100%;font-size:13.5px;margin:6px 0}
th,td{border:1px solid var(--border);padding:7px 10px;text-align:left;vertical-align:top}
th{background:var(--panel2);color:var(--accent2);font-weight:600}
td code{white-space:nowrap}
/* desktop window */
.win{border:1px solid var(--border);border-radius:12px;overflow:hidden;box-shadow:0 14px 44px rgba(0,0,0,.45);background:var(--bg);max-width:1000px}
.titlebar{height:38px;background:var(--panel2);display:flex;align-items:center;padding:0 14px;border-bottom:1px solid var(--border)}
.dots{display:flex;gap:8px} .dots i{width:12px;height:12px;border-radius:50%;background:#3a3f4b;display:block}
.dots i:nth-child(1){background:#e0655a}.dots i:nth-child(2){background:#e0b84f}.dots i:nth-child(3){background:#5ec27a}
.wt{flex:1;text-align:center;font-size:13px;color:var(--fg2);font-weight:600;margin-left:-40px}
.winbody{display:flex;height:560px}
.sidebar{width:172px;background:var(--panel);border-right:1px solid var(--border);padding:12px 8px;flex:0 0 auto}
.si{padding:9px 12px;border-radius:8px;font-size:13.5px;color:var(--fg2);margin-bottom:2px}
.si.on{background:var(--accent);color:#1a1206;font-weight:600}
.content{flex:1;min-width:0;padding:18px 20px;overflow-y:auto;display:flex;flex-direction:column}
.chead{display:flex;align-items:center;gap:16px;margin-bottom:14px}
.ctitle{font-size:18px;font-weight:700}
.modeseg{display:flex;background:var(--panel2);border-radius:9px;padding:3px;margin-left:auto}
.modeseg span{font-size:12.5px;padding:6px 14px;border-radius:7px;color:var(--fg2);font-weight:600}
.modeseg span.on{background:var(--accent);color:#1a1206}
.binline{display:flex;gap:18px;flex-wrap:wrap;background:var(--panel);border:1px solid var(--border);border-radius:10px;padding:11px 14px;margin-bottom:14px;font-size:13px;color:var(--fg2)}
.binline label{display:flex;align-items:center;gap:7px}
.tg{width:34px;height:20px;border-radius:14px;background:var(--accent);position:relative;display:inline-block}
.tg.off{background:var(--panel2)} .tg::after{content:"";position:absolute;top:2px;left:16px;width:16px;height:16px;border-radius:50%;background:#fff}.tg.off::after{left:2px}
.ruletable{border-collapse:collapse;width:100%;font-size:13px;display:table;margin:0}
.ruletable th{background:var(--panel2);color:var(--accent2);font-weight:600;padding:8px 10px;text-align:left;font-size:11.5px;text-transform:uppercase;letter-spacing:.4px;border:1px solid var(--border)}
.ruletable td{padding:9px 10px;border:1px solid var(--border);vertical-align:middle}
.ruletable tr:hover td{background:rgba(95,176,201,.05)}
.ruletable .g{color:var(--fg2);cursor:grab;opacity:.55}
.ruletable .v{font-family:var(--mono);font-size:12.5px}
.ty{font-size:11px;padding:2px 8px;border-radius:6px;background:var(--panel2);color:var(--fg2);font-family:var(--mono)}
.tablefoot{display:flex;align-items:center;gap:16px;margin-top:12px;font-size:13px;color:var(--accent);flex-wrap:wrap}
.tablefoot .fin{margin-left:auto;color:var(--fg2)}
.preview{width:250px;flex:0 0 auto;border-left:1px solid var(--border);background:var(--panel);padding:14px}
.pvh{font-size:11.5px;color:var(--fg2);text-transform:uppercase;letter-spacing:.4px;margin-bottom:8px}
.preview pre{font-size:11px;line-height:1.5;padding:11px;margin:0}
@media (max-width:820px){.preview{display:none}}
</style>
</head>
<body>
<div class="wrap">
<h1>Pangolin 可配置分流 · 交互原型</h1>
<p class="lead">Task 3 设计稿 · 让用户像 Shadowrocket 那样自定义"哪些流量直连 / 走隧道 / 拒绝"。下含<b>移动端</b>三屏 + <b>桌面端(macOS/Windows)</b>设置窗口的视觉原型(mockup,非真实数据),两端共用同一套服务端路由档案。配套规则模型与实现见 <a href="configurable-proxy-spec.html" style="color:var(--accent2)">配置说明文档 →</a></p>
<div class="phones">
<!-- Screen 1: 分流规则主屏 -->
<div class="phone"><div class="screen">
<div class="statusbar"><span>9:41</span><span>5G ▮▮▮</span></div>
<div class="navbar"><span class="back"></span><span class="title">分流规则</span><span class="add"></span></div>
<div class="body">
<div class="caption">代理模式</div>
<div class="card"><div class="segment">
<div>全局代理</div><div class="on">智能分流</div><div>全部直连</div>
</div></div>
<div class="hint">智能分流:按下面规则表逐条匹配;命中「直连」不走隧道,「走隧道」经节点出网。</div>
<div class="caption">内置规则(系统)</div>
<div class="card">
<div class="row"><span class="rowlabel">国内直连(GeoIP/GeoSite CN)</span><span class="toggle"></span></div>
<div class="row"><span class="rowlabel">局域网直连(LAN/私网)</span><span class="lock">🔒 强制</span></div>
<div class="row"><span class="rowlabel">私有服务走隧道</span><span class="lock">🔒 服务端</span></div>
</div>
<div class="caption">我的规则 · 按顺序匹配(首命中生效)</div>
<div class="card">
<div class="row"><span class="grip"></span><div class="main"><div class="rt">git.51yanmei.com</div><div class="rsub">域名后缀 · DOMAIN-SUFFIX</div></div><span class="tag t-direct">直连</span></div>
<div class="row"><span class="grip"></span><div class="main"><div class="rt">*.aliyun.com</div><div class="rsub">域名后缀 · DOMAIN-SUFFIX</div></div><span class="tag t-direct">直连</span></div>
<div class="row"><span class="grip"></span><div class="main"><div class="rt">github.com</div><div class="rsub">域名后缀 · DOMAIN-SUFFIX</div></div><span class="tag t-proxy">走隧道</span></div>
<div class="row"><span class="grip"></span><div class="main"><div class="rt">广告 / 追踪(GeoSite: category-ads)</div><div class="rsub">规则集 · GEOSITE</div></div><span class="tag t-reject">拒绝</span></div>
<div class="row"><span class="grip"></span><div class="main"><div class="rt">35.190.0.0/16</div><div class="rsub">IP 段 · IP-CIDR</div></div><span class="tag t-proxy">走隧道</span></div>
</div>
<div class="card" style="margin-top:10px"><div class="addbtn"> 添加规则</div></div>
<div class="caption">最终(未命中任何规则)</div>
<div class="card"><div class="row"><span class="rowlabel">FINAL · 兜底动作</span><span class="tag t-proxy">走隧道</span></div></div>
<div class="hint">从文本导入(Shadowrocket / Clash 规则)· 重置为默认</div>
</div>
</div></div>
<!-- Screen 2: 添加/编辑规则 -->
<div class="phone"><div class="screen">
<div class="statusbar"><span>9:41</span><span>5G ▮▮▮</span></div>
<div class="navbar"><span class="back"></span><span class="title">添加规则</span></div>
<div class="body">
<div class="sheet">
<div class="sh"><span class="c">取消</span><span class="t">添加规则</span><span class="s">保存</span></div>
<div class="field"><div class="fl">类型</div>
<div class="chips">
<span class="chip">域名</span><span class="chip on">域名后缀</span><span class="chip">关键字</span>
<span class="chip">IP-CIDR</span><span class="chip">GeoIP 国家</span><span class="chip">GeoSite 类别</span>
</div>
</div>
<div class="field"><div class="fl"></div>
<input class="inp" style="width:100%" value="git.51yanmei.com" readonly>
</div>
<div class="field"><div class="fl">动作</div>
<div class="chips">
<span class="chip on" style="border-color:var(--ok);color:var(--ok);background:rgba(94,194,122,.14)">直连 DIRECT</span>
<span class="chip">走隧道 PROXY</span>
<span class="chip">拒绝 REJECT</span>
</div>
</div>
<div class="field" style="border-bottom:none"><div class="fl">说明(选填)</div>
<input class="inp" style="width:100%" value="CI 编译源,国内直连不占隧道" readonly>
</div>
</div>
<div class="hint">GeoIP/GeoSite 由服务端自托管规则集(.srs)支持,墙内可直连下载,无需梯子。IP-CIDR 支持 v4/v6。</div>
<div class="caption">预览:将翻译为 sing-box 路由规则</div>
<div class="card" style="padding:12px"><pre style="margin:0;font-size:11.5px;color:#cdd3df;font-family:var(--mono);white-space:pre-wrap">{ "domain_suffix": ["git.51yanmei.com"],
"outbound": "direct" }</pre></div>
</div>
</div></div>
<!-- Screen 3: 从文本导入 -->
<div class="phone"><div class="screen">
<div class="statusbar"><span>9:41</span><span>5G ▮▮▮</span></div>
<div class="navbar"><span class="back"></span><span class="title">从文本导入</span><span class="add" style="font-size:14px;font-weight:700">导入</span></div>
<div class="body">
<div class="caption">粘贴规则(Shadowrocket / Clash 风格)</div>
<div class="card" style="padding:12px"><pre style="margin:0;font-size:11.5px;color:#cdd3df;font-family:var(--mono);white-space:pre-wrap"># 一行一条:类型,值,动作
DOMAIN-SUFFIX,git.51yanmei.com,DIRECT
DOMAIN-SUFFIX,aliyun.com,DIRECT
DOMAIN-SUFFIX,tencent.com,DIRECT
DOMAIN-SUFFIX,flutter-io.cn,DIRECT
DOMAIN-SUFFIX,github.com,PROXY
GEOSITE,category-ads,REJECT
GEOIP,CN,DIRECT
FINAL,PROXY</pre></div>
<div class="hint">解析后逐条加入「我的规则」,可再拖动排序。非法行(错误 CIDR / 未知类型)高亮跳过并提示。</div>
<div class="caption">解析结果预览</div>
<div class="card">
<div class="row"><div class="main"><div class="rt">✓ 7 条有效</div><div class="rsub">4 直连 · 1 走隧道 · 1 拒绝 · FINAL</div></div><span class="tag t-sys">OK</span></div>
<div class="row"><div class="main"><div class="rt">⚠ 0 条跳过</div><div class="rsub">无非法行</div></div></div>
</div>
</div>
</div></div>
</div>
<h2>桌面端(macOS / Windows)· 设置窗口</h2>
<p class="lead" style="margin-bottom:16px">桌面有更大空间:左侧栏 + 规则<b>表格</b>(可内联编辑/拖动排序)+ 右侧<b>实时预览</b>生成的 sing-box 规则。同一套档案模型,与移动端共用服务端。</p>
<div class="win">
<div class="titlebar"><span class="dots"><i></i><i></i><i></i></span><span class="wt">Pangolin — 设置</span></div>
<div class="winbody">
<div class="sidebar">
<div class="si">通用</div>
<div class="si">节点</div>
<div class="si on">分流规则</div>
<div class="si">账户</div>
<div class="si">统计</div>
<div class="si">关于</div>
</div>
<div class="content">
<div class="chead">
<div class="ctitle">分流规则</div>
<div class="modeseg"><span>全局代理</span><span class="on">智能分流</span><span>全部直连</span></div>
</div>
<div class="binline">
<label>国内直连(GeoIP/GeoSite CN)<span class="tg"></span></label>
<label>LAN / 私网直连 <span class="lock">🔒 强制</span></label>
<label>私有服务走隧道 <span class="lock">🔒 服务端</span></label>
</div>
<table class="ruletable">
<tr><th style="width:26px"></th><th style="width:130px">类型</th><th></th><th style="width:96px">动作</th><th style="width:150px">说明</th><th style="width:52px">启用</th></tr>
<tr><td class="g"></td><td><span class="ty">域名后缀</span></td><td class="v">git.51yanmei.com</td><td><span class="tag t-direct">直连</span></td><td style="color:var(--fg2);font-size:12px">CI 编译源</td><td><span class="tg" style="transform:scale(.85)"></span></td></tr>
<tr><td class="g"></td><td><span class="ty">域名后缀</span></td><td class="v">aliyun.com</td><td><span class="tag t-direct">直连</span></td><td style="color:var(--fg2);font-size:12px">maven 镜像</td><td><span class="tg" style="transform:scale(.85)"></span></td></tr>
<tr><td class="g"></td><td><span class="ty">域名后缀</span></td><td class="v">github.com</td><td><span class="tag t-proxy">走隧道</span></td><td style="color:var(--fg2);font-size:12px"></td><td><span class="tg" style="transform:scale(.85)"></span></td></tr>
<tr><td class="g"></td><td><span class="ty">GeoSite</span></td><td class="v">category-ads</td><td><span class="tag t-reject">拒绝</span></td><td style="color:var(--fg2);font-size:12px">广告/追踪</td><td><span class="tg" style="transform:scale(.85)"></span></td></tr>
<tr><td class="g"></td><td><span class="ty">IP-CIDR</span></td><td class="v">35.190.0.0/16</td><td><span class="tag t-proxy">走隧道</span></td><td style="color:var(--fg2);font-size:12px"></td><td><span class="tg off" style="transform:scale(.85)"></span></td></tr>
</table>
<div class="tablefoot"><span> 添加规则</span><span>⇪ 从文本导入</span><span>↺ 重置默认</span><span class="fin">FINAL 兜底:<span class="tag t-proxy">走隧道</span></span></div>
</div>
<div class="preview">
<div class="pvh">实时预览 · route.rules</div>
<pre>[
{"action":"hijack-dns",
"port":[53]},
{"ip_cidr":["10.0.0.0/8",
"192.168.0.0/16",...],
"outbound":"direct"},
{"domain_suffix":
["git.51yanmei.com",
"aliyun.com"],
"outbound":"direct"},
{"domain_suffix":
["github.com"],
"outbound":"auto"},
{"rule_set":["geosite-ads"],
"outbound":"block"},
{"rule_set":
["geoip-cn","geosite-cn"],
"outbound":"direct"}
]
final: "auto"</pre>
</div>
</div>
</div>
<p class="lead" style="margin-top:14px">桌面端与移动端<b>共用同一份服务端路由档案</b>——在任一端改,另一端下次连接生效(per-user 同步)。桌面多了内联表格编辑与实时预览,适合高级用户。</p>
<h2>三块界面在讲什么</h2>
<div class="cols">
<div class="note">
<h3>① 分流规则主屏</h3>
<p><b>代理模式</b>三选一(全局代理 / 智能分流 / 全部直连),对应 Shadowrocket 的 Global/Rule/Direct。</p>
<p><b>内置规则</b>是系统/服务端强制层:LAN 直连恒开(🔒),私有服务走隧道由服务端下发(🔒),国内直连可开关。</p>
<p><b>我的规则</b>是用户自定义、可拖动排序的有序表,<b>首命中生效</b><b>FINAL</b> 是兜底动作。</p>
</div>
<div class="note">
<h3>② 添加 / 编辑规则</h3>
<p><b>类型</b>(域名/后缀/关键字/IP-CIDR/GeoIP/GeoSite)→ 填<b></b> → 选<b>动作</b>(直连/走隧道/拒绝)。</p>
<p>实时<b>预览</b>该规则会被翻译成的 sing-box 路由片段,让高级用户看得懂、放心。</p>
</div>
<div class="note">
<h3>③ 从文本导入</h3>
<p>粘贴 <code>类型,值,动作</code> 一行一条,兼容 Shadowrocket/Clash 直觉。批量建规则、迁移旧配置。</p>
<p>解析给出有效/跳过统计,非法行不静默吞。</p>
</div>
</div>
<h2>动作与类型对照(给你确认)</h2>
<table>
<tr><th>动作</th><th>含义</th><th>sing-box outbound</th></tr>
<tr><td><span class="tag t-direct">直连</span></td><td>不走隧道,本机物理网卡直接出网(国内站、CI 源、私网)</td><td><code>direct</code></td></tr>
<tr><td><span class="tag t-proxy">走隧道</span></td><td>经 pangolin 节点出网(需科学上网的站)</td><td><code>auto</code>(REALITY/Hy2 择优)</td></tr>
<tr><td><span class="tag t-reject">拒绝</span></td><td>直接阻断(广告/追踪/恶意域)</td><td><code>block</code></td></tr>
</table>
<table>
<tr><th>类型</th><th>值示例</th><th>匹配</th></tr>
<tr><td>域名</td><td><code>example.com</code></td><td>精确</td></tr>
<tr><td>域名后缀</td><td><code>aliyun.com</code></td><td>含子域(<code>*.aliyun.com</code>)</td></tr>
<tr><td>关键字</td><td><code>google</code></td><td>域名含该串</td></tr>
<tr><td>IP-CIDR</td><td><code>35.190.0.0/16</code></td><td>IP 段(v4/v6)</td></tr>
<tr><td>GeoIP 国家</td><td><code>CN</code></td><td>该国 IP 段(自托管规则集)</td></tr>
<tr><td>GeoSite 类别</td><td><code>category-ads</code> / <code>netflix</code></td><td>预置域名集</td></tr>
</table>
<p class="lead" style="margin-top:30px">需要你确认:①这套 UI/模型对不对路?②要不要「从文本导入」这一块(可后置)?③规则粒度够不够(要不要 per-app 分应用代理,shadowrocket 有,较重、建议后置)?确认后我出实现计划开发。设计取舍与实现细节见 <a href="configurable-proxy-spec.html" style="color:var(--accent2)">配置说明文档 →</a></p>
</div>
</body>
</html>