|
|
@@ -57,6 +57,14 @@
|
|
57
|
57
|
</div>
|
|
58
|
58
|
<div class="session-item__preview">{{ s.lastMessagePreview || dash }}</div>
|
|
59
|
59
|
</div>
|
|
|
60
|
+ <el-button
|
|
|
61
|
+ v-hasPermi="['diseaseTreatment:aiOnlineConsult:remove']"
|
|
|
62
|
+ type="text"
|
|
|
63
|
+ icon="el-icon-delete"
|
|
|
64
|
+ class="session-item__delete"
|
|
|
65
|
+ :title="dtT('deleteSession')"
|
|
|
66
|
+ @click.stop="handleDeleteSession(s)"
|
|
|
67
|
+ />
|
|
60
|
68
|
</div>
|
|
61
|
69
|
<el-empty
|
|
62
|
70
|
v-if="!listLoading && !sessions.length"
|
|
|
@@ -294,6 +302,7 @@ import {
|
|
294
|
302
|
createAiConsultSession,
|
|
295
|
303
|
listAiConsultMessages,
|
|
296
|
304
|
sendAiConsultMessage,
|
|
|
305
|
+ hideAiConsultSession,
|
|
297
|
306
|
sendChatMessage,
|
|
298
|
307
|
extractLlmSessionIdFromJson,
|
|
299
|
308
|
getModelList
|
|
|
@@ -439,7 +448,7 @@ export default {
|
|
439
|
448
|
methods: {
|
|
440
|
449
|
getModelList() {
|
|
441
|
450
|
getModelList().then((res) => {
|
|
442
|
|
- console.log(res)
|
|
|
451
|
+
|
|
443
|
452
|
})
|
|
444
|
453
|
},
|
|
445
|
454
|
renderChatMarkdown,
|
|
|
@@ -657,6 +666,33 @@ export default {
|
|
657
|
666
|
this.loadMessages(false)
|
|
658
|
667
|
this.startPolling()
|
|
659
|
668
|
},
|
|
|
669
|
+ handleDeleteSession(session) {
|
|
|
670
|
+ const sid = this.resolveSessionId(session)
|
|
|
671
|
+ if (!sid) {
|
|
|
672
|
+ return
|
|
|
673
|
+ }
|
|
|
674
|
+ const title = this.sessionTitle(session)
|
|
|
675
|
+ this.$modal
|
|
|
676
|
+ .confirm(this.dtT("confirmDeleteSession", { title }))
|
|
|
677
|
+ .then(() => hideAiConsultSession(sid))
|
|
|
678
|
+ .then(() => {
|
|
|
679
|
+ this.$modal.msgSuccess(this.dtCommon("msgDelOk"))
|
|
|
680
|
+ this.clearLlmSessionId(sid)
|
|
|
681
|
+ this.sessions = this.sessions.filter((s) => this.resolveSessionId(s) !== sid)
|
|
|
682
|
+ if (this.pendingPersist && this.pendingPersist.consultSessionId === sid) {
|
|
|
683
|
+ this.pendingPersist = null
|
|
|
684
|
+ }
|
|
|
685
|
+ if (this.activeSessionId === sid) {
|
|
|
686
|
+ this.abortStreamRequest()
|
|
|
687
|
+ this.stopPolling()
|
|
|
688
|
+ this.activeSessionId = ""
|
|
|
689
|
+ this.messages = []
|
|
|
690
|
+ this.draft = ""
|
|
|
691
|
+ this.sending = false
|
|
|
692
|
+ }
|
|
|
693
|
+ })
|
|
|
694
|
+ .catch(() => {})
|
|
|
695
|
+ },
|
|
660
|
696
|
loadMessages(older) {
|
|
661
|
697
|
if (!this.activeSessionId) {
|
|
662
|
698
|
return
|
|
|
@@ -981,12 +1017,13 @@ export default {
|
|
981
|
1017
|
}
|
|
982
|
1018
|
}
|
|
983
|
1019
|
},
|
|
984
|
|
- queuePendingPersist(consultSessionId, persistBody, aiReplyContent, llmSessionId) {
|
|
|
1020
|
+ queuePendingPersist(consultSessionId, persistBody, aiReplyContent, llmSessionId, costTime) {
|
|
985
|
1021
|
this.pendingPersist = {
|
|
986
|
1022
|
consultSessionId,
|
|
987
|
1023
|
persistBody: { ...persistBody },
|
|
988
|
1024
|
aiReplyContent,
|
|
989
|
|
- llmSessionId: llmSessionId != null ? llmSessionId : null
|
|
|
1025
|
+ llmSessionId: llmSessionId != null ? llmSessionId : null,
|
|
|
1026
|
+ costTime: costTime != null ? costTime : null
|
|
990
|
1027
|
}
|
|
991
|
1028
|
},
|
|
992
|
1029
|
async flushPendingPersist() {
|
|
|
@@ -998,14 +1035,15 @@ export default {
|
|
998
|
1035
|
await sendAiConsultMessage(pending.consultSessionId, {
|
|
999
|
1036
|
...pending.persistBody,
|
|
1000
|
1037
|
aiReplyContent: pending.aiReplyContent,
|
|
1001
|
|
- realSessionId: pending.llmSessionId != null ? pending.llmSessionId : null
|
|
|
1038
|
+ realSessionId: pending.llmSessionId != null ? pending.llmSessionId : null,
|
|
|
1039
|
+ costTime: pending.costTime != null ? pending.costTime : undefined
|
|
1002
|
1040
|
})
|
|
1003
|
1041
|
this.pendingPersist = null
|
|
1004
|
1042
|
} catch (err) {
|
|
1005
|
1043
|
// 离开页面时仍失败则保留队列,下次进入同页可再试(仅内存,刷新会丢)
|
|
1006
|
1044
|
}
|
|
1007
|
1045
|
},
|
|
1008
|
|
- async persistConsultExchange(persistBody, aiReplyContent) {
|
|
|
1046
|
+ async persistConsultExchange(persistBody, aiReplyContent, costTime) {
|
|
1009
|
1047
|
const reply = (aiReplyContent || "").trim()
|
|
1010
|
1048
|
if (!this.activeSessionId || !persistBody || !reply) {
|
|
1011
|
1049
|
return true
|
|
|
@@ -1015,7 +1053,8 @@ export default {
|
|
1015
|
1053
|
const saveBody = {
|
|
1016
|
1054
|
...persistBody,
|
|
1017
|
1055
|
aiReplyContent: reply,
|
|
1018
|
|
- realSessionId: llmSessionId || null
|
|
|
1056
|
+ realSessionId: llmSessionId || null,
|
|
|
1057
|
+ costTime: costTime != null ? costTime : undefined
|
|
1019
|
1058
|
}
|
|
1020
|
1059
|
try {
|
|
1021
|
1060
|
const res = await sendAiConsultMessage(consultSessionId, saveBody)
|
|
|
@@ -1030,7 +1069,7 @@ export default {
|
|
1030
|
1069
|
}
|
|
1031
|
1070
|
return true
|
|
1032
|
1071
|
} catch (err) {
|
|
1033
|
|
- this.queuePendingPersist(consultSessionId, persistBody, reply, llmSessionId)
|
|
|
1072
|
+ this.queuePendingPersist(consultSessionId, persistBody, reply, llmSessionId, costTime)
|
|
1034
|
1073
|
const msg = (err && err.message) || this.dtT("saveSessionFailed")
|
|
1035
|
1074
|
this.$modal.msgWarning(msg)
|
|
1036
|
1075
|
return false
|
|
|
@@ -1191,6 +1230,7 @@ export default {
|
|
1191
|
1230
|
|
|
1192
|
1231
|
let aiReplyContent = ""
|
|
1193
|
1232
|
let aiMsg = null
|
|
|
1233
|
+ let costTime = null
|
|
1194
|
1234
|
this.abortStreamRequest()
|
|
1195
|
1235
|
const abortController = new AbortController()
|
|
1196
|
1236
|
this.streamAbortController = abortController
|
|
|
@@ -1216,6 +1256,7 @@ export default {
|
|
1216
|
1256
|
if (llmSid) {
|
|
1217
|
1257
|
this.rememberLlmSessionId(session, llmSid)
|
|
1218
|
1258
|
}
|
|
|
1259
|
+ costTime = streamResult.durationMs != null ? streamResult.durationMs : null
|
|
1219
|
1260
|
this.clearStreamRevealTimer()
|
|
1220
|
1261
|
aiReplyContent = (streamResult.content || aiReplyContent || "").trim() || this.dtT("noContent")
|
|
1221
|
1262
|
if (!aiMsg) {
|
|
|
@@ -1246,7 +1287,7 @@ export default {
|
|
1246
|
1287
|
this.sending = false
|
|
1247
|
1288
|
this.$nextTick(() => this.scrollChatBottom())
|
|
1248
|
1289
|
}
|
|
1249
|
|
- await this.persistConsultExchange(persistBody, (aiReplyContent || "").trim())
|
|
|
1290
|
+ await this.persistConsultExchange(persistBody, (aiReplyContent || "").trim(), costTime)
|
|
1250
|
1291
|
},
|
|
1251
|
1292
|
extOf(fileName) {
|
|
1252
|
1293
|
if (!fileName || fileName.lastIndexOf(".") < 0) {
|
|
|
@@ -1424,6 +1465,25 @@ export default {
|
|
1424
|
1465
|
}
|
|
1425
|
1466
|
}
|
|
1426
|
1467
|
|
|
|
1468
|
+.session-item__delete {
|
|
|
1469
|
+ flex-shrink: 0;
|
|
|
1470
|
+ align-self: center;
|
|
|
1471
|
+ padding: 4px;
|
|
|
1472
|
+ margin-left: 4px;
|
|
|
1473
|
+ color: #909399;
|
|
|
1474
|
+ opacity: 0;
|
|
|
1475
|
+ transition: opacity 0.15s, color 0.15s;
|
|
|
1476
|
+
|
|
|
1477
|
+ &:hover {
|
|
|
1478
|
+ color: #f56c6c;
|
|
|
1479
|
+ }
|
|
|
1480
|
+}
|
|
|
1481
|
+
|
|
|
1482
|
+.session-item:hover .session-item__delete,
|
|
|
1483
|
+.session-item.is-active .session-item__delete {
|
|
|
1484
|
+ opacity: 1;
|
|
|
1485
|
+}
|
|
|
1486
|
+
|
|
1427
|
1487
|
.session-item__avatar {
|
|
1428
|
1488
|
flex-shrink: 0;
|
|
1429
|
1489
|
background: #dcdfe6;
|