askbot-dragon 1.7.65-beta → 1.7.67-beta

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.
Files changed (95) hide show
  1. package/README.md +27 -27
  2. package/babel.config.js +6 -6
  3. package/dragon.iml +7 -7
  4. package/package.json +57 -57
  5. package/public/index.html +73 -73
  6. package/src/App.vue +31 -31
  7. package/src/api/index.js +1 -1
  8. package/src/api/mock.http +2 -2
  9. package/src/api/requestUrl.js +185 -185
  10. package/src/assets/js/AliyunlssUtil.js +141 -141
  11. package/src/assets/js/Base64Util.js +22 -22
  12. package/src/assets/js/common.js +252 -252
  13. package/src/assets/js/hammer.js +100 -100
  14. package/src/assets/js/script.js +36 -36
  15. package/src/assets/less/common.css +6773 -6773
  16. package/src/assets/less/converSationContainer/common.less +199 -199
  17. package/src/assets/less/converSationContainer/converSatonContainer.less +493 -493
  18. package/src/assets/less/iconfont.css +37 -37
  19. package/src/assets/less/ticketMessage.less +294 -294
  20. package/src/components/ActionAlertIframe.vue +178 -178
  21. package/src/components/AiGuide.vue +434 -434
  22. package/src/components/AnswerDocknowledge.vue +1203 -1203
  23. package/src/components/AnswerVoice.vue +285 -285
  24. package/src/components/AskIFrame.vue +15 -15
  25. package/src/components/ConversationContainer.vue +10764 -10764
  26. package/src/components/FileType.vue +86 -86
  27. package/src/components/Message.vue +27 -27
  28. package/src/components/MyEditor.vue +342 -342
  29. package/src/components/QwFeedback.vue +302 -302
  30. package/src/components/actionSatisfaction.vue +107 -107
  31. package/src/components/actionSendToBot.vue +62 -62
  32. package/src/components/answerDissatisfaction.vue +62 -62
  33. package/src/components/answerRadio.vue +259 -259
  34. package/src/components/ask-components/DissatisfactionOptions.vue +57 -57
  35. package/src/components/ask-components/Msgloading.vue +37 -37
  36. package/src/components/ask-components/SatisfactionV2.vue +15 -15
  37. package/src/components/askVideo.vue +162 -162
  38. package/src/components/assetDetails.vue +378 -378
  39. package/src/components/assetMessage.vue +229 -229
  40. package/src/components/associationIntention.vue +378 -378
  41. package/src/components/attachmentPreview.vue +90 -90
  42. package/src/components/botActionSatisfactor.vue +68 -68
  43. package/src/components/chatContent.vue +513 -513
  44. package/src/components/feedBack.vue +136 -136
  45. package/src/components/fielListView.vue +351 -351
  46. package/src/components/file/AliyunOssComponents.vue +108 -108
  47. package/src/components/formTemplate.vue +3512 -3512
  48. package/src/components/imgView.vue +31 -31
  49. package/src/components/intelligentSummary.vue +234 -234
  50. package/src/components/kkview.vue +1138 -1138
  51. package/src/components/loadingProcess.vue +164 -164
  52. package/src/components/markDownText.vue +357 -357
  53. package/src/components/message/ActionAlertIframe.vue +112 -112
  54. package/src/components/message/ShopMessage.vue +164 -164
  55. package/src/components/message/TextMessage.vue +928 -928
  56. package/src/components/message/TicketMessage.vue +201 -201
  57. package/src/components/message/swiper/index.js +4 -4
  58. package/src/components/message/swiper/ticketSwiper.vue +503 -503
  59. package/src/components/message/swiper/ticketSwiperItem.vue +61 -61
  60. package/src/components/msgLoading.vue +231 -231
  61. package/src/components/myPopup.vue +73 -73
  62. package/src/components/newPdfPosition.vue +877 -877
  63. package/src/components/pagination.vue +128 -128
  64. package/src/components/pdfPosition.vue +1523 -1523
  65. package/src/components/popup.vue +228 -228
  66. package/src/components/preview/docView.vue +113 -113
  67. package/src/components/preview/excelView.vue +190 -190
  68. package/src/components/preview/newPositionPreview.vue +384 -369
  69. package/src/components/preview/pdfView.vue +824 -824
  70. package/src/components/previewDoc.vue +252 -252
  71. package/src/components/previewPdf.vue +1087 -1087
  72. package/src/components/receiverMessagePlatform.vue +69 -69
  73. package/src/components/recommend.vue +80 -80
  74. package/src/components/selector/hOption.vue +20 -20
  75. package/src/components/selector/hSelector.vue +199 -199
  76. package/src/components/selector/hWrapper.vue +216 -216
  77. package/src/components/senderMessagePlatform.vue +58 -58
  78. package/src/components/source/BotMessage.vue +24 -24
  79. package/src/components/source/CustomMessage.vue +24 -24
  80. package/src/components/test.vue +260 -260
  81. package/src/components/tree.vue +307 -307
  82. package/src/components/utils/AliyunIssUtil.js +103 -103
  83. package/src/components/utils/ckeditor.js +185 -185
  84. package/src/components/utils/format_date.js +25 -25
  85. package/src/components/utils/index.js +6 -6
  86. package/src/components/utils/math_utils.js +29 -29
  87. package/src/components/voiceComponent.vue +119 -119
  88. package/src/components/welcomeKnowledgeFile.vue +347 -347
  89. package/src/components/welcomeLlmCard.vue +144 -144
  90. package/src/components/welcomeSuggest.vue +97 -97
  91. package/src/locales/cn.json +95 -95
  92. package/src/locales/en.json +95 -95
  93. package/src/locales/jp.json +72 -72
  94. package/src/main.js +76 -76
  95. package/vue.config.js +54 -54
