uni-ai-msg.vue 10.9 KB
Newer Older
DCloud_JSON's avatar
1.0.17  
DCloud_JSON 已提交
1
<template>
DCloud_JSON's avatar
1.0.23  
DCloud_JSON 已提交
2
	<view class="msg-item" v-if="!msg.isDelete">
DCloud_JSON's avatar
1.0.17  
DCloud_JSON 已提交
3 4 5 6 7
		<view class="create_time-box">
			<uni-dateformat class="create_time" :date="msg.create_time" format="MM/dd hh:mm:ss"></uni-dateformat>
		</view>
		<view :class="{reverse:!msg.isAi}">
			<view class="userInfo">
DCloud_JSON's avatar
1.0.21  
DCloud_JSON 已提交
8
				<image class="avatar" :src="msg.isAi?'../../static/uni-ai.png':'../../static/avatar.png'" mode="widthFix"></image>
DCloud_JSON's avatar
1.0.17  
DCloud_JSON 已提交
9 10
			</view>
			<view class="content">
DCloud_JSON's avatar
1.0.21  
DCloud_JSON 已提交
11
				<view v-if="msg.isAi" class="rich-text-box" :class="{'show-cursor':showCursor}" ref="rich-text-box">
DCloud_JSON's avatar
1.0.17  
DCloud_JSON 已提交
12
					<rich-text v-if="nodes&&nodes.length" space="nbsp" :nodes="nodes" @itemclick="trOnclick"></rich-text>
DCloud_JSON's avatar
1.0.19  
DCloud_JSON 已提交
13
				</view>
DCloud_JSON's avatar
1.0.21  
DCloud_JSON 已提交
14 15 16 17
				<view v-else>
					{{msgContent}}
				</view>
				
DCloud_JSON's avatar
1.0.19  
DCloud_JSON 已提交
18 19 20 21 22 23 24
				<view v-if="isLastMsg && adpid && msg.insufficientScore">
					<text style="color: red;">
						默认不启用广告组件(被注释),如需使用,请"去掉注释"(“重新运行”后生效)
						位置:/components/uni-ai-msg/uni-ai-msg.vue 第28行,或全局搜索 uni-ad-rewarded-video
					</text>
					<!-- <uni-ad-rewarded-video :adpid="adpid" @onAdClose="onAdClose"></uni-ad-rewarded-video> -->
				</view>
DCloud_JSON's avatar
1.0.23  
DCloud_JSON 已提交
25 26 27 28
				<view class="menu-box" :class='{"menu-box-ai":msg.isAi}'>
					<text v-if="isLastMsg && msg.isAi" title="换一个答案" @click="changeAnswer" class="pointer change-answer"></text>
					<view @click="showMoreMenu = !showMoreMenu" class="more-icon-box">
						<text class="more-icon pointer">...</text>
DCloud_JSON's avatar
1.0.19  
DCloud_JSON 已提交
29
					</view>
DCloud_JSON's avatar
1.0.23  
DCloud_JSON 已提交
30 31 32 33 34 35 36 37 38 39
					<template v-if="showMoreMenu">
						<view class="more-menu">
							<view @click="copy" title="复制" class="copy-icon pointer">
								<view class="copy-icon-a"></view>
								<view class="copy-icon-b"></view>
							</view>
							<uni-icons class="remove-msg pointer" @click="removeMsg" type="trash" size="20" color="#bbb"></uni-icons>
						</view>
						<view class="more-menu-mask" @click="showMoreMenu = false"></view>
					</template>
DCloud_JSON's avatar
1.0.17  
DCloud_JSON 已提交
40 41 42 43 44 45 46 47
				</view>
			</view>
			<uni-icons v-if="isLastMsg && !msg.isAi && msg.state != 100 && msgStateIcon(msg)"
				@click="msg.state == -100 ? retriesSendMsg() : ''" :color="msg.state===0?'#999':'#d22'"
				:type="msgStateIcon(msg)" class="msgStateIcon">
			</uni-icons>
		</view>
	</view>
DCloud_JSON's avatar
DCloud_JSON 已提交
48 49
</template>

