release / release (push) Successful in 26s
顶层端口字段没有 proxy 可写(listener/inbound/base.go:97),界面上 切不了订阅。升级删掉顶层键、建同端口的 listener:listen 按 allow-lan 推导后写死,全局规则里 MATCH 之前的部分复制成附加规则,来源照抄 MATCH 目标组的 use:,让流量去向尽量不变。udp 不写,命名入站解析时 默认就是开的(listener/parse.go:52)。 「默认」tag 随术语表改成 legacy,旧叫法进 avoid 列表。
52 lines
1.7 KiB
TypeScript
52 lines
1.7 KiB
TypeScript
/**
|
|
* 仪表盘页的数据整理。
|
|
*
|
|
* 「拿到内核数据之后怎么摆」的纯逻辑,放在这里而不是 DashboardPage.vue 的
|
|
* computed 里,才能被 bun test 直接测到。流量窗口和每路吞吐的聚合在
|
|
* shared/telemetry.ts——那些是采集层的事,跨页面共用。
|
|
*/
|
|
|
|
/** 内核运行模式在界面上怎么念。不在表里的原样显示,不猜它的意思。 */
|
|
export function modeLabel(mode: unknown): string {
|
|
switch (mode) {
|
|
case 'rule':
|
|
return '规则'
|
|
case 'global':
|
|
return '全局'
|
|
case 'direct':
|
|
return '直连'
|
|
default:
|
|
return typeof mode === 'string' && mode ? mode : '—'
|
|
}
|
|
}
|
|
|
|
/** 一个监听中的代理端口。name 用配置键原词,和路由页legacy 入站的命名一致。 */
|
|
export interface KernelPort {
|
|
name: string
|
|
port: number
|
|
}
|
|
|
|
const PORT_KEYS = ['port', 'socks-port', 'mixed-port', 'redir-port', 'tproxy-port'] as const
|
|
|
|
/** 从内核 /configs 的运行时设置里挑出正在监听的代理端口。0 和缺省都表示没启用。 */
|
|
export function kernelPorts(configs: Record<string, unknown>): KernelPort[] {
|
|
const result: KernelPort[] = []
|
|
for (const key of PORT_KEYS) {
|
|
const raw = configs[key]
|
|
const port = typeof raw === 'number' ? raw : Number(raw)
|
|
if (Number.isFinite(port) && port > 0) result.push({ name: key, port })
|
|
}
|
|
return result
|
|
}
|
|
|
|
/**
|
|
* 入站声明的端口在探测公网 IP 时用哪个数。
|
|
* 新式入站的端口可以写 "200,302" 或 "401-429",探测取第一个数字;解析不出返回 null。
|
|
*/
|
|
export function firstPort(port: string): number | null {
|
|
const match = /\d+/.exec(port)
|
|
if (!match) return null
|
|
const value = Number(match[0])
|
|
return value >= 1 && value <= 65535 ? value : null
|
|
}
|