@@ -1,358 +1,358 @@
1
- <template>
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>
8
- </div>
9
-
10
- </template>
11
- <script>
12
- import VueMarkdown from 'vue-markdown';
13
- import ImgView from "./imgView";
14
- // import Typed from "typed.js";
15
-
16
- export default {
17
- name: "markDownText",
18
- data() {
19
- return {
20
- typedContent: "",
21
- typingSpeed: 15,
22
- showPreview: false,
23
- imgList: [],
24
- isManualScroll: false,
25
- }
26
- },
27
- props: {
28
- chainValues: {
29
- type: String,
30
- default: ""
31
- },
32
- msgId: {
33
- type: String,
34
- default: ""
35
- },
36
- isHistory: {
37
- type: Boolean,
38
- default: false
39
- },
40
- streamRequestUrl: {
41
- type: String,
42
- default: ""
43
- },
44
- whetherRequestStream: {
45
- type: Boolean,
46
- default: false
47
- }
48
- },
49
- components: {
50
- ImgView,
51
- VueMarkdown
52
- },
53
- mounted() {
54
- this.$nextTick(() => {
55
- console.log("this.askMassageStream: ", this.askMassageStream);
56
- console.log("this.whetherRequestStream: ", this.whetherRequestStream);
57
- console.log("this.streamRequestUrl: ", this.streamRequestUrl);
58
- console.log("this.isHistory: ", this.isHistory);
59
- if (this.isHistory) {
60
- if (this.whetherRequestStream) {
61
- console.log("71 新版 真 流 打字 效果");
62
- window.addEventListener('wheel', this.handleScroll, true);
63
- this.streamInfo(this.streamRequestUrl);
64
- } else {
65
- this.typedContent = this.chainValues
66
- console.log(JSON.parse(JSON.stringify(this.typedContent)));
67
-
68
- }
69
-
70
- } else {
71
- console.log("78 pre 新版 真 流 打字 效果");
72
- // 新版 真 流 打字 效果
73
- if (this.askMassageStream && this.whetherRequestStream && this.streamRequestUrl) {
74
- console.log("81 新版 真 流 打字 效果");
75
- window.addEventListener('wheel', this.handleScroll, true);
76
- this.streamInfo(this.streamRequestUrl);
77
- } else {
78
- this.$emit("sseOtherInfo", this.msgId, "start", "");
79
- // 旧版 模拟 流 打字 效果
80
- this.typedContent = this.chainValues
81
- // this.startTypingEffect();
82
- }
83
- }
84
- })
85
- },
86
- methods: {
87
- // 打字效果已在MarkdownText文件中处理
88
- // typeNewWriter(text, keyId, msg) {
89
- // setTimeout(() => {
90
- // let ref = 'msgTyped' + keyId;
91
- // const el = this.$refs[ref][0];
92
- // new Typed(el, {
93
- // strings: [text],
94
- // typeSpeed: 15,
95
- // showCursor: false,
96
- // onComplete: () => {
97
- // msg.isHistory = true
98
- // this.$emit('openFirstPreview', msg)
99
- // this.typingSuccess()
100
- // },
101
- // })
102
- // }, 500)
103
- // },
104
- handleScroll() {
105
- console.log("this.isManualScroll = true;");
106
- this.isManualScroll = true;
107
- window.removeEventListener('wheel', this.handleScroll, true);
108
- },
109
- scrollMarkdown(){
110
- !this.isManualScroll && this.$nextTick(() => {
111
- const element = document.getElementById('el_id_markdown_' + this.msgId);
112
- if (element) {
113
- element.scrollIntoView({ behavior: 'smooth', block: 'start' });
114
- }
115
- });
116
- },
117
- streamInfo(url){
118
- // 通知消息列表,当前还未建立sse,先不出空消息
119
- this.$emit("sseOtherInfo", this.msgId, "init", "");
120
-
121
- const eventSource = new EventSource(url);
122
- let tempString = "";
123
- let generatingString = "";
124
- let timer = null;
125
- let images = [];
126
- let matched = [];
127
- let recommendItems = [];
128
- let isfirstStr = false;
129
- const backslashOrNRegex = /\n/;
130
- eventSource.onmessage = (event) => {
131
- const data = JSON.parse(event.data);
132
- if (event.lastEventId === 'finish') { // 不能删除 finish
133
- console.log("finish+++++");
134
- } else if (event.lastEventId === '[DONE]') {
135
- let DONETmier = setInterval(() => {
136
- // 在所有文本内容打字效果完毕后 展示底部图片 文件 推荐等
137
- if (generatingString == "") {
138
- if (images.length != 0) {
139
- setTimeout(() => {
140
- this.$emit("sseOtherInfo", this.msgId,"images", images);
141
- this.scrollMarkdown();
142
- }, 50);
143
- }
144
- if (matched.length != 0) {
145
- setTimeout(() => {
146
- this.$emit("sseOtherInfo", this.msgId, "matched", matched);
147
- this.scrollMarkdown();
148
- }, 100);
149
- }
150
- if (recommendItems.length != 0) {
151
- setTimeout(() => {
152
- this.$emit("sseOtherInfo", this.msgId, "recommendItems", recommendItems);
153
- this.scrollMarkdown();
154
- }, 150);
155
- }
156
- clearInterval(timer);
157
- clearInterval(DONETmier);
158
- }
159
- }, 100);
160
- eventSource.close();
161
- } else if (event.lastEventId === 'matched') {
162
- matched = data;
163
- } else if (event.lastEventId === 'images') {
164
- images = data;
165
- } else if (event.lastEventId === 'recommendItems') {
166
- recommendItems = data;
167
- } else {
168
- // 设置当前知识答案id,用于loading取消和展示
169
- this.$emit("sseOtherInfo", this.msgId, "start", "");
170
- // 字符串中存在特定字符,本次接收消息暂不展示
171
- if (backslashOrNRegex.test(data.content)) {
172
- tempString += data.content;
173
- } else {
174
- if (!isfirstStr) {
175
- isfirstStr = true;
176
- timer = setInterval(() => {
177
- if (generatingString != "") {
178
- this.$set(this, "typedContent", this.typedContent + generatingString.charAt(0))
179
- generatingString = generatingString.slice(1)
180
- this.scrollMarkdown();
181
- }
182
- }, 20);
183
- this.$emit("answerDocKnowledgeFn");
184
- }
185
- let repStr = tempString.replace(/\\n/g, '\n');
186
- generatingString = generatingString + repStr + data.content;
187
- tempString = "";
188
- }
189
- }
190
- };
191
-
192
- eventSource.onerror = function(err) {
193
- console.error('EventSource failed:', err);
194
- this.typedContent += '\nError receiving data from server.\n';
195
- eventSource.close();
196
- };
197
- },
198
- startTypingEffect() {
199
- // 使用正则表达式将 HTML 内容按 <table> 标签分割
200
- const segments = this.chainValues.split(/(<\/?table[\s\S]*?>[\s\S]*?<\/table>)/i);
201
- console.log("segments: ", segments);
202
-
203
- let segmentIndex = 0;
204
- let i = 0;
205
- const processNextSegment = () => {
206
- if (segmentIndex >= segments.length) {
207
- this.$emit('openFirstPreview')
208
- this.$emit('typingSuccess');
209
- return;
210
- }
211
- const segment = segments[segmentIndex];
212
- if (/^<\/?table[\s\S]*?>[\s\S]*?<\/table>$/i.test(segment)) {
213
- // 如果当前段是 <table> 标签,直接添加到 typedContent 中
214
- this.typedContent += segment;
215
- segmentIndex++;
216
- processNextSegment();
217
- } else {
218
- i = 0;
219
- const updateContent = () => {
220
- if (i < segment.length) {
221
- this.typedContent += segment.charAt(i);
222
- i++;
223
- // 使用 requestAnimationFrame 替代 setInterval,防止卡顿
224
- requestAnimationFrame(updateContent);
225
- } else {
226
- segmentIndex++;
227
- processNextSegment();
228
- }
229
- };
230
- updateContent();
231
- }
232
- };
233
- processNextSegment();
234
- },
235
-
236
- lookImage(e) {
237
- let previewImageUrl = ""
238
- console.log('e.target', e.target)
239
- if (e.target.localName == 'img') {
240
- previewImageUrl = e.target.currentSrc;
241
- this.showPreview = true;
242
- }
243
- let richtext = JSON.parse(JSON.stringify(this.typedContent))
244
- this.imgList = [];
245
- richtext.replace(/<img [^>]*src=['"]([^'"]+)[^>]*>/g, (match, capture) => {
246
- this.imgList.push(capture);
247
- });
248
- /*当前点击的图片作为第一个图片*/
249
- let index = this.imgList.indexOf(previewImageUrl);
250
- this.imgList.splice(index, 1);
251
- this.imgList.unshift(previewImageUrl);
252
- },
253
- closeViewer() {
254
- this.showPreview = false;
255
- }
256
- }
257
- };
258
- </script>
259
-
260
- <style scoped lang="less">
261
- .mark_down {
262
- line-height: 24px;
263
- overflow-x: auto;
264
- /deep/p {
265
- margin-bottom: 14px;
266
- font-size: 16px;
267
- }
268
-
269
- /deep/p:only-child {
270
- margin: 0 !important;
271
- }
272
-
273
- /deep/p:last-child {
274
- margin-bottom: 0 !important;
275
- }
276
-
277
- /deep/ul {
278
- margin-bottom: 16px;
279
- list-style: disc;
280
- padding-left: 40px;
281
-
282
- li {
283
- margin: 7px 0 !important;
284
- font-size: 16px;
285
- // padding-left: 40px;
286
-
287
- }
288
- }
289
-
290
- /deep/ ol {
291
- list-style: auto;
292
- padding-left: 40px;
293
-
294
- li {
295
- margin: 7px 0 !important;
296
- font-size: 16px;
297
- // padding-left: 40px;
298
- }
299
- }
300
-
301
- /deep/img {
302
- max-width: 400px;
303
- }
304
-
305
- /deep/h3,
306
- /deep/h2,
307
- /deep/h1,
308
- /deep/h4,
309
- /deep/h5,
310
- /deep/h6 {
311
- color: #000000;
312
- font-weight: 500;
313
- line-height: 26px;
314
- }
315
-
316
- /deep/h3 {
317
- font-size: 20px;
318
- }
319
-
320
- /deep/h2 {
321
- font-size: 22px;
322
- }
323
-
324
- /deep/h1 {
325
- font-size: 24px;
326
- }
327
-
328
- /deep/h3 {
329
- font-size: 20px;
330
- }
331
-
332
-
333
- /deep/ table {
334
- border-spacing: 0;
335
- // border-radius: 8px;
336
- // overflow: hidden;
337
- border: solid 1px #e0e6f7;
338
- min-width: 800px;
339
- overflow-x: auto;
340
- }
341
-
342
- /deep/ th {
343
- background: #EEF1FF;
344
- border: solid 1px #e0e6f7;
345
- padding: 8px;
346
- height: 38px;
347
- min-width: 100px;
348
- }
349
-
350
- /deep/ td {
351
- border: solid 1px #e0e6f7;
352
- padding: 8px;
353
- height: 28px;
354
- min-width: 100px;
355
- }
356
- }
357
- </style>
1
+ <template>
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>
8
+ </div>
9
+
10
+ </template>
11
+ <script>
12
+ import VueMarkdown from 'vue-markdown';
13
+ import ImgView from "./imgView";
14
+ // import Typed from "typed.js";
15
+
16
+ export default {
17
+ name: "markDownText",
18
+ data() {
19
+ return {
20
+ typedContent: "",
21
+ typingSpeed: 15,
22
+ showPreview: false,
23
+ imgList: [],
24
+ isManualScroll: false,
25
+ }
26
+ },
27
+ props: {
28
+ chainValues: {
29
+ type: String,
30
+ default: ""
31
+ },
32
+ msgId: {
33
+ type: String,
34
+ default: ""
35
+ },
36
+ isHistory: {
37
+ type: Boolean,
38
+ default: false
39
+ },
40
+ streamRequestUrl: {
41
+ type: String,
42
+ default: ""
43
+ },
44
+ whetherRequestStream: {
45
+ type: Boolean,
46
+ default: false
47
+ }
48
+ },
49
+ components: {
50
+ ImgView,
51
+ VueMarkdown
52
+ },
53
+ mounted() {
54
+ this.$nextTick(() => {
55
+ console.log("this.askMassageStream: ", this.askMassageStream);
56
+ console.log("this.whetherRequestStream: ", this.whetherRequestStream);
57
+ console.log("this.streamRequestUrl: ", this.streamRequestUrl);
58
+ console.log("this.isHistory: ", this.isHistory);
59
+ if (this.isHistory) {
60
+ if (this.whetherRequestStream) {
61
+ console.log("71 新版 真 流 打字 效果");
62
+ window.addEventListener('wheel', this.handleScroll, true);
63
+ this.streamInfo(this.streamRequestUrl);
64
+ } else {
65
+ this.typedContent = this.chainValues
66
+ console.log(JSON.parse(JSON.stringify(this.typedContent)));
67
+
68
+ }
69
+
70
+ } else {
71
+ console.log("78 pre 新版 真 流 打字 效果");
72
+ // 新版 真 流 打字 效果
73
+ if (this.askMassageStream && this.whetherRequestStream && this.streamRequestUrl) {
74
+ console.log("81 新版 真 流 打字 效果");
75
+ window.addEventListener('wheel', this.handleScroll, true);
76
+ this.streamInfo(this.streamRequestUrl);
77
+ } else {
78
+ this.$emit("sseOtherInfo", this.msgId, "start", "");
79
+ // 旧版 模拟 流 打字 效果
80
+ this.typedContent = this.chainValues
81
+ // this.startTypingEffect();
82
+ }
83
+ }
84
+ })
85
+ },
86
+ methods: {
87
+ // 打字效果已在MarkdownText文件中处理
88
+ // typeNewWriter(text, keyId, msg) {
89
+ // setTimeout(() => {
90
+ // let ref = 'msgTyped' + keyId;
91
+ // const el = this.$refs[ref][0];
92
+ // new Typed(el, {
93
+ // strings: [text],
94
+ // typeSpeed: 15,
95
+ // showCursor: false,
96
+ // onComplete: () => {
97
+ // msg.isHistory = true
98
+ // this.$emit('openFirstPreview', msg)
99
+ // this.typingSuccess()
100
+ // },
101
+ // })
102
+ // }, 500)
103
+ // },
104
+ handleScroll() {
105
+ console.log("this.isManualScroll = true;");
106
+ this.isManualScroll = true;
107
+ window.removeEventListener('wheel', this.handleScroll, true);
108
+ },
109
+ scrollMarkdown(){
110
+ !this.isManualScroll && this.$nextTick(() => {
111
+ const element = document.getElementById('el_id_markdown_' + this.msgId);
112
+ if (element) {
113
+ element.scrollIntoView({ behavior: 'smooth', block: 'start' });
114
+ }
115
+ });
116
+ },
117
+ streamInfo(url){
118
+ // 通知消息列表,当前还未建立sse,先不出空消息
119
+ this.$emit("sseOtherInfo", this.msgId, "init", "");
120
+
121
+ const eventSource = new EventSource(url);
122
+ let tempString = "";
123
+ let generatingString = "";
124
+ let timer = null;
125
+ let images = [];
126
+ let matched = [];
127
+ let recommendItems = [];
128
+ let isfirstStr = false;
129
+ const backslashOrNRegex = /\n/;
130
+ eventSource.onmessage = (event) => {
131
+ const data = JSON.parse(event.data);
132
+ if (event.lastEventId === 'finish') { // 不能删除 finish
133
+ console.log("finish+++++");
134
+ } else if (event.lastEventId === '[DONE]') {
135
+ let DONETmier = setInterval(() => {
136
+ // 在所有文本内容打字效果完毕后 展示底部图片 文件 推荐等
137
+ if (generatingString == "") {
138
+ if (images.length != 0) {
139
+ setTimeout(() => {
140
+ this.$emit("sseOtherInfo", this.msgId,"images", images);
141
+ this.scrollMarkdown();
142
+ }, 50);
143
+ }
144
+ if (matched.length != 0) {
145
+ setTimeout(() => {
146
+ this.$emit("sseOtherInfo", this.msgId, "matched", matched);
147
+ this.scrollMarkdown();
148
+ }, 100);
149
+ }
150
+ if (recommendItems.length != 0) {
151
+ setTimeout(() => {
152
+ this.$emit("sseOtherInfo", this.msgId, "recommendItems", recommendItems);
153
+ this.scrollMarkdown();
154
+ }, 150);
155
+ }
156
+ clearInterval(timer);
157
+ clearInterval(DONETmier);
158
+ }
159
+ }, 100);
160
+ eventSource.close();
161
+ } else if (event.lastEventId === 'matched') {
162
+ matched = data;
163
+ } else if (event.lastEventId === 'images') {
164
+ images = data;
165
+ } else if (event.lastEventId === 'recommendItems') {
166
+ recommendItems = data;
167
+ } else {
168
+ // 设置当前知识答案id,用于loading取消和展示
169
+ this.$emit("sseOtherInfo", this.msgId, "start", "");
170
+ // 字符串中存在特定字符,本次接收消息暂不展示
171
+ if (backslashOrNRegex.test(data.content)) {
172
+ tempString += data.content;
173
+ } else {
174
+ if (!isfirstStr) {
175
+ isfirstStr = true;
176
+ timer = setInterval(() => {
177
+ if (generatingString != "") {
178
+ this.$set(this, "typedContent", this.typedContent + generatingString.charAt(0))
179
+ generatingString = generatingString.slice(1)
180
+ this.scrollMarkdown();
181
+ }
182
+ }, 20);
183
+ this.$emit("answerDocKnowledgeFn");
184
+ }
185
+ let repStr = tempString.replace(/\\n/g, '\n');
186
+ generatingString = generatingString + repStr + data.content;
187
+ tempString = "";
188
+ }
189
+ }
190
+ };
191
+
192
+ eventSource.onerror = function(err) {
193
+ console.error('EventSource failed:', err);
194
+ this.typedContent += '\nError receiving data from server.\n';
195
+ eventSource.close();
196
+ };
197
+ },
198
+ startTypingEffect() {
199
+ // 使用正则表达式将 HTML 内容按 <table> 标签分割
200
+ const segments = this.chainValues.split(/(<\/?table[\s\S]*?>[\s\S]*?<\/table>)/i);
201
+ console.log("segments: ", segments);
202
+
203
+ let segmentIndex = 0;
204
+ let i = 0;
205
+ const processNextSegment = () => {
206
+ if (segmentIndex >= segments.length) {
207
+ this.$emit('openFirstPreview')
208
+ this.$emit('typingSuccess');
209
+ return;
210
+ }
211
+ const segment = segments[segmentIndex];
212
+ if (/^<\/?table[\s\S]*?>[\s\S]*?<\/table>$/i.test(segment)) {
213
+ // 如果当前段是 <table> 标签,直接添加到 typedContent 中
214
+ this.typedContent += segment;
215
+ segmentIndex++;
216
+ processNextSegment();
217
+ } else {
218
+ i = 0;
219
+ const updateContent = () => {
220
+ if (i < segment.length) {
221
+ this.typedContent += segment.charAt(i);
222
+ i++;
223
+ // 使用 requestAnimationFrame 替代 setInterval,防止卡顿
224
+ requestAnimationFrame(updateContent);
225
+ } else {
226
+ segmentIndex++;
227
+ processNextSegment();
228
+ }
229
+ };
230
+ updateContent();
231
+ }
232
+ };
233
+ processNextSegment();
234
+ },
235
+
236
+ lookImage(e) {
237
+ let previewImageUrl = ""
238
+ console.log('e.target', e.target)
239
+ if (e.target.localName == 'img') {
240
+ previewImageUrl = e.target.currentSrc;
241
+ this.showPreview = true;
242
+ }
243
+ let richtext = JSON.parse(JSON.stringify(this.typedContent))
244
+ this.imgList = [];
245
+ richtext.replace(/<img [^>]*src=['"]([^'"]+)[^>]*>/g, (match, capture) => {
246
+ this.imgList.push(capture);
247
+ });
248
+ /*当前点击的图片作为第一个图片*/
249
+ let index = this.imgList.indexOf(previewImageUrl);
250
+ this.imgList.splice(index, 1);
251
+ this.imgList.unshift(previewImageUrl);
252
+ },
253
+ closeViewer() {
254
+ this.showPreview = false;
255
+ }
256
+ }
257
+ };
258
+ </script>
259
+
260
+ <style scoped lang="less">
261
+ .mark_down {
262
+ line-height: 24px;
263
+ overflow-x: auto;
264
+ /deep/p {
265
+ margin-bottom: 14px;
266
+ font-size: 16px;
267
+ }
268
+
269
+ /deep/p:only-child {
270
+ margin: 0 !important;
271
+ }
272
+
273
+ /deep/p:last-child {
274
+ margin-bottom: 0 !important;
275
+ }
276
+
277
+ /deep/ul {
278
+ margin-bottom: 16px;
279
+ list-style: disc;
280
+ padding-left: 40px;
281
+
282
+ li {
283
+ margin: 7px 0 !important;
284
+ font-size: 16px;
285
+ // padding-left: 40px;
286
+
287
+ }
288
+ }
289
+
290
+ /deep/ ol {
291
+ list-style: auto;
292
+ padding-left: 40px;
293
+
294
+ li {
295
+ margin: 7px 0 !important;
296
+ font-size: 16px;
297
+ // padding-left: 40px;
298
+ }
299
+ }
300
+
301
+ /deep/img {
302
+ max-width: 400px;
303
+ }
304
+
305
+ /deep/h3,
306
+ /deep/h2,
307
+ /deep/h1,
308
+ /deep/h4,
309
+ /deep/h5,
310
+ /deep/h6 {
311
+ color: #000000;
312
+ font-weight: 500;
313
+ line-height: 26px;
314
+ }
315
+
316
+ /deep/h3 {
317
+ font-size: 20px;
318
+ }
319
+
320
+ /deep/h2 {
321
+ font-size: 22px;
322
+ }
323
+
324
+ /deep/h1 {
325
+ font-size: 24px;
326
+ }
327
+
328
+ /deep/h3 {
329
+ font-size: 20px;
330
+ }
331
+
332
+
333
+ /deep/ table {
334
+ border-spacing: 0;
335
+ // border-radius: 8px;
336
+ // overflow: hidden;
337
+ border: solid 1px #e0e6f7;
338
+ min-width: 800px;
339
+ overflow-x: auto;
340
+ }
341
+
342
+ /deep/ th {
343
+ background: #EEF1FF;
344
+ border: solid 1px #e0e6f7;
345
+ padding: 8px;
346
+ height: 38px;
347
+ min-width: 100px;
348
+ }
349
+
350
+ /deep/ td {
351
+ border: solid 1px #e0e6f7;
352
+ padding: 8px;
353
+ height: 28px;
354
+ min-width: 100px;
355
+ }
356
+ }
357
+ </style>
358
358