askbot-dragon 1.6.21 → 1.6.22

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "askbot-dragon",
3
- "version": "1.6.21",
3
+ "version": "1.6.22",
4
4
  "scripts": {
5
5
  "serve": "vue-cli-service serve",
6
6
  "build": "vue-cli-service build",
@@ -17,7 +17,28 @@
17
17
  <p v-html="msg.content.text"></p>
18
18
  </template>
19
19
  <template v-else-if="msg.content.renderType == 2">
20
- <markDownText :chainValues="msg.content.text" :isHistory="isHistory"></markDownText>
20
+ <!-- <markDownText :chainValues="msg.content.text" :isHistory="isHistory"></markDownText> -->
21
+ <markDownText
22
+ :chainValues="msg.content.text || ''"
23
+ :whetherRequestStream="msg.content.whetherRequestStream"
24
+ @sseOtherInfo="sseOtherInfo"
25
+ @answerDocKnowledgeFn="answerDocKnowledgeFn"
26
+ :streamRequestUrl="msg.content.streamRequestUrl"
27
+ :msgId="msg.id"
28
+ :isHistory="isHistory">
29
+ </markDownText>
30
+ </template>
31
+ <template v-else-if="msg.content.renderType == null">
32
+ <!-- <markDownText :chainValues="msg.content.text" :isHistory="isHistory"></markDownText> -->
33
+ <markDownText
34
+ :chainValues="msg.content.text || ''"
35
+ :whetherRequestStream="msg.content.whetherRequestStream"
36
+ @sseOtherInfo="sseOtherInfo"
37
+ @answerDocKnowledgeFn="answerDocKnowledgeFn"
38
+ :streamRequestUrl="msg.content.streamRequestUrl"
39
+ :msgId="msg.id"
40
+ :isHistory="isHistory">
41
+ </markDownText>
21
42
  </template>
22
43
  <template v-else>{{ msg.content.text }}</template>
23
44
  </div>
@@ -75,7 +96,7 @@
75
96
  </div>
76
97
  </div>
77
98
  </template>
78
- <template v-if="msg.content.type == 0">
99
+ <template v-if="msg.content.type == 0 || msg.content.type == 2">
79
100
  <div v-for="(item, itemIndex) in msg.content.list" :key="itemIndex" class="ad-list-cell-recognition" :id="item.knowledgeId + knowledgeIndex">
80
101
  <div class="alc-source-name" @click="lookAttach(item.url, item, $event)">
81
102
  <img class="alc-title-icon" height="18px" width="18px" :src="getIconSrc(item)" alt srcset />
@@ -328,6 +349,24 @@ export default {
328
349
  }
329
350
  },
