diff --git a/shared/inbounds.test.ts b/shared/inbounds.test.ts index 2aa5e20..15e6165 100644 --- a/shared/inbounds.test.ts +++ b/shared/inbounds.test.ts @@ -28,7 +28,7 @@ describe('合并两套写法的入站', () => { 'mixed-port': 7777, listeners: [{ name: '容器A', type: 'mixed', port: 7778, proxy: 'AUTO' }], }) - expect(list.map((i) => i.name)).toEqual(['HTTP 和 SOCKS5 共用', '容器A']) + expect(list.map((i) => i.name)).toEqual(['mixed-port', '容器A']) expect(list[0]!.isDefault).toBe(true) expect(list[1]!.isDefault).toBe(false) expect(list[1]!.listenerIndex).toBe(0) diff --git a/shared/inbounds.ts b/shared/inbounds.ts index 0821907..03f09ee 100644 --- a/shared/inbounds.ts +++ b/shared/inbounds.ts @@ -23,12 +23,12 @@ export const BUILTIN_OUTBOUNDS = [ ] as const /** 旧写法的顶层端口字段,以及它们各自等价于哪种入站类型。 */ -const LEGACY_PORTS: Array<{ key: string; type: string; label: string }> = [ - { key: 'mixed-port', type: 'mixed', label: 'HTTP 和 SOCKS5 共用' }, - { key: 'port', type: 'http', label: 'HTTP' }, - { key: 'socks-port', type: 'socks', label: 'SOCKS5' }, - { key: 'redir-port', type: 'redir', label: '透明代理(REDIRECT)' }, - { key: 'tproxy-port', type: 'tproxy', label: '透明代理(TPROXY)' }, +const LEGACY_PORTS: Array<{ key: string; type: string }> = [ + { key: 'mixed-port', type: 'mixed' }, + { key: 'port', type: 'http' }, + { key: 'socks-port', type: 'socks' }, + { key: 'redir-port', type: 'redir' }, + { key: 'tproxy-port', type: 'tproxy' }, ] /** 一路入站的出站去向。四选一,对应界面上那个下拉框。 */ @@ -77,14 +77,16 @@ export function outboundToProxyField(mode: OutboundMode): string | undefined { export function collectInbounds(data: ConfigObject): Inbound[] { const result: Inbound[] = [] - for (const { key, type, label } of LEGACY_PORTS) { + for (const { key, type } of LEGACY_PORTS) { const raw = data[key] const port = typeof raw === 'number' ? raw : Number(raw) // 0 和缺省都表示没启用这个端口 if (!Number.isFinite(port) || port <= 0) continue result.push({ id: `legacy:${key}`, - name: label, + // 名字直接用它来自的那个配置键。比「HTTP 和 SOCKS5 共用」这种描述好: + // 类型那一列已经写着协议了,名字再说一遍是重复,而配置键能直接对上文件里的行。 + name: key, type, port: String(port), listen: null, diff --git a/web/App.vue b/web/App.vue index 20d95e8..53aebff 100644 --- a/web/App.vue +++ b/web/App.vue @@ -4,13 +4,14 @@ import { ApiError, api, getToken, setToken } from './api' import type { ConfigSnapshot } from './api' import { NAV } from './nav' import { density, toggleDensity } from './prefs' -import InboundList from './views/InboundList.vue' +import RouterPage from './views/RouterPage.vue' import TokenGate from './views/TokenGate.vue' import IconFold from '~icons/ri/sidebar-fold-line' import IconUnfold from '~icons/ri/sidebar-unfold-line' const snapshot = ref(null) const kernel = ref<{ online: boolean; version?: string }>({ online: false }) +const providerLines = ref([]) const needsToken = ref(!getToken()) const loadError = ref('') const loading = ref(false) @@ -24,6 +25,9 @@ async function load() { snapshot.value = config kernel.value = status needsToken.value = false + // 订阅里有哪些线路只有运行中的内核知道,配置文件里只有一个订阅地址。 + // 拿不到不算错误——界面照常能编辑,只是订阅线路那一档不可选。 + providerLines.value = status.online ? await readProviderLines() : [] } catch (error) { if (error instanceof ApiError && error.unauthorized) { needsToken.value = true @@ -35,6 +39,18 @@ async function load() { } } +/** 只取真正的订阅。内核会给每个用了 proxies 的策略组造一个内部 provider,那些不是订阅。 */ +async function readProviderLines(): Promise { + try { + const { providers } = await api.providers() + return Object.values(providers) + .filter((p) => p.vehicleType !== 'Compatible') + .flatMap((p) => p.proxies.map((line) => line.name)) + } catch { + return [] + } +} + function submitToken(value: string) { setToken(value) void load() @@ -109,7 +125,14 @@ const current = computed(() => NAV.find((n) => n.key === active.value)) - +
diff --git a/web/views/InboundDetail.vue b/web/views/InboundDetail.vue new file mode 100644 index 0000000..ad48ea8 --- /dev/null +++ b/web/views/InboundDetail.vue @@ -0,0 +1,259 @@ + + + + + diff --git a/web/views/InboundList.vue b/web/views/InboundList.vue deleted file mode 100644 index 33de9c5..0000000 --- a/web/views/InboundList.vue +++ /dev/null @@ -1,310 +0,0 @@ - - - - - diff --git a/web/views/RouterPage.vue b/web/views/RouterPage.vue new file mode 100644 index 0000000..98dcc6c --- /dev/null +++ b/web/views/RouterPage.vue @@ -0,0 +1,323 @@ + + + + +