添加变更历史 添加ARD文档
This commit is contained in:
206
Project/fonrey/ADR.md
Normal file
206
Project/fonrey/ADR.md
Normal file
@@ -0,0 +1,206 @@
|
||||
# Fonrey ADR 动态决策记录(Architecture & Requirement Decision Records)
|
||||
|
||||
> 目的:沉淀 Vibe Coding 过程中的**技术决策**与**需求决策**,避免跨会话后方案漂移。
|
||||
> 适用范围:全项目(TECH_STACK / DATA_MODEL / PRD / TEST_CASES / 开发流程)。
|
||||
> 维护原则:新增决策只追加,不覆盖历史;若决策被替代,必须新增 supersede 记录。
|
||||
|
||||
---
|
||||
|
||||
## 变更历史
|
||||
|
||||
| 日期 | 变更人 | 变更内容 |
|
||||
|---|---|---|
|
||||
| 2026-04-30 | Atlas | 初始化 ADR 动态决策记录;补录当日关键技术与需求决策 |
|
||||
|
||||
## 一、记录规范(必须遵守)
|
||||
|
||||
### 1.1 决策ID规则
|
||||
- 格式:`ADR-YYYYMMDD-XXX`
|
||||
- 例:`ADR-20260430-001`
|
||||
|
||||
### 1.2 决策类型
|
||||
- `TECH`:技术决策(架构、接口、数据、测试、流程规范)
|
||||
- `REQ`:需求决策(范围、术语、优先级、验收口径)
|
||||
|
||||
### 1.3 状态枚举
|
||||
- `accepted`:已生效
|
||||
- `superseded`:已被替代(需指向新 ADR)
|
||||
- `deprecated`:废弃(不再执行)
|
||||
|
||||
### 1.4 最小字段
|
||||
每条 ADR 必须包含:
|
||||
1. 决策ID
|
||||
2. 日期
|
||||
3. 模块
|
||||
4. 类型(TECH/REQ)
|
||||
5. 状态
|
||||
6. 背景
|
||||
7. 决策内容
|
||||
8. 影响范围
|
||||
9. 关联文档
|
||||
10. 备注(可选)
|
||||
|
||||
---
|
||||
|
||||
## 二、按日期记录(主索引)
|
||||
|
||||
## 2026-04-30
|
||||
|
||||
### ADR-20260430-001
|
||||
- **类型**:REQ
|
||||
- **模块**:测试治理(全局)
|
||||
- **状态**:accepted
|
||||
- **背景**:测试文档与沟通中存在“业务旅程/测试用例”术语混用,易导致执行偏差。
|
||||
- **决策**:全项目统一使用“测试用例”术语,不再以“业务旅程”作为执行口径。
|
||||
- **影响范围**:`TECH_STACK/测试规范.md`、`TEST_CASES/*`
|
||||
- **关联文档**:`TECH_STACK/测试规范.md`
|
||||
|
||||
### ADR-20260430-002
|
||||
- **类型**:TECH
|
||||
- **模块**:测试治理(全局)
|
||||
- **状态**:accepted
|
||||
- **背景**:多模块并行时测试编号易重复、不可追溯。
|
||||
- **决策**:采用全局唯一测试用例编号:`TC-FON-XXXXXX`,并建立注册表,禁止复用废弃编号。
|
||||
- **影响范围**:所有测试用例文档与测试报告系统
|
||||
- **关联文档**:
|
||||
- `TEST_CASES/TEST_CASE_ID_SPEC.md`
|
||||
- `TEST_CASES/TEST_CASE_REGISTRY.md`
|
||||
|
||||
### ADR-20260430-003
|
||||
- **类型**:TECH
|
||||
- **模块**:测试执行与报告
|
||||
- **状态**:accepted
|
||||
- **背景**:失败定位粒度不足,无法快速定位到具体步骤。
|
||||
- **决策**:测试报告必须支持 `test_case_id + step_id` 级追踪,并记录 `expected/actual/error_message` 与证据路径。
|
||||
- **影响范围**:CI 报告、自动化测试框架
|
||||
- **关联文档**:`TECH_STACK/测试规范.md`
|
||||
|
||||
### ADR-20260430-004
|
||||
- **类型**:REQ
|
||||
- **模块**:登录管理
|
||||
- **状态**:accepted
|
||||
- **背景**:登录 PRD v2.0 与技术方案存在接口命名漂移。
|
||||
- **决策**:登录模块接口路径以 PRD v2.0 为唯一权威,技术方案与测试用例全部对齐 PRD 路径。
|
||||
- **影响范围**:登录模块 API 设计、自动化测试调用路径
|
||||
- **关联文档**:
|
||||
- `PRD/登录管理/用户登录管理模块PRD.md`
|
||||
- `TECH_STACK/登录管理技术方案.md`
|
||||
- `TEST_CASES/TEST_CASES_LOGIN_MODULE.md`
|
||||
|
||||
### ADR-20260430-005
|
||||
- **类型**:REQ
|
||||
- **模块**:登录管理
|
||||
- **状态**:accepted
|
||||
- **背景**:Story 边界存在历史遗留混淆。
|
||||
- **决策**:登录模块范围冻结为:短信验证码登录为 MVP 正式能力;“找回用户名”废弃;微信扫码保留为预留。
|
||||
- **影响范围**:实现范围、测试覆盖边界
|
||||
- **关联文档**:
|
||||
- `PRD/登录管理/用户登录管理模块PRD.md`
|
||||
- `TECH_STACK/登录管理技术方案.md`
|
||||
|
||||
### ADR-20260430-006
|
||||
- **类型**:TECH
|
||||
- **模块**:客户端发布管理
|
||||
- **状态**:accepted
|
||||
- **背景**:发布模块缺少可执行技术方案,无法指导实现与测试。
|
||||
- **决策**:新增独立技术方案文档,明确 Electron 壳层边界、EV 签名、Heartbeat、自动更新、完整性校验、R2 版本管理、官网分发、便携版策略。
|
||||
- **影响范围**:`apps/release` 设计与落地
|
||||
- **关联文档**:
|
||||
- `TECH_STACK/客户端发布管理技术方案.md`
|
||||
- `PRD/发布管理/客户端发布管理模块PRD.md`
|
||||
|
||||
### ADR-20260430-007
|
||||
- **类型**:TECH
|
||||
- **模块**:客户端发布管理 / 数据模型
|
||||
- **状态**:accepted
|
||||
- **背景**:统计口径需支撑跨租户版本分布与活跃安装数。
|
||||
- **决策**:以 `public.client_heartbeats` 作为心跳事实表,使用 `(tenant_id, device_id)` 为 Upsert 锚点,活跃定义为最近 24h。
|
||||
- **影响范围**:统计接口、看板与聚合查询
|
||||
- **关联文档**:`DATA_MODEL/DATA_MODEL_PUBLIC.md`
|
||||
|
||||
### ADR-20260430-008
|
||||
- **类型**:TECH
|
||||
- **模块**:客户端发布管理 / 安全
|
||||
- **状态**:accepted
|
||||
- **背景**:下载链路存在篡改与损坏风险。
|
||||
- **决策**:客户端更新包必须进行 SHA256 完整性校验,校验失败禁止安装并保留当前版本可用。
|
||||
- **影响范围**:客户端更新器、发布接口响应字段
|
||||
- **关联文档**:
|
||||
- `TECH_STACK/客户端发布管理技术方案.md`
|
||||
- `PRD/发布管理/客户端发布管理模块PRD.md`
|
||||
|
||||
### ADR-20260430-009
|
||||
- **类型**:TECH
|
||||
- **模块**:客户端发布管理 / API
|
||||
- **状态**:accepted
|
||||
- **背景**:历史文档存在 `/api/client/updates/*` 与 `/api/release/updates/*` 双口径。
|
||||
- **决策**:发布模块统一采用 `/api/release/...` 命名空间。
|
||||
- **影响范围**:服务端路由、客户端调用、测试用例
|
||||
- **关联文档**:
|
||||
- `PRD/发布管理/客户端发布管理模块PRD.md`
|
||||
- `TECH_STACK/TECH_STACK.md`
|
||||
- `TECH_STACK/客户端发布管理技术方案.md`
|
||||
|
||||
### ADR-20260430-010
|
||||
- **类型**:TECH
|
||||
- **模块**:文档治理(全局)
|
||||
- **状态**:accepted
|
||||
- **背景**:多目录文档缺少统一变更追溯入口。
|
||||
- **决策**:`TECH_STACK / DATA_MODEL / TEST_CASES` 下文档统一添加“变更历史”章节,并规范位置:**头部元信息之后、正文主章节(## 一/## 1)之前**。
|
||||
- **影响范围**:全量技术文档与测试文档
|
||||
- **关联文档**:
|
||||
- `TECH_STACK/*.md`
|
||||
- `DATA_MODEL/*.md`
|
||||
- `TEST_CASES/*.md`
|
||||
|
||||
---
|
||||
|
||||
## 三、按模块分类记录(视图索引)
|
||||
|
||||
## 3.1 测试治理(全局)
|
||||
- `ADR-20260430-001`:术语统一为“测试用例”(REQ)
|
||||
- `ADR-20260430-002`:全局唯一测试编号机制(TECH)
|
||||
- `ADR-20260430-003`:报告粒度到 step_id(TECH)
|
||||
|
||||
## 3.2 登录管理
|
||||
- `ADR-20260430-004`:接口路径以 PRD 为准(REQ)
|
||||
- `ADR-20260430-005`:MVP 范围冻结(REQ)
|
||||
|
||||
## 3.3 客户端发布管理
|
||||
- `ADR-20260430-006`:新增独立技术方案(TECH)
|
||||
- `ADR-20260430-008`:SHA256 完整性校验强制(TECH)
|
||||
- `ADR-20260430-009`:API 命名空间统一 `/api/release/...`(TECH)
|
||||
|
||||
## 3.4 数据模型(public schema)
|
||||
- `ADR-20260430-007`:`client_heartbeats` Upsert + 24h 活跃口径(TECH)
|
||||
|
||||
## 3.5 文档治理(全局)
|
||||
- `ADR-20260430-010`:变更历史章节统一规则(TECH)
|
||||
|
||||
---
|
||||
|
||||
## 四、历史记录(Append-Only Log)
|
||||
|
||||
> 说明:本节为机器可检索的历史流水,不删改旧记录。
|
||||
|
||||
| ADR ID | 日期 | 模块 | 类型 | 状态 | 摘要 | 关联 |
|
||||
|---|---|---|---|---|---|---|
|
||||
| ADR-20260430-001 | 2026-04-30 | 测试治理 | REQ | accepted | 术语统一为“测试用例” | `TECH_STACK/测试规范.md` |
|
||||
| ADR-20260430-002 | 2026-04-30 | 测试治理 | TECH | accepted | 测试编号全局唯一 `TC-FON-XXXXXX` | `TEST_CASES/TEST_CASE_ID_SPEC.md` |
|
||||
| ADR-20260430-003 | 2026-04-30 | 测试执行 | TECH | accepted | 报告必须定位到 `test_case_id+step_id` | `TECH_STACK/测试规范.md` |
|
||||
| ADR-20260430-004 | 2026-04-30 | 登录管理 | REQ | accepted | 登录接口路径全部按 PRD v2.0 | `TECH_STACK/登录管理技术方案.md` |
|
||||
| ADR-20260430-005 | 2026-04-30 | 登录管理 | REQ | accepted | 登录模块范围冻结(含废弃/预留) | `PRD/登录管理/用户登录管理模块PRD.md` |
|
||||
| ADR-20260430-006 | 2026-04-30 | 客户端发布 | TECH | accepted | 新建独立技术方案文档 | `TECH_STACK/客户端发布管理技术方案.md` |
|
||||
| ADR-20260430-007 | 2026-04-30 | 数据模型 | TECH | accepted | `client_heartbeats` Upsert + 24h 活跃 | `DATA_MODEL/DATA_MODEL_PUBLIC.md` |
|
||||
| ADR-20260430-008 | 2026-04-30 | 客户端发布安全 | TECH | accepted | SHA256 校验失败禁止安装 | `TECH_STACK/客户端发布管理技术方案.md` |
|
||||
| ADR-20260430-009 | 2026-04-30 | 客户端发布 API | TECH | accepted | 统一 `/api/release/...` 路径 | `TECH_STACK/TECH_STACK.md` |
|
||||
| ADR-20260430-010 | 2026-04-30 | 文档治理 | TECH | accepted | 变更历史章节位置统一规范 | `TECH_STACK/*.md` `DATA_MODEL/*.md` `TEST_CASES/*.md` |
|
||||
|
||||
---
|
||||
|
||||
## 五、后续维护约定
|
||||
|
||||
1. 每当接受新技术或需求决策,**当天必须新增 ADR 条目**。
|
||||
2. 若新决策替代旧决策,在新 ADR 中写明 `supersedes: ADR-xxxx`,并将旧条目标记 `superseded`。
|
||||
3. PRD / TECH_STACK / DATA_MODEL / TEST_CASES 发生关键口径变化时,必须同步更新本文件。
|
||||
4. 本文件是跨 Session 的决策权威输入之一,和 PRD 一起喂给 Agent。
|
||||
@@ -247,12 +247,13 @@ apps/property/
|
||||
| 登录认证 | `TECH_STACK/登录管理技术方案.md` | `PRD/登录管理/` |
|
||||
| 权限管理 | `TECH_STACK/权限管理系统技术方案.md` | `PRD/权限管理/` |
|
||||
| 测试规范 | `TECH_STACK/测试规范.md` | — |
|
||||
| 房源管理 | _待补充_ | `PRD/房源管理/` |
|
||||
| 客源管理 | _待补充_ | `PRD/客源管理/` |
|
||||
| 楼盘管理 | _待补充_ | `PRD/房源管理/(含楼盘)` |
|
||||
| 组织人事 | _待补充_ | `PRD/组织人事管理/` |
|
||||
| 系统设置 | _待补充_ | `PRD/系统配置/`、`PRD/系统管理/` |
|
||||
| 客户端发布 | `TECH_STACK/TECH_STACK.md §7` | `PRD/发布管理/客户端发布管理模块PRD.md` |
|
||||
| 房源管理 | `TECH_STACK/房源管理技术方案.md` | `PRD/房源管理/` |
|
||||
| 客源管理 | `TECH_STACK/客源管理技术方案.md` | `PRD/客源管理/` |
|
||||
| 楼盘管理 | `TECH_STACK/楼盘管理技术方案.md` | `PRD/房源管理/(含楼盘)` |
|
||||
| 组织人事 | `TECH_STACK/组织人事技术方案.md` | `PRD/组织人事管理/` |
|
||||
| 系统设置 | `TECH_STACK/系统设置技术方案.md` | `PRD/系统配置/`、`PRD/系统管理/` |
|
||||
| 客户端发布 | `TECH_STACK/客户端发布管理技术方案.md` | `PRD/发布管理/客户端发布管理模块PRD.md` |
|
||||
| ADR 决策记录 | `ADR.md` | 全局(TECH/REQ) |
|
||||
|
||||
**设计 Review 记录**(了解当前已知技术债与阻塞项):
|
||||
- `REVIEW/REVIEW_全局_2026-04-26.md`(最新)
|
||||
@@ -260,6 +261,12 @@ apps/property/
|
||||
|
||||
---
|
||||
|
||||
### 9.1 ADR 治理联动规则
|
||||
|
||||
- 任何跨模块规则、口径或范围边界调整,先记录 `ADR.md`,再改对应 TECH_STACK/PRD/DATA_MODEL/TEST_CASES 文档。
|
||||
- 若已有结论被替代,必须在 ADR 中新增 superseded 记录并引用新 ADR ID,禁止直接覆盖历史。
|
||||
- 涉及上述变更的 PR/提交说明,必须包含 ADR ID(`ADR-YYYYMMDD-XXX`)。
|
||||
|
||||
## 10. 已知待解决问题(编码前必须确认)
|
||||
|
||||
以下问题在开始编码前需先确认当前状态,若未解决应在实现对应模块前暂停并上报:
|
||||
|
||||
@@ -2,13 +2,20 @@
|
||||
# Fonrey 房产经纪管理系统 — DATA MODEL 设计文档
|
||||
|
||||
> **作者**: Backend Architect
|
||||
> **版本**: v1.4
|
||||
> **日期**: 2026-04-24(v1.1 修复 S1/S2/S4;v1.2 扩展 public schema;v1.3 §三 DDL 迁至 DATA_MODEL_PUBLIC.md,本文改为索引;v1.4 补充 LOGIN/PERMISSION 子文档引用、领域对象、租户 Schema 章节、Redis 缓存策略)
|
||||
> **版本**: v1.5
|
||||
> **日期**: 2026-04-30(v1.1 修复 S1/S2/S4;v1.2 扩展 public schema;v1.3 §三 DDL 迁至 DATA_MODEL_PUBLIC.md,本文改为索引;v1.4 补充 LOGIN/PERMISSION 子文档引用、领域对象、租户 Schema 章节、Redis 缓存策略;v1.5 新增 ADR 导航与治理联动)
|
||||
> **技术栈**: Django 4.x + PostgreSQL + django-tenants + Redis
|
||||
> **设计目标**: 支撑 89,000+ 房源、多租户隔离、sub-100ms 查询、合规审计
|
||||
|
||||
---
|
||||
|
||||
## 变更历史
|
||||
|
||||
| 日期 | 变更人 | 变更内容 |
|
||||
|---|---|---|
|
||||
| 2026-04-30 | Atlas | 新增 ADR 导航与治理联动规则(数据模型变更需 ADR 可追溯) |
|
||||
| 2026-04-30 | Atlas | 补充“变更历史”章节(文档治理) |
|
||||
|
||||
## 一、架构决策总览 (Architecture Decision Records)
|
||||
|
||||
### 1.1 多租户策略:Schema-per-Tenant
|
||||
@@ -157,6 +164,7 @@ OrgUnit (组织架构)
|
||||
| [DATA_MODEL_LOGIN.md](./DATA_MODEL_LOGIN.md) | 登录与账号认证(user_accounts, login_attempts, password_reset_tokens, password_histories + Redis 登录缓存) | ✅ 完成 |
|
||||
| [DATA_MODEL_PERMISSION.md](./DATA_MODEL_PERMISSION.md) | 权限管理(permission_defs, roles, role_permissions, staff_roles, staff_permission_overrides, staff_data_scopes, permission_change_logs + Redis 权限缓存) | ✅ 完成 |
|
||||
| [ENUMS.md](./ENUMS.md) | 枚举字典(`public.enum_labels` 表设计 + 所有模块枚举定义 + 种子数据 SQL) | ✅ 完成 |
|
||||
| [ADR.md](../ADR.md) | 架构与需求决策记录(按日期/按模块/历史流水,append-only) | ✅ 完成 |
|
||||
|
||||
---
|
||||
|
||||
@@ -833,7 +841,14 @@ app.conf.beat_schedule["partition_maintenance_task"] = {
|
||||
| 跟进目的枚举 | 存 lookup_items 表,运营可维护 | 初始化数据需提前收集 |
|
||||
| 手机号加密算法 | AES-256-GCM,密钥存 Django settings(生产用 Vault) | 密钥管理需单独规划 |
|
||||
|
||||
## 十、文档治理与 ADR 联动规则
|
||||
|
||||
- 任何会影响数据模型边界的变更(新增/删除表、关键约束变更、索引策略调整、枚举口径变更)必须先在 `ADR.md` 记录为 `accepted`,再修改本文件与子文档。
|
||||
- 若既有数据决策被替代,必须在 `ADR.md` 增加 `superseded` 记录并指向新 ADR,禁止直接覆盖旧结论。
|
||||
- 提交 PR 时,凡涉及 `DATA_MODEL/*` 结构性变更,PR 描述必须包含 ADR ID(格式:`ADR-YYYYMMDD-XXX`)。
|
||||
- `DATA_MODEL.md` 只维护全局索引与规则;表级 DDL 以各子文档为权威源,避免双写漂移。
|
||||
|
||||
---
|
||||
|
||||
*本文档为 Fonrey 系统 DATA MODEL v1.0,随 PRD 迭代同步更新。*
|
||||
*本文档为 Fonrey 系统 DATA MODEL v1.5,随 PRD 与 ADR 迭代同步更新。*
|
||||
*下一步建议:API 接口规范(URL 设计 + Request/Response Schema)*
|
||||
|
||||
@@ -8,6 +8,12 @@
|
||||
|
||||
---
|
||||
|
||||
## 变更历史
|
||||
|
||||
| 日期 | 变更人 | 变更内容 |
|
||||
|---|---|---|
|
||||
| 2026-04-30 | Atlas | 补充“变更历史”章节(文档治理) |
|
||||
|
||||
## 一、领域概览(Domain Overview)
|
||||
|
||||
### 核心概念
|
||||
|
||||
@@ -8,6 +8,12 @@
|
||||
|
||||
---
|
||||
|
||||
## 变更历史
|
||||
|
||||
| 日期 | 变更人 | 变更内容 |
|
||||
|---|---|---|
|
||||
| 2026-04-30 | Atlas | 补充“变更历史”章节(文档治理) |
|
||||
|
||||
## 一、领域概览(Domain Overview)
|
||||
|
||||
### 核心概念
|
||||
|
||||
@@ -9,6 +9,12 @@
|
||||
|
||||
---
|
||||
|
||||
## 变更历史
|
||||
|
||||
| 日期 | 变更人 | 变更内容 |
|
||||
|---|---|---|
|
||||
| 2026-04-30 | Atlas | 补充“变更历史”章节(文档治理) |
|
||||
|
||||
## 一、领域概览(Domain Overview)
|
||||
|
||||
### 核心概念
|
||||
|
||||
@@ -8,6 +8,12 @@
|
||||
|
||||
---
|
||||
|
||||
## 变更历史
|
||||
|
||||
| 日期 | 变更人 | 变更内容 |
|
||||
|---|---|---|
|
||||
| 2026-04-30 | Atlas | 补充“变更历史”章节(文档治理) |
|
||||
|
||||
## 一、领域概览(Domain Overview)
|
||||
|
||||
### 核心概念
|
||||
|
||||
@@ -10,6 +10,12 @@
|
||||
|
||||
---
|
||||
|
||||
## 变更历史
|
||||
|
||||
| 日期 | 变更人 | 变更内容 |
|
||||
|---|---|---|
|
||||
| 2026-04-30 | Atlas | 补充“变更历史”章节(文档治理) |
|
||||
|
||||
## 一、领域概览(Domain Overview)
|
||||
|
||||
### 1.1 核心概念
|
||||
|
||||
@@ -1,45 +1,20 @@
|
||||
> **For AI assistants**: Read this entire file before writing any code. All decisions here are final. Do not suggest alternatives unless asked.
|
||||
# Fonrey — 房源模块数据模型(DATA_MODEL_PROPERTY)
|
||||
|
||||
> **权威定义**:本文件是房源模块所有表结构的唯一权威来源。
|
||||
> **所属系统**: Fonrey 房产经纪管理系统
|
||||
> **版本**: v1.0
|
||||
> **日期**: 2026-04-24
|
||||
> **关联模块**: `apps/property/`
|
||||
> **主文档引用**:`DATA_MODEL.md` §3.3–§3.16 为本文件的概览摘要,开发以本文件为准。
|
||||
> **版本**:v1.0 | **日期**:2026-04-24
|
||||
|
||||
---
|
||||
## 变更历史
|
||||
|
||||
## 目录
|
||||
| 日期 | 变更人 | 变更内容 |
|
||||
| ---------- | ----- | ---------------- |
|
||||
| 2026-04-30 | Atlas | 补充“变更历史”章节(文档治理) |
|
||||
|
||||
1. [模块说明](#1-模块说明)
|
||||
2. [表清单](#2-表清单)
|
||||
3. [枚举值总览](#3-枚举值总览)
|
||||
4. [DDL 定义](#4-ddl-定义)
|
||||
- 4.1 [properties(房源主表)](#41-properties房源主表)
|
||||
- 4.2 [property_contacts(联系人)](#42-property_contacts联系人)
|
||||
- 4.3 [listing_histories(挂牌历史)](#43-listing_histories挂牌历史)
|
||||
- 4.4 [price_changes(调价记录)](#44-price_changes调价记录)
|
||||
- 4.5 [follow_logs(跟进日志)](#45-follow_logs跟进日志)
|
||||
- 4.6 [follow_log_attachments(跟进附件)](#46-follow_log_attachments跟进附件)
|
||||
- 4.7 [follow_log_recordings(跟进录音)](#47-follow_log_recordings跟进录音)
|
||||
- 4.8 [property_keys(钥匙管理)](#48-property_keys钥匙管理)
|
||||
- 4.9 [key_attachments(钥匙附件)](#49-key_attachments钥匙附件)
|
||||
- 4.10 [commissions(委托管理)](#410-commissions委托管理)
|
||||
- 4.11 [commission_attachments(委托附件)](#411-commission_attachments委托附件)
|
||||
- 4.12 [field_surveys(实勘管理)](#412-field_surveys实勘管理)
|
||||
- 4.13 [survey_photos(实勘照片)](#413-survey_photos实勘照片)
|
||||
- 4.14 [property_photos(房源图片)](#414-property_photos房源图片)
|
||||
- 4.15 [property_attachments(房源附件)](#415-property_attachments房源附件)
|
||||
- 4.16 [property_marketing(营销信息)](#416-property_marketing营销信息)
|
||||
- 4.17 [property_certificates(产证信息)](#417-property_certificates产证信息)
|
||||
- 4.18 [property_completeness(维护完成度)](#418-property_completeness维护完成度)
|
||||
- 4.19 [property_tags / property_tag_relations(标签)](#419-property_tags--property_tag_relations标签)
|
||||
- 4.20 [property_favorites(收藏)](#420-property_favorites收藏)
|
||||
- 4.21 [property_protections(保护房)](#421-property_protections保护房)
|
||||
- 4.22 [number_holder_approvals(号码方审批)](#422-number_holder_approvals号码方审批)
|
||||
5. [触发器](#5-触发器)
|
||||
6. [查询模式参考](#6-查询模式参考)
|
||||
7. [禁止操作](#7-禁止操作)
|
||||
|
||||
---
|
||||
|
||||
## 1 模块说明
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
# Fonrey — Public Schema 数据模型
|
||||
|
||||
> **作者**: Backend Architect
|
||||
> **版本**: v1.3
|
||||
> **版本**: v1.5
|
||||
> **日期**: 2026-04-30
|
||||
> **权威源**: 本文件是 `public` schema 所有表的唯一权威定义
|
||||
> **设计依据**: 系统管理模块 PRD(`PRD/系统管理/系统管理模块PRD.md`);客户端发布管理模块 PRD(`PRD/发布管理/客户端发布管理模块PRD.md`)
|
||||
@@ -10,6 +10,12 @@
|
||||
|
||||
---
|
||||
|
||||
## 变更历史
|
||||
|
||||
| 日期 | 变更人 | 变更内容 |
|
||||
|---|---|---|
|
||||
| 2026-04-30 | Atlas | 补充“变更历史”章节(文档治理) |
|
||||
|
||||
## 一、概览
|
||||
|
||||
`public` schema 存储**平台运营层**数据,与各租户的业务 schema 完全隔离。
|
||||
@@ -34,6 +40,7 @@ PostgreSQL Instance
|
||||
│ ├── system_versions 版本历史
|
||||
│ ├── upgrade_events 升级事件(A/B/C 分级 + B 类分批编排)
|
||||
│ ├── client_releases 客户端版本发布
|
||||
│ ├── client_heartbeats 客户端启动心跳(活跃统计 + 版本分布)
|
||||
│ ├── feature_flag_definitions Feature Flag 定义(C 类灰度控制平面)
|
||||
│ └── feature_flag_change_log Feature Flag 变更历史(append-only)
|
||||
│
|
||||
@@ -59,6 +66,7 @@ PostgreSQL Instance
|
||||
| `public.system_versions` | 平台版本历史,唯一 current 约束 | §2.5 |
|
||||
| `public.upgrade_events` | 升级/回滚事件,A/B/C 升级类型分级,B 类按租户分批编排 + 健康门控 | §2.5 |
|
||||
| `public.client_releases` | Windows 客户端发布版本,含安装包 URL、SHA256、强制更新标记 | §2.6 |
|
||||
| `public.client_heartbeats` | 客户端启动心跳(活跃统计 + 版本分布支撑) | §2.6 |
|
||||
| `public.feature_flag_definitions` | Feature Flag 全局定义(C 类运行时灰度控制平面) | §2.7 |
|
||||
| `public.tenants.feature_flags` | 租户级 Flag 显式覆盖(`tenants` 表新增 JSONB 列) | §2.7 |
|
||||
| `public.feature_flag_change_log` | Feature Flag 变更历史(append-only) | §2.7 |
|
||||
@@ -538,6 +546,72 @@ CREATE INDEX idx_client_releases_status ON public.client_releases(status, create
|
||||
|
||||
-- 按版本号快速定位(客户端更新检测时传入 current_version 查询)
|
||||
CREATE INDEX idx_client_releases_version ON public.client_releases(version);
|
||||
|
||||
-- ────────────────────────────────────────────────────────────
|
||||
-- 客户端启动心跳表(活跃统计 + 版本分布数据支撑)
|
||||
-- ────────────────────────────────────────────────────────────
|
||||
-- 设计依据: 客户端发布管理模块 PRD §5.5 Story 5(客户端版本分布查询)
|
||||
-- 上报模型: 客户端 App 每次启动时 Upsert 一条记录(by tenant_id + device_id)
|
||||
-- 归属说明: 本表属于 shared_apps(public schema)。虽然 tenant_id 字段做了租户归属,
|
||||
-- 但 device_id 由客户端首次安装时生成(本机 UUID),跨租户全局唯一管理;
|
||||
-- 将本表放在 public schema 便于平台运营做全量版本分布、活跃数统计,
|
||||
-- 避免跨所有 tenant schema 做 UNION ALL。
|
||||
-- 隐私说明: 不收集任何业务数据,仅用于平台运营版本管理与升级决策。
|
||||
|
||||
CREATE TABLE public.client_heartbeats (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
|
||||
-- 归属
|
||||
tenant_id UUID NOT NULL REFERENCES public.tenants(id) ON DELETE CASCADE,
|
||||
-- 心跳上报时所属租户(由客户端登录态决定,从 Tenant Code 解析得到);
|
||||
-- 是"按租户统计安装数 / 活跃数 / 版本分布"的核心维度字段,
|
||||
-- 配合 idx_client_heartbeats_tenant_lastseen 索引支撑租户维度聚合查询;
|
||||
-- 租户被硬删除时心跳一并清理(CASCADE);
|
||||
-- 同一物理设备登录不同租户视作多条独立记录(Upsert 锚点为 (tenant_id, device_id))
|
||||
device_id UUID NOT NULL,
|
||||
-- 客户端首次安装时本机生成并持久化的设备 UUID;
|
||||
-- 卸载重装会变化(视作新设备);同一设备换租户登录视作不同记录
|
||||
user_id UUID,
|
||||
-- 上次启动时登录的用户 ID(指向 tenant schema 的 staff.id);
|
||||
-- 不加外键约束(跨 schema 无法外键),仅作排查辅助;
|
||||
-- 未登录或退出后启动允许为 NULL
|
||||
|
||||
-- 版本与环境
|
||||
client_version VARCHAR(20) NOT NULL,
|
||||
-- 上报时客户端 SemVer 版本号,如 '1.2.3'
|
||||
platform VARCHAR(20) NOT NULL DEFAULT 'win32'
|
||||
CHECK (platform IN ('win32')),
|
||||
arch VARCHAR(10) NOT NULL DEFAULT 'x64'
|
||||
CHECK (arch IN ('x64', 'arm64')),
|
||||
os_version VARCHAR(80),
|
||||
-- 操作系统版本字符串,如 'Windows 10 22H2';可选
|
||||
|
||||
-- 时间戳
|
||||
first_seen_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
-- 该 (tenant_id, device_id) 组合首次心跳时间,Upsert 时不更新
|
||||
last_seen_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
-- 最近一次启动心跳时间,Upsert 时刷新为 NOW()
|
||||
launch_count INTEGER NOT NULL DEFAULT 1,
|
||||
-- 累计启动次数,Upsert 时 +1,用于排查异常高频启动
|
||||
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
|
||||
-- 同一租户下同一设备唯一一条记录(Upsert 锚点)
|
||||
CONSTRAINT uq_client_heartbeats_tenant_device UNIQUE (tenant_id, device_id)
|
||||
);
|
||||
|
||||
-- 活跃数统计("最近 24h 内有心跳")核心索引
|
||||
CREATE INDEX idx_client_heartbeats_last_seen
|
||||
ON public.client_heartbeats(last_seen_at DESC);
|
||||
|
||||
-- 版本分布统计:按版本聚合活跃设备数
|
||||
CREATE INDEX idx_client_heartbeats_version_lastseen
|
||||
ON public.client_heartbeats(client_version, last_seen_at DESC);
|
||||
|
||||
-- 租户维度排查:某租户下所有活跃设备
|
||||
CREATE INDEX idx_client_heartbeats_tenant_lastseen
|
||||
ON public.client_heartbeats(tenant_id, last_seen_at DESC);
|
||||
```
|
||||
|
||||
### 2.7 Feature Flag 灰度体系
|
||||
@@ -644,6 +718,9 @@ CREATE INDEX idx_ff_log_operator ON public.feature_flag_change_log(operator_id,
|
||||
| `client_releases` 唯一 published | `idx_client_releases_published` 部分唯一索引保证同平台+架构下只有一条 `status='published'` |
|
||||
| `client_releases` 不可跨租户隔离 | 本表属于 public schema,所有租户共享;禁止在租户 schema 中创建副本 |
|
||||
| `client_releases.download_count` 原子递增 | 必须使用 `UPDATE ... SET download_count = download_count + 1`,禁止先读后写 |
|
||||
| `client_heartbeats` Upsert 锚点 | 必须使用 `INSERT ... ON CONFLICT (tenant_id, device_id) DO UPDATE SET last_seen_at=NOW(), launch_count=client_heartbeats.launch_count+1, client_version=EXCLUDED.client_version`;禁止先 SELECT 再 INSERT |
|
||||
| `client_heartbeats` 仅启动时上报 | 客户端 App 仅在每次启动时上报一次心跳;不做 4h 周期心跳,避免 public schema 写入压力 |
|
||||
| `client_heartbeats` 不可跨租户隔离 | 本表属于 public schema,所有租户共享;禁止在租户 schema 中创建副本 |
|
||||
| `upgrade_events.gray_tenant_ids` 与 `upgrade_type` 一致性 | A_app 类型必须为空数组(CHECK 约束 `chk_app_upgrade_no_gray` 强制);只有 B_schema 类型才使用灰度名单与批次字段 |
|
||||
| `upgrade_events` 状态流转单向 | 状态机详见 §4.2;`succeeded` / `rolled_back` / `failed` 为终态,禁止再写回中间态 |
|
||||
| `feature_flag_change_log` append-only | 禁止 UPDATE / DELETE;任何 Flag 变更都必须经此表追溯,含 `reason` 强制非空 |
|
||||
@@ -782,11 +859,83 @@ SELECT version, platform, arch, release_type, status,
|
||||
FROM public.client_releases
|
||||
ORDER BY created_at DESC;
|
||||
|
||||
-- 统计各版本活跃客户端数(需结合客户端上报心跳表,当前仅记录下载量)
|
||||
SELECT version, download_count
|
||||
FROM public.client_releases
|
||||
WHERE status IN ('published', 'archived')
|
||||
ORDER BY published_at DESC;
|
||||
-- 客户端启动心跳 Upsert(每次启动调用,原子更新最后活跃时间与启动次数)
|
||||
INSERT INTO public.client_heartbeats (
|
||||
tenant_id, device_id, user_id,
|
||||
client_version, platform, arch, os_version,
|
||||
first_seen_at, last_seen_at, launch_count
|
||||
)
|
||||
VALUES ($1, $2, $3, $4, $5, $6, $7, NOW(), NOW(), 1)
|
||||
ON CONFLICT (tenant_id, device_id) DO UPDATE
|
||||
SET last_seen_at = NOW(),
|
||||
launch_count = public.client_heartbeats.launch_count + 1,
|
||||
client_version = EXCLUDED.client_version,
|
||||
user_id = EXCLUDED.user_id,
|
||||
os_version = EXCLUDED.os_version,
|
||||
updated_at = NOW();
|
||||
|
||||
-- 统计各版本活跃客户端数(活跃 = 最近 24h 内有心跳)
|
||||
SELECT cr.version,
|
||||
cr.status,
|
||||
cr.download_count,
|
||||
COUNT(ch.id) FILTER (
|
||||
WHERE ch.last_seen_at >= NOW() - INTERVAL '24 hours'
|
||||
) AS active_devices_24h,
|
||||
COUNT(ch.id) AS total_devices_ever
|
||||
FROM public.client_releases cr
|
||||
LEFT JOIN public.client_heartbeats ch ON ch.client_version = cr.version
|
||||
WHERE cr.status IN ('published', 'archived')
|
||||
GROUP BY cr.version, cr.status, cr.download_count, cr.published_at
|
||||
ORDER BY cr.published_at DESC;
|
||||
|
||||
-- 平台总活跃数(最近 24h)
|
||||
SELECT COUNT(*) AS active_devices_24h
|
||||
FROM public.client_heartbeats
|
||||
WHERE last_seen_at >= NOW() - INTERVAL '24 hours';
|
||||
|
||||
-- 某租户下活跃设备列表(运营排查)
|
||||
SELECT device_id, client_version, user_id, last_seen_at, launch_count
|
||||
FROM public.client_heartbeats
|
||||
WHERE tenant_id = $1
|
||||
AND last_seen_at >= NOW() - INTERVAL '24 hours'
|
||||
ORDER BY last_seen_at DESC;
|
||||
|
||||
-- ============================================================
|
||||
-- 租户维度安装/活跃统计(Platform Admin 运营看板)
|
||||
-- ============================================================
|
||||
|
||||
-- 某租户当前活跃安装数(最近 24h 内启动过的设备)
|
||||
SELECT COUNT(*) AS active_installs_24h
|
||||
FROM public.client_heartbeats
|
||||
WHERE tenant_id = $1
|
||||
AND last_seen_at >= NOW() - INTERVAL '24 hours';
|
||||
|
||||
-- 某租户历史装机总数(不区分是否活跃,含已离线设备)
|
||||
SELECT COUNT(*) AS total_installs_ever
|
||||
FROM public.client_heartbeats
|
||||
WHERE tenant_id = $1;
|
||||
|
||||
-- 某租户内部各版本分布(识别该租户内升级覆盖率)
|
||||
SELECT client_version,
|
||||
COUNT(*) FILTER (WHERE last_seen_at >= NOW() - INTERVAL '24 hours') AS active_devices_24h,
|
||||
COUNT(*) AS total_devices_ever
|
||||
FROM public.client_heartbeats
|
||||
WHERE tenant_id = $1
|
||||
GROUP BY client_version
|
||||
ORDER BY active_devices_24h DESC;
|
||||
|
||||
-- 全平台租户活跃榜(PRD §5.5 Story 5:按租户维度查看版本分布,识别落后租户)
|
||||
SELECT t.tenant_code,
|
||||
t.name,
|
||||
COUNT(h.id) FILTER (
|
||||
WHERE h.last_seen_at >= NOW() - INTERVAL '24 hours'
|
||||
) AS active_installs_24h,
|
||||
COUNT(h.id) AS total_installs_ever
|
||||
FROM public.tenants t
|
||||
LEFT JOIN public.client_heartbeats h ON h.tenant_id = t.id
|
||||
WHERE t.status = 'active'
|
||||
GROUP BY t.id, t.tenant_code, t.name
|
||||
ORDER BY active_installs_24h DESC;
|
||||
|
||||
-- ============================================================
|
||||
-- 升级编排相关查询(B 类 Schema 迁移分批升级)
|
||||
@@ -878,3 +1027,6 @@ ORDER BY created_at DESC;
|
||||
| v1.0 | 2026-04-24 | 从 `DATA_MODEL.md §三` 独立拆分;内容等价于 v1.2 DATA_MODEL.md §三 |
|
||||
| v1.1 | 2026-04-24 | 新增 §2.6 `client_releases` 表(客户端发布管理);同步更新表清单、约束规则、查询模式 |
|
||||
| v1.2 | 2026-04-26 | 配合系统管理技术文档 v1.2 升级分批专节:§2.5 `upgrade_events` 增加 `upgrade_type`、`gray_tenant_ids`、`batch_size`、`batch_concurrency`、`batch_interval_seconds`、`failure_policy`、`current_batch_no`、`total_batch_count`、`health_gate_config`、`pre_backup_record_id`、`halted_reason` 字段,状态机扩展为 10 态;新增 §2.7 Feature Flag 体系(`feature_flag_definitions` / `tenants.feature_flags` JSONB / `feature_flag_change_log`);同步更新表清单、§4.2 升级状态机、§4.3 Flag 流程、§5.1 查询模式、§5.2 禁止操作 |
|
||||
| v1.3 | 2026-04-30 | 配合登录管理 PRD v2.0 / 系统管理 PRD:§2.1 `tenants` 新增 `tenant_code` (CHAR(12), 全局唯一对外识别码) 与 `contact_phone` (CHAR(11),Tenant Admin 账号创建数据来源),`contact_email` 改为可 NULL;同步更新约束、查询模式 |
|
||||
| v1.4 | 2026-04-30 | 配合客户端发布管理 PRD v1.1 §5.5 Story 5:§2.6 新增 `client_heartbeats` 表(启动时 Upsert by `tenant_id + device_id`,活跃定义为最近 24h 内心跳);同步更新表清单、§三 约束(Upsert 锚点 / 启动上报 / 不可下沉到租户 schema)、§5.1 查询模式(Upsert 模板 + 版本活跃分布 JOIN + 平台总活跃数 + 租户维度排查);MVP 不做升级趋势图(v2 规划) |
|
||||
| v1.5 | 2026-04-30 | 配合客户端发布管理 PRD v1.2 §5.5 Story 5 验收标准追加(按租户统计安装数):① §2.6 `client_heartbeats.tenant_id` 注释强化,明确为"按租户统计安装数 / 活跃数 / 版本分布"的核心维度字段;② §5.1 新增"租户维度安装/活跃统计"查询专区(4 个查询:某租户活跃安装数 / 历史装机总数 / 租户内版本分布 / 全平台租户活跃榜) |
|
||||
|
||||
@@ -9,6 +9,12 @@
|
||||
|
||||
---
|
||||
|
||||
## 变更历史
|
||||
|
||||
| 日期 | 变更人 | 变更内容 |
|
||||
|---|---|---|
|
||||
| 2026-04-30 | Atlas | 补充“变更历史”章节(文档治理) |
|
||||
|
||||
## 一、模块定位与架构边界
|
||||
|
||||
### 1.1 系统配置模块职责
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
|
||||
`DATA_MODEL.md` 的核心目标是:**让 AI 在触碰任何数据相关代码时,都能理解业务语义,而不只是看到一堆字段名。**
|
||||
|
||||
---
|
||||
@@ -11,6 +12,7 @@
|
||||
md
|
||||
|
||||
```md
|
||||
|
||||
## Domain Overview
|
||||
|
||||
This is a **multi-tenant** project management tool.
|
||||
@@ -259,4 +261,4 @@ md
|
||||
|
||||
---
|
||||
|
||||
**核心原则**:`DATA_MODEL.md` 写的不是给数据库看的 DDL,而是给 AI 看的**业务契约**。每一个"显而易见"的业务规则,在 AI 眼里都是需要被明确告知的约束。没写的,它都会自己猜。
|
||||
**核心原则**:`DATA_MODEL.md` 写的不是给数据库看的 DDL,而是给 AI 看的**业务契约**。每一个"显而易见"的业务规则,在 AI 眼里都是需要被明确告知的约束。没写的,它都会自己猜。
|
||||
|
||||
@@ -13,6 +13,12 @@
|
||||
|
||||
---
|
||||
|
||||
## 变更历史
|
||||
|
||||
| 日期 | 变更人 | 变更内容 |
|
||||
|---|---|---|
|
||||
| 2026-04-30 | Atlas | 补充“变更历史”章节(文档治理) |
|
||||
|
||||
## 一、枚举分层标准(必须遵守)
|
||||
|
||||
Fonrey 采用两层枚举体系:
|
||||
|
||||
@@ -1,111 +0,0 @@
|
||||
# Schema 变更记录
|
||||
|
||||
> **用途**:记录在初始 Model 创建之后新增/修改的字段,供架构师逐一更新 Migration 脚本。
|
||||
> **格式**:每条变更含目标表、变更类型、字段定义、变更原因、来源 PRD 依据。
|
||||
> **状态流转**:`待迁移` → `已迁移`(架构师完成 migration 后更新状态)
|
||||
|
||||
---
|
||||
|
||||
## 变更清单
|
||||
|
||||
| # | 状态 | 目标表 | 变更类型 | 字段名 | 提出日期 |
|
||||
|---|------|--------|----------|--------|----------|
|
||||
| 1 | 待迁移 | `public.tenants` | 新增字段 | `tenant_code` | 2026-04-30 |
|
||||
| 2 | 待迁移 | `public.tenants` | 新增字段 | `contact_phone` | 2026-04-30 |
|
||||
| 3 | 待迁移 | `public.tenants` | 字段修改 | `contact_email`(NOT NULL → 可 NULL) | 2026-04-30 |
|
||||
|
||||
---
|
||||
|
||||
## 变更详情
|
||||
|
||||
### #1 — `public.tenants` 新增 `tenant_code`
|
||||
|
||||
**状态**:待迁移
|
||||
**提出日期**:2026-04-30
|
||||
**目标表**:`public.tenants`(Public Schema,django-tenants 主租户表)
|
||||
|
||||
**字段定义**:
|
||||
```sql
|
||||
tenant_code CHAR(12) UNIQUE NOT NULL
|
||||
```
|
||||
|
||||
**注释**:对外暴露的 12 位纯数字识别码,如 `202500010001`;用户首次登录客户端时输入;由平台运营在注册租户时生成;创建后不可修改。
|
||||
|
||||
**推荐加在**:`schema_name` 字段之后,`name` 字段之前。
|
||||
|
||||
**约束要求**:
|
||||
- `CHAR(12)`:固定 12 位
|
||||
- `UNIQUE`:全局唯一
|
||||
- `NOT NULL`:注册时必填
|
||||
- 禁止 `UPDATE`(应用层 + DB 层双重约束,与 `schema_name` 同等级别)
|
||||
|
||||
**建议索引**:
|
||||
```sql
|
||||
CREATE UNIQUE INDEX idx_tenants_tenant_code ON public.tenants(tenant_code);
|
||||
```
|
||||
|
||||
**变更原因**:
|
||||
登录 PRD §5.1.3 明确用户输入 12 位 Tenant Code 完成租户识别,服务端需通过该码查找对应 `schema_name`,原始 `public.tenants` 表中缺少此字段。
|
||||
|
||||
**PRD 依据**:
|
||||
`PRD/登录管理/用户登录管理模块PRD.md` §5.1.3 — Tenant Code 格式规范:
|
||||
> 格式:固定 12 位纯数字,如 `202500010001`
|
||||
|
||||
**登录查询示例**:
|
||||
```sql
|
||||
SELECT schema_name, name
|
||||
FROM public.tenants
|
||||
WHERE tenant_code = '202500010001'
|
||||
AND status = 'active';
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### #2 — `public.tenants` 新增 `contact_phone`
|
||||
|
||||
**状态**:待迁移
|
||||
**提出日期**:2026-04-30
|
||||
**目标表**:`public.tenants`(Public Schema)
|
||||
|
||||
**字段定义**:
|
||||
```sql
|
||||
contact_phone CHAR(11) NOT NULL
|
||||
```
|
||||
|
||||
**注释**:联系人手机号(11位纯数字);系统开通租户时自动以此手机号创建 Tenant Admin 登录账号;必填字段,平台运营在创建租户时录入。
|
||||
|
||||
**推荐加在**:`contact_name` 字段之后,`contact_email` 字段之前。
|
||||
|
||||
**约束要求**:
|
||||
- `CHAR(11)`:固定 11 位手机号
|
||||
- `NOT NULL`:开通租户时必填
|
||||
|
||||
**变更原因**:
|
||||
登录 PRD v1.5 决策:Tenant Admin 账号统一以联系人手机号作为用户名,与普通员工账号规则对齐。需在 tenants 表增加手机号字段作为 Tenant Admin 账号创建的数据来源。
|
||||
|
||||
**PRD 依据**:
|
||||
`PRD/登录管理/用户登录管理模块PRD.md` §5.3.2 Tenant Admin 账号规格表
|
||||
|
||||
---
|
||||
|
||||
### #3 — `public.tenants.contact_email` 改为可 NULL
|
||||
|
||||
**状态**:待迁移
|
||||
**提出日期**:2026-04-30
|
||||
**目标表**:`public.tenants`(Public Schema)
|
||||
|
||||
**变更 SQL**:
|
||||
```sql
|
||||
ALTER TABLE public.tenants
|
||||
ALTER COLUMN contact_email DROP NOT NULL;
|
||||
```
|
||||
|
||||
**变更原因**:
|
||||
`contact_email` 原为 `NOT NULL`。由于 Tenant Admin 账号创建数据来源改为 `contact_phone`(手机号,必填),邮箱降级为选填,仅用于找回密码功能。为空时 Tenant Admin 无法自助找回密码,需联系平台运营处理。
|
||||
|
||||
**PRD 依据**:
|
||||
`PRD/登录管理/用户登录管理模块PRD.md` §5.3.2
|
||||
|
||||
---
|
||||
|
||||
*后续如有新增字段,按同样格式追加到本文件。*
|
||||
@@ -7,6 +7,13 @@
|
||||
|
||||
> **For AI assistants**: 本文件定义 Phase 1(MVP)的边界。在任何功能实现前,先对照本文确认是否在范围内。范围外的功能禁止在 MVP 阶段实现。
|
||||
|
||||
## 变更历史
|
||||
|
||||
| 版本 | 日期 | 作者 | 变更说明 |
|
||||
|------|------|------|---------|
|
||||
| v1.0 | 2026-04-24 | Product Team | 初稿:定义 Phase 1(MVP)边界与范围 |
|
||||
|
||||
|
||||
---
|
||||
|
||||
## 1. 产品背景与目标
|
||||
|
||||
@@ -1,11 +1,20 @@
|
||||
# PRD: 客户端发布管理模块
|
||||
**状态**: Draft
|
||||
**作者**: 产品经理
|
||||
**最后更新**: 2026-04-24(v1.0 初稿)
|
||||
**版本**: 1.0
|
||||
**最后更新**: 2026-04-30(v1.2)
|
||||
**版本**: 1.2
|
||||
**所属系统**: Fonrey 房产经纪管理系统
|
||||
**关联模块**: 系统管理、权限管理
|
||||
**干系人**: 工程负责人、运维负责人、Tenant Admin(租户管理员)
|
||||
**关联模块**: 系统管理
|
||||
**干系人**: 工程负责人、运维负责人、Platform Admin(平台超级管理员)
|
||||
|
||||
## 变更历史
|
||||
|
||||
| 版本 | 日期 | 作者 | 变更说明 |
|
||||
|------|------|------|---------|
|
||||
| v1.0 | 2026-04-24 | 产品经理 | 初稿 |
|
||||
| v1.1 | 2026-04-30 | 产品经理 | Persona 与命名修正:① Story 4 / Story 5 责任角色由 Tenant Admin(租户管理员)修正为 Platform Admin(平台超级管理员),客户端版本上传与版本分布监控属于平台运营职责,跨租户统一管理;② §5.3 版本管理后台从"租户系统管理模块"迁移至"平台运营后台",明确 public schema 跨租户、Tenant Admin 与 Agent 无访问权限、不配置 RBAC permission_code;③ 全部 API 路径 `/api/client/updates/...` 重命名为 `/api/release/updates/...`,避免与客源管理模块(apps/client/)命名空间冲突,与 AGENTS.md §3 的 `apps/release/` 目录约定对齐;④ 头部"关联模块"由"系统管理、权限管理"修订为"系统管理"(不再涉及租户 RBAC);⑤ 干系人列表 Tenant Admin → Platform Admin。 |
|
||||
| v1.2 | 2026-04-30 | 产品经理 | Story 5 验收标准追加"按租户统计安装数"能力:① 新增验收项——可查看任意租户的"当前活跃安装数(最近 24h)"与"历史装机总数";② 新增验收项——全平台租户活跃榜视图,按 `tenant_code` + 租户名称 + 活跃安装数 + 历史装机数列表展示,按活跃安装数降序。底层数据由 `public.client_heartbeats` 表的 `tenant_id` 维度聚合提供(详见 DATA_MODEL_PUBLIC v1.5 §5.1 租户维度安装/活跃统计查询专区)。 |
|
||||
|
||||
|
||||
---
|
||||
|
||||
@@ -26,7 +35,7 @@ Fonrey 房产经纪管理系统当前为纯 Web 应用,依赖用户自行通
|
||||
|------|---------|----------|
|
||||
| Agent(经纪人) | 下载安装客户端、日常登录使用系统、接受自动更新 | 每日 |
|
||||
| 店长/经理 | 同上 | 每日 |
|
||||
| Tenant Admin(租户管理员) | 发布新版本、管理安装包下载地址、监控客户端版本分布 | 按需 |
|
||||
| Platform Admin(平台超级管理员) | 发布新版本、管理安装包下载地址、监控客户端版本分布 | 按需 |
|
||||
| IT 运维人员 | 维护更新服务器、签名证书、构建发布流水线 | 按发布周期 |
|
||||
|
||||
### 核心痛点
|
||||
@@ -108,12 +117,12 @@ Fonrey 房产经纪管理系统当前为纯 Web 应用,依赖用户自行通
|
||||
|
||||
---
|
||||
|
||||
### Story 4:Tenant Admin(租户管理员)发布新版本
|
||||
### Story 4:Platform Admin(平台超级管理员)发布新版本
|
||||
|
||||
**As** Tenant Admin(租户管理员),**I want** 通过管理后台上传新版客户端安装包并配置版本信息,**So that** 客户端能感知到更新并引导用户升级。
|
||||
**As** Platform Admin(平台超级管理员),**I want** 通过平台运营后台上传新版客户端安装包并配置版本信息,**So that** 全平台所有租户的客户端能感知到更新并引导用户升级。
|
||||
|
||||
**验收标准**:
|
||||
- [ ] 系统管理后台提供"客户端版本管理"页面(位于系统管理模块下)
|
||||
- [ ] 平台运营后台提供"客户端版本管理"页面(位于平台运营后台下,不在租户系统管理模块)
|
||||
- [ ] 支持上传 `.exe` 安装包,并填写版本号(遵循 SemVer:`X.Y.Z`)、版本说明(更新日志,支持 Markdown)、发布日期
|
||||
- [ ] 支持设置版本类型:普通更新 / 强制更新
|
||||
- [ ] 支持设置版本状态:草稿(不对外生效)/ 已发布 / 已下线
|
||||
@@ -123,13 +132,15 @@ Fonrey 房产经纪管理系统当前为纯 Web 应用,依赖用户自行通
|
||||
|
||||
---
|
||||
|
||||
### Story 5:管理员监控客户端版本分布
|
||||
### Story 5:Platform Admin(平台超级管理员)监控客户端版本分布
|
||||
|
||||
**As** Tenant Admin(租户管理员),**I want** 查看当前所有在线客户端的版本分布情况,**So that** 了解升级覆盖率,对仍在使用旧版本的客户端发出提醒或强制升级。
|
||||
**As** Platform Admin(平台超级管理员),**I want** 跨租户查看当前所有在线客户端的版本分布情况,**So that** 了解全平台升级覆盖率,对仍在使用旧版本的客户端发出提醒或强制升级。
|
||||
|
||||
**验收标准**:
|
||||
- [ ] 客户端版本管理页面展示版本分布统计:各版本在线客户端数量及占比(饼图或条形图)
|
||||
- [ ] 支持按租户维度查看版本分布(多租户场景下,区分不同经纪公司的版本使用情况)
|
||||
- [ ] 支持按租户维度查看版本分布(区分不同经纪公司的版本使用情况,便于平台超管识别落后租户)
|
||||
- [ ] 支持**按租户统计安装数**:可查看任意租户的"当前活跃安装数(最近 24h)"与"历史装机总数(不论是否活跃)",用于评估各租户的客户端覆盖率与渗透率
|
||||
- [ ] 支持全平台租户活跃榜视图:以列表形式展示各 active 状态租户的 `tenant_code`、租户名称、活跃安装数、历史装机总数,按活跃安装数降序排列
|
||||
- [ ] 支持对指定版本范围的用户推送"强制更新"通知(如:将所有低于 v1.5.0 的客户端标记为强制更新)
|
||||
|
||||
---
|
||||
@@ -178,7 +189,7 @@ Fonrey 房产经纪管理系统当前为纯 Web 应用,依赖用户自行通
|
||||
客户端启动 / 定时检测(每4小时)
|
||||
│
|
||||
▼
|
||||
GET /api/client/updates/latest?platform=win32&arch=x64¤t_version=1.2.0
|
||||
GET /api/release/updates/latest?platform=win32&arch=x64¤t_version=1.2.0
|
||||
│
|
||||
▼
|
||||
更新服务器(Fonrey 后端 Django API)
|
||||
@@ -201,10 +212,10 @@ GET /api/client/updates/latest?platform=win32&arch=x64¤t_version=1.2.0
|
||||
|
||||
| 端点 | 方法 | 说明 |
|
||||
|------|------|------|
|
||||
| `/api/client/updates/latest/` | GET | 客户端查询最新版本,返回版本信息和下载 URL |
|
||||
| `/api/client/updates/` | GET | 管理端查询版本列表(需认证) |
|
||||
| `/api/client/updates/` | POST | 管理端发布新版本(需管理员权限) |
|
||||
| `/api/client/updates/<id>/` | PATCH | 管理端修改版本状态(发布/下线/强制) |
|
||||
| `/api/release/updates/latest/` | GET | 客户端查询最新版本,返回版本信息和下载 URL |
|
||||
| `/api/release/updates/` | GET | 管理端查询版本列表(需认证) |
|
||||
| `/api/release/updates/` | POST | 管理端发布新版本(需管理员权限) |
|
||||
| `/api/release/updates/<id>/` | PATCH | 管理端修改版本状态(发布/下线/强制) |
|
||||
|
||||
---
|
||||
|
||||
@@ -259,9 +270,11 @@ GET /api/client/updates/latest?platform=win32&arch=x64¤t_version=1.2.0
|
||||
|
||||
---
|
||||
|
||||
### 5.3 版本管理后台(系统管理模块新增页面)
|
||||
### 5.3 版本管理后台(平台运营后台新增页面)
|
||||
|
||||
**页面路径**:系统管理 → 客户端发布管理
|
||||
**页面路径**:平台运营后台 → 客户端发布管理
|
||||
|
||||
> **归属说明**:本页面归属 Platform Admin(平台超级管理员),位于平台运营后台(public schema 跨租户),不在租户的"系统管理"模块下。Tenant Admin 与 Agent 均无访问权限。
|
||||
|
||||
#### 5.3.1 版本列表
|
||||
|
||||
@@ -300,7 +313,7 @@ GET /api/client/updates/latest?platform=win32&arch=x64¤t_version=1.2.0
|
||||
|
||||
### 5.4 更新 API 规格
|
||||
|
||||
#### GET `/api/client/updates/latest/`
|
||||
#### GET `/api/release/updates/latest/`
|
||||
|
||||
**请求参数(Query String)**:
|
||||
|
||||
@@ -346,7 +359,7 @@ GET /api/client/updates/latest?platform=win32&arch=x64¤t_version=1.2.0
|
||||
| EV 代码签名证书 | 需提前申请,EV 证书审核周期 1-2 周 | IT/运维 | 中(需提前排期) |
|
||||
| Cloudflare R2 存储桶 | 存放安装包,利用现有账号新增 bucket | 运维 | 低 |
|
||||
| `electron-updater` | 自动更新库,需配合更新 API 端点实现 | 客户端工程师 | 低 |
|
||||
| Django 更新 API | 新增 `/api/client/updates/` 相关接口 | 后端工程师 | 低 |
|
||||
| Django 更新 API | 新增 `/api/release/updates/` 相关接口 | 后端工程师 | 低 |
|
||||
| CI/CD 构建流水线 | 自动构建、签名、上传安装包 | 运维/DevOps | 中 |
|
||||
|
||||
### 6.2 已知风险
|
||||
|
||||
@@ -6,6 +6,14 @@
|
||||
**所属系统**: Fonrey 房产经纪管理系统
|
||||
**关联模块**: 房源管理、组织人事管理、权限管理
|
||||
|
||||
## 变更历史
|
||||
|
||||
| 版本 | 日期 | 作者 | 变更说明 |
|
||||
|------|------|------|---------|
|
||||
| v1.0 | — | 产品经理 | 初稿 |
|
||||
| v1.4 | 2026-04-23 | 产品经理 | 新增客源信息概览/编辑基础信息/收藏/改等级/改状态/转公客/转成交/转无效/联系人管理/相关员工管理/操作日志章节及 Story 15-24,基于 35 张截图分析完成 |
|
||||
|
||||
|
||||
---
|
||||
|
||||
## 1. 问题陈述
|
||||
|
||||
@@ -6,6 +6,14 @@
|
||||
**所属系统**: Fonrey 房产经纪管理系统
|
||||
**关联模块**: 客源管理、组织人事管理、权限管理
|
||||
|
||||
## 变更历史
|
||||
|
||||
| 版本 | 日期 | 作者 | 变更说明 |
|
||||
|------|------|------|---------|
|
||||
| v1.0 | — | 产品经理 | 初稿 |
|
||||
| v2.1 | 2026-04-23 | 产品经理 | 重写 §8.3 相关截图参考:修正所有路径拼写错误(sreenshots→screenshots);补充全部未收录截图(房源详情1-3、房源备注、价格解读、市场报盘、全部商铺、全部写字楼、附件信息、编辑业主联系人、小区/楼盘管理全部截图);按文档章节分组重新整理为表格格式 |
|
||||
|
||||
|
||||
---
|
||||
|
||||
## 1. 问题陈述
|
||||
|
||||
@@ -6,6 +6,13 @@
|
||||
**所属系统**: Fonrey 房产经纪管理系统
|
||||
**关联模块**: 房源管理、客源管理、组织人事管理、权限管理
|
||||
|
||||
## 变更历史
|
||||
|
||||
| 版本 | 日期 | 作者 | 变更说明 |
|
||||
|------|------|------|---------|
|
||||
| v1.0 | 2026-04-23 | 产品经理 | 初稿,基于楼盘管理列表、楼盘详情(楼盘信息/楼栋管理/结构管理/楼盘照片/楼盘价格走势/周边配套)、区域管理(城区/商圈/关联关系)、学校管理共 14 张截图分析完成 |
|
||||
|
||||
|
||||
---
|
||||
|
||||
## 1. 问题陈述
|
||||
|
||||
@@ -6,6 +6,14 @@
|
||||
**所属系统**: Fonrey 房产经纪管理系统
|
||||
**关联模块**: 组织人事管理、房源管理、客源管理、系统设置
|
||||
|
||||
## 变更历史
|
||||
|
||||
| 版本 | 日期 | 作者 | 变更说明 |
|
||||
|------|------|------|---------|
|
||||
| v1.0 | — | 产品经理 | 初稿 |
|
||||
| v1.1 | 2026-04-24 | 产品经理 | 锁定多角色合并规则 = 并集 / 最宽松 |
|
||||
|
||||
|
||||
---
|
||||
|
||||
## 1. 问题陈述
|
||||
|
||||
@@ -7,6 +7,14 @@
|
||||
**所属系统**: Fonrey 房产经纪管理系统
|
||||
**关联模块**: 组织人事管理、权限管理、系统管理
|
||||
|
||||
## 变更历史
|
||||
|
||||
| 版本 | 日期 | 作者 | 变更说明 |
|
||||
|------|------|------|---------|
|
||||
| v1.x | — | 产品经理 | 初稿至 v1.9(详见 git 历史) |
|
||||
| v2.0 | 2026-04-30 | 产品经理 | 根据 review 后的 §4 用户故事全面同步 §5 功能详细说明:删除找回用户名流程及邮件模板;找回密码改为纯短信流程;新增 §5.5 手机验证码登录详细说明;§6 技术注意事项更新短信依赖/风险/开放问题;§8.2 接口清单同步正式功能状态;全文「Tenant ID」对外概念统一替换为「Tenant Code」 |
|
||||
|
||||
|
||||
---
|
||||
|
||||
## 1. 问题陈述
|
||||
|
||||
@@ -6,6 +6,13 @@
|
||||
**版本**:v1.0
|
||||
**利益相关方**:工程负责人、运营团队、安全合规、客户成功团队
|
||||
|
||||
## 变更历史
|
||||
|
||||
| 版本 | 日期 | 作者 | 变更说明 |
|
||||
|------|------|------|---------|
|
||||
| v1.0 | 2026-04-24 | 产品经理 | 初稿 |
|
||||
|
||||
|
||||
---
|
||||
|
||||
## 1. 问题陈述
|
||||
|
||||
@@ -7,6 +7,13 @@
|
||||
**关联 Task**:US-SETTING-001
|
||||
**相关文档**:`DATA_MODEL/ENUMS.md`、`PRD/系统配置/系统配置参数数据.md`、`DATA_MODEL/DATA_MODEL.md`
|
||||
|
||||
## 变更历史
|
||||
|
||||
| 版本 | 日期 | 作者 | 变更说明 |
|
||||
|------|------|------|---------|
|
||||
| v0.1 | 2026-04-27 | Nova(PM) | 初稿(MVP 范围) |
|
||||
|
||||
|
||||
---
|
||||
|
||||
## 1. 问题陈述
|
||||
|
||||
@@ -6,6 +6,15 @@
|
||||
**所属系统**: Fonrey 房产经纪管理系统
|
||||
**关联模块**: 权限管理、房源管理、客源管理、系统设置
|
||||
|
||||
## 变更历史
|
||||
|
||||
| 版本 | 日期 | 作者 | 变更说明 |
|
||||
|------|------|------|---------|
|
||||
| v1.0 | — | 产品经理 | 初稿 |
|
||||
| v1.1 | — | 产品经理 | (详见 git 历史) |
|
||||
| v1.2 | 2026-04-24 | 产品经理 | 移除技术实现章节,该部分由独立 DATA_MODEL 文档承载 |
|
||||
|
||||
|
||||
---
|
||||
|
||||
## 1. 问题陈述
|
||||
|
||||
@@ -9,6 +9,12 @@
|
||||
|
||||
---
|
||||
|
||||
## 变更历史
|
||||
|
||||
| 日期 | 变更人 | 变更内容 |
|
||||
|---|---|---|
|
||||
| 2026-04-30 | Atlas | 补充“变更历史”章节(文档治理) |
|
||||
|
||||
## 1. 文档定位与原则
|
||||
|
||||
本文件定义 Fonrey 全局 API 契约标准,解决跨模块接口风格漂移问题。模块技术方案中的 API 章节必须遵循本文件,不得各自定义冲突规则。
|
||||
@@ -477,7 +483,7 @@ git diff --exit-code openapi.json || echo "⚠️ openapi.json has changed —
|
||||
# 对本地运行的 dev server 跑契约测试
|
||||
schemathesis run openapi.json \
|
||||
--base-url http://localhost:8000 \
|
||||
--auth-header "Authorization: Bearer $TEST_TOKEN" \
|
||||
--auth-header "Authorization: Bearer *** \
|
||||
--checks status_code_conformance response_schema_conformance \
|
||||
--tag property # 可按模块 tag 分批跑
|
||||
```
|
||||
|
||||
@@ -1,3 +1,9 @@
|
||||
## 变更历史
|
||||
|
||||
| 日期 | 变更人 | 变更内容 |
|
||||
|---|---|---|
|
||||
| 2026-04-30 | Atlas | 补充“变更历史”章节(文档治理) |
|
||||
|
||||
#### 1. 项目概览(Project Overview)
|
||||
|
||||
用 2-3 句话说清楚这是什么项目、核心用途、目标用户。AI 需要这个"北极星"来判断所有技术取舍。
|
||||
@@ -5,6 +11,7 @@
|
||||
md
|
||||
|
||||
```md
|
||||
|
||||
## Project Overview
|
||||
A B2B SaaS invoice management tool. Target users are SMB accountants.
|
||||
Prioritize reliability and data integrity over flashy UI.
|
||||
@@ -158,4 +165,4 @@ md
|
||||
|🟡 重要|关键约定|保持风格一致|
|
||||
|🟢 加分|测试策略 + 代码风格|提升整体质量|
|
||||
|
||||
**核心原则**:写给 AI 看的文档要比写给人看的**更具体、更强硬、更少歧义**。任何"视情况而定"的描述,AI 都会做出你不想要的选择。
|
||||
**核心原则**:写给 AI 看的文档要比写给人看的**更具体、更强硬、更少歧义**。任何"视情况而定"的描述,AI 都会做出你不想要的选择。
|
||||
|
||||
@@ -2,11 +2,18 @@
|
||||
|
||||
> **For AI assistants**: Read this entire file before writing any code. All decisions here are final. Do not suggest alternatives unless asked.
|
||||
|
||||
**版本**: 2.3 | **最后更新**: 2026-04-29
|
||||
**版本**: 2.5 | **最后更新**: 2026-04-30
|
||||
**定位**: 本文档是 Fonrey 项目技术栈的**总索引**。所有跨模块的技术决策、版本约束、目录规范、禁止项在此定稿;**单一模块的具体技术方案**(数据模型、服务层、HTMX 交互、Celery 任务等)见各自子文档(见 §9 索引)。
|
||||
|
||||
---
|
||||
|
||||
## 变更历史
|
||||
|
||||
| 日期 | 变更人 | 变更内容 |
|
||||
|---|---|---|
|
||||
| 2026-04-30 | Atlas | 新增 ADR 导航入口与变更治理规则(README 缺失场景下接入 TECH_STACK / DATA_MODEL / AGENTS) |
|
||||
| 2026-04-30 | Atlas | 补充“变更历史”章节(文档治理) |
|
||||
|
||||
## 1. 项目概览
|
||||
|
||||
**Fonrey(房睿)房产经纪管理系统** —— 面向房地产经纪公司的 B2B SaaS 平台,解决房源/客源信息散乱、跟进缺失、重复录入等痛点,支撑单租户 89,000+ 房源数据量级下的高效匹配。
|
||||
@@ -115,11 +122,11 @@ apps/property/
|
||||
|
||||
## 7. 客户端发布技术栈(Desktop Client)
|
||||
|
||||
> **完整方案**见 PRD:`PRD/发布管理/客户端发布管理模块PRD.md`。本节仅列最终结论。
|
||||
> **完整方案**见:`TECH_STACK/客户端发布管理技术方案.md`(实现口径)与 `PRD/发布管理/客户端发布管理模块PRD.md`(需求口径)。本节仅列最终结论。
|
||||
|
||||
- **框架**:Electron(稳定版) + Chromium 内核(随版本固定,不依赖系统浏览器)
|
||||
- **渲染层**:直接加载 Fonrey Web URL,**100% 复用 HTMX + Alpine + Tailwind**,渲染层零新增框架
|
||||
- **自动更新**:`electron-updater`;更新包存 R2 / 经 CDN 分发;后端检测端点 `GET /api/client/updates/latest/`(公开);启动时 + 每 4h 轮询;后台静默下载,下载完成提示重启;服务端可标记强制更新
|
||||
- **自动更新**:`electron-updater`;更新包存 R2 / 经 CDN 分发;后端检测端点 `GET /api/release/updates/latest/`(公开);启动时 + 每 4h 轮询;后台静默下载,下载完成提示重启;服务端可标记强制更新
|
||||
- **构建**:`electron-builder` 输出 NSIS `.exe` + 便携版 `.zip`;目标 Windows x64(优先),ARM64 按需
|
||||
- **代码签名**:EV 证书,CI/CD 自动签名,消除 SmartScreen 警告
|
||||
- **完整性校验**:下载后必须校验 SHA256 与服务端返回一致才能安装
|
||||
@@ -140,11 +147,12 @@ apps/property/
|
||||
| 楼盘管理 | [`楼盘管理技术方案.md`](./楼盘管理技术方案.md) | `PRD/房源管理/`(含楼盘) | `DATA_MODEL/DATA_MODEL_COMPLEX.md` | `tests/integration/complex/test_us_complex.py` | `v1.0` |
|
||||
| 组织人事 | [`组织人事技术方案.md`](./组织人事技术方案.md) | `PRD/组织人事管理/` | `DATA_MODEL/DATA_MODEL_ORG.md` | `tests/integration/org/test_us_org.py` | `v1.0` |
|
||||
| 系统设置 | [`系统设置技术方案.md`](./系统设置技术方案.md) | `PRD/系统配置/`、`PRD/系统管理/` | `DATA_MODEL/DATA_MODEL_SETTING.md` | `tests/integration/setting/test_us_setting.py` | `v1.2` |
|
||||
| 客户端发布 | 见本文档 §7 | `PRD/发布管理/客户端发布管理模块PRD.md` | — | — | `§7(本文)` |
|
||||
| 客户端发布 | [`客户端发布管理技术方案.md`](./客户端发布管理技术方案.md) | `PRD/发布管理/客户端发布管理模块PRD.md` | `DATA_MODEL/DATA_MODEL_PUBLIC.md`(`client_releases` / `client_heartbeats`) | `tests/integration/release/test_us_release.py` | `v1.0` |
|
||||
|
||||
**总览数据模型**:[`DATA_MODEL/DATA_MODEL.md`](../DATA_MODEL/DATA_MODEL.md)
|
||||
**全局 API 契约**:[`API_CONTRACT.md`](./API_CONTRACT.md)
|
||||
**MVP 范围与产品总览**:[`PRD/PRD_MVP.md`](../PRD/PRD_MVP.md)
|
||||
**ADR 动态决策记录**:[`ADR.md`](../ADR.md)
|
||||
|
||||
---
|
||||
|
||||
@@ -172,7 +180,7 @@ apps/property/
|
||||
| 14 | 落地顺序建议 |
|
||||
| 15 | 文档同步规则 |
|
||||
|
||||
### 9.2 模块覆盖情况(2026-04-27)
|
||||
### 9.2 模块覆盖情况(2026-04-30)
|
||||
|
||||
| 模块 | 技术方案文档 | 15 章节覆盖 | 备注 |
|
||||
|---|---|---:|---|
|
||||
@@ -183,6 +191,7 @@ apps/property/
|
||||
| 楼盘管理 | `楼盘管理技术方案.md` | 15/15 | 完全覆盖 |
|
||||
| 组织人事 | `组织人事技术方案.md` | 15/15 | 完全覆盖 |
|
||||
| 系统设置 | `系统设置技术方案.md` | 15/15 | 完全覆盖 |
|
||||
| 客户端发布 | `客户端发布管理技术方案.md` | 15/15 | 新增,已覆盖 Electron/EV/Heartbeat/自动升级/R2/官网下载/便携版 |
|
||||
|
||||
### 9.3 使用规则(对 AI Agent 生效)
|
||||
|
||||
@@ -238,6 +247,9 @@ Fonrey 采用 AI vibe coding 模式开发,测试是保证每日迭代质量的
|
||||
- API 契约总则在 `API_CONTRACT.md` 维护;模块文档只做模块特化,不得覆盖全局契约
|
||||
- 任何技术栈变更(替换组件、升级主版本、新增外部服务)须同步更新本文档 §2、§5、§6
|
||||
- 新增模块时,先在 §4 目录结构补位,再在 §8 索引登记子文档
|
||||
- 涉及跨模块规则、接口口径、测试治理、范围边界的决策,必须先写入 `ADR.md`(新增 accepted 记录)再改 TECH_STACK/PRD/DATA_MODEL/TEST_CASES
|
||||
- 若已有决策被替代,必须在 `ADR.md` 新增 superseded 记录并显式关联新 ADR;禁止静默改文档覆盖历史
|
||||
- 提交 PR 时,若变更命中上述决策域,必须在描述中附 ADR ID(如 `ADR-20260430-011`)
|
||||
- 测试规范变更须同步更新 §10 关键结论,完整细节在 [`测试规范.md`](./测试规范.md) 中维护
|
||||
- 15 章节统一模板发生变更时,须先更新 §9 标准章节骨架,再同步各模块文档
|
||||
|
||||
@@ -448,5 +460,3 @@ class ScopedModel(models.Model):
|
||||
| own | 员工查自己负责的数据 | 返回数据 ✅ |
|
||||
| department | 店长查本部门数据 | 按角色返回 ✅ |
|
||||
| cross_department_denied | 普通员工跨部门查询 | 空集或 403 ✅ |
|
||||
|
||||
|
||||
|
||||
330
Project/fonrey/TECH_STACK/客户端发布管理技术方案.md
Normal file
330
Project/fonrey/TECH_STACK/客户端发布管理技术方案.md
Normal file
@@ -0,0 +1,330 @@
|
||||
> **For AI assistants**: Read this entire file before writing any code. All decisions here are final. Do not suggest alternatives unless asked.
|
||||
|
||||
# Fonrey 客户端发布管理技术方案
|
||||
|
||||
**版本**: 1.0
|
||||
**项目**: Fonrey 房产经纪管理系统
|
||||
**技术栈**: Django 4.x + HTMX + PostgreSQL 16(public schema)+ Redis + Celery + Electron + electron-updater + Cloudflare R2/CDN
|
||||
**关联 PRD**: `PRD/发布管理/客户端发布管理模块PRD.md`(v1.2)
|
||||
**关联数据模型**: `DATA_MODEL/DATA_MODEL_PUBLIC.md`(`client_releases` / `client_heartbeats`)
|
||||
**关联枚举字典**: `DATA_MODEL/ENUMS.md`(含中文显示标签)
|
||||
**关联契约规范**: `TECH_STACK/API_CONTRACT.md`
|
||||
**最后更新**: 2026-04-30
|
||||
|
||||
---
|
||||
|
||||
## 变更历史
|
||||
|
||||
| 日期 | 变更人 | 变更内容 |
|
||||
|---|---|---|
|
||||
| 2026-04-30 | Atlas | 补充“变更历史”章节(文档治理) |
|
||||
|
||||
## 一、文档定位与边界
|
||||
|
||||
本文件定义客户端发布管理模块(`apps/release`)的实现口径:
|
||||
|
||||
1. Electron 客户端壳应用与运行时安全边界
|
||||
2. EV 代码签名与构建发布链路
|
||||
3. Heartbeat 上报与版本分布统计方案
|
||||
4. 自动升级、强制升级与失败回退策略
|
||||
5. 客户端下载完整性校验(SHA256)
|
||||
6. R2 版本资产管理(对象键、状态流转、回滚)
|
||||
7. 公司下载站点(官网)分发方案
|
||||
8. 便携版(Portable ZIP)落地方案
|
||||
|
||||
> 本文件不重复 DDL。表结构与索引以 `DATA_MODEL_PUBLIC.md` 为唯一权威。
|
||||
|
||||
---
|
||||
|
||||
## 二、范围定义(以 PRD v1.2 为准)
|
||||
|
||||
### 2.1 P0 必须覆盖
|
||||
|
||||
- Windows 客户端(win32)下载安装与登录使用
|
||||
- 平台运营后台版本管理(草稿/发布/下线、普通/强制)
|
||||
- 自动更新(启动 + 每 4 小时检测)
|
||||
- SHA256 完整性校验(EXE/ZIP)
|
||||
- Heartbeat(启动时上报)与版本分布/租户活跃统计
|
||||
- 官方下载页(公司站点)
|
||||
- 便携版 ZIP(可选上传、受控分发)
|
||||
|
||||
### 2.2 非目标(本期不做)
|
||||
|
||||
- macOS / Linux 客户端
|
||||
- 移动端 App
|
||||
- 客户端离线模式
|
||||
- 客户端反逆向加固(v2)
|
||||
|
||||
---
|
||||
|
||||
## 三、模块架构边界
|
||||
|
||||
### 3.1 模块职责(`apps/release`)
|
||||
|
||||
- 管理端:客户端版本元数据管理、发布状态流转、回滚
|
||||
- 公共接口:客户端更新检测、下载引导、Heartbeat 上报
|
||||
- 统计接口:版本分布、租户活跃数、历史装机总数
|
||||
- 资产管理:R2 对象键规范、发布包引用与审计
|
||||
|
||||
### 3.2 分层与鉴权
|
||||
|
||||
| 子能力 | Schema | 鉴权 | 说明 |
|
||||
|---|---|---|---|
|
||||
| 版本管理后台 API | public | Platform Admin 必须认证 | 跨租户统一运营能力 |
|
||||
| 更新检测 API | public | 公开(客户端调用) | 仅返回当前发布版本,不暴露草稿/下线版本 |
|
||||
| Heartbeat API | public | 已登录客户端会话或签名设备票据 | 防伪造上报、防刷统计 |
|
||||
| 统计 API | public | Platform Admin 必须认证 | 提供 Story 5 所需聚合指标 |
|
||||
|
||||
### 3.3 外部依赖
|
||||
|
||||
| 依赖 | 用途 |
|
||||
|---|---|
|
||||
| Electron + electron-updater | 客户端壳应用、更新下载与安装 |
|
||||
| electron-builder | 打包 NSIS EXE + Portable ZIP |
|
||||
| EV 代码签名证书 | Windows SmartScreen 信任 |
|
||||
| Cloudflare R2 + CDN | 发布包存储与分发 |
|
||||
| Celery | 异步计算 checksum / 文件扫描 / 可选预热 |
|
||||
|
||||
---
|
||||
|
||||
## 四、API 设计原则
|
||||
|
||||
1. **路径以 PRD 为准**:统一使用 `/api/release/...` 命名空间。
|
||||
2. **只允许单一生效版本**:同 `platform + arch` 仅 1 条 `published`。
|
||||
3. **公开接口最小暴露**:客户端仅获取更新必要字段,不返回后台内部字段。
|
||||
4. **统计可信优先**:Heartbeat 仅“启动上报”,按 `(tenant_id, device_id)` Upsert。
|
||||
5. **完整性优先于安装**:校验失败禁止安装,保留当前版本可用。
|
||||
6. **强制更新可控**:`release_type=force` + `min_required_version` 双保险。
|
||||
|
||||
---
|
||||
|
||||
## 五、端点清单(核心)
|
||||
|
||||
### 5.1 页面路由(平台运营后台)
|
||||
|
||||
| 路径 | 方法 | 鉴权 | 说明 |
|
||||
|---|---|---|---|
|
||||
| `/platform/release/updates/` | GET | Platform Admin | 版本列表页 |
|
||||
| `/platform/release/updates/new/` | GET | Platform Admin | 新建版本页 |
|
||||
| `/platform/release/updates/{id}/edit/` | GET | Platform Admin | 编辑版本页 |
|
||||
| `/platform/release/metrics/` | GET | Platform Admin | 版本分布与租户活跃榜 |
|
||||
|
||||
### 5.2 JSON API(对齐 PRD + 数据模型)
|
||||
|
||||
| 端点 | 方法 | 说明 |
|
||||
|---|---|---|
|
||||
| `/api/release/updates/latest/` | GET | 客户端检查最新版本(公开) |
|
||||
| `/api/release/updates/` | GET | 管理端查询版本列表 |
|
||||
| `/api/release/updates/` | POST | 管理端创建版本(草稿/发布) |
|
||||
| `/api/release/updates/{id}/` | PATCH | 修改状态、版本类型、日志 |
|
||||
| `/api/release/updates/{id}/rollback/` | POST | 回滚至历史版本(原子切换 published) |
|
||||
| `/api/release/heartbeats/` | POST | 客户端启动上报(Upsert) |
|
||||
| `/api/release/metrics/version-distribution/` | GET | 版本活跃分布 |
|
||||
| `/api/release/metrics/tenant-installs/` | GET | 指定租户活跃安装数 + 历史装机数 |
|
||||
| `/api/release/metrics/tenant-leaderboard/` | GET | 全平台租户活跃榜 |
|
||||
|
||||
> 说明:`heartbeats/metrics` 为实现 Story 5 与 `DATA_MODEL_PUBLIC` 聚合查询所需端点,归属同一模块。
|
||||
|
||||
---
|
||||
|
||||
## 六、关键 API 规范(请求/响应)
|
||||
|
||||
### 6.1 更新检测
|
||||
|
||||
`GET /api/release/updates/latest/?platform=win32&arch=x64¤t_version=1.2.0`
|
||||
|
||||
响应(有更新):
|
||||
|
||||
```json
|
||||
{
|
||||
"has_update": true,
|
||||
"latest_version": "1.3.0",
|
||||
"force_update": false,
|
||||
"min_required_version": "1.0.0",
|
||||
"download_url": "https://download.fonrey.com/releases/system/v1.3.0/fonrey-setup-1.3.0-win.exe",
|
||||
"portable_url": "https://download.fonrey.com/releases/system/v1.3.0/fonrey-portable-1.3.0-win.zip",
|
||||
"checksum_sha256": "<exe_sha256>",
|
||||
"portable_checksum_sha256": "<zip_sha256>",
|
||||
"file_size_bytes": 157286400,
|
||||
"release_notes": "## v1.3.0\n- ...",
|
||||
"release_date": "2026-05-01"
|
||||
}
|
||||
```
|
||||
|
||||
### 6.2 Heartbeat 上报
|
||||
|
||||
`POST /api/release/heartbeats/`
|
||||
|
||||
```json
|
||||
{
|
||||
"device_id": "9e6de37b-8c49-4f9b-af47-52f4e5b8b7f2",
|
||||
"client_version": "1.3.0",
|
||||
"platform": "win32",
|
||||
"arch": "x64",
|
||||
"os_version": "Windows 11 23H2"
|
||||
}
|
||||
```
|
||||
|
||||
处理要求:
|
||||
- 服务端从登录上下文解析 `tenant_id`、`user_id`
|
||||
- 使用 `INSERT ... ON CONFLICT (tenant_id, device_id) DO UPDATE`
|
||||
- 更新 `last_seen_at` 与 `launch_count = launch_count + 1`
|
||||
|
||||
### 6.3 版本发布(管理端)
|
||||
|
||||
`POST /api/release/updates/`
|
||||
|
||||
```json
|
||||
{
|
||||
"version": "1.3.0",
|
||||
"platform": "win32",
|
||||
"arch": "x64",
|
||||
"release_type": "normal",
|
||||
"min_required_version": "1.0.0",
|
||||
"download_url": "https://download.fonrey.com/releases/system/v1.3.0/fonrey-setup-1.3.0-win.exe",
|
||||
"portable_url": "https://download.fonrey.com/releases/system/v1.3.0/fonrey-portable-1.3.0-win.zip",
|
||||
"checksum_sha256": "<exe_sha256>",
|
||||
"portable_checksum_sha256": "<zip_sha256>",
|
||||
"release_notes": "## v1.3.0\n- ...",
|
||||
"status": "published"
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 七、HTMX 交互约定(平台运营后台)
|
||||
|
||||
- 列表筛选(状态/版本号)使用 HTMX 局刷表格区域
|
||||
- 发布/下线/回滚操作使用确认弹窗 + 局部刷新
|
||||
- 成功:`HX-Trigger: toast-success`
|
||||
- 失败:`HX-Trigger: toast-error`(同时返回标准错误码)
|
||||
|
||||
模板建议:
|
||||
- `templates/release/updates_list.html`
|
||||
- `templates/release/fragments/updates_table.html`
|
||||
- `templates/release/fragments/version_distribution_chart.html`
|
||||
- `templates/release/fragments/tenant_leaderboard_table.html`
|
||||
|
||||
---
|
||||
|
||||
## 八、权限与数据范围
|
||||
|
||||
### 8.1 最小权限矩阵
|
||||
|
||||
| 能力 | permission_code |
|
||||
|---|---|
|
||||
| 客户端版本列表查看 | `platform.release.view.allow` |
|
||||
| 创建/编辑发布版本 | `platform.release.edit.allow` |
|
||||
| 发布/下线/回滚 | `platform.release.publish.allow` |
|
||||
| 版本分布与租户统计查看 | `platform.release.metrics.view.allow` |
|
||||
|
||||
### 8.2 范围规则
|
||||
|
||||
- 所有管理能力仅 Platform Admin 可访问
|
||||
- Tenant Admin / Agent 不可访问平台发布后台
|
||||
- 数据物理存储在 public schema,逻辑上属于平台级共享数据
|
||||
|
||||
---
|
||||
|
||||
## 九、异步任务与缓存策略
|
||||
|
||||
### 9.1 异步任务
|
||||
|
||||
| 任务 | 触发时机 | 说明 |
|
||||
|---|---|---|
|
||||
| `release_compute_checksum_task` | 文件上传后 | 计算 EXE/ZIP SHA256 并回填 |
|
||||
| `release_publish_cdn_warmup_task` | 版本发布后 | 可选,预热热点下载节点 |
|
||||
| `release_scan_artifact_task` | 文件上传后 | 可选,执行恶意文件扫描与审计 |
|
||||
|
||||
### 9.2 Redis Key 建议
|
||||
|
||||
| Key | TTL | 说明 |
|
||||
|---|---|---|
|
||||
| `release:latest:{platform}:{arch}` | 60s | 最新发布版本缓存 |
|
||||
| `release:metrics:version_distribution` | 60s | 版本分布聚合缓存 |
|
||||
| `release:metrics:tenant:{tenant_id}` | 60s | 单租户安装/活跃统计缓存 |
|
||||
| `release:download:ratelimit:{ip}` | 60s | 下载链接接口限流 |
|
||||
|
||||
---
|
||||
|
||||
## 十、性能与可靠性约束
|
||||
|
||||
- 更新检测接口:`p95 < 120ms`(缓存命中)
|
||||
- Heartbeat 写入:`p95 < 80ms`
|
||||
- 版本列表页:`p95 < 200ms`
|
||||
- 发布状态切换使用事务,保证“下线旧版 + 发布新版”原子完成
|
||||
- 任意更新失败不影响当前版本继续运行(可恢复原则)
|
||||
|
||||
---
|
||||
|
||||
## 十一、安全与合规
|
||||
|
||||
1. Electron 必须启用:`contextIsolation=true`、`nodeIntegration=false`、`sandbox=true`。
|
||||
2. 更新包仅允许 HTTPS 下载;域名白名单固定为 `download.fonrey.com`。
|
||||
3. EV 证书私钥仅在 CI 密钥库中可用,禁止落盘到开发机。
|
||||
4. 校验值由服务端生成并签名传输(至少 TLS + 服务端可信源)。
|
||||
5. Heartbeat 接口必须防重放/防刷(鉴权 + 频控 + 审计)。
|
||||
6. 管理端操作(发布、回滚、下线)全部记录审计日志。
|
||||
|
||||
---
|
||||
|
||||
## 十二、错误码建议
|
||||
|
||||
| code | HTTP | 中文含义 |
|
||||
|---|---|---|
|
||||
| `RELEASE_VERSION_INVALID` | 400 | 版本号不符合 SemVer |
|
||||
| `RELEASE_PUBLISHED_CONFLICT` | 409 | 当前平台架构已存在发布版本 |
|
||||
| `RELEASE_ARTIFACT_NOT_FOUND` | 404 | 发布包不存在或不可访问 |
|
||||
| `RELEASE_CHECKSUM_MISMATCH` | 400 | 安装包完整性校验失败 |
|
||||
| `RELEASE_HEARTBEAT_INVALID` | 400 | 心跳参数非法 |
|
||||
| `RELEASE_PERMISSION_DENIED` | 403 | 权限不足 |
|
||||
| `RELEASE_RATE_LIMITED` | 429 | 请求过于频繁 |
|
||||
|
||||
---
|
||||
|
||||
## 十三、测试映射(P0)
|
||||
|
||||
| Story | 测试关注点 |
|
||||
|---|---|
|
||||
| Story 1 下载安装 | 官网下载链接可用、签名有效、安装步骤 ≤3、首次启动直达登录 |
|
||||
| Story 2 客户端使用 | Chromium 内核能力、HTMX/Alpine/Tailwind 渲染一致性、文件上传下载 |
|
||||
| Story 3 自动升级 | 启动 + 4h 检测、普通更新/强制更新分支、失败可恢复 |
|
||||
| Story 4 发布管理 | 版本创建/发布/下线/回滚、唯一 published 约束 |
|
||||
| Story 5 版本分布 | Heartbeat Upsert、活跃统计(24h)、租户活跃榜排序 |
|
||||
|
||||
测试文件建议:`tests/integration/release/test_us_release.py`
|
||||
|
||||
---
|
||||
|
||||
## 十四、落地顺序建议
|
||||
|
||||
1. `apps/release` 模型/服务/API 基础骨架(先打通 `/api/release/updates/latest/`)
|
||||
2. 平台运营后台版本管理页(列表 + 新建 + 发布/下线)
|
||||
3. Electron 壳应用最小可运行版本(加载 Web + 标题版本)
|
||||
4. 自动更新链路(electron-updater + 后端 latest API)
|
||||
5. Heartbeat 上报 + 统计 API + 后台图表
|
||||
6. 官网下载页上线(公司域名)
|
||||
7. 便携版 ZIP 与企业无安装权限场景验收
|
||||
|
||||
---
|
||||
|
||||
## 十五、文档同步规则
|
||||
|
||||
- PRD 发布管理模块变更:同步本文件
|
||||
- `client_releases/client_heartbeats` 字段变更:同步 `DATA_MODEL_PUBLIC.md`
|
||||
- 枚举值变更:同步 `DATA_MODEL/ENUMS.md`(含中文标签)
|
||||
- API 包络/错误契约变更:同步 `TECH_STACK/API_CONTRACT.md`
|
||||
- 若将来新增独立测试用例文档:同步 `TECH_STACK/测试规范.md` 与测试用例注册表
|
||||
|
||||
---
|
||||
|
||||
## 附:你关注的 8 个专题落地结论
|
||||
|
||||
1. **Electron 方案**:采用 Electron + electron-updater,客户端坚持“壳应用”原则。
|
||||
2. **EV 证书方案**:CI 自动签名,证书私钥仅在密钥管理系统。
|
||||
3. **Heartbeat 方案**:仅启动上报,`(tenant_id, device_id)` Upsert,支撑活跃与版本分布。
|
||||
4. **自动升级方案**:启动 + 每 4h 轮询,普通/强制双模式,失败可恢复。
|
||||
5. **完整性验证**:下载后先 SHA256 校验,再安装;失败禁止覆盖当前版本。
|
||||
6. **R2 版本管理**:`releases/system/v{version}/...` 路径规范,发布状态驱动可见性。
|
||||
7. **公司网站下载**:`download.fonrey.com` 静态下载页 + 版本信息 + 更新日志。
|
||||
8. **便携版实现**:electron-builder 输出 ZIP,首次运行写入用户目录配置,不修改系统级安装。
|
||||
@@ -13,6 +13,12 @@
|
||||
|
||||
---
|
||||
|
||||
## 变更历史
|
||||
|
||||
| 日期 | 变更人 | 变更内容 |
|
||||
|---|---|---|
|
||||
| 2026-04-30 | Atlas | 补充“变更历史”章节(文档治理) |
|
||||
|
||||
## 一、文档定位与边界
|
||||
|
||||
本文件聚焦客源模块的:
|
||||
|
||||
@@ -13,6 +13,12 @@
|
||||
|
||||
---
|
||||
|
||||
## 变更历史
|
||||
|
||||
| 日期 | 变更人 | 变更内容 |
|
||||
|---|---|---|
|
||||
| 2026-04-30 | Atlas | 补充“变更历史”章节(文档治理) |
|
||||
|
||||
## 一、文档定位与边界
|
||||
|
||||
本文件只定义房源模块的:
|
||||
|
||||
@@ -12,6 +12,12 @@
|
||||
|
||||
---
|
||||
|
||||
## 变更历史
|
||||
|
||||
| 日期 | 变更人 | 变更内容 |
|
||||
|---|---|---|
|
||||
| 2026-04-30 | Atlas | 补充“变更历史”章节(文档治理) |
|
||||
|
||||
## 一、文档定位与边界
|
||||
|
||||
本文件仅定义权限模块的:
|
||||
|
||||
@@ -13,6 +13,12 @@
|
||||
|
||||
---
|
||||
|
||||
## 变更历史
|
||||
|
||||
| 日期 | 变更人 | 变更内容 |
|
||||
|---|---|---|
|
||||
| 2026-04-30 | Atlas | 补充“变更历史”章节(文档治理) |
|
||||
|
||||
## 一、文档定位与边界
|
||||
|
||||
本文件只定义楼盘模块的:
|
||||
|
||||
@@ -10,6 +10,12 @@
|
||||
|
||||
---
|
||||
|
||||
## 变更历史
|
||||
|
||||
| 日期 | 变更人 | 变更内容 |
|
||||
|---|---|---|
|
||||
| 2026-04-30 | Atlas | 补充“变更历史”章节(文档治理) |
|
||||
|
||||
## 一、文档定位与边界
|
||||
|
||||
本文件定义项目统一测试标准:
|
||||
|
||||
@@ -13,6 +13,12 @@
|
||||
|
||||
---
|
||||
|
||||
## 变更历史
|
||||
|
||||
| 日期 | 变更人 | 变更内容 |
|
||||
|---|---|---|
|
||||
| 2026-04-30 | Atlas | 补充“变更历史”章节(文档治理) |
|
||||
|
||||
## 一、文档定位与边界
|
||||
|
||||
本文件定义登录模块的实现口径:
|
||||
|
||||
@@ -13,6 +13,12 @@
|
||||
|
||||
---
|
||||
|
||||
## 变更历史
|
||||
|
||||
| 日期 | 变更人 | 变更内容 |
|
||||
|---|---|---|
|
||||
| 2026-04-30 | Atlas | 补充“变更历史”章节(文档治理) |
|
||||
|
||||
## 1. 模块边界与定位
|
||||
|
||||
| 维度 | 说明 |
|
||||
|
||||
@@ -13,6 +13,12 @@
|
||||
|
||||
---
|
||||
|
||||
## 变更历史
|
||||
|
||||
| 日期 | 变更人 | 变更内容 |
|
||||
|---|---|---|
|
||||
| 2026-04-30 | Atlas | 补充“变更历史”章节(文档治理) |
|
||||
|
||||
## 一、文档定位与边界
|
||||
|
||||
本文件仅定义系统设置模块的:
|
||||
|
||||
@@ -13,6 +13,12 @@
|
||||
|
||||
---
|
||||
|
||||
## 变更历史
|
||||
|
||||
| 日期 | 变更人 | 变更内容 |
|
||||
|---|---|---|
|
||||
| 2026-04-30 | Atlas | 补充“变更历史”章节(文档治理) |
|
||||
|
||||
## 一、文档定位与边界
|
||||
|
||||
本文件只定义组织人事模块的:
|
||||
|
||||
@@ -7,6 +7,12 @@
|
||||
|
||||
---
|
||||
|
||||
## 变更历史
|
||||
|
||||
| 日期 | 变更人 | 变更内容 |
|
||||
|---|---|---|
|
||||
| 2026-04-30 | Atlas | 补充“变更历史”章节(文档治理) |
|
||||
|
||||
## 1. 目标与原则
|
||||
|
||||
1. 本文档用于让工程师直接生成自动化测试代码(API 集成测试 + Web E2E)。
|
||||
|
||||
221
Project/fonrey/TEST_CASES/TEST_CASES_RELEASE_MODULE.md
Normal file
221
Project/fonrey/TEST_CASES/TEST_CASES_RELEASE_MODULE.md
Normal file
@@ -0,0 +1,221 @@
|
||||
# Fonrey 客户端发布模块测试用例文档(可自动化)
|
||||
|
||||
> 文档版本:v1.0
|
||||
> 适用范围:`PRD/发布管理/客户端发布管理模块PRD.md` v1.2
|
||||
> 用例编号范围:`TC-FON-000049` ~ `TC-FON-000072`(全局唯一)
|
||||
> 编号规范:`TEST_CASES/TEST_CASE_ID_SPEC.md`
|
||||
|
||||
---
|
||||
|
||||
## 变更历史
|
||||
|
||||
| 日期 | 变更人 | 变更内容 |
|
||||
|---|---|---|
|
||||
| 2026-04-30 | Atlas | 补充“变更历史”章节(文档治理) |
|
||||
|
||||
## 1. 目标与原则
|
||||
|
||||
1. 覆盖客户端发布模块 P0:下载安装、自动升级、版本发布、版本分布统计。
|
||||
2. 每个用例必须可追溯到 `test_case_id + step_id`。
|
||||
3. 优先 API 集成自动化,客户端壳层 UI 能力以 E2E/手工补充。
|
||||
4. 失败报告必须定位到具体步骤,并保留请求响应或截图证据。
|
||||
|
||||
---
|
||||
|
||||
## 2. 自动化执行与报告要求(强制)
|
||||
|
||||
- 执行层:
|
||||
- API 集成:`pytest + pytest-django`(public schema)
|
||||
- 客户端 E2E:后续 `playwright + Electron`(当前先预留)
|
||||
- 每步输出:`run_id / test_case_id / step_id / status / expected_result / actual_result / error_message`
|
||||
- 失败附件:
|
||||
- API:请求体、响应体、关键日志路径
|
||||
- E2E:截图与视频路径
|
||||
|
||||
---
|
||||
|
||||
## 3. 客户端发布模块 API 端点口径(以 PRD/TECH_STACK 为准)
|
||||
|
||||
- `GET /api/release/updates/latest/`
|
||||
- `GET /api/release/updates/`
|
||||
- `POST /api/release/updates/`
|
||||
- `PATCH /api/release/updates/{id}/`
|
||||
- `POST /api/release/updates/{id}/rollback/`
|
||||
- `POST /api/release/heartbeats/`
|
||||
- `GET /api/release/metrics/version-distribution/`
|
||||
- `GET /api/release/metrics/tenant-installs/`
|
||||
- `GET /api/release/metrics/tenant-leaderboard/`
|
||||
|
||||
---
|
||||
|
||||
## 4. 全量测试用例清单(24条)
|
||||
|
||||
## A. 下载与完整性(Story 1)
|
||||
|
||||
### TC-FON-000049 官网下载页可访问且展示最新版本
|
||||
- 级别:E2E
|
||||
- 步骤:
|
||||
- `TC-FON-000049-S01` 访问官网客户端下载页
|
||||
- `TC-FON-000049-S02` 校验展示版本号/发布日期/下载按钮
|
||||
- `TC-FON-000049-S03` 校验下载按钮链接可用
|
||||
- 预期:页面可访问,元信息完整
|
||||
|
||||
### TC-FON-000050 latest 接口返回下载地址与校验值
|
||||
- 级别:API
|
||||
- 步骤:
|
||||
- `TC-FON-000050-S01` 调用 `GET /api/release/updates/latest/?platform=win32&arch=x64¤t_version=1.2.0`
|
||||
- `TC-FON-000050-S02` 校验返回 `download_url`、`checksum_sha256`、`release_notes`
|
||||
- `TC-FON-000050-S03` 校验 `checksum_sha256` 长度为 64
|
||||
- 预期:响应字段完整且格式正确
|
||||
|
||||
### TC-FON-000051 安装包 SHA256 校验通过
|
||||
- 级别:API+脚本
|
||||
- 步骤:
|
||||
- `TC-FON-000051-S01` 获取 `download_url` 和 `checksum_sha256`
|
||||
- `TC-FON-000051-S02` 下载文件并计算本地 SHA256
|
||||
- `TC-FON-000051-S03` 比对本地值与接口返回值
|
||||
- 预期:一致,允许进入安装流程
|
||||
|
||||
### TC-FON-000052 安装包 SHA256 不一致时拒绝安装
|
||||
- 级别:客户端集成
|
||||
- 步骤:
|
||||
- `TC-FON-000052-S01` 构造篡改包或错误 checksum
|
||||
- `TC-FON-000052-S02` 触发更新下载完成后的校验
|
||||
- `TC-FON-000052-S03` 校验客户端拒绝安装并保留当前版本
|
||||
- 预期:提示完整性校验失败,不覆盖现版本
|
||||
|
||||
---
|
||||
|
||||
## B. 自动升级(Story 3)
|
||||
|
||||
### TC-FON-000053 无新版本时返回 has_update=false
|
||||
- 级别:API
|
||||
- 步骤:`S01` 用当前最新版本调用 latest;`S02` 校验 `has_update=false`;`S03` 校验 `latest_version` 存在
|
||||
- 预期:不触发更新
|
||||
|
||||
### TC-FON-000054 有新版本时返回升级信息
|
||||
- 级别:API
|
||||
- 步骤:`S01` 用旧版本调用 latest;`S02` 校验 `has_update=true`;`S03` 校验 `latest_version` 高于 `current_version`
|
||||
- 预期:触发可升级状态
|
||||
|
||||
### TC-FON-000055 普通更新允许“稍后提醒”
|
||||
- 级别:客户端 E2E
|
||||
- 步骤:`S01` 服务端发布 `release_type=normal`;`S02` 客户端检测更新;`S03` 校验出现“立即更新/稍后提醒”
|
||||
- 预期:普通更新可延期
|
||||
|
||||
### TC-FON-000056 强制更新不允许“稍后提醒”
|
||||
- 级别:客户端 E2E
|
||||
- 步骤:`S01` 服务端发布 `release_type=force`;`S02` 客户端检测更新;`S03` 校验仅可“立即更新”
|
||||
- 预期:必须升级后继续使用
|
||||
|
||||
### TC-FON-000057 更新下载失败时保持当前版本可用
|
||||
- 级别:客户端 E2E
|
||||
- 步骤:`S01` 模拟下载中断/磁盘不足;`S02` 校验错误提示;`S03` 校验当前版本仍可正常操作
|
||||
- 预期:失败可恢复,不影响业务使用
|
||||
|
||||
### TC-FON-000058 更新成功后重启生效并保留登录态
|
||||
- 级别:客户端 E2E
|
||||
- 步骤:`S01` 执行更新并下载完成;`S02` 重启客户端;`S03` 校验标题版本号更新且会话恢复
|
||||
- 预期:升级成功且无需重新登录
|
||||
|
||||
---
|
||||
|
||||
## C. 平台发布管理(Story 4)
|
||||
|
||||
### TC-FON-000059 平台管理员可创建草稿版本
|
||||
- 级别:API
|
||||
- 步骤:`S01` 调用 `POST /api/release/updates/` 创建草稿;`S02` 校验 `status=draft`;`S03` 校验版本记录可在列表查询到
|
||||
- 预期:草稿创建成功
|
||||
|
||||
### TC-FON-000060 版本号必须符合 SemVer
|
||||
- 级别:API
|
||||
- 步骤:`S01` 提交非法版本号(如 `1.2`);`S02` 校验 400;`S03` 校验错误码 `RELEASE_VERSION_INVALID`
|
||||
- 预期:非法版本号被拒绝
|
||||
|
||||
### TC-FON-000061 发布后 latest 接口即时可见
|
||||
- 级别:API
|
||||
- 步骤:`S01` 将草稿改为 `published`(PATCH);`S02` 调用 latest;`S03` 校验返回该版本
|
||||
- 预期:发布即时生效
|
||||
|
||||
### TC-FON-000062 同平台架构仅允许一个 published
|
||||
- 级别:API
|
||||
- 步骤:`S01` 已有一个 published;`S02` 尝试并发发布第二个;`S03` 校验冲突(409)
|
||||
- 预期:唯一生效版本约束成立
|
||||
|
||||
### TC-FON-000063 版本下线后 latest 不再返回该版本
|
||||
- 级别:API
|
||||
- 步骤:`S01` 将已发布版本改 `archived`;`S02` 调用 latest;`S03` 校验不返回已下线版本
|
||||
- 预期:下线立即生效
|
||||
|
||||
### TC-FON-000064 回滚接口将历史版本恢复为 published
|
||||
- 级别:API
|
||||
- 步骤:`S01` 调用 `POST /api/release/updates/{id}/rollback/`;`S02` 校验目标版本为 `published`;`S03` 校验原版本自动下线
|
||||
- 预期:回滚原子完成
|
||||
|
||||
---
|
||||
|
||||
## D. Heartbeat 与版本分布(Story 5)
|
||||
|
||||
### TC-FON-000065 启动心跳首次上报创建记录
|
||||
- 级别:API
|
||||
- 步骤:`S01` 调用 `POST /api/release/heartbeats/`;`S02` 校验写入 `(tenant_id, device_id)`;`S03` 校验 `launch_count=1`
|
||||
- 预期:首次上报成功
|
||||
|
||||
### TC-FON-000066 启动心跳重复上报走 Upsert
|
||||
- 级别:API
|
||||
- 步骤:`S01` 对同 `(tenant_id,device_id)` 再次上报;`S02` 校验未新增新行;`S03` 校验 `launch_count+1` 且 `last_seen_at` 刷新
|
||||
- 预期:符合 Upsert 语义
|
||||
|
||||
### TC-FON-000067 版本分布统计按 24h 活跃口径
|
||||
- 级别:API
|
||||
- 步骤:`S01` 构造多版本心跳数据(含超 24h);`S02` 调用 `GET /api/release/metrics/version-distribution/`;`S03` 校验仅统计最近 24h 活跃
|
||||
- 预期:统计口径正确
|
||||
|
||||
### TC-FON-000068 指定租户安装统计返回活跃+历史总数
|
||||
- 级别:API
|
||||
- 步骤:`S01` 调用 `GET /api/release/metrics/tenant-installs/?tenant_id=...`;`S02` 校验返回 `active_install_count_24h`;`S03` 校验返回 `historical_install_count`
|
||||
- 预期:两个指标均返回且数值正确
|
||||
|
||||
### TC-FON-000069 租户活跃榜按活跃安装数降序
|
||||
- 级别:API
|
||||
- 步骤:`S01` 调用 `GET /api/release/metrics/tenant-leaderboard/`;`S02` 校验字段包含 `tenant_code/tenant_name/active/historical`;`S03` 校验按活跃安装数降序
|
||||
- 预期:排序与字段正确
|
||||
|
||||
### TC-FON-000070 心跳接口拒绝未鉴权请求
|
||||
- 级别:API
|
||||
- 步骤:`S01` 未带会话访问 heartbeats;`S02` 校验 401/403;`S03` 校验无数据写入
|
||||
- 预期:防伪造上报有效
|
||||
|
||||
### TC-FON-000071 发布管理接口拒绝非平台管理员
|
||||
- 级别:API
|
||||
- 步骤:`S01` 租户管理员调用 `POST /api/release/updates/`;`S02` 校验 403;`S03` 校验无新版本记录
|
||||
- 预期:权限边界正确
|
||||
|
||||
### TC-FON-000072 下载检测接口限流生效
|
||||
- 级别:API
|
||||
- 步骤:`S01` 同 IP 高频访问 latest;`S02` 校验前 N 次成功;`S03` 校验超阈值 429
|
||||
- 预期:触发限流,保护服务
|
||||
|
||||
---
|
||||
|
||||
## 5. 工程实现指引(给测试开发工程师)
|
||||
|
||||
1. **目录建议**
|
||||
- `tests/integration/release/test_us_release.py`
|
||||
- `tests/e2e/release/test_tc_fon_000049_000072.spec.ts`(预留)
|
||||
2. **命名规范**
|
||||
- 函数名必须带用例ID,例如:`def test_tc_fon_000062_single_published_constraint():`
|
||||
3. **步骤日志**
|
||||
- 每步打印 step_id,断言失败消息包含 step_id
|
||||
4. **报告产物**
|
||||
- `reports/release_run_<run_id>.json`
|
||||
5. **CI 门禁(阶段性)**
|
||||
- P0 API 用例(000050, 000053~000054, 000059~000069, 000070~000072)必须全过
|
||||
|
||||
---
|
||||
|
||||
## 6. 变更规则
|
||||
|
||||
- 本模块新增用例从 `TC-FON-000073` 继续递增
|
||||
- 全项目继续使用单一序列,不得重号
|
||||
- 历史 ID 仅可 `deprecated`,不得复用
|
||||
@@ -1,5 +1,11 @@
|
||||
# 测试用例全局编号规范(Fonrey)
|
||||
|
||||
## 变更历史
|
||||
|
||||
| 日期 | 变更人 | 变更内容 |
|
||||
|---|---|---|
|
||||
| 2026-04-30 | Atlas | 补充“变更历史”章节(文档治理) |
|
||||
|
||||
## 1. 目标
|
||||
确保所有模块(登录、房源、客源等)测试用例编号**全局唯一**,便于自动化执行、失败定位、统计报表。
|
||||
|
||||
|
||||
@@ -1,11 +1,17 @@
|
||||
# Fonrey 测试用例编号注册表(全局唯一)
|
||||
|
||||
> 用途:统一管理全项目测试用例编号,避免撞号,支持自动化报告追踪。
|
||||
> 适用范围:登录、房源、客源、组织人事、权限、系统设置等全部模块。
|
||||
> 适用范围:登录、房源、客源、组织人事、权限、系统设置、客户端发布等全部模块。
|
||||
> 编号规范:见 `TEST_CASES/TEST_CASE_ID_SPEC.md`
|
||||
|
||||
---
|
||||
|
||||
## 变更历史
|
||||
|
||||
| 日期 | 变更人 | 变更内容 |
|
||||
|---|---|---|
|
||||
| 2026-04-30 | Atlas | 补充“变更历史”章节(文档治理) |
|
||||
|
||||
## 1) 全局规则(强制)
|
||||
|
||||
1. 全项目共用一个递增序列:`TC-FON-XXXXXX`。
|
||||
@@ -18,12 +24,12 @@
|
||||
|
||||
## 2) 当前编号水位
|
||||
|
||||
- **已分配到**:`TC-FON-000048`
|
||||
- **下一个可用编号**:`TC-FON-000049`
|
||||
- **已分配到**:`TC-FON-000072`
|
||||
- **下一个可用编号**:`TC-FON-000073`
|
||||
- **最后更新人**:Atlas
|
||||
- **最后更新时间**:2026-04-30
|
||||
|
||||
> 说明:下一个新增用例(不论哪个模块)都应从 `TC-FON-000049` 开始。
|
||||
> 说明:下一个新增用例(不论哪个模块)都应从 `TC-FON-000073` 开始。
|
||||
|
||||
---
|
||||
|
||||
@@ -32,6 +38,7 @@
|
||||
| 批次ID | 模块 | 编号范围 | 数量 | 状态 | 文档 |
|
||||
|---|---|---:|---:|---|---|
|
||||
| BATCH-LOGIN-001 | 登录模块 | TC-FON-000001 ~ TC-FON-000048 | 48 | active | `TEST_CASES/TEST_CASES_LOGIN_MODULE.md` |
|
||||
| BATCH-RELEASE-001 | 客户端发布模块 | TC-FON-000049 ~ TC-FON-000072 | 24 | active | `TEST_CASES/TEST_CASES_RELEASE_MODULE.md` |
|
||||
|
||||
**状态枚举**:
|
||||
- `active`:有效且执行中
|
||||
@@ -48,6 +55,8 @@
|
||||
|---|---|---|---|---|---|
|
||||
| TC-FON-000001 | 登录 | Tenant Code 页面首启展示 | active | v1.0 | 见登录用例文档 |
|
||||
| TC-FON-000048 | 登录 | 验证码登录成功/失败/锁定限制 | active | v1.0 | 见登录用例文档 |
|
||||
| TC-FON-000049 | 客户端发布 | 官网下载页可访问且展示最新版本 | active | v1.0 | 见发布模块用例文档 |
|
||||
| TC-FON-000072 | 客户端发布 | 下载检测接口限流生效 | active | v1.0 | 见发布模块用例文档 |
|
||||
|
||||
---
|
||||
|
||||
@@ -75,3 +84,4 @@
|
||||
| 日期 | 变更人 | 变更内容 |
|
||||
|---|---|---|
|
||||
| 2026-04-30 | Atlas | 初始化注册表;登记登录模块 000001~000048;下一号设为 000049 |
|
||||
| 2026-04-30 | Atlas | 新增客户端发布模块测试用例文档;登记 000049~000072;下一号设为 000073 |
|
||||
|
||||
Reference in New Issue
Block a user