uni-ai-msg.vue 10.4 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
				</view>
			</view>
		</view>
	</view>
DCloud_JSON's avatar
DCloud_JSON 已提交
44 45
</template>

DCloud_JSON's avatar
1.0.17  
DCloud_JSON 已提交
46 47 48 49 50 51 52 53 54
<script>
	// 引入配置文件
	import config from '@/config.js';

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

DCloud_JSON's avatar
DCloud_JSON 已提交
55 56 57 58 59 60 61
	// 引入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 已提交
62
	import parseHtml from '@/lib/html-parser.js';
63 64 65

	// console.log('hljs--',hljs);
	// console.log('hljs--',hljs.getLanguage('js'));
DCloud_JSON's avatar
1.0.17  
DCloud_JSON 已提交
66 67 68 69
	
	// 为复制代码功能保留代码内容
	let codeDataList = []
	
DCloud_JSON's avatar
DCloud_JSON 已提交
70
	// 初始化 MarkdownIt库
71
	const markdownIt = MarkdownIt({
DCloud_JSON's avatar
DCloud_JSON 已提交
72
		// 在源码中启用 HTML 标签
73
		html: true,
DCloud_JSON's avatar
DCloud_JSON 已提交
74
		// 如果结果以 <pre ... 开头内部包装器则会跳过
DCloud_JSON's avatar
1.0.18  
DCloud_JSON 已提交
75
		highlight: function(str, lang) {
76 77 78
			// if (lang && hljs.getLanguage(lang)) {
			// 	console.error('lang', lang)
			// 	try {
DCloud_JSON's avatar
1.0.17  
DCloud_JSON 已提交
79
			// 		return '<pre class="hljs" style="padding: 5px 8px;margin: 5px 0;overflow: auto;display: block;"><code>' +
80 81 82 83
			// 			hljs.highlight('lang', str, true).value +
			// 			'</code></pre>';
			// 	} catch (__) {}
			// }
DCloud_JSON's avatar
1.0.17  
DCloud_JSON 已提交
84 85
			// 经过highlight.js处理后的html
			let preCode = ""
86
			try {
DCloud_JSON's avatar
1.0.17  
DCloud_JSON 已提交
87 88 89 90 91
				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 已提交
92
			
DCloud_JSON's avatar
1.0.17  
DCloud_JSON 已提交
93 94 95 96 97 98 99 100 101 102 103
			
			// 以换行进行分割
			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 已提交
104
			html = '<ol style="padding: 0px 30px;">' + html + '</ol>'
DCloud_JSON's avatar
1.0.17  
DCloud_JSON 已提交
105
			
DCloud_JSON's avatar
1.0.18  
DCloud_JSON 已提交
106 107
			// 代码复制功能
			codeDataList.push(str)
DCloud_JSON's avatar
1.0.20  
DCloud_JSON 已提交
108 109 110 111 112 113 114 115 116
			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 已提交
117 118
		}
	})
119

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

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

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

				// #ifdef APP-NVUE
				return parseHtml(htmlString)
				// #endif
192 193
			}
		},
