fix(content-gen): strip URLs and site-list sections from generated content
Forbid URLs/domains/markdown links across prompt rules (runtime, platform templates, outline/imitation/title flows) and rename "官网" placeholder to "官网信息" with explicit instructions that links are background only. Add sanitizeGeneratedArticleMarkdown to strip URLs, HTML images, and "网站列表/官网列表" labels from LLM output, wired into article, prompt-rule, template, and outline generation. Drop the site_list outline section seed and filter blocked outline keys in the wizard so stored drafts cannot resurrect it.
This commit is contained in:
@@ -379,9 +379,10 @@ const baseOutlineOptions = computed<ResolvedOutlineOption[]>(() => {
|
||||
)
|
||||
return [...configured, ...customOutlineSections.value]
|
||||
})
|
||||
const outlineOptions = computed<ResolvedOutlineOption[]>(() =>
|
||||
sortOutlineOptions(baseOutlineOptions.value, outlineOptionOrder.value),
|
||||
)
|
||||
const outlineOptions = computed<ResolvedOutlineOption[]>(() => {
|
||||
const visible = baseOutlineOptions.value.filter((section) => !isBlockedOutlineOption(section))
|
||||
return sortOutlineOptions(visible, outlineOptionOrder.value)
|
||||
})
|
||||
const selectedOutlineLabels = computed(() =>
|
||||
outlineOptions.value
|
||||
.filter((section) => outlineSections.value.includes(section.key))
|
||||
@@ -517,7 +518,7 @@ function resetWizardState(detail: NonNullable<typeof templateDetail.value>): voi
|
||||
competitorCount: 0,
|
||||
}),
|
||||
)
|
||||
.filter((section) => section.default)
|
||||
.filter((section) => section.default && !isBlockedOutlineOption(section))
|
||||
.map((section) => section.key)
|
||||
outlineOptionOrder.value = buildOutlineOptions(
|
||||
templateCardConfig.value.wizard?.outline,
|
||||
@@ -532,7 +533,9 @@ function resetWizardState(detail: NonNullable<typeof templateDetail.value>): voi
|
||||
inputParams: {},
|
||||
competitorCount: 0,
|
||||
}),
|
||||
).map((section) => section.key)
|
||||
)
|
||||
.filter((section) => !isBlockedOutlineOption(section))
|
||||
.map((section) => section.key)
|
||||
outlineSections.value = defaults
|
||||
}
|
||||
|
||||
@@ -562,9 +565,9 @@ function applyDraftArticleState(detail: ArticleDetail): void {
|
||||
selectedKnowledgeGroupIds.value = numberListFromUnknown(draftState.knowledge_group_ids) ?? []
|
||||
customOutlineSections.value = parseCustomOutlineSections(draftState.custom_outline_sections)
|
||||
outlineOptionOrder.value =
|
||||
stringListFromUnknown(draftState.outline_option_order) ?? outlineOptionOrder.value
|
||||
sanitizeOutlineKeys(stringListFromUnknown(draftState.outline_option_order)) ?? outlineOptionOrder.value
|
||||
outlineSections.value =
|
||||
stringListFromUnknown(draftState.outline_sections) ?? outlineSections.value
|
||||
sanitizeOutlineKeys(stringListFromUnknown(draftState.outline_sections)) ?? outlineSections.value
|
||||
generatedOutline.value = decorateOutlineNodes(parseOutlineNodes(draftState.generated_outline))
|
||||
|
||||
restoringDraft.value = false
|
||||
@@ -1307,8 +1310,8 @@ function buildDraftState(): Record<string, JsonValue> {
|
||||
title: finalTitle.value || selectedTitle.value || '',
|
||||
review_intro_hook: reviewIntroHook.value,
|
||||
knowledge_group_ids: selectedKnowledgeGroupIds.value,
|
||||
outline_sections: outlineSections.value,
|
||||
outline_option_order: outlineOptionOrder.value,
|
||||
outline_sections: sanitizeOutlineKeys(outlineSections.value) ?? [],
|
||||
outline_option_order: sanitizeOutlineKeys(outlineOptionOrder.value) ?? [],
|
||||
custom_outline_sections: customOutlineSections.value.map((item) => ({
|
||||
key: item.key,
|
||||
label: item.label,
|
||||
@@ -1764,6 +1767,23 @@ function buildOutlineOptions(
|
||||
}))
|
||||
}
|
||||
|
||||
function isBlockedOutlineOption(section: ResolvedOutlineOption): boolean {
|
||||
const key = section.key.trim().toLowerCase()
|
||||
const label = section.label.trim()
|
||||
return key === 'site_list' || ['网站列表', '官网列表', '网址列表'].includes(label)
|
||||
}
|
||||
|
||||
function sanitizeOutlineKeys(keys: string[] | undefined): string[] | undefined {
|
||||
if (!keys) {
|
||||
return undefined
|
||||
}
|
||||
const blockedKeys = new Set(
|
||||
baseOutlineOptions.value.filter((section) => isBlockedOutlineOption(section)).map((section) => section.key),
|
||||
)
|
||||
const filtered = keys.filter((key) => !blockedKeys.has(key) && key.trim().toLowerCase() !== 'site_list')
|
||||
return filtered.length > 0 ? filtered : []
|
||||
}
|
||||
|
||||
function buildFallbackTitles(
|
||||
_templateKey: string | undefined,
|
||||
currentBrand: string,
|
||||
|
||||
Reference in New Issue
Block a user