顶层端口字段没有 proxy 可写(listener/inbound/base.go:97),界面上 切不了订阅。升级删掉顶层键、建同端口的 listener:listen 按 allow-lan 推导后写死,全局规则里 MATCH 之前的部分复制成附加规则,来源照抄 MATCH 目标组的 use:,让流量去向尽量不变。udp 不写,命名入站解析时 默认就是开的(listener/parse.go:52)。 「默认」tag 随术语表改成 legacy,旧叫法进 avoid 列表。
This commit is contained in:
@@ -32,6 +32,7 @@ import OutboundCard from '../components/OutboundCard.vue'
|
||||
import SourcePicker from '../components/SourcePicker.vue'
|
||||
import IconEdit from '~icons/ri/edit-line'
|
||||
import IconDelete from '~icons/ri/delete-bin-line'
|
||||
import IconUpgrade from '~icons/ri/arrow-up-circle-line'
|
||||
import IconRight from '~icons/ri/arrow-right-s-line'
|
||||
import IconOffline from '~icons/ri/cloud-off-line'
|
||||
import IconAdd from '~icons/ri/add-line'
|
||||
@@ -61,6 +62,8 @@ const props = defineProps<{
|
||||
const emit = defineEmits<{
|
||||
edit: []
|
||||
remove: []
|
||||
/** 把 legacy 入站升级成命名入站。写配置文件,由父组件先弹确认 */
|
||||
upgrade: []
|
||||
/** 切换某个策略组当前选中谁 */
|
||||
select: [group: string, member: string]
|
||||
test: [name: string, provider: string]
|
||||
@@ -90,7 +93,7 @@ const lanMissing = computed(() => missingLanRules(props.subRules).length)
|
||||
*/
|
||||
const subMatchAt = computed(() => firstMatchIndex(props.subRules))
|
||||
|
||||
/** 默认入站由配置顶层的端口字段声明,没有 proxy 字段可写,也不能删。 */
|
||||
/** legacy 入站由配置顶层的端口字段声明,没有 proxy 字段可写,也不能删,只能升级。 */
|
||||
const locked = computed(() => props.inbound.isDefault)
|
||||
|
||||
const activeTab = ref('')
|
||||
@@ -448,10 +451,15 @@ const complete = computed(
|
||||
<div class="title">
|
||||
<span class="port mono">{{ inbound.port }}</span>
|
||||
<span class="name">{{ inbound.name }}</span>
|
||||
<div v-if="!locked" class="acts">
|
||||
<button type="button" @click="emit('edit')"><IconEdit /> 编辑</button>
|
||||
<button type="button" class="danger" @click="emit('remove')">
|
||||
<IconDelete /> 删除
|
||||
<div class="acts">
|
||||
<template v-if="!locked">
|
||||
<button type="button" @click="emit('edit')"><IconEdit /> 编辑</button>
|
||||
<button type="button" class="danger" @click="emit('remove')">
|
||||
<IconDelete /> 删除
|
||||
</button>
|
||||
</template>
|
||||
<button v-else type="button" :disabled="saving" @click="emit('upgrade')">
|
||||
<IconUpgrade /> 改为命名入站
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
@@ -842,16 +850,21 @@ const complete = computed(
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.acts button:hover {
|
||||
.acts button:hover:not(:disabled) {
|
||||
border-color: var(--c-accent);
|
||||
color: var(--c-accent-text);
|
||||
}
|
||||
|
||||
.acts button.danger:hover {
|
||||
.acts button.danger:hover:not(:disabled) {
|
||||
border-color: var(--c-danger);
|
||||
color: var(--c-danger);
|
||||
}
|
||||
|
||||
.acts button:disabled {
|
||||
color: var(--c-text-faint);
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
.facts {
|
||||
display: grid;
|
||||
grid-template-columns: auto 1fr;
|
||||
|
||||
@@ -22,6 +22,7 @@ import {
|
||||
sharedPeers,
|
||||
syncGenerated,
|
||||
readSetup,
|
||||
upgradeLegacyInbound,
|
||||
userProviders,
|
||||
} from '@shared/inbound-groups.ts'
|
||||
import { missingLanRules, moveRule, ruleProvidersOf } from '@shared/rules.ts'
|
||||
@@ -177,6 +178,30 @@ async function adopt() {
|
||||
await commit(applySetup(clone(), target.name, defaultSetup()), `${target.name} 已改为逐条选线路`)
|
||||
}
|
||||
|
||||
/** 待确认升级的那一路 legacy 入站。非 null 时确认对话框打开着。 */
|
||||
const upgrading = ref<Inbound | null>(null)
|
||||
|
||||
function askUpgrade() {
|
||||
const target = selected.value
|
||||
if (!target || target.legacyKey === null || saving.value) return
|
||||
upgrading.value = target
|
||||
}
|
||||
|
||||
async function upgradeConfirmed() {
|
||||
const target = upgrading.value
|
||||
upgrading.value = null
|
||||
if (!target || saving.value) return
|
||||
const next = upgradeLegacyInbound(clone(), target)
|
||||
if (!next) {
|
||||
toast(`已有名为 ${target.name} 的入站,无法升级`, { kind: 'error' })
|
||||
return
|
||||
}
|
||||
// 新入站追加在 listeners 末尾,升级成功后把选中跟过去,否则选中会被重置到第一行
|
||||
const index = Array.isArray(props.data.listeners) ? props.data.listeners.length : 0
|
||||
const ok = await commit(next, `${target.name} 已改为命名入站`)
|
||||
if (ok) selectedId.value = `listener:${String(index)}`
|
||||
}
|
||||
|
||||
function openAdd() {
|
||||
formEditing.value = null
|
||||
formOpen.value = true
|
||||
@@ -368,6 +393,7 @@ async function removeConfirmed() {
|
||||
:saving="saving"
|
||||
@edit="openEdit"
|
||||
@remove="askRemove"
|
||||
@upgrade="askUpgrade"
|
||||
@select="selectMember"
|
||||
@test="test"
|
||||
@save="saveSetup"
|
||||
@@ -400,6 +426,19 @@ async function removeConfirmed() {
|
||||
@confirm="removeConfirmed"
|
||||
/>
|
||||
|
||||
<ConfirmDialog
|
||||
:open="upgrading !== null"
|
||||
:message="
|
||||
upgrading
|
||||
? `将「${upgrading.name}」改为命名入站?端口不变,此后它的流量改查自己的附加规则` +
|
||||
`(全局规则中 MATCH 之前的部分会复制过来),可以单独选订阅和线路。`
|
||||
: ''
|
||||
"
|
||||
action="升级"
|
||||
@close="upgrading = null"
|
||||
@confirm="upgradeConfirmed"
|
||||
/>
|
||||
|
||||
<RuleForm
|
||||
:open="subFormOpen"
|
||||
:editing="subEditing === null ? null : { index: subEditing, raw: subRules[subEditing]! }"
|
||||
|
||||
Reference in New Issue
Block a user