DCloud_JSON's avatar
1.0.21  
DCloud_JSON 已提交
194
		methods: {
DCloud_JSON's avatar
1.0.17  
DCloud_JSON 已提交
195
			trOnclick(e){
DCloud_JSON's avatar
1.0.20  
DCloud_JSON 已提交
196
				console.log(e);
DCloud_JSON's avatar
1.0.18  
DCloud_JSON 已提交
197
				let {attrs} = e.detail.node
DCloud_JSON's avatar
1.0.20  
DCloud_JSON 已提交
198
				console.log({attrs});
DCloud_JSON's avatar
1.0.18  
DCloud_JSON 已提交
199 200
				let {"code-data-index":codeDataIndex,"class":className} = attrs
				if(className == 'copy-btn'){
DCloud_JSON's avatar
1.0.23  
DCloud_JSON 已提交
201
					// console.log('codeDataList[codeDataIndex]',codeDataList[codeDataIndex]);
DCloud_JSON's avatar
1.0.18  
DCloud_JSON 已提交
202 203 204 205 206 207 208 209 210 211 212
					uni.setClipboardData({
						data:codeDataList[codeDataIndex],
						showToast:false,
						success() {
							uni.showToast({
								title: '复制成功',
								icon: 'none'
							});
						}
					})
				}
DCloud_JSON's avatar
1.0.19  
DCloud_JSON 已提交
213 214 215 216 217 218
			},
			changeAnswer(){
				this.$emit('changeAnswer')
			},
			retriesSendMsg(){
				this.$emit('retriesSendMsg')
DCloud_JSON's avatar
1.0.17  
DCloud_JSON 已提交
219
			},
DCloud_JSON's avatar
DCloud_JSON 已提交
220
			// 复制文本内容到系统剪切板
221 222
			copy() {
				uni.setClipboardData({
DCloud_JSON's avatar
1.0.21  
DCloud_JSON 已提交
223
					data: this.msgContent,
DCloud_JSON's avatar
1.0.19  
DCloud_JSON 已提交
224 225 226 227 228 229 230
					showToast: false,
					success() {
						uni.showToast({
							title: '复制成功',
							icon: 'none'
						});
					}
DCloud_JSON's avatar
1.0.23  
DCloud_JSON 已提交
231 232 233 234 235
				})
				this.showMoreMenu = false
			},
			// 删除消息
			removeMsg(){
DCloud_JSON's avatar
1.2.0  
DCloud_JSON 已提交
236
				this.$emit('removeMsg')
DCloud_JSON's avatar
1.0.23  
DCloud_JSON 已提交
237
				this.showMoreMenu = false
DCloud_JSON's avatar
1.2.0  
DCloud_JSON 已提交
238 239 240
			},
			onAdClose(e){
				this.$emit('onAdClose',e)
241
			}
242
		}
DCloud_JSON's avatar
DCloud_JSON 已提交
243 244 245
	}
</script>

DCloud_JSON's avatar
1.0.17  
DCloud_JSON 已提交
246 247 248 249 250 251 252 253 254 255 256 257 258
<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 已提交
259
		flex-direction: column;
DCloud_JSON's avatar
1.0.17  
DCloud_JSON 已提交
260 261 262 263 264 265 266 267 268 269 270 271 272
	}

	.msg-item {
		position: relative;
		width: 750rpx;
		flex-direction: column;
		padding: 0 15px;
		padding-bottom: 15px;
	}
	.avatar {
		width: 40px;
		height: 40px;
		border-radius: 2px;
DCloud_JSON's avatar
1.0.21  
DCloud_JSON 已提交
273 274
	}

DCloud_JSON's avatar
1.0.17  
DCloud_JSON 已提交
275 276 277 278 279 280 281 282 283 284 285 286 287
	.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 已提交
288 289
	.content {
		position: relative;
DCloud_JSON's avatar
1.0.17  
DCloud_JSON 已提交
290
		/* #ifndef APP-NVUE */
DCloud_JSON's avatar
1.0.23  
DCloud_JSON 已提交
291
		max-width: calc(85% - 45px);
DCloud_JSON's avatar
1.0.17  
DCloud_JSON 已提交
292 293 294 295 296 297 298 299 300
		/* #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;
DCloud_JSON's avatar
1.2.0  
DCloud_JSON 已提交
301 302
		/* #endif */
		flex-direction: column;
DCloud_JSON's avatar
1.0.19  
DCloud_JSON 已提交
303 304
	}
	
DCloud_JSON's avatar
1.0.23  
DCloud_JSON 已提交
305
	.menu-box {
DCloud_JSON's avatar
1.0.19  
DCloud_JSON 已提交
306
		position: absolute;
DCloud_JSON's avatar
1.0.23  
DCloud_JSON 已提交
307
		left: -18px;
DCloud_JSON's avatar
1.0.19  
DCloud_JSON 已提交
308 309 310 311 312 313 314
		bottom: 0;
		width: 20px;
		flex-direction: column;
		height: 40px;
		justify-content: flex-end;
	}
	
