跳转至

前端-DOM注入-来源收藏按钮缺失

问题现象

  • OneDay 页面(/#/one-day)每个主题的"来源"区域,新闻条目没有收藏按钮
  • 来源条目标题样式(黑色、无下划线、间距 20px)不生效

核心问题

根因 1:h3.nextElementSibling 未找到 <ul>

injectSourceFavButtons() 通过 h3.nextElementSibling 查找紧邻的 <ul>。但 LLM prompt 模板中 ### 来源 和列表之间有指令性文字,LLM 将其一并输出,导致 DOM 变为:

<h3>来源</h3>
<p>从上方输入新闻列表中...</p>  <!-- LLM 输出的指令文本 -->
<ul><li>[1] 标题A</li></ul>

nextElementSibling 取到 <p> 而非 <ul>,代码判定失败,跳过收藏按钮注入。

根因 2:scoped 样式不作用于动态 DOM

.oneday-src-item 等样式写在 <style scoped> 中,但元素是通过 JS createElement 动态注入的,不含 Vue 的 data-v-xxx 属性,导致 scoped 选择器无法匹配。而 .theme-src-fav-btn 用了 :deep() 穿透,所以收藏按钮样式正常。

解决方法

步骤 1:清理 prompt 模板

文件:docs/config/aiOneDay.md

### 来源 后直接跟列表,移除中间的指令文字。要求已合并到文末"输出要求"中。

步骤 2:前端 DOM 搜索改为向前遍历

文件:web/src/views/OneDay.vue:60-66

// 旧:只查紧邻兄弟
const srcUl = h3.nextElementSibling

// 新:向前遍历直到找到 <ul> 或 <ol>
let el = h3.nextElementSibling
while (el && el.tagName !== 'UL' && el.tagName !== 'OL') {
  el = el.nextElementSibling
}

步骤 3:动态注入样式加 :deep() 穿透

文件:web/src/views/OneDay.vue:434-436

/* 旧(scoped 无法匹配动态 DOM) */
.oneday-src-item { ... }

/* 新(:deep() 穿透 scoped) */
:deep(.oneday-src-item) { ... }
:deep(.oneday-src-item a) { ... }

步骤 4:重建前端

cd web && pnpm build

下次防错措施

  • 任何通过 JS createElement / innerHTML 注入的 DOM 元素,CSS 必须用 :deep() 包裹
  • LLM prompt 模板中,格式示例不要夹杂指令性文字,指令统一放在文末"输出要求"中
  • 新增 inject 型 DOM 操作时,避免假设紧邻兄弟结构,用循环遍历查找目标元素更稳健