330
351
  methods: {
352
+ answerDocKnowledgeFn(){
353
+ console.log(
354
+ "answerDocKnowledgeFn 2"
355
+ );
356
+ this.$emit('answerDocKnowledgeFn');
357
+ },
358
+ // 知识类型消息 推荐、关联文档、图片
359
+ sseOtherInfo(msgId, eventId, data){
360
+ if (eventId === "matched") {
361
+ console.log("matched: ", this.msg.content.type);
362
+
363
+ if (JSON.parse(data.content).length > 0) {
364
+ this.$set(this.msg.content, "list", JSON.parse(data.content));
365
+ }
366
+ } else {
367
+ this.$emit("sseOtherInfo",msgId, eventId, data);
368
+ }
369
+ },
331
370
  getIconSrc (element) {
332
371
  if ((element.format === "txt" || element.format === "html") && element.source === "WECHAT") {
333
372
  return require("../assets/image/filtType/wechat.png")
@@ -1,176 +1,341 @@
1
1
  <template>
2
2
  <div @click="lookImage">
3
- <vue-markdown class="mark_down" :source="typedContent" :ref="'markdown' + msgId">
4
- </vue-markdown>
5
- <div v-if="showPreview">
6
- <img-view :url-list="imgList" @closeViewer="closeViewer"></img-view>
7
- </div>
3
+ <vue-markdown class="mark_down" :source="typedContent" :ref="'markdown' + msgId">
4
+ </vue-markdown>
5
+ <div v-if="showPreview">
6
+ <img-view :url-list="imgList" @closeViewer="closeViewer"></img-view>
7
+ </div>
8
8
  </div>
9
- </template>
10
-
11
- <script>
12
- import VueMarkdown from "vue-markdown";
13
- import ImgView from "./imgView.vue";
14
-
15
- export default {
9
+
10
+ </template>
11
+
12
+ <script>
13
+ import VueMarkdown from 'vue-markdown';
14
+ import ImgView from "./imgView";
15
+ // import Typed from "typed.js";
16
+
17
+ export default {
16
18
  name: "markDownText",
17
19
  data() {
18
- return {
19
- typedContent: "",
20
- typingSpeed: 15,
21
- showPreview: false,
22
- imgList: [],
23
- };
20
+ return {
21
+ typedContent: "",
22
+ typingSpeed: 15,
23
+ showPreview: false,
24
+ imgList: [],
25
+ isManualScroll: false,
26
+ }
24
27
  },
25
28
  props: {
26
- chainValues: {
27
- type: String,
28
- default: "",
29
- },
30
- msgId: {
31
- type: String,
32
- default: "",
33
- },
34
- isHistory: {
35
- type: Boolean,
36
- default: false,
37
- },
29
+ chainValues: {
30
+ type: String,
31
+ default: ""
32
+ },
33
+ msgId: {
34
+ type: String,
35
+ default: ""
36
+ },
37
+ isHistory: {
38
+ type: Boolean,
39
+ default: false
40
+ },
41
+ streamRequestUrl: {
42
+ type: String,
43
+ default: ""
44
+ },
45
+ whetherRequestStream: {
46
+ type: Boolean,
47
+ default: false
48
+ }
38
49
  },
39
50
  components: {
40
- ImgView,
41
- VueMarkdown,
51
+ ImgView,
52
+ VueMarkdown
42
53
  },
43
54
  mounted() {
44
- this.$nextTick(() => {
45
- // let ref = 'markdown' + this.msgId
46
- // const el = this.$refs[ref].$el;
47
- // if (this.isHistory){
48
- // el.innerHTML = this.chainValues;
49
- // } else {
50
- // new Typed(el, {
51
- // strings: [this.chainValues],
52
- // typeSpeed: 30,
53
- // showCursor: false
54
- // })
55
- // }
56
- this.typedContent = this.chainValues;
57
- // if (this.isHistory) {
58
- // this.typedContent = this.chainValues;
59
- // } else {
60
- // this.startTypingEffect();
61
- // }
62
- });
55
+ this.$nextTick(() => {
56
+ console.log("this.askMassageStream: ", this.askMassageStream);
57
+ console.log("this.whetherRequestStream: ", this.whetherRequestStream);
58
+ console.log("this.streamRequestUrl: ", this.streamRequestUrl);
59
+ console.log("this.isHistory: ", this.isHistory);
60
+ if (this.isHistory) {
61
+ if (this.whetherRequestStream) {
62
+ console.log("71 新版 真 流 打字 效果");
63
+ window.addEventListener('wheel', this.handleScroll, true);
64
+ this.streamInfo(this.streamRequestUrl);
65
+ } else {
66
+ this.typedContent = this.chainValues
67
+ console.log(JSON.parse(JSON.stringify(this.typedContent)));
68
+
69
+ }
70
+
71
+ } else {
72
+ console.log("78 pre 新版 真 流 打字 效果");
73
+ // 新版 真 流 打字 效果
74
+ if (this.askMassageStream && this.whetherRequestStream && this.streamRequestUrl) {
75
+ console.log("81 新版 真 流 打字 效果");
76
+ window.addEventListener('wheel', this.handleScroll, true);
77
+ this.streamInfo(this.streamRequestUrl);
78
+ } else {
79
+ this.$emit("sseOtherInfo", this.msgId, "start", "");
80
+ // 旧版 模拟 流 打字 效果
81
+ this.typedContent = this.chainValues
82
+ // this.startTypingEffect();
83
+ }
84
+ }
85
+ })
63
86
  },
64
87
  methods: {
65
- startTypingEffect() {
66
- let i = 0;
67
- const interval = setInterval(() => {
68
- if (i < this.chainValues.length) {
69
- this.typedContent += this.chainValues.charAt(i);
70
- i++;
71
- } else {
72
- clearInterval(interval);
88
+ // 打字效果已在MarkdownText文件中处理
89
+ // typeNewWriter(text, keyId, msg) {
90
+ // setTimeout(() => {
91
+ // let ref = 'msgTyped' + keyId;
92
+ // const el = this.$refs[ref][0];
93
+ // new Typed(el, {
94
+ // strings: [text],
95
+ // typeSpeed: 15,
96
+ // showCursor: false,
97
+ // onComplete: () => {
98
+ // msg.isHistory = true
99
+ // this.$emit('openFirstPreview', msg)
100
+ // this.typingSuccess()
101
+ // },
102
+ // })
103
+ // }, 500)
104
+ // },
105
+ handleScroll() {
106
+ console.log("this.isManualScroll = true;");
107
+ this.isManualScroll = true;
108
+ window.removeEventListener('wheel', this.handleScroll, true);
109
+ },
110
+ scrollMarkdown(){
111
+ !this.isManualScroll && this.$nextTick(() => {
112
+ const element = document.getElementById('el_id_markdown_' + this.msgId);
113
+ if (element) {
114
+ element.scrollIntoView({ behavior: 'smooth', block: 'start' });
115
+ }
116
+ });
117
+ },
118
+ streamInfo(url){
119
+ // 通知消息列表,当前还未建立sse,先不出空消息
120
+ this.$emit("sseOtherInfo", this.msgId, "init", "");
121
+
122
+ const eventSource = new EventSource(url);
123
+ let tempString = "";
124
+ let generatingString = "";
125
+ let timer = null;
126
+ let images = [];
127
+ let matched = [];
128
+ let recommendItems = [];
129
+ let isfirstStr = false;
130
+ const backslashOrNRegex = /[\\n]/;
131
+ eventSource.onmessage = (event) => {
132
+ const data = JSON.parse(event.data);
133
+ if (event.lastEventId === 'finish') { // 不能删除 finish
134
+ console.log("finish+++++");
135
+ } else if (event.lastEventId === '[DONE]') {
136
+ let DONETmier = setInterval(() => {
137
+ // 在所有文本内容打字效果完毕后 展示底部图片 文件 推荐等
138
+ if (generatingString == "") {
139
+ if (images.length != 0) {
140
+ setTimeout(() => {
141
+ this.$emit("sseOtherInfo", this.msgId,"images", images);
142
+ this.scrollMarkdown();
143
+ }, 50);
73
144
  }
74
- }, this.typingSpeed);
75
- },
76
- lookImage(e) {
77
- let previewImageUrl = "";
78
- console.log("e.target", e.target);
79
- if (e.target.localName == "img") {
80
- previewImageUrl = e.target.currentSrc;
81
- this.showPreview = true;
82
- }
83
- let richtext = JSON.parse(JSON.stringify(this.typedContent));
84
- this.imgList = [];
85
- richtext.replace(
86
- /<img [^>]*src=['"]([^'"]+)[^>]*>/g,
87
- (match, capture) => {
88
- this.imgList.push(capture);
145
+ if (matched.length != 0) {
146
+ setTimeout(() => {
147
+ this.$emit("sseOtherInfo", this.msgId, "matched", matched);
148
+ this.scrollMarkdown();
149
+ }, 100);
89
150
  }
90
- );
91
- /*当前点击的图片作为第一个图片*/
92
- let index = this.imgList.indexOf(previewImageUrl);
93
- this.imgList.splice(index, 1);
94
- this.imgList.unshift(previewImageUrl);
95
- },
96
- closeViewer() {
97
- this.showPreview = false;
98
- },
99
- },
100
- };
101
- </script>
102
-
103
- <style scoped lang="less">
104
- .mark_down {
151
+ if (recommendItems.length != 0) {
152
+ setTimeout(() => {
153
+ this.$emit("sseOtherInfo", this.msgId, "recommendItems", recommendItems);
154
+ this.scrollMarkdown();
155
+ }, 150);
156
+ }
157
+ clearInterval(DONETmier);
158
+ }
159
+ }, 100);
160
+
161
+ eventSource.close();
162
+ } else if (event.lastEventId === 'matched') {
163
+ matched = data;
164
+ } else if (event.lastEventId === 'images') {
165
+ images = data;
166
+ } else if (event.lastEventId === 'recommendItems') {
167
+ recommendItems = data;
168
+ } else {
169
+ // 设置当前知识答案id,用于loading取消和展示
170
+ this.$emit("sseOtherInfo", this.msgId, "start", "");
171
+ // 字符串中存在特定字符,本次接收消息暂不展示
172
+ if (backslashOrNRegex.test(data.content)) {
173
+ tempString += data.content;
174
+ } else {
175
+ if (!isfirstStr) {
176
+ isfirstStr = true;
177
+ timer = setInterval(() => {
178
+ if (generatingString != "") {
179
+ this.$set(this, "typedContent", this.typedContent + generatingString.charAt(0))
180
+ generatingString = generatingString.slice(1)
181
+ this.scrollMarkdown();
182
+ } else {
183
+ clearInterval(timer);
184
+ }
185
+ }, 20);
186
+ console.log(
187
+ "answerDocKnowledgeFn 1"
188
+ );
189
+
190
+ this.$emit("answerDocKnowledgeFn");
191
+ }
192
+ let repStr = tempString.replace(/\\n/g, '\n');
193
+ generatingString = generatingString + repStr + data.content;
194
+ tempString = "";
195
+ }
196
+ }
197
+ };
198
+
199
+ eventSource.onerror = function(err) {
200
+ console.error('EventSource failed:', err);
201
+ this.typedContent += '\nError receiving data from server.\n';
202
+ eventSource.close();
203
+ };
204
+ },
205
+ startTypingEffect() {
206
+ // 使用正则表达式将 HTML 内容按 <table> 标签分割
207
+ const segments = this.chainValues.split(/(<\/?table[\s\S]*?>[\s\S]*?<\/table>)/i);
208
+ console.log("segments: ", segments);
209
+
210
+ let segmentIndex = 0;
211
+ let i = 0;
212
+ const processNextSegment = () => {
213
+ if (segmentIndex >= segments.length) {
214
+ this.$emit('openFirstPreview')
215
+ this.$emit('typingSuccess');
216
+ return;
217
+ }
218
+ const segment = segments[segmentIndex];
219
+ if (/^<\/?table[\s\S]*?>[\s\S]*?<\/table>$/i.test(segment)) {
220
+ // 如果当前段是 <table> 标签,直接添加到 typedContent 中
221
+ this.typedContent += segment;
222
+ segmentIndex++;
223
+ processNextSegment();
224
+ } else {
225
+ i = 0;
226
+ const updateContent = () => {
227
+ if (i < segment.length) {
228
+ this.typedContent += segment.charAt(i);
229
+ i++;
230
+ // 使用 requestAnimationFrame 替代 setInterval,防止卡顿
231
+ requestAnimationFrame(updateContent);
232
+ } else {
233
+ segmentIndex++;
234
+ processNextSegment();
235
+ }
236
+ };
237
+ updateContent();
238
+ }
239
+ };
240
+ processNextSegment();
241
+ },
242
+
243
+ lookImage(e) {
244
+ let previewImageUrl = ""
245
+ console.log('e.target', e.target)
246
+ if (e.target.localName == 'img') {
247
+ previewImageUrl = e.target.currentSrc;
248
+ this.showPreview = true;
249
+ }
250
+ let richtext = JSON.parse(JSON.stringify(this.typedContent))
251
+ this.imgList = [];
252
+ richtext.replace(/<img [^>]*src=['"]([^'"]+)[^>]*>/g, (match, capture) => {
253
+ this.imgList.push(capture);
254
+ });
255
+ /*当前点击的图片作为第一个图片*/
256
+ let index = this.imgList.indexOf(previewImageUrl);
257
+ this.imgList.splice(index, 1);
258
+ this.imgList.unshift(previewImageUrl);
259
+ },
260
+ closeViewer() {
261
+ this.showPreview = false;
262
+ }
263
+ }
264
+ };
265
+ </script>
266
+
267
+ <style scoped lang="less">
268
+ .mark_down {
105
269
  line-height: 24px;
106
270
  overflow-x: auto;
107
271
  /deep/p {
108
- margin-bottom: 14px;
109
- font-size: 16px;
272
+ margin-bottom: 14px;
273
+ font-size: 16px;
110
274
  }
111
-
275
+
112
276
  /deep/p:only-child {
113
- margin: 0 !important;
277
+ margin: 0 !important;
114
278
  }
115
-
279
+
116
280
  /deep/p:last-child {
117
- margin-bottom: 0 !important;
281
+ margin-bottom: 0 !important;
118
282
  }
119
-
283
+
120
284
  /deep/ul {
121
- margin-bottom: 16px;
122
- list-style: disc;
123
- padding-left: 16px;
124
-
125
- li {
126
- margin: 7px 0 !important;
127
- font-size: 16px;
128
- // padding-left: 40px;
129
-
130
- }
285
+ margin-bottom: 16px;
286
+ list-style: disc;
287
+ padding-left: 40px;
288
+
289
+ li {
290
+ margin: 7px 0 !important;
291
+ font-size: 16px;
292
+ // padding-left: 40px;
293
+
294
+ }
131
295
  }
132
-
296
+
133
297
  /deep/ ol {
134
- list-style: auto;
135
- padding-left: 16px;
136
-
137
- li {
138
- margin: 7px 0 !important;
139
- font-size: 16px;
140
- // padding-left: 40px;
141
- }
298
+ list-style: auto;
299
+ padding-left: 40px;
300
+
301
+ li {
302
+ margin: 7px 0 !important;
303
+ font-size: 16px;
304
+ // padding-left: 40px;
305
+ }
142
306
  }
143
-
307
+
144
308
  /deep/img {
145
- max-width: 400px;
309
+ max-width: 400px;
146
310
  }
147
-
311
+
148
312
  /deep/h3,
149
313
  /deep/h2,
150
314
  /deep/h1,
151
315
  /deep/h4,
152
316
  /deep/h5,
153
317
  /deep/h6 {
154
- color: #000000;
155
- font-weight: 500;
156
- line-height: 26px;
318
+ color: #000000;
319
+ font-weight: 500;
320
+ line-height: 26px;
157
321
  }
158
-
322
+
159
323
  /deep/h3 {
160
- font-size: 20px;
324
+ font-size: 20px;
161
325
  }
162
-
326
+
163
327
  /deep/h2 {
164
- font-size: 22px;
328
+ font-size: 22px;
165
329
  }
166
-
330
+
167
331
  /deep/h1 {
168
- font-size: 24px;
332
+ font-size: 24px;
169
333
  }
170
-
334
+
171
335
  /deep/h3 {
172
- font-size: 20px;
336
+ font-size: 20px;
173
337
  }
338
+
174
339
 
175
340
  /deep/ table {
176
341
  border-spacing: 0;
@@ -180,6 +345,7 @@ export default {
180
345
  min-width: 800px;
181
346
  overflow-x: auto;
182
347
  }
348
+
183
349
  /deep/ th {
184
350
  background: #EEF1FF;
185
351
  border: solid 1px #e0e6f7;
@@ -195,4 +361,5 @@ export default {
195
361
  min-width: 100px;
196
362
  }
197
363
  }
198
- </style>
364
+ </style>
365
+