提交 a0bf4c43 编写于 作者: DCloud_JSON's avatar DCloud_JSON

1.0.17

上级 d47ae269
## 1.0.17(2023-05-29)
- 新增 显示代码行号
- 修复 代码块显示样式错误的问题
- 修复 部分情况下广告位不能正确显示的问题
## 1.0.16(2023-05-26)
- 更新 默认不启用(注释掉)广告组件`uni-ad-rewarded-video`
## 1.0.15(2023-05-26)
......
@import "@/lib/highlight/github-dark.min.css";
/* #ifndef APP-NVUE */
.rich-text-box {
max-width: 100%;
}
.rich-text-box ::v-deep pre.hljs {
padding: 5px 8px;
margin: 5px 0;
......
......@@ -8,9 +8,8 @@
<image class="avatar" :src="msg.isAi?'../../static/uni-ai.png':'../../static/avatar.png'" mode="widthFix"></image>
</view>
<view class="content">
<view class="rich-text-box" :class="{'show-cursor':showCursor}" ref="rich-text-box">
<rich-text v-if="nodes&&nodes.length" space="nbsp" :nodes="nodes"></rich-text>
<rich-text v-if="nodes&&nodes.length" space="nbsp" :nodes="nodes" @itemclick="trOnclick"></rich-text>
<!-- #ifdef H5 -->
<view class="copy-box" :style="{left,top}">
......@@ -18,17 +17,15 @@
</view>
<!-- #endif -->
</view>
<view v-if="msgIndex == msgIndexList.length-1 && adpid && msg.insufficientScore">
<view style="flex-direction: column;color: red;">
<view>默认不启用广告组件(被注释),如需使用,请"去掉注释"</view>
<view>位置:/components/uni-ai-msg/uni-ai-msg.vue 第28行,或全局搜索 uni-ad-rewarded-video</view>
</view>
<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>
</view>
<uni-icons v-if="msgIndex == msgIndexList.length-1 && !msg.isAi && msg.state != 100 && msgStateIcon(msg)"
<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>
......@@ -45,7 +42,9 @@
adpid
} = config
import {msgList} from '@/pages/chat/msgList.js';
import {
msgList
} from '@/pages/chat/msgList.js';
// 引入markdown-it库
import MarkdownIt from '@/lib/markdown-it.min.js';
......@@ -59,6 +58,9 @@
// console.log('hljs--',hljs);
// console.log('hljs--',hljs.getLanguage('js'));
// 为复制代码功能保留代码内容
let codeDataList = []
// 初始化 MarkdownIt库
const markdownIt = MarkdownIt({
// 在源码中启用 HTML 标签
......@@ -68,20 +70,41 @@
// if (lang && hljs.getLanguage(lang)) {
// console.error('lang', lang)
// try {
// return '<pre class="hljs" style="padding: 5px 8px;margin: 5px 0;overflow: auto;"><code>' +
// return '<pre class="hljs" style="padding: 5px 8px;margin: 5px 0;overflow: auto;display: block;"><code>' +
// hljs.highlight('lang', str, true).value +
// '</code></pre>';
// } catch (__) {}
// }
// 经过highlight.js处理后的html
let preCode = ""
try {
return '<pre class="hljs" style="padding: 5px 8px;margin: 5px 0;overflow: auto;"><code>' +
hljs.highlightAuto(str).value +
'</code></pre>';
} catch (__) {}
preCode = hljs.highlightAuto(str).value
} catch (err) {
// console.log('err',err);
preCode = markdownIt.utils.escapeHtml(str);
}
return '<pre class="hljs" style="padding: 5px 8px;margin: 5px 0;overflow: auto;"><code>' +
markdownIt.utils.escapeHtml(str) + '</code></pre>';
// 以换行进行分割
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>' + html + '</ol>'
// #ifdef APP || H5
// // 复制功能~未完待续
// let tmpDom = document.createElement('div')
// tmpDom.innerHTML = html
// codeDataList.push(tmpDom.innerText)
// let codeDataIndex = Date.now()
// html = `<a class="copy-btn" code-data-index="${codeDataList.length - 1}" style="float:right;">复制</a>` + html
// #endif
return `<pre class="hljs" style="padding: 5px 8px;margin: 5px 0;overflow: auto;display: block;"><code>${html}</code></pre>`;
}
})
......@@ -93,10 +116,10 @@
left: "-100px",
// 悬浮的复制按钮的上边距
top: "-100px",
msg:{
content:""
msg: {
content: ""
},
msgIndexList:0,
msgIndexList: 0,
adpid
};
},
......@@ -138,24 +161,30 @@
return false
}
},
msgIndex:{
msgIndex: {
type: Number,
default () {
return false
}
},
isLastMsg: {
type: Boolean,
default () {
return false
}
}
},
computed: {
md(){
md() {
return this.msg.content
},
nodes() {
let htmlString = ''
// 修改转换结果的htmlString值 用于正确给界面增加鼠标闪烁的效果
// 判断markdown中代码块标识符的数量是否为偶数
if(this.md.split("```").length%2){
if (this.md.split("```").length % 2) {
htmlString = markdownIt.render(this.md + ' \n <span class="cursor">|</span>');
}else{
} else {
htmlString = markdownIt.render(this.md) + ' \n <span class="cursor">|</span>';
}
......@@ -172,6 +201,40 @@
}
},
methods: {
// 根据消息状态返回对应的图标
msgStateIcon(msg) {
switch (msg.state) {
case 0:
// 发送中
return 'spinner-cycle'
break;
case -100:
// 发送失败
return 'refresh-filled'
break;
case -200:
// 禁止发送(内容不合法)
return 'info-filled'
break;
default:
// 默认不返回任何图标
return false
break;
}
},
trOnclick(e){
// console.log(e);
// let {attrs} = e.detail.node
// console.log({attrs});
// let {"code-data-index":codeDataIndex,"class":className} = attrs
// if(className == 'copy-btn'){
// console.log('codeDataList[codeDataIndex]',codeDataList[codeDataIndex]);
// uni.setClipboardData({
// data:codeDataList[codeDataIndex],
// showToast:false
// })
// }
},
// #ifdef H5
// 复制文本内容到系统剪切板
copy() {
......@@ -196,6 +259,7 @@
display: flex;
box-sizing: border-box;
}
/* #endif */
.userInfo {
......@@ -238,7 +302,7 @@
.content {
/* #ifndef APP-NVUE */
max-width: 550rpx;
max-width: 85%;
/* #endif */
background-color: #FFF;
border-radius: 5px;
......@@ -252,24 +316,20 @@
}
/* #ifndef APP-NVUE */
.content {
display: inline;
}
.content ::v-deep rich-text {
max-width: 550rpx;
max-width: 100%;
overflow: auto;
}
/* #endif */
/* #ifdef H5 */
.content * {
display: inline;
code .l:before {
color: #516363;
position: absolute;
left: 15px;
content: counter(step);
counter-increment: step;
}
/* #endif */
.reverse {
flex-direction: row-reverse;
}
......
{
"id": "uni-ai-chat",
"name": "uni-ai-chat",
"version": "1.0.16",
"version": "1.0.17",
"description": "基于uni-ai的聊天示例项目,支持流式、支持前文总结,云端一体",
"main": "main.js",
"scripts": {
......
......@@ -5,7 +5,7 @@
<text class="noData" v-if="msgLength === 0">没有对话记录</text>
<scroll-view :scroll-into-view="scrollIntoView" scroll-y="true" class="msg-list" :enable-flex="true">
<uni-ai-msg ref="msg" v-for="(msgIndex,index) in msgLength" :key="index" :msgIndex="index"
:show-cursor="index == msgLength - 1 && msgLength%2 === 0 && sseIndex"></uni-ai-msg>
:show-cursor="index == msgLength - 1 && msgLength%2 === 0 && sseIndex" :isLastMsg="index == msgLength - 1"></uni-ai-msg>
<view class="tip-ai-ing" v-if="msgLength && msgLength%2 !== 0">
<text>uni-ai正在思考中...</text>
<view v-if="NODE_ENV == 'development' && !enableStream">
......@@ -27,11 +27,11 @@
<view v-if="!isWidescreen" class="trash">
<uni-icons @click="clear" type="trash" size="24" color="#888"></uni-icons>
</view>
<view class="textarea-box">
<view class="textarea-box" @click="focus = true">
<textarea v-model="content" :cursor-spacing="15" class="textarea" :auto-height="!isWidescreen"
@keyup.shift="onKeyup('shift')" @keydown.shift="onKeydown('shift')"
@keydown.enter="onKeydown('enter')" :disabled="inputBoxDisabled"
:placeholder="placeholderText" :maxlength="-1" :focus="focus"
:placeholder="placeholderText" :maxlength="-1" :focus="focus" @blur="focus = false"
placeholder-class="input-placeholder"></textarea>
</view>
<view class="send-btn-box">
......@@ -127,7 +127,6 @@
// #endif
msgList: {
handler(msgList) {
let msgLength = msgList.length
if (msgLength != this.msgLength) {
this.msgLength = msgLength
......@@ -135,7 +134,6 @@
this.updateLastMsg(msgList[msgLength - 1])
})
}
// 将msgList存储到本地缓存中
uni.setStorage({
"key": "uni-ai-msg",
......@@ -146,6 +144,16 @@
deep: true
}
},
beforeMount() {
// #ifdef H5
// 监听屏幕宽度变化,判断是否为宽屏 并设置isWidescreen的值
uni.createMediaQueryObserver(this).observe({
minWidth: 650,
}, matches => {
this.isWidescreen = matches;
})
// #endif
},
async mounted() {
// 如果存在广告位id且用户token未过期
......@@ -201,16 +209,6 @@
this.showLastMsg()
})
// #ifdef H5
// 监听屏幕宽度变化,判断是否为宽屏 并设置isWidescreen的值
uni.createMediaQueryObserver(this).observe({
minWidth: 650,
}, matches => {
this.isWidescreen = matches;
})
// #endif
// 兼容 Vue3下textarea不支持@keydown
// #ifdef H5 && VUE3
//获得消息输入框对象
......@@ -641,27 +639,6 @@
})
})
},
// 根据消息状态返回对应的图标
msgStateIcon(msg) {
switch (msg.state) {
case 0:
// 发送中
return 'spinner-cycle'
break;
case -100:
// 发送失败
return 'refresh-filled'
break;
case -200:
// 禁止发送(内容不合法)
return 'info-filled'
break;
default:
// 默认不返回任何图标
return false
break;
}
},
// 清空消息列表
clear() {
// 弹出确认清空聊天记录的提示框
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册