feat: 添加加载动画,优化table展示
This commit is contained in:
parent
5851a70aae
commit
4b4f65845f
|
@ -41,6 +41,21 @@ renderer.link = function(href, title, text) {
|
||||||
return `<a href="${href}" title="${title || ''}" style="display:inline !important;white-space:normal !important;word-break:break-all !important;letter-spacing:normal !important;word-spacing:normal !important;text-align:left !important;">${text}</a>`;
|
return `<a href="${href}" title="${title || ''}" style="display:inline !important;white-space:normal !important;word-break:break-all !important;letter-spacing:normal !important;word-spacing:normal !important;text-align:left !important;">${text}</a>`;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 重写表格渲染方法,添加表格容器使其可滚动
|
||||||
|
renderer.table = function(header, body) {
|
||||||
|
return `<div class="table-container"><table class="custom-table">
|
||||||
|
<thead>${header}</thead>
|
||||||
|
<tbody>${body}</tbody>
|
||||||
|
</table></div>`;
|
||||||
|
};
|
||||||
|
|
||||||
|
// 重写表格单元格渲染方法
|
||||||
|
renderer.tablecell = function(content, flags) {
|
||||||
|
const type = flags.header ? 'th' : 'td';
|
||||||
|
const align = flags.align ? ` style="text-align:${flags.align}"` : '';
|
||||||
|
return `<${type}${align}>${content}</${type}>`;
|
||||||
|
};
|
||||||
|
|
||||||
// 配置marked
|
// 配置marked
|
||||||
marked.use({
|
marked.use({
|
||||||
renderer: renderer,
|
renderer: renderer,
|
||||||
|
@ -164,6 +179,22 @@ export default {
|
||||||
color: inherit !important; /* 确保颜色正确继承 */
|
color: inherit !important; /* 确保颜色正确继承 */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 专门修复mp-html组件生成的列表结构 */
|
||||||
|
div[data-v-7e5387f] {
|
||||||
|
display: inline !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 处理列表编号所在的容器 - 重要修复 */
|
||||||
|
div[data-v-7e5387f] {
|
||||||
|
display: inline !important;
|
||||||
|
white-space: nowrap !important; /* 防止编号和首个字符分开 */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 首行缩进优化(确保列表项不会被意外截断) */
|
||||||
|
div div {
|
||||||
|
display: inline !important;
|
||||||
|
}
|
||||||
|
|
||||||
/* 有序列表样式 */
|
/* 有序列表样式 */
|
||||||
.custom-ordered-list, ol {
|
.custom-ordered-list, ol {
|
||||||
display: block !important;
|
display: block !important;
|
||||||
|
@ -183,6 +214,19 @@ export default {
|
||||||
list-style-type: none !important;
|
list-style-type: none !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 针对mp-html生成的列表标记容器 */
|
||||||
|
div[style*="undefined"] {
|
||||||
|
display: inline !important;
|
||||||
|
white-space: nowrap !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 对列表项第一个元素特殊处理 */
|
||||||
|
h4 {
|
||||||
|
display: inline !important;
|
||||||
|
margin: 0 !important;
|
||||||
|
padding: 0 !important;
|
||||||
|
}
|
||||||
|
|
||||||
/* 列表项共用样式 */
|
/* 列表项共用样式 */
|
||||||
.custom-list-item, ol li, ul li {
|
.custom-list-item, ol li, ul li {
|
||||||
display: flex !important;
|
display: flex !important;
|
||||||
|
@ -308,6 +352,13 @@ export default {
|
||||||
// 处理HTML,确保所有文本元素都有正确的显示属性
|
// 处理HTML,确保所有文本元素都有正确的显示属性
|
||||||
let processedHtml = htmlContent;
|
let processedHtml = htmlContent;
|
||||||
|
|
||||||
|
// 处理表格,确保表格正确显示
|
||||||
|
processedHtml = processedHtml.replace(/<table([^>]*)>/g, (match, attrs) => {
|
||||||
|
return `<div class="table-container"><table${attrs || ''} class="custom-table">`;
|
||||||
|
});
|
||||||
|
|
||||||
|
processedHtml = processedHtml.replace(/<\/table>/g, '</table></div>');
|
||||||
|
|
||||||
// 将所有段落包装在特殊div中,防止段落间的换行问题
|
// 将所有段落包装在特殊div中,防止段落间的换行问题
|
||||||
processedHtml = processedHtml.replace(/<p([^>]*)>(.*?)<\/p>/gs, (match, attrs, content) => {
|
processedHtml = processedHtml.replace(/<p([^>]*)>(.*?)<\/p>/gs, (match, attrs, content) => {
|
||||||
// 确保段落内容连续显示,不被换行打断
|
// 确保段落内容连续显示,不被换行打断
|
||||||
|
@ -361,6 +412,27 @@ export default {
|
||||||
word-spacing: normal !important; /* 正常词间距 */
|
word-spacing: normal !important; /* 正常词间距 */
|
||||||
text-align: left !important; /* 左对齐 */
|
text-align: left !important; /* 左对齐 */
|
||||||
}
|
}
|
||||||
|
/* 表格样式 */
|
||||||
|
table {
|
||||||
|
border-collapse: collapse !important;
|
||||||
|
width: 100% !important;
|
||||||
|
margin: 16rpx 0 !important;
|
||||||
|
table-layout: fixed !important;
|
||||||
|
border: 1px solid #e0e0e0 !important;
|
||||||
|
overflow-x: auto !important;
|
||||||
|
}
|
||||||
|
th, td {
|
||||||
|
border: 1px solid #e0e0e0 !important;
|
||||||
|
padding: 12rpx !important;
|
||||||
|
text-align: left !important;
|
||||||
|
word-break: break-word !important;
|
||||||
|
white-space: normal !important;
|
||||||
|
font-size: 28rpx !important;
|
||||||
|
}
|
||||||
|
th {
|
||||||
|
background-color: #f5f5f5 !important;
|
||||||
|
font-weight: bold !important;
|
||||||
|
}
|
||||||
/* 禁用所有可能导致文本被拉伸的样式 */
|
/* 禁用所有可能导致文本被拉伸的样式 */
|
||||||
* {
|
* {
|
||||||
text-align-last: left !important;
|
text-align-last: left !important;
|
||||||
|
@ -471,6 +543,22 @@ export default {
|
||||||
text-decoration: none !important;
|
text-decoration: none !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 专门修复mp-html组件生成的列表结构 */
|
||||||
|
.markdown-container >>> div[data-v-7e5387f] {
|
||||||
|
display: inline !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 处理列表编号所在的容器 - 重要修复 */
|
||||||
|
.markdown-container >>> div[data-v-7e5387f] {
|
||||||
|
display: inline !important;
|
||||||
|
white-space: nowrap !important; /* 防止编号和首个字符分开 */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 首行缩进优化(确保列表项不会被意外截断) */
|
||||||
|
.markdown-container >>> div div {
|
||||||
|
display: inline !important;
|
||||||
|
}
|
||||||
|
|
||||||
/* 有序列表样式 */
|
/* 有序列表样式 */
|
||||||
.markdown-container >>> .custom-ordered-list,
|
.markdown-container >>> .custom-ordered-list,
|
||||||
.markdown-container >>> ol {
|
.markdown-container >>> ol {
|
||||||
|
@ -492,6 +580,19 @@ export default {
|
||||||
list-style-type: none !important;
|
list-style-type: none !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 针对mp-html生成的列表标记容器 */
|
||||||
|
.markdown-container >>> div[style*="undefined"] {
|
||||||
|
display: inline !important;
|
||||||
|
white-space: nowrap !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 对列表项第一个元素特殊处理 */
|
||||||
|
.markdown-container >>> h4 {
|
||||||
|
display: inline !important;
|
||||||
|
margin: 0 !important;
|
||||||
|
padding: 0 !important;
|
||||||
|
}
|
||||||
|
|
||||||
/* 列表项共用样式 */
|
/* 列表项共用样式 */
|
||||||
.markdown-container >>> .custom-list-item,
|
.markdown-container >>> .custom-list-item,
|
||||||
.markdown-container >>> ol li,
|
.markdown-container >>> ol li,
|
||||||
|
@ -586,4 +687,64 @@ export default {
|
||||||
overflow-wrap: break-word !important;
|
overflow-wrap: break-word !important;
|
||||||
max-width: 100% !important;
|
max-width: 100% !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 表格样式 */
|
||||||
|
.markdown-container >>> table {
|
||||||
|
border-collapse: collapse !important;
|
||||||
|
width: 100% !important;
|
||||||
|
margin: 0 !important;
|
||||||
|
table-layout: fixed !important;
|
||||||
|
border: 1px solid #e0e0e0 !important;
|
||||||
|
font-size: 24rpx !important; /* 稍微减小字体大小,适应移动端 */
|
||||||
|
}
|
||||||
|
|
||||||
|
.markdown-container >>> table th,
|
||||||
|
.markdown-container >>> table td {
|
||||||
|
border: 1px solid #e0e0e0 !important;
|
||||||
|
padding: 8rpx 10rpx !important; /* 减小内边距 */
|
||||||
|
text-align: left !important;
|
||||||
|
word-break: break-word !important;
|
||||||
|
white-space: normal !important;
|
||||||
|
vertical-align: middle !important;
|
||||||
|
min-width: 80rpx !important; /* 设置最小宽度 */
|
||||||
|
}
|
||||||
|
|
||||||
|
.markdown-container >>> table th {
|
||||||
|
background-color: #f5f5f5 !important;
|
||||||
|
font-weight: bold !important;
|
||||||
|
color: #333333 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.markdown-container >>> table tr:nth-child(even) {
|
||||||
|
background-color: #fafafa !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.markdown-container >>> table tr:hover {
|
||||||
|
background-color: #f0f0f0 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 表格容器,使表格可以水平滚动 */
|
||||||
|
.markdown-container >>> .table-container {
|
||||||
|
width: 100% !important;
|
||||||
|
overflow-x: auto !important;
|
||||||
|
margin: 16rpx 0 !important;
|
||||||
|
-webkit-overflow-scrolling: touch !important; /* 为iOS设备提供平滑滚动 */
|
||||||
|
position: relative !important;
|
||||||
|
display: block !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 自定义表格类 */
|
||||||
|
.markdown-container >>> .custom-table {
|
||||||
|
min-width: 100% !important;
|
||||||
|
border-spacing: 0 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 表格标题 */
|
||||||
|
.markdown-container >>> table caption {
|
||||||
|
font-weight: bold !important;
|
||||||
|
padding: 10rpx !important;
|
||||||
|
caption-side: top !important;
|
||||||
|
text-align: center !important;
|
||||||
|
color: #333333 !important;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
|
@ -161,7 +161,14 @@
|
||||||
mode="scaleToFill"
|
mode="scaleToFill"
|
||||||
/>
|
/>
|
||||||
<view class="message-content">
|
<view class="message-content">
|
||||||
<markdown-viewer :content="message.message" />
|
<!-- 加载动画 -->
|
||||||
|
<view v-if="message.isLoading" class="loading-dots">
|
||||||
|
<view class="dot"></view>
|
||||||
|
<view class="dot"></view>
|
||||||
|
<view class="dot"></view>
|
||||||
|
</view>
|
||||||
|
<!-- 正常消息内容 -->
|
||||||
|
<markdown-viewer v-else :content="message.message" />
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</block>
|
</block>
|
||||||
|
@ -495,6 +502,23 @@ export default {
|
||||||
// 添加到消息列表
|
// 添加到消息列表
|
||||||
this.messageGroups.push(userMessage);
|
this.messageGroups.push(userMessage);
|
||||||
this.messageValue = "";
|
this.messageValue = "";
|
||||||
|
|
||||||
|
// 立即添加一个AI回复的加载状态消息
|
||||||
|
const loadingMessage = {
|
||||||
|
id: "loading_" + Math.random().toString(36).substring(2, 15),
|
||||||
|
message: "",
|
||||||
|
sendDate: "",
|
||||||
|
isSend: true,
|
||||||
|
isRead: false,
|
||||||
|
interactMode: 1, // AI消息
|
||||||
|
messageType: 0,
|
||||||
|
timeLabel: 0,
|
||||||
|
displayTime: "",
|
||||||
|
isLoading: true // 标记为加载状态
|
||||||
|
};
|
||||||
|
|
||||||
|
// 添加加载状态消息到列表
|
||||||
|
this.messageGroups.push(loadingMessage);
|
||||||
|
|
||||||
this.$u.api
|
this.$u.api
|
||||||
.SendMessageApi({
|
.SendMessageApi({
|
||||||
|
@ -507,6 +531,9 @@ export default {
|
||||||
|
|
||||||
this.currentConversationId = data.conversationId;
|
this.currentConversationId = data.conversationId;
|
||||||
|
|
||||||
|
// 从消息列表中移除加载状态消息
|
||||||
|
this.messageGroups = this.messageGroups.filter(msg => !msg.isLoading);
|
||||||
|
|
||||||
// 创建AI回复消息对象
|
// 创建AI回复消息对象
|
||||||
const aiMessage = {
|
const aiMessage = {
|
||||||
id:
|
id:
|
||||||
|
@ -524,6 +551,27 @@ export default {
|
||||||
|
|
||||||
// 添加到消息列表
|
// 添加到消息列表
|
||||||
this.messageGroups.push(aiMessage);
|
this.messageGroups.push(aiMessage);
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
console.error("API请求失败:", error);
|
||||||
|
|
||||||
|
// 从消息列表中移除加载状态消息
|
||||||
|
this.messageGroups = this.messageGroups.filter(msg => !msg.isLoading);
|
||||||
|
|
||||||
|
// 添加错误消息
|
||||||
|
const errorMessage = {
|
||||||
|
id: "error_" + Math.random().toString(36).substring(2, 15),
|
||||||
|
message: "请求失败,请稍后重试",
|
||||||
|
sendDate: "",
|
||||||
|
isSend: true,
|
||||||
|
isRead: false,
|
||||||
|
interactMode: 1, // AI消息
|
||||||
|
messageType: 0,
|
||||||
|
timeLabel: 0,
|
||||||
|
displayTime: "",
|
||||||
|
};
|
||||||
|
|
||||||
|
this.messageGroups.push(errorMessage);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -997,6 +1045,52 @@ export default {
|
||||||
font-size: 28rpx;
|
font-size: 28rpx;
|
||||||
line-height: 1.5;
|
line-height: 1.5;
|
||||||
|
|
||||||
|
/* 加载动画样式 */
|
||||||
|
.loading-dots {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: flex-start;
|
||||||
|
|
||||||
|
.dot {
|
||||||
|
display: inline-block;
|
||||||
|
width: 12rpx;
|
||||||
|
height: 12rpx;
|
||||||
|
border-radius: 50%;
|
||||||
|
background-color: #cccccc;
|
||||||
|
margin: 0 6rpx;
|
||||||
|
opacity: 0.6;
|
||||||
|
animation: dot-flashing 1.5s infinite linear alternate;
|
||||||
|
|
||||||
|
&:nth-child(1) {
|
||||||
|
animation-delay: 0s;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:nth-child(2) {
|
||||||
|
animation-delay: 0.5s;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:nth-child(3) {
|
||||||
|
animation-delay: 1s;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes dot-flashing {
|
||||||
|
0% {
|
||||||
|
opacity: 0.6;
|
||||||
|
transform: scale(1);
|
||||||
|
}
|
||||||
|
50% {
|
||||||
|
opacity: 1;
|
||||||
|
transform: scale(1.2);
|
||||||
|
background-color: #4370fe;
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
opacity: 0.6;
|
||||||
|
transform: scale(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Markdown内容样式调整 */
|
/* Markdown内容样式调整 */
|
||||||
/deep/ .markdown-container {
|
/deep/ .markdown-container {
|
||||||
padding: 0;
|
padding: 0;
|
||||||
|
|
Loading…
Reference in New Issue