From 57690a159c1d0a58ccf93e2641e53bb6d9abb43e Mon Sep 17 00:00:00 2001 From: Jz0ojiang Date: Wed, 12 Aug 2026 13:43:38 +0800 Subject: [PATCH] =?UTF-8?q?=E8=A7=84=E5=88=99=E5=88=97=E8=A1=A8=E6=A0=87?= =?UTF-8?q?=E5=87=BA=E4=B8=8D=E5=8F=AF=E8=BE=BE=E8=A1=8C=EF=BC=8C=E3=80=8C?= =?UTF-8?q?=E5=88=86=E6=B5=81=E8=A7=84=E5=88=99=E3=80=8D=E6=94=B9=E5=90=8D?= =?UTF-8?q?=E3=80=8C=E5=85=A8=E5=B1=80=E8=A7=84=E5=88=99=E3=80=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit MATCH 的实现是无条件返回 true(rules/common/final.go:16-18),第一条 MATCH 之后的行永远轮不到。全局规则和附加规则的列表都把这类行标红、 拦路的 MATCH 标黄,hover 给原因;表底作兜底的 MATCH 不标黄,那是正常 用法。附加规则里用户自己的 MATCH 总会架空表底的自动兜底,兜底行跟着 标红。 规则页的「分流规则」改名「全局规则」,和「附加规则」对仗;术语表里 「分流规则」退为两者的统称。 顺手修 ini 导入的兜底判断:firstMatchIndex 没有 MATCH 时返回 -1, 之前误写成 === null,条件恒假,配方的兜底规则从来没被导入过。 --- CONTEXT.md | 6 +++- web/views/InboundDetail.vue | 44 +++++++++++++++++++++++++---- web/views/RulesPage.vue | 56 +++++++++++++++++++++++++++---------- 3 files changed, 85 insertions(+), 21 deletions(-) diff --git a/CONTEXT.md b/CONTEXT.md index 440a4b8..3ea236a 100644 --- a/CONTEXT.md +++ b/CONTEXT.md @@ -85,9 +85,13 @@ _Avoid_: 无效引用、悬空引用、坏引用 ## 规则 **分流规则**: -配置文件 `rules:` 里的有序列表,自上而下匹配,决定一条连接走哪个出站。顺序本身是语义的一部分。 +自上而下匹配、决定一条连接走哪个出站的有序规则列表,第一条命中即生效。顺序本身是语义的一部分。全局规则和附加规则都是分流规则。 _Avoid_: 路由规则、规则表 +**全局规则**: +配置文件顶层 `rules:` 里的分流规则表。只对没有附加规则的入站生效——带附加规则的入站整表改查自己的表,不再看它。 +_Avoid_: 顶层规则、主规则、默认规则 + **附加规则**: 挂在某一路入站上的一组分流规则,只对从该入站进来的流量生效。 _Avoid_: sub-rules、子规则、私有规则 diff --git a/web/views/InboundDetail.vue b/web/views/InboundDetail.vue index 14181f1..6a4a295 100644 --- a/web/views/InboundDetail.vue +++ b/web/views/InboundDetail.vue @@ -20,7 +20,7 @@ import { proxyGroupName, subRuleName, } from '@shared/inbound-groups.ts' -import { missingLanRules } from '@shared/rules.ts' +import { firstMatchIndex, missingLanRules } from '@shared/rules.ts' import type { GroupSpec, OutboundSetup, PanelGroup } from '@shared/inbound-groups.ts' import { resolveChain } from '@shared/outbound-chain.ts' import { latestDelay } from '../api' @@ -84,6 +84,12 @@ const foreignRuleSet = computed( /** 内网直连还缺几条。全齐了按钮就不出现 */ const lanMissing = computed(() => missingLanRules(props.subRules).length) +/** + * 用户自己写的第一条 MATCH 的下标,没有时是 -1。它之后的行——包括表底的 + * 自动兜底——永远轮不到,标红;它自己标黄,hover 说明原因。 + */ +const subMatchAt = computed(() => firstMatchIndex(props.subRules)) + /** 默认入站由配置顶层的端口字段声明,没有 proxy 字段可写,也不能删。 */ const locked = computed(() => props.inbound.isDefault) @@ -717,8 +723,22 @@ const complete = computed(