规则编辑:建议列表全量展开,目标补齐候选,删除免确认

组合框展开先给全量、本次展开输入过才过滤——按当前值过滤的话,预填的
类型会把列表滤到只剩它自己,MATCH 这类排在后面的选项等于不存在。类型
因此可以默认留空,placeholder 当示例。

目标建议由页面传入:全局规则给内置两个加用户自建的组和自有线路;附加
规则多一项本路专属组——「这个载荷走本路代理」写的就是它,放在拦截规则
前面还能做豁免。生成的专属组不列,每路三个会把列表灌成一面墙。

原文/字段切换只拦真正整行编辑的类型(isRawOnlyRule):之前用
isStructuredEditable 拦,新增时的空原文永远过不了,卡死在原文模式。

删除规则和附加规则不再二次确认——删错了有撤回,确认框只是多一步;
toast 带上被删规则的原文。
This commit is contained in:
2026-08-12 13:16:58 +08:00
parent 955fa340af
commit 48e97bd91f
6 changed files with 80 additions and 55 deletions
+24 -18
View File
@@ -7,13 +7,14 @@
* 运行时动作(切换选中、测延迟)不经过它,因为它们不写文件也不需要校验。
*/
import { computed, onMounted, ref, watch } from 'vue'
import { collectInbounds } from '@shared/inbounds.ts'
import { collectInbounds, collectOutboundNames } from '@shared/inbounds.ts'
import type { Inbound } from '@shared/inbounds.ts'
import {
applySetup,
applySubRules,
chainGroupName,
groupUses,
isGenerated,
panelGroups,
proxyGroupName,
pruneGenerated,
@@ -233,11 +234,24 @@ const subRules = computed(() =>
/** RULE-SET 载荷的候选,给规则表单用 */
const ruleProviderNames = computed(() => Object.keys(ruleProvidersOf(props.data)))
/**
* 附加规则目标的建议:日常用的两个内置出站、这一路自己的专属组(「这个载荷走
* 本路代理」写的就是它),再加用户自己建的策略组和自有线路。别的入站的专属组不列。
*/
const subTargetOptions = computed(() => {
const outs = collectOutboundNames(props.data)
return [
'DIRECT',
'REJECT',
...(selected.value ? [proxyGroupName(selected.value.name)] : []),
...outs.groups.filter((name) => !isGenerated(name)),
...outs.ownProxies,
]
})
const subFormOpen = ref(false)
/** 编辑时是下标,新增时是 null */
const subEditing = ref<number | null>(null)
/** 待确认删除的附加规则下标 */
const removingSubRule = ref<number | null>(null)
function openSubAdd() {
subEditing.value = null
@@ -272,13 +286,13 @@ async function moveSubRule(index: number, delta: -1 | 1) {
await commitSubRules(moveRule(subRules.value, index, delta), '顺序已保存')
}
async function removeSubRuleConfirmed() {
const index = removingSubRule.value
removingSubRule.value = null
if (index === null) return
// 删除不设二次确认:删错了有撤回,规则原文放进提示里让人看清删掉的是哪条
async function removeSubRule(index: number) {
const rule = subRules.value[index]
if (rule === undefined) return
await commitSubRules(
subRules.value.filter((_, i) => i !== index),
'已删除这条附加规则',
`已删除附加规则 [ ${rule} ]`,
)
}
@@ -360,7 +374,7 @@ async function removeConfirmed() {
@adopt="adopt"
@sub-add="openSubAdd"
@sub-edit="openSubEdit"
@sub-remove="removingSubRule = $event"
@sub-remove="removeSubRule"
@sub-move="moveSubRule"
@sub-lan="addLanSubRules"
/>
@@ -390,20 +404,12 @@ async function removeConfirmed() {
:open="subFormOpen"
:editing="subEditing === null ? null : { index: subEditing, raw: subRules[subEditing]! }"
:provider-names="ruleProviderNames"
:target-options="subTargetOptions"
:saving="saving"
@close="subFormOpen = false"
@submit="submitSubRule"
/>
<ConfirmDialog
:open="removingSubRule !== null"
:message="
removingSubRule !== null ? `删除附加规则「${subRules[removingSubRule] ?? ''}」?` : ''
"
action="删除"
@close="removingSubRule = null"
@confirm="removeSubRuleConfirmed"
/>
</div>
</template>