@@ -67,13 +67,20 @@ interface FormData {
6767 logLevel : string ;
6868 connectionPort : string ;
6969 accessInfo : string ;
70+ intranetTargetMaster : string ; // 内网穿透的目标服务器
71+ intranetTargetPort : string ; // 内网穿透的目标端口
72+ intranetExitIp : string ; // 内网穿透的出口IP
73+ certPath : string ; // TLS 2 证书路径
74+ keyPath : string ; // TLS 2 密钥路径
7075}
7176
7277interface TemplateCreateRequest {
7378 log : string ;
7479 listen_port : number ;
7580 mode : string ;
7681 tls ?: number ;
82+ cert_path ?: string ;
83+ key_path ?: string ;
7784 inbounds ?: {
7885 target_host : string ;
7986 target_port : number ;
@@ -164,7 +171,12 @@ export default function TemplatesPage() {
164171 tlsLevel : '1' ,
165172 logLevel : 'debug' , // 默认debug级别
166173 connectionPort : '' ,
167- accessInfo : ''
174+ accessInfo : '' ,
175+ intranetTargetMaster : '' ,
176+ intranetTargetPort : '' ,
177+ intranetExitIp : '' ,
178+ certPath : '' ,
179+ keyPath : ''
168180 } ) ;
169181
170182 // 当监听类型改变时,自动设置目标IP
@@ -180,6 +192,34 @@ export default function TemplatesPage() {
180192 setFormData ( prev => ( { ...prev , [ field ] : value } ) ) ;
181193 } ;
182194
195+ // 清空表单数据的函数
196+ const resetFormData = ( ) => {
197+ setFormData ( {
198+ userPort : '' ,
199+ masterServer : '' ,
200+ listenType : 'external' , // 保持默认值
201+ targetIp : '' ,
202+ targetPort : '' ,
203+ targetMaster : '' ,
204+ targetMasterPort : '' ,
205+ tlsLevel : '1' , // 保持默认值
206+ logLevel : 'debug' , // 保持默认值
207+ connectionPort : '' ,
208+ accessInfo : '' ,
209+ intranetTargetMaster : '' ,
210+ intranetTargetPort : '' ,
211+ intranetExitIp : '' ,
212+ certPath : '' ,
213+ keyPath : ''
214+ } ) ;
215+ } ;
216+
217+ // 切换隧道模式时清空表单数据
218+ const handleModeChange = ( mode : string ) => {
219+ setSelectedMode ( mode ) ;
220+ resetFormData ( ) ;
221+ } ;
222+
183223 // 从URL中提取IP/域名
184224 const extractHostFromUrl = ( url : string ) : string => {
185225 try {
@@ -221,7 +261,7 @@ export default function TemplatesPage() {
221261 < div className = "flex items-center gap-3 justify-between" >
222262 < div className = "flex items-center gap-3" >
223263 < FontAwesomeIcon icon = { faLayerGroup } className = "text-2xl text-primary" />
224- < h2 className = "text-2xl font-bold" > 选择隧道模式 </ h2 >
264+ < h2 className = "text-2xl font-bold" > 选择应用模式 </ h2 >
225265 </ div >
226266 < Button
227267 variant = "flat"
@@ -238,7 +278,7 @@ export default function TemplatesPage() {
238278 key = { mode . id }
239279 isPressable
240280 isHoverable
241- onPress = { ( ) => setSelectedMode ( mode . id ) }
281+ onPress = { ( ) => handleModeChange ( mode . id ) }
242282 className = { `cursor-pointer transition-all duration-200 ${
243283 selectedMode === mode . id
244284 ? 'ring-2 ring-primary ring-offset-2'
@@ -351,7 +391,7 @@ export default function TemplatesPage() {
351391 ]
352392 } ,
353393 {
354- label : '中转机器 [server]' ,
394+ label : '入口机器 [server]' ,
355395 type : 'relay' ,
356396 formFields : [
357397 {
@@ -369,7 +409,7 @@ export default function TemplatesPage() {
369409 ]
370410 } ,
371411 {
372- label : '目标机器 [client]' ,
412+ label : '出口机器 [client]' ,
373413 type : 'target' ,
374414 formFields : [
375415 {
@@ -401,9 +441,9 @@ export default function TemplatesPage() {
401441 type : 'user' ,
402442 formFields : [
403443 {
404- label : '服务端口 ' ,
444+ label : '访问端口 ' ,
405445 key : 'userPort' ,
406- placeholder : '例如: 8080' ,
446+ placeholder : '8080' ,
407447 value : formData . userPort
408448 }
409449 ]
@@ -413,51 +453,46 @@ export default function TemplatesPage() {
413453 type : 'relay' ,
414454 formFields : [
415455 {
416- label : '中转服务器 ' ,
456+ label : '连接服务器 ' ,
417457 key : 'masterServer' ,
418458 type : 'select' ,
419- placeholder : '选择服务器 ' ,
459+ placeholder : '下拉选择 ' ,
420460 value : formData . masterServer ,
421461 options : endpoints . map ( endpoint => ( {
422462 value : endpoint . name ,
423463 label : `${ endpoint . name } [${ extractHostFromUrl ( endpoint . url ) } ]${ endpoint . status === 'FAIL' ? ' - 异常' : '' } ` ,
424464 disabled : endpoint . status === 'FAIL'
425465 } ) )
426- } ,
427- {
428- label : 'TLS级别' ,
429- key : 'tlsLevel' ,
430- type : 'select' ,
431- value : formData . tlsLevel ,
432- placeholder : '选择TLS级别' ,
433- options : tlsLevels . map ( level => ( {
434- value : level . value ,
435- label : level . label
436- } ) )
437- } ,
438- {
439- label : '日志级别' ,
440- key : 'logLevel' ,
441- type : 'select' ,
442- value : formData . logLevel ,
443- placeholder : '选择日志级别' ,
444- options : logLevels . map ( level => ( {
445- value : level . value ,
446- label : level . label
447- } ) )
448466 }
449467 ]
450468 } ,
451469 {
452- label : '外网访问 [client]' ,
470+ label : '内网服务 [client]' ,
453471 type : 'target' ,
454472 formFields : [
455473 {
456- label : '访问信息' ,
457- key : 'accessInfo' ,
458- placeholder : '将自动生成' ,
459- value : formData . masterServer ? `${ formData . masterServer } :公网端口` : '' ,
460- type : 'text'
474+ label : '连接服务器' ,
475+ key : 'intranetTargetMaster' ,
476+ type : 'select' ,
477+ placeholder : '下拉选择' ,
478+ value : formData . intranetTargetMaster ,
479+ options : endpoints . map ( endpoint => ( {
480+ value : endpoint . name ,
481+ label : `${ endpoint . name } [${ extractHostFromUrl ( endpoint . url ) } ]${ endpoint . status === 'FAIL' ? ' - 异常' : '' } ` ,
482+ disabled : endpoint . status === 'FAIL'
483+ } ) )
484+ } ,
485+ {
486+ label : '服务IP' ,
487+ key : 'intranetExitIp' ,
488+ placeholder : '服务的IP' ,
489+ value : formData . intranetExitIp
490+ } ,
491+ {
492+ label : '服务端口' ,
493+ key : 'intranetTargetPort' ,
494+ placeholder : '3306' ,
495+ value : formData . intranetTargetPort
461496 }
462497 ]
463498 }
@@ -604,7 +639,7 @@ export default function TemplatesPage() {
604639 < div className = "text-xs text-default-500 mb-2" >
605640 { selectedMode === 'single' ? '访问' :
606641 selectedMode === 'double' ? '访问' :
607- selectedMode === 'intranet' ? '穿透 ' : '连接' }
642+ selectedMode === 'intranet' ? '访问 ' : '连接' }
608643 </ div >
609644 < svg width = "120" height = "14" viewBox = "0 0 120 14" className = "text-blue-600" >
610645 { /* 双向箭头横线 */ }
@@ -641,14 +676,29 @@ export default function TemplatesPage() {
641676 < polygon points = "110,7 102,4 102,10" fill = "currentColor" />
642677 </ svg >
643678
644- { /* 双端转发的连接池配置 */ }
645- { selectedMode === 'double' && (
679+ { /* 双端转发和内网穿透的连接池配置 */ }
680+ { ( selectedMode === 'double' || selectedMode === 'intranet' ) && (
646681 < div className = "bg-blue-50 border-2 border-blue-200 rounded-lg p-2 shadow-sm mt-2" style = { { width : '120px' } } >
647682 < div className = "flex items-center gap-1 mb-2" >
648683 < FontAwesomeIcon icon = { faGear } className = "text-blue-600 text-xs" />
649- < span className = "text-xs font-medium text-blue-800" > 连接池</ span >
684+ < span className = "text-xs font-medium text-blue-800" >
685+ { selectedMode === 'double' ? '连接配置' : '连接配置' }
686+ </ span >
650687 </ div >
651688 < div className = "space-y-1" >
689+ < div >
690+ < label className = "block text-xs text-gray-700 mb-1" >
691+ { selectedMode === 'double' ? '连接端口' : '连接端口' }
692+ </ label >
693+ < input
694+ type = "text"
695+ value = { formData . connectionPort }
696+ onChange = { ( e ) => updateField ( 'connectionPort' , e . target . value ) }
697+ placeholder = "10101"
698+ className = "w-full px-1 py-1 text-xs border border-gray-300 rounded"
699+ />
700+ </ div >
701+
652702 < div >
653703 < label className = "block text-xs text-gray-700 mb-1" > TLS</ label >
654704 < select
@@ -663,15 +713,32 @@ export default function TemplatesPage() {
663713 ) ) }
664714 </ select >
665715 </ div >
666- < div >
667- < label className = "block text-xs text-gray-700 mb-1" > 连接端口</ label >
668- < input
669- type = "text"
670- value = { formData . connectionPort || '10101' }
671- onChange = { ( e ) => updateField ( 'connectionPort' , e . target . value ) }
672- className = "w-full px-1 py-1 text-xs border border-gray-300 rounded"
673- />
674- </ div >
716+
717+ { /* TLS 2 的证书配置 */ }
718+ { formData . tlsLevel === '2' && (
719+ < >
720+ < div >
721+ < label className = "block text-xs text-gray-700 mb-1" > 证书路径</ label >
722+ < input
723+ type = "text"
724+ value = { formData . certPath }
725+ onChange = { ( e ) => updateField ( 'certPath' , e . target . value ) }
726+ placeholder = "/path/to/cert.pem"
727+ className = "w-full px-1 py-1 text-xs border border-gray-300 rounded"
728+ />
729+ </ div >
730+ < div >
731+ < label className = "block text-xs text-gray-700 mb-1" > 密钥路径</ label >
732+ < input
733+ type = "text"
734+ value = { formData . keyPath }
735+ onChange = { ( e ) => updateField ( 'keyPath' , e . target . value ) }
736+ placeholder = "/path/to/key.pem"
737+ className = "w-full px-1 py-1 text-xs border border-gray-300 rounded"
738+ />
739+ </ div >
740+ </ >
741+ ) }
675742 </ div >
676743 </ div >
677744 ) }
@@ -695,7 +762,7 @@ export default function TemplatesPage() {
695762 : '用户可以访问指定端口来访问目标IP的服务'
696763 ) }
697764 { selectedMode === 'double' && '用户可以访问本地端口,通过双端加密隧道连接到目标服务' }
698- { selectedMode === 'intranet' && '外部用户可以通过公网地址访问您的内网服务 ' }
765+ { selectedMode === 'intranet' && '用户可以通过公网端口访问内网服务,实现内网穿透 ' }
699766 </ div >
700767 </ div >
701768 </ CardBody >
@@ -786,7 +853,7 @@ export default function TemplatesPage() {
786853 return null ;
787854 }
788855
789- return {
856+ const doubleRequest : TemplateCreateRequest = {
790857 log : formData . logLevel ,
791858 listen_port : parseInt ( formData . connectionPort ) ,
792859 mode : 'bothway' ,
@@ -805,9 +872,37 @@ export default function TemplatesPage() {
805872 }
806873 } ;
807874
875+ // 如果是TLS 2,添加证书路径
876+ if ( formData . tlsLevel === '2' ) {
877+ doubleRequest . cert_path = formData . certPath ;
878+ doubleRequest . key_path = formData . keyPath ;
879+ }
880+
881+ return doubleRequest ;
882+
808883 case 'intranet' :
809- // 内网穿透暂未实现
810- return null ;
884+ if ( ! formData . userPort || ! formData . masterServer || ! formData . intranetTargetMaster || ! formData . intranetTargetPort || ! formData . connectionPort ) {
885+ return null ;
886+ }
887+
888+ return {
889+ log : formData . logLevel ,
890+ listen_port : parseInt ( formData . connectionPort ) ,
891+ mode : 'intranet' ,
892+ tls : parseInt ( formData . tlsLevel ) ,
893+ inbounds : {
894+ target_host : '' ,
895+ target_port : parseInt ( formData . userPort ) ,
896+ master_id : getEndpointIdByName ( formData . masterServer ) ,
897+ type : 'server'
898+ } ,
899+ outbounds : {
900+ target_host : formData . intranetExitIp || '127.0.0.1' ,
901+ target_port : parseInt ( formData . intranetTargetPort ) ,
902+ master_id : getEndpointIdByName ( formData . intranetTargetMaster ) ,
903+ type : 'client'
904+ }
905+ } ;
811906
812907 default :
813908 return null ;
@@ -830,8 +925,9 @@ export default function TemplatesPage() {
830925
831926 // 显示进度提示
832927 addToast ( {
833- title : '正在创建隧道...' ,
834- description : selectedMode === 'bothway' ? '正在创建双端隧道,请稍候' : '正在创建隧道,请稍候' ,
928+ timeout : 1 ,
929+ title : '正在创建场景中...' ,
930+ description : selectedMode === 'bothway' ? '正在创建场景中,请稍候' : '正在创建场景中,请稍候' ,
835931 color : 'primary'
836932 } ) ;
837933
0 commit comments