From c83c36baa6dd0b052d5810105eb5f6ea5a93eb42 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=8F=B2=E6=82=A6?= Date: Mon, 27 Oct 2025 09:51:28 +0800 Subject: [PATCH] =?UTF-8?q?=20-=20=E5=9C=A8=20js/app.js:728-766=20?= =?UTF-8?q?=E6=96=B0=E5=A2=9E=20buildDeleteButtonHtml=EF=BC=8C=E5=B9=B6?= =?UTF-8?q?=E5=9C=A8=20js/app.js:1000-1034=20=E5=B0=86=E6=B5=AE=E5=8A=A8?= =?UTF-8?q?=E5=88=A0=E9=99=A4=E6=8C=89=E9=92=AE=E6=A4=8D=E5=85=A5=E7=94=A8?= =?UTF-8?q?=E6=88=B7=E3=80=81AI=20=20=20=20=20=E4=B8=8E=E9=94=99=E8=AF=AF?= =?UTF-8?q?=E6=B6=88=E6=81=AF=E6=B0=94=E6=B3=A1=EF=BC=8C=E5=90=8C=E6=97=B6?= =?UTF-8?q?=E9=98=BB=E6=96=AD=E4=BA=8B=E4=BB=B6=E5=86=92=E6=B3=A1=E4=BB=A5?= =?UTF-8?q?=E5=85=8D=E5=B9=B2=E6=89=B0=20SVG=20=E7=82=B9=E5=87=BB=EF=BC=9B?= =?UTF-8?q?=E5=B8=A6=20SVG=20=E7=9A=84=E6=B6=88=E6=81=AF=E4=BA=A6=E5=9C=A8?= =?UTF-8?q?=20js/app.js:1042-1054=20=E6=B3=A8=E5=85=A5=E5=90=8C=E6=A0=B7?= =?UTF-8?q?=E7=9A=84=20=20=20=20=20=E5=88=A0=E9=99=A4=E5=85=A5=E5=8F=A3?= =?UTF-8?q?=E3=80=82=20=20=20-=20=E9=80=9A=E8=BF=87=20js/app.js:870-924=20?= =?UTF-8?q?=E7=9A=84=20confirmDeleteMessage=20=E4=B8=8E=20deleteMessagePer?= =?UTF-8?q?manently=EF=BC=8C=E5=88=A0=E9=99=A4=E5=89=8D=E5=BC=B9=E5=87=BA?= =?UTF-8?q?=E4=B8=8D=E5=8F=AF=E6=81=A2=E5=A4=8D=E6=8F=90=E7=A4=BA=EF=BC=8C?= =?UTF-8?q?=20=20=20=20=20=E7=A1=AE=E8=AE=A4=E5=90=8E=E5=90=8C=E6=AD=A5?= =?UTF-8?q?=E6=B8=85=E7=90=86=E5=BD=93=E5=89=8D=E6=A8=A1=E5=BC=8F=E7=9A=84?= =?UTF-8?q?=E5=AF=B9=E8=AF=9D=E5=8E=86=E5=8F=B2=E3=80=81=E5=85=B3=E8=81=94?= =?UTF-8?q?=20SVG=20=E7=BC=93=E5=AD=98=E4=BB=A5=E5=8F=8A=E6=9C=AC=E5=9C=B0?= =?UTF-8?q?=E5=AD=98=E5=82=A8=EF=BC=8C=E5=BF=85=E8=A6=81=E6=97=B6=E8=87=AA?= =?UTF-8?q?=E5=8A=A8=E5=9B=9E=E9=80=80=E8=87=B3=E5=8D=A0=E4=BD=8D=E8=A7=86?= =?UTF-8?q?=E5=9B=BE=E3=80=82=20=20=20-=20=E5=9C=A8=20css/style.css:235-26?= =?UTF-8?q?6=20=E5=AE=9A=E4=B9=89=20message-with-delete=20=E4=B8=8E=20mess?= =?UTF-8?q?age-delete-btn=EF=BC=8C=E5=AE=9E=E7=8E=B0=E5=8F=B3=E4=B8=8A?= =?UTF-8?q?=E8=A7=92=E9=AB=98=E4=BA=AE=E6=82=AC=E6=B5=AE=E6=8C=89=E9=92=AE?= =?UTF-8?q?=E5=8F=8A=20=20=20=20=20hover=20=E5=8F=8D=E9=A6=88=EF=BC=8C?= =?UTF-8?q?=E4=BF=9D=E8=AF=81=E5=9C=A8=E6=B7=B1=E6=B5=85=E8=83=8C=E6=99=AF?= =?UTF-8?q?=E4=B8=8B=E5=9D=87=E5=8F=AF=E6=B8=85=E6=99=B0=E8=AF=86=E5=88=AB?= =?UTF-8?q?=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- css/style.css | 33 +++++++++++++++++++ js/app.js | 88 +++++++++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 114 insertions(+), 7 deletions(-) diff --git a/css/style.css b/css/style.css index dc6a774..926e53c 100644 --- a/css/style.css +++ b/css/style.css @@ -232,6 +232,39 @@ iconify-icon { transition: color 0.2s ease; } +/* 消息删除浮动按钮 */ +.message-with-delete { + position: relative; + padding-right: 48px; +} + +.message-delete-btn { + position: absolute; + top: 8px; + right: 8px; + width: 30px; + height: 30px; + border-radius: 9999px; + border: 2px solid #1f2937; + background: rgba(255, 255, 255, 0.92); + color: #dc2626; + display: inline-flex; + align-items: center; + justify-content: center; + box-shadow: 2px 2px 0 rgba(0,0,0,0.2); + transition: transform 0.2s ease, background 0.2s ease, color 0.2s ease; +} + +.message-delete-btn:hover { + background: #dc2626; + color: #ffffff; + transform: scale(1.05); +} + +.message-delete-btn iconify-icon { + font-size: 16px; +} + .svg-placeholder-block { position: relative; } diff --git a/js/app.js b/js/app.js index 95aeff0..14d5a73 100644 --- a/js/app.js +++ b/js/app.js @@ -757,6 +757,14 @@ class ProductCanvasApp { `; } + buildDeleteButtonHtml(messageId) { + return ` + + `; + } + // 组装标准化的SVG消息字符串 buildSVGMessageContent(beforeText = '', svgBody = '', afterText = '') { const segments = []; @@ -859,6 +867,62 @@ class ProductCanvasApp { this.renderSvgViewerForMode(); } + confirmDeleteMessage(messageId) { + const history = this.conversationHistory[this.currentMode] || []; + const targetMessage = history.find(msg => msg.id === messageId); + if (!targetMessage) { + alert('未找到要删除的消息,请刷新后重试。'); + return; + } + + const typeLabel = targetMessage.type === 'user' + ? '这条用户消息' + : targetMessage.type === 'ai' + ? '这条AI回复' + : '这条提示'; + + const confirmed = confirm(`${typeLabel}删除后无法恢复,确定要删除吗?`); + if (!confirmed) { + return; + } + + this.deleteMessagePermanently(messageId); + } + + deleteMessagePermanently(messageId) { + const history = this.conversationHistory[this.currentMode] || []; + const messageIndex = history.findIndex(msg => msg.id === messageId); + if (messageIndex === -1) { + return; + } + + history.splice(messageIndex, 1); + + const svgStore = this.svgStorage[this.currentMode] || {}; + let viewerShouldReset = false; + for (const [svgId, meta] of Object.entries(svgStore)) { + if (meta.messageId === messageId) { + delete svgStore[svgId]; + if (this.currentSvgId === svgId) { + viewerShouldReset = true; + } + } + } + + if (viewerShouldReset) { + this.currentSvgId = null; + this.showSvgPlaceholder(); + } + + Utils.storage.set('canvasHistory', this.conversationHistory.canvas || []); + Utils.storage.set('swotHistory', this.conversationHistory.swot || []); + Utils.storage.set('canvasSVGs', this.svgStorage.canvas || {}); + Utils.storage.set('swotSVGs', this.svgStorage.swot || {}); + + this.renderConversationHistory(); + this.renderSvgViewerForMode(); + } + // 添加用户消息 addUserMessage(text) { const messageId = Utils.generateId('msg'); @@ -935,25 +999,33 @@ class ProductCanvasApp { if (message.type === 'user') { messageDiv.className = 'flex justify-end'; + const deleteButton = this.buildDeleteButtonHtml(message.id); messageDiv.innerHTML = ` -
- ${Utils.escapeHtml(message.content)} +
+
${Utils.escapeHtml(message.content)}
+ ${deleteButton}
`; } else if (message.type === 'error') { messageDiv.className = 'flex justify-start'; + const deleteButton = this.buildDeleteButtonHtml(message.id); messageDiv.innerHTML = ` -
- - ${Utils.escapeHtml(message.content)} +
+ ${deleteButton} +
+ + ${Utils.escapeHtml(message.content)} +
`; } else if (message.type === 'ai') { const parsedContent = typeof marked !== 'undefined' ? marked.parse(message.content) : Utils.escapeHtml(message.content); const actions = this.buildActionToolbar(message.id, { allowRegenerate, allowRollback }); + const deleteButton = this.buildDeleteButtonHtml(message.id); messageDiv.className = 'flex justify-start'; messageDiv.innerHTML = ` -
+
+ ${deleteButton}
${parsedContent}
@@ -972,11 +1044,13 @@ class ProductCanvasApp { const beforeHtml = parsed.beforeText ? (typeof marked !== 'undefined' ? marked.parse(parsed.beforeText) : Utils.escapeHtml(parsed.beforeText)) : ''; const afterHtml = parsed.afterText ? (typeof marked !== 'undefined' ? marked.parse(parsed.afterText) : Utils.escapeHtml(parsed.afterText)) : ''; const actions = this.buildActionToolbar(message.id, { allowRegenerate, allowRollback }); + const deleteButton = this.buildDeleteButtonHtml(message.id); messageDiv.className = 'flex justify-start'; const placeholderClass = this.currentSvgId === svgId ? 'svg-placeholder-block svg-placeholder-active' : 'svg-placeholder-block'; messageDiv.innerHTML = ` -
+
+ ${deleteButton}
${beforeHtml}