Files
nexus/Project/fonrey/TECH_STACK/房源管理技术方案.md
Shen Wei 712a33fbac docs: 新增系统配置模块PRD及数据模型文档,更新TASK.md
- 新增 PRD/系统配置/系统配置模块PRD.md(v0.1 Draft)
  - MVP 范围:US-SETTING-001-A(Lookup Items)、B(房源字段必填规则)、C(客源录入规则)
- 新增 PRD/系统配置/系统配置数据模型设计说明_for_Atlas.md
- 新增 PRD/系统配置/系统配置参数数据.md(竞品参数数据)
- 删除旧版 PRD/系统配置/系统配置.md(已被新PRD替代)
- 新增 DATA_MODEL/DATA_MODEL_SETTING.md(系统配置数据模型)
- 新增 DATA_MODEL/ENUMS.md(枚举定义与约定)
- 新增 AGENTS.md(AI Agent 开发规范)
- 更新 PRD/TASK.md:US-SETTING-001 拆分为 A/B/C 三个子任务,修正参考文档路径与验收标准
- 新增 VIBE_CODING_开工前缺失清单.md
- 新增 TECH_STACK/房源管理技术方案.md
- 更新 DATA_MODEL/DATA_MODEL.md、DATA_MODEL_CLIENT.md、DATA_MODEL_LOGIN.md
- 更新 PRD/PRD_MVP.md、PRD/权限管理/权限管理模块PRD.md
- 更新 TECH_STACK/TECH_STACK.md、权限管理系统技术方案.md
- 更新 UI_DESIGN/preview.html、UI_SYSTEM/UI_SYSTEM.md
- 新增 prompt/PRD - 为系统设置生成PRD设计文档.md、更新 prompt 模板
2026-04-27 15:33:12 +08:00

16 KiB
Raw Blame History

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 + Alpine.js + PostgreSQL 16 + Redis + Celery + Cloudflare R2
关联 PRD: PRD/房源管理/房源管理模块PRD.mdv2.1
关联数据模型: DATA_MODEL/DATA_MODEL_PROPERTY.md(本方案不重复 DDL
关联枚举字典: DATA_MODEL/ENUMS.md
最后更新: 2026-04-27


一、文档定位与边界

本文件只定义房源模块的:

  1. 服务边界与模块协作
  2. API 端点设计(重点)
  3. HTMX 局刷协议
  4. 权限接入、异步任务、缓存与性能约束
  5. 测试与验收映射

不在本文件展开表结构字段、索引、DDL、触发器。请以 DATA_MODEL_PROPERTY.md 为唯一权威来源。


二、P0 范围(与 Task Board 对齐)

本方案覆盖 PRD/TASK.md 中房源 P0 User Story

  • US-PROPERTY-001录入二手住宅出售/出租)
  • US-PROPERTY-002查看与筛选房源列表
  • US-PROPERTY-003查看房源详情
  • US-PROPERTY-004写入与查看跟进记录
  • US-PROPERTY-005管理房源图片上传/分类/排序)
  • US-PROPERTY-006管理业主联系人
  • US-PROPERTY-007调整房源价格
  • US-PROPERTY-008变更房源状态

三、模块架构边界

3.1 模块职责

apps/property 负责:

  • 房源主流程:新增、列表检索、详情展示、状态与价格维护
  • 房源协作数据:联系人、跟进、图片
  • 房源审计轨迹:挂牌历史、调价记录、敏感查看记录(通过服务层写入)

3.2 外部依赖

依赖模块 依赖内容 依赖方式
apps/complex 小区/楼盘基础信息、联想搜索 Service 调用 + 外键引用
apps/org 员工组织信息(相关方、操作人) 外键 + Service 查询
apps/permission RBAC/Scope 权限判定 PermissionChecker + ScopeQueryBuilder
apps/setting 可配置枚举(来源、跟进目的等) lookup_items 读取缓存
core/encryption.py 手机号加密/脱敏/哈希 统一工具调用,禁止明文
core/cache.py 筛选缓存、任务进度、短期详情缓存 Redis Key 带租户前缀
Celery 导出、图片处理、完成度重算 异步任务
Cloudflare R2 房源图片与附件对象存储 预签名上传 + 回写元数据

