规则表单:类型候选补全为内核全集,目标候选精简

类型照抄内核解析器的 switch(rules/parser.go:17-98),37 种全给——
候选列表是过滤式的,全集不构成负担,缺项才是。目标反着来:只建议
DIRECT 和 REJECT,策略组名手填——全列出来的话,每路入站自动生成的
三个专属组会把列表灌成一面墙。

按原文编辑的输入框给一个完整的逻辑规则做占位例子(原文模式存在的
理由就是这类规则)。弹层滚动条改细杆透明轨道。
This commit is contained in:
2026-08-12 00:13:02 +08:00
parent 4c43756208
commit 7d08f37248
5 changed files with 51 additions and 9 deletions
+3
View File
@@ -230,6 +230,9 @@ function onFocusOut(event: FocusEvent) {
max-width: min(360px, calc(100vw - 2 * var(--s-4)));
max-height: 200px;
overflow-y: auto;
/* 细杆加透明轨道,别让弹层里出现一根系统灰滚动条 */
scrollbar-width: thin;
scrollbar-color: var(--c-border-strong) transparent;
list-style: none;
margin: 0;
padding: var(--s-1);
+3
View File
@@ -242,6 +242,9 @@ function groupAt(index: number): string | null {
max-width: min(360px, calc(100vw - 2 * var(--s-4)));
max-height: 200px;
overflow-y: auto;
/* 细杆加透明轨道,别让弹层里出现一根系统灰滚动条 */
scrollbar-width: thin;
scrollbar-color: var(--c-border-strong) transparent;
list-style: none;
margin: 0;
padding: var(--s-1);
+3
View File
@@ -238,6 +238,9 @@ function onFocusOut(event: FocusEvent) {
max-width: min(360px, calc(100vw - 2 * var(--s-4)));
max-height: 240px;
overflow-y: auto;
/* 细杆加透明轨道,别让弹层里出现一根系统灰滚动条 */
scrollbar-width: thin;
scrollbar-color: var(--c-border-strong) transparent;
list-style: none;
margin: 0;
padding: var(--s-1);
+42 -8
View File
@@ -16,8 +16,6 @@ const props = defineProps<{
open: boolean
/** 传了就是编辑:下标加原文;没传就是新增 */
editing: { index: number; raw: string } | null
/** 目标出站的候选:内置出站、策略组、自有线路。之外也允许手填 */
outboundNames: string[]
/** RULE-SET 载荷的候选:已声明的规则组 */
providerNames: string[]
saving: boolean
@@ -25,27 +23,56 @@ const props = defineProps<{
const emit = defineEmits<{ close: []; submit: [rule: string] }>()
/** 常见的规则类型。不在里面的手填,填了就自动按原文编辑。 */
const COMMON_TYPES = [
/**
* 内核认识的全部规则类型,照抄解析器的 switch(rules/parser.go:17-98),
* 按域名、地理、IP、端口、进程、入站、逻辑的次序排。
*/
const RULE_TYPES = [
'DOMAIN',
'DOMAIN-SUFFIX',
'DOMAIN-KEYWORD',
'DOMAIN-REGEX',
'DOMAIN-WILDCARD',
'GEOSITE',
'GEOIP',
'SRC-GEOIP',
'IP-CIDR',
'IP-CIDR6',
'IP-ASN',
'SRC-IP-CIDR',
'IP-SUFFIX',
'SRC-IP-SUFFIX',
'IP-ASN',
'SRC-IP-ASN',
'DST-PORT',
'SRC-PORT',
'IN-PORT',
'PROCESS-NAME',
'PROCESS-PATH',
'PROCESS-NAME-REGEX',
'PROCESS-PATH-REGEX',
'PROCESS-NAME-WILDCARD',
'PROCESS-PATH-WILDCARD',
'NETWORK',
'UID',
'DSCP',
'IN-TYPE',
'IN-USER',
'IN-NAME',
'REMATCH-NAME',
'AND',
'OR',
'NOT',
'SUB-RULE',
'RULE-SET',
'MATCH',
]
/**
* 目标的建议只给内置出站里日常用的两个。策略组名允许手填——
* 全部列出来的话,每路入站自动生成的三个专属组会把列表灌成一面墙。
*/
const TARGET_SUGGESTIONS = ['DIRECT', 'REJECT']
const dialog = ref<HTMLDialogElement | null>(null)
const rawMode = ref(false)
const raw = ref('')
@@ -135,7 +162,14 @@ function submit() {
<label class="row">
<span class="k">规则</span>
<span class="v">
<input v-model="raw" class="mono" type="text" autocomplete="off" spellcheck="false" />
<input
v-model="raw"
class="mono"
type="text"
placeholder="AND,((DOMAIN-SUFFIX,baidu.com),(NETWORK,UDP)),DIRECT"
autocomplete="off"
spellcheck="false"
/>
</span>
</label>
</div>
@@ -144,7 +178,7 @@ function submit() {
<label class="row">
<span class="k">类型</span>
<span class="v">
<ComboBox v-model="type" mono :options="COMMON_TYPES" />
<ComboBox v-model="type" mono :options="RULE_TYPES" />
</span>
</label>
@@ -173,7 +207,7 @@ function submit() {
<label class="row">
<span class="k">目标</span>
<span class="v">
<ComboBox v-model="target" mono :options="outboundNames" placeholder="DIRECT" />
<ComboBox v-model="target" mono :options="TARGET_SUGGESTIONS" placeholder="DIRECT" />
</span>
</label>
-1
View File
@@ -450,7 +450,6 @@ async function updateNow(name: string) {
<RuleForm
:open="ruleFormOpen"
:editing="ruleEditing === null ? null : { index: ruleEditing, raw: rules[ruleEditing]! }"
:outbound-names="outboundNames"
:provider-names="providerNames"
:saving="saving"
@close="ruleFormOpen = false"