前端-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 操作时,避免假设紧邻兄弟结构,用循环遍历查找目标元素更稳健