重构+优化: CR-04+06 AiChat 流式渲染改进 + CR-10 useRendered DRY 抽

- CR-04: splitBlocks 正则切块改 marked.lexer() tokens 遍历(type=code 的 .raw 整块,其余按双换行切),正确处理行首空格/4+反引号嵌套/未闭合围栏——lexer 与 parse 同 marked 实例同 gfm 规则,切块边界与渲染边界一致。
- CR-06: watch(mdReady) 翻 true 时主动 scheduleStreamParse 重算,修首屏 marked 慢+暂无 delta 致末段停留 escapeFallback 纯文本。
- CR-10: useMarkdown 抽 useRendered(computed 读 mdReady+renderMd + ensureLoaded 幂等预热),4 view(TaskDetail/ProjectDetail/Ideas/Knowledge)删手写 renderedDesc computed + onMounted loadMarkdown 重复,loadMarkdown 提模块级。DRY 行为零变化。
批4 wlnazlvdc,vue-tsc 0 err
This commit is contained in:
2026-06-15 05:40:37 +08:00
parent dfb459a8d6
commit 9bf9e12058
6 changed files with 103 additions and 71 deletions

View File

@@ -214,19 +214,9 @@ import { useProjectStore } from '../stores/project'
import { formatDate } from '../utils/time'
import ConfirmDialog from '../components/ConfirmDialog.vue'
import { useConfirm } from '../composables/useConfirm'
import { useMarkdown } from '../composables/useMarkdown'
import { useRendered } from '../composables/useMarkdown'
import type { IdeaRecord } from '../api/types'
// B-260615-25:灵感描述 Markdown 渲染(复用 AiChat/TaskDetail 同款渲染器,模块级单例)
const { renderMd, loadMarkdown, mdReady } = useMarkdown()
// 描述渲染依赖 mdReady 响应式:loadMarkdown 完成前 escapeFallback 纯文本,完成后 mdReady 翻转
// 触发 computed 重算(B-25 漏响应式致 v-html=renderMd 首次纯文本后不重算,代码块不渲染)
const renderedDesc = computed(() => {
void mdReady.value
return renderMd(currentIdea.value?.description ?? '')
})
const { t } = useI18n()
const router = useRouter()
const store = useProjectStore()
@@ -295,6 +285,12 @@ const currentIdea = computed(() => {
return store.ideas.find(i => i.id === selectedId.value) ?? null
})
// B-260615-25:灵感描述 Markdown 渲染(复用 AiChat/TaskDetail 同款渲染器,模块级单例),
// useRendered 封装 computed(读 mdReady 触发响应式 + renderMd)+ ensureLoaded(幂等预热)
const { rendered: renderedDesc, ensureLoaded } = useRendered(
() => currentIdea.value?.description ?? '',
)
const currentStatus = computed(() => {
return currentIdea.value?.status || 'draft'
})
@@ -450,7 +446,7 @@ async function onStatusChange(e: Event) {
}
onMounted(async () => {
loadMarkdown() // 后台预热 Markdown 渲染器(模块单例,与 AiChat/TaskDetail 共享),不阻塞
ensureLoaded() // 后台预热 Markdown 渲染器(模块单例,与 AiChat/TaskDetail 共享),不阻塞
await store.loadIdeas()
})
</script>