海尔山茶花502值得买吗 零嵌冰箱对比
字段审查结论为避免后端过度设计这一次只保留前端保存和下次恢复所必需的数据。保留字段字段保留原因reviewId定位审核记录沿用现有ReviewArticle.idmarkupVersion/expectedMarkupVersion解决多人同时编辑时的覆盖问题baseContentHash判断当前标记是否仍基于同一份原文markupJson云端唯一需要持久化的标记快照annotations备注和修改列表下次进入页面需要还原blockPath/from/to/quote用于把标记定位回原文updatedBy/updatedAt仅用于展示最近保存信息和冲突提示第一版去掉的字段字段去掉原因reviewVersion/expectedReviewVersion审核状态变化可通过后端校验monitorStatus 0解决标记并发由markupVersion解决createdBy/createdAt/updatedBy/updatedAtannotation 内本期全量覆盖保存不做单条批注审计每条标记的独立历史不准确也不必要prefix/suffix/blockTextHash原文冻结且只允许同块选区blockPath/from/to/quote足够这些字段可作为后续增强finalContentHtml/finalContentMarkdown草稿保存终稿可由前端实时计算草稿阶段只需要保存markupJsoncontentFormat当前内容格式由既有content字段约定若后端后续支持 HTML/Markdown 混合再扩展editable前端已有权限和状态判断后端保存时仍必须做权限/状态校验不是恢复标记所必需数据结构ReviewMarkupJsoninterface ReviewMarkupJson { schema: review-markup/v1; baseContentHash: string; annotations: ReviewMarkupAnnotation[]; }字段说明字段类型必填说明schemastring是标记数据协议版本固定review-markup/v1baseContentHashstring是原文内容 hash用于判断原文是否变化annotationsarray是当前有效的备注和修改列表markupVersion不放在markupJson内部由接口顶层字段维护避免前后端版本不一致。ReviewMarkupAnnotationinterface ReviewMarkupAnnotation { id: string; type: comment | replace; anchor: ReviewTextAnchor; comment?: string; replacement?: string; }字段说明字段类型必填说明idstring是前端生成的全局唯一标记 id例如ann_...typecomment/replace是comment备注replace替换建议anchorobject是标记在原文中的位置commentstring条件必填typecomment时必填replacementstring条件必填typereplace时必填ReviewTextAnchorinterface ReviewTextAnchor { blockPath: string; from: number; to: number; quote: string; }字段说明字段类型必填说明blockPathstring是文本块位置例如h1[0]、p[2]、li[4]fromnumber是在该文本块纯文本中的起始 offset包含tonumber是在该文本块纯文本中的结束 offset不包含quotestring是被选中的原文片段示例{ schema: review-markup/v1, baseContentHash: sha256:6adf9c..., annotations: [ { id: ann_001, type: comment, anchor: { blockPath: p[2], from: 10, to: 18, quote: 智能化高 }, comment: 这里表述偏绝对建议补充数据来源 }, { id: ann_002, type: replace, anchor: { blockPath: p[4], from: 5, to: 11, quote: 行业领先 }, replacement: 表现较强 } ] }接口设计统一响应结构沿用现有后端风格interface GeoApiResponseT { success: boolean; code: number; message: string; data: T; }如果后端支持 HTTP 409冲突场景建议直接返回 HTTP 409。如果后端统一返回 HTTP 200则必须使用明确业务 code例如40901、40902。接口 1查询文章标记数据GET /geo/api/review/getReviewMarkupByReviewId?reviewId11入参参数位置类型必填说明reviewIdquerynumber是审核记录 id即当前ReviewArticle.id出参interface GetReviewMarkupResponse { reviewId: number; baseContentHash: string; markupVersion: number; markupJson: ReviewMarkupJson | null; updatedBy?: string; updatedAt?: string; }字段说明reviewId审核记录 id等于当前列表行ReviewArticle.id。baseContentHash后端根据当前原文生成前端保存和提交时必须原样传回。markupVersion标记数据版本标记保存成功时递增。markupJson为空时前端按无标记初始化。updatedBy/updatedAt最近一次成功保存标记的人和时间仅用于展示或冲突提示。说明文章标题、正文、状态继续复用现有ReviewArticle数据如果后端希望详情页完全不依赖列表数据可另行把title/content/monitorStatus合并进该接口但第一版不是必须。前端权限仍按现有content_review_check和monitorStatus判断后端保存时必须再次校验状态和权限。示例{ success: true, code: 200, message: success, data: { reviewId: 11, baseContentHash: sha256:6adf9c..., markupVersion: 2, markupJson: { schema: review-markup/v1, baseContentHash: sha256:6adf9c..., annotations: [] }, updatedBy: zhangsan, updatedAt: 2026-07-03 15:20:00 } }接口 2保存标记草稿PUT /geo/api/review/saveReviewMarkup调用时机用户在备注弹窗点击保存。用户在修改弹窗点击保存。用户删除或编辑已有备注/修改后点击确认。保存语义前端每次提交当前文章的完整markupJson不是只提交本次新增或修改的单条 annotation。后端只在expectedMarkupVersion、baseContentHash都校验通过且当前审核状态仍允许编辑时覆盖保存。覆盖对象是该文章当前草稿的整份markup_json。校验失败时必须返回冲突不能覆盖云端已有草稿。入参interface SaveReviewMarkupParams { reviewId: number; expectedMarkupVersion: number; baseContentHash: string; markupJson: ReviewMarkupJson; }字段说明字段类型必填说明reviewIdnumber是审核记录 idexpectedMarkupVersionnumber是前端当前基于的标记版本baseContentHashstring是前端当前基于的原文 hashmarkupJsonobject是完整标记 JSON出参interface SaveReviewMarkupResponse { reviewId: number; markupVersion: number; updatedBy: string; updatedAt: string; }后端校验reviewId存在。当前审核状态仍允许编辑例如monitorStatus 0。expectedMarkupVersion等于后端当前markupVersion。baseContentHash等于后端当前原文 hash。markupJson.baseContentHash等于后端当前原文 hash。每个anchor.quote能在对应blockPath/from/to上匹配到原文。第一版建议不允许有效标记区间互相重叠尤其是replace与replace不能重叠。成功保存后后端用本次请求的完整markupJson整体覆盖保存该文章的markup_json。markupVersion 1。返回最新版本。接口 3提交审核结果沿用现有接口扩展标记快照和并发校验字段PUT /geo/api/review/updateArticleReview入参interface UpdateArticleReviewWithMarkupParams { id: number; monitorStatus: 2 | 3; rejectReason?: string; expectedMarkupVersion: number; baseContentHash: string; markupJson?: ReviewMarkupJson; }字段说明字段类型必填说明idnumber是审核记录 idmonitorStatus2/3是2未通过3待投放rejectReasonstring条件必填未通过时必填expectedMarkupVersionnumber是前端当前基于的标记版本baseContentHashstring是前端当前基于的原文 hashmarkupJsonobject否当前标记快照。建议提交时携带便于后端事务内保存最终标记后端事务要求锁定审核记录和标记记录。校验当前monitorStatus仍允许提交。校验expectedMarkupVersion等于当前markupVersion。校验baseContentHash等于当前原文 hash。如果请求携带markupJson校验所有 anchor 合法后保存为最终标记快照并递增markupVersion。更新审核状态为monitorStatus。写入审核历史。提交接口必须把保存最终标记 更新审核状态 写审核历史作为原子操作处理。