3.3 分层约束(必须遵守)

  • views.py 仅做:参数校验、权限门禁、调用 service、组织响应
  • 业务规则全部下沉到 services/
  • 所有写操作必须落审计(至少 follow_logs 或 change_logs
  • 耗时 >500ms 的流程必须异步化

四、API 设计总原则P0

  1. 页面端点与数据端点分离
    • 页面SSR + HTMX 容器):/property/...
    • 数据 APIJSON/api/property/...
  2. HTMX 局刷优先列表筛选、Tab 内容、弹窗提交走局部刷新。
  3. 列表性能目标89k 房源规模下,p95 < 2s(索引 + Keyset 分页 + 预加载)。
  4. 统一错误协议
    • JSON{"error":"...","code":"SNAKE_CASE"}
    • HTMX返回片段 + HX-Trigger Toast
  5. 权限前置:所有 API 在 service 执行前完成权限与 scope 过滤。
  6. 敏感信息最小暴露:默认打码;明文查看必须具备权限并记录审计。

五、端点清单(核心)

5.1 页面路由SSR + HTMX 容器)

路径 方法 鉴权 说明
/property/list/ GET 房源列表主页面(包含筛选栏与列表容器)
/property/create/ GET 新增房源页面P0: 住宅)
/property/{property_id}/ GET 房源详情主页面(多 Tab 容器)
/property/{property_id}/edit/ GET 编辑房源页面(非弹窗)

5.2 HTMX 片段端点

路径 方法 用途 返回
/property/fragments/list-table/ GET 列表筛选/排序/翻页局刷 HTML 片段
/property/fragments/filter-panel/ GET 筛选项联动刷新(区域→商圈等) HTML 片段
/property/{id}/fragments/tab/{tab_name}/ GET 详情页 Tab 懒加载(跟进/相册/附件等) HTML 片段
/property/{id}/fragments/contact-panel/ GET 联系人侧栏局刷 HTML 片段
/property/{id}/fragments/follow-timeline/ GET 跟进时间线局刷(筛选后) HTML 片段
/property/{id}/fragments/photo-grid/ GET 相册宫格局刷 HTML 片段

所有 fragment 端点必须校验 HX-Request=true,非 HTMX 请求返回 400。

5.3 JSON APIP0

端点 方法 鉴权 权限码(建议) 说明
/api/property/ POST property.create.allow 新增房源US-001
/api/property/list/query/ POST property.list.view.scope 列表查询US-002
/api/property/{id}/detail/ GET property.list.view.scope 详情聚合数据US-003
/api/property/{id}/status/change/ POST property.status.change.allow 改状态US-008
/api/property/{id}/price/change/ POST property.price.change.allow 调价US-007
/api/property/{id}/follow-logs/ POST property.follow.create.allow 新增跟进US-004
/api/property/{id}/follow-logs/query/ POST property.follow.view.scope 跟进查询US-004
/api/property/{id}/contacts/ POST property.contact.create.allow 新增联系人US-006
/api/property/{id}/contacts/{contact_id}/ PATCH property.contact.edit.allow 编辑联系人US-006
/api/property/{id}/contacts/same-owner/ GET property.list.view.scope 同业主其他房源US-006
/api/property/{id}/owner-phone/view/ POST property.owner_phone.view.daily_limit 查看号码(审计+额度)
/api/property/{id}/photos/upload-token/ POST property.photo.upload.allow 获取 R2 预签名US-005
/api/property/{id}/photos/commit/ POST property.photo.upload.allow 上传回执写库US-005
/api/property/{id}/photos/reorder/ POST property.photo.edit.allow 图片排序US-005
/api/property/{id}/photos/category/batch/ POST property.photo.edit.allow 批量改分类US-005
/api/property/{id}/photos/{photo_id}/set-cover/ POST property.photo.edit.allow 设封面US-005
/api/property/export/jobs/ POST property.list.export.scope 创建导出任务US-002
/api/property/export/jobs/{job_id}/ GET property.list.export.scope 查询导出任务状态
/api/property/export/jobs/{job_id}/download/ GET property.list.export.scope 下载导出结果

六、关键 API 规范(请求/响应)

6.1 新增房源

POST /api/property/

{
  "property_type": "residential",
  "trade_type": "sale_rent",
  "complex_id": "uuid",
  "building_no": "5",
  "unit_no": "2",
  "room_no": "1102",
  "floor_current": 11,
  "floor_total": 33,
  "area": "89.50",
  "layout": {"bedroom": 3, "living": 2, "bathroom": 2, "kitchen": 1, "balcony": 1},
  "sale_price": "368.00",
  "rent_price": null,
  "owner_contacts": [
    {
      "name": "张三",
      "identity": "owner",
      "phone": "13800000000",
      "gender": "male"
    }
  ],
  "related_staff": {
    "first_agent_id": "uuid",
    "number_agent_id": "uuid",
    "sale_agent_id": "uuid"
  }
}