DCloud_JSON's avatar
1.0.17  
DCloud_JSON 已提交
50 51 52 53 54 55 56 57 58 59 60 61 62
<script>
	// 引入配置文件
	import config from '@/config.js';

	// 获取广告id
	const {
		adpid
	} = config

	import {
		msgList
	} from '@/pages/chat/msgList.js';

DCloud_JSON's avatar
DCloud_JSON 已提交
63 64 65 66 67 68 69
	// 引入markdown-it库
	import MarkdownIt from '@/lib/markdown-it.min.js';

	// hljs是由 Highlight.js 经兼容性修改后的文件,请勿直接升级。否则会造成uni-app-vue3-Android下有兼容问题
	import hljs from "@/lib/highlight/highlight-uni.min.js";

	// 引入html-parser.js库
DCloud_JSON's avatar
1.0.17  
DCloud_JSON 已提交
70
	import parseHtml from '@/lib/html-parser.js';
71 72 73

	// console.log('hljs--',hljs);
	// console.log('hljs--',hljs.getLanguage('js'));
DCloud_JSON's avatar
1.0.17  
DCloud_JSON 已提交
74 75 76 77
	
	// 为复制代码功能保留代码内容
	let codeDataList = []
	
DCloud_JSON's avatar
DCloud_JSON 已提交
78
	// 初始化 MarkdownIt库
79
	const markdownIt = MarkdownIt({
DCloud_JSON's avatar
DCloud_JSON 已提交
80
		// 在源码中启用 HTML 标签
81
		html: true,
DCloud_JSON's avatar
DCloud_JSON 已提交
82
		// 如果结果以 <pre ... 开头内部包装器则会跳过
DCloud_JSON's avatar
1.0.18  
DCloud_JSON 已提交
83
		highlight: function(str, lang) {
84 85 86
			// if (lang && hljs.getLanguage(lang)) {
			// 	console.error('lang', lang)
			// 	try {
DCloud_JSON's avatar
1.0.17  
DCloud_JSON 已提交
87
			// 		return '<pre class="hljs" style="padding: 5px 8px;margin: 5px 0;overflow: auto;display: block;"><code>' +
88 89 90 91
			// 			hljs.highlight('lang', str, true).value +
			// 			'</code></pre>';
			// 	} catch (__) {}
			// }
DCloud_JSON's avatar
1.0.17  
DCloud_JSON 已提交
92 93
			// 经过highlight.js处理后的html
			let preCode = ""
94
			try {
DCloud_JSON's avatar
1.0.17  
DCloud_JSON 已提交
95 96 97 98 99
				preCode = hljs.highlightAuto(str).value
			} catch (err) {
				// console.log('err',err);
				preCode = markdownIt.utils.escapeHtml(str);
			}
DCloud_JSON's avatar
1.0.20  
DCloud_JSON 已提交
100
			
DCloud_JSON's avatar
1.0.17  
DCloud_JSON 已提交
101 102 103 104 105 106 107 108 109 110 111
			
			// 以换行进行分割
			const lines = preCode.split(/\n/).slice(0, -1)
			// 添加自定义行号
			let html = lines.map((item, index) => {
				// 去掉空行
				if( item == ''){
					return ''
				}
				return '<li><span class="line-num" data-line="' + (index + 1) + '"></span>' + item +'</li>'
			}).join('')
DCloud_JSON's avatar
1.0.20  
DCloud_JSON 已提交
112
			html = '<ol style="padding: 0px 30px;">' + html + '</ol>'
DCloud_JSON's avatar
1.0.17  
DCloud_JSON 已提交
113
			
DCloud_JSON's avatar
1.0.18  
DCloud_JSON 已提交
114 115
			// 代码复制功能
			codeDataList.push(str)
DCloud_JSON's avatar
1.0.20  
DCloud_JSON 已提交
116 117 118 119 120 121 122 123 124
			let htmlCode = `<div style="background:#0d1117;margin-top: 5px;color: #888;padding:5px 0;border-radius: 5px;">`
				// #ifndef MP-WEIXIN
					htmlCode += `<div style="text-align: end;font-size: 12px;">`
						htmlCode += `${lang}<a class="copy-btn" code-data-index="${codeDataList.length - 1}" style="cursor: pointer;"> 复制代码 </a>`
					htmlCode += `</div>`
				// #endif
					htmlCode += `<pre class="hljs" style="padding:0 8px;margin-bottom:5px;overflow: auto;display: block;border-radius: 5px;"><code>${html}</code></pre>`;
				htmlCode += '</div>'
			return htmlCode
DCloud_JSON's avatar
1.0.17  
DCloud_JSON 已提交
125 126
		}
	})
