@@ -67,6 +67,7 @@ import SecureVerificationModal from '../../../common/modals/SecureVerificationMo
6767import StatusCodeRiskGuardModal from './StatusCodeRiskGuardModal' ;
6868import ChannelKeyDisplay from '../../../common/ui/ChannelKeyDisplay' ;
6969import { useSecureVerification } from '../../../../hooks/common/useSecureVerification' ;
70+ import { parseChannelConnectionString } from '../../../../helpers/token' ;
7071import { createApiCalls } from '../../../../services/secureVerification' ;
7172import {
7273 collectInvalidStatusCodeEntries ,
@@ -398,6 +399,9 @@ const EditChannelModal = (props) => {
398399 [ ] ,
399400 ) ;
400401
402+ // 剪贴板连接信息自动检测
403+ const [ clipboardConfig , setClipboardConfig ] = useState ( null ) ;
404+
401405 // 高级设置折叠状态
402406 const [ advancedSettingsOpen , setAdvancedSettingsOpen ] = useState ( false ) ;
403407 const formContainerRef = useRef ( null ) ;
@@ -538,6 +542,35 @@ const EditChannelModal = (props) => {
538542 handleInputChange ( 'settings' , settingsJson ) ;
539543 } ;
540544
545+ const applyClipboardConfig = ( config ) => {
546+ if ( ! config ) return ;
547+ setInputs ( ( prev ) => ( {
548+ ...prev ,
549+ key : config . key ,
550+ base_url : config . url ,
551+ } ) ) ;
552+ if ( formApiRef . current ) {
553+ formApiRef . current . setValue ( 'key' , config . key ) ;
554+ formApiRef . current . setValue ( 'base_url' , config . url ) ;
555+ }
556+ setClipboardConfig ( null ) ;
557+ showSuccess ( t ( '连接信息已填入' ) ) ;
558+ } ;
559+
560+ const pasteFromClipboard = async ( ) => {
561+ try {
562+ const text = await navigator . clipboard . readText ( ) ;
563+ const parsed = parseChannelConnectionString ( text ) ;
564+ if ( parsed ) {
565+ applyClipboardConfig ( parsed ) ;
566+ } else {
567+ showInfo ( t ( '剪贴板中未检测到连接信息' ) ) ;
568+ }
569+ } catch {
570+ showError ( t ( '无法读取剪贴板' ) ) ;
571+ }
572+ } ;
573+
541574 const isIonetLocked = isIonetChannel && isEdit ;
542575
543576 const handleInputChange = ( name , value ) => {
@@ -1269,6 +1302,13 @@ const EditChannelModal = (props) => {
12691302 loadChannel ( ) ;
12701303 } else {
12711304 formApiRef . current ?. setValues ( getInitValues ( ) ) ;
1305+ // best-effort clipboard auto-detect for new channels
1306+ navigator . clipboard . readText ( ) . then ( ( text ) => {
1307+ const parsed = parseChannelConnectionString ( text ) ;
1308+ if ( parsed ) {
1309+ setClipboardConfig ( parsed ) ;
1310+ }
1311+ } ) . catch ( ( ) => { } ) ;
12721312 }
12731313 fetchModelGroups ( ) ;
12741314 // 重置手动输入模式状态
@@ -1329,6 +1369,8 @@ const EditChannelModal = (props) => {
13291369 setInputs ( getInitValues ( ) ) ;
13301370 // 重置密钥显示状态
13311371 resetKeyDisplayState ( ) ;
1372+ // 重置剪贴板检测状态
1373+ setClipboardConfig ( null ) ;
13321374 } ;
13331375
13341376 const handleVertexUploadChange = ( { fileList } ) => {
@@ -2077,14 +2119,27 @@ const EditChannelModal = (props) => {
20772119 < SideSheet
20782120 placement = { isEdit ? 'right' : 'left' }
20792121 title = {
2080- < Space >
2081- < Tag color = 'blue' shape = 'circle' >
2082- { isEdit ? t ( '编辑' ) : t ( '新建' ) }
2083- </ Tag >
2084- < Title heading = { 4 } className = 'm-0' >
2085- { isEdit ? t ( '更新渠道信息' ) : t ( '创建新的渠道' ) }
2086- </ Title >
2087- </ Space >
2122+ < div className = 'flex items-center justify-between w-full' >
2123+ < Space >
2124+ < Tag color = 'blue' shape = 'circle' >
2125+ { isEdit ? t ( '编辑' ) : t ( '新建' ) }
2126+ </ Tag >
2127+ < Title heading = { 4 } className = 'm-0' >
2128+ { isEdit ? t ( '更新渠道信息' ) : t ( '创建新的渠道' ) }
2129+ </ Title >
2130+ </ Space >
2131+ { ! isEdit && (
2132+ < Button
2133+ size = 'small'
2134+ type = 'tertiary'
2135+ className = 'ec-dbcd0a3c01b55203 shrink-0'
2136+ icon = { < IconBolt /> }
2137+ onClick = { pasteFromClipboard }
2138+ >
2139+ { t ( '从剪贴板粘贴配置' ) }
2140+ </ Button >
2141+ ) }
2142+ </ div >
20882143 }
20892144 bodyStyle = { { padding : '0' } }
20902145 visible = { props . visible }
@@ -2446,6 +2501,34 @@ const EditChannelModal = (props) => {
24462501 < >
24472502 < Spin spinning = { loading } >
24482503 < div className = 'p-2 space-y-3' ref = { formContainerRef } >
2504+ { ! isEdit && clipboardConfig && (
2505+ < Banner
2506+ type = 'info'
2507+ className = 'ec-dbcd0a3c01b55203'
2508+ description = {
2509+ < div className = 'flex items-center justify-between gap-2' >
2510+ < span > { t ( '检测到剪贴板中的连接信息' ) } </ span >
2511+ < div className = 'flex gap-1' >
2512+ < Button
2513+ size = 'small'
2514+ theme = 'solid'
2515+ type = 'primary'
2516+ onClick = { ( ) => applyClipboardConfig ( clipboardConfig ) }
2517+ >
2518+ { t ( '自动填入' ) }
2519+ </ Button >
2520+ < Button
2521+ size = 'small'
2522+ type = 'tertiary'
2523+ onClick = { ( ) => setClipboardConfig ( null ) }
2524+ >
2525+ { t ( '忽略' ) }
2526+ </ Button >
2527+ </ div >
2528+ </ div >
2529+ }
2530+ />
2531+ ) }
24492532 { /* Core Configuration Card - Always Visible */ }
24502533 < Card className = '!rounded-2xl shadow-sm border-0' >
24512534 { /* Header */ }
0 commit comments