feat(project): 项目基本信息修改和分包选择(FR-M2-03、04)
Some checks failed
ci / server (push) Has been cancelled
ci / web (push) Has been cancelled
ci / contract (push) Has been cancelled

- 字段修改:人工值优先、撤销恢复 AI 值、按字段校验(金额可写「286万」,按元存)、
  冗余列同步、审计留痕、只读项目 409;关键日期显示改后的投标截止时间
- 分包:增删改、选包(至少一个)、一键「不分包」;删包时条目归为通用,删到一个不剩回到不分包
- 清单列表 lot_scope 默认只列通用 + 所投的包,响应带 hidden_count
- 检查记下当时用的项目依据(截止时间、限价、所投的包、法律体系):报告按它写,
  之后改了信息检查结果接口给 basis_changed,查标页提示重新检查
- 前端:概览标签页(项目要点、采购包、关键日期)、字段修改对话框、选包页和手工调整;
  解析完识别到多个包时进选包页;读标页清单范围和所属采购包;查标页写明查哪几个包
- 决策 PI1–PI7;方案和落地记录 docs/architecture/project-info-plan.md

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
YANG JIANKUAN
2026-11-04 23:46:07 +08:00
parent 08e3fe7eff
commit ed6a2a907d
29 changed files with 1834 additions and 43 deletions

View File

@@ -573,6 +573,28 @@ paths:
items: { $ref: '#/components/schemas/Lot' }
'409': { $ref: '#/components/responses/ProjectReadOnly' }
/projects/{project_id}/lots/clear:
parameters:
- $ref: '#/components/parameters/ProjectId'
post:
tags: [projects]
operationId: clearLots
summary: 这个项目不分包(PI2)
description: 删掉所有包,清单项都归为各包通用,建回默认包。用于把分项误识别成包等情况。
responses:
'200':
description: OK
content:
application/json:
schema:
type: object
required: [items]
properties:
items:
type: array
items: { $ref: '#/components/schemas/Lot' }
'409': { $ref: '#/components/responses/ProjectReadOnly' }
/lots/{lot_id}:
parameters:
- name: lot_id
@@ -599,12 +621,11 @@ paths:
delete:
tags: [projects]
operationId: deleteLot
summary: 删除分包(原属这个包的清单项变为各包通用)
summary: 删除分包(原属这个包的清单项变为各包通用,PI3)
description: 删掉最后一个包时项目回到「不分包」(自动建回默认包,PI2)。
responses:
'204': { description: 已删除 }
'409':
description: '`last_lot`:至少保留一个包;或 `project_read_only`'
content: { application/problem+json: { schema: { $ref: '#/components/schemas/Problem' } } }
'409': { $ref: '#/components/responses/ProjectReadOnly' }
# ------------------------------------------------------------------ uploads
/uploads:
@@ -965,11 +986,12 @@ paths:
application/json:
schema:
type: object
required: [items]
required: [items, hidden_count]
properties:
items:
type: array
items: { $ref: '#/components/schemas/ChecklistItem' }
hidden_count: { type: integer, description: '`lot_scope = bidding` 时不在所投包里、没列出的条数' }
post:
tags: [checklist]
operationId: createChecklistItem
@@ -2229,9 +2251,15 @@ components:
type: object
required: [item_id, label, at]
properties:
item_id: { $ref: '#/components/schemas/Id' }
item_id:
oneOf:
- $ref: '#/components/schemas/Id'
- type: 'null'
description: 来自哪条清单项;人工改过的投标截止时间没有对应条目,为 null
label: { type: string, examples: [投标截止] }
kind: { type: string, enum: [question_deadline, bid_deadline, opening, deposit_deadline, validity, other] }
at: { $ref: '#/components/schemas/Timestamp' }
edited: { type: boolean, description: 人工改过(投标截止时间按项目字段的人工值显示) }
superseded_pending: { type: boolean, description: 补遗带来了新值、等用户确认 }
latest_check_run_id:
oneOf:
@@ -2265,6 +2293,10 @@ components:
oneOf:
- $ref: '#/components/schemas/UserRef'
- type: 'null'
updated_at:
oneOf:
- $ref: '#/components/schemas/Timestamp'
- type: 'null'
pending:
type: [object, 'null']
description: 补遗带来的新值(FR-M2-10)
@@ -2306,6 +2338,9 @@ components:
edited_fields:
type: array
items: { type: string }
ai_values:
type: [object, 'null']
description: AI 识别的原值(包号、名称、预算、限价),人工修改不覆盖
# ---------- uploads / documents
Upload:
@@ -2782,6 +2817,9 @@ components:
documents:
type: array
items: { $ref: '#/components/schemas/Document' }
basis_changed:
type: boolean
description: 检查之后改过项目依据(截止时间、限价、所投的包、法律体系),查标页提示「重新检查后生效」(PI5)
coverage:
type: [object, 'null']
description: |
@@ -2823,6 +2861,12 @@ components:
value: { $ref: '#/components/schemas/LegalRegime' }
rules_verified: { type: boolean, description: 这套法律体系的规则是否经过样本验证(招标投标体系暂无样本) }
rule_set_version: { type: string }
qualification:
type: object
description: 资质匹配的计数(qualification-plan §3.4):资质库条数、核对的资质要求、按资质库判断的、没认出类别的、排除的
basis:
type: object
description: 检查时用的项目依据(PI5):deadline_at、ceiling_total、legal_regime 各为 {value, source},lots 是所投各包 {lot_no, ceiling_amount, source}。报告按它写
prompt_versions: { type: object }
tokens:
type: object