系统管理模块更新

This commit is contained in:
Shen Wei
2026-05-02 05:10:16 +08:00
parent 804954c367
commit 464c5fce51
4 changed files with 567 additions and 348 deletions

View File

@@ -2,8 +2,8 @@
**状态**Draft
**作者**:产品经理
**最后更新**2026-04-24
**版本**v1.0
**最后更新**2026-05-01
**版本**v1.3
**利益相关方**:工程负责人、运营团队、安全合规、客户成功团队
## 变更历史
@@ -11,6 +11,8 @@
| 版本 | 日期 | 作者 | 变更说明 |
|------|------|------|---------|
| v1.0 | 2026-04-24 | 产品经理 | 初稿 |
| v1.1 | 2026-05-01 | 产品经理 | ① Story 1 补充「默认配置」内容定义(权限定义 + 系统默认角色);② Story 1 补充欢迎通知机制邮件内容规范、默认密码发放、Tenant Code、页面下载 PDF③ Story 2 补充 License 时效管理(到期自动挂起、提前 15 天预警倒计时);④ Story 3 标注为已废弃(暂不实现);⑤ 新增 Story 7平台版本总览基础数据版本 + 租户数据升级版本);⑥ §5.1.1 补充默认配置内容说明、通知机制细节、时效日期字段、到期挂起流程;⑦ 管理员角色权限矩阵补充版本总览权限 |
| v1.3 | 2026-05-01 | 产品经理 | Story 1 Tenant Admin 权限机制修正:初始 Tenant Admin 不赋予任何业务角色,由系统在租户创建时直接写入独立的「租户管理员」专属权限集合;该集合不在角色管理界面显示,不可自行修改或分配;新增/变更租户管理员须由平台运营方操作 |
---
@@ -48,13 +50,13 @@ Fonrey 是一套面向房产经纪公司的 B2B SaaS 平台,采用 `django-ten
## 2. 目标与成功指标
| 目标 | 指标 | 当前基线 | 目标值 | 测量窗口 |
|------|------|---------|--------|---------|
| 租户管理效率提升 | 新租户开通耗时 | 人工脚本 ~30 分钟 | < 5 分钟(含自动初始化) | 上线后 30 天 |
| 平台升级零停机 | 升级期间受影响租户数 | 全量中断 | 灰度阶段受影响 ≤ 5% 租户 | 每次升级 |
| 数据恢复能力建立 | RTO恢复时间目标 | 无标准流程 | 单租户恢复 < 2 小时 | v1 上线即达标 |
| 操作合规覆盖 | 高危操作审计日志覆盖率 | 0% | 100% | 上线后 30 天 |
| 管理员安全 | MFA 启用率 | 0% | 100%(强制) | 上线即达标 |
| 目标 | 指标 | 当前基线 | 目标值 | 测量窗口 |
| -------- | ----------- | ----------- | --------------- | -------- |
| 租户管理效率提升 | 新租户开通耗时 | 人工脚本 ~30 分钟 | < 5 分钟(含自动初始化) | 上线后 30 天 |
| 平台升级零停机 | 升级期间受影响租户数 | 全量中断 | 灰度阶段受影响 ≤ 5% 租户 | 每次升级 |
| 数据恢复能力建立 | RTO恢复时间目标 | 无标准流程 | 单租户恢复 < 2 小时 | v1 上线即达标 |
| 操作合规覆盖 | 高危操作审计日志覆盖率 | 0% | 100% | 上线后 30 天 |
| 管理员安全 | MFA 启用率 | 0% | 100%(强制) | 上线即达标 |
---
@@ -78,11 +80,29 @@ Fonrey 是一套面向房产经纪公司的 B2B SaaS 平台,采用 `django-ten
> 作为运营人员,我希望通过填写表单快速完成租户开通,并由系统自动完成数据库初始化与欢迎邮件,无需手动执行脚本。
**验收标准**
- [ ] 表单提交后,系统在后台自动创建 PostgreSQL Schema 并注入默认配置,完成时间 < 60 秒
- [ ] 新租户创建后,管理员收到系统通知,租户联系人收到欢迎邮件
- [ ] 子域名创建成功后在租户详情中显示可访问链接
- [ ] 表单提交后,系统在后台自动创建 PostgreSQL Schema 并注入默认配置(见 §5.1.1 默认配置说明),完成时间 < 60 秒
- [ ] 默认配置注入包含两部分:**1权限定义PermissionDef**:注入该平台所有权限码的定义数据(`permission_code`、描述、模块归属),作为该租户 RBAC 权限体系的基础;**2系统默认角色与权限绑定**:按「角色权限矩阵.md」定义注入 7 个系统内置业务角色——置业顾问、店管、区管、区总、副总、总经、其他职能——并完成各角色对应的权限集合绑定
- [ ] 初始 Tenant Admin 用户(以联系人手机号创建)**不通过业务角色赋权**,而是在租户创建时由系统直接写入「租户管理员」专属权限集合;该权限集合独立于 7 个业务角色之外,不在租户的角色管理界面中显示,不可由 Tenant Admin 自行修改或分配给其他用户;如需新增或变更租户管理员,须由平台运营方在管理后台操作
- [ ] 新租户创建后,平台运营管理员收到系统内通知(站内消息);租户联系人收到欢迎邮件(见下方「欢迎邮件规范」)
- [ ] 若联系人无邮箱,运营人员可在租户详情页下载「入驻信息 PDF 文档」,通过微信等渠道手动转发
- [ ] 租户访问地址采用 Fonrey 平台统一域名 + Tenant Code 参数的形式(如 `https://app.fonrey.com/?tenant=ABCD`),无需为每个租户单独创建子域名;租户详情页展示该访问链接,可一键复制
- [ ] 创建失败时回滚所有已创建资源,并显示明确的错误原因
**欢迎邮件规范**(联系人有邮箱时自动发送):
| 字段 | 内容 |
| ---- | ----------------------------------------------------------------------------------------------------------- |
| 主题 | 【房睿平台】您的账号已开通,欢迎登录 |
| 收件人 | 租户联系人邮箱 |
| 正文内容 | 公司名称、**Tenant Code**(登录时所需的租户识别码)、登录地址(`https://app.fonrey.com/?tenant={Tenant Code}`、Tenant Admin 手机号(脱敏展示后三位)、**系统初始密码**(明文,首次登录后强制修改)、平台客服联系方式 |
| 备注 | 初始密码由系统随机生成12 位,含大小写字母+数字),发送后立即标记为「首次登录强制修改」状态 |
**入驻信息 PDF 文档**(可在租户详情页下载,适用于无邮箱客户):
- 包含与欢迎邮件相同的所有关键信息
- 页面入口:租户详情 → 基本信息 Tab → 「下载入驻信息」按钮
- 文件名格式:`{公司名称}_入驻信息_{日期}.pdf`
**Story 2**:挂起问题租户
> 作为运营人员,我希望能快速冻结欠费租户的访问,同时保证数据不丢失,并在欠费解决后一键恢复。
@@ -92,15 +112,21 @@ Fonrey 是一套面向房产经纪公司的 B2B SaaS 平台,采用 `django-ten
- [ ] 支持设置到期时间,到期后系统自动恢复租户状态,并发送通知邮件
- [ ] 所有挂起/恢复操作记录于操作审计日志,包含操作人、时间、原因
**Story 3**响应客户数据导出请求
**Story 2b**License 时效管理与到期自动挂起
> 作为运营人员,我希望能为指定租户触发数据导出,并在完成后通过邮件通知对方下载,无需手动操作数据库
> 作为 Platform Admin我希望每个租户能够设置 License 有效期,在到期后系统自动挂起租户,并在到期前提前预警,减少人工干预
**验收标准**
- [ ] 导出任务异步执行Celery提交后界面不阻塞
- [ ] 导出完成后邮件通知管理员,邮件包含加密下载链接,有效期 24 小时
- [ ] 支持按模块选择导出内容(客户数据、房源数据、交易记录、系统配置
- [ ] 导出格式支持CSV、JSON、SQL Dump
- [ ] 每个租户的「基本信息」中包含 **License 到期日期**字段,由 Platform Admin 在创建租户或套餐续费时设定(如购买 1 年期 License
- [ ] 系统Celery Beat 每日检查)在 License 到期时自动将租户状态切换为「已挂起 Suspended」挂起原因标注为「License 到期」
- [ ] 自动挂起后租户联系人收到通知邮件Platform Admin 可手动解除挂起(续费后操作
- [ ] **提前 15 天预警倒计时**:租户内的 Tenant Admin 在登录后的管理界面顶部看到醒目横幅提示,内容示例:「您的 License 将于 X 天后到期({到期日期}),请联系平台续费。」;提前 15 天开始出现,每天展示直至到期或续费完成
- [ ] 倒计时横幅仅对租户端 Tenant Admin 可见,不影响普通 Agent 用户体验(可配置)
- [ ] License 到期日期在管理后台租户列表和详情页均可见支持按「即将到期15 天内)」筛选
**Story 3**:响应客户数据导出请求
> **状态**:暂缓(当前 P0 计划阶段不实现,后续迭代规划)。本 Story 保留需求描述,待进入相应排期后正式细化。
---
@@ -145,7 +171,46 @@ Fonrey 是一套面向房产经纪公司的 B2B SaaS 平台,采用 `django-ten
---
## 5. 功能规格
### Persona DPlatform Admin平台超级管理员David平台版本总览
**Story 7**:查看平台与租户版本总览
> 作为 Platform Admin我希望能在管理界面一眼看到整个平台的版本情况包括基础数据版本和每个租户各自的数据升级版本以便掌握升级进度和版本差异。
**验收标准**
- [ ] 管理控制台「系统版本管理」页面提供「版本总览」视图,分为两个部分:
**Part 1平台基础数据版本**
- 展示当前平台基础数据(公共 Schema 中的 PermissionDef、系统配置等 seed 数据)的版本号
- 该版本对所有租户一致,每次平台升级为一次性全量升级
- 展示字段:版本号、最后升级时间、升级描述、升级执行人
**Part 2租户数据升级版本**
- 以列表形式展示每个租户当前的数据版本号(即该租户 Schema 已完成的 migration 版本)
- 由于采用灰度升级,各租户版本号可能不一致
- 列表字段:租户名称、当前数据版本号、上次升级时间、升级状态(最新 / 待升级 / 升级中 / 升级失败)
- 支持按「待升级」「升级失败」筛选,快速定位异常租户
- 点击租户行可跳转至该租户详情的「备份记录」Tab 查看详情
- [ ] 页面支持手动刷新版本状态
- [ ] 「版本总览」数据展示无需实时,允许最多 5 分钟缓存延迟
---
**Story 8**:查看与控制租户用户数
> 作为 Platform Admin我希望能在管理界面看到每个租户当前的用户数量并能设置用户数上限以便根据 License 授权进行管控(用户数是 License 计费的重要依据)。
**验收标准**
- [ ] 租户列表新增「当前用户数」列,显示该租户当前已创建的有效用户总数(含 Tenant Admin + 所有 Agent不含已删除/离职用户)
- [ ] 租户详情页「基本信息」Tab 显示:当前用户数 / License 授权用户数上限12 / 50
- [ ] Platform Admin 可在租户详情页设置「License 授权用户数上限」字段当租户实际用户数达到上限时Tenant Admin 在该租户内将无法继续创建新用户,并收到提示:「当前用户数已达 License 上限,请联系平台扩容」
- [ ] Platform Admin 可随时调整用户数上限(续费扩容 or 缩容),变更记录写入操作审计日志
- [ ] 租户列表支持按「用户数已满(≥ 上限)」筛选,便于平台运营主动识别需要续费的租户
---
### 5.1 租户管理Tenant Management
@@ -157,27 +222,40 @@ Fonrey 是一套面向房产经纪公司的 B2B SaaS 平台,采用 `django-ten
|------|------|------|------|
| 公司名称 | Text | ✅ | 最大 100 字符 |
| 联系人 | Text | ✅ | 租户主联系人姓名 |
| 联系邮箱 | Email | | 用于发送欢迎邮件及系统通知 |
| 联系邮箱 | Email | ❌(可选) | 用于发送欢迎邮件及系统通知;无邮箱时改用 PDF 下载方式 |
| 所在地区 | Select | ✅ | 省市两级 |
| 订阅套餐 | Select | ✅ | Basic / Professional / Enterprise |
| 子域名 | Text | ✅ | 格式:`{slug}.platform.com`,唯一,创建后不可修改 |
| 子域名 | Text | ❌(无需) | 租户访问统一使用 Fonrey 平台域名 + Tenant Code 参数,无子域名 |
| License 到期日期 | Date | ✅ | 由 Platform Admin 设定,决定租户有效期;到期后系统自动挂起 |
创建流程:
1. 表单校验通过后,后台 Celery 任务执行:
- 创建 PostgreSQL Schema`tenant_{id}`
- 执行 Migrate 初始化表结构
- 注入默认系统配置
- 发送欢迎邮件至联系邮箱
- 注入默认配置(见下方「默认配置内容」说明)
- 生成初始密码12 位随机,含大小写字母+数字),标记为「首次登录强制修改」
- 若联系邮箱已填写:发送欢迎邮件(含 Tenant Code、初始密码、平台访问链接 `https://app.fonrey.com/?tenant={TenantCode}`
2. 任务完成后更新租户状态为 `active`,失败则全量回滚并标记为 `failed`
3. 生成唯一 Tenant IDUUID记录创建时间、创建人
3. 生成唯一 Tenant IDUUID及 Tenant Code可读短码`FR-2024-0001`,记录创建时间、创建人
**默认配置内容Schema 初始化时注入)**
| 配置类型 | 内容 | 说明 |
|---------|------|------|
| 权限定义PermissionDef | 平台全量权限码(`permission_code`、描述、模块归属) | 从 public schema 同步至租户 schema作为 RBAC 权限体系基础 |
| 系统默认角色 | Tenant Admin租户管理员、Agent经纪人 | 按权限管理模块 PRD 定义的权限集合完成角色-权限绑定 |
| 初始 Tenant Admin 用户 | 以联系人手机号创建,角色为 Tenant Admin | 首次登录后强制修改密码 |
**挂起Suspend**
- 操作触发条件:运营人员手动触发,选择挂起原因(欠费 / 违规 / 主动申请 / 其他)
- 操作触发条件:
- **手动触发**:运营人员手动触发,选择挂起原因(欠费 / 违规 / 主动申请 / 其他)
- **自动触发**Celery Beat 每日检查 License 到期日期到期后自动挂起原因标注为「License 到期」)
- 可设置挂起到期时间(留空表示永久挂起直至手动恢复)
- 挂起效果:该租户所有用户请求返回 `HTTP 403`,重定向至暂停提示页;管理后台数据仍可访问
- 到期自动恢复:`Celery Beat` 定时检查到期挂起记录,自动切换状态为 `active`
- 通知:挂起与恢复均向租户联系邮箱发送通知邮件
- 到期自动恢复:`Celery Beat` 定时检查到期挂起记录,自动切换状态为 `active`仅适用于手动设置了到期时间的挂起License 到期自动挂起需 Platform Admin 手动恢复)
- 通知:挂起与恢复均向租户联系邮箱发送通知邮件(无邮箱则跳过)
- **License 到期预警**License 到期前 15 天起,租户端 Tenant Admin 管理界面顶部显示倒计时横幅,直至到期或续费后由 Platform Admin 更新 License 到期日期
**删除Delete**
@@ -385,7 +463,7 @@ Fonrey 是一套面向房产经纪公司的 B2B SaaS 平台,采用 `django-ten
- 分页展示(默认 20 条/页)
- 搜索:按公司名称、子域名、联系邮箱关键词搜索
- 筛选按状态Active / Suspended / Deleted、套餐Basic/Pro/Enterprise、注册时间范围
- 筛选按状态Active / Suspended / Deleted、套餐Basic/Pro/Enterprise、注册时间范围、**即将到期15 天内)**
- 列表字段:公司名称、子域名、套餐、状态、注册时间、活跃用户数
- 快捷操作:查看详情、挂起、发起备份、数据导出
@@ -564,6 +642,7 @@ Fonrey 是一套面向房产经纪公司的 B2B SaaS 平台,采用 `django-ten
| 数据恢复 | ✅ | ❌ | ❌ |
| 系统升级 | ✅ | ❌ | ❌ |
| 系统回滚 | ✅ | ❌ | ❌ |
| 查看版本总览 | ✅ | ✅ | ❌ |
| 配置告警规则 | ✅ | ✅ | ❌ |
| 查看审计日志 | ✅ | ✅ | ✅ |
| 导出审计日志 | ✅ | ✅ | ✅ |

