优化业务逻辑和基础库的大标题区间和字段的识别精度

This commit is contained in:
2026-07-31 16:39:04 +08:00
parent 8b996772ea
commit 0c8193d230
8 changed files with 210 additions and 183 deletions
+39 -2
View File
@@ -865,6 +865,28 @@ export async function handleAutoFillCommon(params: AutoFillCommonParams): Promis
const allTitles = getAllPageTitles(sectionResults)
const FIVE_EXP_SECTIONS_JSON = new Set(["education", "work", "internship", "project", "competition"])
// 从简历数据中提取所有值,构建排除集合(避免将已填值误认为标签)
const excludeTexts = new Set<string>()
if (currentResumeData) {
const main = currentResumeData.main
if (main) {
for (const val of Object.values(main)) {
if (typeof val === "string" && val.trim()) excludeTexts.add(val.trim())
if (Array.isArray(val)) val.forEach((v) => { if (typeof v === "string" && v.trim()) excludeTexts.add(v.trim()) })
}
}
const expKeys: ("education" | "work" | "internship" | "project" | "competition")[] = ["education", "work", "internship", "project", "competition"]
for (const sec of expKeys) {
const items = currentResumeData[sec]
if (!Array.isArray(items)) continue
for (const item of items) {
for (const val of Object.values(item as Record<string, any>)) {
if (typeof val === "string" && val.trim()) excludeTexts.add(val.trim())
}
}
}
}
/** 判断某个字段是否属于简历数据格式(JOB_FORM_LABELS 里 resumeField 非空的) */
const resumeFormatInputs = new Set<Element>()
// 阶段A和B的所有 input 都是简历格式字段
@@ -928,6 +950,17 @@ export async function handleAutoFillCommon(params: AutoFillCommonParams): Promis
type FieldItem = { label: string; value: string; inputEl: Element }
const collectedFields: FieldItem[] = []
// 构建当前大标题范围内所有已填 input 的值集合
// 用于排除误将已填值(如"香港理工大学"、"硕士"、"2026"等)当作标签的情况
const filledInputValues = new Set<string>()
for (const inp of Array.from(allInputs)) {
const afterT = !!(titleEl.compareDocumentPosition(inp) & Node.DOCUMENT_POSITION_FOLLOWING)
const beforeN = !nextTitleEl || !!(nextTitleEl.compareDocumentPosition(inp) & Node.DOCUMENT_POSITION_PRECEDING)
if (!afterT || !beforeN) continue
const val = (inp as HTMLInputElement | HTMLTextAreaElement).value?.trim()
if (val) filledInputValues.add(val)
}
for (const inp of Array.from(allInputs)) {
// 范围检查
const afterTitle = !!(titleEl.compareDocumentPosition(inp) & Node.DOCUMENT_POSITION_FOLLOWING)
@@ -946,8 +979,12 @@ export async function handleAutoFillCommon(params: AutoFillCommonParams): Promis
// 查找标签(使用统一封装的 labelFinder
const titleElementSet = new Set<Element>(allTitles.map((t) => t.element))
const { labelText: detectedLabel } = findLabelForInput(inp, titleElementSet)
const labelText = detectedLabel
const { labelText: detectedLabel } = findLabelForInput(inp, titleElementSet, excludeTexts)
const labelText = detectedLabel?.trim()
// 跳过无效标签:空、纯数字、已知排除词、或检测到的"标签"实际是某个已填 input 的值
if (!labelText || /^\d+$/.test(labelText) || JSON_EXCLUDE_LABELS.some((ex) => labelText === ex)) continue
if (filledInputValues.has(labelText)) continue
// 非经历类型:跳过简历格式字段
// 【注意】简历格式字段通过 resumeFormatInputs(阶段A/B实际匹配到的input元素集合)精确跳过