|
|
@@ -137,7 +137,7 @@
|
|
137
|
137
|
<div class="relative mb-4">
|
|
138
|
138
|
<div class="absolute left-0 top-0 w-full h-16 bg-gradient-to-b from
|
|
139
|
139
|
from-white to-transparent pointer-events-none z-10"></div>
|
|
140
|
|
- <div ref="transcriptContainer" class="h-[500px] overflow-y-auto pr-4 space-y-3">
|
|
|
140
|
+ <div ref="transcriptContainer" class="h-[500px] overflow-y-auto pr-4 space-y-3" @mouseenter="chatMouse(0)" @mouseleave="chatMouse(1)">
|
|
141
|
141
|
<div v-for="(item, index) in transcripts" :key="index" class="p-3 rounded-lg"
|
|
142
|
142
|
:class="[item.direction === 2 ? 'bg-blue-50' : 'bg-gray-50']">
|
|
143
|
143
|
<div class="flex items-center mb-1">
|
|
|
@@ -171,6 +171,7 @@ from-white to-transparent pointer-events-none z-10"></div>
|
|
171
|
171
|
effect="plain" size="small" @click="getKnowledgeBaseList(keyword.text)">
|
|
172
|
172
|
{{ keyword.text }}
|
|
173
|
173
|
<span
|
|
|
174
|
+ v-if="keyword.count > 1"
|
|
174
|
175
|
class="absolute -top-1 -right-1 bg-blue-500 text-white text-[10px] rounded-full w-4 h-4 flex items-center justify-center">
|
|
175
|
176
|
{{ keyword.count }}
|
|
176
|
177
|
</span>
|
|
|
@@ -184,14 +185,14 @@ from-white to-transparent pointer-events-none z-10"></div>
|
|
184
|
185
|
<div v-for="(item, idx) in recommendedKnowledge" :key="idx"
|
|
185
|
186
|
class="p-4 bg-white rounded-lg shadow-sm hover:shadow-md transition-all cursor-pointer">
|
|
186
|
187
|
<div class="flex items-center justify-between mb-2">
|
|
187
|
|
- <h5 class="font-medium">{{ item.title }}</h5>
|
|
|
188
|
+ <h5 class="font-medium" @click="openKnowledgeAi(item.docId)">{{ item.title }}</h5>
|
|
188
|
189
|
<el-tag size="small" type="default">{{ item.directoryname }}</el-tag>
|
|
189
|
190
|
</div>
|
|
190
|
191
|
<p class="text-sm text-gray-600 line-clamp-2 mb-2">{{
|
|
191
|
192
|
stripHtmlByRegex(item.content) }}</p>
|
|
192
|
193
|
<div class="flex items-center justify-between text-xs text-gray-500">
|
|
193
|
194
|
<span>发布时间:{{ item.createTime }}</span>
|
|
194
|
|
- <span>阅读:{{ item.reads }}</span>
|
|
|
195
|
+ <!-- <span>阅读:{{ item.reads }}</span> -->
|
|
195
|
196
|
</div>
|
|
196
|
197
|
</div>
|
|
197
|
198
|
</div>
|
|
|
@@ -420,12 +421,24 @@ from-white to-transparent pointer-events-none z-10"></div>
|
|
420
|
421
|
</div>
|
|
421
|
422
|
</div>
|
|
422
|
423
|
|
|
|
424
|
+
|
|
|
425
|
+ <div class="aiDialog">
|
|
|
426
|
+ <!-- title="Tips" -->
|
|
|
427
|
+ <el-dialog v-model="dialogVisible" :close-on-click-modal="false" :close-on-press-escape="false"
|
|
|
428
|
+ :modal="false" width="30%"
|
|
|
429
|
+ :style="{ 'background': 'url(' + base64data.aiBG + ') center center / 100% 100% no-repeat' }" draggable>
|
|
|
430
|
+ <ai-dialog :knowledgeId="selectKnowledgeId"></ai-dialog>
|
|
|
431
|
+ </el-dialog>
|
|
|
432
|
+ </div>
|
|
|
433
|
+
|
|
423
|
434
|
</div>
|
|
424
|
435
|
</template>
|
|
425
|
436
|
<script lang="ts" setup name="CallScreen">
|
|
426
|
437
|
import { ref, computed, onMounted, onUnmounted, watch, nextTick } from 'vue';
|
|
427
|
438
|
import moment from 'moment';
|
|
428
|
439
|
import { findKeyword } from '@/utils/trie';
|
|
|
440
|
+import { base64data } from '@/utils/baseUrlData'
|
|
|
441
|
+import aiDialog from '@/components/main/Navbar/cpns/aiDialog/aiDialog.vue'
|
|
429
|
442
|
import {
|
|
430
|
443
|
UserFilled,
|
|
431
|
444
|
Phone,
|
|
|
@@ -466,6 +479,7 @@ const showCallPanel = ref(false);
|
|
466
|
479
|
const searchQuery = ref('');
|
|
467
|
480
|
const aiLoading = ref(false);
|
|
468
|
481
|
const isCanAutoScroll = ref(1);
|
|
|
482
|
+const dialogVisible = ref(false);
|
|
469
|
483
|
|
|
470
|
484
|
const showAsr = ref(import.meta.env.VITE_APP_AI_ASR === 'true');
|
|
471
|
485
|
const showAI = ref(import.meta.env.VITE_APP_AI_SEARCH === 'true');
|
|
|
@@ -845,23 +859,12 @@ const transcripts: any = ref([
|
|
845
|
859
|
])
|
|
846
|
860
|
// 关键词提示
|
|
847
|
861
|
const keywords: any = ref([
|
|
848
|
|
- {
|
|
849
|
|
- text: '强迫症',
|
|
850
|
|
- type: 'primary',
|
|
851
|
|
- count: 0,
|
|
852
|
|
- },
|
|
853
|
|
- // {
|
|
854
|
|
- // text: '操作流程',
|
|
855
|
|
- // type: 'success'
|
|
856
|
|
- // },
|
|
857
|
862
|
// {
|
|
858
|
|
- // text: '正面反馈',
|
|
859
|
|
- // type: 'success'
|
|
|
863
|
+ // text: '强迫症',
|
|
|
864
|
+ // type: 'primary',
|
|
|
865
|
+ // count: 0,
|
|
860
|
866
|
// },
|
|
861
|
|
- // {
|
|
862
|
|
- // text: '满意度高',
|
|
863
|
|
- // type: 'success'
|
|
864
|
|
- // }
|
|
|
867
|
+
|
|
865
|
868
|
]);
|
|
866
|
869
|
// 建议话术
|
|
867
|
870
|
const suggestions = ref([
|
|
|
@@ -873,21 +876,21 @@ const suggestions = ref([
|
|
873
|
876
|
const transcriptContainer = ref<HTMLElement | null>(null);
|
|
874
|
877
|
// 监听新消息,自动滚动到底部
|
|
875
|
878
|
// 监听新消息和内容变化,自动滚动到底部
|
|
876
|
|
-watch(
|
|
877
|
|
- [
|
|
878
|
|
- () => transcripts.value.length,
|
|
879
|
|
- () => transcripts.value.map(t => t.page_content)
|
|
880
|
|
- ],
|
|
881
|
|
- () => {
|
|
882
|
|
- nextTick(() => {
|
|
883
|
|
- console.log(transcriptContainer.value, 'transcriptContainer');
|
|
884
|
|
- if (transcriptContainer.value) {
|
|
885
|
|
- transcriptContainer.value.scrollTop = transcriptContainer.value.scrollHeight;
|
|
886
|
|
- }
|
|
887
|
|
- });
|
|
888
|
|
- },
|
|
889
|
|
- { deep: true }
|
|
890
|
|
-);
|
|
|
879
|
+// watch(
|
|
|
880
|
+// [
|
|
|
881
|
+// () => transcripts.value.length,
|
|
|
882
|
+// () => transcripts.value.map(t => t.page_content)
|
|
|
883
|
+// ],
|
|
|
884
|
+// () => {
|
|
|
885
|
+// nextTick(() => {
|
|
|
886
|
+// console.log(transcriptContainer.value, 'transcriptContainer');
|
|
|
887
|
+// if (transcriptContainer.value) {
|
|
|
888
|
+// transcriptContainer.value.scrollTop = transcriptContainer.value.scrollHeight;
|
|
|
889
|
+// }
|
|
|
890
|
+// });
|
|
|
891
|
+// },
|
|
|
892
|
+// { deep: true }
|
|
|
893
|
+// );
|
|
891
|
894
|
|
|
892
|
895
|
window.addEventListener('AsrMessageEvent', (msg: any) => {
|
|
893
|
896
|
console.log(msg.detail, '接收asr消息');
|
|
|
@@ -1059,40 +1062,7 @@ async function getSearchDocs (text) {
|
|
1059
|
1062
|
}
|
|
1060
|
1063
|
|
|
1061
|
1064
|
// 推荐知识
|
|
1062
|
|
-const recommendedKnowledge: any = ref([
|
|
1063
|
|
- // {
|
|
1064
|
|
- // title: '智能客服系统功能配置指南',
|
|
1065
|
|
- // content: '本文详细介绍了智能客服系统的核心功能配置方法,包括自动应答规则设置、多渠道接入配置、知识库管理等内容。通过本指南,您可以快速掌握系统的基础配置和高级功能设置。',
|
|
1066
|
|
- // category: '使用指南',
|
|
1067
|
|
- // type: 'primary',
|
|
1068
|
|
- // publishTime: '2024-01-20',
|
|
1069
|
|
- // reads: 1234
|
|
1070
|
|
- // },
|
|
1071
|
|
- // {
|
|
1072
|
|
- // title: '常见故障诊断与解决方案',
|
|
1073
|
|
- // content: '汇总了系统使用过程中最常见的技术问题和解决方案,包括登录异常、数据同步失败、性能优化等问题的处理方法。本文档由技术支持团队整理,持续更新维护。',
|
|
1074
|
|
- // category: '技术支持',
|
|
1075
|
|
- // type: 'warning',
|
|
1076
|
|
- // publishTime: '2024-01-18',
|
|
1077
|
|
- // reads: 856
|
|
1078
|
|
- // },
|
|
1079
|
|
- // {
|
|
1080
|
|
- // title: '客服质量管理最佳实践',
|
|
1081
|
|
- // content: '本文从客服管理者的角度,详细介绍了如何提升客服团队的服务质量,包括话术规范、服务标准、质检方案等内容,帮助管理者建立高效的客服质量管理体系。',
|
|
1082
|
|
- // category: '最佳实践',
|
|
1083
|
|
- // type: 'success',
|
|
1084
|
|
- // publishTime: '2024-01-15',
|
|
1085
|
|
- // reads: 678
|
|
1086
|
|
- // },
|
|
1087
|
|
- // {
|
|
1088
|
|
- // title: '数据分析报表解读指南',
|
|
1089
|
|
- // content: '详细说明了系统各类数据分析报表的含义和使用方法,包括客服效率分析、满意度趋势、问题分类统计等报表的查看和导出方式,帮助您更好地利用数据指导工作。',
|
|
1090
|
|
- // category: '数据分析',
|
|
1091
|
|
- // type: 'info',
|
|
1092
|
|
- // publishTime: '2024-01-12',
|
|
1093
|
|
- // reads: 945
|
|
1094
|
|
- // }
|
|
1095
|
|
-]);
|
|
|
1065
|
+const recommendedKnowledge: any = ref([]);
|
|
1096
|
1066
|
|
|
1097
|
1067
|
|
|
1098
|
1068
|
const keys = useKeysStore().knowledgeKeys;
|
|
|
@@ -1142,8 +1112,33 @@ const setKeys = (keys: Array<string>) => {
|
|
1142
|
1112
|
|
|
1143
|
1113
|
}
|
|
1144
|
1114
|
|
|
|
1115
|
+const selectKnowledgeId = ref(0);
|
|
|
1116
|
+
|
|
|
1117
|
+const openKnowledgeAi = (id) => {
|
|
|
1118
|
+ selectKnowledgeId.value = id;
|
|
|
1119
|
+ dialogVisible.value = true;
|
|
|
1120
|
+}
|
|
|
1121
|
+
|
|
|
1122
|
+const chatMouse = (type) => {
|
|
|
1123
|
+ isCanAutoScroll.value = type;
|
|
|
1124
|
+}
|
|
|
1125
|
+
|
|
|
1126
|
+const scrollToBottom = () => {
|
|
|
1127
|
+ if (transcriptContainer.value) {
|
|
|
1128
|
+ transcriptContainer.value.scrollTop = transcriptContainer.value.scrollHeight;
|
|
|
1129
|
+ }
|
|
|
1130
|
+}
|
|
|
1131
|
+
|
|
|
1132
|
+watch(transcripts, () => {
|
|
|
1133
|
+ nextTick(() => {
|
|
|
1134
|
+ if (isCanAutoScroll.value) scrollToBottom();
|
|
|
1135
|
+ })
|
|
|
1136
|
+}, {
|
|
|
1137
|
+ deep: true
|
|
|
1138
|
+})
|
|
|
1139
|
+
|
|
1145
|
1140
|
</script>
|
|
1146
|
|
-<style scoped>
|
|
|
1141
|
+<style scoped lang="scss">
|
|
1147
|
1142
|
* {
|
|
1148
|
1143
|
transition: height 0.3s ease-out;
|
|
1149
|
1144
|
}
|
|
|
@@ -1211,4 +1206,30 @@ const setKeys = (keys: Array<string>) => {
|
|
1211
|
1206
|
:deep(.el-icon) {
|
|
1212
|
1207
|
font-size: 1.25rem;
|
|
1213
|
1208
|
}
|
|
|
1209
|
+
|
|
|
1210
|
+.aiDialog {
|
|
|
1211
|
+ z-index: 2033;
|
|
|
1212
|
+ pointer-events: none;
|
|
|
1213
|
+
|
|
|
1214
|
+ :deep(.el-dialog) {
|
|
|
1215
|
+ position: absolute;
|
|
|
1216
|
+ height: 700px;
|
|
|
1217
|
+ top: 50px;
|
|
|
1218
|
+ right: 0;
|
|
|
1219
|
+ margin: 0;
|
|
|
1220
|
+ left: unset;
|
|
|
1221
|
+ pointer-events: auto;
|
|
|
1222
|
+ }
|
|
|
1223
|
+}
|
|
|
1224
|
+
|
|
|
1225
|
+/* 隐藏所有滚动条 */
|
|
|
1226
|
+* {
|
|
|
1227
|
+ scrollbar-width: none; /* Firefox */
|
|
|
1228
|
+ -ms-overflow-style: none; /* Internet Explorer 10+ */
|
|
|
1229
|
+}
|
|
|
1230
|
+
|
|
|
1231
|
+/* 针对Webkit浏览器(如Chrome和Safari) */
|
|
|
1232
|
+*::-webkit-scrollbar {
|
|
|
1233
|
+ display: none;
|
|
|
1234
|
+}
|
|
1214
|
1235
|
</style>
|