diff --git a/CHANGELOG.md b/CHANGELOG.md index 76329cb0..6123875c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # 更新日志 +## v4.2.5 + +- 功能优化:在代码右下角增加复制代码功能按钮,增加收起和展开代码功能。 +- Bug 修复:修复 Shift + Enter 不换行的 Bug +- Bug 修复:修复管理后台菜单添加页面的文本错误 + ## v4.2.4 - 功能优化:更改前端构建技术选型,使用 Vite 构建,提升构建速度和兼容性 diff --git a/web/src/components/ChatReply.vue b/web/src/components/ChatReply.vue index 2d18095f..ea116b87 100644 --- a/web/src/components/ChatReply.vue +++ b/web/src/components/ChatReply.vue @@ -124,7 +124,7 @@ import hl from 'highlight.js' import MarkdownIt from 'markdown-it' import emoji from 'markdown-it-emoji' import mathjaxPlugin from 'markdown-it-mathjax3' -import { ref } from 'vue' +import { nextTick, onMounted, reactive, ref, watchEffect } from 'vue' import Thinking from './Thinking.vue' // eslint-disable-next-line no-undef,no-unused-vars const props = defineProps({ @@ -155,6 +155,9 @@ const isPlaying = ref(false) const playIcon = ref('/images/voice.gif') const store = useSharedStore() +// 添加代码块展开/收起状态管理 +const codeBlockStates = reactive({}) + const md = new MarkdownIt({ breaks: true, html: true, @@ -162,24 +165,29 @@ const md = new MarkdownIt({ typographer: true, highlight: function (str, lang) { const codeIndex = parseInt(Date.now()) + Math.floor(Math.random() * 10000000) - // 显示复制代码按钮 - const copyBtn = `复制 -${str.replace( + // 显示复制代码按钮和展开/收起按钮 + const copyBtn = ` + 展开 + 复制 + ${str.replace( /<\/textarea>/g, '</textarea>' )}` + let langHtml = '' + let preCode = '' + // 处理代码高亮 if (lang && hl.getLanguage(lang)) { - const langHtml = `${lang}` - // 处理代码高亮 - const preCode = hl.highlight(str, { language: lang }).value - // 将代码包裹在 pre 中 - return `${preCode}${copyBtn} ${langHtml}` + langHtml = `${lang}` + preCode = hl.highlight(str, { language: lang }).value + } else { + preCode = md.utils.escapeHtml(str) } - // 处理代码高亮 - const preCode = md.utils.escapeHtml(str) - // 将代码包裹在 pre 中 - return `${preCode}${copyBtn}` + // 将代码包裹在 pre 中,添加收起状态的类 + return ` + ${langHtml}${copyBtn} + ${preCode} + 复制` }, }) md.use(mathjaxPlugin) @@ -226,6 +234,81 @@ const stopSynthesis = () => { const reGenerate = (messageId) => { emits('regen', messageId) } + +// 添加代码块展开/收起功能 +const toggleCodeBlock = (codeId) => { + const codeContainer = document.querySelector(`pre[data-code-id="${codeId}"]`) + const expandBtn = document.querySelector(`.expand-btn[data-code-id="${codeId}"]`) + + if (codeContainer && expandBtn) { + if (codeContainer.classList.contains('code-collapsed')) { + codeContainer.classList.remove('code-collapsed') + codeContainer.classList.add('code-expanded') + expandBtn.textContent = '收起' + } else { + codeContainer.classList.remove('code-expanded') + codeContainer.classList.add('code-collapsed') + expandBtn.textContent = '展开' + } + } +} + +// 添加事件监听 +onMounted(() => { + nextTick(() => { + setupCodeBlockEvents() + }) +}) + +// 监听内容变化,重新绑定事件 +watchEffect(() => { + if (props.data.content.text) { + nextTick(() => { + setupCodeBlockEvents() + }) + } +}) + +const setupCodeBlockEvents = () => { + // 移除旧的事件监听器 + const oldBtns = document.querySelectorAll('.expand-btn') + oldBtns.forEach((btn) => { + btn.removeEventListener('click', handleExpandClick) + }) + + // 为展开按钮添加点击事件 + const expandBtns = document.querySelectorAll('.expand-btn') + expandBtns.forEach((btn) => { + btn.addEventListener('click', handleExpandClick) + + // 检查对应的代码块是否需要展开功能 + const codeId = btn.getAttribute('data-code-id') + const codeContainer = document.querySelector(`pre[data-code-id="${codeId}"]`) + const codeElement = codeContainer?.querySelector('.hljs') + + if (codeElement) { + // 临时移除高度限制来获取真实高度 + const originalMaxHeight = codeElement.style.maxHeight + codeElement.style.maxHeight = 'none' + const realHeight = codeElement.scrollHeight + codeElement.style.maxHeight = originalMaxHeight + + // 如果代码块高度小于等于200px,隐藏展开按钮 + if (realHeight <= 200) { + btn.style.display = 'none' + // 移除收起状态的类,让短代码块完全展示 + codeContainer.classList.remove('code-collapsed') + } else { + btn.style.display = 'inline' + } + } + }) +} + +const handleExpandClick = (e) => { + const codeId = e.target.getAttribute('data-code-id') + toggleCodeBlock(codeId) +}
${preCode}${copyBtn} ${langHtml}
${preCode}
${preCode}${copyBtn}
+ ${langHtml}${copyBtn} + ${preCode} + 复制