127

DCloud_JSON's avatar
DCloud_JSON 已提交
128 129 130
	export default {
		name: "msg",
		data() {
DCloud_JSON's avatar
1.0.17  
DCloud_JSON 已提交
131
			return {
DCloud_JSON's avatar
DCloud_JSON 已提交
132
				// 悬浮的复制按钮的左边距
133
				left: "-100px",
DCloud_JSON's avatar
DCloud_JSON 已提交
134
				// 悬浮的复制按钮的上边距
DCloud_JSON's avatar
1.0.17  
DCloud_JSON 已提交
135 136
				top: "-100px",
				msg: {
DCloud_JSON's avatar
1.0.23  
DCloud_JSON 已提交
137 138
					content: "",
					isDelete:false
DCloud_JSON's avatar
1.0.17  
DCloud_JSON 已提交
139 140
				},
				msgIndexList: 0,
DCloud_JSON's avatar
1.0.23  
DCloud_JSON 已提交
141 142
				adpid,
				showMoreMenu:false
DCloud_JSON's avatar
1.0.0  
DCloud_JSON 已提交
143
			};
DCloud_JSON's avatar
1.0.17  
DCloud_JSON 已提交
144
		},
145
		mounted() {
DCloud_JSON's avatar
1.0.17  
DCloud_JSON 已提交
146 147 148
		},
		created() {
			this.msg = msgList[this.msgIndex]
DCloud_JSON's avatar
DCloud_JSON 已提交
149 150
		},
		props: {
DCloud_JSON's avatar
DCloud_JSON 已提交
151
			// 是否显示鼠标闪烁的效果
152 153 154 155 156
			showCursor: {
				type: [Boolean, Number],
				default () {
					return false
				}
DCloud_JSON's avatar
1.0.17  
DCloud_JSON 已提交
157 158
			},
			msgIndex: {
DCloud_JSON's avatar
1.0.12  
DCloud_JSON 已提交
159 160 161 162
				type: Number,
				default () {
					return false
				}
DCloud_JSON's avatar
1.0.17  
DCloud_JSON 已提交
163 164 165 166 167 168
			},
			isLastMsg: {
				type: Boolean,
				default () {
					return false
				}
DCloud_JSON's avatar
1.0.21  
DCloud_JSON 已提交
169
			}
DCloud_JSON's avatar
DCloud_JSON 已提交
170
		},
DCloud_JSON's avatar
1.0.17  
DCloud_JSON 已提交
171
		computed: {
DCloud_JSON's avatar
1.0.21  
DCloud_JSON 已提交
172
			msgContent() {
DCloud_JSON's avatar
1.0.17  
DCloud_JSON 已提交
173
				return this.msg.content
DCloud_JSON's avatar
1.0.12  
DCloud_JSON 已提交
174
			},
DCloud_JSON's avatar
1.0.17  
DCloud_JSON 已提交
175 176 177 178
			nodes() {
				let htmlString = ''
				// 修改转换结果的htmlString值 用于正确给界面增加鼠标闪烁的效果
				// 判断markdown中代码块标识符的数量是否为偶数
DCloud_JSON's avatar
1.0.21  
DCloud_JSON 已提交
179
				if (this.msgContent.split("```").length % 2) {
DCloud_JSON's avatar
1.0.23  
DCloud_JSON 已提交
180
					htmlString = markdownIt.render(this.msgContent)+ '<span class="cursor">|</span>';
DCloud_JSON's avatar
1.0.17  
DCloud_JSON 已提交
181
				} else {
DCloud_JSON's avatar
1.0.21  
DCloud_JSON 已提交
182
					htmlString = markdownIt.render(this.msgContent) + ' \n <span class="cursor">|</span>';
DCloud_JSON's avatar
1.0.17  
DCloud_JSON 已提交
183 184 185 186 187 188 189 190 191 192 193 194
				}

				// #ifndef APP-NVUE
				return htmlString
				// #endif

				// nvue模式下将htmlString转成htmlArray,其他情况rich-text内部转
				// 注:本示例项目还没使用nvue编译

				// #ifdef APP-NVUE
				return parseHtml(htmlString)
				// #endif
195 196
			}
		},
DCloud_JSON's avatar
1.0.21  
DCloud_JSON 已提交
197
		methods: {
DCloud_JSON's avatar
1.0.17  
DCloud_JSON 已提交
198 199 200 201 202
			// 根据消息状态返回对应的图标
			msgStateIcon(msg) {
				switch (msg.state) {
					case 0:
						//	发送中
DCloud_JSON's avatar
1.0.19  
DCloud_JSON 已提交
203
						return ''
DCloud_JSON's avatar
1.0.17  
DCloud_JSON 已提交
204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219
						break;
					case -100:
						//	发送失败
						return 'refresh-filled'
						break;
					case -200:
						//	禁止发送(内容不合法)
						return 'info-filled'
						break;
					default:
						// 默认不返回任何图标
						return false
						break;
				}
			},
			trOnclick(e){
DCloud_JSON's avatar
1.0.20  
DCloud_JSON 已提交
220
				console.log(e);
DCloud_JSON's avatar
1.0.18  
DCloud_JSON 已提交
221
				let {attrs} = e.detail.node
DCloud_JSON's avatar
1.0.20  
DCloud_JSON 已提交
222
				console.log({attrs});
DCloud_JSON's avatar
1.0.18  
DCloud_JSON 已提交
223 224
				let {"code-data-index":codeDataIndex,"class":className} = attrs
				if(className == 'copy-btn'){
DCloud_JSON's avatar
1.0.23  
DCloud_JSON 已提交
225
					// console.log('codeDataList[codeDataIndex]',codeDataList[codeDataIndex]);
DCloud_JSON's avatar
1.0.18  
DCloud_JSON 已提交
226 227 228 229 230 231 232 233 234 235 236
					uni.setClipboardData({
						data:codeDataList[codeDataIndex],
						showToast:false,
						success() {
							uni.showToast({
								title: '复制成功',
								icon: 'none'
							});
						}
					})
				}
DCloud_JSON's avatar
1.0.19  
DCloud_JSON 已提交
237 238 239 240 241 242
			},
			changeAnswer(){
				this.$emit('changeAnswer')
			},
			retriesSendMsg(){
				this.$emit('retriesSendMsg')
DCloud_JSON's avatar
1.0.17  
DCloud_JSON 已提交
243
			},
DCloud_JSON's avatar
DCloud_JSON 已提交
244
			// 复制文本内容到系统剪切板
245 246
			copy() {
				uni.setClipboardData({
DCloud_JSON's avatar
1.0.21  
DCloud_JSON 已提交
247
					data: this.msgContent,
DCloud_JSON's avatar
1.0.19  
DCloud_JSON 已提交
248 249 250 251 252 253 254
					showToast: false,
					success() {
						uni.showToast({
							title: '复制成功',
							icon: 'none'
						});
					}
DCloud_JSON's avatar
1.0.23  
DCloud_JSON 已提交
255 256 257 258 259 260 261
				})
				this.showMoreMenu = false
			},
			// 删除消息
			removeMsg(){
				this.$emit('removeMsg',this.msgIndex)
				this.showMoreMenu = false
262
			}
263
		}
DCloud_JSON's avatar
DCloud_JSON 已提交
264 265 266
	}
