From 4b4f65845f69e6249c5a38736486c30c2a3a0dfe Mon Sep 17 00:00:00 2001 From: yangzhe Date: Tue, 15 Jul 2025 14:39:22 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=B7=BB=E5=8A=A0=E5=8A=A0=E8=BD=BD?= =?UTF-8?q?=E5=8A=A8=E7=94=BB=EF=BC=8C=E4=BC=98=E5=8C=96table=E5=B1=95?= =?UTF-8?q?=E7=A4=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../markdown-viewer/markdown-viewer.vue | 161 ++++++++++++++++++ pages/home/index/index.vue | 96 ++++++++++- 2 files changed, 256 insertions(+), 1 deletion(-) diff --git a/components/markdown-viewer/markdown-viewer.vue b/components/markdown-viewer/markdown-viewer.vue index 3be3798..32fd2f6 100644 --- a/components/markdown-viewer/markdown-viewer.vue +++ b/components/markdown-viewer/markdown-viewer.vue @@ -41,6 +41,21 @@ renderer.link = function(href, title, text) { return `${text}`; }; +// 重写表格渲染方法,添加表格容器使其可滚动 +renderer.table = function(header, body) { + return `
+ ${header} + ${body} +
`; +}; + +// 重写表格单元格渲染方法 +renderer.tablecell = function(content, flags) { + const type = flags.header ? 'th' : 'td'; + const align = flags.align ? ` style="text-align:${flags.align}"` : ''; + return `<${type}${align}>${content}`; +}; + // 配置marked marked.use({ renderer: renderer, @@ -164,6 +179,22 @@ export default { 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 { display: block !important; @@ -183,6 +214,19 @@ export default { 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 { display: flex !important; @@ -308,6 +352,13 @@ export default { // 处理HTML,确保所有文本元素都有正确的显示属性 let processedHtml = htmlContent; + // 处理表格,确保表格正确显示 + processedHtml = processedHtml.replace(/]*)>/g, (match, attrs) => { + return `
`; + }); + + processedHtml = processedHtml.replace(/<\/table>/g, '
'); + // 将所有段落包装在特殊div中,防止段落间的换行问题 processedHtml = processedHtml.replace(/]*)>(.*?)<\/p>/gs, (match, attrs, content) => { // 确保段落内容连续显示,不被换行打断 @@ -361,6 +412,27 @@ export default { word-spacing: normal !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; @@ -471,6 +543,22 @@ export default { 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 >>> ol { @@ -492,6 +580,19 @@ export default { 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 >>> ol li, @@ -586,4 +687,64 @@ export default { overflow-wrap: break-word !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; +} \ No newline at end of file diff --git a/pages/home/index/index.vue b/pages/home/index/index.vue index 4538e54..00ef9c8 100644 --- a/pages/home/index/index.vue +++ b/pages/home/index/index.vue @@ -161,7 +161,14 @@ mode="scaleToFill" /> - + + + + + + + + @@ -495,6 +502,23 @@ export default { // 添加到消息列表 this.messageGroups.push(userMessage); 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 .SendMessageApi({ @@ -507,6 +531,9 @@ export default { this.currentConversationId = data.conversationId; + // 从消息列表中移除加载状态消息 + this.messageGroups = this.messageGroups.filter(msg => !msg.isLoading); + // 创建AI回复消息对象 const aiMessage = { id: @@ -524,6 +551,27 @@ export default { // 添加到消息列表 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; 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内容样式调整 */ /deep/ .markdown-container { padding: 0;