feat: M1 高级传输参数(P0)

- store: Local 增加 useEncryption/useCompression/bandwidthLimit/poolCount/metadatas/annotations;Remote 增加 transportProtocol/transportTls/transportPool/transportTlsServerName;新增 migrate() ALTER TABLE 迁移旧库

- render: 输出 transport 段(protocol/tls/poolCount)与 proxy 高级字段;补 TestRenderTransportAdvanced/OmittedWhenEmpty

- main: renderRemote 闭包透传 M1 字段到 render.Proxy

- web: LocalNode/RemoteNode 折叠高级区表单,types.ts 接口扩展

- 验证:go test 全绿、vue-tsc/build 通过、端到端 PUT canvas→frpc JSON 输出完整
This commit is contained in:
2026-08-17 12:28:54 +08:00
parent e73bd834a1
commit 07f25ea067
11 changed files with 460 additions and 62 deletions

View File

@ -25,12 +25,34 @@
<label>令牌 <input v-model="tokenField" /></label>
<label>URL <input v-model="urlField" /></label>
</div>
<div class="adv">
<button class="adv-toggle" @click.stop="showAdv = !showAdv">
{{ showAdv ? ' 收起高级' : ' 高级' }}
</button>
<div v-if="showAdv" class="adv-body">
<label
>传输协议
<select v-model="transportProtocolField">
<option value="">tcp(默认)</option>
<option value="quic">quic</option>
<option value="kcp">kcp</option>
<option value="websocket">websocket</option>
</select>
</label>
<label class="adv-check">
<input v-model="transportTlsField" type="checkbox" /> TLS 传输
</label>
<label>TLS SNI <input v-model="transportTlsServerNameField" placeholder="frps.local" /></label>
<label>连接池 <input v-model.number="transportPoolField" type="number" min="0" /></label>
</div>
</div>
</div>
</template>
<script setup lang="ts">
import { Handle, Position } from '@vue-flow/core'
import { computed } from 'vue'
import { computed, ref } from 'vue'
import type { CanvasRemote } from '../types'
const props = defineProps<{
@ -58,6 +80,11 @@ const portField = field('port')
const tokenField = field('token')
const urlField = field('url')
const enabledField = field('enabled')
const transportProtocolField = field('transportProtocol')
const transportTlsField = field('transportTls')
const transportTlsServerNameField = field('transportTlsServerName')
const transportPoolField = field('transportPool')
const showAdv = ref(false)
</script>
<style scoped lang="scss">
@ -168,5 +195,54 @@ const enabledField = field('enabled')
flex: 0 0 64px;
}
}
.adv {
margin-top: 6px;
.adv-toggle {
border: 1px dashed #ffcc80;
background: transparent;
color: #ef6c00;
font-size: 11px;
border-radius: 6px;
padding: 2px 8px;
cursor: pointer;
}
.adv-body {
display: flex;
flex-direction: column;
gap: 4px;
margin-top: 6px;
padding: 6px;
background: rgba(255, 152, 0, 0.06);
border-radius: 8px;
label {
display: flex;
align-items: center;
gap: 4px;
font-size: 11px;
color: #ef6c00;
input,
select {
flex: 1;
min-width: 0;
border: 1px solid #ffcc80;
border-radius: 6px;
padding: 2px 6px;
font-size: 12px;
background: #fff;
color: #333;
&:focus {
outline: none;
border-color: #ff9800;
}
}
}
.adv-check {
font-size: 11px;
}
}
}
}
</style>