From 53eafe86488dbb56c4494af538dcd51730efefdf Mon Sep 17 00:00:00 2001 From: Su Yijun Date: Sat, 24 Oct 2026 02:30:01 +0800 Subject: [PATCH] =?UTF-8?q?feat(0.6.4):=20DPI=20=E5=8D=8F=E8=AE=AE?= =?UTF-8?q?=E9=85=8D=E8=89=B2=E7=85=A7=E7=BB=B4=E7=9B=9F=EF=BC=88ECharts?= =?UTF-8?q?=20=E9=BB=98=E8=AE=A4=209=20=E8=89=B2=E5=BE=AA=E7=8E=AF?= =?UTF-8?q?=EF=BC=89=EF=BC=8C=E9=A5=BC=E5=9B=BE=E6=8C=89=E5=A4=A7=E7=B1=BB?= =?UTF-8?q?=E5=9B=BA=E5=AE=9A=E9=A1=BA=E5=BA=8F=E6=8E=92=E5=88=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 5.5 --- CHANGELOG.md | 4 +- DOCKERHUB.md | 2 +- frontend/src/components/Composition.vue | 9 +- frontend/src/format.js | 4 +- frontend/src/style.css | 106 ++++++++++++------------ 5 files changed, 65 insertions(+), 60 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c7b5c1d..6939ec8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,8 +2,10 @@ ## [0.6.4] - 2026-10-24 -识别库面板按层级分组 +识别库面板按层级分组;DPI 协议配色照维盟 +- **应用大类配色照维盟「DPI 协议」饼图**:HTTP协议 蓝、网络游戏 绿、网络电视 黄、P2P下载 红、常用协议 浅蓝、即时通讯 深绿、网络音乐 橙、股票交易 紫、网络电话 粉,第 10 类起按同样 9 色循环(流量代理 蓝、数据库 绿、移动应用 黄……其他 橙、未识别 紫)。小类仍用所属大类颜色的深浅区分。 +- 流量构成饼图和图例改为按大类的固定顺序排列(和维盟一样,不再按大小排),同色的两个大类相隔 9 位,扇区不会挨在一起。 - 「识别规则 → 识别库」按识别层级分成四组:① 按域名认应用(内置规则库、v2fly、blackmatrix7)② 按 IP 认应用(IP 归属库)③ 按域名认类别(Hagezi、UT1)④ 兜底(国内域名列表、官方 IP 段、国内 IP 段)。每组标题下一句话说明这一层做什么、组内谁优先,原来表格下面那一长段匹配顺序说明去掉。 - Google、Cloudflare、AWS、GitHub 四家的官方 IP 段合并成一行「官方 IP 段」,各家的规模列在说明下面;各来源的说明改短。 diff --git a/DOCKERHUB.md b/DOCKERHUB.md index 41c6f28..a0fba06 100644 --- a/DOCKERHUB.md +++ b/DOCKERHUB.md @@ -8,7 +8,7 @@ Source & docs: https://github.com/suyijun8182/ros-dpi ## What's new -- **0.6.4**: the rule-library panel is grouped by tier (apps by domain, apps by IP, categories by domain, fallbacks) with a one-line explanation per tier; the four official IP-range feeds are merged into one row. +- **0.6.4**: app-group colors now match WayOS's DPI pie (ECharts' 9 default colors cycled over the 17 groups), and the traffic-mix pie is drawn in the fixed group order like WayOS; the rule-library panel is grouped by tier (apps by domain, apps by IP, categories by domain, fallbacks) with a one-line explanation per tier; the four official IP-range feeds are merged into one row. - **0.6.3**: app groups now follow WayOS's 17 DPI classes (HTTP, online games, video/TV, P2P, common protocols, messaging, music, stock trading, VoIP, proxies, databases, mobile apps, special protocols, mining pools, PCDN, other, unknown), always listed in that order; new categories HTTPS/QUIC, databases (by port), mining pools and PCDN. Category ids are unchanged, so history is kept; saved analysis settings and group-based audit rules are migrated automatically. On the Applications page, "Details" now opens a WayOS-style "DPI protocol details" dialog that drills down group → category → app. - **0.6.2**: fixes external sources (sing-box / MosDNS) showing "not enabled" after 0.6.0 — a broken upgrade backfill aborted startup initialisation, so saved sing-box / MosDNS settings, LAN ranges and custom rules were not loaded after a restart; no need to re-enter anything. Three more rule sources, downloaded at runtime (not in the image): **blackmatrix7** per-app rules (GPL-2.0, weekly) add domains / IP ranges to ~460 existing apps and ~100 new apps; **Hagezi** (GPL-3.0) and **UT1** (CC BY-SA 4.0) category lists (adult, gambling, VPN/proxy, device telemetry, games, shopping, news, job search, banks…). Order and weights: app-level domain sources (built-in, v2fly, blackmatrix7) are compared by longest matching suffix, ties go to built-in > v2fly > blackmatrix7; then app-level IP (CIDR, ports, ASN); then category lists (Hagezi > UT1); then the China domain list and IP-range fallbacks. On the Tranco top-10k, the share mapped to a specific category went from 19.6% to 35.7%. New category: Gambling. Disable with `BM7_DB` / `HAGEZI_DB` / `UT1_DB=false`. Also: notification channels now match EasySub exactly — 14 channels with the same fields: Telegram (API proxy, HTTP proxy, check bot / get Chat ID), Feishu app bot, new QQ bot, Bark icon, email SSL switch, Pushplus channel, WeCom group robot **or self-built app** (CorpID / AgentId / Secret, API proxy, user / department / tag, text card, "check app"), webhook timeout and retries. The scenario (Home / Business) is now a global setting under **Settings → Scenario & network**; in Business mode the menu says "Employees" instead of "Family members", and the last scenario is cached so the menu no longer flashes the wrong label. Identification order: domain fallbacks (China domain list) are tried before IP-range fallbacks, and overlapping IP ranges use longest-prefix match (before, a small range inside a big one could hide the big one). The "Auto update" switch now also controls the ASN and fallback list downloads. Note: Feishu now uses an app bot (App ID / Secret / Chat IDs) like EasySub; an old Feishu group-webhook config has to be re-entered. - **0.6.1**: much higher identification rate. New fallback sources, all downloaded at runtime and auto-updated daily: the dnsmasq-china-list Chinese domain list (~110k domains, WTFPL) catches long-tail .cn domains as "Chinese websites" (sampling showed v2fly + built-in rules only matched 5.6% of them); official Google / Cloudflare / AWS / GitHub IP ranges plus Apple's 17.0.0.0/8 attribute domain-less traffic (DoH, ECH, raw IPs) to the owning company; China IP ranges (chnroutes2, CC-BY-SA 4.0) group domain-less domestic traffic as "China networks". Purely additive — existing rules always take priority. Disable with `CHINA_DB=false` / `IPLIST_DB=false`. diff --git a/frontend/src/components/Composition.vue b/frontend/src/components/Composition.vue index f878d90..64174e7 100644 --- a/frontend/src/components/Composition.vue +++ b/frontend/src/components/Composition.vue @@ -14,7 +14,7 @@ import { computed, onMounted, onUnmounted, ref } from 'vue' import { useI18n } from 'vue-i18n' import { pieOption } from '../charts.js' -import { bytes, catHex, catName, groupColor, groupHex, groupName, pct } from '../format.js' +import { bytes, CAT_GROUP, catHex, catName, GROUPS, groupColor, groupHex, groupName, pct } from '../format.js' import { ui } from '../state.js' import Chart from './Chart.vue' @@ -30,9 +30,12 @@ const { t, locale } = useI18n() const gs = computed(() => props.groups.filter(g => g.total > 0)) const sum = computed(() => gs.value.reduce((s, g) => s + g.total, 0) || 1) const group = computed(() => (props.drill && props.active ? gs.value.find(g => g.id === props.active) : null)) +// 和维盟一样按固定顺序画(不按大小排):配色是 9 色循环,同色的两个大类相隔 9 位,扇区不会挨在一起 +const CAT_ORDER = Object.keys(CAT_GROUP) +const byOrder = (list, order) => [...list].sort((x, y) => order.indexOf(x.id) - order.indexOf(y.id)) const items = computed(() => (group.value - ? group.value.children.filter(c => c.total > 0).map(c => ({ id: c.id, kind: 'cat', name: catName(c), value: c.total, color: catHex(c.id) })) - : gs.value.map(g => ({ id: g.id, kind: 'group', name: groupName(g), value: g.total, color: groupHex(g.id) })))) + ? byOrder(group.value.children.filter(c => c.total > 0), CAT_ORDER).map(c => ({ id: c.id, kind: 'cat', name: catName(c), value: c.total, color: catHex(c.id) })) + : byOrder(gs.value, GROUPS).map(g => ({ id: g.id, kind: 'group', name: groupName(g), value: g.total, color: groupHex(g.id) })))) const mq = window.matchMedia('(max-width: 640px)') const narrow = ref(mq.matches) const onMq = e => (narrow.value = e.matches) diff --git a/frontend/src/format.js b/frontend/src/format.js index 6b747f8..6a05619 100644 --- a/frontend/src/format.js +++ b/frontend/src/format.js @@ -69,8 +69,8 @@ export function groupName(g) { } /* - * 配色按"应用大类"(维盟的 17 类):流量大的 8 个大类各占一个固定色相(style.css 的 --g-*,已用 dataviz 校验脚本验证色盲区分度), - * 常用协议、股票、电话、代理、数据库、矿池、PCDN、其他、未识别用灰阶。大类下的小类用同一色相的深浅区分,名字始终和色块一起出现。 + * 配色按"应用大类":照维盟 DPI 协议饼图,ECharts 默认 9 色按 17 个大类的顺序循环(style.css 的 --g-*)。 + * 大类下的小类用同一色相的深浅区分,名字始终和色块一起出现。 * 顺序 = 小类在大类内的深浅次序;新增分类时必须同步(后端测试会检查与 apps.yaml 一致)。 */ export const CAT_GROUP = { diff --git a/frontend/src/style.css b/frontend/src/style.css index 1b44fdd..768099e 100644 --- a/frontend/src/style.css +++ b/frontend/src/style.css @@ -35,25 +35,25 @@ --focus: #2b6583; /* 应用大类配色(dataviz validate_palette.js 校验:白底 CVD 相邻 ΔE ≥ 9.1;三色对比度 < 3:1,故图表一律带图例与数值表) */ - /* 8 个流量大的大类用色相,其余小众大类用灰阶(图例和表格都带名称,不靠颜色区分)。 - dataviz validate_palette.js 按维盟顺序校验:白底、深色底均通过,CVD 相邻最差 ΔE 6.9 / 6.5(在 6–8 区间,故图表一律带图例、间隔与数值表) */ - --g-http: #6250d6; - --g-game: #eb6834; - --g-tv: #2a78d6; - --g-p2p: #eda100; - --g-common: #8d9a9d; - --g-im: #1baf7a; - --g-music: #e34948; - --g-stock: #a6b0b3; - --g-phone: #75848a; - --g-proxy: #a6b0b3; - --g-database: #75848a; - --g-mobile: #008300; - --g-special: #e87ba4; - --g-mining: #a6b0b3; - --g-pcdn: #75848a; - --g-other: #a6b0b3; - --g-unknown: #c6ced0; + /* 应用大类配色照维盟 WayOS「DPI 协议」饼图:ECharts 默认 9 色按 17 个大类的顺序循环(第 10 类起重复),深浅主题相同。 + 颜色有重复,所以图例、表格始终带名称(debug12) */ + --g-http: #5470c6; + --g-game: #91cc75; + --g-tv: #fac858; + --g-p2p: #ee6666; + --g-common: #73c0de; + --g-im: #3ba272; + --g-music: #fc8452; + --g-stock: #9a60b4; + --g-phone: #ea7ccc; + --g-proxy: #5470c6; + --g-database: #91cc75; + --g-mobile: #fac858; + --g-special: #ee6666; + --g-mining: #73c0de; + --g-pcdn: #3ba272; + --g-other: #fc8452; + --g-unknown: #9a60b4; --g-social: var(--g-im); /* 兼容:设置页的识别来源条形图沿用 */ --r-sm: 8px; @@ -89,23 +89,23 @@ --line-up: var(--up); --line-down: var(--down); --down: #3fc4c8; - --g-http: #9085e9; - --g-game: #d95926; - --g-tv: #3987e5; - --g-p2p: #c98500; - --g-common: #6b797c; - --g-im: #199e70; - --g-music: #e66767; - --g-stock: #55636a; - --g-phone: #7f8c8f; - --g-proxy: #55636a; - --g-database: #7f8c8f; - --g-mobile: #008300; - --g-special: #d55181; - --g-mining: #55636a; - --g-pcdn: #7f8c8f; - --g-other: #55636a; - --g-unknown: #3e494c; + --g-http: #5470c6; + --g-game: #91cc75; + --g-tv: #fac858; + --g-p2p: #ee6666; + --g-common: #73c0de; + --g-im: #3ba272; + --g-music: #fc8452; + --g-stock: #9a60b4; + --g-phone: #ea7ccc; + --g-proxy: #5470c6; + --g-database: #91cc75; + --g-mobile: #fac858; + --g-special: #ee6666; + --g-mining: #73c0de; + --g-pcdn: #3ba272; + --g-other: #fc8452; + --g-unknown: #9a60b4; --g-social: var(--g-im); color-scheme: dark; } @@ -133,23 +133,23 @@ --line-up: var(--up); --line-down: var(--down); --down: #3fc4c8; - --g-http: #9085e9; - --g-game: #d95926; - --g-tv: #3987e5; - --g-p2p: #c98500; - --g-common: #6b797c; - --g-im: #199e70; - --g-music: #e66767; - --g-stock: #55636a; - --g-phone: #7f8c8f; - --g-proxy: #55636a; - --g-database: #7f8c8f; - --g-mobile: #008300; - --g-special: #d55181; - --g-mining: #55636a; - --g-pcdn: #7f8c8f; - --g-other: #55636a; - --g-unknown: #3e494c; + --g-http: #5470c6; + --g-game: #91cc75; + --g-tv: #fac858; + --g-p2p: #ee6666; + --g-common: #73c0de; + --g-im: #3ba272; + --g-music: #fc8452; + --g-stock: #9a60b4; + --g-phone: #ea7ccc; + --g-proxy: #5470c6; + --g-database: #91cc75; + --g-mobile: #fac858; + --g-special: #ee6666; + --g-mining: #73c0de; + --g-pcdn: #3ba272; + --g-other: #fc8452; + --g-unknown: #9a60b4; --g-social: var(--g-im); color-scheme: dark; }