成功:201

{
  "id": "uuid",
  "code": "FY202604270001",
  "redirect_url": "/property/uuid/",
  "message": "保存成功"
}

6.2 列表查询

POST /api/property/list/query/

{
  "keyword": "阳光花园",
  "filters": {
    "district_ids": ["uuid"],
    "status": ["sale", "rent"],
    "attribute": ["public"],
    "price_sale": {"min": 200, "max": 500}
  },
  "sort": {"field": "updated_at", "order": "desc"},
  "pagination": {"mode": "keyset", "cursor": "opaque_cursor", "limit": 20}
}

成功:200

{
  "items": [{"id": "uuid", "title": "阳光花园 5-2-1102", "status": "sale"}],
  "next_cursor": "opaque_cursor_2",
  "total_estimate": 89432
}

6.3 改状态

POST /api/property/{id}/status/change/

{
  "from_status": "sale",
  "to_status": "paused",
  "reason": "业主暂不出售"
}

校验规则:

  • 必须符合状态机(例如 sale -> paused/other_sale/deal
  • reason 必填,<= 50 字

6.4 调价

POST /api/property/{id}/price/change/

{
  "sale_price": "350.00",
  "bottom_price": "338.00",
  "reason": "业主急售"
}

成功后联动:

  • 更新当前挂牌价
  • 追加 price_changes 记录
  • 触发详情页价格区域局刷

6.5 写跟进

POST /api/property/{id}/follow-logs/

{
  "follow_type": "write_follow",
  "purpose": "owner_follow",
  "content": "今日电话沟通业主接受350万附近报价。",
  "visibility": "team",
  "attachments": ["object_key_1", "object_key_2"]
}

校验规则:

  • content: 6~500 字
  • 附件图片最多 10 张,单张 <=20MB

6.6 导出任务

  1. 创建:POST /api/property/export/jobs/
{"query_snapshot": {...}, "columns": ["code", "title", "status", "sale_price"]}
  1. 查询:GET /api/property/export/jobs/{job_id}/
{"status":"running", "progress":65}
  1. 下载:GET /api/property/export/jobs/{job_id}/download/
  • 任务完成后返回一次性下载 URL

七、HTMX 交互约定(房源模块)

7.1 请求头与响应头

  • 请求必须带:HX-Request: true
  • 成功提示:HX-Trigger: {"toast":{"level":"success","message":"保存成功"}}
  • 失败提示:HX-Trigger: {"toast":{"level":"error","message":"保存失败"}}
  • 跳转:HX-Redirect: /property/{id}/

7.2 片段模板命名

场景 模板
列表表格 templates/property/fragments/list_table.html
跟进时间线 templates/property/fragments/follow_timeline.html
联系人面板 templates/property/fragments/contact_panel.html
相册宫格 templates/property/fragments/photo_grid.html

7.3 推荐前端触发方式

  • 筛选提交:hx-post="/property/fragments/list-table/"
  • 切 Tabhx-get="/property/{id}/fragments/tab/follow/"
  • 弹窗提交:hx-post + hx-target 当前弹窗容器,成功后触发父容器刷新

八、权限与数据范围设计

8.1 P0 必需权限项(最小集合)

DATA_MODEL_PERMISSION.md 对齐;若 permission_defs 尚未落库,则按下列 code 补种子。

权限 code 类型 说明
property.list.view.scope SCOPE 查看房源范围
property.list.export.scope SCOPE 导出房源范围
property.create.allow BOOLEAN 新增房源
property.list.edit.allow BOOLEAN 编辑房源基础信息
property.price.change.allow BOOLEAN 调价
property.status.change.allow BOOLEAN 改状态
property.follow.view.scope SCOPE 查看跟进范围
property.follow.create.allow BOOLEAN 新增跟进
property.contact.create.allow BOOLEAN 新增联系人
property.contact.edit.allow BOOLEAN 编辑联系人
property.photo.upload.allow BOOLEAN 上传图片
property.photo.edit.allow BOOLEAN 改分类/排序/封面
property.owner_phone.view.daily_limit INTEGER 每日查看号码上限0=不限制)

8.2 Scope 与业务属性叠加

