@@ -45,6 +45,7 @@ import {
4545 IconBookmark ,
4646 IconUser ,
4747 IconCode ,
48+ IconSetting ,
4849} from '@douyinfe/semi-icons' ;
4950import { getChannelModels } from '../../../../helpers' ;
5051import { useTranslation } from 'react-i18next' ;
@@ -69,6 +70,8 @@ const EditTagModal = (props) => {
6970 model_mapping : null ,
7071 groups : [ ] ,
7172 models : [ ] ,
73+ param_override : null ,
74+ header_override : null ,
7275 } ;
7376 const [ inputs , setInputs ] = useState ( originInputs ) ;
7477 const formApiRef = useRef ( null ) ;
@@ -190,12 +193,48 @@ const EditTagModal = (props) => {
190193 if ( formVals . models && formVals . models . length > 0 ) {
191194 data . models = formVals . models . join ( ',' ) ;
192195 }
196+ if (
197+ formVals . param_override !== undefined &&
198+ formVals . param_override !== null
199+ ) {
200+ if ( typeof formVals . param_override !== 'string' ) {
201+ showInfo ( '参数覆盖必须是合法的 JSON 格式!' ) ;
202+ setLoading ( false ) ;
203+ return ;
204+ }
205+ const trimmedParamOverride = formVals . param_override . trim ( ) ;
206+ if ( trimmedParamOverride !== '' && ! verifyJSON ( trimmedParamOverride ) ) {
207+ showInfo ( '参数覆盖必须是合法的 JSON 格式!' ) ;
208+ setLoading ( false ) ;
209+ return ;
210+ }
211+ data . param_override = trimmedParamOverride ;
212+ }
213+ if (
214+ formVals . header_override !== undefined &&
215+ formVals . header_override !== null
216+ ) {
217+ if ( typeof formVals . header_override !== 'string' ) {
218+ showInfo ( '请求头覆盖必须是合法的 JSON 格式!' ) ;
219+ setLoading ( false ) ;
220+ return ;
221+ }
222+ const trimmedHeaderOverride = formVals . header_override . trim ( ) ;
223+ if ( trimmedHeaderOverride !== '' && ! verifyJSON ( trimmedHeaderOverride ) ) {
224+ showInfo ( '请求头覆盖必须是合法的 JSON 格式!' ) ;
225+ setLoading ( false ) ;
226+ return ;
227+ }
228+ data . header_override = trimmedHeaderOverride ;
229+ }
193230 data . new_tag = formVals . new_tag ;
194231 if (
195232 data . model_mapping === undefined &&
196233 data . groups === undefined &&
197234 data . models === undefined &&
198- data . new_tag === undefined
235+ data . new_tag === undefined &&
236+ data . param_override === undefined &&
237+ data . header_override === undefined
199238 ) {
200239 showWarning ( '没有任何修改!' ) ;
201240 setLoading ( false ) ;
@@ -491,6 +530,157 @@ const EditTagModal = (props) => {
491530 </ div >
492531 </ Card >
493532
533+ < Card className = '!rounded-2xl shadow-sm border-0 mb-6' >
534+ { /* Header: Advanced Settings */ }
535+ < div className = 'flex items-center mb-2' >
536+ < Avatar size = 'small' color = 'orange' className = 'mr-2 shadow-md' >
537+ < IconSetting size = { 16 } />
538+ </ Avatar >
539+ < div >
540+ < Text className = 'text-lg font-medium' > { t ( '高级设置' ) } </ Text >
541+ < div className = 'text-xs text-gray-600' >
542+ { t ( '渠道的高级配置选项' ) }
543+ </ div >
544+ </ div >
545+ </ div >
546+
547+ < div className = 'space-y-4' >
548+ < Form . TextArea
549+ field = 'param_override'
550+ label = { t ( '参数覆盖' ) }
551+ placeholder = {
552+ t (
553+ '此项可选,用于覆盖请求参数。不支持覆盖 stream 参数' ,
554+ ) +
555+ '\n' +
556+ t ( '旧格式(直接覆盖):' ) +
557+ '\n{\n "temperature": 0,\n "max_tokens": 1000\n}' +
558+ '\n\n' +
559+ t ( '新格式(支持条件判断与json自定义):' ) +
560+ '\n{\n "operations": [\n {\n "path": "temperature",\n "mode": "set",\n "value": 0.7,\n "conditions": [\n {\n "path": "model",\n "mode": "prefix",\n "value": "gpt"\n }\n ]\n }\n ]\n}'
561+ }
562+ autosize
563+ showClear
564+ onChange = { ( value ) =>
565+ handleInputChange ( 'param_override' , value )
566+ }
567+ extraText = {
568+ < div className = 'flex gap-2 flex-wrap' >
569+ < Text
570+ className = '!text-semi-color-primary cursor-pointer'
571+ onClick = { ( ) =>
572+ handleInputChange (
573+ 'param_override' ,
574+ JSON . stringify ( { temperature : 0 } , null , 2 ) ,
575+ )
576+ }
577+ >
578+ { t ( '旧格式模板' ) }
579+ </ Text >
580+ < Text
581+ className = '!text-semi-color-primary cursor-pointer'
582+ onClick = { ( ) =>
583+ handleInputChange (
584+ 'param_override' ,
585+ JSON . stringify (
586+ {
587+ operations : [
588+ {
589+ path : 'temperature' ,
590+ mode : 'set' ,
591+ value : 0.7 ,
592+ conditions : [
593+ {
594+ path : 'model' ,
595+ mode : 'prefix' ,
596+ value : 'gpt' ,
597+ } ,
598+ ] ,
599+ logic : 'AND' ,
600+ } ,
601+ ] ,
602+ } ,
603+ null ,
604+ 2 ,
605+ ) ,
606+ )
607+ }
608+ >
609+ { t ( '新格式模板' ) }
610+ </ Text >
611+ < Text
612+ className = '!text-semi-color-primary cursor-pointer'
613+ onClick = { ( ) =>
614+ handleInputChange ( 'param_override' , null )
615+ }
616+ >
617+ { t ( '不更改' ) }
618+ </ Text >
619+ </ div >
620+ }
621+ />
622+
623+ < Form . TextArea
624+ field = 'header_override'
625+ label = { t ( '请求头覆盖' ) }
626+ placeholder = {
627+ t ( '此项可选,用于覆盖请求头参数' ) +
628+ '\n' +
629+ t ( '格式示例:' ) +
630+ '\n{\n "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36 Edg/139.0.0.0",\n "Authorization": "Bearer {api_key}"\n}'
631+ }
632+ autosize
633+ showClear
634+ onChange = { ( value ) =>
635+ handleInputChange ( 'header_override' , value )
636+ }
637+ extraText = {
638+ < div className = 'flex flex-col gap-1' >
639+ < div className = 'flex gap-2 flex-wrap items-center' >
640+ < Text
641+ className = '!text-semi-color-primary cursor-pointer'
642+ onClick = { ( ) =>
643+ handleInputChange (
644+ 'header_override' ,
645+ JSON . stringify (
646+ {
647+ 'User-Agent' :
648+ 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36 Edg/139.0.0.0' ,
649+ Authorization : 'Bearer {api_key}' ,
650+ } ,
651+ null ,
652+ 2 ,
653+ ) ,
654+ )
655+ }
656+ >
657+ { t ( '填入模板' ) }
658+ </ Text >
659+ < Text
660+ className = '!text-semi-color-primary cursor-pointer'
661+ onClick = { ( ) =>
662+ handleInputChange ( 'header_override' , null )
663+ }
664+ >
665+ { t ( '不更改' ) }
666+ </ Text >
667+ </ div >
668+ < div >
669+ < Text type = 'tertiary' size = 'small' >
670+ { t ( '支持变量:' ) }
671+ </ Text >
672+ < div className = 'text-xs text-tertiary ml-2' >
673+ < div >
674+ { t ( '渠道密钥' ) } : { '{api_key}' }
675+ </ div >
676+ </ div >
677+ </ div >
678+ </ div >
679+ }
680+ />
681+ </ div >
682+ </ Card >
683+
494684 < Card className = '!rounded-2xl shadow-sm border-0' >
495685 { /* Header: Group Settings */ }
496686 < div className = 'flex items-center mb-2' >
0 commit comments