uni-ai-msg.vue 4.2 KB
Newer Older
1 2
<template>
	<view class="rich-text-box" :class="{'show-cursor':showCursor}" ref="rich-text-box">
DCloud_JSON's avatar
1.0.11  
DCloud_JSON 已提交
3
		<rich-text v-if="nodes&&nodes.length" space="nbsp" :nodes="nodes"></rich-text>
4 5 6 7 8 9 10

		<!-- #ifdef H5 -->
		<view class="copy-box" :style="{left,top}">
			<text class="copy" @click="copy">复制</text>
			<!-- <view v-if="left != '-100px'" class="copy-mask" @click="left = '-100px'"></view> -->
		</view>
		<!-- #endif -->
DCloud_JSON's avatar
DCloud_JSON 已提交
11 12 13 14
	</view>
</template>

<script>
DCloud_JSON's avatar
DCloud_JSON 已提交
15 16 17 18 19 20 21 22
	// 引入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库
	import parseHtml from '@/lib/html-parser.js'; 
23 24 25

	// console.log('hljs--',hljs);
	// console.log('hljs--',hljs.getLanguage('js'));
26

DCloud_JSON's avatar
DCloud_JSON 已提交
27
	// 初始化 MarkdownIt库
28
	const markdownIt = MarkdownIt({
DCloud_JSON's avatar
DCloud_JSON 已提交
29
		// 在源码中启用 HTML 标签
30
		html: true,
DCloud_JSON's avatar
DCloud_JSON 已提交
31
		// 如果结果以 <pre ... 开头内部包装器则会跳过
DCloud_JSON's avatar
DCloud_JSON 已提交
32
		highlight: function(str, lang) {
33 34 35 36 37 38 39 40 41 42 43 44 45 46
			// if (lang && hljs.getLanguage(lang)) {
			// 	console.error('lang', lang)
			// 	try {
			// 		return '<pre class="hljs" style="padding: 5px 8px;margin: 5px 0;overflow: auto;"><code>' +
			// 			hljs.highlight('lang', str, true).value +
			// 			'</code></pre>';
			// 	} catch (__) {}
			// }

			try {
				return '<pre class="hljs" style="padding: 5px 8px;margin: 5px 0;overflow: auto;"><code>' +
					hljs.highlightAuto(str).value +
					'</code></pre>';
			} catch (__) {}
47

48 49
			return '<pre class="hljs" style="padding: 5px 8px;margin: 5px 0;overflow: auto;"><code>' +
				markdownIt.utils.escapeHtml(str) + '</code></pre>';
DCloud_JSON's avatar
1.0.11  
DCloud_JSON 已提交
50 51 52
		}
	})
	
DCloud_JSON's avatar
DCloud_JSON 已提交
53 54 55
	export default {
		name: "msg",
		data() {
56
			return {
DCloud_JSON's avatar
DCloud_JSON 已提交
57
				// 悬浮的复制按钮的左边距
58
				left: "-100px",
DCloud_JSON's avatar
DCloud_JSON 已提交
59
				// 悬浮的复制按钮的上边距
DCloud_JSON's avatar
1.0.11  
DCloud_JSON 已提交
60
				top: "-100px"
DCloud_JSON's avatar
1.0.0  
DCloud_JSON 已提交
61
			};
62 63 64 65 66 67
		},
		mounted() {
			// #ifdef H5
			// web端限制不选中文字时出现系统右键菜单
			let richTextBox = this.$refs['rich-text-box']
			if (richTextBox) {
DCloud_JSON's avatar
DCloud_JSON 已提交
68
				// 监听鼠标右键事件
69
				richTextBox.$el.addEventListener('contextmenu', (e) => {
DCloud_JSON's avatar
DCloud_JSON 已提交
70
					// 判断是否选中了文字内容,如果没有则限制系统默认行为(禁止弹出右键菜单)
71
					if (!document.getSelection().toString()) {
72
						// console.log(e);
DCloud_JSON's avatar
DCloud_JSON 已提交
73
						// 设置悬浮的复制按钮的坐标值
74 75 76
						this.top = e.y + 'px'
						this.left = e.x + 'px'

77 78
						// console.log(e.x);
						// console.log(e.y);
DCloud_JSON's avatar
DCloud_JSON 已提交
79
						// 禁止系统默认行为(禁止弹出右键菜单)
80 81 82 83
						e.preventDefault()
					}
				})
			}
DCloud_JSON's avatar
DCloud_JSON 已提交
84
			// 监听全局点击事件,隐藏悬浮的复制按钮的坐标
85 86 87 88
			document.addEventListener('click', () => {
				this.left = "-100px"
			})
			// #endif
DCloud_JSON's avatar
DCloud_JSON 已提交
89 90
		},
		props: {
DCloud_JSON's avatar
DCloud_JSON 已提交
91
			// 传入的markdown内容
DCloud_JSON's avatar
DCloud_JSON 已提交
92 93 94
			md: {
				type: String,
				default () {
95
					return ''
DCloud_JSON's avatar
DCloud_JSON 已提交
96 97
				}
			},
DCloud_JSON's avatar
DCloud_JSON 已提交
98
			// 是否显示鼠标闪烁的效果
99 100 101 102 103 104
			showCursor: {
				type: [Boolean, Number],
				default () {
					return false
				}
			}
DCloud_JSON's avatar
DCloud_JSON 已提交
105 106
		},
		computed: {
DCloud_JSON's avatar
1.0.11  
DCloud_JSON 已提交
107 108 109 110
			nodes() {
				let htmlString = ''
				// 修改转换结果的htmlString值 用于正确给界面增加鼠标闪烁的效果
				// 判断markdown中代码块标识符的数量是否为偶数
111
				if(this.md.split("```").length%2){
DCloud_JSON's avatar
1.0.11  
DCloud_JSON 已提交
112 113 114
					htmlString = markdownIt.render(this.md + ' \n <span class="cursor">|</span>');
				}else{
					htmlString = markdownIt.render(this.md) + ' \n <span class="cursor">|</span>';
115 116
				}
				
DCloud_JSON's avatar
1.0.11  
DCloud_JSON 已提交
117 118
				// #ifndef APP-NVUE
				return htmlString
119 120
				// #endif
				
DCloud_JSON's avatar
1.0.11  
DCloud_JSON 已提交
121 122 123 124 125
				// nvue模式下将htmlString转成htmlArray,其他情况rich-text内部转
				// 注:本示例项目还没使用nvue编译
				
				// #ifdef APP-NVUE
				return parseHtml(htmlString)
126
				// #endif
127 128
			}
		},
DCloud_JSON's avatar
1.0.11  
DCloud_JSON 已提交
129
		methods: {
130
			// #ifdef H5
DCloud_JSON's avatar
DCloud_JSON 已提交
131
			// 复制文本内容到系统剪切板
132 133 134 135 136
			copy() {
				uni.setClipboardData({
					data: this.md,
					showToast: false,
				})
DCloud_JSON's avatar
DCloud_JSON 已提交
137
				// 设置悬浮的复制按钮的坐标值,使其隐藏
138 139 140
				this.left = "-100px"
			}
			// #endif
141
		}
DCloud_JSON's avatar
DCloud_JSON 已提交
142 143 144 145
	}
</script>

<style lang="scss">
DCloud_JSON's avatar
DCloud_JSON 已提交
146 147
	/* #ifndef VUE3 && APP-PLUS */
	@import "@/components/uni-ai-msg/uni-ai-msg.scss";
148
	/* #endif */
DCloud_JSON's avatar
DCloud_JSON 已提交
149
</style>