最终查询范围 = 权限 scope 过滤业务状态过滤房源属性规则(公盘/私盘/特盘/封盘)

  • 权限系统不直接改写 properties.attribute
  • 房源属性由业务规则决定可见性,权限只决定“理论上可看范围”

8.3 查看号码审计

调用 /owner-phone/view/ 时必须:

  1. 校验 daily_limit
  2. 解密返回明文(仅本次)
  3. 自动写入 follow_logssensitive_view
  4. sensitive_view 记录不可删除

九、异步任务与缓存策略

9.1 Celery 任务

任务 触发时机 说明
property_export_task 创建导出任务后 按查询快照导出 Excel 到 R2
property_photo_postprocess_task 图片上传 commit 后 生成缩略图、提取元数据
property_completeness_recalc_task 调价/状态变更/跟进/图片更新后 异步重算维护完成度

所有任务参数必须包含 tenant_schema_name,任务开头显式切 schema。

9.2 Redis Key 规范

Key TTL 说明
{schema}:property:list:query:{hash} 60s 热门筛选结果短缓存
{schema}:property:detail:{id} 120s 详情聚合缓存
{schema}:property:export:{job_id} 24h 导出任务状态
{schema}:property:owner_phone:view:{staff_id}:{date} 24h 每日查看号码计数

十、性能与可靠性约束

  1. 列表查询强制 Keyset 分页(禁止 OFFSET
  2. 所有筛选字段必须走已建索引(见 DATA_MODEL_PROPERTY.md)。
  3. 大列表默认返回精简字段,详情页再按 Tab 懒加载。
  4. 导出走异步任务,前端轮询任务状态,禁止同步导出。
  5. 批量写操作使用事务,失败要回滚并返回结构化错误。

十一、安全与合规

  • 手机号、微信等敏感信息:入库加密、展示脱敏
  • API 全链路 HTTPS
  • 操作审计必须包含:操作者、时间、旧值/新值、来源 IP
  • 文件上传白名单:bmp/jpg/jpeg/png/gif/svgP0 与 PRD 对齐)
  • 上传大小限制20MB/文件
  • 防刷:列表查询、号码查看、导出任务创建均需限流

十二、错误码约定(房源模块)

code HTTP 场景
PROPERTY_NOT_FOUND 404 房源不存在或无访问权限
PROPERTY_INVALID_STATE_TRANSITION 400 非法状态流转
PROPERTY_PRICE_INVALID 400 价格参数非法
PROPERTY_FOLLOW_CONTENT_TOO_SHORT 400 跟进内容不足 6 字
PROPERTY_PHONE_VIEW_LIMIT_EXCEEDED 429 查看号码超限
PROPERTY_EXPORT_JOB_NOT_READY 409 导出未完成即下载
PROPERTY_PERMISSION_DENIED 403 权限不足

十三、测试映射P0

User Story 最低测试覆盖
US-PROPERTY-001 新增成功 / 必填校验失败 / 无权限403
US-PROPERTY-002 关键词+组合筛选 / Keyset 分页 / 导出任务创建
US-PROPERTY-003 详情加载 / 号码默认脱敏 / 查看号码审计
US-PROPERTY-004 跟进写入成功 / 内容长度校验 / 时间线筛选
US-PROPERTY-005 上传签名获取 / commit 落库 / 排序与封面设置
US-PROPERTY-006 联系人新增编辑 / 同业主房源查询
US-PROPERTY-007 调价成功并写历史 / 理由缺失失败
US-PROPERTY-008 合法流转成功 / 非法流转失败

测试强制要求

  • 集成测试使用 TenantClient
  • HTMX 请求必须带 HTTP_HX_REQUEST=true
  • 权限三态200 / 403 / 302
  • Celery 在测试环境 eager 执行

十四、落地顺序建议(供开发阶段使用)

  1. 先搭建列表查询 + Scope 权限过滤US-002
  2. 再打通新增与详情主链路US-001,003
  3. 上线状态变更与调价US-007,008
  4. 补齐跟进、联系人、图片US-004,005,006
  5. 最后接入导出异步与性能压测

十五、与其他文档的同步规则

  • 枚举变更:同步 DATA_MODEL/ENUMS.md
  • 权限 code 变更:同步 DATA_MODEL/DATA_MODEL_PERMISSION.md
  • API 变更:同步本文件与对应 PRD 验收条目
  • 超出 P0 的能力(如地图找房、商业地产)只能写“预留”,不得提前实现