diff --git a/README.md b/README.md index fc52c1a..26757d7 100644 --- a/README.md +++ b/README.md @@ -69,6 +69,7 @@ Vite 通常使用 http://localhost:5173。 - 创建知识沿用 `title/category/content/source_url`,新增可选 `source_id/document_id/collected_at`;状态固定为 `pending`。关联文档时自动解析其来源,填写的来源或网址若冲突会报错。直接来源链接的旧调用仍受支持。 - 来源创建字段:`name`、可选 `source_url`、`notes`。文档创建字段:`source_id/title/content/collected_at`,可选 `category/notes`。文档来源归属固定,换来源需新建文档。 - 知识修改时省略 `collected_at` 表示保留原值,明确传 `null` 表示清空;清空后回到待审核,补全真实采集时间前不能核验通过。文档的采集时间仍是必填字段,不接受 `null`。 +- 知识管理页可为未关联文档的条目选择或解除登记来源;关联文档的条目沿用文档所属来源,来源选择和网址只读,保存其他字段时保留关联。来源选择与边界验收见 [SOURCE_SELECTION_ACCEPTANCE.md](docs/SOURCE_SELECTION_ACCEPTANCE.md)。 - PATCH 请求必须携带读取时获得的 `expected_version`,并至少提交一个修改字段;DELETE 使用查询参数 `expected_version`。版本过期返回 409,防止覆盖他人修改。 - 审核请求字段见下方示例。`verification_status` 只允许 `pending/verified/rejected`;核验人和说明必填。通过审核前必须有来源网址及真实采集时间。这里只记录人工结论,不会自动核实网页。 - 修改条目、关联来源或关联文档都会将相关知识转为 `pending`,清除当前审核字段并记录失效原因。历史快照保留当时的条目、来源和文档。 diff --git a/docs/SOURCE_SELECTION_ACCEPTANCE.md b/docs/SOURCE_SELECTION_ACCEPTANCE.md new file mode 100644 index 0000000..19b65d1 --- /dev/null +++ b/docs/SOURCE_SELECTION_ACCEPTANCE.md @@ -0,0 +1,48 @@ +# 来源选择与文档关联边界验收 + +## 范围与前置 + +原知识编辑修正 PR #50 已由真正合入 dev 的替代 PR #56 完整交付;PR #58 增加来源选择与名称展示,PR #59 维持草稿时间可空、审核前必填,并暂缓知识通用备注。本轮针对新来源选择路径开展浏览器及独立 HTTP 验收,承接 Issue #57 和 #52,不重复实现已有后端字段。 + +使用隔离数据库 Schema、默认 FastAPI 生命周期与 Vite;账户、101个来源、一个文档和三个知识条目均为明确标注的合成数据。网址使用 `example.com`,不代表真实文旅资料或领域质量。修正前的复现与最终验收分别使用两个全新 Schema。 + +## 复现与修正 + +1. 为一个已核验知识条目关联文档;该文档属于一个已登记来源。 +2. 原页面允许将来源选为“不关联已登记来源”并保存,提示成功,但后端会根据文档恢复原来源。条目还会回到待审核;页面没有解释无法解除的原因。 +3. 现在,文档关联知识的来源选择禁用、网址只读,并显示文档决定来源的说明。保存标题等其他字段时省略 `source_id` 和 `source_url`,不会提交来源重绑意图。 +4. 未关联文档的条目仍能选择或解除登记来源,解除后可保留独立网址。后端仍负责关联一致性、版本和权限校验;本页不增加文档解绑功能。 + +![文档关联来源锁定说明](assets/source-selection-acceptance/document-source-locked.png) + +## 最终浏览器验收 + +| 操作 | 实际结果 | +|---|---| +| 管理员打开 `/knowledge`,载入101个来源 | 下拉框包含101个来源及“不关联”选项,覆盖来源API的两页数据 | +| 普通知识选择来源API第二页的合成来源 | 网址正确回填,保存后列表显示正确来源名称与链接,条目回到 `pending` | +| 该条目的来源网址改为与登记来源冲突的值 | 显示后端错误,编辑表单保留,不提示保存成功 | +| 普通知识解除登记来源 | 列表变为“未关联”,仍保留原独立网址;重新查询确认 `source_id=null` | +| 编辑文档关联知识 | 来源控件禁用、网址只读,说明清晰;仍能保存标题修订 | +| 展开普通条目的历史 | 旧版本仍显示其当时来源名称及原微秒采集时间 | + +![第二页来源实际保存后的名称与链接](assets/source-selection-acceptance/source-selected.png) + +## 独立 HTTP 核对 + +- 来源切换、解除与文档关联标题修订的版本、来源ID/网址、审核回退均与页面结果一致;标题修订和来源操作保留原采集时间的全部微秒。 +- 文档来源冲突、登记来源网址冲突返回422;过期编辑返回409;这些失败请求不改变当前条目或审计历史。 +- 普通用户不能读取管理来源列表或修改知识(403);客户端控件不代替后端权限与关联校验。 +- 修改后旧文本发布返回409;保存的检索记录及原有审计事件保持一致。独立网址草稿未受其他条目操作影响。 + +HTTP仅用于准备合成数据、独立查询及负向接口验证,不冒充浏览器交互;浏览器操作与截图均来自实际页面。 + +## 验证与清理 + +- `cd frontend && node --test tests/datetime.test.mjs`:**6 passed**。 +- `cd frontend && npm run build`:类型检查与生产构建通过。 +- `git diff --check`:通过。 +- 本轮没有后端代码或迁移变更,未重跑全量pytest;未运行Embedding或生成模型。 +- 两个隔离Schema已分别独立查询确认不存在;自有FastAPI、Vite及数据库服务停止,临时浏览器标签关闭。原始合成记录、运行环境、账户和本机进度不入库。 + +仅覆盖上述来源编辑路径。原生删除确认、Docker/生产HTTPS/多浏览器/浏览器改密与真实领域资料验收继续单列;Issue #5、#52、#57 已关闭的远程状态不能替代这些剩余验收。 diff --git a/docs/TASKS.md b/docs/TASKS.md index eaf1d35..d0e5d4b 100644 --- a/docs/TASKS.md +++ b/docs/TASKS.md @@ -13,7 +13,7 @@ | T07 | 向量 | 评估 Embedding 并实现 pgvector | 范涵宇 | 已完成(本地模型、精确向量和 RRF 已合入;待真实领域评测) | | T08 | RAG | 集成 LLM 与来源展示 | 范涵宇 | Responses 协议已合入(请求/解析与旧快照兼容已完成;生成模型选型与实际调用延期) | | T09 | 实验 | 构建可核验问题集及评分规范 | 杨星萱 | 待办 | -| T10 | 工程 | 补充测试、Alembic、鉴权与部署 | 范涵宇(主)、全员 | 进行中(聊天边界修正已合入;知识编辑浏览器复核与采集时间清空修正待审,Docker/HTTPS/部署待验收) | +| T10 | 工程 | 补充测试、Alembic、鉴权与部署 | 范涵宇(主)、全员 | 进行中(聊天边界及知识编辑修正已合入;来源选择浏览器复核与文档来源锁定修正待审,Docker/HTTPS/部署待验收) | ## 2026-10-15 首次联调记录 @@ -142,3 +142,13 @@ - 修正清空知识时间却静默保留旧值的问题:前端明确发送 null,后端将文档必填时间约束与知识可空时间分开;文档仍拒绝 null,审核、版本和历史保护保留。无迁移或模型调用。 - 后端目录/索引/导出专项 **75 passed**、前端时区 **6 passed**,ruff检查/格式检查、前端类型/生产构建与diff检查通过;没有把此前312项全量结果当作本轮重跑。可复现步骤、合成截图和浏览器/HTTP证据边界见 [KNOWLEDGE_EDIT_ACCEPTANCE.md](KNOWLEDGE_EDIT_ACCEPTANCE.md)。 - 本阶段提交后等待真正合入,再继续剩余合理后端工作;原生确认、Docker/HTTPS/多浏览器/改密及领域资料待办保留,生成模型和凭据继续延期。 + + +## 2026-10-20 T05/T10:来源选择与文档关联边界验收 + +- 原 PR #50 关闭未标记合并,但全部修正通过真正合入 dev 的 PR #56 进入集成分支;已核对精确 head、完整阶段树、8个改动文件及替代 head/merge 的祖先关系。保留原编号与替代依据,再从最新 dev 创建唯一后端验收分支。 +- PR #58 已实现知识管理页来源选择与名称展示,PR #59 已记录字段决定。本轮仅验收新来源路径及修正其文档关联边界;草稿时间仍可空,审核前真实时间必填,知识通用 notes 暂缓。 +- 浏览器复现:文档关联知识选择“不关联来源”后提示保存成功,但后端按文档恢复原来源。现在页面锁定此类条目的来源选择与网址并解释原因;保存其他字段时省略来源重绑字段。后端关联、版本和审核规则保持原有行为,无迁移。 +- 在全新隔离合成数据中,真实浏览器完成101个来源跨两页加载、第二页来源选择/名称/链接保存、普通条目解除来源并保留独立网址、文档关联条目的只读说明及标题保存、冲突链接错误提示与历史快照展示。HTTP独立核对微秒保留、旧历史/检索记录不变、来源/网址冲突422、过期编辑409、旧发布409和普通用户403;失败请求不改变条目或审计历史。 +- 前端时区 **6 passed**、类型/生产构建与 `git diff --check` 通过;本轮没有后端代码变更或全量pytest重跑,也没有Embedding/生成调用。复现、截图及验证边界见 [SOURCE_SELECTION_ACCEPTANCE.md](SOURCE_SELECTION_ACCEPTANCE.md)。 +- 修正前及最终两轮Schema均经独立查询确认删除,自有服务停止、临时浏览器标签关闭。此阶段提交后等待真正合入;Docker/生产HTTPS/多浏览器/浏览器改密、原生确认和领域资料等剩余条件单列保留,Issue关闭不替代实际验收。 diff --git a/docs/assets/source-selection-acceptance/document-source-locked.png b/docs/assets/source-selection-acceptance/document-source-locked.png new file mode 100644 index 0000000..6c8466b Binary files /dev/null and b/docs/assets/source-selection-acceptance/document-source-locked.png differ diff --git a/docs/assets/source-selection-acceptance/source-selected.png b/docs/assets/source-selection-acceptance/source-selected.png new file mode 100644 index 0000000..c486853 Binary files /dev/null and b/docs/assets/source-selection-acceptance/source-selected.png differ diff --git a/docs/knowledge/field-feedback.md b/docs/knowledge/field-feedback.md index 72b7226..fb01571 100644 --- a/docs/knowledge/field-feedback.md +++ b/docs/knowledge/field-feedback.md @@ -34,8 +34,16 @@ 5. **来源名称回填**:现有直接填 `source_url` 的条目,来源名称缺失;后续入库前应补登记到 `sources` 并关联。 -## 三、核对结论 +## 三、确认决定(2026-10-19) + +1. **来源选择与展示:采纳。** 管理员知识管理页已支持选择已登记来源并展示来源名称与链接;仍由后端校验来源、链接与权限。 +2. **采集时间:维持现有分层约束。** 草稿知识条目的 `collected_at` 可以为空;标记为 `verified` 前必须具备可核验的来源网址与采集时间。文档采集时间继续为必填。 +3. **通用备注:暂缓。** 当前不为 `knowledge_items` 新增 `notes` 字段;待出现稳定业务需求后再评估数据库迁移。审核说明与关联文档备注按现有职责使用。 + +以上确认仅涉及字段与流程,不包含真实资料、账号、凭据或环境信息。 + +## 四、核对结论 - 追溯核心字段(标题、类别、URL、获取/更新时间、核验状态、核验人、核验依据)系统均已支持,状态三值与审核规则一致。 -- 主要缺口集中在「来源名称的独立登记与前端展示」「知识条目通用备注」「摘要与正文的一致性」三点,需在阶段 2 入库前与范涵宇、吉海燕确认。 -- 数据库结构改动仅为建议,不由本文档直接执行。 +- 来源名称的独立登记与前端展示已完成;通用备注字段暂缓,摘要与正文的一致性仍须在核验时确认。 +- 数据库结构改动仍需独立评估,不由本文档直接执行。 diff --git a/docs/knowledge/material-ledger.md b/docs/knowledge/material-ledger.md index ffd5121..eb3a111 100644 --- a/docs/knowledge/material-ledger.md +++ b/docs/knowledge/material-ledger.md @@ -40,9 +40,9 @@ | K-0003 | 那拉提草原景区概况(国家5A级旅游景区) | 旅游资源 | 中国日报网(govt.chinadaily.com.cn) | https://govt.chinadaily.com.cn/s/201812/28/WS5c2592c6498eb4f01ff25691/nalati-grassland-nalati-prairie-ili-kazak-autonomous-prefecture.html | 2026-10-19 | 2026-10-19 | 那拉提草原位于新疆伊犁哈萨克自治州新源县,为国家5A级旅游景区、新疆首个国家级旅游度假区,地处天山腹地、伊犁河谷东端,属亚高山草甸草原(摘自检索摘要,待核实) | 人工核验通过 | 2026-10-21 | 杨星萱 | verified | 试点条目;来源页面为2018年发布,票价等时效信息以景区最新官方发布为准 | | K-0004 | 那拉提镇红色记忆馆 | 红色文化 | 天山网(新疆权威媒体) | https://www.ts.cn/xwzx/shxw/202608/t20260810_35862803.shtml | 2026-10-19 | 2026-10-19 | 新源县那拉提镇塔依阿苏村退役老兵自建红色记忆馆,藏品超5000件(军功章、旧军服、烈士信函、历史报刊等),为当地爱国主义教育、国防教育阵地(摘自检索摘要,待核实) | 人工核验通过 | 2026-10-21 | 杨星萱 | verified | 试点条目 | | K-0005 | 自治区文旅厅红色旅游主题线路(独库公路串联那拉提) | 红色文化 | 新疆维吾尔自治区文化和旅游厅(天山融媒发布) | https://tnews.xjmty.com/app/slyapp/hdf/202310/t20231001_16431821.html | 2026-10-19 | 2026-10-19 | 自治区文旅厅推出6大主题13条红色旅游主题线路,其中以独库公路为主线的线路将乔尔玛革命烈士陵园与那拉提景区等串联(摘自检索摘要,待核实) | 人工核验通过 | 2026-10-21 | 杨星萱 | verified | 试点条目 | -| K-0006 | 那拉提景区交通出行指南 | 交通出行 | 新源县人民政府 | https://www.xinyuan.gov.cn/xinyuan/c113900/202508/6785b61206e94151886c1be0b27f5a90.shtml | 2026-10-19 | 2026-10-19 | 新源县政府发布那拉提交通指南:易拥堵路段含墩那高速那拉提收费站出口、国道218线341—347公里等;那拉提镇设约1010个停车位;伊宁机场/火车站可乘线路车直达,那拉提机场乘景区直通车约1小时抵达游客服务中心(摘自检索摘要,待核实) | 人工核验通过 | 2026-10-21 | 杨星萱 | verified | 试点条目 | +| K-0006 | 2025那拉提音乐节交通安全指南(活动期) | 交通出行 | 新源县人民政府 | https://www.xinyuan.gov.cn/xinyuan/c113900/202508/6785b61206e94151886c1be0b27f5a90.shtml | 2026-10-19 | 2026-10-19 | 来源为2025年那拉提音乐节期间发布的交通安全提示,含活动期易拥堵路段、临时停车和到达建议;仅作为该活动期交通信息线索,不可泛化为常规景区交通指南(待人工核验) | 时效性强(活动期信息),不进入通用问答或正式检索 | 2026-10-21 | 杨星萱 | pending | 时效性强,不进入通用问答或正式检索;后续应另收集常规交通官方资料 | | K-0007 | 新源县旅游产业基本情况(含那拉提住宿与民宿) | 民宿服务 | 新源县人民政府(县文化体育广播电视和旅游局) | https://www.xinyuan.gov.cn/xinyuan/c113962/202505/74a8a8423c7b4f7c906aaa491900d96c.shtml | 2026-10-19 | 2026-10-19 | 新源县旅游产业基本情况:那拉提旅游风景区为5A级景区,那拉提镇为全国特色小镇,阿尔善村、拜依盖托别村为国家级乡村旅游重点村;全县住宿单位1414家,其中那拉提区域1204家(摘自检索摘要,待核实) | 人工核验通过 | 2026-10-21 | 杨星萱 | verified | 试点条目 | -| K-0008 | 新源县旅游资源栏目(政府网目录页) | 旅游资源 | 新源县人民政府 | https://www.xinyuan.gov.cn/xinyuan/c113892/common_list.shtml | 2026-10-19 | 2026-10-19 | 新源县政府网「旅游资源」栏目列表页,收录新源县旅游资源相关文章(栏目入口,具体篇目待逐个打开收集) | 待人工核验(栏目页未打开,需人工访问核实) | | | pending | 栏目目录页,非单条资料;需逐个打开收集其中具体文章 | +| K-0008 | 新源县"风光名胜"栏目(政府网目录页) | 旅游资源 | 新源县人民政府 | https://www.xinyuan.gov.cn/xinyuan/c113892/common_list.shtml | 2026-10-19 | 2026-10-19 | 新源县政府网「风光名胜」栏目入口,目录中含外部平台链接;仅作后续检索线索,不作为单条可核验资料 | 待人工核验(栏目页已可访问,具体篇目需逐条访问) | | | pending | 栏目目录页,非单条资料;仅登记已核对的栏目名称与入口 | | K-0009 | 新源县民宿服务栏目(政府网目录页) | 民宿服务 | 新源县人民政府 | https://www.xinyuan.gov.cn/xinyuan/xyz/common_list.shtml | 2026-10-19 | 2026-10-19 | 新源县政府网民宿服务相关栏目列表页,收录民宿/乡村旅游相关文章(栏目入口,具体篇目待逐个打开收集) | 待人工核验(栏目页未打开,需人工访问核实) | | | pending | 栏目目录页,非单条资料;需逐个打开收集其中具体文章 | | K-0010 | 新源县交通出行栏目(政府网目录页) | 交通出行 | 新源县人民政府 | https://www.xinyuan.gov.cn/xinyuan/xyx/common_list.shtml | 2026-10-19 | 2026-10-19 | 新源县政府网交通出行相关栏目列表页,收录交通出行相关文章(栏目入口,具体篇目待逐个打开收集) | 待人工核验(栏目页未打开,需人工访问核实) | | | pending | 栏目目录页,非单条资料;需逐个打开收集其中具体文章 | | K-0011 | 秋入草原山有色 那拉提的限定秋色美到“出圈” | 旅游资源 | 新源县人民政府 | https://www.xinyuan.gov.cn/xinyuan/c113892/202609/4c805c9d83a34d2cadd5c2808d753a59.shtml | 2026-10-21 | 2026-10-21 | 那拉提秋季景色主题文章(正文待打开核实) | 人工核验通过 | 2026-10-21 | 杨星萱 | verified | | @@ -78,4 +78,4 @@ | K-0041 | 央媒看伊犁丨新疆那拉提——"最先见到太阳的地方" | 旅游资源 | 伊犁哈萨克自治州人民政府 | https://www.xjyl.gov.cn/xjylz/c112427/202605/89ae4da7f30e4bf89c430de4e8c86276.shtml | 2026-10-21 | 2026-10-21 | 那拉提旅游风景区:国家5A级景区、新疆首家国家级旅游度假区,地处天山腹地、伊犁河谷东端;那拉提意为"最先见到太阳的地方",拥有空中草原、河谷草原、盘龙古道等游览线路及哈萨克族民俗活动(摘自检索摘要,待核实) | 人工核验通过 | 2026-10-21 | 杨星萱 | verified | 替补已过期的百度百科词条 K-0019;另有文旅部5A级景区登记(sjfw.mct.gov.cn)可作交叉印证 | | K-0042 | 新源县那拉提镇:提质赋能优服务 精致旅居暖宾客 | 民宿服务 | 新华网 | https://app.xinhuanet.com/news/article.html?articleId=20260901766fd9e2cbf14816996e92507fee44c0 | 2026-10-21 | 2026-10-21 | 那拉提镇引导酒店、民宿推进硬件提质、服务提标,打造"草原明珠·醉美新源"文旅品牌(摘自检索摘要,待核实) | 人工核验通过 | 2026-10-21 | 杨星萱 | verified | 替补不符合主题的 K-0025;新华网转载新源县信息,核验时可找回政府网原文 | -> K-0001 为**示例占位行**、K-0002 为**测试条目**,均不含真实文旅信息,保持 `pending`;K-0008 至 K-0010 为政府网栏目目录页(入口,非单条资料),保持 `pending`。K-0019(百度百科词条已过期)、K-0022(新华网旧文已过期)、K-0025(与民宿服务主题不符)、K-0028(与那拉提/新源/伊犁非直接相关)、K-0031、K-0036(链接打不开)共 6 条于 2026-10-21 改为 `rejected` 不采用。其余单条资料(K-0003 至 K-0042,除上述 rejected 及 pending 者外)已于 2026-10-21 经杨星萱人工核验通过,状态为 `verified`:红色文化 8 条、旅游资源 10 条、民宿服务 7 条、交通出行 6 条,四类均达阶段2目标。 +> K-0001 为**示例占位行**、K-0002 为**测试条目**,均不含真实文旅信息,保持 `pending`;K-0008 至 K-0010 为政府网栏目目录页(入口,非单条资料),保持 `pending`。K-0006 经核对为「2025 那拉提音乐节交通安全指南」,属活动期、时效性强,改为 `pending` 不进入通用问答,常规交通资料待回补。K-0019(百度百科词条已过期)、K-0022(新华网旧文已过期)、K-0025(与民宿服务主题不符)、K-0028(与那拉提/新源/伊犁非直接相关)、K-0031、K-0036(链接打不开)共 6 条于 2026-10-21 改为 `rejected` 不采用。其余单条资料(K-0003 至 K-0042,除上述 rejected 及 pending 者外)已于 2026-10-21 经杨星萱人工核验通过,状态为 `verified`:红色文化 8 条、旅游资源 10 条、民宿服务 7 条、交通出行 5 条。 diff --git a/frontend/src/api.ts b/frontend/src/api.ts index a00280f..05e2477 100644 --- a/frontend/src/api.ts +++ b/frontend/src/api.ts @@ -10,7 +10,7 @@ export const createKnowledge = (payload:{title:string;category:string;content:st export type VerificationStatus='pending'|'verified'|'rejected' export type KnowledgeItem={id:number;version:number;title:string;category:string;content:string;source_url:string|null;source_id:number|null;document_id:number|null;collected_at:string|null;verification_status:VerificationStatus;reviewer:string|null;reviewed_at:string|null;verification_notes:string|null;created_at:string;updated_at:string;is_deleted:boolean} export function getKnowledgePage(filters:{q?:string;category?:string;verification_status?:VerificationStatus;page?:number;page_size?:number}={}){const params=new URLSearchParams();for(const [key,value] of Object.entries(filters)){if(value!==undefined&&value!=='')params.set(key,String(value))}return apiRequest<{items:KnowledgeItem[];total:number;page:number;page_size:number}>(`/api/knowledge/page?${params}`)} -export function updateKnowledge(id:number,payload:{expected_version:number;title?:string;category?:string;content?:string;source_url?:string|null;collected_at?:string|null}){return apiRequest(`/api/knowledge/${id}`,{method:'PATCH',body:JSON.stringify(payload)},true)} +export function updateKnowledge(id:number,payload:{expected_version:number;title?:string;category?:string;content?:string;source_id?:number|null;source_url?:string|null;collected_at?:string|null}){return apiRequest(`/api/knowledge/${id}`,{method:'PATCH',body:JSON.stringify(payload)},true)} export function deleteKnowledge(id:number,expectedVersion:number){return apiRequest(`/api/knowledge/${id}?expected_version=${expectedVersion}`,{method:'DELETE'},true)} export function getKnowledgeHistory(id:number,page=1,pageSize=20){return apiRequest<{items:AuditItem[];total:number;page:number;page_size:number}>(`/api/knowledge/${id}/history?page=${page}&page_size=${pageSize}`)} export type SourceItem={id:number;version:number;name:string;source_url:string|null;notes:string;created_at:string} diff --git a/frontend/src/views/KnowledgeManagementView.vue b/frontend/src/views/KnowledgeManagementView.vue index ad6a915..b06734d 100644 --- a/frontend/src/views/KnowledgeManagementView.vue +++ b/frontend/src/views/KnowledgeManagementView.vue @@ -1,19 +1,22 @@ -