Recientemente, estoy intentando usar uniapp+vue3 para desarrollar una función de sesión de chatgpt de imitación.
Como se muestra arriba: después de la prueba, el análisis de sintaxis de rebajas es compatible con h5/lado de la aplicación/lado del mini programa . Después de levantar el teclado, no se levantará toda la página ni la barra de navegación personalizada superior.
análisis de rebajas de uniapp y resaltado de sintaxis
markdown-it
Los complementos y se utilizan highlight.js
para implementar el análisis de sintaxis de rebajas y el resaltado de código.
// 引入uniapp markdown插件
import MarkdownIt from '@/plugins/markdown-it.min.js'
import hljs from '@/plugins/highlight/highlight.min.js'
// import '@/plugins/highlight/github-dark.min.css'
import '@/plugins/highlight/atom-one-light.css'
import parseHtml from '@/plugins/html-parser.js'
- Inicializar el complemento de rebajas
const markdown = MarkdownIt({
html: true,
highlight: function(str, lang) {
let preCode = ""
try {
preCode = hljs.highlightAuto(str).value
} catch (err) {
preCode = markdown.utils.escapeHtml(str);
}
// 自定义行号
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('')
html = '<ol style="padding: 0px 30px;">' + html + '</ol>'
// 代码复制
copyCode.push(str)
let htmlCode = `<div class="markdown-wrap">`
// #ifndef MP-WEIXIN
htmlCode += `<div style="color: #aaa;text-align: right;font-size: 12px;padding:8px;">`
htmlCode += `${
lang}<a class="copy-btn" code-data-index="${
copyCode.length - 1}" style="margin-left: 8px;">复制代码</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
}
})
- Analizar la sintaxis de rebajas
const parseNodes = (value) => {
if(!value) return
let htmlString = ''
if (value.split("```").length % 2) {
let msgContent = value
if(msgContent[msgContent.length-1] != '\n'){
msgContent += '\n'
}
htmlString = markdown.render(msgContent)
} else {
htmlString = markdown.render(msgContent.value)
}
// #ifndef APP-NVUE
return htmlString
// #endif
// nvue模式下将htmlString转成htmlArray,其他情况rich-text内部转
// 注:本示例项目还没使用nvue编译
// #ifdef APP-NVUE
return parseHtml(htmlString)
// #endif
}
Llame al método parseNodes en el mensaje de sesión.
<rich-text space="nbsp" :nodes="parseNodes(item.content)" @itemclick="handleItemClick"></rich-text>
Los componentes de uniapp rich-text
proporcionan itemclick
métodos. Intercepta eventos de clic (solo admite etiquetas a e img) y devuelve la información del nodo actual event.detail={node}
// 复制代码
const handleItemClick = (e) => {
console.log(e);
let {
attrs} = e.detail.node
console.log({
attrs});
let {
"code-data-index": codeDataIndex, "class": className} = attrs
if(className == 'copy-btn'){
uni.setClipboardData({
data:copyCode[codeDataIndex],
showToast:false,
success() {
uni.showToast({
title: '复制成功',
icon: 'none'
});
}
})
}
}
En este punto, básicamente se puede admitir el análisis de sintaxis de rebajas.
El teclado uniapp retrasa el problema de la página.
En uniapp, flex se usa para diseñar una página de chat. Cuando aparece el cuadro de entrada con el teclado, toda la página se empujará hacia arriba, lo que hará que la barra de navegación superior desaparezca.
Me preguntaba si podría obtener la altura del teclado cuando aparezca el teclado y luego agregar relleno a la capa div emergente. Después de algunos intentos, esta solución funcionó ~~
Como se muestra arriba: agregue una capa de vista a la capa exterior del editor y establezca padding-bottom en la altura de la ventana emergente del teclado.
const fixPaddingBottom = computed(() => {
let keyH = keyboardHeight.value > 70 ? keyboardHeight.value - 70 : keyboardHeight.value
return (keyH || 10) + 'px'
})
Los 70 aquí se pueden ajustar según la situación real.
Luego obtenga la altura de rebote del teclado en onMounted.
onMounted(() => {
nextTick(() => {
scrollToLast()
})
// #ifndef H5
uni.onKeyboardHeightChange(e => {
keyboardHeight.value = e.height
// 在dom渲染完毕 滚动到最后一条消息
nextTick(() => {
scrollToLast()
})
})
// #endif
})
Después de un poco de depuración, cuando aparece el teclado, solo se empuja hacia arriba el área de contenido, pero la barra de navegación personalizada en la parte superior no se empuja hacia arriba, lo que resuelve perfectamente el problema de que se empuje hacia arriba toda la página.
Si tiene otras soluciones mejores, no dude en discutirlas juntos ~~