@@ -214,6 +214,133 @@ const EditChannelModal = (props) => {
214
214
handleInputChange ( 'settings' , settingsJson ) ;
215
215
}
216
216
217
+ // 用于追踪模型的原始名称映射关系 { displayName: originalName }
218
+ const [ modelOriginalMapping , setModelOriginalMapping ] = useState ( { } ) ;
219
+
220
+ // 解析模型映射配置的工具函数
221
+ const parseModelMapping = ( mappingValue ) => {
222
+ if ( ! mappingValue || typeof mappingValue !== 'string' || mappingValue . trim ( ) === '' ) {
223
+ return null ;
224
+ }
225
+
226
+ try {
227
+ const mapping = JSON . parse ( mappingValue ) ;
228
+ if ( typeof mapping !== 'object' || mapping === null ) {
229
+ return null ;
230
+ }
231
+ return mapping ;
232
+ } catch ( error ) {
233
+ console . warn ( '模型重定向 JSON 解析失败:' , error ) ;
234
+ return null ;
235
+ }
236
+ } ;
237
+
238
+ // 获取当前模型列表的工具函数
239
+ const getCurrentModels = ( ) => {
240
+ return formApiRef . current
241
+ ? formApiRef . current . getValue ( 'models' ) || [ ]
242
+ : inputs . models || [ ] ;
243
+ } ;
244
+
245
+ // 更新模型列表的统一方法
246
+ const updateModelsList = ( newModels , newMapping ) => {
247
+ const uniqueModels = Array . from ( new Set ( newModels . filter ( model => model && model . trim ( ) ) ) ) ;
248
+
249
+ setInputs ( ( inputs ) => ( { ...inputs , models : uniqueModels } ) ) ;
250
+ if ( formApiRef . current ) {
251
+ formApiRef . current . setValue ( 'models' , uniqueModels ) ;
252
+ }
253
+ setModelOriginalMapping ( newMapping ) ;
254
+ } ;
255
+
256
+ // 恢复模型到原始名称
257
+ const restoreModelsToOriginalNames = ( ) => {
258
+ const currentModels = getCurrentModels ( ) ;
259
+ const restoredModels = currentModels . map ( model => modelOriginalMapping [ model ] || model ) ;
260
+
261
+ // 使用数组比较而不是JSON.stringify提高性能
262
+ const hasChanges = currentModels . length !== restoredModels . length ||
263
+ currentModels . some ( ( model , index ) => model !== restoredModels [ index ] ) ;
264
+
265
+ if ( hasChanges ) {
266
+ updateModelsList ( restoredModels , { } ) ;
267
+ }
268
+ } ;
269
+
270
+ // 应用模型映射的核心逻辑
271
+ const applyModelMapping = ( mapping , currentModels , currentMapping ) => {
272
+ let updatedModels = [ ...currentModels ] ;
273
+ let newMapping = { ...currentMapping } ;
274
+ let hasChanges = false ;
275
+
276
+ // 遍历重定向映射
277
+ Object . entries ( mapping ) . forEach ( ( [ key , mappedValue ] ) => {
278
+ if ( typeof key === 'string' && typeof mappedValue === 'string' ) {
279
+ const keyTrimmed = key . trim ( ) ;
280
+ const valueTrimmed = mappedValue . trim ( ) ;
281
+
282
+ if ( keyTrimmed && valueTrimmed ) {
283
+ // 查找模型配置中是否存在重定向的"值"(原始模型名)
284
+ const valueIndex = updatedModels . findIndex ( model => {
285
+ return model === valueTrimmed || newMapping [ model ] === valueTrimmed ;
286
+ } ) ;
287
+
288
+ if ( valueIndex !== - 1 ) {
289
+ const currentDisplayName = updatedModels [ valueIndex ] ;
290
+ if ( currentDisplayName !== keyTrimmed ) {
291
+ // 记录原始映射关系
292
+ if ( ! newMapping [ keyTrimmed ] ) {
293
+ newMapping [ keyTrimmed ] = newMapping [ currentDisplayName ] || currentDisplayName ;
294
+ }
295
+ // 清理旧的映射关系
296
+ if ( newMapping [ currentDisplayName ] ) {
297
+ delete newMapping [ currentDisplayName ] ;
298
+ }
299
+ // 更新显示名称为重定向的键
300
+ updatedModels [ valueIndex ] = keyTrimmed ;
301
+ hasChanges = true ;
302
+ }
303
+ }
304
+ }
305
+ }
306
+ } ) ;
307
+
308
+ // 处理不在映射中的模型,恢复为原始名称
309
+ const mappingKeys = new Set ( Object . keys ( mapping ) . map ( key => key . trim ( ) ) ) ;
310
+ updatedModels = updatedModels . map ( model => {
311
+ if ( ! mappingKeys . has ( model ) && newMapping [ model ] ) {
312
+ const originalName = newMapping [ model ] ;
313
+ delete newMapping [ model ] ;
314
+ hasChanges = true ;
315
+ return originalName ;
316
+ }
317
+ return model ;
318
+ } ) ;
319
+
320
+ return { updatedModels, newMapping, hasChanges } ;
321
+ } ;
322
+
323
+ // 实时同步模型重定向到模型配置的函数
324
+ const syncModelMappingToModels = ( mappingValue ) => {
325
+ const mapping = parseModelMapping ( mappingValue ) ;
326
+
327
+ if ( ! mapping ) {
328
+ restoreModelsToOriginalNames ( ) ;
329
+ return ;
330
+ }
331
+
332
+ const currentModels = getCurrentModels ( ) ;
333
+ const { updatedModels, newMapping, hasChanges } = applyModelMapping (
334
+ mapping ,
335
+ currentModels ,
336
+ modelOriginalMapping
337
+ ) ;
338
+
339
+ if ( hasChanges ) {
340
+ updateModelsList ( updatedModels , newMapping ) ;
341
+ }
342
+ } ;
343
+
217
344
const handleInputChange = ( name , value ) => {
218
345
if ( formApiRef . current ) {
219
346
formApiRef . current . setValue ( name , value ) ;
@@ -233,6 +360,14 @@ const EditChannelModal = (props) => {
233
360
} ) ;
234
361
return ;
235
362
}
363
+
364
+ // 处理模型重定向变更时自动同步模型配置(实时同步)
365
+ if ( name === 'model_mapping' ) {
366
+ setInputs ( ( inputs ) => ( { ...inputs , [ name ] : value } ) ) ;
367
+ syncModelMappingToModels ( value ) ;
368
+ return ;
369
+ }
370
+
236
371
setInputs ( ( inputs ) => ( { ...inputs , [ name ] : value } ) ) ;
237
372
if ( name === 'type' ) {
238
373
let localModels = [ ] ;
@@ -375,6 +510,22 @@ const EditChannelModal = (props) => {
375
510
setAutoBan ( true ) ;
376
511
}
377
512
setBasicModels ( getChannelModels ( data . type ) ) ;
513
+
514
+ // 初始化模型原始映射关系
515
+ const mapping = parseModelMapping ( data . model_mapping ) ;
516
+ if ( mapping ) {
517
+ const initialMapping = { } ;
518
+ // 根据当前的模型映射和模型列表,建立原始映射关系
519
+ Object . entries ( mapping ) . forEach ( ( [ key , value ] ) => {
520
+ if ( data . models . includes ( key ) ) {
521
+ initialMapping [ key ] = value ;
522
+ }
523
+ } ) ;
524
+ setModelOriginalMapping ( initialMapping ) ;
525
+ } else {
526
+ setModelOriginalMapping ( { } ) ;
527
+ }
528
+
378
529
// 同步更新channelSettings状态显示
379
530
setChannelSettings ( {
380
531
force_format : data . force_format ,
@@ -592,11 +743,20 @@ const EditChannelModal = (props) => {
592
743
if ( formApiRef . current ) {
593
744
formApiRef . current . setValue ( 'key_mode' , undefined ) ;
594
745
}
746
+ // 重置模型原始映射关系
747
+ setModelOriginalMapping ( { } ) ;
595
748
// 重置本地输入,避免下次打开残留上一次的 JSON 字段值
596
749
setInputs ( getInitValues ( ) ) ;
597
750
}
598
751
} , [ props . visible , channelId ] ) ;
599
752
753
+ // 组件卸载时清理资源
754
+ useEffect ( ( ) => {
755
+ return ( ) => {
756
+ setModelOriginalMapping ( { } ) ;
757
+ } ;
758
+ } , [ ] ) ;
759
+
600
760
const handleVertexUploadChange = ( { fileList } ) => {
601
761
vertexErroredNames . current . clear ( ) ;
602
762
( async ( ) => {
@@ -1607,7 +1767,14 @@ const EditChannelModal = (props) => {
1607
1767
templateLabel = { t ( '填入模板' ) }
1608
1768
editorType = "keyValue"
1609
1769
formApi = { formApiRef . current }
1610
- extraText = { t ( '键为请求中的模型名称,值为要替换的模型名称' ) }
1770
+ extraText = {
1771
+ < div >
1772
+ < div className = "text-center" > { t ( '键为请求中的模型名称,值为要替换的模型名称' ) } </ div >
1773
+ < div className = "text-blue-600 text-xs mt-1" >
1774
+ { t ( '💡 提示:设置重定向后,系统自动将“模型配置”中对应的"值"替换为"键"' ) }
1775
+ </ div >
1776
+ </ div >
1777
+ }
1611
1778
/>
1612
1779
</ Card >
1613
1780
0 commit comments