diff --git a/AGENTS.md b/AGENTS.md index cb949be..ae7e856 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -227,4 +227,9 @@ samples/ - 2026-11-05:查标结果页、概览改成和读标页一样的左右布局(左边内容,右边原文贴住视口),去掉原文侧边抽屉。查标右侧招标文件、投标文件左右切换(`components/DocStage.vue`):当前的占满,另一份露出一窄条(文件名、纸边、带方向箭头的标签,截断处淡入底色),点它或点另一边的出处就滑过去,两边各自记着页和高亮,J / K 时原文跟着翻。概览把关键日期和采购包合成一张卡放到最上面。修了原文查看器直接打开到某页时重复渲染出镜像乱字的问题。内容区四角改为直角(设计规范 §5.3 同步)。 - 2026-11-05:国动真实投标文件跑了一次(`check-eval.md` §14,代码 `5b77012`、规则集 r4、资质库空):重新读标 299 条,查标 26 秒报 44 个问题,逐条对原文后有用 9 个,**致命、重要各 1 个都是误报**(响应格「完全满足,无偏离。」被当成错位;「不……另行收费」被当成附加条件)。另外扫描页只按整页有没有字判断、不需要回答的条目还在出提示。人工看到评分索引表页码和实际页码对不上,产品还不查这一项。结果只记录,6 处问题修不修待用户定。 - 2026-11-05:按用户决定(E3)修了国动暴露的 6 处,规则集 2026.11-r5(`check-eval.md` §15)。国动重新检查 44 → 11 个,全是提示级,有用的 9 个都还在(看过结果才修,只作参考)。开发集不退化:召回 75% → 74%(模型重跑的波动),致命级 25 / 32 不变,规矩的投标文件报出的问题 239 → 213,规则问题 57 / 57。投标分册的文字层升到 v5(每页记图片占比,用来判断扫描件)。 -- 下一步:可做的有:第 6 步前端补齐(键盘操作、批量处理、判断有误反馈、日期选择器的日历弹层、概览页的检查记录和文件卡)、M6 剩下的 P0(额度流水、套餐开通、数据删除、运营后台)。 +- 2026-11-05:查标第 6 步前端补齐(`m3-plan.md` 进度)。 + - 读标页:每条清单项写最近一次检查的结论,点投标侧出处看投标原文;「已响应」也能反馈判断有误。证书要求写资质库里有没有、在截止日是否有效(新接口 `qualification-matches`,资质库空时不写)。 + - 概览:加了检查记录卡和文件卡。 + - 工作台:加了「致命」列、统计可点筛选、待处理的致命问题卡(「去处理」定位到那条问题)。 + - 日期输入加了日历弹层;查标页加了 ? 键。 +- 下一步:M6 剩下的 P0(额度流水、套餐开通、数据删除、运营后台)。 diff --git a/apps/web/package.json b/apps/web/package.json index 2cf6b70..8c7df56 100644 --- a/apps/web/package.json +++ b/apps/web/package.json @@ -13,6 +13,7 @@ "@bid-doctor/api-client": "workspace:*", "@fontsource/barlow-semi-condensed": "5.3.0", "@fontsource/noto-serif-sc": "5.3.0", + "@internationalized/date": "3.12.4", "@lucide/vue": "1.50.0", "@tanstack/vue-query": "5.104.1", "pdfjs-dist": "6.4.299", diff --git a/apps/web/src/components/ChecklistItemRow.vue b/apps/web/src/components/ChecklistItemRow.vue index 4dbfc9a..e41458e 100644 --- a/apps/web/src/components/ChecklistItemRow.vue +++ b/apps/web/src/components/ChecklistItemRow.vue @@ -7,11 +7,23 @@ import { computed } from "vue"; import CitationBlock from "./CitationBlock.vue"; import { groupCitations, type CitationGroup } from "@/lib/citations"; -import { category, failureText, IMPORTANCE_MARK, IMPORTANCE_NAME, pendingReason, specFacts } from "@/lib/labels"; -import type { ChecklistItem } from "@/lib/queries"; +import { RouterLink } from "vue-router"; +import { category, CHECK_VERDICT, failureText, fmtDay, IMPORTANCE_MARK, IMPORTANCE_NAME, pendingReason, specFacts } from "@/lib/labels"; +import type { CheckItemResult, ChecklistItem, Citation, QualificationMatch } from "@/lib/queries"; -const props = defineProps<{ item: ChecklistItem; pending?: boolean; selected?: boolean; activeCitation?: string | null }>(); -const emit = defineEmits<{ select: []; openCitation: [g: CitationGroup] }>(); +const props = defineProps<{ + item: ChecklistItem; + pending?: boolean; + selected?: boolean; + activeCitation?: string | null; + /** 最近一次检查对这一条的结论(C9);没参与检查的不传 */ + check?: CheckItemResult | null; + /** 资质库里的情况(资格条件、评分项里认出证书类别的条目);资质库是用户自己录的,墨色,不用蓝铅笔色 */ + library?: QualificationMatch[] | null; + /** library 按哪天判断有效期:「投标截止日」或「今天」 */ + libraryAsOf?: string; +}>(); +const emit = defineEmits<{ select: []; openCitation: [g: CitationGroup]; openBid: [c: Citation]; feedback: []; findings: [] }>(); /** 一条结论最多默认展开 2 处出处,其余写「另有 N 处」(§7.3);跨页的一句话算一处 */ const groups = computed(() => groupCitations(props.item.citations)); @@ -22,6 +34,9 @@ const mark = computed(() => IMPORTANCE_MARK[props.item.importance] ?? ""); const summary = computed(() => (props.item.summary && props.item.summary !== props.item.title ? props.item.summary : "")); /** 结构化取值:分值、参数要求、日期等,都来自原文(取值校验通过的才进正式清单) */ const facts = computed(() => specFacts(props.item.spec)); +/** 检查结论:已响应、默认接受是好的;其余在查标页有问题可处理 */ +const checkOk = computed(() => props.check?.verdict === "responded" || props.check?.verdict === "implicit_accepted"); +const bidCites = computed(() => groupCitations(props.check?.bid_citations ?? []).slice(0, 2));