View File

@@ -0,0 +1,460 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>Fonrey 项目文档 Review 清单</title>
<style>
* { box-sizing: border-box; margin: 0; padding: 0; }
body { font-family: 'PingFang SC', 'Microsoft YaHei', Arial, sans-serif; font-size: 12px; color: #1a1a1a; background: #fff; }
@media print {
body { font-size: 11px; }
.page-break { page-break-before: always; }
.no-print { display: none; }
table { page-break-inside: auto; }
tr { page-break-inside: avoid; }
}
.header {
padding: 20px 30px 12px;
border-bottom: 3px solid #1a1a2e;
margin-bottom: 20px;
}
.header h1 { font-size: 22px; font-weight: 700; color: #1a1a2e; letter-spacing: 1px; }
.header .meta { margin-top: 6px; color: #666; font-size: 11px; }
.header .meta span { margin-right: 20px; }
.legend {
display: flex; gap: 16px; flex-wrap: wrap;
padding: 10px 30px;
background: #f8f9fa;
border-bottom: 1px solid #e0e0e0;
margin-bottom: 24px;
}
.legend-item { display: flex; align-items: center; gap: 6px; font-size: 11px; }
.badge {
display: inline-block; padding: 1px 8px; border-radius: 3px;
font-size: 10px; font-weight: 600; white-space: nowrap;
}
.badge-prd { background: #e8f4fd; color: #1565c0; border: 1px solid #90caf9; }
.badge-data { background: #e8f5e9; color: #2e7d32; border: 1px solid #a5d6a7; }
.badge-ui { background: #fff3e0; color: #e65100; border: 1px solid #ffcc80; }
.badge-html { background: #fce4ec; color: #880e4f; border: 1px solid #f48fb1; }
.badge-tech { background: #ede7f6; color: #4527a0; border: 1px solid #ce93d8; }
.badge-test { background: #e0f2f1; color: #00695c; border: 1px solid #80cbc4; }
.badge-task { background: #fff8e1; color: #f57f17; border: 1px solid #ffe082; }
.badge-review { background: #fafafa; color: #424242; border: 1px solid #bdbdbd; }
.module-section {
margin: 0 30px 28px;
}
.module-title {
font-size: 15px; font-weight: 700; color: #fff;
background: #1a1a2e; padding: 7px 14px;
border-radius: 4px 4px 0 0;
display: flex; align-items: center; gap: 8px;
}
.module-title .num { opacity: 0.6; font-size: 12px; }
table {
width: 100%; border-collapse: collapse;
border: 1px solid #ddd; border-top: none;
}
thead tr { background: #f0f0f0; }
th {
text-align: left; padding: 6px 10px;
font-size: 10px; font-weight: 700;
color: #555; border-bottom: 1px solid #ccc;
border-right: 1px solid #e0e0e0;
}
td {
padding: 6px 10px; border-bottom: 1px solid #eee;
border-right: 1px solid #e8e8e8; vertical-align: top;
}
tr:last-child td { border-bottom: none; }
td:last-child, th:last-child { border-right: none; }
.col-no { width: 36px; text-align: center; color: #999; }
.col-type { width: 90px; }
.col-name { width: 220px; font-weight: 500; }
.col-path { color: #888; font-size: 10px; font-family: monospace; line-height: 1.4; }
.col-cb { width: 80px; text-align: center; }
.checkbox-group { display: flex; justify-content: center; gap: 8px; }
.cb-label { display: flex; flex-direction: column; align-items: center; gap: 2px; font-size: 9px; color: #888; }
.cb-box { width: 14px; height: 14px; border: 1.5px solid #bbb; border-radius: 2px; display: inline-block; }
.missing { color: #bbb; font-style: italic; font-size: 10px; }
.summary {
margin: 0 30px 30px;
padding: 14px 20px;
background: #f8f9fa;
border: 1px solid #e0e0e0;
border-radius: 4px;
}
.summary h3 { font-size: 13px; margin-bottom: 10px; color: #1a1a2e; }
.summary-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 10px; }
.summary-item { background: #fff; border: 1px solid #ddd; padding: 10px; border-radius: 4px; text-align: center; }
.summary-item .count { font-size: 22px; font-weight: 700; color: #1a1a2e; }
.summary-item .label { font-size: 10px; color: #888; margin-top: 2px; }
.footer {
padding: 16px 30px;
border-top: 1px solid #eee;
color: #aaa; font-size: 10px;
text-align: center;
}
.no-print {
position: fixed; bottom: 20px; right: 20px;
background: #1a1a2e; color: #fff;
border: none; padding: 10px 20px;
border-radius: 6px; cursor: pointer; font-size: 13px;
}
</style>
</head>
<body>
<button class="no-print" onclick="window.print()">🖨️ 打印</button>
<div class="header">
<h1>📋 Fonrey 项目 · 文档 Review 清单</h1>
<div class="meta">
<span>📁 项目路径D:\Workspace\nexus\Project\fonrey</span>
<span>📅 生成时间2026-05-01</span>
<span>✅ 打印后逐项勾选完成状态</span>
</div>
</div>
<div class="legend">
<strong style="font-size:11px;color:#555">文档类型:</strong>
<div class="legend-item"><span class="badge badge-prd">PRD</span> 需求文档</div>
<div class="legend-item"><span class="badge badge-data">DATA</span> 数据模型</div>
<div class="legend-item"><span class="badge badge-ui">UI</span> UI设计文档</div>
<div class="legend-item"><span class="badge badge-html">HTML</span> UI静态原型</div>
<div class="legend-item"><span class="badge badge-tech">TECH</span> 技术方案</div>
<div class="legend-item"><span class="badge badge-test">TEST</span> 测试用例</div>
<div class="legend-item"><span class="badge badge-task">TASK</span> 任务清单</div>
<div class="legend-item"><span class="badge badge-review">REVIEW</span> Review报告</div>
</div>
<!-- ==================== MODULE 1: 登录管理 ==================== -->
<div class="module-section">
<div class="module-title">
<span class="num">01</span> 登录管理Login
</div>
<table>
<thead>
<tr>
<th class="col-no">#</th>
<th class="col-type">类型</th>
<th class="col-name">文档名称</th>
<th class="col-path">文件路径</th>
<th class="col-cb">✓ 已读</th>
<th class="col-cb">⚠ 有问题</th>
</tr>
</thead>
<tbody>
<tr>
<td class="col-no">1</td>
<td><span class="badge badge-prd">PRD</span></td>
<td class="col-name">用户登录管理模块PRD</td>
<td class="col-path">PRD/登录管理/用户登录管理模块PRD.md</td>
<td class="col-cb"><span class="cb-box"></span></td>
<td class="col-cb"><span class="cb-box"></span></td>
</tr>
<tr>
<td class="col-no">2</td>
<td><span class="badge badge-data">DATA</span></td>
<td class="col-name">DATA_MODEL_LOGIN</td>
<td class="col-path">DATA_MODEL/DATA_MODEL_LOGIN.md</td>
<td class="col-cb"><span class="cb-box"></span></td>
<td class="col-cb"><span class="cb-box"></span></td>
</tr>
<tr>
<td class="col-no">3</td>
<td><span class="badge badge-ui">UI</span></td>
<td class="col-name">登录_UI 设计文档</td>
<td class="col-path">UI_DESIGN/登录管理/登录_UI.md</td>
<td class="col-cb"><span class="cb-box"></span></td>
<td class="col-cb"><span class="cb-box"></span></td>
</tr>
<tr>
<td class="col-no">4</td>
<td><span class="badge badge-html">HTML</span></td>
<td class="col-name">登录页(账号密码)原型</td>
<td class="col-path">UI_DESIGN/登录_账号密码_UI.html</td>
<td class="col-cb"><span class="cb-box"></span></td>
<td class="col-cb"><span class="cb-box"></span></td>
</tr>
<tr>
<td class="col-no">5</td>
<td><span class="badge badge-html">HTML</span></td>
<td class="col-name">登录页(重置密码)原型</td>
<td class="col-path">UI_DESIGN/登录_重置密码_UI.html</td>
<td class="col-cb"><span class="cb-box"></span></td>
<td class="col-cb"><span class="cb-box"></span></td>
</tr>
<tr>
<td class="col-no">6</td>
<td><span class="badge badge-html">HTML</span></td>
<td class="col-name">登录页原型(主入口)</td>
<td class="col-path">UI_DESIGN/登录_UI.html</td>
<td class="col-cb"><span class="cb-box"></span></td>
<td class="col-cb"><span class="cb-box"></span></td>
</tr>
<tr>
<td class="col-no">7</td>
<td><span class="badge badge-tech">TECH</span></td>
<td class="col-name">登录管理技术方案</td>
<td class="col-path">TECH_STACK/登录管理技术方案.md</td>
<td class="col-cb"><span class="cb-box"></span></td>
<td class="col-cb"><span class="cb-box"></span></td>
</tr>
<tr>
<td class="col-no">8</td>
<td><span class="badge badge-test">TEST</span></td>
<td class="col-name">TEST_CASES_LOGIN_MODULE</td>
<td class="col-path">TEST_CASES/TEST_CASES_LOGIN_MODULE.md</td>
<td class="col-cb"><span class="cb-box"></span></td>
<td class="col-cb"><span class="cb-box"></span></td>
</tr>
<tr>
<td class="col-no">9</td>
<td><span class="badge badge-task">TASK</span></td>
<td class="col-name">TASK / TASK_AGENT_READY</td>
<td class="col-path">PRD/TASK.md · PRD/TASK_AGENT_READY.md · PRD/TASK_AGENT_READY_P0.md</td>
<td class="col-cb"><span class="cb-box"></span></td>
<td class="col-cb"><span class="cb-box"></span></td>
</tr>
</tbody>
</table>
</div>
<!-- ==================== MODULE 2: 组织人事管理 ==================== -->
<div class="module-section">
<div class="module-title">
<span class="num">02</span> 组织人事管理Org &amp; HR
</div>
<table>
<thead>
<tr>
<th class="col-no">#</th><th class="col-type">类型</th><th class="col-name">文档名称</th>
<th class="col-path">文件路径</th><th class="col-cb">✓ 已读</th><th class="col-cb">⚠ 有问题</th>
</tr>
</thead>
<tbody>
<tr><td class="col-no">1</td><td><span class="badge badge-prd">PRD</span></td><td class="col-name">组织人事管理模块PRD</td><td class="col-path">PRD/组织人事管理/组织人事管理模块PRD.md</td><td class="col-cb"><span class="cb-box"></span></td><td class="col-cb"><span class="cb-box"></span></td></tr>
<tr><td class="col-no">2</td><td><span class="badge badge-data">DATA</span></td><td class="col-name">DATA_MODEL_ORG</td><td class="col-path">DATA_MODEL/DATA_MODEL_ORG.md</td><td class="col-cb"><span class="cb-box"></span></td><td class="col-cb"><span class="cb-box"></span></td></tr>
<tr><td class="col-no">3</td><td><span class="badge badge-ui">UI</span></td><td class="col-name">组织人事_UI 设计文档</td><td class="col-path">UI_DESIGN/组织人事管理/组织人事_UI.md</td><td class="col-cb"><span class="cb-box"></span></td><td class="col-cb"><span class="cb-box"></span></td></tr>
<tr><td class="col-no">4</td><td><span class="badge badge-html">HTML</span></td><td class="col-name">组织人事管理页原型</td><td class="col-path">UI_DESIGN/组织人事_UI.html</td><td class="col-cb"><span class="cb-box"></span></td><td class="col-cb"><span class="cb-box"></span></td></tr>
<tr><td class="col-no">5</td><td><span class="badge badge-tech">TECH</span></td><td class="col-name">组织人事技术方案</td><td class="col-path">TECH_STACK/组织人事技术方案.md</td><td class="col-cb"><span class="cb-box"></span></td><td class="col-cb"><span class="cb-box"></span></td></tr>
<tr><td class="col-no">6</td><td><span class="badge badge-test">TEST</span></td><td class="col-name"><span class="missing">— 暂无 TEST_CASES —</span></td><td class="col-path"></td><td class="col-cb"></td><td class="col-cb"></td></tr>
<tr><td class="col-no">7</td><td><span class="badge badge-task">TASK</span></td><td class="col-name">权限种子数据(组织人事-组织)</td><td class="col-path">PRD/权限管理/组织人事-组织.md</td><td class="col-cb"><span class="cb-box"></span></td><td class="col-cb"><span class="cb-box"></span></td></tr>
</tbody>
</table>
</div>
<!-- ==================== MODULE 3: 权限管理 ==================== -->
<div class="module-section">
<div class="module-title">
<span class="num">03</span> 权限管理Permission
</div>
<table>
<thead>
<tr><th class="col-no">#</th><th class="col-type">类型</th><th class="col-name">文档名称</th><th class="col-path">文件路径</th><th class="col-cb">✓ 已读</th><th class="col-cb">⚠ 有问题</th></tr>
</thead>
<tbody>
<tr><td class="col-no">1</td><td><span class="badge badge-prd">PRD</span></td><td class="col-name">权限管理模块PRD</td><td class="col-path">PRD/权限管理/权限管理模块PRD.md</td><td class="col-cb"><span class="cb-box"></span></td><td class="col-cb"><span class="cb-box"></span></td></tr>
<tr><td class="col-no">2</td><td><span class="badge badge-prd">PRD</span></td><td class="col-name">角色权限矩阵</td><td class="col-path">PRD/权限管理/角色权限矩阵.md</td><td class="col-cb"><span class="cb-box"></span></td><td class="col-cb"><span class="cb-box"></span></td></tr>
<tr><td class="col-no">3</td><td><span class="badge badge-prd">PRD</span></td><td class="col-name">权限种子数据 MVP Batch1</td><td class="col-path">PRD/权限管理/PERMISSION_SEED_MVP_BATCH1.md</td><td class="col-cb"><span class="cb-box"></span></td><td class="col-cb"><span class="cb-box"></span></td></tr>
<tr><td class="col-no">4</td><td><span class="badge badge-data">DATA</span></td><td class="col-name">DATA_MODEL_PERMISSION</td><td class="col-path">DATA_MODEL/DATA_MODEL_PERMISSION.md</td><td class="col-cb"><span class="cb-box"></span></td><td class="col-cb"><span class="cb-box"></span></td></tr>
<tr><td class="col-no">5</td><td><span class="badge badge-ui">UI</span></td><td class="col-name">权限管理_UI 设计文档</td><td class="col-path">UI_DESIGN/权限管理/权限管理_UI.md</td><td class="col-cb"><span class="cb-box"></span></td><td class="col-cb"><span class="cb-box"></span></td></tr>
<tr><td class="col-no">6</td><td><span class="badge badge-html">HTML</span></td><td class="col-name">权限管理页原型</td><td class="col-path">UI_DESIGN/权限管理_UI.html</td><td class="col-cb"><span class="cb-box"></span></td><td class="col-cb"><span class="cb-box"></span></td></tr>
<tr><td class="col-no">7</td><td><span class="badge badge-tech">TECH</span></td><td class="col-name">权限管理系统技术方案</td><td class="col-path">TECH_STACK/权限管理系统技术方案.md</td><td class="col-cb"><span class="cb-box"></span></td><td class="col-cb"><span class="cb-box"></span></td></tr>
<tr><td class="col-no">8</td><td><span class="badge badge-test">TEST</span></td><td class="col-name"><span class="missing">— 暂无 TEST_CASES —</span></td><td class="col-path"></td><td class="col-cb"></td><td class="col-cb"></td></tr>
</tbody>
</table>
</div>
<!-- ==================== MODULE 4: 楼盘管理 ==================== -->
<div class="module-section">
<div class="module-title">
<span class="num">04</span> 楼盘管理Property Complex
</div>
<table>
<thead>
<tr><th class="col-no">#</th><th class="col-type">类型</th><th class="col-name">文档名称</th><th class="col-path">文件路径</th><th class="col-cb">✓ 已读</th><th class="col-cb">⚠ 有问题</th></tr>
</thead>
<tbody>
<tr><td class="col-no">1</td><td><span class="badge badge-prd">PRD</span></td><td class="col-name">楼盘管理模块PRD</td><td class="col-path">PRD/房源管理/楼盘管理模块PRD.md</td><td class="col-cb"><span class="cb-box"></span></td><td class="col-cb"><span class="cb-box"></span></td></tr>
<tr><td class="col-no">2</td><td><span class="badge badge-data">DATA</span></td><td class="col-name">DATA_MODEL_COMPLEX楼盘</td><td class="col-path">DATA_MODEL/DATA_MODEL_COMPLEX.md</td><td class="col-cb"><span class="cb-box"></span></td><td class="col-cb"><span class="cb-box"></span></td></tr>
<tr><td class="col-no">3</td><td><span class="badge badge-ui">UI</span></td><td class="col-name">楼盘列表_UI 设计文档</td><td class="col-path">UI_DESIGN/楼盘管理/楼盘列表_UI.md</td><td class="col-cb"><span class="cb-box"></span></td><td class="col-cb"><span class="cb-box"></span></td></tr>
<tr><td class="col-no">4</td><td><span class="badge badge-ui">UI</span></td><td class="col-name">楼盘详情_UI 设计文档</td><td class="col-path">UI_DESIGN/楼盘管理/楼盘详情_UI.md</td><td class="col-cb"><span class="cb-box"></span></td><td class="col-cb"><span class="cb-box"></span></td></tr>
<tr><td class="col-no">5</td><td><span class="badge badge-ui">UI</span></td><td class="col-name">区域管理_UI 设计文档</td><td class="col-path">UI_DESIGN/楼盘管理/区域管理_UI.md</td><td class="col-cb"><span class="cb-box"></span></td><td class="col-cb"><span class="cb-box"></span></td></tr>
<tr><td class="col-no">6</td><td><span class="badge badge-html">HTML</span></td><td class="col-name">楼盘列表页原型</td><td class="col-path">UI_DESIGN/楼盘列表_UI.html</td><td class="col-cb"><span class="cb-box"></span></td><td class="col-cb"><span class="cb-box"></span></td></tr>
<tr><td class="col-no">7</td><td><span class="badge badge-html">HTML</span></td><td class="col-name">楼盘详情页原型</td><td class="col-path">UI_DESIGN/楼盘详情_UI.html</td><td class="col-cb"><span class="cb-box"></span></td><td class="col-cb"><span class="cb-box"></span></td></tr>
<tr><td class="col-no">8</td><td><span class="badge badge-html">HTML</span></td><td class="col-name">区域管理页原型</td><td class="col-path">UI_DESIGN/区域管理_UI.html</td><td class="col-cb"><span class="cb-box"></span></td><td class="col-cb"><span class="cb-box"></span></td></tr>
<tr><td class="col-no">9</td><td><span class="badge badge-tech">TECH</span></td><td class="col-name">楼盘管理技术方案</td><td class="col-path">TECH_STACK/楼盘管理技术方案.md</td><td class="col-cb"><span class="cb-box"></span></td><td class="col-cb"><span class="cb-box"></span></td></tr>
<tr><td class="col-no">10</td><td><span class="badge badge-test">TEST</span></td><td class="col-name"><span class="missing">— 暂无 TEST_CASES —</span></td><td class="col-path"></td><td class="col-cb"></td><td class="col-cb"></td></tr>
</tbody>
</table>
</div>
<!-- ==================== MODULE 5: 房源管理 ==================== -->
<div class="module-section">
<div class="module-title">
<span class="num">05</span> 房源管理Property Listing
</div>
<table>
<thead>
<tr><th class="col-no">#</th><th class="col-type">类型</th><th class="col-name">文档名称</th><th class="col-path">文件路径</th><th class="col-cb">✓ 已读</th><th class="col-cb">⚠ 有问题</th></tr>
</thead>
<tbody>
<tr><td class="col-no">1</td><td><span class="badge badge-prd">PRD</span></td><td class="col-name">房源管理模块PRD</td><td class="col-path">PRD/房源管理/房源管理模块PRD.md</td><td class="col-cb"><span class="cb-box"></span></td><td class="col-cb"><span class="cb-box"></span></td></tr>
<tr><td class="col-no">2</td><td><span class="badge badge-data">DATA</span></td><td class="col-name">DATA_MODEL_PROPERTY房源</td><td class="col-path">DATA_MODEL/DATA_MODEL_PROPERTY.md</td><td class="col-cb"><span class="cb-box"></span></td><td class="col-cb"><span class="cb-box"></span></td></tr>
<tr><td class="col-no">3</td><td><span class="badge badge-ui">UI</span></td><td class="col-name">房源列表_UI 设计文档</td><td class="col-path">UI_DESIGN/房源管理/房源列表_UI.md</td><td class="col-cb"><span class="cb-box"></span></td><td class="col-cb"><span class="cb-box"></span></td></tr>
<tr><td class="col-no">4</td><td><span class="badge badge-ui">UI</span></td><td class="col-name">房源详情_UI 设计文档</td><td class="col-path">UI_DESIGN/房源管理/房源详情_UI.md</td><td class="col-cb"><span class="cb-box"></span></td><td class="col-cb"><span class="cb-box"></span></td></tr>
<tr><td class="col-no">5</td><td><span class="badge badge-ui">UI</span></td><td class="col-name">新增房源_UI 设计文档</td><td class="col-path">UI_DESIGN/房源管理/新增房源_UI.md</td><td class="col-cb"><span class="cb-box"></span></td><td class="col-cb"><span class="cb-box"></span></td></tr>
<tr><td class="col-no">6</td><td><span class="badge badge-html">HTML</span></td><td class="col-name">房源列表页原型</td><td class="col-path">UI_DESIGN/房源列表_UI.html</td><td class="col-cb"><span class="cb-box"></span></td><td class="col-cb"><span class="cb-box"></span></td></tr>
<tr><td class="col-no">7</td><td><span class="badge badge-html">HTML</span></td><td class="col-name">房源详情页原型</td><td class="col-path">UI_DESIGN/房源详情_UI.html</td><td class="col-cb"><span class="cb-box"></span></td><td class="col-cb"><span class="cb-box"></span></td></tr>
<tr><td class="col-no">8</td><td><span class="badge badge-html">HTML</span></td><td class="col-name">新增房源页原型</td><td class="col-path">UI_DESIGN/新增房源_UI.html</td><td class="col-cb"><span class="cb-box"></span></td><td class="col-cb"><span class="cb-box"></span></td></tr>
<tr><td class="col-no">9</td><td><span class="badge badge-tech">TECH</span></td><td class="col-name">房源管理技术方案</td><td class="col-path">TECH_STACK/房源管理技术方案.md</td><td class="col-cb"><span class="cb-box"></span></td><td class="col-cb"><span class="cb-box"></span></td></tr>
<tr><td class="col-no">10</td><td><span class="badge badge-test">TEST</span></td><td class="col-name"><span class="missing">— 暂无 TEST_CASES —</span></td><td class="col-path"></td><td class="col-cb"></td><td class="col-cb"></td></tr>
<tr><td class="col-no">11</td><td><span class="badge badge-prd">PRD</span></td><td class="col-name">权限种子:房源-二手租赁</td><td class="col-path">PRD/权限管理/房源-二手租赁.md</td><td class="col-cb"><span class="cb-box"></span></td><td class="col-cb"><span class="cb-box"></span></td></tr>
</tbody>
</table>
</div>
<!-- ==================== MODULE 6: 客源管理 ==================== -->
<div class="module-section">
<div class="module-title">
<span class="num">06</span> 客源管理Client / Lead
</div>
<table>
<thead>
<tr><th class="col-no">#</th><th class="col-type">类型</th><th class="col-name">文档名称</th><th class="col-path">文件路径</th><th class="col-cb">✓ 已读</th><th class="col-cb">⚠ 有问题</th></tr>
</thead>
<tbody>
<tr><td class="col-no">1</td><td><span class="badge badge-prd">PRD</span></td><td class="col-name">客源管理模块PRD</td><td class="col-path">PRD/客源管理/客源管理模块PRD.md</td><td class="col-cb"><span class="cb-box"></span></td><td class="col-cb"><span class="cb-box"></span></td></tr>
<tr><td class="col-no">2</td><td><span class="badge badge-data">DATA</span></td><td class="col-name">DATA_MODEL_CLIENT客源</td><td class="col-path">DATA_MODEL/DATA_MODEL_CLIENT.md</td><td class="col-cb"><span class="cb-box"></span></td><td class="col-cb"><span class="cb-box"></span></td></tr>
<tr><td class="col-no">3</td><td><span class="badge badge-ui">UI</span></td><td class="col-name">客源列表_UI 设计文档</td><td class="col-path">UI_DESIGN/客源管理/客源列表_UI.md</td><td class="col-cb"><span class="cb-box"></span></td><td class="col-cb"><span class="cb-box"></span></td></tr>
<tr><td class="col-no">4</td><td><span class="badge badge-ui">UI</span></td><td class="col-name">客源详情_UI 设计文档</td><td class="col-path">UI_DESIGN/客源管理/客源详情_UI.md</td><td class="col-cb"><span class="cb-box"></span></td><td class="col-cb"><span class="cb-box"></span></td></tr>
<tr><td class="col-no">5</td><td><span class="badge badge-ui">UI</span></td><td class="col-name">新增客源_UI 设计文档</td><td class="col-path">UI_DESIGN/客源管理/新增客源_UI.md</td><td class="col-cb"><span class="cb-box"></span></td><td class="col-cb"><span class="cb-box"></span></td></tr>
<tr><td class="col-no">6</td><td><span class="badge badge-ui">UI</span></td><td class="col-name">编辑客源_UI 设计文档</td><td class="col-path">UI_DESIGN/客源管理/编辑客源_UI.md</td><td class="col-cb"><span class="cb-box"></span></td><td class="col-cb"><span class="cb-box"></span></td></tr>
<tr><td class="col-no">7</td><td><span class="badge badge-html">HTML</span></td><td class="col-name">客源列表页原型</td><td class="col-path">UI_DESIGN/客源列表_UI.html</td><td class="col-cb"><span class="cb-box"></span></td><td class="col-cb"><span class="cb-box"></span></td></tr>
<tr><td class="col-no">8</td><td><span class="badge badge-html">HTML</span></td><td class="col-name">客源详情页原型</td><td class="col-path">UI_DESIGN/客源详情_UI.html</td><td class="col-cb"><span class="cb-box"></span></td><td class="col-cb"><span class="cb-box"></span></td></tr>
<tr><td class="col-no">9</td><td><span class="badge badge-html">HTML</span></td><td class="col-name">新增客源页原型</td><td class="col-path">UI_DESIGN/新增客源_UI.html</td><td class="col-cb"><span class="cb-box"></span></td><td class="col-cb"><span class="cb-box"></span></td></tr>
<tr><td class="col-no">10</td><td><span class="badge badge-html">HTML</span></td><td class="col-name">编辑客源页原型</td><td class="col-path">UI_DESIGN/编辑客源_UI.html</td><td class="col-cb"><span class="cb-box"></span></td><td class="col-cb"><span class="cb-box"></span></td></tr>
<tr><td class="col-no">11</td><td><span class="badge badge-tech">TECH</span></td><td class="col-name">客源管理技术方案</td><td class="col-path">TECH_STACK/客源管理技术方案.md</td><td class="col-cb"><span class="cb-box"></span></td><td class="col-cb"><span class="cb-box"></span></td></tr>
<tr><td class="col-no">12</td><td><span class="badge badge-test">TEST</span></td><td class="col-name"><span class="missing">— 暂无 TEST_CASES —</span></td><td class="col-path"></td><td class="col-cb"></td><td class="col-cb"></td></tr>
<tr><td class="col-no">13</td><td><span class="badge badge-prd">PRD</span></td><td class="col-name">权限种子:客源</td><td class="col-path">PRD/权限管理/客源.md</td><td class="col-cb"><span class="cb-box"></span></td><td class="col-cb"><span class="cb-box"></span></td></tr>
</tbody>
</table>
</div>
<!-- ==================== MODULE 7: 系统配置 ==================== -->
<div class="module-section">
<div class="module-title">
<span class="num">07</span> 系统配置 / 系统管理System Config &amp; Admin
</div>
<table>
<thead>
<tr><th class="col-no">#</th><th class="col-type">类型</th><th class="col-name">文档名称</th><th class="col-path">文件路径</th><th class="col-cb">✓ 已读</th><th class="col-cb">⚠ 有问题</th></tr>
</thead>
<tbody>
<tr><td class="col-no">1</td><td><span class="badge badge-prd">PRD</span></td><td class="col-name">系统配置模块PRD</td><td class="col-path">PRD/系统配置/系统配置模块PRD.md</td><td class="col-cb"><span class="cb-box"></span></td><td class="col-cb"><span class="cb-box"></span></td></tr>
<tr><td class="col-no">2</td><td><span class="badge badge-prd">PRD</span></td><td class="col-name">系统管理模块PRD</td><td class="col-path">PRD/系统管理/系统管理模块PRD.md</td><td class="col-cb"><span class="cb-box"></span></td><td class="col-cb"><span class="cb-box"></span></td></tr>
<tr><td class="col-no">3</td><td><span class="badge badge-prd">PRD</span></td><td class="col-name">系统配置参数数据</td><td class="col-path">PRD/系统配置/系统配置参数数据.md</td><td class="col-cb"><span class="cb-box"></span></td><td class="col-cb"><span class="cb-box"></span></td></tr>
<tr><td class="col-no">4</td><td><span class="badge badge-data">DATA</span></td><td class="col-name">DATA_MODEL_SETTING系统设置</td><td class="col-path">DATA_MODEL/DATA_MODEL_SETTING.md</td><td class="col-cb"><span class="cb-box"></span></td><td class="col-cb"><span class="cb-box"></span></td></tr>
<tr><td class="col-no">5</td><td><span class="badge badge-ui">UI</span></td><td class="col-name">系统配置_UI 设计文档</td><td class="col-path">UI_DESIGN/系统配置/系统配置_UI.md</td><td class="col-cb"><span class="cb-box"></span></td><td class="col-cb"><span class="cb-box"></span></td></tr>
<tr><td class="col-no">6</td><td><span class="badge badge-ui">UI</span></td><td class="col-name">首页设置_UI 设计文档</td><td class="col-path">UI_DESIGN/系统配置/首页设置_UI.md</td><td class="col-cb"><span class="cb-box"></span></td><td class="col-cb"><span class="cb-box"></span></td></tr>
<tr><td class="col-no">7</td><td><span class="badge badge-html">HTML</span></td><td class="col-name">系统配置页原型</td><td class="col-path">UI_DESIGN/系统配置_UI.html</td><td class="col-cb"><span class="cb-box"></span></td><td class="col-cb"><span class="cb-box"></span></td></tr>
<tr><td class="col-no">8</td><td><span class="badge badge-html">HTML</span></td><td class="col-name">首页设置页原型</td><td class="col-path">UI_DESIGN/首页设置_UI.html</td><td class="col-cb"><span class="cb-box"></span></td><td class="col-cb"><span class="cb-box"></span></td></tr>
<tr><td class="col-no">9</td><td><span class="badge badge-tech">TECH</span></td><td class="col-name">系统设置技术方案</td><td class="col-path">TECH_STACK/系统设置技术方案.md</td><td class="col-cb"><span class="cb-box"></span></td><td class="col-cb"><span class="cb-box"></span></td></tr>
<tr><td class="col-no">10</td><td><span class="badge badge-tech">TECH</span></td><td class="col-name">系统管理技术文档</td><td class="col-path">TECH_STACK/系统管理技术文档.md</td><td class="col-cb"><span class="cb-box"></span></td><td class="col-cb"><span class="cb-box"></span></td></tr>
<tr><td class="col-no">11</td><td><span class="badge badge-test">TEST</span></td><td class="col-name"><span class="missing">— 暂无 TEST_CASES —</span></td><td class="col-path"></td><td class="col-cb"></td><td class="col-cb"></td></tr>
<tr><td class="col-no">12</td><td><span class="badge badge-prd">PRD</span></td><td class="col-name">权限种子:首页</td><td class="col-path">PRD/权限管理/首页.md</td><td class="col-cb"><span class="cb-box"></span></td><td class="col-cb"><span class="cb-box"></span></td></tr>
</tbody>
</table>
</div>
<!-- ==================== MODULE 8: 客户端发布管理 ==================== -->
<div class="module-section">
<div class="module-title">
<span class="num">08</span> 客户端发布管理Release Management
</div>
<table>
<thead>
<tr><th class="col-no">#</th><th class="col-type">类型</th><th class="col-name">文档名称</th><th class="col-path">文件路径</th><th class="col-cb">✓ 已读</th><th class="col-cb">⚠ 有问题</th></tr>
</thead>
<tbody>
<tr><td class="col-no">1</td><td><span class="badge badge-prd">PRD</span></td><td class="col-name">客户端发布管理模块PRD</td><td class="col-path">PRD/发布管理/客户端发布管理模块PRD.md</td><td class="col-cb"><span class="cb-box"></span></td><td class="col-cb"><span class="cb-box"></span></td></tr>
<tr><td class="col-no">2</td><td><span class="badge badge-data">DATA</span></td><td class="col-name"><span class="missing">— 暂无专属 DATA_MODEL —</span></td><td class="col-path"></td><td class="col-cb"></td><td class="col-cb"></td></tr>
<tr><td class="col-no">3</td><td><span class="badge badge-ui">UI</span></td><td class="col-name"><span class="missing">— 暂无 UI 设计文档 —</span></td><td class="col-path"></td><td class="col-cb"></td><td class="col-cb"></td></tr>
<tr><td class="col-no">4</td><td><span class="badge badge-html">HTML</span></td><td class="col-name"><span class="missing">— 暂无 HTML 原型 —</span></td><td class="col-path"></td><td class="col-cb"></td><td class="col-cb"></td></tr>
<tr><td class="col-no">5</td><td><span class="badge badge-tech">TECH</span></td><td class="col-name">客户端发布管理技术方案</td><td class="col-path">TECH_STACK/客户端发布管理技术方案.md</td><td class="col-cb"><span class="cb-box"></span></td><td class="col-cb"><span class="cb-box"></span></td></tr>
<tr><td class="col-no">6</td><td><span class="badge badge-test">TEST</span></td><td class="col-name">TEST_CASES_RELEASE_MODULE</td><td class="col-path">TEST_CASES/TEST_CASES_RELEASE_MODULE.md</td><td class="col-cb"><span class="cb-box"></span></td><td class="col-cb"><span class="cb-box"></span></td></tr>
</tbody>
</table>
</div>
<!-- ==================== 全局文档 ==================== -->
<div class="module-section">
<div class="module-title" style="background:#374151;">
⬡ 全局文档Global
</div>
<table>
<thead>
<tr><th class="col-no">#</th><th class="col-type">类型</th><th class="col-name">文档名称</th><th class="col-path">文件路径</th><th class="col-cb">✓ 已读</th><th class="col-cb">⚠ 有问题</th></tr>
</thead>
<tbody>
<tr><td class="col-no">1</td><td><span class="badge badge-prd">PRD</span></td><td class="col-name">PRD_MVP全局需求</td><td class="col-path">PRD/PRD_MVP.md</td><td class="col-cb"><span class="cb-box"></span></td><td class="col-cb"><span class="cb-box"></span></td></tr>
<tr><td class="col-no">2</td><td><span class="badge badge-prd">PRD</span></td><td class="col-name">PERSONA 用户画像定义</td><td class="col-path">PRD/PERSONA_定义.md</td><td class="col-cb"><span class="cb-box"></span></td><td class="col-cb"><span class="cb-box"></span></td></tr>
<tr><td class="col-no">3</td><td><span class="badge badge-data">DATA</span></td><td class="col-name">DATA_MODEL主索引</td><td class="col-path">DATA_MODEL/DATA_MODEL.md</td><td class="col-cb"><span class="cb-box"></span></td><td class="col-cb"><span class="cb-box"></span></td></tr>
<tr><td class="col-no">4</td><td><span class="badge badge-data">DATA</span></td><td class="col-name">DATA_MODEL_PUBLIC公共</td><td class="col-path">DATA_MODEL/DATA_MODEL_PUBLIC.md</td><td class="col-cb"><span class="cb-box"></span></td><td class="col-cb"><span class="cb-box"></span></td></tr>
<tr><td class="col-no">5</td><td><span class="badge badge-data">DATA</span></td><td class="col-name">ENUMS 枚举数据字典</td><td class="col-path">DATA_MODEL/ENUMS.md</td><td class="col-cb"><span class="cb-box"></span></td><td class="col-cb"><span class="cb-box"></span></td></tr>
<tr><td class="col-no">6</td><td><span class="badge badge-ui">UI</span></td><td class="col-name">UI_SYSTEM 设计系统</td><td class="col-path">UI_SYSTEM/UI_SYSTEM.md</td><td class="col-cb"><span class="cb-box"></span></td><td class="col-cb"><span class="cb-box"></span></td></tr>
<tr><td class="col-no">7</td><td><span class="badge badge-ui">UI</span></td><td class="col-name">UI_DESIGN 设计任务总表</td><td class="col-path">UI_DESIGN/UI_设计任务总表.md</td><td class="col-cb"><span class="cb-box"></span></td><td class="col-cb"><span class="cb-box"></span></td></tr>
<tr><td class="col-no">8</td><td><span class="badge badge-tech">TECH</span></td><td class="col-name">TECH_STACK 全局技术方案</td><td class="col-path">TECH_STACK/TECH_STACK.md</td><td class="col-cb"><span class="cb-box"></span></td><td class="col-cb"><span class="cb-box"></span></td></tr>
<tr><td class="col-no">9</td><td><span class="badge badge-tech">TECH</span></td><td class="col-name">API_CONTRACT 接口契约</td><td class="col-path">TECH_STACK/API_CONTRACT.md</td><td class="col-cb"><span class="cb-box"></span></td><td class="col-cb"><span class="cb-box"></span></td></tr>
<tr><td class="col-no">10</td><td><span class="badge badge-tech">TECH</span></td><td class="col-name">ADR 架构决策记录</td><td class="col-path">ADR.md</td><td class="col-cb"><span class="cb-box"></span></td><td class="col-cb"><span class="cb-box"></span></td></tr>
<tr><td class="col-no">11</td><td><span class="badge badge-tech">TECH</span></td><td class="col-name">测试规范</td><td class="col-path">TECH_STACK/测试规范.md</td><td class="col-cb"><span class="cb-box"></span></td><td class="col-cb"><span class="cb-box"></span></td></tr>
<tr><td class="col-no">12</td><td><span class="badge badge-test">TEST</span></td><td class="col-name">TEST_CASE_REGISTRY 测试用例注册表</td><td class="col-path">TEST_CASES/TEST_CASE_REGISTRY.md</td><td class="col-cb"><span class="cb-box"></span></td><td class="col-cb"><span class="cb-box"></span></td></tr>
<tr><td class="col-no">13</td><td><span class="badge badge-test">TEST</span></td><td class="col-name">TEST_CASE_ID_SPEC 用例ID规范</td><td class="col-path">TEST_CASES/TEST_CASE_ID_SPEC.md</td><td class="col-cb"><span class="cb-box"></span></td><td class="col-cb"><span class="cb-box"></span></td></tr>
<tr><td class="col-no">14</td><td><span class="badge badge-task">TASK</span></td><td class="col-name">TASK_AGENT_READY_P0优先任务</td><td class="col-path">PRD/TASK_AGENT_READY_P0.md</td><td class="col-cb"><span class="cb-box"></span></td><td class="col-cb"><span class="cb-box"></span></td></tr>
<tr><td class="col-no">15</td><td><span class="badge badge-review">REVIEW</span></td><td class="col-name">REVIEW_全局_2026-04-25</td><td class="col-path">REVIEW/REVIEW_全局_2026-04-25.md</td><td class="col-cb"><span class="cb-box"></span></td><td class="col-cb"><span class="cb-box"></span></td></tr>
<tr><td class="col-no">16</td><td><span class="badge badge-review">REVIEW</span></td><td class="col-name">REVIEW_全局_2026-04-26</td><td class="col-path">REVIEW/REVIEW_全局_2026-04-26.md</td><td class="col-cb"><span class="cb-box"></span></td><td class="col-cb"><span class="cb-box"></span></td></tr>
<tr><td class="col-no">17</td><td><span class="badge badge-review">REVIEW</span></td><td class="col-name">REVIEW_全局_2026-04-28</td><td class="col-path">REVIEW/REVIEW_全局_2026-04-28.md</td><td class="col-cb"><span class="cb-box"></span></td><td class="col-cb"><span class="cb-box"></span></td></tr>
<tr><td class="col-no">18</td><td><span class="badge badge-review">REVIEW</span></td><td class="col-name">VIBE_CODING 开工前缺失清单</td><td class="col-path">VIBE_CODING_开工前缺失清单.md</td><td class="col-cb"><span class="cb-box"></span></td><td class="col-cb"><span class="cb-box"></span></td></tr>
</tbody>
</table>
</div>
<!-- ==================== 统计摘要 ==================== -->
<div class="summary">
<h3>📊 文档统计摘要</h3>
<div class="summary-grid">
<div class="summary-item"><div class="count" style="color:#1565c0">17</div><div class="label">PRD 需求文档</div></div>
<div class="summary-item"><div class="count" style="color:#2e7d32">9</div><div class="label">Data Model 数据模型</div></div>
<div class="summary-item"><div class="count" style="color:#e65100">16</div><div class="label">UI 设计文档 (.md)</div></div>
<div class="summary-item"><div class="count" style="color:#880e4f">17</div><div class="label">UI HTML 原型页面</div></div>
<div class="summary-item"><div class="count" style="color:#4527a0">11</div><div class="label">Tech Stack 技术方案</div></div>
<div class="summary-item"><div class="count" style="color:#00695c">4</div><div class="label">Test Cases 测试用例</div></div>
<div class="summary-item"><div class="count" style="color:#f57f17">3</div><div class="label">Task 任务清单</div></div>
<div class="summary-item"><div class="count" style="color:#424242">4</div><div class="label">Review 报告</div></div>
</div>
<div style="margin-top:12px;font-size:11px;color:#888;">
📦 合计 <strong style="color:#1a1a2e;font-size:14px;">81</strong> 份文档待 Review &nbsp;·&nbsp;
⚠ 标记 <strong style="color:#e65100">5</strong> 个模块缺少 TEST_CASES &nbsp;·&nbsp;
⚠ 发布管理 缺少 UI 设计 + HTML 原型
</div>
</div>
<div class="footer">
Fonrey 项目文档 Review 清单 · 由 Atlas 自动生成 · 2026-05-01
</div>
</body>
</html>

Binary file not shown.

View File

@@ -1,320 +0,0 @@
# DATA_MODEL 注释补全规范 v1.0
> **作者**: Backend Engineer
> **日期**: 2026-04-29
> **目标读者**: 产品经理 / 数据模型维护者
> **目的**: 统一 `/DATA_MODEL/*.md` 中所有字段的中文注释格式与覆盖度,使其能机械化同步到 Django 模型代码与 OpenAPI 文档
---
## 一、背景
当前 Django 项目骨架已搭建完成74 个模型 / 781 个字段),但模型代码中**几乎没有任何中文字段说明**
| 维度 | 现状 |
|---|---|
| `verbose_name="中文名"`(字段中文名) | 0 / 781 |
| `help_text="..."`(字段详细说明) | 14 / 781 |
| `Meta.verbose_name`(模型中文名) | 0 / 74 |
| 模型类中文 docstring | 0 / 74 |
代码侧无法凭空生成业务语义,必须**以 DATA_MODEL 为唯一权威源**,由产品经理补全后,由开发同步到代码。
DATA_MODEL 现有的业务字段注释覆盖率约 **70%**——大量业务字段已有清晰的中文说明(这是本规范的范本),缺口集中在**技术元数据字段**和少数边角字段。本规范定义补全标准。
---
## 二、规范总览
### 2.1 必须补全的字段范围
每个表的 **每一个字段** 都必须有中文注释,包括:
- ✅ 业务字段property.name / client.phone 等)— 大多已有
- ✅ 状态枚举字段status / type / level 等)— 大多已有
- ✅ 外键字段complex_id / staff_id 等)— 部分缺失
- ⚠️ **技术元数据字段(重点缺口)**
- `id` / `uuid` — 主键
- `created_at` / `updated_at` / `deleted_at` — 时间戳
- `created_by` / `updated_by` — 操作人
- `version` — 乐观锁版本号
- `search_vector` — 全文检索向量
- `*_hash` — 加密字段配套哈希
- `*_enc` — 加密字段密文
- `sort_order` — 排序权重
### 2.2 表级别也需补全
每张表必须有:
- **表名中文标题**(已有,无需改)
- **业务摘要**1-2 句话说明该表的业务作用,已有大部分)
- **关键业务规则**(如"不可删除"、"按月分区"等,已有大部分)
---
## 三、字段注释格式(统一模板)
### 3.1 标准 Markdown 表格格式
DATA_MODEL 现有格式已经很好,**继续沿用**
```markdown
| 字段 | 类型 | 约束 | 默认 | 业务说明 |
|------|------|------|------|----------|
| id | UUID | PK | gen_random_uuid() | 主键(系统生成,业务无关) |
| name | varchar(100) | NOT NULL | - | 房源名称(如"翠湖天地 3 号楼 1502 室",展示给客户) |
| status | varchar(20) | NOT NULL | 'for_sale' | 房源状态for_sale=在售 / sold=已成交 / off_market=下架(详见 ENUMS.md |
```
**关键要求**
1. **每行的"业务说明"列必须填写**,不允许留空或只写 "-"
2. **业务说明要包含三类信息**(按重要性):
- **是什么**(必填):如"房源名称"、"主键"
- **示例值**(推荐):如"如'翠湖天地 3 号楼 1502 室'"
- **业务规则**(按需):如"展示给客户"、"系统生成"、"不可修改"
### 3.2 SQL DDL 内联注释DDL 块也要写)
DATA_MODEL 中的 SQL DDL 块也必须有中文 `-- 注释`
```sql
CREATE TABLE properties (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(), -- 主键(系统生成)
name VARCHAR(100) NOT NULL, -- 房源名称
status VARCHAR(20) NOT NULL DEFAULT 'for_sale', -- 房源状态(详见 ENUMS
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), -- 记录创建时间(系统自动)
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), -- 记录最后更新时间(系统自动)
deleted_at TIMESTAMPTZ, -- 软删除时间戳NULL=未删除
created_by UUID REFERENCES staff(id), -- 创建人FK 到员工表)
updated_by UUID REFERENCES staff(id), -- 最后修改人
version INTEGER NOT NULL DEFAULT 1 -- 乐观锁版本号(每次更新 +1
);
```
---
## 四、技术元数据字段标准注释库
**这是本规范的核心交付物**——所有表的元数据字段使用统一中文注释PM 不必逐个想,开发也能机械化套用。
### 4.1 通用元数据字段(每张表都要)
| 字段名 | 类型 | 标准中文注释 |
|---|---|---|
| `id` | UUID / BIGINT | 主键(系统生成,业务无关) |
| `created_at` | TIMESTAMPTZ | 记录创建时间(系统自动) |
| `updated_at` | TIMESTAMPTZ | 记录最后更新时间(系统自动) |
| `deleted_at` | TIMESTAMPTZ NULL | 软删除时间戳NULL=未删除,非 NULL=已软删除 |
| `created_by` | FK → staff/account | 创建人(操作员工) |
| `updated_by` | FK → staff/account | 最后修改人(操作员工) |
| `version` | INTEGER | 乐观锁版本号(每次更新 +1用于并发冲突检测 |
### 4.2 加密字段配套(涉及手机号/身份证等敏感数据)
| 字段名 | 类型 | 标准中文注释 |
|---|---|---|
| `phone_enc` | BYTEA | 手机号密文AES-256-GCM 加密,不可直接查询) |
| `phone_hash` | CHAR(64) | 手机号哈希SHA-256用于唯一性约束和精确查询 |
| `id_card_enc` | BYTEA | 身份证号密文AES-256-GCM 加密) |
| `id_card_hash` | CHAR(64) | 身份证号哈希SHA-256 |
### 4.3 全文检索字段
| 字段名 | 类型 | 标准中文注释 |
|---|---|---|
| `search_vector` | TSVECTOR | 全文检索向量(由触发器或 Celery 自动维护) |
### 4.4 排序与状态字段
| 字段名 | 类型 | 标准中文注释 |
|---|---|---|
| `sort_order` | INTEGER | 排序权重(数值越小越靠前) |
| `is_active` | BOOLEAN | 是否启用true=启用false=禁用) |
| `is_deleted` | BOOLEAN | 是否已删除(与 deleted_at 二选一,按表设计) |
### 4.5 计分/统计字段(多见于楼盘、房源完成度)
| 字段名 | 类型 | 标准中文注释 |
|---|---|---|
| `total_score` | SMALLINT | 总分0-100其他 score_* 字段加权汇总) |
| `calculated_at` | TIMESTAMPTZ | 上次计算时间(由 Celery 异步任务更新,非实时) |
---
## 五、业务字段注释三段式(用于补全缺失项)
对于业务字段,使用**三段式**结构(用 / 或 分隔):
```
[字段中文名][示例值或取值范围][业务规则或备注]
```
**示例**
| 原始(缺失) | 补全后 |
|---|---|
| `floor` | `所在楼层1=底层;总楼层不超过 total_floorsCheckConstraint 校验)` |
| `built_year` | `建成年份:如 2018可空老房源无记录` |
| `is_only_house` | `是否唯一住房true=唯一/false=非唯一/NULL=未确认;影响交易税费计算` |
| `completeness_score` | `房源完整度评分0-100由 Celery 异步计算,非实时;前端列表页展示徽章` |
| `commission_rate` | `佣金费率:百分比,如 2.5 表示 2.5%;范围 0-10` |
| `protection_end_at` | `保护期结束时间null=永久保护;保护期内禁止其他经纪人接单` |
---
## 六、状态/枚举字段注释规范
枚举字段必须**列出所有可能值的中英对照**
```markdown
| status | varchar(20) | NOT NULL | 'for_sale' | 房源状态for_sale=在售 / sold=已成交 / rented=已出租 / off_market=下架 / pending=审核中(详见 ENUMS.md §房源状态) |
```
**规则**
1. 使用 `英文值=中文名` 的对照
2. 多个值用 ` / ` 分隔
3. 末尾加 `(详见 ENUMS.md §章节名)` 引用枚举权威源
4. 默认值如有业务含义需说明(如"新建房源默认 for_sale"
---
## 七、外键字段注释规范
```markdown
| complex_id | UUID | FK → complexes.id | NOT NULL | 所属楼盘(关联 complexes 表;房源必须挂在楼盘下) |
| seller_agent_id | UUID | FK → staff.id NULL | NULL | 出售经纪人接单后填写ON DELETE SET NULL |
| created_by | UUID | FK → staff.id NULL | NULL | 创建人(系统自动从登录会话填写) |
```
**规则**
1. 必须说明**关联表**"关联 X 表"
2. 必须说明**业务含义**"所属楼盘"、"出售经纪人",而非只写"complex_id"
3. 可空字段说明**何时为空**"接单后填写"、"老数据无此字段"
---
## 八、表级别补全要求
每张表在 DATA_MODEL 中必须有:
```markdown
### 3.X `table_name` — 中文表名
**业务作用**[一句话说明这张表存什么、为什么需要]
**关键业务规则**
- 规则 1手机号必须加密存储
- 规则 2跟进日志不可删除
- 规则 3每月自动分区
**字段表**
[标准字段表格]
**索引说明**
- idx_xxx[为什么建这个索引,支撑什么查询]
```
---
## 九、补全工作清单PM 待办)
### 9.1 待补全文件清单
| DATA_MODEL 文件 | 当前覆盖率(业务字段) | 主要缺口 | 优先级 |
|---|---|---|---|
| DATA_MODEL_PROPERTY.md | ~75% | 技术元数据字段;部分 shop_* 字段说明;保护期字段 | P0 |
| DATA_MODEL_CLIENT.md | ~70% | 跟进日志字段;匹配字段;技术元数据 | P0 |
| DATA_MODEL_COMPLEX.md | ~80% | 楼栋/单元字段;技术元数据 | P1 |
| DATA_MODEL_ORG.md | ~80% | 员工日志字段;技术元数据 | P1 |
| DATA_MODEL_LOGIN.md含 ACCOUNT | ~70% | 登录尝试/会话字段;技术元数据 | P0 |
| DATA_MODEL_PERMISSION.md | ~85% | 权限种子数据字段说明;技术元数据 | P1 |
| DATA_MODEL_SETTING.md | ~75% | LookupItem 字段;技术元数据 | P2 |
| DATA_MODEL_PUBLIC.md含 TENANT/RELEASE | ~70% | tenant/domain/release 字段;技术元数据 | P1 |
### 9.2 检查清单PM 自检)
补完后请逐文件检查:
- [ ] 每个字段表的"业务说明"列**全部填写**,无空行无 "-"
- [ ] 所有技术元数据字段id/created_at/...)使用 §四 的标准注释
- [ ] 所有枚举字段列出全部取值的中英对照
- [ ] 所有外键字段说明关联表 + 业务含义
- [ ] 每张表有"业务作用"段落
- [ ] 每张表有"关键业务规则"段落(即使只有 1 条)
- [ ] DDL 块的每行 SQL 都有 `-- 中文注释`
---
## 十、补全完成后开发同步流程
PM 补完后,开发会按以下顺序同步到 Django 代码(无需 PM 介入):
| 步骤 | 同步目标 | 来源 | 工时估算 |
|---|---|---|---|
| 1 | `Meta.verbose_name` / `verbose_name_plural` | 表名("### 3.X xxx — 中文表名"中的中文部分) | 30 分钟 |
| 2 | 模型类 docstring | 表的"业务作用" + "关键业务规则" | 1 小时 |
| 3 | 字段 `verbose_name="..."` | 字段表"业务说明"的第一段 | 3-4 小时 |
| 4 | 字段 `help_text="..."`(关键字段) | 字段表"业务说明"的二/三段(示例 + 规则) | 2 小时 |
**总计开发工时**:约 7-8 小时,分批次按 app commit。
代码层面这些注释会被以下系统自动消费:
- **Django Admin**:列表页/表单页直接显示中文表名和字段名
- **drf-spectacular**:生成 OpenAPI 文档时 `verbose_name → title``help_text → description`
- **Django shell / 报错信息**:使用中文字段名
---
## 十一、范例:一张完整规范的表(参考标准)
参考 `DATA_MODEL_PROPERTY.md` §3.X `properties` 表,补全后应类似:
```markdown
### 3.1 `properties` — 房源主表
**业务作用**:存储经纪公司管理的所有待售/待租房屋的核心信息,是整个房源管理模块的根表。
**关键业务规则**
- 软删除:通过 `deleted_at` 标记,绝不物理删除(合规要求)
- 楼层校验:`floor <= total_floors`CheckConstraint
- 完整度异步:`completeness_score` 由 Celery 任务计算,非实时
- 全文检索:`search_vector` 由数据库触发器自动维护
**字段表**
| 字段 | 类型 | 约束 | 默认 | 业务说明 |
|------|------|------|------|----------|
| id | UUID | PK | gen_random_uuid() | 主键(系统生成,业务无关) |
| property_type | varchar(30) | NOT NULL | - | 房源类型apartment=住宅 / villa=别墅 / shop=商铺 / office=写字楼(详见 ENUMS |
| status | varchar(20) | NOT NULL | 'for_sale' | 房源状态for_sale=在售 / sold=已成交 / rented=已出租 / off_market=下架(详见 ENUMS |
| name | varchar(100) | NOT NULL | - | 房源名称(如"翠湖天地 3 号楼 1502 室",展示给客户) |
| complex_id | UUID | FK → complexes.id | NOT NULL | 所属楼盘(房源必须挂在楼盘下) |
| floor | smallint | NOT NULL | - | 所在楼层1=底层;不超过 total_floors |
| total_floors | smallint | NOT NULL | - | 楼栋总层数 |
| sale_price | decimal(12,2) | NULL | - | 挂牌售价:单位元;可空(仅出租房源) |
| has_elevator | boolean | NULL | - | 是否有电梯true=有 / false=无 / NULL=未确认 |
| seller_agent_id | UUID | FK → staff.id NULL | NULL | 出售经纪人接单后填写ON DELETE SET NULL |
| completeness_score | smallint | NOT NULL | 0 | 房源完整度评分0-100由 Celery 异步计算,非实时 |
| created_at | TIMESTAMPTZ | NOT NULL | NOW() | 记录创建时间(系统自动) |
| updated_at | TIMESTAMPTZ | NOT NULL | NOW() | 记录最后更新时间(系统自动) |
| deleted_at | TIMESTAMPTZ | NULL | NULL | 软删除时间戳NULL=未删除 |
| created_by | UUID | FK → staff.id NULL | NULL | 创建人(系统自动从登录会话填写) |
| version | integer | NOT NULL | 1 | 乐观锁版本号(每次更新 +1 |
| search_vector | TSVECTOR | NULL | NULL | 全文检索向量(由触发器自动维护) |
```
---
## 十二、变更与维护
- 本规范由开发与 PM 共同维护
- DATA_MODEL 任何新增字段必须遵循本规范
- 字段含义变更时,必须同步更新 DATA_MODEL 注释 → 触发开发同步代码注释
- 本规范版本变更需 PM + 开发双方确认
**联系人**
- 规范问题 → Backend Engineer
- 业务字段含义 → Product Manager
- 枚举权威 → ENUMS.md