215
215
</a-tooltip >
216
216
</a-dropdown >
217
217
</div >
218
-
218
+ < a-progress :percent = " progressPercent " show-info size = " small " />
219
219
220
220
<div v-if =" !isMobile" class =" table-container" >
221
221
<a-table
231
231
{{ record.status }}
232
232
</template >
233
233
<template v-else-if =" column .dataIndex === ' model' " >
234
- <span >
235
- 📦 {{ record.model }}
236
- <CopyOutlined
237
- style =" margin-left : 8px ; cursor : pointer ;"
238
- @click =" copyText(record.model)"
239
- />
234
+ <span @click =" copyText(item.model)" >
235
+ {{ record.model }}
240
236
</span >
241
237
</template >
242
238
<template v-else-if =" column .dataIndex === ' responseTime' " >
303
299
</div >
304
300
<div class =" list-item-field" >
305
301
<span class =" field-label" >{{ t('MODEL_NAME_LABEL') }}</span >
306
- <span class =" field-value" >
307
- 📦 {{ item.model }}
308
- <CopyOutlined
309
- type =" copy"
310
- style =" margin-left : 8px ; cursor : pointer ;"
311
- @click =" copyText(item.model)"
312
- />
302
+ <span class =" field-value" @click =" copyText(item.model)" >
303
+ {{ item.model }}
313
304
</span >
314
305
</div >
315
306
<div class =" list-item-field" >
372
363
</a-form >
373
364
</a-modal >
374
365
<a-modal
375
- v-model:open =" showSettingsModal1 "
366
+ v-model:open =" showAppSettingsModal "
376
367
:title =" t('SETTINGS_PANEL')"
377
368
:footer =" null"
378
369
:width =" 600"
381
372
:centered =" true"
382
373
>
383
374
<a-tabs >
384
- <a-tab-pane key =" 1" :tab =" t('LOCAL_CACHE')" style =" overflow-x : hidden ;" >
375
+ <a-tab-pane key =" 1" :tab =" t('LOCAL_CACHE')" style =" overflow-x : hidden ;" tabPosition = " left " >
385
376
<a-form @submit.prevent >
386
377
<a-row :gutter =" 16" >
387
378
<a-col :span =" 16" >
@@ -765,6 +756,7 @@ const chartContainer = ref(null);
765
756
let chartInstance = null ;
766
757
const showSVGModal = ref (false );
767
758
const svgDataUrl = ref (' ' );
759
+
768
760
const appDescription = computed (() => {
769
761
const currentLocale = locale .value || ' zh' ;
770
762
return appInfo .description [currentLocale] || appInfo .description [' zh' ];
@@ -787,7 +779,7 @@ const paginatedData = computed(() => {
787
779
return tableData .value .slice (start, end);
788
780
});
789
781
// 设置面板相关状态
790
- const showSettingsModal1 = ref (false );
782
+ const showAppSettingsModal = ref (false );
791
783
const showLoginModal = ref (false );
792
784
793
785
// 主题切换方法
@@ -1091,6 +1083,11 @@ const checkQuota = async () => {
1091
1083
checkQuota_spinning .value = false ;
1092
1084
}
1093
1085
};
1086
+ let modelNames= []
1087
+ const tableData = ref ([]);
1088
+ const totalModels = ref (0 );
1089
+ const completedModels = ref (0 );
1090
+ const progressPercent = ref (0 );
1094
1091
1095
1092
// 添加 testModels 函数
1096
1093
async function testModels () {
@@ -1100,9 +1097,12 @@ async function testModels() {
1100
1097
results .inconsistent = [];
1101
1098
results .awaitOfficialVerification = [];
1102
1099
1103
- const apiUrlValue = apiUrl .value ;
1100
+ // 清空表格数据
1101
+ tableData .value = [];
1102
+
1103
+ const apiUrlValue = apiUrl .value .replace (/ \/ + $ / , ' ' );
1104
1104
const apiKeyValue = apiKey .value ;
1105
- const modelNames = modelName .value . split ( ' , ' ). map (( m ) => m . trim ()). filter (( m ) => m) ;
1105
+ const modelNames = selectedModels .value ;
1106
1106
const timeout = parseInt (modelTimeout .value );
1107
1107
const concurrency = parseInt (modelConcurrency .value );
1108
1108
@@ -1111,32 +1111,64 @@ async function testModels() {
1111
1111
return ;
1112
1112
}
1113
1113
1114
+ // 显示结果容器
1115
+ shouldShift .value = true ;
1116
+ showResultContainer .value = true ;
1117
+
1118
+ // 初始化进度
1119
+ totalModels .value = selectedModels .value .length ;
1120
+ completedModels .value = 0 ;
1121
+ progressPercent .value = 0 ;
1122
+
1114
1123
testModels_spinning .value = true ;
1115
1124
1116
1125
try {
1117
- const testResults = await testModelList (
1126
+ await testModelList (
1118
1127
apiUrlValue,
1119
1128
apiKeyValue,
1120
1129
modelNames,
1121
1130
timeout,
1122
- concurrency
1131
+ concurrency,
1132
+ (progress ) => {
1133
+ // 更新表格数据
1134
+ updateTableData (progress);
1135
+ // 更新进度
1136
+ completedModels .value += 1 ;
1137
+ progressPercent .value = Math .round ((completedModels .value / totalModels .value ) * 100 );
1138
+ }
1123
1139
);
1124
1140
1125
- // 处理测试结果
1126
- results .valid = testResults .valid ;
1127
- results .invalid = testResults .invalid ;
1128
- results .inconsistent = testResults .inconsistent ;
1129
- results .awaitOfficialVerification = testResults .awaitOfficialVerification ;
1130
-
1131
1141
testModels_spinning .value = false ;
1132
1142
1143
+ // 所有模型测试完成后,显示摘要
1133
1144
showSummary (results);
1145
+
1134
1146
} catch (error) {
1135
1147
testModels_spinning .value = false ;
1136
1148
message .error (' 测试模型时发生错误: ' + error .message );
1137
1149
}
1138
1150
}
1139
1151
1152
+ function updateTableData (progress ) {
1153
+ const { type , data } = progress;
1154
+
1155
+ // 根据类型,将结果添加到对应的数组
1156
+ if (type === ' valid' ) {
1157
+ results .valid .push (data);
1158
+ } else if (type === ' invalid' ) {
1159
+ results .invalid .push (data);
1160
+ } else if (type === ' inconsistent' ) {
1161
+ results .inconsistent .push (data);
1162
+ }
1163
+
1164
+ // 重新计算表格数据
1165
+ tableData .value = computeTableData ();
1166
+
1167
+ // 更新进度
1168
+ progressPercent .value = Math .round ((completedModels .value / totalModels .value ) * 100 );
1169
+ }
1170
+
1171
+
1140
1172
function showSummary (results ) {
1141
1173
// 使用 reactive 的 'results' 对象
1142
1174
const resultsData = results;
@@ -1357,9 +1389,117 @@ const columns = [
1357
1389
];
1358
1390
1359
1391
// 定义 tableData
1360
- const tableData = computed (() => {
1392
+ // const tableData = computed(() => {
1393
+ // const data = [];
1394
+ //
1395
+ // results.valid.forEach((item, index) => {
1396
+ // const buttons = [];
1397
+ // buttons.push({
1398
+ // label: t('FUNCTION_VERIFICATION'),
1399
+ // type: 'default',
1400
+ // onClick: () => verifyFunctionCalling(item.model),
1401
+ // });
1402
+ // if (isGpt(item.model) || isClaude(item.model)) {
1403
+ // buttons.push({
1404
+ // label: t('TEMPERATURE_VERIFICATION'),
1405
+ // type: 'primary',
1406
+ // onClick: () => verifyTemperature(item.model),
1407
+ // });
1408
+ // if (isGpt(item.model)) {
1409
+ // const officialVerificationDone =
1410
+ // results.awaitOfficialVerification &&
1411
+ // results.awaitOfficialVerification.some((r) => r.model === item.model);
1412
+ // const buttonType = officialVerificationDone ? 'success' : 'warning';
1413
+ // buttons.push({
1414
+ // label: t('OFFICIAL_VERIFICATION'),
1415
+ // type: buttonType,
1416
+ // onClick: () => verifyOfficial(item.model),
1417
+ // });
1418
+ // }
1419
+ // }
1420
+ // data.push({
1421
+ // key: `valid-${index}`,
1422
+ // status: t('MODEL_STATE_AVAILABLE'),
1423
+ // model: item.model,
1424
+ // responseTime: item.responseTime.toFixed(2),
1425
+ // buttons: buttons,
1426
+ // remark: '',
1427
+ // });
1428
+ // });
1429
+ //
1430
+ // results.inconsistent.forEach((item, index) => {
1431
+ // const buttons = [];
1432
+ // buttons.push({
1433
+ // label: t('FUNCTION_VERIFICATION'),
1434
+ // type: 'default',
1435
+ // onClick: () => verifyFunctionCalling(item.model),
1436
+ // });
1437
+ // if (isGpt(item.model) || isClaude(item.model)) {
1438
+ // buttons.push({
1439
+ // label: t('TEMPERATURE_VERIFICATION'),
1440
+ // type: 'primary',
1441
+ // onClick: () => verifyTemperature(item.model),
1442
+ // });
1443
+ // if (isGpt(item.model)) {
1444
+ // const officialVerificationDone =
1445
+ // results.awaitOfficialVerification &&
1446
+ // results.awaitOfficialVerification.some((r) => r.model === item.model);
1447
+ // const buttonType = officialVerificationDone ? 'success' : 'warning';
1448
+ // buttons.push({
1449
+ // label: t('OFFICIAL_VERIFICATION'),
1450
+ // type: buttonType,
1451
+ // onClick: () => verifyOfficial(item.model),
1452
+ // });
1453
+ // }
1454
+ // }
1455
+ //
1456
+ // // 根据返回的模型名称,判断是模型映射还是未匹配
1457
+ // let status = '';
1458
+ // let remark = '';
1459
+ // let fullRemark = '';
1460
+ //
1461
+ // if (item.returnedModel && item.returnedModel.startsWith(`${item.model}-`)) {
1462
+ // status = t('MODEL_STATE_INCONSISTENT');
1463
+ // remark = '模型映射';
1464
+ // fullRemark = `模型映射到:${item.returnedModel}`;
1465
+ // } else {
1466
+ // status = '🤔未匹配';
1467
+ // remark = '未匹配';
1468
+ // fullRemark = `返回模型:${item.returnedModel}`;
1469
+ // }
1470
+ //
1471
+ // data.push({
1472
+ // key: `inconsistent-${index}`,
1473
+ // status: status,
1474
+ // model: item.model,
1475
+ // responseTime: item.responseTime.toFixed(2),
1476
+ // buttons: buttons,
1477
+ // remark: remark,
1478
+ // fullRemark: fullRemark,
1479
+ // });
1480
+ // });
1481
+ //
1482
+ // results.invalid.forEach((item, index) => {
1483
+ // let displayedRemark = '';
1484
+ // let fullRemark = item.response_text || item.error || '';
1485
+ // displayedRemark = errorHandler(fullRemark);
1486
+ // data.push({
1487
+ // key: `invalid-${index}`,
1488
+ // status: t('MODEL_STATE_UNAVAILABLE'),
1489
+ // model: item.model,
1490
+ // responseTime: '-',
1491
+ // buttons: [],
1492
+ // remark: displayedRemark,
1493
+ // fullRemark: fullRemark,
1494
+ // });
1495
+ // });
1496
+ //
1497
+ // return data;
1498
+ // });
1499
+ function computeTableData () {
1361
1500
const data = [];
1362
1501
1502
+ // 处理 valid 模型
1363
1503
results .valid .forEach ((item , index ) => {
1364
1504
const buttons = [];
1365
1505
buttons .push ({
@@ -1385,16 +1525,32 @@ const tableData = computed(() => {
1385
1525
});
1386
1526
}
1387
1527
}
1528
+
1529
+ // 针对 o1- 模型的特殊处理
1530
+ let remark = ' ' ;
1531
+ let fullRemark = ' ' ;
1532
+ if (item .model .startsWith (' o1-' )) {
1533
+ if (item .has_o1_reason ) {
1534
+ remark = ' ✨API 可靠' ;
1535
+ fullRemark = ' 返回响应中包含非空 reasoning_tokens,API 可靠' ;
1536
+ } else {
1537
+ remark = ' ⚠️API 非官' ;
1538
+ fullRemark = ' 返回响应中不包含 reasoning_tokens 或为空,API 非官' ;
1539
+ }
1540
+ }
1541
+
1388
1542
data .push ({
1389
1543
key: ` valid-${ index} ` ,
1390
1544
status: t (' MODEL_STATE_AVAILABLE' ),
1391
1545
model: item .model ,
1392
1546
responseTime: item .responseTime .toFixed (2 ),
1393
1547
buttons: buttons,
1394
- remark: ' ' ,
1548
+ remark: remark,
1549
+ fullRemark: fullRemark,
1395
1550
});
1396
1551
});
1397
1552
1553
+ // 处理 inconsistent 模型
1398
1554
results .inconsistent .forEach ((item , index ) => {
1399
1555
const buttons = [];
1400
1556
buttons .push ({
@@ -1427,15 +1583,26 @@ const tableData = computed(() => {
1427
1583
let fullRemark = ' ' ;
1428
1584
1429
1585
if (item .returnedModel && item .returnedModel .startsWith (` ${ item .model } -` )) {
1430
- status = t (' MODEL_STATE_INCONSISTENT' );
1586
+ status = ` ${ t (' MODEL_STATE_INCONSISTENT' )} 🧐 ` ;
1431
1587
remark = ' 模型映射' ;
1432
1588
fullRemark = ` 模型映射到:${ item .returnedModel } ` ;
1433
1589
} else {
1434
- status = ' 🤔未匹配' ;
1590
+ status = ' 🤔 未匹配' ;
1435
1591
remark = ' 未匹配' ;
1436
1592
fullRemark = ` 返回模型:${ item .returnedModel } ` ;
1437
1593
}
1438
1594
1595
+ // 针对 o1- 模型的特殊处理
1596
+ if (item .model .startsWith (' o1-' )) {
1597
+ if (item .has_o1_reason ) {
1598
+ remark += ' / ✨API 可靠' ;
1599
+ fullRemark += ' ;返回响应中包含非空 reasoning_tokens,API 可靠' ;
1600
+ } else {
1601
+ remark += ' / ⚠️API 非官' ;
1602
+ fullRemark += ' ;返回响应中不包含 reasoning_tokens 或为空,API 非官' ;
1603
+ }
1604
+ }
1605
+
1439
1606
data .push ({
1440
1607
key: ` inconsistent-${ index} ` ,
1441
1608
status: status,
@@ -1447,10 +1614,12 @@ const tableData = computed(() => {
1447
1614
});
1448
1615
});
1449
1616
1617
+ // 处理 invalid 模型
1450
1618
results .invalid .forEach ((item , index ) => {
1451
1619
let displayedRemark = ' ' ;
1452
1620
let fullRemark = item .response_text || item .error || ' ' ;
1453
1621
displayedRemark = errorHandler (fullRemark);
1622
+
1454
1623
data .push ({
1455
1624
key: ` invalid-${ index} ` ,
1456
1625
status: t (' MODEL_STATE_UNAVAILABLE' ),
@@ -1463,8 +1632,7 @@ const tableData = computed(() => {
1463
1632
});
1464
1633
1465
1634
return data;
1466
- });
1467
-
1635
+ }
1468
1636
1469
1637
// 复制文本函数
1470
1638
function copyText (text ) {
@@ -1685,13 +1853,13 @@ function openSettingsModal() {
1685
1853
fetchCloudData ();
1686
1854
}
1687
1855
1688
- showSettingsModal1 .value = true ;
1856
+ showAppSettingsModal .value = true ;
1689
1857
}
1690
1858
1691
1859
1692
1860
// 关闭设置面板
1693
1861
function closeSettingsModal () {
1694
- showSettingsModal1 .value = false ;
1862
+ showAppSettingsModal .value = false ;
1695
1863
}
1696
1864
1697
1865
// 保存到本地缓存
0 commit comments