完成AI辅导员修改

This commit is contained in:
2025-09-23 16:59:20 +08:00
parent d217ea3a14
commit 2fc41315fa
4 changed files with 185 additions and 3 deletions

View File

@@ -295,6 +295,9 @@ export default {
// 启动鼠标跟踪
this.startMouseTracking()
// 添加图片点击事件委托
this.setupImagePreviewEvents()
// 确保DOM完全渲染后再初始化聊天
this.$nextTick(() => {
setTimeout(async () => {
@@ -345,6 +348,12 @@ export default {
// 停止鼠标跟踪
this.stopMouseTracking()
// 移除图片点击事件监听器
const messageList = this.$refs.messageList
if (messageList && this.imageClickHandler) {
messageList.removeEventListener('click', this.imageClickHandler)
}
// 取消正在进行的请求
if (this.currentCancel) {
this.currentCancel()
@@ -1112,7 +1121,10 @@ export default {
// 渲染markdown
const html = this.md.render(text)
const sanitizedHtml = DOMPurify.sanitize(html)
let sanitizedHtml = DOMPurify.sanitize(html)
// 处理图片:添加样式和点击预览功能
sanitizedHtml = this.processImages(sanitizedHtml)
// 缓存管理:如果缓存超过最大大小,删除最旧的条目
if (this.markdownCache.size >= this.maxCacheSize) {
@@ -1126,6 +1138,107 @@ export default {
return sanitizedHtml
},
/**
* 处理图片:添加样式和点击预览功能
*/
processImages(html) {
// 创建临时DOM元素来处理HTML
const tempDiv = document.createElement('div')
tempDiv.innerHTML = html
// 查找所有图片元素
const images = tempDiv.querySelectorAll('img')
images.forEach((img, index) => {
// 添加样式
img.style.maxWidth = '100%'
img.style.height = 'auto'
img.style.cursor = 'pointer'
img.style.borderRadius = '8px'
img.style.boxShadow = '0 2px 8px rgba(0, 0, 0, 0.1)'
img.style.transition = 'all 0.3s ease'
// 添加hover效果的class
img.classList.add('markdown-image')
// 添加唯一标识符用于后续绑定事件
img.setAttribute('data-preview-src', img.src)
img.setAttribute('data-preview-image', 'true')
// 添加加载错误处理
img.setAttribute('onerror', 'this.style.display="none"')
})
return tempDiv.innerHTML
},
/**
* 图片预览功能
*/
previewImage(src) {
// 创建预览遮罩层
const overlay = document.createElement('div')
overlay.style.cssText = `
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.8);
display: flex;
justify-content: center;
align-items: center;
z-index: 9999;
cursor: pointer;
`
// 创建预览图片
const previewImg = document.createElement('img')
previewImg.src = src
previewImg.style.cssText = `
max-width: 90%;
max-height: 90%;
object-fit: contain;
border-radius: 8px;
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.3);
`
// 点击遮罩层关闭预览
overlay.addEventListener('click', () => {
document.body.removeChild(overlay)
})
// 阻止图片点击事件冒泡
previewImg.addEventListener('click', (e) => {
e.stopPropagation()
})
overlay.appendChild(previewImg)
document.body.appendChild(overlay)
},
/**
* 设置图片预览事件委托
*/
setupImagePreviewEvents() {
// 创建事件处理函数
this.imageClickHandler = (e) => {
// 检查点击的是否是标记为预览的图片
if (e.target.tagName === 'IMG' && e.target.getAttribute('data-preview-image') === 'true') {
const src = e.target.getAttribute('data-preview-src')
if (src) {
this.previewImage(src)
}
}
}
// 使用事件委托在消息列表容器上监听点击事件
const messageList = this.$refs.messageList
if (messageList) {
messageList.addEventListener('click', this.imageClickHandler)
}
},
/**
* 节流更新内容
*/
@@ -2633,6 +2746,23 @@ export default {
color: #722ed1 !important;
}
/* Markdown 图片样式 */
.content-text .markdown-image {
max-width: 100% !important;
height: auto !important;
cursor: pointer !important;
border-radius: 8px !important;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1) !important;
transition: all 0.3s ease !important;
display: block;
margin: 8px 0;
}
.content-text .markdown-image:hover {
transform: scale(1.02);
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.15) !important;
}
/* 消息限制提示样式 */
.message-limit-notice {
background: #f6f8fa;

View File

@@ -21,7 +21,7 @@
<!-- 其他页面内容 -->
<!-- 触发按钮控制弹窗显示隐藏 -->
<div class="ai-hover" @click="toggleAI">
<span v-if="!showAI" style="font-size: 30px; font-weight: bold;">AI</span>
<AiIcon v-if="!showAI" :size="48" color="white" />
<i v-else class="el-icon-close" style="font-size: 20px;"></i>
</div>
<!-- 聊天弹窗通过 v-if 控制显隐 -->
@@ -40,6 +40,7 @@ import ResizeMixin from './mixin/ResizeHandler'
import { mapState } from 'vuex'
import variables from '@/assets/styles/variables.scss'
import ChatPopup from '../layout/components/Aichat/ChatPopup.vue'
import AiIcon from '@/components/AiIcon/index.vue'
import {
initCoze
@@ -57,7 +58,8 @@ export default {
Settings,
Sidebar,
TagsView,
ChatPopup // 注册ChatPopup组件
ChatPopup, // 注册ChatPopup组件
AiIcon // 注册AiIcon组件
},
mixins: [ResizeMixin],
data() {