</script>

DCloud_JSON's avatar
1.0.17  
DCloud_JSON 已提交
267 268 269 270 271 272 273 274 275 276 277 278 279
<style lang="scss">
	/* #ifndef APP-NVUE */
	view,
	textarea,
	button,
	.page {
		display: flex;
		box-sizing: border-box;
	}

	/* #endif */

	.userInfo {
DCloud_JSON's avatar
1.0.21  
DCloud_JSON 已提交
280
		flex-direction: column;
DCloud_JSON's avatar
1.0.17  
DCloud_JSON 已提交
281 282 283 284 285 286 287 288 289 290 291 292
	}

	.msg-item {
		position: relative;
		width: 750rpx;
		flex-direction: column;
		padding: 0 15px;
		padding-bottom: 15px;
	}

	.msgStateIcon {
		position: relative;
DCloud_JSON's avatar
1.0.23  
DCloud_JSON 已提交
293 294
		top: -5px;
		right: 1px;
DCloud_JSON's avatar
1.0.17  
DCloud_JSON 已提交
295 296 297 298 299 300 301
		align-self: center;
	}

	.avatar {
		width: 40px;
		height: 40px;
		border-radius: 2px;
DCloud_JSON's avatar
1.0.21  
DCloud_JSON 已提交
302 303
	}

