fix(admin-frontend): 修复节点权限组保存与协议默认值
统一将节点编辑和批量修改的 group_ids、route_ids 序列化为字符串 ID,避免保存权限组后订阅侧无法命中节点 后端新增 whereGroupId 兼容历史字符串与数字 JSON 值, 并补齐 TUIC 版本、ALPN 选项及 AnyTLS 默认 Padding 配置 docs: 新增 HelloAGENTS 通用与工作流避坑指南
This commit is contained in:
Vendored
+3
-3
@@ -909,7 +909,7 @@ export interface AdminNodeBatchUpdatePayload {
|
||||
ids: number[]
|
||||
host?: string
|
||||
rate?: number
|
||||
group_ids?: number[]
|
||||
group_ids?: string[]
|
||||
}
|
||||
|
||||
export interface AdminNodeSavePayload {
|
||||
@@ -917,8 +917,8 @@ export interface AdminNodeSavePayload {
|
||||
type: AdminNodeType
|
||||
code?: string
|
||||
name: string
|
||||
group_ids?: number[]
|
||||
route_ids?: number[]
|
||||
group_ids?: string[]
|
||||
route_ids?: string[]
|
||||
parent_id?: number | null
|
||||
enabled?: boolean
|
||||
host: string
|
||||
|
||||
@@ -55,6 +55,14 @@ function toNumberArray(value: unknown): number[] {
|
||||
)]
|
||||
}
|
||||
|
||||
function toJsonIdArray(value: unknown[]): string[] {
|
||||
return [...new Set(
|
||||
value
|
||||
.map((item) => String(item ?? '').trim())
|
||||
.filter(Boolean),
|
||||
)]
|
||||
}
|
||||
|
||||
function splitMultiline(value: string): string[] {
|
||||
return [...new Set(
|
||||
value
|
||||
@@ -154,6 +162,9 @@ export function toNodeFormModel(node?: AdminNodeItem | null): NodeFormModel {
|
||||
: createEmptyNodeForm().rateTimeRanges
|
||||
form.tags = toStringArray(node.tags)
|
||||
form.groupIds = toNumberArray(node.group_ids)
|
||||
if (form.groupIds.length === 0 && Array.isArray(node.groups)) {
|
||||
form.groupIds = toNumberArray(node.groups.map((group) => group.id))
|
||||
}
|
||||
form.routeIds = toNumberArray(node.route_ids)
|
||||
form.host = toStringValue(node.host)
|
||||
form.port = toStringValue(node.port)
|
||||
@@ -467,8 +478,8 @@ export function toNodeSavePayload(form: NodeFormModel): AdminNodeSavePayload {
|
||||
type: form.type as AdminNodeType,
|
||||
code: form.code.trim() || undefined,
|
||||
name: form.name.trim(),
|
||||
group_ids: [...new Set(form.groupIds)],
|
||||
route_ids: [...new Set(form.routeIds)],
|
||||
group_ids: toJsonIdArray(form.groupIds),
|
||||
route_ids: toJsonIdArray(form.routeIds),
|
||||
parent_id: form.parentId ?? undefined,
|
||||
enabled: form.enabled,
|
||||
host: form.host.trim(),
|
||||
|
||||
@@ -197,6 +197,17 @@ export const NODE_UDP_RELAY_MODE_OPTIONS: Array<NodeOption> = [
|
||||
{ value: 'quic', label: 'quic' },
|
||||
]
|
||||
|
||||
export const NODE_TUIC_VERSION_OPTIONS: Array<NodeOption<number>> = [
|
||||
{ value: 5, label: 'V5' },
|
||||
{ value: 4, label: 'V4' },
|
||||
]
|
||||
|
||||
export const NODE_ALPN_OPTIONS: Array<NodeOption> = [
|
||||
{ value: 'h3', label: 'HTTP/3' },
|
||||
{ value: 'h2', label: 'HTTP/2' },
|
||||
{ value: 'http/1.1', label: 'HTTP/1.1' },
|
||||
]
|
||||
|
||||
export const NODE_MUX_PROTOCOL_OPTIONS: Array<NodeOption> = [
|
||||
{ value: 'yamux', label: 'yamux' },
|
||||
{ value: 'smux', label: 'smux' },
|
||||
@@ -290,6 +301,11 @@ export function createEmptyNodeForm(): NodeFormModel {
|
||||
'0=30-30',
|
||||
'1=100-400',
|
||||
'2=400-500,c,500-1000,c,500-1000,c,500-1000,c,500-1000',
|
||||
'3=9-9,500-1000',
|
||||
'4=500-1000',
|
||||
'5=500-1000',
|
||||
'6=500-1000',
|
||||
'7=500-1000',
|
||||
].join('\n'),
|
||||
multiplexEnabled: false,
|
||||
multiplexProtocol: 'yamux',
|
||||
|
||||
@@ -6,7 +6,7 @@ import type { AdminServerGroupItem } from '@/types/api'
|
||||
interface NodeBatchEditPayload {
|
||||
host?: string
|
||||
rate?: number
|
||||
group_ids?: number[]
|
||||
group_ids?: string[]
|
||||
}
|
||||
|
||||
const props = defineProps<{
|
||||
@@ -64,7 +64,7 @@ function handleSubmit() {
|
||||
emit('submit', {
|
||||
host: form.updateHost ? form.host.trim() : undefined,
|
||||
rate: form.updateRate ? Number(form.rate) : undefined,
|
||||
group_ids: form.updateGroups ? [...form.groupIds] : undefined,
|
||||
group_ids: form.updateGroups ? [...new Set(form.groupIds.map((item) => String(item)))] : undefined,
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -2,12 +2,14 @@
|
||||
import { computed } from 'vue'
|
||||
import {
|
||||
getNodeProtocolHint,
|
||||
NODE_ALPN_OPTIONS,
|
||||
NODE_CONGESTION_CONTROL_OPTIONS,
|
||||
NODE_MUX_PROTOCOL_OPTIONS,
|
||||
NODE_SHADOWSOCKS_CIPHER_OPTIONS,
|
||||
NODE_SHADOWSOCKS_OBFS_OPTIONS,
|
||||
NODE_TCP_HEADER_OPTIONS,
|
||||
NODE_TLS_FINGERPRINT_OPTIONS,
|
||||
NODE_TUIC_VERSION_OPTIONS,
|
||||
NODE_UDP_RELAY_MODE_OPTIONS,
|
||||
NODE_VLESS_FLOW_OPTIONS,
|
||||
shouldShowRealitySettings,
|
||||
@@ -58,13 +60,6 @@ const currentProtocolHint = computed(() => getNodeProtocolHint(props.form.type))
|
||||
</ElSelect>
|
||||
</ElFormItem>
|
||||
|
||||
<ElFormItem
|
||||
v-if="['hysteria', 'tuic', 'anytls'].includes(props.form.type)"
|
||||
label="服务器名称(SNI)"
|
||||
>
|
||||
<ElInput v-model="props.form.tlsServerName" placeholder="example.com" />
|
||||
</ElFormItem>
|
||||
|
||||
<ElFormItem v-if="showTlsSection" label="服务器名称(SNI)">
|
||||
<ElInput v-model="props.form.tlsServerName" placeholder="example.com" />
|
||||
</ElFormItem>
|
||||
@@ -366,7 +361,14 @@ const currentProtocolHint = computed(() => getNodeProtocolHint(props.form.type))
|
||||
|
||||
<template v-else-if="props.form.type === 'tuic'">
|
||||
<ElFormItem label="协议版本">
|
||||
<ElInputNumber v-model="props.form.tuicVersion" :min="1" :controls="false" class="full-width" />
|
||||
<ElSelect v-model="props.form.tuicVersion" placeholder="请选择版本">
|
||||
<ElOption
|
||||
v-for="option in NODE_TUIC_VERSION_OPTIONS"
|
||||
:key="option.value"
|
||||
:label="option.label"
|
||||
:value="option.value"
|
||||
/>
|
||||
</ElSelect>
|
||||
</ElFormItem>
|
||||
<ElFormItem label="拥塞控制">
|
||||
<ElSelect v-model="props.form.tuicCongestionControl" placeholder="请选择拥塞控制">
|
||||
@@ -396,7 +398,14 @@ const currentProtocolHint = computed(() => getNodeProtocolHint(props.form.type))
|
||||
allow-create
|
||||
default-first-option
|
||||
placeholder="输入后回车添加 ALPN"
|
||||
/>
|
||||
>
|
||||
<ElOption
|
||||
v-for="option in NODE_ALPN_OPTIONS"
|
||||
:key="option.value"
|
||||
:label="option.label"
|
||||
:value="option.value"
|
||||
/>
|
||||
</ElSelect>
|
||||
</ElFormItem>
|
||||
</template>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user