DCloud_JSON's avatar
1.0.23  
DCloud_JSON 已提交
315 316 317 318 319 320
	.menu-box-ai {
		left: auto;
		right: -20px;
	}
	
	.change-answer {
DCloud_JSON's avatar
1.0.19  
DCloud_JSON 已提交
321 322 323 324 325
		font-size: 26px;
		color: #d4d4d4;
		height: 25px;
		line-height: 15px;
		margin-bottom: 5px;
DCloud_JSON's avatar
1.0.23  
DCloud_JSON 已提交
326 327
		position: relative;
		left: 2px;
DCloud_JSON's avatar
1.0.19  
DCloud_JSON 已提交
328
	}
DCloud_JSON's avatar
1.0.23  
DCloud_JSON 已提交
329 330 331 332 333 334
	
	.pointer {
		cursor: pointer;
	}
	
	.pointer:hover {
DCloud_JSON's avatar
1.0.19  
DCloud_JSON 已提交
335 336 337
		color: #BBB;
	}
	
DCloud_JSON's avatar
1.0.23  
DCloud_JSON 已提交
338 339 340
	.more-icon-box {
		justify-content: center;
		overflow: hidden;
DCloud_JSON's avatar
1.0.19  
DCloud_JSON 已提交
341 342
	}
	
DCloud_JSON's avatar
1.0.23  
DCloud_JSON 已提交
343 344
	.more-icon {
		color: #d4d4d4;
DCloud_JSON's avatar
1.1.0  
DCloud_JSON 已提交
345
		transform: rotate(270deg);
DCloud_JSON's avatar
1.0.19  
DCloud_JSON 已提交
346
		position: relative;
DCloud_JSON's avatar
1.1.0  
DCloud_JSON 已提交
347
		left: -8px;
DCloud_JSON's avatar
1.0.23  
DCloud_JSON 已提交
348 349
		font-size: 16px;
		z-index: 999;
DCloud_JSON's avatar
1.1.0  
DCloud_JSON 已提交
350 351 352 353 354 355 356 357
		padding-bottom: 5px;
		height: 10px;
	}
	
	.menu-box-ai .more-icon{
		left: 7px;
		top: -2px;
		transform: rotate(90deg);
DCloud_JSON's avatar
1.0.23  
DCloud_JSON 已提交
358 359 360 361 362 363 364 365 366 367 368 369 370 371 372
	}
	
	.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 已提交
373 374
	}
	
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 393 394 395 396 397
	.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 已提交
398 399 400 401 402 403 404
	.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 已提交
405 406
		left: 3px;
		top: 4px;
DCloud_JSON's avatar
1.0.19  
DCloud_JSON 已提交
407 408
		border-radius: 3px;
	}
DCloud_JSON's avatar
1.0.23  
DCloud_JSON 已提交
409 410 411 412
	.copy-icon-b {
		top: 8px;
		left: 6px;
	}
DCloud_JSON's avatar
1.0.19  
DCloud_JSON 已提交
413 414 415 416
	.copy-icon:hover .copy-icon-a,
	.copy-icon:hover .copy-icon-b,{
		border-color:#bbb;
	}
DCloud_JSON's avatar
1.0.23  
DCloud_JSON 已提交
417 418 419 420 421 422 423 424 425 426 427
	
	
	.remove-msg {
		position: relative;
		opacity: 0.7;
	}
	
	.remove-msg:hover{
		opacity: 1;
	}
	
DCloud_JSON's avatar
1.0.17  
DCloud_JSON 已提交
428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459

	/* #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 已提交
460 461 462 463 464 465 466
	}
	
	/* #ifdef H5 */
	a.copy-btn:hover {
	    color: #259939;
	}
	/* #endif */
DCloud_JSON's avatar
1.0.17  
DCloud_JSON 已提交
467 468


DCloud_JSON's avatar
DCloud_JSON 已提交
469 470
	/* #ifndef VUE3 && APP-PLUS */
	@import "@/components/uni-ai-msg/uni-ai-msg.scss";
DCloud_JSON's avatar
1.0.17  
DCloud_JSON 已提交
471
	/* #endif */
DCloud_JSON's avatar
DCloud_JSON 已提交
472
</style>