DCloud_JSON's avatar
1.0.17  
DCloud_JSON 已提交
304 305 306 307 308 309 310 311 312 313 314 315 316
	.create_time {
		font-size: 12px;
		padding: 5px 0;
		padding-top: 0;
		color: #aaa;
		text-align: center;
		width: 750rpx;
		/* #ifdef MP */
		display: flex;
		/* #endif */
		justify-content: center;
	}

DCloud_JSON's avatar
1.0.19  
DCloud_JSON 已提交
317 318
	.content {
		position: relative;
DCloud_JSON's avatar
1.0.17  
DCloud_JSON 已提交
319
		/* #ifndef APP-NVUE */
DCloud_JSON's avatar
1.0.23  
DCloud_JSON 已提交
320
		max-width: calc(85% - 45px);
DCloud_JSON's avatar
1.0.17  
DCloud_JSON 已提交
321 322 323 324 325 326 327 328 329 330
		/* #endif */
		background-color: #FFF;
		border-radius: 5px;
		padding: 12px 10px;
		margin-left: 10px;
		/* #ifndef APP-NVUE */
		word-break: break-all;
		user-select: text;
		cursor: text;
		/* #endif */
DCloud_JSON's avatar
1.0.19  
DCloud_JSON 已提交
331 332
	}
	
DCloud_JSON's avatar
1.0.23  
DCloud_JSON 已提交
333
	.menu-box {
DCloud_JSON's avatar
1.0.19  
DCloud_JSON 已提交
334
		position: absolute;
DCloud_JSON's avatar
1.0.23  
DCloud_JSON 已提交
335
		left: -18px;
DCloud_JSON's avatar
1.0.19  
DCloud_JSON 已提交
336 337 338 339 340 341 342
		bottom: 0;
		width: 20px;
		flex-direction: column;
		height: 40px;
		justify-content: flex-end;
	}
	
DCloud_JSON's avatar
1.0.23  
DCloud_JSON 已提交
343 344 345 346 347 348
	.menu-box-ai {
		left: auto;
		right: -20px;
	}
	
	.change-answer {
DCloud_JSON's avatar
1.0.19  
DCloud_JSON 已提交
349 350 351 352 353
		font-size: 26px;
		color: #d4d4d4;
		height: 25px;
		line-height: 15px;
		margin-bottom: 5px;
DCloud_JSON's avatar
1.0.23  
DCloud_JSON 已提交
354 355
		position: relative;
		left: 2px;
DCloud_JSON's avatar
1.0.19  
DCloud_JSON 已提交
356
	}
DCloud_JSON's avatar
1.0.23  
DCloud_JSON 已提交
357 358 359 360 361 362
	
	.pointer {
		cursor: pointer;
	}
	
	.pointer:hover {
DCloud_JSON's avatar
1.0.19  
DCloud_JSON 已提交
363 364 365
		color: #BBB;
	}
	
DCloud_JSON's avatar
1.0.23  
DCloud_JSON 已提交
366 367 368
	.more-icon-box {
		justify-content: center;
		overflow: hidden;
DCloud_JSON's avatar
1.0.19  
DCloud_JSON 已提交
369 370
	}
	
DCloud_JSON's avatar
1.0.23  
DCloud_JSON 已提交
371 372 373
	.more-icon {
		color: #d4d4d4;
		transform: rotate(90deg);
DCloud_JSON's avatar
1.0.19  
DCloud_JSON 已提交
374
		position: relative;
DCloud_JSON's avatar
1.0.23  
DCloud_JSON 已提交
375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392
		left: 4px;
		font-size: 16px;
		z-index: 999;
	}
	
	.more-menu {
		position: absolute;
		bottom:-10px;
		left:-30px;
		flex-direction: column;
		justify-content: space-around;
		width: 30px;
		padding: 2px 5px;
		height: 60px;
		z-index: 999;
		background-color: #FFF;
		box-shadow: 0 0 20px #eee;
		border-radius: 3px;
DCloud_JSON's avatar
1.0.19  
DCloud_JSON 已提交
393 394
	}
	
DCloud_JSON's avatar
1.0.23  
DCloud_JSON 已提交
395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417
	.more-menu-mask {
		position: fixed;
		width: 100vw;
		height: 100vh;
		top: 0;
		left: 0;
		z-index: 998;
	}
	
	.menu-box-ai .more-menu {
		left:auto;
		right: -32px;
	}
	
	.more-menu .pointer{
		width: 20px;
	}
	
	.copy-icon{
		position: relative;
		height: 25px;
		width: 20px;
	}
DCloud_JSON's avatar
1.0.19  
DCloud_JSON 已提交
418 419 420 421 422 423 424
	.copy-icon-a,
	.copy-icon-b {
		position: absolute;
		border: 1.5px solid #d4d4d4;
		width: 10px;
		height: 12px;
		background-color: #FFF;
DCloud_JSON's avatar
1.0.23  
DCloud_JSON 已提交
425 426
		left: 3px;
		top: 4px;
DCloud_JSON's avatar
1.0.19  
DCloud_JSON 已提交
427 428
		border-radius: 3px;
	}
DCloud_JSON's avatar
1.0.23  
DCloud_JSON 已提交
429 430 431 432
	.copy-icon-b {
		top: 8px;
		left: 6px;
	}
DCloud_JSON's avatar
1.0.19  
DCloud_JSON 已提交
433 434 435 436
	.copy-icon:hover .copy-icon-a,
	.copy-icon:hover .copy-icon-b,{
		border-color:#bbb;
	}
DCloud_JSON's avatar
1.0.23  
DCloud_JSON 已提交
437 438 439 440 441 442 443 444 445 446 447
	
	
	.remove-msg {
		position: relative;
		opacity: 0.7;
	}
	
	.remove-msg:hover{
		opacity: 1;
	}
	
DCloud_JSON's avatar
1.0.17  
DCloud_JSON 已提交
448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479

	/* #ifndef APP-NVUE */
	.content ::v-deep rich-text {
		max-width: 100%;
		overflow: auto;
	}
	code .l:before {
		color: #516363;
		position: absolute;
		left: 15px;
		content: counter(step);
		counter-increment: step;
	}
	/* #endif */


	.reverse {
		flex-direction: row-reverse;
	}

	.reverse .content {
		margin-left: 0;
		margin-right: 10px;
	}

	.reverse-align {
		align-items: flex-end;
	}

	.create_time-box {
		margin-top: 15px;
		justify-content: center;
DCloud_JSON's avatar
1.0.20  
DCloud_JSON 已提交
480 481 482 483 484 485 486
	}
	
	/* #ifdef H5 */
	a.copy-btn:hover {
	    color: #259939;
	}
	/* #endif */
DCloud_JSON's avatar
1.0.17  
DCloud_JSON 已提交
487 488


DCloud_JSON's avatar
DCloud_JSON 已提交
489 490
	/* #ifndef VUE3 && APP-PLUS */
	@import "@/components/uni-ai-msg/uni-ai-msg.scss";
DCloud_JSON's avatar
1.0.17  
DCloud_JSON 已提交
491
	/* #endif */
DCloud_JSON's avatar
DCloud_JSON 已提交
492
</style>