diff --git a/Project/fonrey/AGENTS.md b/Project/fonrey/AGENTS.md new file mode 100644 index 00000000..bc8809ff --- /dev/null +++ b/Project/fonrey/AGENTS.md @@ -0,0 +1,317 @@ +> **For AI assistants**: Read this entire file before writing any code. All decisions here are final. Do not suggest alternatives unless asked. Every new feature or User Story implementation must be accompanied by corresponding tests as defined in this document. + +# Fonrey(房睿)— AGENTS.md + +**适用对象**:所有 AI Coding Agent(vibe coding 模式) +**文档定位**:开发启动前的强制阅读清单,定义架构约定、禁止项和文档导航 +**最后更新**:2026-04-27 + +--- + +## 1. 项目概览 + +**Fonrey(房睿)房产经纪管理系统** —— 面向房地产经纪公司的 B2B SaaS 平台,解决房源/客源信息散乱、跟进缺失、重复录入等痛点,支撑单租户 89,000+ 房源数据量级下的高效匹配。 + +- **核心模块**:房源管理、客源管理、楼盘管理、组织人事、权限管理、登录管理、系统设置、客户端发布 +- **目标用户**:一线经纪人(高频)、店长/经理(每日)、运营/行政(每日)、系统管理员(不定期) +- **形态**:Web 端为主 + Electron 桌面客户端(壳应用);移动端为 v2 规划 +- **设计哲学**:数据一致性 > 录入/筛选速度 > UI 简洁高效。优先保障多租户数据物理隔离与极速响应。 + +--- + +## 2. 核心技术栈 + +| 层级 | 技术选型 | 说明 | +|---|---|---| +| **Frontend** | HTMX + Alpine.js + Tailwind CSS | 无重前端框架;HTMX 局刷、Alpine 管状态、Tailwind 样式 | +| **Backend** | Django 4.x(ASGI 模式) | 支持异步能力 | +| **Multi-tenant** | `django-tenants` | PostgreSQL Schema 隔离,租户数据物理安全 | +| **Database** | PostgreSQL 16 + PgBouncer | 连接池优化,支撑高并发 | +| **Cache** | Redis | 缓存、限流、Token、权限快照 | +| **Tasks** | Celery + Celery Beat | 异步导出、智能配房、邮件、图片转码 | +| **Storage** | Cloudflare R2(S3 兼容) | 房源图片、附件、客户端安装包 | +| **CDN** | Cloudflare | 静态资源 + 客户端更新包加速 | +| **Server** | Gunicorn + Uvicorn workers + Nginx | ASGI 服务部署 | +| **Monitoring** | Sentry + Grafana | 错误追踪 + 指标监控 | +| **Deployment** | Docker Compose | 容器化部署 | +| **Desktop Client** | Electron + electron-updater | 壳应用,渲染层复用 Web 技术栈 | + +--- + +## 3. 目录结构 + +代码库标准目录结构如下,**严格遵循**,不得自行创建新的顶层目录: + +``` +fonrey/ +├── apps/ +│ ├── tenant/ # django-tenants 配置(shared_apps) +│ ├── account/ # 登录认证 +│ ├── permission/ # 权限管理 +│ ├── org/ # 组织人事(org_units, staff) +│ ├── region/ # 区域管理(districts, business_areas) +│ ├── complex/ # 楼盘管理(complexes, buildings, schools) +│ ├── property/ # 房源核心(含 models/services/tasks 三层) +│ ├── client/ # 客源管理 +│ ├── setting/ # 系统设置(lookup, tags) +│ └── release/ # 客户端发布管理(shared_apps) +├── shared/ # 公共 Schema App(public schema 模型) +└── core/ + ├── models/base.py # 抽象基类(所有业务表继承) + ├── encryption.py # PII 加密(AES-256-GCM) + └── cache.py # Redis 工具(含 tenant 前缀) +``` + +**Django App 内部分层规范**(以 `property` 为典型,所有 App 参照执行): + +``` +apps/property/ +├── models/ # 一表一文件,禁止全部堆在 models.py +├── services/ # 业务逻辑(完成度计算、重复检测、匹配等) +├── tasks.py # Celery 异步任务 +├── views.py # HTMX/JSON 视图(薄视图,调 services) +└── urls.py +``` + +--- + +## 4. 关键开发约定 + +### 4.1 多租户隔离(最高优先级) + +- 所有数据库查询**必须**基于当前租户 Schema;`django-tenants` 中间件已自动切换,不得绕过 +- **严禁**跨租户 SQL 查询(包括 raw SQL 和 ORM 的 `using()` 指定 public schema) +- `shared_apps` 仅放平台基础数据:`Tenant`、`ClientRelease`、`PermissionDef`、`PlatformAdmin` 等 +- Celery 任务必须在任务参数中传入 `tenant_schema_name`,任务开头调用 `connection.set_schema(schema_name)` 切换到正确 Schema,**不得依赖外部上下文传递** + +### 4.2 前端交互约定 + +- **HTMX** 处理局部 DOM 刷新:分页、筛选、联想搜索、表单提交 +- **Alpine.js** 处理前端状态:弹窗开关、多选状态、字数统计、条件显示 +- **禁止**编写复杂原生 JavaScript;逻辑无法用 HTMX/Alpine 覆盖时,优先提出问题而不是自行引入 JS 库 +- HTMX 请求失败(4xx/5xx)必须触发全局 Toast 提示(通过 `HX-Trigger` 响应头) +- 所有 HTMX 局部请求后端视图必须校验 `HX-Request` header,防止直接访问返回残缺 HTML + +### 4.3 异步任务约定 + +- 所有耗时 **> 500ms** 的操作**必须**经 Celery 异步执行:Excel 导出、图片处理、智能配房、邮件发送、完成度重算 +- Celery Beat 定时任务:私客自动转公客(每小时)、重复客源检测(每日) +- 任务状态存 Redis,前端通过轮询 HTMX 端点展示进度 + +### 4.4 数据模型约定 + +| 约定 | 规则 | +|------|------| +| 主键类型 | `UUID v4`(`gen_random_uuid()`),禁止自增整数 | +| 软删除 | 所有核心表含 `deleted_at TIMESTAMPTZ`,查询默认加 `WHERE deleted_at IS NULL` | +| 时间戳 | 全部使用 `TIMESTAMPTZ`(含时区),禁止 naive datetime | +| 手机号存储 | AES-256-GCM 加密,建立 SHA-256 哈希索引,通过 `core/encryption.py` 操作 | +| 审计字段 | `created_by UUID`、`updated_by UUID` 全表覆盖 | +| 枚举值 | 业务枚举用 `VARCHAR + CHECK CONSTRAINT`;不得在代码中硬编码中文枚举值 | +| 金额 | `NUMERIC(12,2)` 万元精度,禁止 FLOAT | +| 大文本 | `TEXT` 类型,不设长度限制 | +| 不可删除记录 | `listing_histories`、`price_changes` 无 `deleted_at`,append-only,禁止物理删除 | + +### 4.5 查询性能约定 + +- 列表查询目标:89,000 条房源 / 200 万条跟进日志下,p95 响应 **< 2 秒** +- **所有列表查询必须使用 Keyset 分页**(`WHERE id > :last_id ORDER BY id`),禁止 OFFSET 分页用于大数据量场景 +- 新增表必须在 migration 中同步创建必要索引,不得事后补建 +- 高写入表(`follow_logs`、`property_photos`、`permission_change_logs`、`login_attempts`)必须按月分区(`PARTITION BY RANGE`) + +### 4.6 安全约定 + +- 手机号等 PII 数据统一通过 `core/encryption.py` 加密存储,**禁止明文入库** +- 所有配置(密钥、Bucket 名、外部服务 URL)通过 `.env` 注入,**禁止硬编码** +- 每个受权限保护的 View 必须覆盖三个测试场景:有权限(200)、无权限(403)、未登录(302) +- Redis Key 必须携带租户 Schema 前缀,格式:`{tenant_schema}:{module}:{key}` + +### 4.7 错误处理约定 + +- 后端 API 返回标准 JSON 错误格式:`{"error": "...", "code": "SNAKE_CASE_CODE"}` +- View 层禁止直接抛出异常,必须捕获并返回对应 HTTP 状态码 +- Celery 任务失败必须记录到 Sentry,并更新任务状态表 + +### 4.8 文件命名约定 + +- Django App:`snake_case`(如 `property`、`follow_log`) +- 前端模板组件:`kebab-case`(如 `property-card.html`、`client-form.html`) +- Migration 文件:不得手动重命名,保留 Django 自动生成的序号 + +--- + +## 5. 禁止项(Do NOT — 违反视为 Bug) + +- ❌ **React / Vue / Angular** 等重前端框架 +- ❌ 在请求线程中处理耗时 **> 500ms** 的任务(必须用 Celery) +- ❌ 传统页面全刷方案(除初始页面加载外) +- ❌ 复杂原生 JavaScript(优先 HTMX/Alpine 指令) +- ❌ Electron 渲染进程开启 `nodeIntegration: true` +- ❌ 客户端内嵌业务逻辑或本地数据库(壳应用原则,渲染层只加载 Web URL) +- ❌ 跨租户 SQL 查询(必须经 `django-tenants` 中间件切换 Schema) +- ❌ 代码中硬编码密钥、Tenant ID、URL、枚举中文字符串 +- ❌ 使用 OFFSET 分页处理 1000 条以上数据集 +- ❌ 手机号/身份证号明文存储 +- ❌ 使用 Django 原生 `Client()` 做集成测试(必须用 `TenantClient`) +- ❌ 在 MVP 阶段实现 `PRD_MVP.md §3` 中标注的 Out-of-Scope 功能(移动端、合同、财务、新房、三网发布等) + +--- + +## 6. 测试要求 + +**核心原则**:每个 P0 User Story 完成后,对应测试必须同步产出,**不允许欠测试债**。 + +### 测试分层 + +| 层级 | 工具 | 覆盖目标 | 运行频率 | +|------|------|---------|---------| +| **单元测试** | `pytest-django` + `factory_boy` | `core/`、`services/`、`tasks.py` | 每次 push | +| **集成测试** | `pytest-django` + `TenantClient` | 所有 P0 User Story 的 HTTP 接口 | 每次 push | +| **E2E 测试** | `playwright` (Python) | 5 条核心用户旅程 | 每日定时 | + +### 测试关键约定 + +- 集成测试**必须**使用 `TenantClient`,禁止使用 Django 原生 `Client()` +- HTMX 局部请求测试须携带 `HTTP_HX_REQUEST: true` header,验证返回局部 HTML 而非完整页面 +- Celery 任务测试使用 `CELERY_TASK_ALWAYS_EAGER = True` 同步执行 +- 外部服务(R2、Redis、邮件)在测试中全部 Mock,禁止真实调用 +- 权限测试必须覆盖:有权限(200)、无权限(403)、未登录(302)三场景 + +### 覆盖率基准 + +| 模块 | 最低目标 | +|------|---------| +| `core/` 核心基础模块 | ≥ 90% | +| `apps/*/services/` 业务逻辑层 | ≥ 80% | +| `apps/*/views.py` 视图层 | ≥ 70% | +| E2E 核心用户旅程(5 条) | 100% 通过 | + +--- + +## 7. MVP 范围(Phase 1) + +**当前阶段**:MVP Phase 1(P0 功能) + +实现任何功能前,先对照 `PRD/PRD_MVP.md` 确认是否在 P0 范围。**P0 范围以外的功能在 MVP 阶段禁止实现**,包括但不限于: + +- 移动端适配(v2 规划) +- 新房模块、合同、财务、三网发布 +- 公客管理(P2) +- 门店分布地图(P2) + +**当前 Phase 1 P0 Task 列表**:见 `PRD/TASK.md §Phase 1`(US-ACCOUNT-001~003、US-COMPLEX-001~003、US-PROPERTY-001~008、US-CLIENT-001~017、US-ORG-001~003、US-PERMISSION-001~005、US-SETTING-001) + +--- + +## 8. 数据模型参考(实现前必读) + +所有数据模型的**权威来源**如下,开发前必须阅读对应文档,不得凭印象实现: + +| 模块 | 数据模型权威文档 | +|------|---------------| +| 总览 & 架构决策 | `DATA_MODEL/DATA_MODEL.md` | +| 房源管理 | `DATA_MODEL/DATA_MODEL_PROPERTY.md` | +| 客源管理 | `DATA_MODEL/DATA_MODEL_CLIENT.md` | +| 楼盘/小区/区域 | `DATA_MODEL/DATA_MODEL_COMPLEX.md` | +| 组织人事 | `DATA_MODEL/DATA_MODEL_ORG.md` | +| 权限管理 | `DATA_MODEL/DATA_MODEL_PERMISSION.md` | +| 登录认证 | `DATA_MODEL/DATA_MODEL_LOGIN.md` | +| Public Schema(平台运营层) | `DATA_MODEL/DATA_MODEL_PUBLIC.md` | +| 系统配置(lookup/setting) | `DATA_MODEL/DATA_MODEL_SETTING.md` | + +### 核心领域关系速览 + +``` +[区域/商圈] ──────────────────────────────┐ + │ │ +[学校管理] │ + │ ▼ +[楼盘/小区] ── [楼栋] ──────────► [房源] ◄──── [挂牌历史] + │ │ + │ ┌────────┼────────┐ + │ │ │ │ + │ [联系人] [跟进日志] [维护完成度] + │ +[客源] ──── [配对记录] ──── [带看记录] + │ +[员工/组织] ──── [权限] +``` + +--- + +## 9. 技术方案文档导航 + +| 模块 | 技术方案文档 | PRD | +|------|------------|-----| +| 总纲 & 禁止项 | `TECH_STACK/TECH_STACK.md` | `PRD/PRD_MVP.md` | +| 登录认证 | `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` | + +**设计 Review 记录**(了解当前已知技术债与阻塞项): +- `REVIEW/REVIEW_全局_2026-04-26.md`(最新) +- `REVIEW/REVIEW_全局_2026-04-25.md` + +--- + +## 10. 已知待解决问题(编码前必须确认) + +以下问题在开始编码前需先确认当前状态,若未解决应在实现对应模块前暂停并上报: + +| 编号 | 级别 | 问题描述 | 影响模块 | +|------|------|---------|---------| +| **B-01** | 🔴 Blocker | 系统配置 PRD(`PRD/系统配置/系统配置.md`)为空骨架,US-SETTING-001 无法启动 | 系统配置 | +| **B-02** | 🔴 Blocker | 核心枚举三方不一致(PRD ↔ DDL ↔ TASK AC):客源 status/grade、房源 status 互相矛盾,需先冻结 `DATA_MODEL/ENUMS.md` | 房源、客源 | +| **B-03** | 🔴 Blocker | 权限数据范围档位冲突:§3 非目标"三档" vs §5.6"五档",DataScope 实现方式未统一 | 权限管理 | +| **B-04** | 🔴 Blocker | Keyset 分页规范完全缺位,89k 房源列表设计错误 | 房源、客源 | +| **M-02** | 🟠 Major | 主表 `properties`/`clients` 缺乏乐观锁字段 `version` | 房源、客源 | +| **M-03** | 🟠 Major | 高写入表分区 DDL 未落地(`follow_logs` 等) | 跟进日志 | +| **M-04** | 🟠 Major | Celery 多租户 schema 切换规范、R2 文件路径前缀规范、查询索引矩阵未补充 | 全局 | + +> 详细内容见 `REVIEW/REVIEW_全局_2026-04-26.md` + +--- + +## 11. 文档根目录 + +所有项目文档位于:`/mnt/d/Workspace/nexus/Project/fonrey/` + +``` +fonrey/ +├── AGENTS.md # 本文件(AI Agent 开发指南) +├── PRD/ +│ ├── PRD_MVP.md # MVP 范围书(必读) +│ ├── TASK.md # 全量 Task Board(US 编号) +│ ├── 房源管理/ +│ ├── 客源管理/ +│ ├── 楼盘管理/ +│ ├── 组织人事管理/ +│ ├── 权限管理/ +│ ├── 登录管理/ +│ ├── 系统配置/ +│ ├── 系统管理/ +│ └── 发布管理/ +├── DATA_MODEL/ +│ ├── DATA_MODEL.md # 数据模型总览(必读) +│ ├── DATA_MODEL_PROPERTY.md +│ ├── DATA_MODEL_CLIENT.md +│ ├── DATA_MODEL_COMPLEX.md +│ ├── DATA_MODEL_ORG.md +│ ├── DATA_MODEL_PERMISSION.md +│ ├── DATA_MODEL_LOGIN.md +│ └── DATA_MODEL_PUBLIC.md +├── TECH_STACK/ +│ ├── TECH_STACK.md # 技术栈总纲(必读) +│ ├── 登录管理技术方案.md +│ ├── 权限管理系统技术方案.md +│ └── 测试规范.md +└── REVIEW/ + ├── REVIEW_全局_2026-04-26.md # 最新 Review(含阻塞问题) + └── REVIEW_全局_2026-04-25.md +``` diff --git a/Project/fonrey/DATA_MODEL/DATA_MODEL.md b/Project/fonrey/DATA_MODEL/DATA_MODEL.md index 333528d8..9c23a564 100644 --- a/Project/fonrey/DATA_MODEL/DATA_MODEL.md +++ b/Project/fonrey/DATA_MODEL/DATA_MODEL.md @@ -2,8 +2,8 @@ # Fonrey 房产经纪管理系统 — DATA MODEL 设计文档 > **作者**: Backend Architect -> **版本**: v1.3 -> **日期**: 2026-04-24(v1.1 修复 S1/S2/S4;v1.2 扩展 public schema;v1.3 §三 DDL 迁至 DATA_MODEL_PUBLIC.md,本文改为索引) +> **版本**: 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 缓存策略) > **技术栈**: Django 4.x + PostgreSQL + django-tenants + Redis > **设计目标**: 支撑 89,000+ 房源、多租户隔离、sub-100ms 查询、合规审计 @@ -17,23 +17,24 @@ ┌──────────────────────────────────────────────────────────────────────┐ │ PostgreSQL Instance │ │ │ -│ ┌─────────────────────────┐ ┌──────────────┐ ┌──────────────┐ │ -│ │ public schema │ │ tenant_abc │ │ tenant_xyz │ │ -│ │ (平台运营层) │ │ schema │ │ schema │ │ -│ │ │ │ │ │ │ │ -│ │ - tenants │ │ - properties │ │ - properties │ │ -│ │ - domains │ │ - clients │ │ - clients │ │ -│ │ - tenant_status_logs │ │ - complexes │ │ - complexes │ │ -│ │ - platform_admins │ │ - staff │ │ - staff │ │ -│ │ - admin_mfa_devices │ │ - org_units │ │ - org_units │ │ -│ │ - admin_sessions │ │ - ... │ │ - ... │ │ -│ │ - ip_whitelist │ └──────────────┘ └──────────────┘ │ -│ │ - platform_audit_logs │ │ -│ │ - backup_schedules │ │ -│ │ - backup_records │ │ -│ │ - export_tasks │ │ -│ │ - system_versions │ │ -│ │ - upgrade_events │ │ +│ ┌─────────────────────────┐ ┌──────────────────┐ ┌────────────┐ │ +│ │ public schema │ │ tenant_abc │ │ tenant_xyz │ │ +│ │ (平台运营层) │ │ schema │ │ schema │ │ +│ │ │ │ │ │ │ │ +│ │ - tenants │ │ - org_units │ │ (同左) │ │ +│ │ - domains │ │ - staff │ │ │ │ +│ │ - tenant_status_logs │ │ - complexes │ │ │ │ +│ │ - platform_admins │ │ - properties │ │ │ │ +│ │ - admin_mfa_devices │ │ - clients │ │ │ │ +│ │ - admin_sessions │ │ - user_accounts │ │ │ │ +│ │ - ip_whitelist │ │ - login_attempts │ │ │ │ +│ │ - platform_audit_logs │ │ - permission_defs│ │ │ │ +│ │ - backup_schedules │ │ - roles │ │ │ │ +│ │ - backup_records │ │ - staff_roles │ │ │ │ +│ │ - export_tasks │ │ - lookup_items │ │ │ │ +│ │ - system_versions │ │ - ... │ │ │ │ +│ │ - upgrade_events │ └──────────────────┘ └────────────┘ │ +│ │ - enum_labels │ │ │ └─────────────────────────┘ │ └──────────────────────────────────────────────────────────────────────┘ ``` @@ -104,6 +105,7 @@ | **ExportTask** | `public.export_tasks` | 数据导出异步任务(CSV/JSON/SQL Dump,24h 下载链接) | | **SystemVersion** | `public.system_versions` | 平台版本历史,唯一 current 版本约束 | | **UpgradeEvent** | `public.upgrade_events` | 升级/回滚事件,含灰度租户维度进度快照 | +| **EnumLabel** | `public.enum_labels` | 固定枚举字典(英文 Key → 中文标签),所有租户共享,供前端下拉渲染、导出报表中文标签、日志快照使用 | #### Tenant Schema(租户业务层) @@ -121,6 +123,9 @@ | **Client(客源)** | `clients` → [DATA_MODEL_CLIENT.md](./DATA_MODEL_CLIENT.md) | 买家/租客档案,分私客/公客/成交客,含活跃度评分与自动公客转换机制 | | **Viewing(带看)** | `client_viewings` → [DATA_MODEL_CLIENT.md](./DATA_MODEL_CLIENT.md) | 经纪人带客户看房的完整记录 | | **Match(配对)** | `client_property_matches` → [DATA_MODEL_CLIENT.md](./DATA_MODEL_CLIENT.md) | 系统/人工推荐的客源↔房源配对 | +| **UserAccount(用户账号)** | `user_accounts` → [DATA_MODEL_LOGIN.md](./DATA_MODEL_LOGIN.md) | 系统登录主体,与员工档案 1:1 绑定,含账号锁定/密码历史/登录审计 | +| **PermissionDef(权限定义)** | `permission_defs` → [DATA_MODEL_PERMISSION.md](./DATA_MODEL_PERMISSION.md) | 权限目录(约 300 条),驱动 Hybrid RBAC + Override 权限模型 | +| **Role(业务角色)** | `roles` → [DATA_MODEL_PERMISSION.md](./DATA_MODEL_PERMISSION.md) | 权限模板,含 4 大类别(置业顾问/店管/总经/运营/自定义) | ### 领域关系快速导航 @@ -149,6 +154,9 @@ OrgUnit (组织架构) | [DATA_MODEL_COMPLEX.md](./DATA_MODEL_COMPLEX.md) | 楼盘/区域(districts, business_areas, complexes, buildings, room_units, schools 等) | ✅ 完成 | | [DATA_MODEL_CLIENT.md](./DATA_MODEL_CLIENT.md) | 客源管理(clients, requirements, follow_logs, viewings, matches 等) | ✅ 完成 | | [DATA_MODEL_PROPERTY.md](./DATA_MODEL_PROPERTY.md) | 房源管理(properties 及配套 22 张表,含跟进/钥匙/委托/实勘/营销/产证/完成度/标签/收藏/保护/号码方审批等) | ✅ 完成 | +| [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) | ✅ 完成 | --- @@ -175,6 +183,7 @@ OrgUnit (组织架构) | `public.export_tasks` | 数据导出异步任务(CSV/JSON/SQL Dump,24h 下载链接) | §2.4 | | `public.system_versions` | 平台版本历史,部分唯一索引保证唯一 current | §2.5 | | `public.upgrade_events` | 升级/回滚事件,`tenant_progress` JSONB 快照各租户状态 | §2.5 | +| `public.enum_labels` | 固定枚举字典(英文 Key → 中文标签),所有租户共享 | §2.6 | **关键约束提示**: - `tenant_status_logs` / `platform_audit_logs` **无 deleted_at**,禁止 UPDATE/DELETE,append-only @@ -257,31 +266,31 @@ OrgUnit (组织架构) **核心表概览**(开发时以 DATA_MODEL_PROPERTY.md 为准): -| 表名 | 说明 | 关键字段 | -|------|------|----------| -| `properties` | 房源主表(系统核心,89,000+ 数据量) | `status`, `attribute`, `property_type`, `complex_id`, `sale_price`, `area`, `grade`, `completeness_score`, `search_vector` | -| `property_contacts` | 业主/联系人(手机号 AES 加密+哈希索引) | `property_id`, `phone_enc`, `phone_hash`, `identity`, `is_number_holder` | -| `listing_histories` | 挂牌历史快照(不可删除) | `property_id`, `listing_type`, `status`, `sale_price`, `seller_agent_snapshot` | -| `price_changes` | 调价记录(不可删除) | `property_id`, `old_sale_price`, `new_sale_price`, `change_reason`, `changed_by` | -| `follow_logs` | 跟进日志(6种类型,最高写入频率) | `property_id`, `log_type`, `content`, `is_deletable`, `operator_id` | -| `follow_log_attachments` | 跟进附件(图片) | `follow_log_id`, `file_key`, `file_type` | -| `follow_log_recordings` | 跟进录音 | `follow_log_id`, `file_key`, `duration_seconds` | -| `property_keys` | 钥匙管理(机械钥匙/密码) | `property_id`, `key_type`, `holder_id`, `is_active` | -| `key_attachments` | 钥匙附件 | `key_id`, `file_key` | -| `commissions` | 委托管理(独家/非独家) | `property_id`, `commission_type`, `period_start`, `status` | -| `commission_attachments` | 委托附件(身份证/产证/委托书) | `commission_id`, `category`, `file_key` | -| `field_surveys` | 实勘管理(GPS 打卡) | `property_id`, `status`, `gps_latitude`, `gps_longitude`, `created_by` | -| `survey_photos` | 实勘照片(按空间分类) | `survey_id`, `category`, `file_key`, `is_vr_screenshot` | -| `property_photos` | 房源图片(经纪人管理,封面唯一约束) | `property_id`, `category`, `is_cover`, `file_key` | -| `property_attachments` | 房源附件 | `property_id`, `category`, `file_key` | -| `property_marketing` | 营销信息(1:1,卖点/业主心态/介绍) | `property_id`, `marketing_title`, `core_selling_points` | -| `property_certificates` | 产证信息(1:1) | `property_id`, `cert_no`, `owner_name`, `land_nature` | -| `property_completeness` | 维护完成度快照(1:1,Celery 异步计算) | `property_id`, `total_score`, `score_survey`, `score_commission`, ... | -| `property_tags` | 标签字典(系统预置+运营自定义) | `name`, `color`, `is_system` | -| `property_tag_relations` | 房源↔标签多对多 | `property_id`, `tag_id` | -| `property_favorites` | 经纪人收藏房源 | `staff_id`, `property_id` | -| `property_protections` | 保护房设置(1:1) | `property_id`, `is_protected`, `start_at`, `end_at` | -| `number_holder_approvals` | 号码方变更审批 | `property_id`, `applicant_id`, `status` | +| 表名 | 说明 | 关键字段 | +| ------------------------- | ------------------------ | -------------------------------------------------------------------------------------------------------------------------- | +| `properties` | 房源主表(系统核心,89,000+ 数据量) | `status`, `attribute`, `property_type`, `complex_id`, `sale_price`, `area`, `grade`, `completeness_score`, `search_vector` | +| `property_contacts` | 业主/联系人(手机号 AES 加密+哈希索引) | `property_id`, `phone_enc`, `phone_hash`, `identity`, `is_number_holder` | +| `listing_histories` | 挂牌历史快照(不可删除) | `property_id`, `listing_type`, `status`, `sale_price`, `seller_agent_snapshot` | +| `price_changes` | 调价记录(不可删除) | `property_id`, `old_sale_price`, `new_sale_price`, `change_reason`, `changed_by` | +| `follow_logs` | 跟进日志(6种类型,最高写入频率) | `property_id`, `log_type`, `content`, `is_deletable`, `operator_id` | +| `follow_log_attachments` | 跟进附件(图片) | `follow_log_id`, `file_key`, `file_type` | +| `follow_log_recordings` | 跟进录音 | `follow_log_id`, `file_key`, `duration_seconds` | +| `property_keys` | 钥匙管理(机械钥匙/密码) | `property_id`, `key_type`, `holder_id`, `is_active` | +| `key_attachments` | 钥匙附件 | `key_id`, `file_key` | +| `commissions` | 委托管理(独家/非独家) | `property_id`, `commission_type`, `period_start`, `status` | +| `commission_attachments` | 委托附件(身份证/产证/委托书) | `commission_id`, `category`, `file_key` | +| `field_surveys` | 实勘管理(GPS 打卡) | `property_id`, `status`, `gps_latitude`, `gps_longitude`, `created_by` | +| `survey_photos` | 实勘照片(按空间分类) | `survey_id`, `category`, `file_key`, `is_vr_screenshot` | +| `property_photos` | 房源图片(经纪人管理,封面唯一约束) | `property_id`, `category`, `is_cover`, `file_key` | +| `property_attachments` | 房源附件 | `property_id`, `category`, `file_key` | +| `property_marketing` | 营销信息(1:1,卖点/业主心态/介绍) | `property_id`, `marketing_title`, `core_selling_points` | +| `property_certificates` | 产证信息(1:1) | `property_id`, `cert_no`, `owner_name`, `land_nature` | +| `property_completeness` | 维护完成度快照(1:1,Celery 异步计算) | `property_id`, `total_score`, `score_survey`, `score_commission`, ... | +| `property_tags` | 标签字典(系统预置+运营自定义) | `name`, `color`, `is_system` | +| `property_tag_relations` | 房源↔标签多对多 | `property_id`, `tag_id` | +| `property_favorites` | 经纪人收藏房源 | `staff_id`, `property_id` | +| `property_protections` | 保护房设置(1:1) | `property_id`, `is_protected`, `start_at`, `end_at` | +| `number_holder_approvals` | 号码方变更审批 | `property_id`, `applicant_id`, `status` | **关键约束提示**: - `property_contacts.phone_hash` 是重复房源检测的主要依据,录入前必须查重 @@ -293,6 +302,83 @@ OrgUnit (组织架构) --- +### 3.4 登录与账号认证(Login & Account) + +> **详细模型** → 见 [`DATA_MODEL_LOGIN.md`](./DATA_MODEL_LOGIN.md) +> 该文件为权威定义,包含完整字段、状态机、Redis 缓存结构和禁止操作。 + +**核心表概览**(开发时以 DATA_MODEL_LOGIN.md 为准): + +| 表名 | 说明 | +|------|------| +| `user_accounts` | 账号主表(1:1 绑定 `org.Staff`),含加密手机号/哈希、状态机(active/locked/disabled)、初始密码标识 | +| `login_attempts` | 登录审计日志(append-only,成功/失败均记录,无 FK 冗余存 username 保证历史完整) | +| `password_reset_tokens` | 密码重置 Token(有效期 30 分钟,使用后立即标记 `is_used`) | +| `password_histories` | 历史密码记录(保留最近 3 条,含初始密码,防止重复使用) | + +**关键约束提示**: +- `user_accounts` 主键用 `BIGSERIAL`(非 UUID),登录审计场景 BigInt 更高效 +- `user_accounts.phone_enc` AES-256-GCM 加密,`phone_hash` SHA-256 用于唯一索引 +- **禁止物理删除** `user_accounts`,离职员工只能 `status=disabled` +- 账号锁定(5 次密码错误)→ `status=locked`,`locked_until=NOW()+30min`;Redis 仅计数,实际锁定以 DB 为准 +- Tenant Admin 的 `staff_id` 可为空(可无员工档案);普通员工 `staff_id` 必填且关联 active Staff +- 员工离职(`org.Staff.status→resigned`)→ 应用层 Service 调用触发账号 `status→disabled`,**禁止循环 FK** +- `password_reset_tokens` / `login_attempts` **无 deleted_at**,不可修改/删除 + +**Redis 辅助状态**(非持久化): + +| Key 格式 | TTL | 说明 | +|----------|-----|------| +| `captcha_token:{uuid}` | 3 分钟 | 滑块验证会话 Token | +| `captcha_pass:{uuid}` | 3 分钟 | 一次性通过凭证(验证后立即删除) | +| `login_fail:{tenant_id}:{username}` | 30 分钟 | 连续密码错误计数;≥5 触发锁定 | +| `recover_email:{email}` | 1 小时 | 找回邮件发送次数上限 3 次 | +| `tenant_verify_ip:{ip}` | 1 分钟 | Tenant 验证接口 IP 限流;≥10 次拒绝 | + +--- + +### 3.5 权限管理(Permission & RBAC) + +> **详细模型** → 见 [`DATA_MODEL_PERMISSION.md`](./DATA_MODEL_PERMISSION.md) +> 该文件为权威定义,包含完整字段、权限解析算法、`ScopeQueryBuilder` 实现和禁止操作。 + +**权限模型概述**:Hybrid RBAC + Individual Override,支持 `BOOLEAN / SCOPE / INTEGER` 三类权限值,多角色合并规则 OR / MAX。 + +**核心表概览**(开发时以 DATA_MODEL_PERMISSION.md 为准): + +| 表名 | 说明 | +|------|------| +| `permission_defs` | 权限目录(约 300 条,`PUBLIC Schema` 中 `shared_apps` 存储,所有租户共享),含模块/分组/值类型/默认值/上限类别 | +| `roles` | 业务角色(每租户独立),5 种类别:`agent/store_manager/director/operator/custom`,含系统内置标识 | +| `role_permissions` | 角色↔权限值(稀疏存储,仅存与 default_value 不同的项) | +| `staff_roles` | 员工↔角色分配(N:M,含主角色标识 `is_primary`、有效期) | +| `staff_permission_overrides` | 员工个人权限覆盖(稀疏存储,仅存与角色合并值不同的项),3 种 override_mode:REPLACE / RESTRICT / GRANT | +| `staff_data_scopes` | 员工数据范围扩展(补充 SCOPE 权限之外的额外可读范围,如特殊跨门店授权) | +| `permission_change_logs` | 权限变更不可变审计日志(append-only,禁止 UPDATE/DELETE) | + +**关键约束提示**: +- `permission_defs` 位于 **Public Schema**(`shared_apps`),所有租户共享;`roles` 及其余表属租户 Schema +- **禁止硬删除** `permission_defs`,改用 `is_active=FALSE` 下线;`code` 字段不可修改 +- **禁止直接构造 Q 对象绕过 `ScopeQueryBuilder`**,会导致越权漏洞 +- `permission_change_logs` **无 deleted_at**,禁止 UPDATE/DELETE +- 员工权限解析:`is_system_admin=TRUE` → 短路返回全权限;否则多角色 OR/MAX 合并后叠加 Override +- `StaffPermissionOverride` 保存前必须做差异对比,**禁止存与角色合并值相同的冗余记录**(稀疏存储) +- `staff_roles.is_primary` 唯一约束通过 Signal 维护,**禁止绕过** + +**权限解析缓存**: + +| Cache Key | TTL | 失效触发 | +|-----------|-----|---------| +| `perm:v{VER}:{schema}:{staff_id}` | 3600s | Override / StaffRole 变更 | +| `perm:v{VER}:{schema}:role:{role_id}:staff_ids` | 3600s | 角色权限变更 → Pipeline 批量失效 | +| `perm:inconsistent:{schema}:{staff_id}` | 300s | 同上 | +| `perm:defs:{schema}` | 86400s | PermissionDef 变更(低频) | +| `perm:role_applied_count:{schema}:{role_id}` | 600s | StaffRole 变更 | + +> **版本号机制**:`CACHE_VERSION` 在 Django settings 中,升级 PermissionDef 结构时 bump,一键全局失效。 + +--- + ### 3.17 客源管理(Client Management) > **详细模型** → 见 [`DATA_MODEL_CLIENT.md`](./DATA_MODEL_CLIENT.md) @@ -381,6 +467,73 @@ CREATE INDEX idx_saved_filters_staff ON saved_filters(staff_id, module); --- +### 3.19 枚举字典(Enum Labels) + +> **权威定义** → 见 [`DATA_MODEL/ENUMS.md`](./ENUMS.md) +> 本节为概览,开发时以 ENUMS.md 为准。 + +#### 表归属 + +`enum_labels` 位于 **Public Schema**(`shared_apps`),所有租户共享,**不属于任何租户 Schema**。 + +#### 核心表设计 + +```sql +CREATE TABLE enum_labels ( + id UUID PRIMARY KEY DEFAULT gen_random_uuid(), + domain VARCHAR(60) NOT NULL, -- 枚举域,格式:{模块}.{字段},如 client.status + value VARCHAR(60) NOT NULL, -- 英文 Key(与数据库 CHECK 约束一致) + label_zh VARCHAR(60) NOT NULL, -- 中文标签(前端展示用) + sort_order SMALLINT NOT NULL DEFAULT 0, + is_active BOOLEAN NOT NULL DEFAULT TRUE, + remark TEXT, + created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), + updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW() +); + +CREATE UNIQUE INDEX idx_enum_labels_domain_value ON enum_labels(domain, value); +CREATE INDEX idx_enum_labels_domain ON enum_labels(domain, sort_order); +``` + +#### 覆盖的枚举域(domain 清单) + +| domain | 说明 | 对应表字段 | +|--------|------|-----------| +| `client.status` | 客源状态(7 态) | `clients.status` | +| `client.grade` | 客源等级(5 档 + E) | `clients.grade` | +| `client.purpose_type` | 需求类型 | `client_requirements.purpose_type` | +| `client.usage` | 房源用途偏好 | `client_requirements.usage` | +| `client.orientation` | 朝向偏好 | `client_requirements.orientation` | +| `client.payment_method` | 付款方式 | `clients.payment_method` | +| `property.status` | 房源状态 | `properties.status` | +| `property.attribute` | 房源属性(公/私/保护) | `properties.attribute` | +| `property.usage` | 房源用途 | `properties.usage` | +| `property.grade` | 房源等级(5 档) | `properties.grade` | +| `property.listing_type` | 挂牌类型 | `properties.listing_type` | +| `property.decoration` | 装修程度 | `properties.decoration` | +| `property.orientation` | 朝向 | `properties.orientation` | +| `commission.type` | 委托类型 | `commissions.commission_type` | +| `field_survey.status` | 实勘状态 | `field_surveys.status` | +| `follow_log.log_type` | 跟进日志类型 | `follow_logs.log_type` | + +#### 重要约定 + +- `enum_labels.value` 必须与对应表的 `CHECK` 约束完全一致,**两者必须同步修改** +- 新增枚举值流程:① 修改 DDL `CHECK` 约束 → ② 插入 `enum_labels` 种子数据 → ③ 更新 `ENUMS.md` +- `is_active = FALSE` 仅停用前端展示,**不得修改或删除已有 `value`**(历史数据引用不可破坏) +- 前端下拉渲染**统一从 `enum_labels` 读取**,禁止在前端代码中硬编码中文标签 + +#### 与 `lookup_items` 的区别 + +| 对比维度 | `enum_labels` | `lookup_items` | +|---------|---------------|----------------| +| 用途 | 固定枚举的中文标签映射 | 运营可配置的动态选项(如跟进目的、来源渠道) | +| 修改权限 | 仅开发/DBA | 运营人员后台配置 | +| Schema 位置 | Public Schema(共享) | Tenant Schema(每租户独立) | +| 典型示例 | 客源状态、房源等级 | 跟进目的、客户来源渠道 | + +--- + ## 五、关键索引汇总与查询优化策略 ### 4.1 房源列表页核心查询分析 @@ -489,6 +642,21 @@ CREATE TRIGGER trg_update_last_followed # 枚举值/lookup(几乎不变) {schema}:lookup:{category_code} TTL: 86400 (24小时) +# 登录模块(详见 DATA_MODEL_LOGIN.md §四) +captcha_token:{uuid} TTL: 180 (3分钟) +captcha_pass:{uuid} TTL: 180 (3分钟) +login_fail:{tenant_id}:{username} TTL: 1800 (30分钟,连续失败计数) +recover_email:{email} TTL: 3600 (1小时,发送次数限流) +recover_reset:{account_id} TTL: 3600 (1小时,Token 生成次数限流) +tenant_verify_ip:{ip} TTL: 60 (1分钟,IP 限流) + +# 权限模块(详见 DATA_MODEL_PERMISSION.md §六) +perm:v{VER}:{schema}:{staff_id} TTL: 3600 (员工完整权限快照) +perm:v{VER}:{schema}:role:{role_id}:staff_ids TTL: 3600 (角色→员工 ID 列表,批量失效用) +perm:inconsistent:{schema}:{staff_id} TTL: 300 (权限不一致标记) +perm:defs:{schema} TTL: 86400 (权限定义全量缓存) +perm:role_applied_count:{schema}:{role_id} TTL: 600 (角色应用人数) + # 标签列表 {schema}:tags:property TTL: 3600 diff --git a/Project/fonrey/DATA_MODEL/DATA_MODEL_CLIENT.md b/Project/fonrey/DATA_MODEL/DATA_MODEL_CLIENT.md index 9d3797e3..2e98a40e 100644 --- a/Project/fonrey/DATA_MODEL/DATA_MODEL_CLIENT.md +++ b/Project/fonrey/DATA_MODEL/DATA_MODEL_CLIENT.md @@ -357,12 +357,12 @@ CREATE UNIQUE INDEX idx_favorite_folders_default ON client_favorite_folders(staf ### 3.10 client_folder_items — 收藏夹中的客源 -| 字段 | 类型 | 约束 | 业务说明 | -|------|------|------|----------| -| folder_id | UUID | NOT NULL, FK→client_favorite_folders, CASCADE | | -| client_id | UUID | NOT NULL, FK→clients, CASCADE | | -| added_at | TIMESTAMPTZ | NOT NULL DEFAULT NOW() | | -| PRIMARY KEY | (folder_id, client_id) | | | +| 字段 | 类型 | 约束 | 业务说明 | +| ----------- | ---------------------- | --------------------------------------------- | ---- | +| folder_id | UUID | NOT NULL, FK→client_favorite_folders, CASCADE | | +| client_id | UUID | NOT NULL, FK→clients, CASCADE | | +| added_at | TIMESTAMPTZ | NOT NULL DEFAULT NOW() | | +| PRIMARY KEY | (folder_id, client_id) | | | ```sql CREATE INDEX idx_folder_items_client ON client_folder_items(client_id); @@ -415,8 +415,7 @@ buying/renting/buy_or_rent ### clients.grade(等级) ``` -A_urgent = A(急迫) -A = A +A = A(急迫) B = B(较强) C = C(一般,默认值) D = D(较弱) @@ -438,15 +437,15 @@ merge = 合并客源(被合并的记录保留日志) ### clients.activity_level(活跃度分层,系统计算) -| 值 | 含义 | 触发条件(示例,以运营配置为准) | -|----|------|------| -| `new_matched` | 新配偶 | 录入后 3 天内 | -| `active_7d` | 7日活跃 | 最后跟进在 7 天内 | -| `active_30d` | 30日活跃 | 最后跟进在 30 天内 | -| `active_90d` | 90日活跃 | 最后跟进在 90 天内 | -| `expiring` | 即将过期 | 距自动转公还有 N 天 | -| `frozen` | 冻结(暂缓) | status = suspended | -| `invalid` | 无效 | status = invalid | +| 值 | 含义 | 触发条件(示例,以运营配置为准) | +| ------------- | ------ | ------------------ | +| `new_matched` | 新匹配 | 录入后 3 天内 | +| `active_7d` | 7日活跃 | 最后跟进在 7 天内 | +| `active_30d` | 30日活跃 | 最后跟进在 30 天内 | +| `active_90d` | 90日活跃 | 最后跟进在 90 天内 | +| `expiring` | 即将过期 | 距自动转公还有 N 天 | +| `frozen` | 冻结(暂缓) | status = suspended | +| `invalid` | 无效 | status = invalid | --- diff --git a/Project/fonrey/DATA_MODEL/DATA_MODEL_LOGIN.md b/Project/fonrey/DATA_MODEL/DATA_MODEL_LOGIN.md index b23ff206..27026aba 100644 --- a/Project/fonrey/DATA_MODEL/DATA_MODEL_LOGIN.md +++ b/Project/fonrey/DATA_MODEL/DATA_MODEL_LOGIN.md @@ -1,470 +1,470 @@ -# Fonrey — 登录与账号认证数据模型(DATA_MODEL_LOGIN) - -> **所属系统**: Fonrey 房产经纪管理系统 -> **版本**: v1.0 -> **日期**: 2026-04-24 -> **关联模块**: `apps/accounts/` — 账号认证、登录安全、密码管理 -> **关联 PRD**: `Project/fonrey/PRD/登录管理/用户登录管理模块PRD.md` (v1.3) -> **关联技术方案**: `Project/fonrey/TECH_STACK/登录管理技术方案.md` - ---- - -## 一、领域概览(Domain Overview) - -### 核心概念 - -- **UserAccount(用户账号)**:系统登录主体,必须与员工档案(`org.Staff`)1:1 绑定。分为 Tenant Admin(超级管理账号,每租户唯一)和普通员工账号(username 固定为手机号)。 -- **LoginAttempt(登录尝试记录)**:记录每次登录行为(成功/失败),用于安全审计和账号锁定判断,保留 ≥ 90 天。 -- **PasswordResetToken(密码重置令牌)**:通过邮件找回密码时生成的一次性令牌,有效期 30 分钟,使用后立即失效。 -- **PasswordHistory(历史密码记录)**:保存最近 3 次密码哈希,用于防止重复使用历史密码。 - -### 关键业务规则 - -1. **账号与员工强绑定**:每个登录账号 **必须** 与 `org.Staff` 中的员工档案 1:1 绑定(Tenant Admin 例外,可不绑定)。 -2. **用户名规则差异化**: - - Tenant Admin:由平台运营自定义(字母开头,6~30 位,含字母/数字/下划线) - - 普通员工:**固定为员工手机号**(11 位数字),创建后不可变更 -3. **初始密码强制修改**:新账号及密码重置后,`is_initial_password = True`,首次登录必须修改密码,不可跳过。 -4. **账号锁定机制**:同一账号连续密码错误 ≥ 5 次,状态置为 `locked`,30 分钟后自动恢复;Tenant Admin 可提前手动解锁。 -5. **员工离职联动**:员工离职时,对应账号的 `status` 自动置为 `disabled`,不可登录,历史操作记录保留。 -6. **不支持自助注册**:所有账号由有权限的管理角色创建,普通员工账号在新增员工时由系统自动生成。 - ---- - -## 二、实体关系 - -``` -UserAccount - │ - ├── 1:1 ── org.Staff (实名绑定,普通员工必须) - ├── 1:N ── LoginAttempt (登录审计记录) - ├── 1:N ── PasswordResetToken (密码重置令牌) - ├── 1:N ── PasswordHistory (历史密码记录) - └── M:1 ── UserAccount.created_by (创建人自引用) -``` - -### Schema 归属 - -| 表 | Schema 位置 | 说明 | -|----|------------|------| -| `user_accounts` | 租户 Schema | 账号数据按租户隔离,username 唯一性在 Schema 维度生效 | -| `login_attempts` | 租户 Schema | 审计记录属于租户,跨租户不可见 | -| `password_reset_tokens` | 租户 Schema | 令牌与租户账号绑定 | -| `password_histories` | 租户 Schema | 历史密码与账号绑定 | - -> **注意**:Tenant ID 验证相关逻辑在 **Public Schema**(`shared_apps`),使用 `django-tenants` 的 `TenantModel`,不在本文档范围内,详见 `DATA_MODEL.md` §四(公共 Schema)。 - ---- - -## 三、Schema 定义 - -### 3.1 `user_accounts` — 账号主表(租户 Schema) - -**表说明**:系统登录主体,每个租户内独立隔离,`username` 唯一性约束在 Schema 维度生效。 - -#### 字段定义 - -| 字段名 | 类型 | 约束 | 默认值 | 说明 | -|--------|------|------|--------|------| -| `id` | `BIGSERIAL` | `PRIMARY KEY` | — | 自增主键(审计场景下 BigInt 更直观;跨环境引用使用 UUID 扩展字段见下) | -| `username` | `VARCHAR(30)` | `NOT NULL` | — | 登录名;普通员工为手机号(11 位数字);Tenant Admin 为自定义字符串;创建后不可更改 | -| `password` | `VARCHAR(128)` | `NOT NULL` | — | PBKDF2+SHA256 哈希存储,使用 Django `make_password` | -| `email` | `VARCHAR(254)` | `NULL` | `NULL` | 绑定邮箱;用于找回密码/用户名;为空则无法自助找回;同租户唯一 | -| `phone_enc` | `TEXT` | `NULL` | `NULL` | 手机号 AES-256-GCM 加密密文(`core.encryption`);普通员工必填 | -| `phone_hash` | `VARCHAR(64)` | `NULL` | `NULL` | 手机号 SHA-256 哈希;用于唯一性校验和查询;不可反推原文 | -| `staff_id` | `BIGINT` | `FK → org_staff.id`, `NULL`, `UNIQUE` | `NULL` | 员工档案绑定(1:1);普通员工必须有值;Tenant Admin 可为空 | -| `is_tenant_admin` | `BOOLEAN` | `NOT NULL` | `FALSE` | 是否为该租户的超级管理账号;每个租户最多 1 个(应用层约束) | -| `status` | `VARCHAR(10)` | `NOT NULL`, `CHECK(status IN ('active','disabled','locked'))` | `'active'` | 账号状态;`locked` 为密码错误锁定,30 分钟自动恢复 | -| `is_initial_password` | `BOOLEAN` | `NOT NULL` | `TRUE` | 初始密码标记;True 时登录成功后强制跳转修改密码页,不可跳过 | -| `last_login` | `TIMESTAMPTZ` | `NULL` | `NULL` | 最后登录时间 | -| `locked_until` | `TIMESTAMPTZ` | `NULL` | `NULL` | 锁定到期时间;到期后应用层将 status 恢复 active | -| `created_at` | `TIMESTAMPTZ` | `NOT NULL` | `NOW()` | 账号创建时间 | -| `updated_at` | `TIMESTAMPTZ` | `NOT NULL` | `NOW()` | 最后更新时间(触发器维护) | -| `created_by` | `BIGINT` | `FK → user_accounts.id`, `NULL` | `NULL` | 创建人;普通员工由 Tenant Admin 创建;Tenant Admin 由平台运营创建(可为 NULL) | - -#### 唯一性约束 - -```sql -UNIQUE (username) -- Schema 内唯一,跨租户不冲突(django-tenants 机制保障) -UNIQUE (email) -- 同租户内邮箱唯一(可为 NULL,NULL 不参与唯一性校验) -UNIQUE (phone_hash) -- 同租户内手机号唯一(通过 hash 实现,不暴露原文) -UNIQUE (staff_id) -- 员工档案 1:1 绑定 -``` - -#### 索引 - -```sql -CREATE UNIQUE INDEX uq_user_accounts_username ON user_accounts (username); -CREATE UNIQUE INDEX uq_user_accounts_email ON user_accounts (email) WHERE email IS NOT NULL; -CREATE UNIQUE INDEX uq_user_accounts_phone ON user_accounts (phone_hash) WHERE phone_hash IS NOT NULL; -CREATE INDEX idx_user_accounts_status ON user_accounts (status); -CREATE INDEX idx_user_accounts_staff ON user_accounts (staff_id); -``` - -#### Django Model 定义 - -```python -# apps/accounts/models.py -from django.contrib.auth.models import AbstractBaseUser, BaseUserManager -from django.db import models - - -class UserAccountManager(BaseUserManager): - def create_user(self, username, password, **extra_fields): - if not username: - raise ValueError("username 不能为空") - user = self.model(username=username, **extra_fields) - user.set_password(password) - user.save(using=self._db) - return user - - -class UserAccount(AbstractBaseUser): - """ - 租户级用户账号。 - - 普通员工:username 固定为手机号(11 位数字) - - Tenant Admin:username 由平台运营自定义(字母开头,6~30 位) - 注意:此表位于租户 Schema,username 唯一性约束在 Schema 维度生效。 - """ - username = models.CharField(max_length=30) - email = models.EmailField(null=True, blank=True) - phone_enc = models.TextField(null=True, blank=True) # AES-256-GCM 加密密文 - phone_hash = models.CharField(max_length=64, null=True, blank=True) # SHA-256 哈希索引 - staff = models.OneToOneField( - 'org.Staff', - null=True, blank=True, - on_delete=models.SET_NULL, - related_name='account', - ) - is_tenant_admin = models.BooleanField(default=False) - status = models.CharField( - max_length=10, - choices=[('active', 'Active'), ('disabled', 'Disabled'), ('locked', 'Locked')], - default='active', - ) - is_initial_password = models.BooleanField(default=True) - last_login = models.DateTimeField(null=True, blank=True) - locked_until = models.DateTimeField(null=True, blank=True) - created_at = models.DateTimeField(auto_now_add=True) - updated_at = models.DateTimeField(auto_now=True) - created_by = models.ForeignKey( - 'self', - null=True, blank=True, - on_delete=models.SET_NULL, - related_name='created_accounts', - ) - - USERNAME_FIELD = 'username' - REQUIRED_FIELDS = [] - - objects = UserAccountManager() - - class Meta: - db_table = 'user_accounts' - # Schema 内唯一约束 - constraints = [ - models.UniqueConstraint(fields=['username'], name='uq_user_accounts_username'), - ] - - def __str__(self): - return f"{self.username} ({'admin' if self.is_tenant_admin else 'staff'})" - - def is_locked(self) -> bool: - """检查账号是否处于锁定状态(含自动过期判断)""" - from django.utils import timezone - if self.status == 'locked': - if self.locked_until and timezone.now() >= self.locked_until: - # 锁定已到期,应用层自动恢复(实际由 service 层处理) - return False - return True - return False -``` - ---- - -### 3.2 `login_attempts` — 登录尝试审计表(租户 Schema) - -**表说明**:记录每次登录请求(成功/失败),用于安全审计和锁定判断。数据保留 ≥ 90 天,不得提前清理。 - -#### 字段定义 - -| 字段名 | 类型 | 约束 | 默认值 | 说明 | -|--------|------|------|--------|------| -| `id` | `BIGSERIAL` | `PRIMARY KEY` | — | 自增主键 | -| `username` | `VARCHAR(30)` | `NOT NULL` | — | 尝试登录的用户名(冗余存储,即使账号不存在也记录) | -| `ip_address` | `INET` | `NOT NULL` | — | 来源 IP 地址(支持 IPv4/IPv6) | -| `user_agent` | `TEXT` | `NULL` | `NULL` | 客户端 User-Agent(Electron 版本信息) | -| `success` | `BOOLEAN` | `NOT NULL` | — | 是否登录成功 | -| `failure_reason` | `VARCHAR(30)` | `NULL` | `NULL` | 失败原因;可选值见下方枚举 | -| `attempted_at` | `TIMESTAMPTZ` | `NOT NULL` | `NOW()` | 尝试时间 | - -**`failure_reason` 枚举值**: - -| 值 | 含义 | -|----|------| -| `wrong_password` | 用户名或密码错误 | -| `wrong_captcha` | 行为验证码失败 | -| `account_locked` | 账号已锁定 | -| `account_disabled` | 账号已停用 | -| `tenant_not_found` | 租户不存在(理论上不应出现,防御性记录) | - -#### 索引 - -```sql -CREATE INDEX idx_login_attempts_username ON login_attempts (username); -CREATE INDEX idx_login_attempts_ip ON login_attempts (ip_address); -CREATE INDEX idx_login_attempts_time ON login_attempts (attempted_at DESC); --- 复合索引:按账号查询最近失败记录(锁定判断场景) -CREATE INDEX idx_login_attempts_fail_check ON login_attempts (username, success, attempted_at DESC); -``` - -#### Django Model 定义 - -```python -class LoginAttempt(models.Model): - """ - 登录尝试审计记录。 - - 合规保留周期:≥ 90 天 - - 注意:failure_reason 不得存储密码明文(含错误密码) - """ - FAILURE_REASONS = [ - ('wrong_password', '用户名或密码错误'), - ('wrong_captcha', '行为验证码失败'), - ('account_locked', '账号已锁定'), - ('account_disabled', '账号已停用'), - ('tenant_not_found', '租户不存在'), - ] - - username = models.CharField(max_length=30) - ip_address = models.GenericIPAddressField() - user_agent = models.TextField(null=True, blank=True) - success = models.BooleanField() - failure_reason = models.CharField(max_length=30, null=True, blank=True, choices=FAILURE_REASONS) - attempted_at = models.DateTimeField(auto_now_add=True) - - class Meta: - db_table = 'login_attempts' - indexes = [ - models.Index(fields=['username']), - models.Index(fields=['ip_address']), - models.Index(fields=['-attempted_at']), - models.Index(fields=['username', 'success', '-attempted_at'], - name='idx_login_attempts_fail_check'), - ] - - def __str__(self): - return f"{self.username} @ {self.attempted_at} - {'OK' if self.success else self.failure_reason}" -``` - ---- - -### 3.3 `password_reset_tokens` — 密码重置令牌表(租户 Schema) - -**表说明**:用于通过邮件找回密码的一次性令牌。单次有效,30 分钟过期。 - -#### 字段定义 - -| 字段名 | 类型 | 约束 | 默认值 | 说明 | -|--------|------|------|--------|------| -| `id` | `BIGSERIAL` | `PRIMARY KEY` | — | 自增主键 | -| `user_id` | `BIGINT` | `FK → user_accounts.id`, `NOT NULL` | — | 关联账号 | -| `token` | `VARCHAR(86)` | `NOT NULL`, `UNIQUE` | — | `secrets.token_urlsafe(64)` 生成(86 字符),全局唯一 | -| `expires_at` | `TIMESTAMPTZ` | `NOT NULL` | — | 过期时间(`created_at + 30 分钟`) | -| `is_used` | `BOOLEAN` | `NOT NULL` | `FALSE` | 是否已使用;使用后立即置 True,防止重放攻击 | -| `created_at` | `TIMESTAMPTZ` | `NOT NULL` | `NOW()` | 创建时间 | - -#### 索引 - -```sql -CREATE UNIQUE INDEX uq_password_reset_tokens_token ON password_reset_tokens (token); -CREATE INDEX idx_password_reset_tokens_user ON password_reset_tokens (user_id); -CREATE INDEX idx_password_reset_tokens_expiry ON password_reset_tokens (expires_at) WHERE is_used = FALSE; -``` - -#### Django Model 定义 - -```python -class PasswordResetToken(models.Model): - """ - 密码重置令牌。 - 安全约束: - - Token 单次有效(is_used=True 后立即失效) - - 有效期 30 分钟 - - 同一账号 1 小时内最多生成 3 个(服务层限频,Redis 计数) - """ - user = models.ForeignKey(UserAccount, on_delete=models.CASCADE, related_name='reset_tokens') - token = models.CharField(max_length=86, unique=True) # secrets.token_urlsafe(64) - expires_at = models.DateTimeField() - is_used = models.BooleanField(default=False) - created_at = models.DateTimeField(auto_now_add=True) - - class Meta: - db_table = 'password_reset_tokens' - indexes = [ - models.Index(fields=['user_id']), - ] - - def is_valid(self) -> bool: - from django.utils import timezone - return not self.is_used and timezone.now() < self.expires_at -``` - ---- - -### 3.4 `password_histories` — 历史密码记录表(租户 Schema) - -**表说明**:保存账号最近 3 次密码哈希,用于防止重复使用历史密码(含初始密码)。 - -#### 字段定义 - -| 字段名 | 类型 | 约束 | 默认值 | 说明 | -|--------|------|------|--------|------| -| `id` | `BIGSERIAL` | `PRIMARY KEY` | — | 自增主键 | -| `user_id` | `BIGINT` | `FK → user_accounts.id`, `NOT NULL` | — | 关联账号 | -| `password_hash` | `VARCHAR(128)` | `NOT NULL` | — | PBKDF2+SHA256 哈希值 | -| `created_at` | `TIMESTAMPTZ` | `NOT NULL` | `NOW()` | 记录时间(密码修改时间) | - -#### 索引 - -```sql -CREATE INDEX idx_password_histories_user ON password_histories (user_id, created_at DESC); -``` - -#### Django Model 定义 - -```python -class PasswordHistory(models.Model): - """ - 历史密码记录,每个账号保留最近 N 条(默认 3 条)。 - 新密码不得与最近 3 条历史记录相同(含系统初始密码 Fonrey@2025)。 - """ - user = models.ForeignKey(UserAccount, on_delete=models.CASCADE, related_name='password_histories') - password_hash = models.CharField(max_length=128) - created_at = models.DateTimeField(auto_now_add=True) - - class Meta: - db_table = 'password_histories' - ordering = ['-created_at'] - indexes = [ - models.Index(fields=['user', '-created_at']), - ] -``` - ---- - -## 四、Redis 缓存结构(辅助状态,非持久化) - -以下 Redis Key 不存入 PostgreSQL,属于运行时状态,需与数据库状态保持最终一致: - -| Key 格式 | 类型 | TTL | 说明 | -|----------|------|-----|------| -| `captcha_token:{uuid}` | STRING | 3 分钟 | 滑块验证会话 Token;验证通过后生成 `captcha_pass_token` | -| `captcha_pass:{uuid}` | STRING | 3 分钟 | 一次性通过凭证;登录提交时校验后立即删除 | -| `login_fail:{tenant_id}:{username}` | STRING(计数) | 30 分钟 | 连续密码错误次数;≥ 5 触发锁定;TTL 30 分钟自动清零 | -| `recover_email:{email}` | STRING(计数) | 1 小时 | 找回邮件发送次数;上限 3 次/小时 | -| `recover_reset:{account_id}` | STRING(计数) | 1 小时 | 同一账号密码重置 Token 生成次数;上限 3 次/小时 | -| `tenant_verify_ip:{ip}` | STRING(计数) | 1 分钟 | Tenant 验证接口 IP 限流;≥ 10 次拒绝请求 | - -> **一致性说明**:账号锁定状态由 `user_accounts.status` 持久化,Redis 仅做计数触发器。当 Redis 数据丢失(如 Redis 重启),应用层通过 `locked_until` 字段恢复锁定状态判断。 - ---- - -## 五、账号创建流程与状态机 - -### 5.1 账号状态机 - -``` - ┌─────────────────────────────────────┐ - │ 账号生命周期状态机 │ - └─────────────────────────────────────┘ - - [创建账号] - │ is_initial_password=True, status=active - ▼ - [初始密码态] ─── 使用初始密码登录成功 ───► [强制修改密码页] - │ │ 修改成功 - │ ▼ - │ [正常使用态] - │ status=active - │ is_initial_password=False - │ - ├── 密码错误 ≥ 5 次 ──────────────────► [锁定态] - │ status=locked - │ locked_until = now+30min - │ │ - │ ┌───────────────┤ - │ │ 30分钟到期 │ 管理员手动解锁 - │ ▼ ▼ - │ [正常使用态] ◄─── [管理员操作] - │ - └── 员工离职 / 管理员停用 ──► [停用态] - status=disabled - │ - 员工复职/管理员恢复 - │ - ▼ - [正常使用态] -``` - -### 5.2 账号创建触发时机 - -| 账号类型 | 触发时机 | 创建者 | username 规则 | 初始密码 | -|----------|----------|--------|--------------|---------| -| Tenant Admin | 平台运营在系统后台开通租户时 | 平台运营 | 自定义(字母开头,6~30 位) | 平台运营自定义 | -| 普通员工 | Tenant Admin 在「新增员工」时系统自动生成 | 系统(Tenant Admin 触发) | 固定为员工手机号(11 位) | 系统统一初始密码(部署配置) | - ---- - -## 六、关联约束与数据完整性 - -### 6.1 与 `org.Staff` 的关联规则 - -``` -org_staff (1) ──── (0..1) user_accounts -``` - -- 普通员工账号:`staff_id` **必须**有值,且在 `org.Staff` 中对应记录的 `status` 为 active -- Tenant Admin:`staff_id` **可为空**(平台运营账号可不绑定实名档案) -- 员工离职时(`org.Staff.status` → `resigned`),触发账号 `status` → `disabled`(由 `org` App Service 层调用 `accounts` 服务执行,避免循环依赖) -- 账号删除:**不允许物理删除**,仅允许 `status=disabled`,审计记录永久保留 - -### 6.2 跨 App 依赖方向 - -``` -accounts ──► org (单向依赖:accounts.UserAccount.staff_id → org.Staff) -org ──► accounts (反向触发,通过 Service 层调用,不通过 FK 反查) -``` - -> **设计原则**:避免循环 FK 依赖,跨 App 的状态联动通过 Service 层的显式调用完成,不在 Model 层建立反向 FK。 - ---- - -## 七、迁移说明(Django Migrations) - -### 初始迁移顺序 - -``` -0001_initial_user_accounts.py # UserAccount 表(依赖 org.Staff 表已存在) -0002_login_attempts.py # LoginAttempt 表 -0003_password_reset_tokens.py # PasswordResetToken 表 -0004_password_histories.py # PasswordHistory 表 -``` - -### 注意事项 - -- `accounts` App 的迁移依赖 `org` App(`org.Staff` 表须先创建),需在 `INSTALLED_APPS` 中确保 `org` 在 `accounts` 之前 -- 所有迁移均在**租户 Schema** 下执行(`django-tenants` 的 `migrate_schemas` 命令) -- 不得为 `email` 字段设置 `NOT NULL` 约束(允许为空,是否绑定邮箱属于用户选择) - ---- - -## 八、设计决策说明(ADR) - -| 决策 | 选择 | 理由 | -|------|------|------| -| 主键类型 | `BIGSERIAL` (BigInt) | 登录审计场景下 BigInt 主键更简洁高效;跨环境引用场景少,无需 UUID 的随机性 | -| `phone` 字段拆分为 `phone_enc` + `phone_hash` | 是 | 与 `org.Staff` 保持一致;`phone_enc` 保存原文用于展示,`phone_hash` 用于唯一性校验和快速查询,避免加密字段全表扫描 | -| 不扩展 Django `User` | 使用 `AbstractBaseUser` | 避免 `django.contrib.auth.User` 的全局唯一性限制(多租户下同一 username 在不同租户是允许的) | -| `LoginAttempt` 不设外键到 `UserAccount` | 是(冗余存储 username) | 即使账号被删除(停用),审计记录仍需保留;使用 username 字符串字段保证审计完整性 | -| 历史密码单独建表 | `PasswordHistory` 独立表 | 而非在 `UserAccount` 中存 JSON 数组,便于查询和维护,支持未来扩展保留次数 | -| 锁定到期时间持久化 | `locked_until` 字段 | Redis 可能重启丢失数据,持久化 `locked_until` 保证 Redis 故障时锁定状态不丢失 | +# Fonrey — 登录与账号认证数据模型(DATA_MODEL_LOGIN) + +> **所属系统**: Fonrey 房产经纪管理系统 +> **版本**: v1.0 +> **日期**: 2026-04-24 +> **关联模块**: `apps/accounts/` — 账号认证、登录安全、密码管理 +> **关联 PRD**: `Project/fonrey/PRD/登录管理/用户登录管理模块PRD.md` (v1.3) +> **关联技术方案**: `Project/fonrey/TECH_STACK/登录管理技术方案.md` + +--- + +## 一、领域概览(Domain Overview) + +### 核心概念 + +- **UserAccount(用户账号)**:系统登录主体,必须与员工档案(`org.Staff`)1:1 绑定。分为 Tenant Admin(超级管理账号,每租户唯一)和普通员工账号(username 固定为手机号)。 +- **LoginAttempt(登录尝试记录)**:记录每次登录行为(成功/失败),用于安全审计和账号锁定判断,保留 ≥ 90 天。 +- **PasswordResetToken(密码重置令牌)**:通过邮件找回密码时生成的一次性令牌,有效期 30 分钟,使用后立即失效。 +- **PasswordHistory(历史密码记录)**:保存最近 3 次密码哈希,用于防止重复使用历史密码。 + +### 关键业务规则 + +1. **账号与员工强绑定**:每个登录账号 **必须** 与 `org.Staff` 中的员工档案 1:1 绑定(Tenant Admin 例外,可不绑定)。 +2. **用户名规则差异化**: + - Tenant Admin:由平台运营自定义(字母开头,6~30 位,含字母/数字/下划线) + - 普通员工:**固定为员工手机号**(11 位数字),创建后不可变更 +3. **初始密码强制修改**:新账号及密码重置后,`is_initial_password = True`,首次登录必须修改密码,不可跳过。 +4. **账号锁定机制**:同一账号连续密码错误 ≥ 5 次,状态置为 `locked`,30 分钟后自动恢复;Tenant Admin 可提前手动解锁。 +5. **员工离职联动**:员工离职时,对应账号的 `status` 自动置为 `disabled`,不可登录,历史操作记录保留。 +6. **不支持自助注册**:所有账号由有权限的管理角色创建,普通员工账号在新增员工时由系统自动生成。 + +--- + +## 二、实体关系 + +``` +UserAccount + │ + ├── 1:1 ── org.Staff (实名绑定,普通员工必须) + ├── 1:N ── LoginAttempt (登录审计记录) + ├── 1:N ── PasswordResetToken (密码重置令牌) + ├── 1:N ── PasswordHistory (历史密码记录) + └── M:1 ── UserAccount.created_by (创建人自引用) +``` + +### Schema 归属 + +| 表 | Schema 位置 | 说明 | +|----|------------|------| +| `user_accounts` | 租户 Schema | 账号数据按租户隔离,username 唯一性在 Schema 维度生效 | +| `login_attempts` | 租户 Schema | 审计记录属于租户,跨租户不可见 | +| `password_reset_tokens` | 租户 Schema | 令牌与租户账号绑定 | +| `password_histories` | 租户 Schema | 历史密码与账号绑定 | + +> **注意**:Tenant ID 验证相关逻辑在 **Public Schema**(`shared_apps`),使用 `django-tenants` 的 `TenantModel`,不在本文档范围内,详见 `DATA_MODEL.md` §四(公共 Schema)。 + +--- + +## 三、Schema 定义 + +### 3.1 `user_accounts` — 账号主表(租户 Schema) + +**表说明**:系统登录主体,每个租户内独立隔离,`username` 唯一性约束在 Schema 维度生效。 + +#### 字段定义 + +| 字段名 | 类型 | 约束 | 默认值 | 说明 | +|--------|------|------|--------|------| +| `id` | `BIGSERIAL` | `PRIMARY KEY` | — | 自增主键(审计场景下 BigInt 更直观;跨环境引用使用 UUID 扩展字段见下) | +| `username` | `VARCHAR(30)` | `NOT NULL` | — | 登录名;普通员工为手机号(11 位数字);Tenant Admin 为自定义字符串;创建后不可更改 | +| `password` | `VARCHAR(128)` | `NOT NULL` | — | PBKDF2+SHA256 哈希存储,使用 Django `make_password` | +| `email` | `VARCHAR(254)` | `NULL` | `NULL` | 绑定邮箱;用于找回密码/用户名;为空则无法自助找回;同租户唯一 | +| `phone_enc` | `TEXT` | `NULL` | `NULL` | 手机号 AES-256-GCM 加密密文(`core.encryption`);普通员工必填 | +| `phone_hash` | `VARCHAR(64)` | `NULL` | `NULL` | 手机号 SHA-256 哈希;用于唯一性校验和查询;不可反推原文 | +| `staff_id` | `BIGINT` | `FK → org_staff.id`, `NULL`, `UNIQUE` | `NULL` | 员工档案绑定(1:1);普通员工必须有值;Tenant Admin 可为空 | +| `is_tenant_admin` | `BOOLEAN` | `NOT NULL` | `FALSE` | 是否为该租户的超级管理账号;每个租户最多 1 个(应用层约束) | +| `status` | `VARCHAR(10)` | `NOT NULL`, `CHECK(status IN ('active','disabled','locked'))` | `'active'` | 账号状态;`locked` 为密码错误锁定,30 分钟自动恢复 | +| `is_initial_password` | `BOOLEAN` | `NOT NULL` | `TRUE` | 初始密码标记;True 时登录成功后强制跳转修改密码页,不可跳过 | +| `last_login` | `TIMESTAMPTZ` | `NULL` | `NULL` | 最后登录时间 | +| `locked_until` | `TIMESTAMPTZ` | `NULL` | `NULL` | 锁定到期时间;到期后应用层将 status 恢复 active | +| `created_at` | `TIMESTAMPTZ` | `NOT NULL` | `NOW()` | 账号创建时间 | +| `updated_at` | `TIMESTAMPTZ` | `NOT NULL` | `NOW()` | 最后更新时间(触发器维护) | +| `created_by` | `BIGINT` | `FK → user_accounts.id`, `NULL` | `NULL` | 创建人;普通员工由 Tenant Admin 创建;Tenant Admin 由平台运营创建(可为 NULL) | + +#### 唯一性约束 + +```sql +UNIQUE (username) -- Schema 内唯一,跨租户不冲突(django-tenants 机制保障) +UNIQUE (email) -- 同租户内邮箱唯一(可为 NULL,NULL 不参与唯一性校验) +UNIQUE (phone_hash) -- 同租户内手机号唯一(通过 hash 实现,不暴露原文) +UNIQUE (staff_id) -- 员工档案 1:1 绑定 +``` + +#### 索引 + +```sql +CREATE UNIQUE INDEX uq_user_accounts_username ON user_accounts (username); +CREATE UNIQUE INDEX uq_user_accounts_email ON user_accounts (email) WHERE email IS NOT NULL; +CREATE UNIQUE INDEX uq_user_accounts_phone ON user_accounts (phone_hash) WHERE phone_hash IS NOT NULL; +CREATE INDEX idx_user_accounts_status ON user_accounts (status); +CREATE INDEX idx_user_accounts_staff ON user_accounts (staff_id); +``` + +#### Django Model 定义 + +```python +# apps/accounts/models.py +from django.contrib.auth.models import AbstractBaseUser, BaseUserManager +from django.db import models + + +class UserAccountManager(BaseUserManager): + def create_user(self, username, password, **extra_fields): + if not username: + raise ValueError("username 不能为空") + user = self.model(username=username, **extra_fields) + user.set_password(password) + user.save(using=self._db) + return user + + +class UserAccount(AbstractBaseUser): + """ + 租户级用户账号。 + - 普通员工:username 固定为手机号(11 位数字) + - Tenant Admin:username 由平台运营自定义(字母开头,6~30 位) + 注意:此表位于租户 Schema,username 唯一性约束在 Schema 维度生效。 + """ + username = models.CharField(max_length=30) + email = models.EmailField(null=True, blank=True) + phone_enc = models.TextField(null=True, blank=True) # AES-256-GCM 加密密文 + phone_hash = models.CharField(max_length=64, null=True, blank=True) # SHA-256 哈希索引 + staff = models.OneToOneField( + 'org.Staff', + null=True, blank=True, + on_delete=models.SET_NULL, + related_name='account', + ) + is_tenant_admin = models.BooleanField(default=False) + status = models.CharField( + max_length=10, + choices=[('active', 'Active'), ('disabled', 'Disabled'), ('locked', 'Locked')], + default='active', + ) + is_initial_password = models.BooleanField(default=True) + last_login = models.DateTimeField(null=True, blank=True) + locked_until = models.DateTimeField(null=True, blank=True) + created_at = models.DateTimeField(auto_now_add=True) + updated_at = models.DateTimeField(auto_now=True) + created_by = models.ForeignKey( + 'self', + null=True, blank=True, + on_delete=models.SET_NULL, + related_name='created_accounts', + ) + + USERNAME_FIELD = 'username' + REQUIRED_FIELDS = [] + + objects = UserAccountManager() + + class Meta: + db_table = 'user_accounts' + # Schema 内唯一约束 + constraints = [ + models.UniqueConstraint(fields=['username'], name='uq_user_accounts_username'), + ] + + def __str__(self): + return f"{self.username} ({'admin' if self.is_tenant_admin else 'staff'})" + + def is_locked(self) -> bool: + """检查账号是否处于锁定状态(含自动过期判断)""" + from django.utils import timezone + if self.status == 'locked': + if self.locked_until and timezone.now() >= self.locked_until: + # 锁定已到期,应用层自动恢复(实际由 service 层处理) + return False + return True + return False +``` + +--- + +### 3.2 `login_attempts` — 登录尝试审计表(租户 Schema) + +**表说明**:记录每次登录请求(成功/失败),用于安全审计和锁定判断。数据保留 ≥ 90 天,不得提前清理。 + +#### 字段定义 + +| 字段名 | 类型 | 约束 | 默认值 | 说明 | +|--------|------|------|--------|------| +| `id` | `BIGSERIAL` | `PRIMARY KEY` | — | 自增主键 | +| `username` | `VARCHAR(30)` | `NOT NULL` | — | 尝试登录的用户名(冗余存储,即使账号不存在也记录) | +| `ip_address` | `INET` | `NOT NULL` | — | 来源 IP 地址(支持 IPv4/IPv6) | +| `user_agent` | `TEXT` | `NULL` | `NULL` | 客户端 User-Agent(Electron 版本信息) | +| `success` | `BOOLEAN` | `NOT NULL` | — | 是否登录成功 | +| `failure_reason` | `VARCHAR(30)` | `NULL` | `NULL` | 失败原因;可选值见下方枚举 | +| `attempted_at` | `TIMESTAMPTZ` | `NOT NULL` | `NOW()` | 尝试时间 | + +**`failure_reason` 枚举值**: + +| 值 | 含义 | +|----|------| +| `wrong_password` | 用户名或密码错误 | +| `wrong_captcha` | 行为验证码失败 | +| `account_locked` | 账号已锁定 | +| `account_disabled` | 账号已停用 | +| `tenant_not_found` | 租户不存在(理论上不应出现,防御性记录) | + +#### 索引 + +```sql +CREATE INDEX idx_login_attempts_username ON login_attempts (username); +CREATE INDEX idx_login_attempts_ip ON login_attempts (ip_address); +CREATE INDEX idx_login_attempts_time ON login_attempts (attempted_at DESC); +-- 复合索引:按账号查询最近失败记录(锁定判断场景) +CREATE INDEX idx_login_attempts_fail_check ON login_attempts (username, success, attempted_at DESC); +``` + +#### Django Model 定义 + +```python +class LoginAttempt(models.Model): + """ + 登录尝试审计记录。 + - 合规保留周期:≥ 90 天 + - 注意:failure_reason 不得存储密码明文(含错误密码) + """ + FAILURE_REASONS = [ + ('wrong_password', '用户名或密码错误'), + ('wrong_captcha', '行为验证码失败'), + ('account_locked', '账号已锁定'), + ('account_disabled', '账号已停用'), + ('tenant_not_found', '租户不存在'), + ] + + username = models.CharField(max_length=30) + ip_address = models.GenericIPAddressField() + user_agent = models.TextField(null=True, blank=True) + success = models.BooleanField() + failure_reason = models.CharField(max_length=30, null=True, blank=True, choices=FAILURE_REASONS) + attempted_at = models.DateTimeField(auto_now_add=True) + + class Meta: + db_table = 'login_attempts' + indexes = [ + models.Index(fields=['username']), + models.Index(fields=['ip_address']), + models.Index(fields=['-attempted_at']), + models.Index(fields=['username', 'success', '-attempted_at'], + name='idx_login_attempts_fail_check'), + ] + + def __str__(self): + return f"{self.username} @ {self.attempted_at} - {'OK' if self.success else self.failure_reason}" +``` + +--- + +### 3.3 `password_reset_tokens` — 密码重置令牌表(租户 Schema) + +**表说明**:用于通过邮件找回密码的一次性令牌。单次有效,30 分钟过期。 + +#### 字段定义 + +| 字段名 | 类型 | 约束 | 默认值 | 说明 | +|--------|------|------|--------|------| +| `id` | `BIGSERIAL` | `PRIMARY KEY` | — | 自增主键 | +| `user_id` | `BIGINT` | `FK → user_accounts.id`, `NOT NULL` | — | 关联账号 | +| `token` | `VARCHAR(86)` | `NOT NULL`, `UNIQUE` | — | `secrets.token_urlsafe(64)` 生成(86 字符),全局唯一 | +| `expires_at` | `TIMESTAMPTZ` | `NOT NULL` | — | 过期时间(`created_at + 30 分钟`) | +| `is_used` | `BOOLEAN` | `NOT NULL` | `FALSE` | 是否已使用;使用后立即置 True,防止重放攻击 | +| `created_at` | `TIMESTAMPTZ` | `NOT NULL` | `NOW()` | 创建时间 | + +#### 索引 + +```sql +CREATE UNIQUE INDEX uq_password_reset_tokens_token ON password_reset_tokens (token); +CREATE INDEX idx_password_reset_tokens_user ON password_reset_tokens (user_id); +CREATE INDEX idx_password_reset_tokens_expiry ON password_reset_tokens (expires_at) WHERE is_used = FALSE; +``` + +#### Django Model 定义 + +```python +class PasswordResetToken(models.Model): + """ + 密码重置令牌。 + 安全约束: + - Token 单次有效(is_used=True 后立即失效) + - 有效期 30 分钟 + - 同一账号 1 小时内最多生成 3 个(服务层限频,Redis 计数) + """ + user = models.ForeignKey(UserAccount, on_delete=models.CASCADE, related_name='reset_tokens') + token = models.CharField(max_length=86, unique=True) # secrets.token_urlsafe(64) + expires_at = models.DateTimeField() + is_used = models.BooleanField(default=False) + created_at = models.DateTimeField(auto_now_add=True) + + class Meta: + db_table = 'password_reset_tokens' + indexes = [ + models.Index(fields=['user_id']), + ] + + def is_valid(self) -> bool: + from django.utils import timezone + return not self.is_used and timezone.now() < self.expires_at +``` + +--- + +### 3.4 `password_histories` — 历史密码记录表(租户 Schema) + +**表说明**:保存账号最近 3 次密码哈希,用于防止重复使用历史密码(含初始密码)。 + +#### 字段定义 + +| 字段名 | 类型 | 约束 | 默认值 | 说明 | +|--------|------|------|--------|------| +| `id` | `BIGSERIAL` | `PRIMARY KEY` | — | 自增主键 | +| `user_id` | `BIGINT` | `FK → user_accounts.id`, `NOT NULL` | — | 关联账号 | +| `password_hash` | `VARCHAR(128)` | `NOT NULL` | — | PBKDF2+SHA256 哈希值 | +| `created_at` | `TIMESTAMPTZ` | `NOT NULL` | `NOW()` | 记录时间(密码修改时间) | + +#### 索引 + +```sql +CREATE INDEX idx_password_histories_user ON password_histories (user_id, created_at DESC); +``` + +#### Django Model 定义 + +```python +class PasswordHistory(models.Model): + """ + 历史密码记录,每个账号保留最近 N 条(默认 3 条)。 + 新密码不得与最近 3 条历史记录相同(含系统初始密码 Fonrey@2025)。 + """ + user = models.ForeignKey(UserAccount, on_delete=models.CASCADE, related_name='password_histories') + password_hash = models.CharField(max_length=128) + created_at = models.DateTimeField(auto_now_add=True) + + class Meta: + db_table = 'password_histories' + ordering = ['-created_at'] + indexes = [ + models.Index(fields=['user', '-created_at']), + ] +``` + +--- + +## 四、Redis 缓存结构(辅助状态,非持久化) + +以下 Redis Key 不存入 PostgreSQL,属于运行时状态,需与数据库状态保持最终一致: + +| Key 格式 | 类型 | TTL | 说明 | +|----------|------|-----|------| +| `captcha_token:{uuid}` | STRING | 3 分钟 | 滑块验证会话 Token;验证通过后生成 `captcha_pass_token` | +| `captcha_pass:{uuid}` | STRING | 3 分钟 | 一次性通过凭证;登录提交时校验后立即删除 | +| `login_fail:{tenant_id}:{username}` | STRING(计数) | 30 分钟 | 连续密码错误次数;≥ 5 触发锁定;TTL 30 分钟自动清零 | +| `recover_email:{email}` | STRING(计数) | 1 小时 | 找回邮件发送次数;上限 3 次/小时 | +| `recover_reset:{account_id}` | STRING(计数) | 1 小时 | 同一账号密码重置 Token 生成次数;上限 3 次/小时 | +| `tenant_verify_ip:{ip}` | STRING(计数) | 1 分钟 | Tenant 验证接口 IP 限流;≥ 10 次拒绝请求 | + +> **一致性说明**:账号锁定状态由 `user_accounts.status` 持久化,Redis 仅做计数触发器。当 Redis 数据丢失(如 Redis 重启),应用层通过 `locked_until` 字段恢复锁定状态判断。 + +--- + +## 五、账号创建流程与状态机 + +### 5.1 账号状态机 + +``` + ┌─────────────────────────────────────┐ + │ 账号生命周期状态机 │ + └─────────────────────────────────────┘ + + [创建账号] + │ is_initial_password=True, status=active + ▼ + [初始密码态] ─── 使用初始密码登录成功 ───► [强制修改密码页] + │ │ 修改成功 + │ ▼ + │ [正常使用态] + │ status=active + │ is_initial_password=False + │ + ├── 密码错误 ≥ 5 次 ──────────────────► [锁定态] + │ status=locked + │ locked_until = now+30min + │ │ + │ ┌───────────────┤ + │ │ 30分钟到期 │ 管理员手动解锁 + │ ▼ ▼ + │ [正常使用态] ◄─── [管理员操作] + │ + └── 员工离职 / 管理员停用 ──► [停用态] + status=disabled + │ + 员工复职/管理员恢复 + │ + ▼ + [正常使用态] +``` + +### 5.2 账号创建触发时机 + +| 账号类型 | 触发时机 | 创建者 | username 规则 | 初始密码 | +|----------|----------|--------|--------------|---------| +| Tenant Admin | 平台运营在系统后台开通租户时 | 平台运营 | 自定义(字母开头,6~30 位) | 平台运营自定义 | +| 普通员工 | Tenant Admin 在「新增员工」时系统自动生成 | 系统(Tenant Admin 触发) | 固定为员工手机号(11 位) | 系统统一初始密码(部署配置) | + +--- + +## 六、关联约束与数据完整性 + +### 6.1 与 `org.Staff` 的关联规则 + +``` +org_staff (1) ──── (0..1) user_accounts +``` + +- 普通员工账号:`staff_id` **必须**有值,且在 `org.Staff` 中对应记录的 `status` 为 active +- Tenant Admin:`staff_id` **可为空**(平台运营账号可不绑定实名档案) +- 员工离职时(`org.Staff.status` → `resigned`),触发账号 `status` → `disabled`(由 `org` App Service 层调用 `accounts` 服务执行,避免循环依赖) +- 账号删除:**不允许物理删除**,仅允许 `status=disabled`,审计记录永久保留 + +### 6.2 跨 App 依赖方向 + +``` +accounts ──► org (单向依赖:accounts.UserAccount.staff_id → org.Staff) +org ──► accounts (反向触发,通过 Service 层调用,不通过 FK 反查) +``` + +> **设计原则**:避免循环 FK 依赖,跨 App 的状态联动通过 Service 层的显式调用完成,不在 Model 层建立反向 FK。 + +--- + +## 七、迁移说明(Django Migrations) + +### 初始迁移顺序 + +``` +0001_initial_user_accounts.py # UserAccount 表(依赖 org.Staff 表已存在) +0002_login_attempts.py # LoginAttempt 表 +0003_password_reset_tokens.py # PasswordResetToken 表 +0004_password_histories.py # PasswordHistory 表 +``` + +### 注意事项 + +- `accounts` App 的迁移依赖 `org` App(`org.Staff` 表须先创建),需在 `INSTALLED_APPS` 中确保 `org` 在 `accounts` 之前 +- 所有迁移均在**租户 Schema** 下执行(`django-tenants` 的 `migrate_schemas` 命令) +- 不得为 `email` 字段设置 `NOT NULL` 约束(允许为空,是否绑定邮箱属于用户选择) + +--- + +## 八、设计决策说明(ADR) + +| 决策 | 选择 | 理由 | +|------|------|------| +| 主键类型 | `BIGSERIAL` (BigInt) | 登录审计场景下 BigInt 主键更简洁高效;跨环境引用场景少,无需 UUID 的随机性 | +| `phone` 字段拆分为 `phone_enc` + `phone_hash` | 是 | 与 `org.Staff` 保持一致;`phone_enc` 保存原文用于展示,`phone_hash` 用于唯一性校验和快速查询,避免加密字段全表扫描 | +| 不扩展 Django `User` | 使用 `AbstractBaseUser` | 避免 `django.contrib.auth.User` 的全局唯一性限制(多租户下同一 username 在不同租户是允许的) | +| `LoginAttempt` 不设外键到 `UserAccount` | 是(冗余存储 username) | 即使账号被删除(停用),审计记录仍需保留;使用 username 字符串字段保证审计完整性 | +| 历史密码单独建表 | `PasswordHistory` 独立表 | 而非在 `UserAccount` 中存 JSON 数组,便于查询和维护,支持未来扩展保留次数 | +| 锁定到期时间持久化 | `locked_until` 字段 | Redis 可能重启丢失数据,持久化 `locked_until` 保证 Redis 故障时锁定状态不丢失 | diff --git a/Project/fonrey/DATA_MODEL/DATA_MODEL_SETTING.md b/Project/fonrey/DATA_MODEL/DATA_MODEL_SETTING.md new file mode 100644 index 00000000..669173f0 --- /dev/null +++ b/Project/fonrey/DATA_MODEL/DATA_MODEL_SETTING.md @@ -0,0 +1,391 @@ +> **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_SETTING) + +> **定位**:本文件是 `apps/setting/` 模块的数据模型权威来源。 +> **版本**:v1.0 | **日期**:2026-04-27 +> **关联 PRD**:`PRD/系统配置/系统配置模块PRD.md` +> **关联文档**:`DATA_MODEL/ENUMS.md`、`DATA_MODEL/DATA_MODEL.md` + +--- + +## 一、模块定位与架构边界 + +### 1.1 系统配置模块职责 + +系统配置模块(`apps/setting/`)负责管理三类性质不同的配置数据: + +| 类型 | 说明 | 表 | Schema | +| -------------- | ---------------- | --------------------------------------------- | -------------- | +| **A. 固定系统枚举** | 平台级固定值域,所有租户共享 | `enum_labels` | Public(shared) | +| **B. 可配置枚举** | 各租户选项不同,管理员可增删排序 | `lookup_groups` + `lookup_items` | Tenant | +| **C. 行为规则与开关** | 标量配置开关 + 字段必填规则 | `tenant_settings` + `field_requirement_rules` | Tenant | + +> **重要区分**: +> - 类型 A (`enum_labels`) 已在 `DATA_MODEL/ENUMS.md` 完整定义,**本文件不重复** +> - 类型 B/C 均存于 **租户 Schema**,由租户管理员通过界面维护 +> - `apps/setting/` 是 `tenant_apps`(**非** `shared_apps`) + +### 1.2 依赖关系 + +``` +apps/setting/ + ├── 依赖 → core.cache(Redis,统一租户前缀) + ├── 依赖 → org.Staff(created_by / updated_by FK) + └── 被依赖 ← apps/property(读取字段规则、枚举选项) + ← apps/client(读取查重范围、枚举选项) +``` + +--- + +## 二、可配置枚举表(类型 B) + +### 2.1 `lookup_groups`(枚举分组) + +每个分组代表一类可配置枚举(如「客源来源」「跟进目的」),由研发预置,租户管理员**不可新增或删除分组**,仅可管理分组内的选项。 + +```sql +-- ============================================================ +-- 可配置枚举分组(Tenant Schema) +-- 研发预置,租户不可修改分组本身 +-- ============================================================ +CREATE TABLE lookup_groups ( + id UUID PRIMARY KEY DEFAULT gen_random_uuid(), + module VARCHAR(50) NOT NULL, -- 'client' | 'property' + key VARCHAR(100) NOT NULL, -- 'source' | 'follow_purpose' + label_zh VARCHAR(50) NOT NULL, -- 界面显示名称,如「客源来源」 + description TEXT, -- 说明文案(前端 tooltip 使用) + sort_order SMALLINT NOT NULL DEFAULT 0, + created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), + updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), + UNIQUE (module, key) +); +``` + +**MVP 预置分组(种子数据)**: + +| module | key | label_zh | description | +|--------|-----|----------|-------------| +| `client` | `source` | 客源来源 | 客源从何处获取,用于来源渠道分析 | +| `client` | `follow_purpose` | 跟进目的 | 客源跟进时选择的目的分类 | +| `property` | `source` | 房源来源 | 房源从何处获取 | + +--- + +### 2.2 `lookup_items`(枚举选项) + +```sql +-- ============================================================ +-- 可配置枚举选项(Tenant Schema) +-- 租户管理员可增删排序;is_system=True 的预制项不可物理删除 +-- ============================================================ +CREATE TABLE lookup_items ( + id UUID PRIMARY KEY DEFAULT gen_random_uuid(), + group_id UUID NOT NULL REFERENCES lookup_groups(id) ON DELETE CASCADE, + value VARCHAR(100) NOT NULL, -- 存储值,英文 snake_case(如 'door_to_door') + label_zh VARCHAR(50) NOT NULL, -- 显示文本(如「上门」) + is_system BOOLEAN NOT NULL DEFAULT FALSE, -- True=系统预制,不可删除,仅可停用 + is_active BOOLEAN NOT NULL DEFAULT TRUE, + sort_order SMALLINT NOT NULL DEFAULT 0, + created_by UUID REFERENCES staff(id) ON DELETE SET NULL, -- 系统预制时为 NULL + created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), + updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), + UNIQUE (group_id, value) +); + +CREATE INDEX idx_lookup_items_group_active + ON lookup_items(group_id, is_active, sort_order); +``` + +**关键约束**: +- `is_system = TRUE` 的记录不允许物理删除(Service 层强制拦截) +- `is_active = FALSE` 后:前端录入下拉不展示;历史已选该值的记录保留原值,展示时追加「(已停用)」后缀 +- `value` 一旦写入不允许修改(历史数据依赖);如需改名,停用旧项、新增新项 + +--- + +### 2.3 MVP 预置种子数据(`is_system = TRUE`) + +以下选项在租户初始化时自动写入: + +#### 客源来源(`client.source`) + +| value | label_zh | sort_order | +|-------|----------|------------| +| `store_reception` | 门店接待 | 1 | +| `old_client_referral` | 老客户转介绍 | 2 | +| `stationed_dispatch` | 驻守派单 | 3 | +| `walk_in` | 上门 | 4 | +| `online_58` | 网络-58同城 | 5 | +| `online_anjuke` | 网络-安居客 | 6 | +| `wechat` | 微信 | 7 | +| `friend_referral` | 朋友介绍 | 8 | + +#### 跟进目的(`client.follow_purpose`) + +| value | label_zh | sort_order | +|-------|----------|------------| +| `callback` | 回拨 | 1 | +| `push_property` | 推房 | 2 | +| `showing` | 带看 | 3 | +| `maintain` | 维护 | 4 | +| `other` | 其他 | 5 | + +#### 房源来源(`property.source`) + +| value | label_zh | sort_order | +|-------|----------|------------| +| `proactive_development` | 主动开发 | 1 | +| `owner_walk_in` | 业主上门 | 2 | +| `old_client_referral` | 老客户转介绍 | 3 | +| `online_inquiry` | 网络来电 | 4 | + +--- + +## 三、行为规则与开关(类型 C) + +### 3.1 `tenant_settings`(标量配置键值表) + +存储开关(bool)、阈值(int)、单选枚举(string)等标量类型配置项。 + +```sql +-- ============================================================ +-- 租户标量配置(键值对)(Tenant Schema) +-- ============================================================ +CREATE TABLE tenant_settings ( + id UUID PRIMARY KEY DEFAULT gen_random_uuid(), + category VARCHAR(50) NOT NULL, -- 配置分类:'client' | 'property' | 'showroom' + key VARCHAR(100) NOT NULL, -- 配置 key,如 'duplicate_check_scope' + value JSONB NOT NULL, -- 存储任意类型(bool/int/str),如 {"v": "self"} + value_type VARCHAR(20) NOT NULL -- 'bool' | 'int' | 'string' | 'enum'(用于前端渲染控件) + CHECK (value_type IN ('bool', 'int', 'string', 'enum')), + updated_by UUID REFERENCES staff(id) ON DELETE SET NULL, + updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), + UNIQUE (category, key) +); + +CREATE INDEX idx_tenant_settings_category ON tenant_settings(category); +``` + +**存储格式约定**: +- `bool`:`{"v": true}` 或 `{"v": false}` +- `int`:`{"v": 30}` +- `string`:`{"v": "some_value"}` +- `enum`:`{"v": "self", "choices": ["self", "dept", "company"]}` — `choices` 由代码硬编码,不存 DB + +**MVP 阶段预置 key**: + +| category | key | value_type | 默认值 | 说明 | +|----------|-----|-----------|--------|------| +| `client` | `duplicate_check_scope` | `enum` | `{"v": "self"}` | 新增私客查重范围:`self`(本人)/ `dept`(本部门)/ `company`(全公司) | + +> 未来 P1 阶段可按需追加 key,无需修改表结构。 + +--- + +### 3.2 `field_requirement_rules`(字段必填规则表) + +按「模块 × 房源用途 × 交易状态 × 字段」四元组确定一条规则,控制录入界面的字段显示状态。 + +```sql +-- ============================================================ +-- 字段必填/隐藏规则(Tenant Schema) +-- MVP 仅支持 module='property' +-- ============================================================ +CREATE TABLE field_requirement_rules ( + id UUID PRIMARY KEY DEFAULT gen_random_uuid(), + module VARCHAR(20) NOT NULL, -- 'property' | 'client'(MVP 只用 'property') + entity_type VARCHAR(50) NOT NULL, -- 与 property.property_type CHECK 约束值对齐 + -- 'residential'|'villa'|'commercial_residential'|'shop'|'office'|'other' + trade_status VARCHAR(20) NOT NULL, -- 交易大类:'sale'|'rent'|'sale_rent'|'*'(全部) + CHECK (trade_status IN ('sale', 'rent', 'sale_rent', '*')), + field_key VARCHAR(50) NOT NULL, -- 字段 key,如 'orientation'|'decoration'|'floor' + requirement VARCHAR(10) NOT NULL -- 规则值 + CHECK (requirement IN ('required', 'optional', 'hidden')), + updated_by UUID REFERENCES staff(id) ON DELETE SET NULL, + updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), + UNIQUE (module, entity_type, trade_status, field_key) +); + +CREATE INDEX idx_field_req_lookup + ON field_requirement_rules(module, entity_type, trade_status); +``` + +**与 `property.property_type` 对齐说明**: + +`entity_type` 的值域与 `property.property_type` 的 CHECK 约束完全一致: + +| entity_type | property_type label_zh | +|-------------|----------------------| +| `residential` | 住宅 | +| `villa` | 别墅 | +| `commercial_residential` | 商住 | +| `shop` | 商铺 | +| `office` | 写字楼 | +| `other` | 其他 | + +**`trade_status` 与 `property.status` 的映射关系**: + +| trade_status | 对应 property.status 值 | +|--------------|------------------------| +| `sale` | `for_sale` | +| `rent` | `for_rent` | +| `sale_rent` | `for_sale_rent` | +| `*` | 所有状态通用规则(fallback) | + +> **重要**:`trade_status` 是录入场景的交易意图分类,不是 `property.status` 的完整枚举。规则匹配逻辑:先查精确匹配(`entity_type + trade_status`),不存在则查 `*` 通配规则。 + +**MVP 初始规则(研发预置,管理员可覆盖)**: + +| module | entity_type | trade_status | field_key | requirement | +|--------|-------------|--------------|-----------|-------------| +| `property` | `residential` | `sale` | `orientation` | `optional` | +| `property` | `residential` | `sale` | `decoration` | `optional` | +| `property` | `residential` | `sale` | `floor` | `optional` | +| `property` | `residential` | `sale` | `building_area` | `required` | +| `property` | `residential` | `sale` | `inner_area` | `optional` | +| `property` | `residential` | `sale` | `room_layout` | `required` | +| `property` | `residential` | `rent` | `decoration` | `optional` | +| `property` | `residential` | `rent` | `floor` | `optional` | +| `property` | `residential` | `rent` | `building_area` | `required` | +| `property` | `residential` | `rent` | `room_layout` | `required` | + +**MVP 可配置字段范围(对应 PRD AC-4)**: + +| field_key | 说明 | 字段类型 | +|-----------|------|---------| +| `orientation` | 朝向(`property.orientation` 枚举) | 枚举 | +| `decoration` | 装修情况(`property.decoration` 枚举) | 枚举 | +| `floor` | 所在楼层/总楼层 | 数值 | +| `building_area` | 建筑面积(㎡) | 数值 | +| `inner_area` | 套内面积(㎡) | 数值 | +| `room_layout` | 房型(室/厅/卫) | 数值组 | +| `ownership_years` | 产权年限(年) | 数值 | +| `parking_count` | 车位数 | 数值 | + +--- + +## 四、服务层设计 + +所有业务模块**禁止直接查询配置表**,必须通过统一服务层读取: + +```python +# apps/setting/services/tenant_settings_service.py + +class TenantSettingsService: + """ + 系统配置统一读取服务。 + 所有配置均经 Redis 缓存,TTL 5min,写入时主动 invalidate。 + Redis Key 规范:{tenant_schema}:setting:{type}:{key} + """ + + def get(self, category: str, key: str, default=None): + """ + 读取标量配置(tenant_settings 表) + Cache Key: {tenant_schema}:setting:kv:{category}.{key} + 返回 JSONB value 字段中 'v' 的值(已解包) + """ + + def set(self, category: str, key: str, value, updated_by_id) -> None: + """ + 写入标量配置 + 主动 invalidate 缓存 + """ + + def get_lookup_items(self, module: str, key: str) -> list[dict]: + """ + 获取可配置枚举选项(lookup_items 表) + 仅返回 is_active=True 的项,按 sort_order 排序 + Cache Key: {tenant_schema}:setting:lookup:{module}.{key} + 返回格式:[{"value": "walk_in", "label_zh": "上门", "is_system": True}, ...] + """ + + def get_field_requirements( + self, module: str, entity_type: str, trade_status: str + ) -> dict[str, str]: + """ + 获取字段必填规则 + 匹配顺序:精确匹配(entity_type + trade_status) > 通配规则(trade_status='*') + Cache Key: {tenant_schema}:setting:field_req:{module}.{entity_type}.{trade_status} + 返回格式:{"orientation": "optional", "decoration": "required", ...} + """ +``` + +--- + +## 五、Redis 缓存键规范 + +| 用途 | Cache Key | TTL | 失效触发 | +|------|-----------|-----|---------| +| 标量配置 | `{schema}:setting:kv:{category}.{key}` | 300s | `TenantSettingsService.set()` | +| 可配置枚举 | `{schema}:setting:lookup:{module}.{key}` | 300s | 管理员保存 lookup_items | +| 字段规则 | `{schema}:setting:field_req:{module}.{entity_type}.{trade_status}` | 300s | 管理员保存 field_requirement_rules | +| 客源规则(整体) | `{schema}:setting:client_rules` | 300s | 任意客源规则变更 | + +> TTL 300s(5 分钟)对应 PRD 成功指标「配置变更生效时延 ≤ 5 分钟」。 + +--- + +## 六、目录结构 + +``` +apps/setting/ +├── models/ +│ ├── lookup.py # LookupGroup, LookupItem +│ └── setting.py # TenantSetting, FieldRequirementRule +├── services/ +│ └── tenant_settings_service.py # 统一配置读取服务(禁止直接查表) +├── views/ +│ ├── lookup_views.py # 参数配置页面(US-SETTING-001-A) +│ ├── field_rule_views.py # 房源字段规则(US-SETTING-001-B) +│ └── client_rule_views.py # 客源规则(US-SETTING-001-C) +├── templates/setting/ +├── fixtures/ +│ ├── lookup_groups.json # 分组种子数据(3 组) +│ ├── lookup_items.json # 选项种子数据(is_system=True) +│ ├── tenant_settings.json # 默认配置种子数据 +│ └── field_requirement_rules.json # 默认字段规则 +├── migrations/ +│ ├── 0001_lookup_groups.py +│ ├── 0002_lookup_items.py +│ ├── 0003_tenant_settings.py +│ └── 0004_field_requirement_rules.py +└── urls.py +``` + +--- + +## 七、迁移执行顺序 + +``` +0001_lookup_groups # 先建分组表(无外键依赖) +0002_lookup_items # 再建选项表(依赖 lookup_groups + staff) +0003_tenant_settings # 独立,无外键依赖 +0004_field_requirement_rules # 独立,仅依赖 staff +``` + +迁移执行后,通过 `call_command('loaddata', 'lookup_groups')` 等方式加载 fixtures 种子数据。 + +--- + +## 八、关键约束与禁止项 + +| 约束 | 规则 | +|------|------| +| 不可删除系统预制项 | `lookup_items.is_system = True` 的记录,Service 层硬拦截物理删除请求 | +| 不可修改已有 value | `lookup_items.value` 写入后只读;修改请停用旧项 + 新增新项 | +| 不可直接查询配置表 | 业务模块(property/client)**必须**通过 `TenantSettingsService` 读取,禁止 ORM 直查 | +| entity_type 值域 | 必须与 `property.property_type` CHECK 约束完全一致(见第三章) | +| Redis Key 前缀 | 必须携带租户 schema 前缀,格式:`{tenant_schema}:setting:{type}:{key}` | + +--- + +## 九、设计决策(ADR) + +| 决策 | 选择 | 理由 | +|------|------|------| +| 枚举两级架构 | `enum_labels`(Public/固定)+ `lookup_items`(Tenant/可配置)分离 | 保障系统一致性的同时给租户灵活度 | +| `lookup_groups` 由研发预置 | 是 | 防止租户随意创建不规范分组,控制可配置范围边界 | +| `tenant_settings` 使用 JSONB | 是 | 支持 bool/int/string 等多类型,无需为每类型单独建列 | +| `field_requirement_rules` 不新增字段 | 是 | 规则层只控制「必填/选填/隐藏」,字段存在性由 DATA_MODEL_PROPERTY 决定 | +| 服务层统一读取 | `TenantSettingsService` | 统一缓存管理,业务层与配置存储解耦 | +| trade_status 不复用 property.status | 独立 `sale/rent/sale_rent/*` | 录入场景的交易意图与房源全生命周期状态不同,避免耦合 | diff --git a/Project/fonrey/DATA_MODEL/ENUMS.md b/Project/fonrey/DATA_MODEL/ENUMS.md new file mode 100644 index 00000000..52ab65c5 --- /dev/null +++ b/Project/fonrey/DATA_MODEL/ENUMS.md @@ -0,0 +1,762 @@ +> **For AI assistants**: Read this entire file before writing any code. All decisions here are final. Do not suggest alternatives unless asked. + +# Fonrey — 统一枚举字典(ENUMS) + +> **定位**:本文件是 Fonrey 全局枚举标准(Public + Tenant)的统一实现基线。 +> **版本**:v2.1 +> **日期**:2026-04-27 +> **适用范围**:`DATA_MODEL_PUBLIC.md`、`DATA_MODEL_LOGIN.md`、`DATA_MODEL_ORG.md`、`DATA_MODEL_COMPLEX.md`、`DATA_MODEL_PROPERTY.md`、`DATA_MODEL_CLIENT.md`、`DATA_MODEL_PERMISSION.md`、`DATA_MODEL_SETTING.md` + +--- + +## 一、枚举分层标准(必须遵守) + +Fonrey 采用两层枚举体系: + +1. **固定枚举(Fixed Enum)** + - 值域固定,受 `CHECK` 或强业务约束保护 + - 作为系统契约,不能随意改值 + - 可落地到 `public.enum_labels`(用于统一标签) + +2. **可配置枚举(Configurable Enum)** + - 值域由租户自行维护 + - 存储在 Tenant Schema:`lookup_groups` + `lookup_items` + - **禁止**对业务表字段加固定 `CHECK IN (...)` + +--- + +## 二、全局固定枚举(Public / 平台级) + +### 2.1 tenant 生命周期 + +**domain**: `public.tenant.plan` +- `basic`:基础版 +- `professional`:专业版 +- `enterprise`:企业版 + +**domain**: `public.tenant.status` +- `creating`:创建中 +- `active`:正常 +- `suspended`:已挂起 +- `pending_delete`:待删除 +- `deleted`:已删除 +- `failed`:创建/初始化失败 + +**domain**: `public.tenant.suspended_reason` +- `overdue`:欠费 +- `violation`:违规 +- `requested`:客户申请 +- `other`:其他 + +### 2.2 平台管理员 + +**domain**: `public.platform_admin.role` +- `super_admin`:超级管理员 +- `ops_operator`:运营管理员 +- `read_only_auditor`:只读审计员 + +### 2.3 平台审计与备份导出 + +**domain**: `public.platform_audit.result` +- `SUCCESS`:成功 +- `FAILED`:失败 + +**domain**: `public.backup_schedule.frequency` +- `hourly`:每小时 +- `daily`:每日 +- `weekly`:每周 + +**domain**: `public.backup_schedule.storage_target` +- `local`:本地存储 +- `s3`:Amazon S3 +- `r2`:Cloudflare R2 +- `gcs`:Google Cloud Storage + +**domain**: `public.backup_record.trigger_type` +- `auto`:自动触发 +- `manual`:手动触发 +- `pre_upgrade`:升级前触发 +- `pre_restore`:恢复前触发 + +**domain**: `public.backup_record.status` +- `pending`:待执行 +- `in_progress`:执行中 +- `success`:成功 +- `failed`:失败 + +**domain**: `public.export_task.format` +- `csv`:CSV +- `json`:JSON +- `sql_dump`:SQL 导出 + +**domain**: `public.export_task.status` +- `pending`:待执行 +- `in_progress`:执行中 +- `done`:已完成 +- `failed`:失败 + +### 2.4 升级与发布(Public) + +**domain**: `public.upgrade_event.event_type` +- `upgrade`:升级 +- `rollback`:回滚 + +**domain**: `public.upgrade_event.upgrade_type` +- `A_app`:A类应用升级 +- `B_schema`:B类数据库结构升级 +- `C_feature`:C类功能开关升级 + +**domain**: `public.upgrade_event.strategy` +- `full`:全量发布 +- `canary`:灰度发布 + +**domain**: `public.upgrade_event.status` +- `draft`:草稿 +- `pre_check`:预检查 +- `pre_backup`:预备份 +- `batch_running`:批次执行中 +- `batch_done`:批次完成 +- `halted`:已暂停 +- `succeeded`:已成功 +- `failed`:失败 +- `rollback_running`:回滚中 +- `rolled_back`:已回滚 + +**domain**: `public.upgrade_event.failure_policy` +- `halt_batch`:失败即停止批次 +- `continue`:失败继续 + +**domain**: `public.client_release.platform` +- `win32`:Windows 客户端 + +**domain**: `public.client_release.arch` +- `x64`:x64 架构 +- `arm64`:ARM64 架构 + +**domain**: `public.client_release.release_type` +- `normal`:普通更新 +- `force`:强制更新 + +**domain**: `public.client_release.status` +- `draft`:草稿 +- `published`:已发布 +- `archived`:已归档 + +--- + +## 三、Tenant 固定枚举(模块级,值域统一) + +> 说明:以下字段在 Tenant Schema 中存储,但值域为系统统一标准,属于“全局实现标准”。 + +## 3.1 登录认证(account/login) + +**domain**: `login.user_account.status` +- `active`:启用 +- `disabled`:停用 +- `locked`:锁定 + +**domain**: `login.login_attempt.failure_reason` +- `wrong_password`:用户名或密码错误 +- `wrong_captcha`:验证码错误 +- `account_locked`:账号锁定 +- `account_disabled`:账号停用 +- `tenant_not_found`:租户不存在 + +--- + +## 3.2 组织人事(org) + +**domain**: `org.org_unit.type` +- `company`:公司 +- `division`:事业部 +- `region`:大区 +- `area`:区域 +- `district`:片区 +- `store`:门店 +- `group`:店组 +- `functional`:职能部门 + +**domain**: `org.org_unit.attribute` +- `direct`:直营 +- `franchise`:加盟 + +**domain**: `org.staff.role` +- `agent`:经纪人 +- `store_manager`:店长 +- `area_manager`:区域经理 +- `admin`:系统管理员 +- `operator`:运营/行政 +- `system`:系统账号 + +**domain**: `org.staff.status` +- `active`:在职 +- `probation`:试用 +- `resigned`:离职 +- `frozen`:冻结 + +**domain**: `org.staff_personal_info.gender` +- `male`:男 +- `female`:女 +- `unknown`:未知 + +**domain**: `org.staff_personal_info.id_type` +- `id_card`:身份证 +- `passport`:护照 +- `other`:其他 + +**domain**: `org.staff_transfer.transfer_type` +- `onboard`:入职 +- `transfer`:调动 +- `resign`:离职 +- `rejoin`:复职 +- `supervisor_change`:上级变更 +- `role_change`:角色变更 +- `freeze`:冻结账号 +- `unfreeze`:恢复账号 + +**domain**: `org.staff_account.platform` +- `fonrey`:房睿主账号 +- `58anjuke`:58安居客 +- `cnreic`:中国网络经纪人 +- `wechat_mp`:微信公众号 + +--- + +## 3.3 权限系统(permission) + +**domain**: `permission.module` +- `home`:首页 +- `property`:房源 +- `new_house`:新房 +- `client`:客源 +- `transaction`:交易 +- `data`:数据 +- `marketing`:营销 +- `hr`:人事OA +- `contract`:合同 +- `trinet`:三网 +- `system`:系统 +- `mobile`:移动端 +- `smart_store`:智能门店 +- `recharge`:在线充值 + +**domain**: `permission.value_type` +- `BOOLEAN`:开关型 +- `SCOPE`:范围型 +- `INTEGER`:数值型 + +**domain**: `permission.role_category` +- `agent`:置业顾问 +- `store_manager`:店管 +- `director`:总经 +- `operator`:运营/行政 +- `custom`:自定义 + +**domain**: `permission.scope_level` +- `none`:无 +- `self`:本人 +- `group`:本组 +- `store`:本门店 +- `area`:本区域 +- `region`:本大区 +- `company`:全公司 + +**domain**: `permission.override_mode` +- `REPLACE`:覆盖 +- `RESTRICT`:限制 +- `GRANT`:授予 + +**domain**: `permission.data_scope_type` +- `self`:本人 +- `group`:本组 +- `store`:本门店 +- `area`:本区域 +- `region`:本大区 +- `company`:全公司 +- `custom_unit`:自定义组织单元 + +**domain**: `permission.change_log.target_type` +- `role`:角色 +- `role_permission`:角色权限 +- `staff_role`:员工角色 +- `staff_override`:员工权限覆盖 +- `staff_scope`:员工数据范围 + +**domain**: `permission.change_log.action` +- `create`:创建 +- `update`:更新 +- `delete`:删除 +- `assign`:分配 +- `revoke`:撤销 + +--- + +## 3.4 楼盘区域(complex) + +**domain**: `complex.school.type` +- `primary`:小学 +- `middle`:初中 +- `high`:高中 +- `k9`:九年一贯制 +- `k12`:十二年一贯制 + +**domain**: `complex.school.nature` +- `public`:公立 +- `private`:私立 +- `international`:国际 + +**domain**: `complex.school.level` +- `normal`:普通 +- `key`:重点 +- `top`:名校 + +**domain**: `complex.building_type` +- `slab`:板楼 +- `tower`:塔楼 +- `slab_tower`:板塔结合 + +**domain**: `complex.water_type` +- `civil`:民水 +- `commercial`:商水 + +**domain**: `complex.electricity_type` +- `civil`:民电 +- `commercial`:商电 + +**domain**: `complex.school_zone_type` +- `guaranteed`:对口 +- `reference`:参考 +- `lottery`:摇号 + +**domain**: `complex.photo.category` +- `complex`:楼盘图 +- `layout`:户型图 +- `vr`:VR图 +- `other`:其他 + +--- + +## 3.5 房源(property) + +**domain**: `property.property_type` +- `residential`:住宅 +- `villa`:别墅 +- `commercial_residential`:商住 +- `shop`:商铺 +- `office`:写字楼 +- `other`:其他 + +**domain**: `property.status` +- `for_sale`:出售 +- `for_rent`:出租 +- `for_sale_rent`:租售 +- `suspended`:暂缓 +- `sold_elsewhere`:他售 +- `rented_elsewhere`:他租 +- `sold`:成交 +- `unlisted`:未挂牌 + +**domain**: `property.attribute` +- `public`:公盘 +- `private`:私盘 +- `special`:特盘 +- `sealed`:封盘 + +**domain**: `property.orientation` +- `east`:东 +- `south`:南 +- `west`:西 +- `north`:北 +- `southeast`:东南 +- `northeast`:东北 +- `east_west`:东西 +- `south_north`:南北 +- `northwest`:西北 +- `southwest`:西南 + +**domain**: `property.decoration` +- `rough`:毛坯 +- `plain`:清水 +- `simple`:简装 +- `medium`:中装 +- `fine`:精装 +- `luxury`:豪装 + +**domain**: `property.house_status` +- `owner_occupied`:业主自住 +- `vacant`:空置 +- `tenant_occupied`:租客在住 +- `unknown`:未知 + +**domain**: `property.viewing_time` +- `anytime`:随时看房 +- `by_appointment`:预约看房 +- `inconvenient`:不便看房 + +**domain**: `property.grade` +- `A_urgent`:A(急迫) +- `A`:A +- `B`:B(较强) +- `C`:C(一般) +- `D`:D(较弱) + +**domain**: `property.contact.gender` +- `male`:先生 +- `female`:女士 + +**domain**: `property.contact.identity` +- `owner`:业主 +- `contact`:联系人 +- `subletter`:转租人 +- `tenant`:租客 +- `agent`:代理人 +- `corporate`:企业法人 + +**domain**: `property.listing_history.listing_type` +- `for_sale`:出售挂牌 +- `for_rent`:出租挂牌 + +**domain**: `property.listing_history.status` +- `active`:生效中 +- `ended`:已结束 + +**domain**: `property.follow_log.log_type` +- `written`:手写跟进 +- `modified`:修改跟进 +- `sensitive_op`:敏感操作 +- `sensitive_view`:敏感查看 +- `other`:其他 +- `system`:系统 + +**domain**: `property.follow_log.ai_tag` +- `ai_for_sale`:AI判断可售 +- `ai_not_for_sale`:AI判断不可售 + +**domain**: `property.follow_attachment.file_type` +- `bmp`:BMP +- `jpg`:JPG +- `png`:PNG +- `svg`:SVG +- `gif`:GIF + +**domain**: `property.key.key_type` +- `mechanical`:机械钥匙 +- `password`:密码钥匙 + +**domain**: `property.commission.owner_type` +- `owner`:产权人本人 +- `authorized_third`:授权第三方 + +**domain**: `property.commission.status` +- `active`:有效 +- `expired`:过期 +- `cancelled`:取消 + +**domain**: `property.commission_attachment.category` +- `id_card`:身份证件 +- `property_cert`:产权证明 +- `commission_letter`:委托书 +- `other`:其他 + +**domain**: `property.field_survey.status` +- `draft`:草稿 +- `submitted`:已提交 + +**domain**: `property.survey_photo.category` +- `layout`:户型图 +- `living_room`:客厅 +- `dining_room`:餐厅 +- `bedroom`:卧室 +- `bathroom`:卫生间 +- `kitchen`:厨房 +- `entrance`:入户 +- `balcony`:阳台 +- `study`:书房 +- `indoor_other`:室内其他 +- `outdoor`:室外 + +**domain**: `property.photo.category` +- `cover`:封面 +- `entrance`:入户 +- `living_room`:客厅 +- `dining_room`:餐厅 +- `bedroom`:卧室 +- `bathroom`:卫生间 +- `kitchen`:厨房 +- `balcony`:阳台 +- `study`:书房 +- `indoor_other`:室内其他 +- `outdoor`:室外 +- `panorama`:全景 + +**domain**: `property.attachment.category` +- `id_card`:身份证件 +- `property_cert`:产权证明 +- `commission_letter`:委托书 +- `other`:其他 + +**domain**: `property.number_holder_approval.status` +- `pending`:待审批 +- `approved`:已通过 +- `rejected`:已驳回 + +--- + +## 3.6 客源(client) + +**domain**: `client.client_type` +- `private`:私客 +- `public`:公客 +- `transacted`:成交客 + +**domain**: `client.status` +- `buying`:求购 +- `renting`:求租 +- `buy_or_rent`:租购 +- `suspended`:暂缓 +- `bought`:已购 +- `rented_done`:已租 +- `public`:公客 +- `invalid`:无效 + +**domain**: `client.grade` +- `A`:A(急迫) +- `B`:B(较强) +- `C`:C(一般) +- `D`:D(较弱) +- `E`:E(暂不关注) + +**domain**: `client.property_usage` +- `residential`:住宅 +- `villa`:别墅 +- `commercial_residential`:商住 +- `shop`:商铺 +- `office`:写字楼 +- `other`:其他 + +**domain**: `client.buying_purpose` +- `rigid`:刚需 +- `investment`:投资 +- `school_district`:学区 +- `upgrade`:改善 +- `commercial`:商用 +- `other`:其他 + +**domain**: `client.payment_method` +- `full`:全额 +- `mortgage`:商业贷款 +- `mortgage_fund`:商贷+公积金 +- `fund`:公积金 + +**domain**: `client.properties_owned` +- `none`:无 +- `local_none`:本地无/外地有 +- `local_has`:本地有 + +**domain**: `client.id_type` +- `id_card`:身份证 +- `passport`:护照 +- `hk_macao`:港澳通行证 +- `other`:其他 + +**domain**: `client.transfer_to_public_type` +- `manual`:手动转公 +- `auto`:自动转公 +- `marketing_jump`:营销客跳公 +- `resource_public`:资料客素公 + +**domain**: `client.invalid_reason` +- `invalid_phone`:号码无效 +- `peer_agent`:同行 +- `ad`:广告推销 +- `no_intent`:无意向 +- `other`:其他 + +**domain**: `client.transacted_type` +- `bought`:我购 +- `rented`:我租 + +**domain**: `client.transacted_property_type` +- `second_hand`:二手 +- `new_house`:新房 + +**domain**: `client.activity_level` +- `new_matched`:新配对 +- `active_7d`:7日活跃 +- `active_30d`:30日活跃 +- `active_90d`:90日活跃 +- `expiring`:即将过期 +- `frozen`:暂缓中 +- `invalid`:无效 + +**domain**: `client.contact.gender` +- `male`:先生 +- `female`:女士 + +**domain**: `client.requirement_type` +- `second_hand`:二手 +- `new_house`:新房 +- `rental`:租房 + +**domain**: `client.floor_preference` +- `no_first`:不要一楼 +- `low`:低楼层 +- `mid`:中楼层 +- `high`:高楼层 +- `no_top`:不要顶楼 + +**domain**: `client.orientation` +- `east`:东 +- `south`:南 +- `west`:西 +- `north`:北 + +**domain**: `client.decoration` +- `rough`:毛坯 +- `plain`:清水 +- `simple`:简装 +- `medium`:中装 +- `fine`:精装 +- `luxury`:豪装 + +**domain**: `client.building_age_range` +- `within_5y`:5年内 +- `5_10y`:5-10年 +- `10_15y`:10-15年 +- `15_20y`:15-20年 +- `over_20y`:20年以上 + +**domain**: `client.follow_log.log_type` +- `written`:写入跟进 +- `modified`:修改跟进 +- `sensitive_view`:敏感查看 +- `other`:其他 +- `system`:系统 + +**domain**: `client.viewing.viewing_type` +- `appointment`:预约 +- `viewing`:带看 +- `revisit`:复看 +- `empty`:空看 + +**domain**: `client.viewing.client_intent` +- `interested`:感兴趣 +- `not_interested`:不感兴趣 +- `negotiating`:谈判中 +- `cancelled`:取消 + +**domain**: `client.property_match.match_source` +- `recorded`:录客配房 +- `system`:系统配房 + +**domain**: `client.property_match.match_group` +- `quality_layout`:优质户型 +- `price_reduced`:降价 +- `hot`:热门 +- `newly_listed`:新上 + +**domain**: `client.property_match.status` +- `suggested`:待推送 +- `shared`:已分享 +- `rejected`:已反馈不合适 +- `viewed`:客户已查看 + +**domain**: `client.status_log.change_type` +- `status_change`:改状态 +- `grade_change`:改等级 +- `to_public`:转公客 +- `to_transacted`:转成交 +- `to_invalid`:转无效 +- `owner_change`:改归属人 +- `source_change`:改来源 +- `merge`:合并客源 + +--- + +## 3.7 系统配置(setting) + +**domain**: `setting.tenant_setting.value_type` +- `bool`:布尔 +- `int`:整数 +- `string`:字符串 +- `enum`:枚举 + +**domain**: `setting.field_rule.module` +- `property`:房源 +- `client`:客源(预留) + +**domain**: `setting.field_rule.entity_type`(与 `property.property_type` 对齐) +- `residential`:住宅 +- `villa`:别墅 +- `commercial_residential`:商住 +- `shop`:商铺 +- `office`:写字楼 +- `other`:其他 + +**domain**: `setting.field_rule.trade_status` +- `sale`:出售 +- `rent`:出租 +- `sale_rent`:租售 +- `*`:全部 + +**domain**: `setting.field_rule.requirement` +- `required`:必填 +- `optional`:选填 +- `hidden`:隐藏 + +--- + +## 四、Tenant 可配置枚举字段清单(lookup_items 权威) + +> 以下字段值域由 `lookup_items` 维护,属于租户级配置,不在业务表中写死 `CHECK`。 + +| domain(统一命名) | 对应字段 | 当前状态 | 说明 | +|---|---|---|---| +| `client.source` | `clients.source` | ✅ 已落地 | 客源来源 | +| `client.follow_purpose` | `client_follow_logs.purpose` | ✅ 已落地 | 客源跟进目的 | +| `property.source` | `properties.source` | ✅ 已落地 | 房源来源 | +| `property.follow_purpose` | `follow_logs.purpose` | 🔄 建议统一 | 房源跟进目的(建议与 `client.follow_purpose` 共享或独立分组) | +| `property.commission_type` | `commissions.commission_type` | 🔄 待入组 | 委托类型(独家/非独家等) | +| `client.match_feedback` | `client_property_matches.feedback` | 🔄 待入组 | 配房反馈原因 | +| `org.reward_punish_category` | `staff_reward_punish.category` | 🔄 待入组 | 人事奖惩类别 | + +### 4.1 lookup_groups 规范(Tenant Schema) + +- `module`: 业务模块标识(如 `client` / `property` / `org`) +- `key`: 领域键(如 `source` / `follow_purpose`) +- 同一组内 `value` 不可重复(`UNIQUE(group_id, value)`) +- `is_system = TRUE` 的项禁止物理删除(仅可停用) + +--- + +## 五、统一实现约束 + +1. **固定枚举值不可改名**:只能新增或停用,禁止修改既有 value。 +2. **中文展示从字典取值**:前端/UI 不得硬编码中文。 +3. **可配置枚举不得加固定 CHECK**:防止租户自定义被数据库约束阻断。 +4. **跨模块同名枚举必须复用语义**:如 `status` 在不同领域必须使用 domain 区分,不允许混用。 +5. **缓存规范**: + - 固定枚举:`public:enum_labels:{domain}`(建议 TTL 24h) + - 可配置枚举:`{schema}:setting:lookup:{module}.{key}`(TTL 300s) + +--- + +## 六、变更流程(必须同步) + +新增或修改任一枚举时,必须同时更新: + +1. 本文档 `ENUMS.md` +2. 对应 `DATA_MODEL_*.md` 字段定义(CHECK / 注释 / 业务规则) +3. `enum_labels` 种子数据(若为固定枚举)或 `lookup_groups/items` fixture(若为可配置枚举) +4. 服务层缓存失效逻辑(Redis key) + +--- + +## 七、与 ADR 的一致性说明 + +本文件已对齐以下冻结决策: + +- 固定枚举与可配置枚举双轨并存 +- 状态机和值域以文档为权威来源 +- Tenant 级可配置枚举统一由 `setting` 模块托管 +- Agent 编码前先读枚举标准,禁止各模块自行定义“影子枚举” diff --git a/Project/fonrey/PRD/PRD_MVP.md b/Project/fonrey/PRD/PRD_MVP.md index 4d035bff..80c0af23 100644 --- a/Project/fonrey/PRD/PRD_MVP.md +++ b/Project/fonrey/PRD/PRD_MVP.md @@ -1,280 +1,280 @@ -# Fonrey 房睿 — MVP 范围书 - -**Status**: Draft -**Author**: Product Team -**Last Updated**: 2026-04-24 -**Version**: 1.0 - -> **For AI assistants**: 本文件定义 Phase 1(MVP)的边界。在任何功能实现前,先对照本文确认是否在范围内。范围外的功能禁止在 MVP 阶段实现。 - ---- - -## 1. 产品背景与目标 - -**Fonrey(房睿)** 是一套面向中小型房产经纪公司的 B2B SaaS 管理平台,解决以下核心痛点: - -- 房源/客源信息散乱,全靠人工记录 -- 跟进记录缺失,数据流失严重 -- 重复录入浪费大量经纪人时间 -- 无法支撑 89,000+ 数据量级下的高效房客匹配 - -**MVP 目标**:在一家种子客户(单租户)环境下,完整跑通"录入房源 → 录入客源 → 匹配带看 → 成交"的核心业务链路。 - ---- - -## 2. MVP 核心功能清单(Phase 1 必须实现) - -### 2.1 优先级定义 - -| 优先级 | 含义 | -|--------|------| -| **P0** | MVP 上线前必须完成,阻断核心业务链路 | -| **P1** | MVP 上线后第一个迭代周期内完成 | -| **P2** | 已规划,列入路线图但不阻断上线 | - ---- - -### 2.2 模块优先级矩阵 - -#### 🏠 房源管理 - -| 功能 | 优先级 | 说明 | -|------|--------|------| -| 录入住宅(二手出售/出租) | **P0** | 核心业务入口 | -| 房源列表(二手&租赁) | **P0** | 含筛选、排序、分页 | -| 房源详情页 | **P0** | 含基本信息、产证、交易信息展示 | -| 跟进记录(全部/写入/修改/其他) | **P0** | 含钥匙、委托、实勘 | -| 图片管理(相册上传/分类/排序) | **P0** | 核心房源内容 | -| 业主联系人管理 | **P0** | 含新增/编辑/查看同业主房源 | -| 价格调整(调价/调价记录) | **P0** | 核心运营操作 | -| 房源状态变更(在售/暂缓/成交/下架) | **P0** | 状态机核心 | -| 房源维护完成度(诊断面板) | **P1** | 提升数据质量 | -| 敏感信息跟进(查看权限控制) | **P1** | 需配合权限模块 | -| 附件管理 | **P1** | 非阻断性 | -| 市场报盘 | **P1** | 运营辅助功能 | -| 价格解读 | **P1** | 分析辅助 | -| 录入别墅/商铺/商住/写字楼/其他 | **P2** | 住宅优先,商业类低频 | -| 全部商铺列表 / 全部写字楼列表 | **P2** | 配合 P2 录入功能 | -| 房源广场 | **P2** | 跨租户/公共池功能 | - -#### 🏙️ 楼盘管理 - -| 功能 | 优先级 | 说明 | -|------|--------|------| -| 楼盘列表 + 楼盘详情(楼盘信息/楼栋/结构) | **P0** | 房源数据底座,必须先行 | -| 区域管理(城区/商圈) | **P0** | 房源关联必须 | -| 楼盘照片管理 | **P1** | 数据完善 | -| 楼盘价格走势 | **P1** | 分析辅助 | -| 周边配套(学校管理) | **P1** | 补充信息 | -| 应用数据标准 | **P2** | 明确不做 | - -#### 👥 客源管理 - -| 功能 | 优先级 | 说明 | -|------|--------|------| -| 录入私客(求购/求租) | **P0** | 核心业务 | -| 私客列表(全部/求购/求租) | **P0** | 含筛选、排序 | -| 私客详情(基本信息/需求信息) | **P0** | | -| 跟进记录(全部/写入/修改/其他) | **P0** | | -| 带看管理(预约带看/新增带看) | **P0** | 房客匹配核心 | -| 联系人管理 | **P0** | | -| 客源状态变更(改等级/改状态) | **P0** | | -| 转公客 / 转成交 / 转无效 | **P0** | 生命周期核心 | -| 二手配房(智能匹配) | **P1** | 核心价值,但可后续迭代 | -| 客源解读 | **P1** | AI 辅助分析 | -| 客源信息概览 | **P1** | 汇总视图 | -| 客源收藏夹 | **P1** | 辅助功能 | -| 公客管理 | **P2** | 私客优先 | -| 成交客管理 | **P2** | | -| 暂缓私客 | **P2** | | - -#### 🏢 组织人事 - -| 功能 | 优先级 | 说明 | -|------|--------|------| -| 公司组织结构(部门/门店树) | **P0** | 权限系统基础 | -| 员工列表/员工详情 | **P0** | | -| 员工入职/账号创建 | **P0** | | -| 员工离职 / 调动 | **P1** | | -| 员工通讯录 | **P1** | | -| 异动记录 | **P1** | | -| 奖惩记录 | **P2** | | -| 职务管理 | **P1** | | -| 门店分布地图 | **P2** | | - -#### 🔐 权限管理 - -| 功能 | 优先级 | 说明 | -|------|--------|------| -| 角色管理(预设角色 + 自定义角色) | **P0** | 权限基础 | -| 人员权限列表 | **P0** | | -| 角色批量分配 | **P0** | | -| 功能权限(菜单级) | **P0** | | -| 数据权限(部门/个人/全司) | **P0** | | -| 字段级权限(敏感字段可见性) | **P1** | 配合房源/客源敏感信息 | -| 个人特定权限覆盖 | **P1** | | - -#### 🔑 用户登录 - -| 功能 | 优先级 | 说明 | -|------|--------|------| -| 账号密码登录 | **P0** | | -| 多租户识别(子域名/域名) | **P0** | | -| Token 管理 / 会话超时 | **P0** | | -| 短信验证码登录 | **P1** | | -| 密码重置 | **P1** | | -| 记住登录状态 | **P1** | | - -#### ⚙️ 系统配置 - -| 功能 | 优先级 | 说明 | -|------|--------|------| -| 首页设置 | **P1** | | -| 房源设置(字段必填/自定义字段/标签) | **P0** | 影响录入表单 | -| 相关方设置 | **P1** | | -| 客源设置(基本配置/参数配置) | **P1** | | -| 人事OA设置 | **P2** | | -| 交易设置 | **P2** | | -| 财务设置 | **P2** | | -| 合同设置 | **P2** | | - -#### 🖥️ 系统管理(运营后台) - -| 功能 | 优先级 | 说明 | -|------|--------|------| -| 租户管理(开通/暂停/配置) | **P1** | 单租户种子阶段可手动 | -| 系统健康监控 | **P1** | | -| 操作审计日志 | **P2** | | -| 灰度发布 / 滚动升级 | **P2** | | - -#### 💻 客户端发布 - -| 功能 | 优先级 | 说明 | -|------|--------|------| -| Windows 桌面客户端(内置浏览器) | **P1** | 种子客户使用 Web 端可先行 | -| 自动更新机制 | **P1** | 配合客户端 | - ---- - -## 3. 非目标(Out of Scope — MVP 阶段绝对不做) - -以下功能在 MVP 阶段**明确不实现**,AI 生成代码时不得为这些功能预留接口或引入相关依赖: - -| 功能 | 原因 | -|------|------| -| 移动端适配 | v2 规划 | -| 新房模块(新房管理/新房设置) | 独立模块,后续版本 | -| 合同管理模块 | 独立模块,后续版本 | -| 财务管理/提成结算 | 独立模块,后续版本 | -| 三网发布(安居客/链家/贝壳对接) | 独立模块,后续版本 | -| 数据报表/行程量化 | 独立模块,后续版本 | -| 在线充值/增值服务 | 独立模块,后续版本 | -| 任务管理(OA任务/入职祝福) | 低优先 | -| 考勤管理 | 独立 HR 模块 | -| 审批流程 | 独立 OA 模块 | -| 智慧大屏 / VR换装 | 增值产品 | -| 房源广场(跨租户公共池) | 多租户复杂场景 | - ---- - -## 4. 用户故事(MVP 核心路径) - -### Story 1 — 经纪人录入房源 -> As a **一线经纪人**, -> I want to **快速录入一套二手住宅并上传图片和业主联系方式**, -> So that **这套房源的信息能被团队所有成员找到和跟进**. - -**验收标准**: -- 可在 3 分钟内完成住宅基本信息录入 -- 上传图片后自动按分类展示 -- 录入后即刻出现在房源列表 - ---- - -### Story 2 — 经纪人跟进房源 -> As a **一线经纪人**, -> I want to **对我负责的房源记录每次跟进(面访/电话/钥匙/实勘)**, -> So that **我的跟进历史有据可查,团队不会重复联系同一业主**. - -**验收标准**: -- 跟进记录按时间线倒序展示 -- 支持写入跟进、修改跟进、其他跟进(钥匙/委托/实勘) -- 敏感信息跟进只对有权限的人员可见 - ---- - -### Story 3 — 经纪人录入客源 -> As a **一线经纪人**, -> I want to **录入意向购房/租房客户并跟进其需求变化**, -> So that **我能在合适时机将客户与合适房源匹配**. - -**验收标准**: -- 区分求购/求租两种意向 -- 支持跟进记录 -- 可安排带看并记录带看结果 - ---- - -### Story 4 — 转成交 -> As a **一线经纪人**, -> I want to **将已达成交易的客源标记为"成交"并关联成交房源**, -> So that **成交数据进入系统留存,房源状态自动更新**. - -**验收标准**: -- 转成交时必须选择关联房源 -- 成交后客源状态自动变为"成交客" -- 关联房源状态建议变更为"成交"(可手动确认) - ---- - -### Story 5 — 店长查看团队数据 -> As a **门店店长**, -> I want to **查看本门店所有员工的房源和客源列表**, -> So that **我能掌握团队整体情况并合理分配资源**. - -**验收标准**: -- 数据权限按部门隔离,店长可见本门店数据 -- 可筛选查看特定员工的房源/客源 -- 无法看到其他门店的数据 - ---- - -## 5. MVP 技术边界 - -| 约束 | 决策 | -|------|------| -| 租户数 | **单租户**种子阶段,多租户架构已就位但不激活多租户切换 UI | -| 数据量 | 目标支撑 **89,000 条**房源,测试阶段以 10,000 条压测 | -| 浏览器支持 | Chrome 最新版 / Edge 最新版,不支持 IE | -| 语言 | 简体中文,不做国际化 | -| 移动端 | **不做**,Web 端 Desktop-first | -| 导出 | Excel/CSV 导出通过 Celery 异步,不超时 | - ---- - -## 6. MVP 交付检查清单 - -在 MVP 正式上线前,以下项目必须全部勾选: - -- [ ] 房源录入(住宅)完整流程可用 -- [ ] 房源列表可筛选/排序/分页 -- [ ] 客源录入(求购/求租)完整流程可用 -- [ ] 带看创建与记录可用 -- [ ] 转成交流程可用 -- [ ] 楼盘数据可录入(为房源提供底座) -- [ ] 员工账号可创建/分配角色 -- [ ] 权限隔离:经纪人只能看自己数据,店长能看本店数据 -- [ ] 89,000 条数据量下列表查询 < 2 秒(含索引优化) -- [ ] 图片上传到 Cloudflare R2 可用 -- [ ] 多租户 Schema 隔离验证通过 - ---- - -## 7. 版本路线图 - -| 版本 | 目标 | 核心功能 | -|------|------|---------| -| **v0.1 MVP** | 单租户种子验证 | P0 功能全部上线 | -| **v0.2** | 功能完善 | P1 功能上线,开始多租户测试 | -| **v0.3** | 商业化就绪 | Windows 客户端、多租户正式开放、系统配置完善 | -| **v1.0** | 正式发布 | 新房模块、合同/财务模块路线图确认 | +# Fonrey 房睿 — MVP 范围书 + +**Status**: Draft +**Author**: Product Team +**Last Updated**: 2026-04-24 +**Version**: 1.0 + +> **For AI assistants**: 本文件定义 Phase 1(MVP)的边界。在任何功能实现前,先对照本文确认是否在范围内。范围外的功能禁止在 MVP 阶段实现。 + +--- + +## 1. 产品背景与目标 + +**Fonrey(房睿)** 是一套面向中小型房产经纪公司的 B2B SaaS 管理平台,解决以下核心痛点: + +- 房源/客源信息散乱,全靠人工记录 +- 跟进记录缺失,数据流失严重 +- 重复录入浪费大量经纪人时间 +- 无法支撑 89,000+ 数据量级下的高效房客匹配 + +**MVP 目标**:在一家种子客户(单租户)环境下,完整跑通"录入房源 → 录入客源 → 匹配带看 → 成交"的核心业务链路。 + +--- + +## 2. MVP 核心功能清单(Phase 1 必须实现) + +### 2.1 优先级定义 + +| 优先级 | 含义 | +|--------|------| +| **P0** | MVP 上线前必须完成,阻断核心业务链路 | +| **P1** | MVP 上线后第一个迭代周期内完成 | +| **P2** | 已规划,列入路线图但不阻断上线 | + +--- + +### 2.2 模块优先级矩阵 + +#### 🏠 房源管理 + +| 功能 | 优先级 | 说明 | +|------|--------|------| +| 录入住宅(二手出售/出租) | **P0** | 核心业务入口 | +| 房源列表(二手&租赁) | **P0** | 含筛选、排序、分页 | +| 房源详情页 | **P0** | 含基本信息、产证、交易信息展示 | +| 跟进记录(全部/写入/修改/其他) | **P0** | 含钥匙、委托、实勘 | +| 图片管理(相册上传/分类/排序) | **P0** | 核心房源内容 | +| 业主联系人管理 | **P0** | 含新增/编辑/查看同业主房源 | +| 价格调整(调价/调价记录) | **P0** | 核心运营操作 | +| 房源状态变更(在售/暂缓/成交/下架) | **P0** | 状态机核心 | +| 房源维护完成度(诊断面板) | **P1** | 提升数据质量 | +| 敏感信息跟进(查看权限控制) | **P1** | 需配合权限模块 | +| 附件管理 | **P1** | 非阻断性 | +| 市场报盘 | **P1** | 运营辅助功能 | +| 价格解读 | **P1** | 分析辅助 | +| 录入别墅/商铺/商住/写字楼/其他 | **P2** | 住宅优先,商业类低频 | +| 全部商铺列表 / 全部写字楼列表 | **P2** | 配合 P2 录入功能 | +| 房源广场 | **P2** | 跨租户/公共池功能 | + +#### 🏙️ 楼盘管理 + +| 功能 | 优先级 | 说明 | +|------|--------|------| +| 楼盘列表 + 楼盘详情(楼盘信息/楼栋/结构) | **P0** | 房源数据底座,必须先行 | +| 区域管理(城区/商圈) | **P0** | 房源关联必须 | +| 楼盘照片管理 | **P1** | 数据完善 | +| 楼盘价格走势 | **P1** | 分析辅助 | +| 周边配套(学校管理) | **P1** | 补充信息 | +| 应用数据标准 | **P2** | 明确不做 | + +#### 👥 客源管理 + +| 功能 | 优先级 | 说明 | +|------|--------|------| +| 录入私客(求购/求租) | **P0** | 核心业务 | +| 私客列表(全部/求购/求租) | **P0** | 含筛选、排序 | +| 私客详情(基本信息/需求信息) | **P0** | | +| 跟进记录(全部/写入/修改/其他) | **P0** | | +| 带看管理(预约带看/新增带看) | **P0** | 房客匹配核心 | +| 联系人管理 | **P0** | | +| 客源状态变更(改等级/改状态) | **P0** | | +| 转公客 / 转成交 / 转无效 | **P0** | 生命周期核心 | +| 二手配房(智能匹配) | **P1** | 核心价值,但可后续迭代 | +| 客源解读 | **P1** | AI 辅助分析 | +| 客源信息概览 | **P1** | 汇总视图 | +| 客源收藏夹 | **P1** | 辅助功能 | +| 公客管理 | **P2** | 私客优先 | +| 成交客管理 | **P2** | | +| 暂缓私客 | **P2** | | + +#### 🏢 组织人事 + +| 功能 | 优先级 | 说明 | +|------|--------|------| +| 公司组织结构(部门/门店树) | **P0** | 权限系统基础 | +| 员工列表/员工详情 | **P0** | | +| 员工入职/账号创建 | **P0** | | +| 员工离职 / 调动 | **P1** | | +| 员工通讯录 | **P1** | | +| 异动记录 | **P1** | | +| 奖惩记录 | **P2** | | +| 职务管理 | **P1** | | +| 门店分布地图 | **P2** | | + +#### 🔐 权限管理 + +| 功能 | 优先级 | 说明 | +|------|--------|------| +| 角色管理(预设角色 + 自定义角色) | **P0** | 权限基础 | +| 人员权限列表 | **P0** | | +| 角色批量分配 | **P0** | | +| 功能权限(菜单级) | **P0** | | +| 数据权限(部门/个人/全司) | **P0** | | +| 字段级权限(敏感字段可见性) | **P1** | 配合房源/客源敏感信息 | +| 个人特定权限覆盖 | **P1** | | + +#### 🔑 用户登录 + +| 功能 | 优先级 | 说明 | +|------|--------|------| +| 账号密码登录 | **P0** | | +| 多租户识别(子域名/域名) | **P0** | | +| Token 管理 / 会话超时 | **P0** | | +| 短信验证码登录 | **P1** | | +| 密码重置 | **P1** | | +| 记住登录状态 | **P1** | | + +#### ⚙️ 系统配置 + +| 功能 | 优先级 | 说明 | +|------|--------|------| +| 首页设置 | **P1** | | +| 房源设置(字段必填/自定义字段/标签) | **P0** | 影响录入表单 | +| 相关方设置 | **P1** | | +| 客源设置(基本配置/参数配置) | **P1** | | +| 人事OA设置 | **P2** | | +| 交易设置 | **P2** | | +| 财务设置 | **P2** | | +| 合同设置 | **P2** | | + +#### 🖥️ 系统管理(运营后台) + +| 功能 | 优先级 | 说明 | +|------|--------|------| +| 租户管理(开通/暂停/配置) | **P1** | 单租户种子阶段可手动 | +| 系统健康监控 | **P1** | | +| 操作审计日志 | **P2** | | +| 灰度发布 / 滚动升级 | **P2** | | + +#### 💻 客户端发布 + +| 功能 | 优先级 | 说明 | +|------|--------|------| +| Windows 桌面客户端(内置浏览器) | **P1** | 种子客户使用 Web 端可先行 | +| 自动更新机制 | **P1** | 配合客户端 | + +--- + +## 3. 非目标(Out of Scope — MVP 阶段绝对不做) + +以下功能在 MVP 阶段**明确不实现**,AI 生成代码时不得为这些功能预留接口或引入相关依赖: + +| 功能 | 原因 | +|------|------| +| 移动端适配 | v2 规划 | +| 新房模块(新房管理/新房设置) | 独立模块,后续版本 | +| 合同管理模块 | 独立模块,后续版本 | +| 财务管理/提成结算 | 独立模块,后续版本 | +| 三网发布(安居客/链家/贝壳对接) | 独立模块,后续版本 | +| 数据报表/行程量化 | 独立模块,后续版本 | +| 在线充值/增值服务 | 独立模块,后续版本 | +| 任务管理(OA任务/入职祝福) | 低优先 | +| 考勤管理 | 独立 HR 模块 | +| 审批流程 | 独立 OA 模块 | +| 智慧大屏 / VR换装 | 增值产品 | +| 房源广场(跨租户公共池) | 多租户复杂场景 | + +--- + +## 4. 用户故事(MVP 核心路径) + +### Story 1 — 经纪人录入房源 +> As a **一线经纪人**, +> I want to **快速录入一套二手住宅并上传图片和业主联系方式**, +> So that **这套房源的信息能被团队所有成员找到和跟进**. + +**验收标准**: +- 可在 3 分钟内完成住宅基本信息录入 +- 上传图片后自动按分类展示 +- 录入后即刻出现在房源列表 + +--- + +### Story 2 — 经纪人跟进房源 +> As a **一线经纪人**, +> I want to **对我负责的房源记录每次跟进(面访/电话/钥匙/实勘)**, +> So that **我的跟进历史有据可查,团队不会重复联系同一业主**. + +**验收标准**: +- 跟进记录按时间线倒序展示 +- 支持写入跟进、修改跟进、其他跟进(钥匙/委托/实勘) +- 敏感信息跟进只对有权限的人员可见 + +--- + +### Story 3 — 经纪人录入客源 +> As a **一线经纪人**, +> I want to **录入意向购房/租房客户并跟进其需求变化**, +> So that **我能在合适时机将客户与合适房源匹配**. + +**验收标准**: +- 区分求购/求租两种意向 +- 支持跟进记录 +- 可安排带看并记录带看结果 + +--- + +### Story 4 — 转成交 +> As a **一线经纪人**, +> I want to **将已达成交易的客源标记为"成交"并关联成交房源**, +> So that **成交数据进入系统留存,房源状态自动更新**. + +**验收标准**: +- 转成交时必须选择关联房源 +- 成交后客源状态自动变为"成交客" +- 关联房源状态建议变更为"成交"(可手动确认) + +--- + +### Story 5 — 店长查看团队数据 +> As a **门店店长**, +> I want to **查看本门店所有员工的房源和客源列表**, +> So that **我能掌握团队整体情况并合理分配资源**. + +**验收标准**: +- 数据权限按部门隔离,店长可见本门店数据 +- 可筛选查看特定员工的房源/客源 +- 无法看到其他门店的数据 + +--- + +## 5. MVP 技术边界 + +| 约束 | 决策 | +|------|------| +| 租户数 | **单租户**种子阶段,多租户架构已就位但不激活多租户切换 UI | +| 数据量 | 目标支撑 **89,000 条**房源,测试阶段以 10,000 条压测 | +| 浏览器支持 | Chrome 最新版 / Edge 最新版,不支持 IE | +| 语言 | 简体中文,不做国际化 | +| 移动端 | **不做**,Web 端 Desktop-first | +| 导出 | Excel/CSV 导出通过 Celery 异步,不超时 | + +--- + +## 6. MVP 交付检查清单 + +在 MVP 正式上线前,以下项目必须全部勾选: + +- [ ] 房源录入(住宅)完整流程可用 +- [ ] 房源列表可筛选/排序/分页 +- [ ] 客源录入(求购/求租)完整流程可用 +- [ ] 带看创建与记录可用 +- [ ] 转成交流程可用 +- [ ] 楼盘数据可录入(为房源提供底座) +- [ ] 员工账号可创建/分配角色 +- [ ] 权限隔离:经纪人只能看自己数据,店长能看本店数据 +- [ ] 89,000 条数据量下列表查询 < 2 秒(含索引优化) +- [ ] 图片上传到 Cloudflare R2 可用 +- [ ] 多租户 Schema 隔离验证通过 + +--- + +## 7. 版本路线图 + +| 版本 | 目标 | 核心功能 | +|------|------|---------| +| **v0.1 MVP** | 单租户种子验证 | P0 功能全部上线 | +| **v0.2** | 功能完善 | P1 功能上线,开始多租户测试 | +| **v0.3** | 商业化就绪 | Windows 客户端、多租户正式开放、系统配置完善 | +| **v1.0** | 正式发布 | 新房模块、合同/财务模块路线图确认 | diff --git a/Project/fonrey/PRD/TASK.md b/Project/fonrey/PRD/TASK.md index ea983450..a5b22467 100644 --- a/Project/fonrey/PRD/TASK.md +++ b/Project/fonrey/PRD/TASK.md @@ -56,7 +56,9 @@ | [US-PERMISSION-003](#US-PERMISSION-003-管理员批量为员工分配角色) | 权限管理 | 管理员批量为员工分配角色 | [ ] | | [US-PERMISSION-004](#US-PERMISSION-004-系统执行功能权限控制菜单级) | 权限管理 | 系统执行功能权限控制(菜单级) | [ ] | | [US-PERMISSION-005](#US-PERMISSION-005-系统执行数据权限控制部门个人全司) | 权限管理 | 系统执行数据权限控制(部门/个人/全司) | [ ] | -| [US-SETTING-001](#US-SETTING-001-管理员配置房源相关设置字段必填自定义字段标签) | 系统配置 | 管理员配置房源相关设置(字段必填/自定义字段/标签) | [ ] | +| [US-SETTING-001-A](#US-SETTING-001-A-管理员配置可选枚举值-Lookup-Items) | 系统配置 | 管理员配置可选枚举值(Lookup Items) | [ ] | +| [US-SETTING-001-B](#US-SETTING-001-B-管理员配置房源字段必填规则) | 系统配置 | 管理员配置房源字段必填规则 | [ ] | +| [US-SETTING-001-C](#US-SETTING-001-C-管理员配置客源录入规则) | 系统配置 | 管理员配置客源录入规则(查重范围/必填字段) | [ ] | #### Phase 2 — 增强功能(P1) @@ -437,12 +439,40 @@ ### 系统配置 -##### US-SETTING-001 管理员配置房源相关设置字段必填自定义字段标签 +##### US-SETTING-001-A 管理员配置可选枚举值 Lookup Items -- 参考PRD文档:`Project/fonrey/PRD/系统配置/系统配置.md` - 房源设置(字段必填/自定义字段/标签) -- 参考DATA_MODEL文档:`Project/fonrey/DATA_MODEL/DATA_MODEL_PUBLIC.md` +- 参考PRD文档:`Project/fonrey/PRD/系统配置/系统配置模块PRD.md` - US-SETTING-001-A +- 参考DATA_MODEL文档:`Project/fonrey/DATA_MODEL/DATA_MODEL.md`(待 Atlas 补充 `lookup_items` DDL) - 状态:[ ] -- 验收标准:可配置房源录入表单中哪些字段为必填;可新增自定义字段并在房源表单中展示;标签配置后可在房源筛选中使用;配置变更后房源录入表单实时生效 +- 验收标准: + - 管理员进入「系统设置 → 参数配置」,页面按模块分组展示所有可配置参数项(客源来源、跟进目的、房源来源) + - 可新增自定义选项,新选项追加至列表末尾并立即对经纪人录入下拉生效(刷新后) + - 系统预制选项(`is_system=True`)不可删除,仅可停用;停用后前端下拉不再展示,历史数据保留并标注「已停用」 + - 支持调整选项排序(拖拽或修改排序值),排序变更在保存后前端生效 + - 配置保存时主动失效 Redis 缓存 key `{tenant_schema}:setting:lookup:{module}.{key}`,最长 5 分钟延迟 + +##### US-SETTING-001-B 管理员配置房源字段必填规则 + +- 参考PRD文档:`Project/fonrey/PRD/系统配置/系统配置模块PRD.md` - US-SETTING-001-B +- 参考DATA_MODEL文档:`Project/fonrey/DATA_MODEL/DATA_MODEL.md`(待 Atlas 补充 `field_requirement_rules` DDL)、`Project/fonrey/DATA_MODEL/DATA_MODEL_PROPERTY.md` +- 状态:[ ] +- 验收标准: + - 管理员进入「系统设置 → 房源字段规则」,以「用途 × 交易状态」矩阵展示配置(住宅×出售、住宅×出租) + - 每个字段显示当前规则(必填 / 选填 / 隐藏),以三态 Toggle 或 Radio 形式编辑,保存后生效 + - 规则应用于录入界面:必填字段显示「*」标记,提交时为空则拦截;隐藏字段不渲染 + - 规则变更仅影响新录入,不影响存量房源数据 + - MVP 可配置字段:朝向、装修情况、楼层、建筑面积、套内面积、房型、产权年限、车位数 + +##### US-SETTING-001-C 管理员配置客源录入规则 + +- 参考PRD文档:`Project/fonrey/PRD/系统配置/系统配置模块PRD.md` - US-SETTING-001-C +- 参考DATA_MODEL文档:`Project/fonrey/DATA_MODEL/DATA_MODEL.md`(待 Atlas 补充 `tenant_settings` DDL)、`Project/fonrey/DATA_MODEL/DATA_MODEL_CLIENT.md` +- 状态:[ ] +- 验收标准: + - 管理员进入「系统设置 → 客源规则」,可配置新增私客时的查重范围:本人(默认)/ 本部门 / 全公司 + - 查重规则实时生效:经纪人录入手机号失焦后,系统按当前查重范围加密比对,若重复则提示归属人和录入时间,经纪人可选「仍然录入」或「放弃」 + - 可配置客源必填字段开关(等级、来源默认必填;总价区间、居室需求、购房目的默认选填) + - 配置保存时主动失效 Redis 缓存 key `{tenant_schema}:setting:client_rules`,经纪人下次打开录入界面即应用最新规则 --- diff --git a/Project/fonrey/PRD/权限管理/权限管理模块PRD.md b/Project/fonrey/PRD/权限管理/权限管理模块PRD.md index 49460822..75fb5106 100644 --- a/Project/fonrey/PRD/权限管理/权限管理模块PRD.md +++ b/Project/fonrey/PRD/权限管理/权限管理模块PRD.md @@ -1,623 +1,623 @@ -# PRD: 权限管理模块 -**状态**: Draft -**作者**: 产品经理 -**最后更新**: 2026-04-24(v1.1 锁定多角色合并规则 = 并集/最宽松) -**版本**: 1.1 -**所属系统**: Fonrey 房产经纪管理系统 -**关联模块**: 组织人事管理、房源管理、客源管理、系统设置 - ---- - -## 1. 问题陈述 - -### 背景 - -房产经纪公司普遍存在多层级组织结构(总部 → 事业部 → 大区 → 区域 → 门店 → 店组),不同层级员工的业务职责和数据访问边界差异显著。在缺乏系统化权限管控的情况下,经纪公司面临以下核心痛点: - -- **数据越权访问风险**:经纪人可随意查看他人客户资料、房源联系方式,导致客源保护机制形同虚设,内部业务竞争失控 -- **角色权限配置低效**:每个系统账号独立配置权限,权限变更需逐一操作;人员增加或角色调整时,管理员重复劳动量巨大 -- **权限与岗位不匹配**:系统权限未与职务/职级联动,新员工默认权限可能超出岗位职责边界,造成数据安全隐患 -- **个性化权限需求无法满足**:部分员工因岗位特殊性需要在通用角色基础上增加或收窄特定权限,纯角色制度缺乏灵活性 -- **权限变更缺乏追溯**:权限调整无操作日志,出现数据纠纷时无法追溯是谁、何时、做了什么操作 - -### 目标用户 - -| 角色 | 描述 | 使用频率 | -|------|------|----------| -| 系统管理员 | 负责角色创建、权限配置、人员权限分配及批量操作,是本模块的核心使用者 | 每日 | -| 店长 / 区域经理 | 查看下属员工当前权限,按需发起权限变更申请 | 按需 | -| 一线经纪人 | 受权限约束的数据访问者,感知到功能入口的显示/隐藏变化 | 被动感知 | - ---- - -## 2. 目标与成功指标 - -| 目标 | 指标 | 当前基准 | 目标值 | 衡量周期 | -|------|------|----------|--------|----------| -| 提升权限配置效率 | 完成一次人员权限分配耗时 | 约 20 分钟(估算,逐条配置) | < 2 分钟(批量设置角色) | 上线后 60 天 | -| 降低越权访问事件 | 经纪人越权查看他人客源/联系方式的投诉工单数 | 待统计 | 减少 80% | 上线后 90 天 | -| 提升权限管理透明度 | 管理员查找某员工当前权限配置的操作步骤数 | 待统计 | ≤ 3 步触达 | 上线后 30 天 | -| 降低权限异常率 | 「权限与角色不一致」人员数量 | 待统计 | < 5% | 持续监控 | - ---- - -## 3. 非目标(本期不做) - -- 不包含细化到行级(Row-level)的数据权限(如仅允许查看特定小区的房源),本期数据范围控制以「本人 / 本部门 / 全公司」三档为主 -- 不包含权限申请审批工作流(员工自助申请权限需上级审批),本期由管理员直接操作 -- 不包含操作日志的可视化看板(日志写入,查询能力在后续版本规划) -- 不包含 IP 白名单、登录时段等安全策略配置(安全策略模块另行规划) -- 不包含移动端 App 独立权限配置(移动端权限为 Web 权限的子集,v2 规划) -- 不包含外部合作伙伴(联合门店)账号的跨租户权限体系 - ---- - -## 4. 用户故事与验收标准 - -> **说明**:以下用户故事按核心业务流程顺序排列,覆盖权限管理模块的两个子模块:「权限管理(人员维度)」和「角色管理(角色维度)」。 - ---- - -### Story 1:管理员查看人员权限列表 - -**As** 系统管理员,**I want** 在人员列表中查看全公司所有员工的当前角色与权限状态,**So that** 能快速定位权限异常人员并执行调整。 - -**验收标准**: -- [ ] 页面入口路径:顶部导航「人事」→「组织人事」→「权限管理」,面包屑显示「人事OA / 组织人事 / 权限管理」 -- [ ] 页面包含两个 Tab:「权限管理」(默认选中)和「角色管理」,Tab 切换无需全页刷新 -- [ ] 页面右上角提供「角色权限帮助」入口链接 -- [ ] 列表顶部提供两个快速筛选按钮:「全部员工」和「新房交易列表」 -- [ ] 支持多条件筛选:姓名/员工号(文本输入)、员工部门(下拉选择)、角色(下拉选择)、职务名称(下拉选择) -- [ ] 提供「权限与角色权限不一致」快捷筛选按钮(高亮橙色),点击直接筛选出个人权限已被单独修改、与所属角色权限不一致的人员 -- [ ] 点击「查询」执行筛选,点击「清空条件」重置所有筛选项 -- [ ] 支持批量操作:勾选员工复选框后,点击「批量设置角色」按钮执行批量角色变更 -- [ ] 列表支持「导出」功能,导出当前筛选结果 -- [ ] 员工列表展示列:复选框、员工姓名、工号、部门、职务、角色、管理范围(带「详情」链接)、操作列 -- [ ] 操作列包含:「修改权限」「复制角色」「扩充范围」「范围」共 4 个操作项 -- [ ] 管理范围列显示该员工当前数据可见范围(如「上海豪园店二组」),点击「详情」展开管理范围明细 -- [ ] 列表支持分页:每页显示条数可切换(20 条/页为默认),支持跳转至指定页 - ---- - -### Story 2:管理员为员工批量设置角色 - -**As** 系统管理员,**I want** 同时为多名员工批量设置同一角色,**So that** 在员工入职或组织架构调整时能高效完成权限初始化,无需逐一操作。 - -**验收标准**: -- [ ] 在人员列表中勾选至少一名员工后,「批量设置角色」按钮从禁用变为可点击 -- [ ] 点击「批量设置角色」弹出 Modal 对话框,标题为「批量设置角色」 -- [ ] Modal 内包含必填字段「角色」,为下拉选择器,展示系统中所有可用角色 -- [ ] 确认后系统将所选角色应用至所有勾选员工,操作成功后给出 Toast 成功提示 -- [ ] 若批量操作影响了已有个人自定义权限的员工,系统应给出提醒:「该操作将覆盖所选员工的个人自定义权限,请确认」 -- [ ] 支持取消操作,取消后返回人员列表,已勾选状态保持 - ---- - -### Story 3:管理员修改个人权限 - -**As** 系统管理员,**I want** 为特定员工在角色权限基础上进行个性化权限调整,**So that** 满足因岗位特殊性而需要区别于通用角色权限配置的场景。 - -**验收标准**: -- [ ] 点击人员列表中某员工操作列的「修改权限」后,进入该员工的权限编辑页 -- [ ] 页面顶部展示员工信息:员工姓名 - 所属部门,及当前角色(带下拉箭头,支持直接在此页切换角色) -- [ ] 页面提供权限名称搜索框,支持关键词快速定位权限项 -- [ ] 左侧为模块导航树,包含以下一级模块(均可折叠/展开): - - 首页 - - 房源(含子菜单:二手 & 租赁、小区、商圈精耕、举证 & 检核、挂牌分析、房源广场等) - - 新房 - - 客源 - - 交易 - - 数据 - - 营销 - - 人事OA - - 合同 - - 三网 - - 系统 - - 移动端 - - 智能门店 - - 在线充值 -- [ ] 点击左侧模块导航,右侧内容区切换至对应模块的权限配置 -- [ ] 右侧内容区按功能分组展示权限项,每组包含:分组标题(带开关)、权限项列表 -- [ ] 每个权限项展示:权限名称、说明(权限作用描述)、当前权限值(下拉选项 / 开关 / 数值输入)、「编辑」操作 -- [ ] 权限值类型包含: - - **开关型**(Toggle):开启 / 关闭 - - **范围型**(Select):本人 / 本组 / 本门店 / 本区域 / 全公司 等选项(不同权限项的选项范围不同) - - **数值型**(Number):如每日最多查看联系人数量(0 = 不限制) -- [ ] 模块级总开关(分组标题处的 Toggle)关闭后,该模块下所有权限项均置灰,对应菜单入口隐藏 -- [ ] 「编辑」操作点击后弹出侧边抽屉(Drawer),展示该权限项的详细说明及当前角色应用人数和应用人员名单 -- [ ] 修改权限后,若该员工权限与其角色默认权限存在差异,系统在人员列表中标记「权限与角色权限不一致」 -- [ ] 页面提供「保存」按钮,保存成功后给出成功提示 - ---- - -### Story 4:管理员查看并编辑特定权限项(侧边抽屉) - -**As** 系统管理员,**I want** 在编辑单个权限项时,同时看到该权限当前应用该角色的所有人员名单,**So that** 能了解本次修改的影响范围,再决定是否确认变更。 - -**验收标准**: -- [ ] 点击权限项的「编辑」按钮后,页面右侧滑出 Drawer(不覆盖左侧导航) -- [ ] Drawer 顶部展示:角色名称 + 应用人数(如「角色:高级业务员 | 应用人数: 12」),并提供「查看详情」链接 -- [ ] Drawer 内展示该角色下所有应用人员的姓名和所属部门(格式:姓名-部门名) -- [ ] Drawer 中列出本权限项的配置表格:权限名称、说明、当前值(下拉选择),支持在 Drawer 内直接修改 -- [ ] Drawer 底部提供「保存」和「取消」按钮 -- [ ] 若权限修改后影响角色所有应用人员,系统提示「权限修改后将影响该角色所有应用人员」 -- [ ] 保存后 Drawer 关闭,右侧内容区对应权限项显示更新后的值 - ---- - -### Story 5:管理员查看角色列表 - -**As** 系统管理员,**I want** 在角色管理页查看所有已创建的角色及其基本信息,**So that** 快速了解当前系统的角色体系,并按需编辑或删除。 - -**验收标准**: -- [ ] 点击顶部「角色管理」Tab 切换至角色列表页 -- [ ] 支持多条件筛选:角色名称(文本输入)、角色类别(下拉,全选)、修改时间(日期范围,开始时间 + 结束时间) -- [ ] 点击「查询」执行筛选,点击「清空条件」重置 -- [ ] 操作区提供:「+ 新增角色」按钮(主按钮,橙色)、「批量删除角色」按钮 -- [ ] 显示总记录条数(如「① 共 5 条」) -- [ ] 角色列表展示列:复选框、角色名称(可排序)、角色类别、应用人数(含「查看」链接)、引用该角色配置、创建时间、修改时间、操作列 -- [ ] 操作列包含:「编辑」「删除」「修改日志」 -- [ ] 点击「应用人数」旁的「查看」链接,弹出该角色应用人员名单 -- [ ] 「引用该角色配置」列显示该角色的权限模板是从哪个已有角色复制/引用的(如「初始劝房」) -- [ ] 支持分页,默认 20 条/页 - ---- - -### Story 6:管理员新增角色 - -**As** 系统管理员,**I want** 新建一个角色并配置其权限,**So that** 为新增岗位或特殊职能定义标准权限模板,便于批量分配给对应员工。 - -**验收标准**: -- [ ] 点击「+ 新增角色」按钮弹出 Modal,标题为「添加角色」 -- [ ] Modal 内包含两个必填字段: - - **角色名称**(文本输入,必填) - - **角色类别**(下拉选择,必填):包含「置业顾问」「店管」「总经」等类别选项 -- [ ] Modal 底部提示:「角色类别影响权限,创建后仅本人创建类别可修改」 -- [ ] Modal 操作按钮:「下一步:设置权限」(橙色主按钮)、「取消」 -- [ ] 点击「下一步:设置权限」后,跳转至权限配置详情页,进入角色权限编辑状态 -- [ ] 角色名称未填写或角色类别未选择时,点击「下一步」显示字段级错误提示,阻止提交 -- [ ] 创建成功后,新角色出现在角色列表中,创建时间为当前时间 - ---- - -### Story 7:管理员配置角色权限 - -**As** 系统管理员,**I want** 在角色权限编辑页为角色精细配置各模块的权限开关和数据范围,**So that** 该角色下所有人员自动继承统一的权限配置,减少重复操作。 - -**验收标准**: -- [ ] 角色权限编辑页顶部展示:角色名称、角色类别、「编辑」按钮(支持在线修改角色基本信息) -- [ ] 顶部操作区包含:「导入角色模板」(从已有角色复制权限配置)、「清空」、「保存」按钮 -- [ ] 左侧模块导航结构与人员权限编辑页一致(首页、房源、客源、交易、数据、营销、人事OA、合同、三网、系统、移动端、智能门店、在线充值) -- [ ] 每个模块有「本模块开启」总开关(Toggle),关闭后该模块下所有权限项置灰,菜单入口隐藏 -- [ ] 权限项按业务分组展示,分组有独立的开关和说明文字 -- [ ] 各权限项支持的值类型与人员权限编辑页保持一致(开关型 / 范围型 / 数值型) -- [ ] 支持「导入角色模板」:选择一个已有角色,将其权限配置复制到当前角色(覆盖当前配置,需二次确认) -- [ ] 点击「清空」重置所有权限为默认最小值(需二次确认) -- [ ] 点击「保存」保存权限配置,成功后 Toast 提示;应用该角色的所有员工权限实时生效 - ---- - -### Story 8:管理员修改角色(切换员工角色) - -**As** 系统管理员,**I want** 在员工权限编辑页直接切换员工所属角色,**So that** 快速完成角色变更而不需要退出到人员列表再操作。 - -**验收标准**: -- [ ] 在员工权限编辑页顶部,角色名称旁有下拉箭头,点击展开角色选择器 -- [ ] 角色选择器展示当前系统中所有可用角色(多选,支持同时分配多个角色) -- [ ] 已选择的角色显示为 Tag 形式,可通过 × 取消 -- [ ] 修改角色后,右侧权限配置区自动刷新至新角色权限设置 -- [ ] 若新角色权限与员工当前个人自定义权限存在差异,系统提示是否保留个人自定义权限或以角色权限覆盖 -- [ ] 操作通过「修改角色」弹窗完成,弹窗关闭后权限编辑页显示新角色配置 - ---- - -## 5. 功能说明 - -### 5.1 子模块结构 - -权限管理模块分为两个子模块,均位于「人事OA / 组织人事 / 权限管理」路径下: - -| 子模块 | 功能定位 | -|--------|----------| -| 权限管理(人员视角) | 以员工为维度,查看、分配、个性化调整每个员工的权限 | -| 角色管理(角色视角) | 以角色为维度,创建和配置权限模板,供批量分配使用 | - ---- - -### 5.2 权限模型设计 - -Fonrey 采用 **RBAC(基于角色的访问控制)+ 个人权限叠加** 的混合权限模型: - -``` -员工实际权限 = 角色基础权限 + 个人定制权限覆盖 -``` - -- **角色权限**:角色是权限的"模板",相同角色的员工拥有一致的默认权限 -- **个人权限**:管理员可在角色基础上为特定员工增加或收窄特定权限项,形成个人定制权限 -- **个人权限优先**:当个人权限与角色权限存在差异时,个人权限值生效 -- **不一致标记**:系统在人员列表中标记「权限与角色权限不一致」的员工,方便管理员识别并决定是否同步 - ---- - -### 5.3 权限管理 - 人员列表 - -#### 5.3.1 列表结构 - -| 字段 | 说明 | -|------|------| -| 员工姓名 | 显示姓名,可作为搜索关键词 | -| 工号 | 员工系统工号 | -| 部门 | 当前所属部门 | -| 职务 | 当前职务 | -| 角色 | 当前分配的角色名称 | -| 管理范围 | 该员工数据可见范围(如「上海豪园店二组」),点击「详情」查看明细 | -| 操作 | 修改权限 / 复制角色 / 扩充范围 / 范围 | - -#### 5.3.2 筛选条件 - -| 筛选项 | 类型 | 说明 | -|--------|------|------| -| 搜索 | 文本输入 | 支持姓名、员工号模糊搜索 | -| 员工部门 | 下拉 | 选择部门过滤 | -| 角色 | 下拉 | 按角色名过滤 | -| 职务名称 | 下拉 | 按职务过滤 | -| 权限与角色权限不一致 | 快捷筛选按钮 | 一键筛选个人权限已被单独定制的员工 | - -#### 5.3.3 行级操作说明 - -| 操作 | 说明 | -|------|------| -| 修改权限 | 进入该员工的个人权限编辑页,在角色权限基础上进行个性化调整 | -| 复制角色 | 将当前员工的角色(包含个人定制权限)复制给其他员工 | -| 扩充范围 | 调整该员工的数据可见范围(如从「本组」扩展到「本门店」) | -| 范围 | 查看当前员工的管理范围详情 | - ---- - -### 5.4 权限管理 - 个人权限编辑页 - -#### 5.4.1 模块导航(左侧树形菜单) - -| 模块 | 子菜单(示例) | -|------|---------------| -| 首页 | 首页 | -| 房源 | 二手 & 租赁 / 小区 / 商圈精耕 / 举证 & 检核 / 挂牌分析 / 房源广场 | -| 新房 | 新房楼盘管理 / 新房(置业顾问视角)| -| 客源 | 客源 | -| 交易 | 交易管理 / 二手房售后管理 / 新房售后管理 | -| 数据 | 报表管理 / 资料客统计 / 行程量化 / 房客权益查询 | -| 营销 | 短视频 / 巧克力(营销工具)| -| 人事OA | 组织 / 审批 / 考勤 / 任务 / 内容 | -| 合同 | 合同管理 | -| 三网 | 三网经纪人后台 / 三网授权管理 | -| 系统 | 系统工具 / 业务工具 / 安装与登录授权 | -| 移动端 | 移动端 | -| 智能门店 | 智慧大屏 / VR 换装 | -| 在线充值 | 电话充值 / 增值服务 | - -#### 5.4.2 权限值类型 - -| 类型 | 控件形式 | 示例权限项 | -|------|----------|-----------| -| 开关型 | Toggle(开 / 关) | 今日新上房源是否显示、管理点赞信息和屏蔽点赞 | -| 范围型 | 下拉选择 | 查看私客列表(本人 / 本组 / 本门店 / 全公司)| -| 数值型 | 数字输入框 | 每日最多查看联系人数量(0 = 不限制)| - -#### 5.4.3 客源模块权限分组(参考截图详细梳理) - -客源模块的权限按以下分组组织: - -**私客基础权限** - -| 权限项 | 值类型 | 说明 | -|--------|--------|------| -| 个人私客数量上限 | 数值型 | 999+ = 不限制,0 = 不允许 | -| 查看私客房源进出页(非保护客) | 范围型 | 控制查看客源保护的私客房源进出页 | -| 查看私客房源进出页(保护客) | 范围型 | 控制已保护客的私客房源进出页 | -| 私客转公客 | 范围型 | — | -| 查看私客(保护客) | 范围型 | 查看己经纪人名下的保护客 | -| 查看私客(合保客) | 范围型 | — | -| 编辑私客(保护客) | 范围型 | 编辑本人工员工名下保护的私客信息 | -| 设置取消私客保护范围 | 范围型 | 设置取消相关员工的私客的保护范围 | -| 私客(非保护)承接客 | 范围型 | 私客(非保护客)承接客的范围 | -| 私客(保护客)承接客 | 范围型 | 私客(保护客)承接客的范围 | - -**公客基础权限** - -| 权限项 | 值类型 | 说明 | -|--------|--------|------| -| 公客查看范围 | 范围型 | 控制公客查看范围 | -| 查看公客详情 | 开关型 | — | -| 查看公私特殊客 | 开关型 | 跟公客查看范围和相同,启用后,还可对对查看范围内的公客特殊客,若关闭,无法在公客查看私客 | -| 改公客状态 | 开关型 | — | -| 编辑公客 | 开关型 | — | -| 公客开客资格 | 范围型 | 公客开客资格的范围 | -| 公客详情跟进记录查看范围 | 范围型 | 以跟客人为准,控制跟进记录可看到的跟客历史记录 | - -**成交客基础权限** - -| 权限项 | 值类型 | 说明 | -|--------|--------|------| -| 查看成交(私客类型) | 范围型 | 控制员工查看的成交情况范围 | -| 查看成交(公客类型) | 范围型 | 控制员工查看公客号码的成交来源范围;查看成交权限为本组时,支持查看本组及以上共享层级的成交 | -| 查看成交跟进 | 范围型 | — | -| 成交客查看范围切换 | 开关型 | 跟成交客查看范围和相同,启用后,还可对对查看范围内的成交客实两次切换,若关闭,无法在成交客查看范围以外切换 | -| 查看成交编辑来源人员限来的成交来源字段 | 范围型 | 控制查看成交编辑来源人员填写的成交来源字段 | -| 查看成交客备注 | 范围型 | — | -| 形成成交客列列表 | 开关型 | 成交客列号列表 | - -**联系人基础权限** - -| 权限项 | 值类型 | 说明 | -|--------|--------|------| -| 私客(非保护客)成交查看号码 | 范围型 | 控制查看客源保护的私客、私客的号码范围 | -| 成交客查看号码 | 范围型 | 控制查看成交客的私客的号码范围;支持查看本组及以上共享层级的成交号码 | -| 私客(保护客)号码 | 范围型 | 控制查看保护客的号码范围 | -| 营销短信/成交联系人【联系人名称】最多个数 | 数值型 | — | -| 查看【公客人号码】最多个数 | 数值型 | 控制公客查看号码的范围,999+ = 不限制 | -| 拨打私客(非保护客)电话 | 范围型 | 控制拨打非保护私客的号码范围 | -| 拨打私客(保护客)电话 | 范围型 | 控制拨打保护私客的号码范围 | -| 成交客打电话 | 范围型 | 控制拨打成交客的号码范围 | -| 公客拨打电话 | 开关型 | 控制拨打公客的号码范围 | -| 编辑私客(非保护客)& 成交联系人 | 范围型 | 控制修改保护客、私客的号码信息,有权时对对刷新联系人 | -| 编辑私客(保护客)联系人 | 范围型 | 控制修改保护客联系人号码信息,有权时对对刷新联系人 | -| 编辑私客(非保护客)& 成交联系人号码 | 范围型 | 控制修改保护客、私客的号码信息 | -| 编辑私客(保护客)联系人号码 | 范围型 | — | -| 公客联系人号码 | 范围型 | 控制公客联系人号码范围 | - -**管理权限** - -| 权限项 | 值类型 | 说明 | -|--------|--------|------| -| 前跑源(查看已跑跑前源) | 开关型 | — | -| 不公客查看号码可划打次数限制 | 开关型 | — | -| 手动原客户为公客 | 开关型 | — | -| 某个范围修改关联员工 | 范围型 | 可修改么么范围内的关联员工,包括添加合作人 | -| 批量修改私客 / 公客来源 | 开关型 | — | -| 查看客户客人操作日志 | 开关型 | 启用后,可查看某人评语中手号码模板、客户客人不可过... | -| 不受到拨号手号码打划打次数限制 | 开关型 | — | -| 跑跑跑 | 开关型 | — | -| 查看客户号码,超频强制刷回跑跑跑 | 开关型 | 乙乙,可以查看更改不超限制号码,普通产业学刷回 | -| 查看备案客 | 开关型 | 查看客户学记录 | -| 接管跑跑新客 | 开关型 | 查看化学优化修改客跑跑新接管员工 | -| 拆解员工划协办 | 范围型 | 控制拆解员工人员划协办 | -| 置换跑跑工跑跑户 | 范围型 | 控制置换跑跑客跑跑户范围 | -| 允许合并自己的私跑跑 | 开关型 | 开启后,允许合并入跑客人登录人员合并入本人的私跑跑 | - -**空客** - -| 权限项 | 值类型 | 说明 | -|--------|--------|------| -| 空跑跑单中哪些单元号房号查看 | 下拉选择 | 以置业顾问人为准 | -| 空跑跑跑单查看范围 | 范围型 | 以置业顾问人为准 | -| 空跑跑单中件查看范围 | 范围型 | 以上述人为准 | - -**带看/随行权限** - -| 权限项 | 值类型 | 说明 | -|--------|--------|------| -| 带跑跑新增 | 开关型 | — | -| 带跑跑单中哪些单元号查看 | 范围型 | 以某某人为准 | -| 带跑跑编辑、作废 | 范围型 | — | -| 私客/成交跑跑记录查看范围 | 范围型 | 以某某人为准 | -| 查看单中中体查看 | 范围型 | 以上述人为准 | -| 公客详情跑跑用应用单查看 | 范围型 | 以上述人为准,此时以跑跑员及跑跑项实项目生效 | - -#### 5.4.4 楼盘(小区)模块权限分组 - -**楼盘管理** - -| 权限项 | 值类型 | 说明 | -|--------|--------|------| -| 楼盘管理查看 | 开关型 | 关闭后,则不显示楼盘管理系统模块 | -| 楼盘结构查看 | 开关型 | 开启后,可以查看楼栋-单元-房号数据 | -| 新增/批量新增楼盘 | 开关型 | 允许新增楼盘 | -| 新增/批量新增楼栋、单元、房号 | 开关型 | 新增楼栋、单元、房号数据 | -| 编辑楼盘 | 开关型 | 编辑楼盘 | -| 编辑楼栋/单元/房号信息 | 开关型 | 编辑楼栋、单元、房号信息 | -| 关联标准库/取关 | 开关型 | 若启用,则可关联至标准楼盘、标准楼栋、单元、房号 | -| 删除楼盘 | 开关型 | 删除楼盘 | -| 删除楼盘数据(一并删除房源) | 开关型 | 若启用,则可无视是否存在房源,对不同层级及以下的数据全部删除 | -| 删除楼栋、单元、房号 | 开关型 | 删除楼栋、单元、房号 | -| 合并楼盘 | 开关型 | 若启用,则可合并不同层级楼盘数据(楼栋、单元、房号)| -| 移动楼栋/单元/房号数据 | 开关型 | 若启用,则可将A楼盘楼栋单元及以下数据移动至B楼盘;转移房号不能跨小区进行转移 | -| 锁定/解锁楼盘 | 开关型 | 操作锁定解锁楼盘 | -| 候审房源地址数据查看范围 | 范围型 | 设置员工是否查看部门内其他员工的候审房源地址数据 | -| 楼盘挂牌成交数据 | 开关型 | 开启后,显示楼盘挂牌及成交数据信息 | -| 司内成交明细及套数 | 开关型 | 开启后,显示公司成交的房源明细信息及成交套数 | -| 区域管理 | 开关型 | 若启用,则可对区域商圈进行新增、合并、关联操作 | -| 查看销控盘 | 开关型 | 开启后,可在楼盘管理系统-楼盘里,查看销控盘;注意:员工查看销控盘时房源地址是直接可见的,建议只给管理层开启!!!| -| 查看销控盘时,只可查看本部门作业范围内的楼盘 | 开关型 | 开启后,只可查看本部门作业范围内的楼盘的销控盘;关闭,则跟作业范围无关,「查看销控盘」权限开启即可查看所有楼盘的销控盘;系统管理员不受限制 | - -**楼盘资料管理** - -| 权限项 | 值类型 | 说明 | -|--------|--------|------| -| 楼盘照片 | 开关型 | 开启后,显示楼盘照片列表 | -| 管理照片 | 开关型 | 楼盘管理系统-楼盘照片,包含上传照片、设为封面 | -| 删除照片 | 开关型 | 允许删除照片 | -| 下载照片 | 开关型 | 允许下载照片 | -| 楼盘附件 | 开关型 | 开启后,显示楼盘附件模块 | -| 管理附件 | 开关型 | 允许上传楼盘附件 | -| 下载附件 | 开关型 | 允许下载楼盘附件 | -| 删除附件 | 开关型 | 允许删除楼盘附件 | -| 周边配套 | 开关型 | 开启后,显示周边配套模块 | -| 学校管理列表 | 开关型 | 开启后,显示楼盘管理系统中的学校管理列表 | -| 学校管理 | 开关型 | 包含新增、编辑、删除 | - -**楼盘处理** - -| 权限项 | 值类型 | 说明 | -|--------|--------|------| -| 楼盘反馈列表 | 范围型 | 可查看小区反馈列表的数据范围 | -| 楼盘反馈处理 | 开关型 | 包含处理、不予处理操作 | - ---- - -### 5.5 角色管理 - -#### 5.5.1 角色列表 - -| 字段 | 说明 | -|------|------| -| 角色名称 | 角色唯一名称,支持排序 | -| 角色类别 | 如置业顾问、店管、总经等类别,影响权限可选范围 | -| 应用人数 | 当前使用该角色的员工数量,点击「查看」查看名单 | -| 引用该角色配置 | 该角色权限是基于哪个角色模板创建的 | -| 创建时间 | 角色创建时间 | -| 修改时间 | 最后一次权限修改时间 | - -#### 5.5.2 已知系统内置角色(来自截图) - -| 角色名称 | 角色类别 | 适用场景 | -|----------|----------|----------| -| 刘文龙 | 置业顾问 | 高级业务员 | -| 最大权限角色 | 总经 | 系统管理员/超管角色 | -| 行政人员 | 置业顾问 | 行政人员 | -| 分行经理 | 店管 | 分行级别管理职务 | -| 高级业务员 | 置业顾问 | 标准销售顾问 | - -#### 5.5.3 角色类别说明 - -角色类别在创建时必选,且创建后**不可随意修改**(仅允许创建者修改),原因是角色类别会直接影响权限的可配置范围(不同类别允许的权限上限不同)。 - ---- - -### 5.6 数据范围(管理范围)说明 - -权限管理中「数据范围」是权限系统的核心维度,控制员工可以看到哪个层级的业务数据: - -| 数据范围值 | 说明 | -|-----------|------| -| 本人 | 仅查看/操作自己名下的数据 | -| 本组 | 查看/操作所在店组的数据 | -| 本门店 | 查看/操作所在门店的所有数据 | -| 本区域 | 查看/操作所在区域范围内的数据 | -| 全公司 | 查看/操作公司所有数据(管理层权限)| -| 无 | 无权查看/操作 | - -> 注:不同权限项的可选范围不同,如某权限项只有「本人 / 本门店 / 全公司」三个选项,另一权限项可能有完整的五档选项。具体可选范围以权限编辑页的下拉选项为准。 - ---- - -## 6. 技术考量 - -### 依赖关系 - -| 依赖系统 / 模块 | 用途 | 风险等级 | -|----------------|------|----------| -| 组织人事管理(org 模块) | 员工 / 部门数据读取,权限与员工身份绑定 | 高 | -| django-tenants | 权限数据必须严格按租户 Schema 隔离,严禁跨租户查询 | 高 | -| Redis 缓存 | 员工权限频繁读取,建议缓存员工权限快照,更新时主动失效 | 中 | - -### 已知风险 - -| 风险 | 可能性 | 影响 | 缓解策略 | -|------|--------|------|----------| -| 权限变更实时生效的一致性问题 | 中 | 高 | 角色/个人权限变更后主动清除 Redis 中该员工权限缓存,强制下次请求重新加载 | -| 权限项数量巨大(14+ 模块,数百个权限项)导致编辑页性能问题 | 中 | 中 | 左侧导航按模块懒加载权限数据,避免一次性加载全部权限项 | -| 多角色合并规则(已锁定 v1.1) | - | - | **规则**:同一员工多角色取**并集(最宽松原则)**。BOOLEAN→OR;SCOPE→MAX(self 2%,或出现跨租户数据泄漏问题,立即回滚并通知所有租户管理员。 - ---- - -## 8. 附录 - -### 8.1 截图参考索引 - -| 截图文件 | 完整路径 | 对应功能 | -|---------|---------|---------| -| `权限管理-人员列表.png` | `Project/fonrey/screenshots/权限管理/权限管理-人员列表.png` | 5.3 权限管理人员列表 | -| `权限管理-修改个人权限-客源.png` | `Project/fonrey/screenshots/权限管理/权限管理-修改个人权限-客源.png` | 5.4 个人权限编辑 - 客源模块 | -| `权限管理-人员编辑特定权限.png` | `Project/fonrey/screenshots/权限管理/权限管理-人员编辑特定权限.png` | Story 4 - 侧边 Drawer 编辑单个权限项 | -| `权限管理-批量设置角色.png` | `Project/fonrey/screenshots/权限管理/权限管理-批量设置角色.png` | Story 2 - 批量设置角色 Modal | -| `角色管理-角色列表.png` | `Project/fonrey/screenshots/权限管理/角色管理-角色列表.png` | 5.5.1 角色列表 | -| `角色管理-添加角色1.png` | `Project/fonrey/screenshots/权限管理/原始图片/角色管理-添加角色1.png` | Story 6 - 新增角色 Modal | -| `角色管理-修改角色.png` | `Project/fonrey/screenshots/权限管理/原始图片/角色管理-修改角色.png` | Story 8 - 修改角色(切换员工角色)| -| `权限-房源-小区.png` | `Project/fonrey/screenshots/权限管理/权限-房源-小区.png` | 5.4.4 楼盘(小区)模块权限分组 | -| `权限-客源-客源.png` | `Project/fonrey/screenshots/权限管理/权限-客源-客源.png` | 5.4.3 客源模块权限分组(角色编辑视角)| -| `权限-房源-挂牌分析.png` | `Project/fonrey/screenshots/权限管理/权限-房源-挂牌分析.png` | 5.4 房源 - 挂牌分析模块权限 | -| `权限-房源-商圈精耕.png` | `Project/fonrey/screenshots/权限管理/权限-房源-商圈精耕.png` | 5.4 房源 - 商圈精耕模块权限 | -| `权限-房源-举证检核.png` | `Project/fonrey/screenshots/权限管理/权限-房源-举证检核.png` | 5.4 房源 - 举证检核模块权限 | -| `权限-客源-客源-table.png` | `Project/fonrey/screenshots/权限管理/权限-客源-客源-table.png` | 5.4.3 客源权限表格视图 | -| `权限-合同-合同管理.png` | `Project/fonrey/screenshots/权限管理/权限-合同-合同管理.png` | 5.4 合同管理模块权限 | -| `权限-人事QA-考勤.png` | `Project/fonrey/screenshots/权限管理/权限-人事QA-考勤.png` | 5.4 人事OA - 考勤权限 | -| `权限-人事QA-组织.png` | `Project/fonrey/screenshots/权限管理/权限-人事QA-组织.png` | 5.4 人事OA - 组织权限 | -| `权限-人事QA-审批.png` | `Project/fonrey/screenshots/权限管理/权限-人事QA-审批.png` | 5.4 人事OA - 审批权限 | -| `权限-人事QA-任务.png` | `Project/fonrey/screenshots/权限管理/权限-人事QA-任务.png` | 5.4 人事OA - 任务权限 | -| `权限-人事QA-内容.png` | `Project/fonrey/screenshots/权限管理/权限-人事QA-内容.png` | 5.4 人事OA - 内容权限 | -| `权限-交易-交易管理.jpg` | `Project/fonrey/screenshots/权限管理/权限-交易-交易管理.jpg` | 5.4 交易 - 交易管理权限 | -| `权限-交易-二手房售后管理.png` | `Project/fonrey/screenshots/权限管理/权限-交易-二手房售后管理.png` | 5.4 交易 - 二手房售后管理权限 | -| `权限-交易-新房售后管理.png` | `Project/fonrey/screenshots/权限管理/权限-交易-新房售后管理.png` | 5.4 交易 - 新房售后管理权限 | -| `权限-三网-三网经纪人后台.png` | `Project/fonrey/screenshots/权限管理/权限-三网-三网经纪人后台.png` | 5.4 三网 - 三网经纪人后台权限 | - -### 8.2 权限模块完整导航结构 - -基于截图梳理的权限配置模块树(以角色编辑页左侧导航为准): - -``` -权限配置 -├── 首页 -├── 房源 -│ ├── 二手 & 租赁 -│ ├── 小区(楼盘管理) -│ ├── 商圈精耕 -│ ├── 举证 & 检核 -│ ├── 挂牌分析 -│ └── 房源广场 -├── 新房 -├── 客源 -├── 交易 -│ ├── 交易管理 -│ ├── 二手房售后管理 -│ └── 新房售后管理 -├── 数据 -│ ├── 报表管理 -│ ├── 资料客统计 -│ ├── 行程量化 -│ └── 房客权益查询 -├── 营销 -│ ├── 短视频 -│ └── 巧克力 -├── 人事OA -│ ├── 组织 -│ ├── 审批 -│ ├── 考勤 -│ ├── 任务 -│ └── 内容 -├── 合同 -│ └── 合同管理 -├── 三网 -│ ├── 三网经纪人后台 -│ └── 三网授权管理 -├── 系统 -│ ├── 系统工具 -│ ├── 业务工具 -│ └── 安装与登录授权 -├── 移动端 -├── 智能门店 -│ ├── 智慧大屏 -│ └── VR 换装 -└── 在线充值 - ├── 电话充值 - └── 增值服务 -``` +# PRD: 权限管理模块 +**状态**: Draft +**作者**: 产品经理 +**最后更新**: 2026-04-24(v1.1 锁定多角色合并规则 = 并集/最宽松) +**版本**: 1.1 +**所属系统**: Fonrey 房产经纪管理系统 +**关联模块**: 组织人事管理、房源管理、客源管理、系统设置 + +--- + +## 1. 问题陈述 + +### 背景 + +房产经纪公司普遍存在多层级组织结构(总部 → 事业部 → 大区 → 区域 → 门店 → 店组),不同层级员工的业务职责和数据访问边界差异显著。在缺乏系统化权限管控的情况下,经纪公司面临以下核心痛点: + +- **数据越权访问风险**:经纪人可随意查看他人客户资料、房源联系方式,导致客源保护机制形同虚设,内部业务竞争失控 +- **角色权限配置低效**:每个系统账号独立配置权限,权限变更需逐一操作;人员增加或角色调整时,管理员重复劳动量巨大 +- **权限与岗位不匹配**:系统权限未与职务/职级联动,新员工默认权限可能超出岗位职责边界,造成数据安全隐患 +- **个性化权限需求无法满足**:部分员工因岗位特殊性需要在通用角色基础上增加或收窄特定权限,纯角色制度缺乏灵活性 +- **权限变更缺乏追溯**:权限调整无操作日志,出现数据纠纷时无法追溯是谁、何时、做了什么操作 + +### 目标用户 + +| 角色 | 描述 | 使用频率 | +|------|------|----------| +| 系统管理员 | 负责角色创建、权限配置、人员权限分配及批量操作,是本模块的核心使用者 | 每日 | +| 店长 / 区域经理 | 查看下属员工当前权限,按需发起权限变更申请 | 按需 | +| 一线经纪人 | 受权限约束的数据访问者,感知到功能入口的显示/隐藏变化 | 被动感知 | + +--- + +## 2. 目标与成功指标 + +| 目标 | 指标 | 当前基准 | 目标值 | 衡量周期 | +|------|------|----------|--------|----------| +| 提升权限配置效率 | 完成一次人员权限分配耗时 | 约 20 分钟(估算,逐条配置) | < 2 分钟(批量设置角色) | 上线后 60 天 | +| 降低越权访问事件 | 经纪人越权查看他人客源/联系方式的投诉工单数 | 待统计 | 减少 80% | 上线后 90 天 | +| 提升权限管理透明度 | 管理员查找某员工当前权限配置的操作步骤数 | 待统计 | ≤ 3 步触达 | 上线后 30 天 | +| 降低权限异常率 | 「权限与角色不一致」人员数量 | 待统计 | < 5% | 持续监控 | + +--- + +## 3. 非目标(本期不做) + +- 不包含细化到行级(Row-level)的数据权限(如仅允许查看特定小区的房源),本期数据范围控制以「本人 / 本部门 / 全公司」三档为主 +- 不包含权限申请审批工作流(员工自助申请权限需上级审批),本期由管理员直接操作 +- 不包含操作日志的可视化看板(日志写入,查询能力在后续版本规划) +- 不包含 IP 白名单、登录时段等安全策略配置(安全策略模块另行规划) +- 不包含移动端 App 独立权限配置(移动端权限为 Web 权限的子集,v2 规划) +- 不包含外部合作伙伴(联合门店)账号的跨租户权限体系 + +--- + +## 4. 用户故事与验收标准 + +> **说明**:以下用户故事按核心业务流程顺序排列,覆盖权限管理模块的两个子模块:「权限管理(人员维度)」和「角色管理(角色维度)」。 + +--- + +### Story 1:管理员查看人员权限列表 + +**As** 系统管理员,**I want** 在人员列表中查看全公司所有员工的当前角色与权限状态,**So that** 能快速定位权限异常人员并执行调整。 + +**验收标准**: +- [ ] 页面入口路径:顶部导航「人事」→「组织人事」→「权限管理」,面包屑显示「人事OA / 组织人事 / 权限管理」 +- [ ] 页面包含两个 Tab:「权限管理」(默认选中)和「角色管理」,Tab 切换无需全页刷新 +- [ ] 页面右上角提供「角色权限帮助」入口链接 +- [ ] 列表顶部提供两个快速筛选按钮:「全部员工」和「新房交易列表」 +- [ ] 支持多条件筛选:姓名/员工号(文本输入)、员工部门(下拉选择)、角色(下拉选择)、职务名称(下拉选择) +- [ ] 提供「权限与角色权限不一致」快捷筛选按钮(高亮橙色),点击直接筛选出个人权限已被单独修改、与所属角色权限不一致的人员 +- [ ] 点击「查询」执行筛选,点击「清空条件」重置所有筛选项 +- [ ] 支持批量操作:勾选员工复选框后,点击「批量设置角色」按钮执行批量角色变更 +- [ ] 列表支持「导出」功能,导出当前筛选结果 +- [ ] 员工列表展示列:复选框、员工姓名、工号、部门、职务、角色、管理范围(带「详情」链接)、操作列 +- [ ] 操作列包含:「修改权限」「复制角色」「扩充范围」「范围」共 4 个操作项 +- [ ] 管理范围列显示该员工当前数据可见范围(如「上海豪园店二组」),点击「详情」展开管理范围明细 +- [ ] 列表支持分页:每页显示条数可切换(20 条/页为默认),支持跳转至指定页 + +--- + +### Story 2:管理员为员工批量设置角色 + +**As** 系统管理员,**I want** 同时为多名员工批量设置同一角色,**So that** 在员工入职或组织架构调整时能高效完成权限初始化,无需逐一操作。 + +**验收标准**: +- [ ] 在人员列表中勾选至少一名员工后,「批量设置角色」按钮从禁用变为可点击 +- [ ] 点击「批量设置角色」弹出 Modal 对话框,标题为「批量设置角色」 +- [ ] Modal 内包含必填字段「角色」,为下拉选择器,展示系统中所有可用角色 +- [ ] 确认后系统将所选角色应用至所有勾选员工,操作成功后给出 Toast 成功提示 +- [ ] 若批量操作影响了已有个人自定义权限的员工,系统应给出提醒:「该操作将覆盖所选员工的个人自定义权限,请确认」 +- [ ] 支持取消操作,取消后返回人员列表,已勾选状态保持 + +--- + +### Story 3:管理员修改个人权限 + +**As** 系统管理员,**I want** 为特定员工在角色权限基础上进行个性化权限调整,**So that** 满足因岗位特殊性而需要区别于通用角色权限配置的场景。 + +**验收标准**: +- [ ] 点击人员列表中某员工操作列的「修改权限」后,进入该员工的权限编辑页 +- [ ] 页面顶部展示员工信息:员工姓名 - 所属部门,及当前角色(带下拉箭头,支持直接在此页切换角色) +- [ ] 页面提供权限名称搜索框,支持关键词快速定位权限项 +- [ ] 左侧为模块导航树,包含以下一级模块(均可折叠/展开): + - 首页 + - 房源(含子菜单:二手 & 租赁、小区、商圈精耕、举证 & 检核、挂牌分析、房源广场等) + - 新房 + - 客源 + - 交易 + - 数据 + - 营销 + - 人事OA + - 合同 + - 三网 + - 系统 + - 移动端 + - 智能门店 + - 在线充值 +- [ ] 点击左侧模块导航,右侧内容区切换至对应模块的权限配置 +- [ ] 右侧内容区按功能分组展示权限项,每组包含:分组标题(带开关)、权限项列表 +- [ ] 每个权限项展示:权限名称、说明(权限作用描述)、当前权限值(下拉选项 / 开关 / 数值输入)、「编辑」操作 +- [ ] 权限值类型包含: + - **开关型**(Toggle):开启 / 关闭 + - **范围型**(Select):本人 / 本组 / 本门店 / 本区域 / 全公司 等选项(不同权限项的选项范围不同) + - **数值型**(Number):如每日最多查看联系人数量(0 = 不限制) +- [ ] 模块级总开关(分组标题处的 Toggle)关闭后,该模块下所有权限项均置灰,对应菜单入口隐藏 +- [ ] 「编辑」操作点击后弹出侧边抽屉(Drawer),展示该权限项的详细说明及当前角色应用人数和应用人员名单 +- [ ] 修改权限后,若该员工权限与其角色默认权限存在差异,系统在人员列表中标记「权限与角色权限不一致」 +- [ ] 页面提供「保存」按钮,保存成功后给出成功提示 + +--- + +### Story 4:管理员查看并编辑特定权限项(侧边抽屉) + +**As** 系统管理员,**I want** 在编辑单个权限项时,同时看到该权限当前应用该角色的所有人员名单,**So that** 能了解本次修改的影响范围,再决定是否确认变更。 + +**验收标准**: +- [ ] 点击权限项的「编辑」按钮后,页面右侧滑出 Drawer(不覆盖左侧导航) +- [ ] Drawer 顶部展示:角色名称 + 应用人数(如「角色:高级业务员 | 应用人数: 12」),并提供「查看详情」链接 +- [ ] Drawer 内展示该角色下所有应用人员的姓名和所属部门(格式:姓名-部门名) +- [ ] Drawer 中列出本权限项的配置表格:权限名称、说明、当前值(下拉选择),支持在 Drawer 内直接修改 +- [ ] Drawer 底部提供「保存」和「取消」按钮 +- [ ] 若权限修改后影响角色所有应用人员,系统提示「权限修改后将影响该角色所有应用人员」 +- [ ] 保存后 Drawer 关闭,右侧内容区对应权限项显示更新后的值 + +--- + +### Story 5:管理员查看角色列表 + +**As** 系统管理员,**I want** 在角色管理页查看所有已创建的角色及其基本信息,**So that** 快速了解当前系统的角色体系,并按需编辑或删除。 + +**验收标准**: +- [ ] 点击顶部「角色管理」Tab 切换至角色列表页 +- [ ] 支持多条件筛选:角色名称(文本输入)、角色类别(下拉,全选)、修改时间(日期范围,开始时间 + 结束时间) +- [ ] 点击「查询」执行筛选,点击「清空条件」重置 +- [ ] 操作区提供:「+ 新增角色」按钮(主按钮,橙色)、「批量删除角色」按钮 +- [ ] 显示总记录条数(如「① 共 5 条」) +- [ ] 角色列表展示列:复选框、角色名称(可排序)、角色类别、应用人数(含「查看」链接)、引用该角色配置、创建时间、修改时间、操作列 +- [ ] 操作列包含:「编辑」「删除」「修改日志」 +- [ ] 点击「应用人数」旁的「查看」链接,弹出该角色应用人员名单 +- [ ] 「引用该角色配置」列显示该角色的权限模板是从哪个已有角色复制/引用的(如「初始劝房」) +- [ ] 支持分页,默认 20 条/页 + +--- + +### Story 6:管理员新增角色 + +**As** 系统管理员,**I want** 新建一个角色并配置其权限,**So that** 为新增岗位或特殊职能定义标准权限模板,便于批量分配给对应员工。 + +**验收标准**: +- [ ] 点击「+ 新增角色」按钮弹出 Modal,标题为「添加角色」 +- [ ] Modal 内包含两个必填字段: + - **角色名称**(文本输入,必填) + - **角色类别**(下拉选择,必填):包含「置业顾问」「店管」「总经」等类别选项 +- [ ] Modal 底部提示:「角色类别影响权限,创建后仅本人创建类别可修改」 +- [ ] Modal 操作按钮:「下一步:设置权限」(橙色主按钮)、「取消」 +- [ ] 点击「下一步:设置权限」后,跳转至权限配置详情页,进入角色权限编辑状态 +- [ ] 角色名称未填写或角色类别未选择时,点击「下一步」显示字段级错误提示,阻止提交 +- [ ] 创建成功后,新角色出现在角色列表中,创建时间为当前时间 + +--- + +### Story 7:管理员配置角色权限 + +**As** 系统管理员,**I want** 在角色权限编辑页为角色精细配置各模块的权限开关和数据范围,**So that** 该角色下所有人员自动继承统一的权限配置,减少重复操作。 + +**验收标准**: +- [ ] 角色权限编辑页顶部展示:角色名称、角色类别、「编辑」按钮(支持在线修改角色基本信息) +- [ ] 顶部操作区包含:「导入角色模板」(从已有角色复制权限配置)、「清空」、「保存」按钮 +- [ ] 左侧模块导航结构与人员权限编辑页一致(首页、房源、客源、交易、数据、营销、人事OA、合同、三网、系统、移动端、智能门店、在线充值) +- [ ] 每个模块有「本模块开启」总开关(Toggle),关闭后该模块下所有权限项置灰,菜单入口隐藏 +- [ ] 权限项按业务分组展示,分组有独立的开关和说明文字 +- [ ] 各权限项支持的值类型与人员权限编辑页保持一致(开关型 / 范围型 / 数值型) +- [ ] 支持「导入角色模板」:选择一个已有角色,将其权限配置复制到当前角色(覆盖当前配置,需二次确认) +- [ ] 点击「清空」重置所有权限为默认最小值(需二次确认) +- [ ] 点击「保存」保存权限配置,成功后 Toast 提示;应用该角色的所有员工权限实时生效 + +--- + +### Story 8:管理员修改角色(切换员工角色) + +**As** 系统管理员,**I want** 在员工权限编辑页直接切换员工所属角色,**So that** 快速完成角色变更而不需要退出到人员列表再操作。 + +**验收标准**: +- [ ] 在员工权限编辑页顶部,角色名称旁有下拉箭头,点击展开角色选择器 +- [ ] 角色选择器展示当前系统中所有可用角色(多选,支持同时分配多个角色) +- [ ] 已选择的角色显示为 Tag 形式,可通过 × 取消 +- [ ] 修改角色后,右侧权限配置区自动刷新至新角色权限设置 +- [ ] 若新角色权限与员工当前个人自定义权限存在差异,系统提示是否保留个人自定义权限或以角色权限覆盖 +- [ ] 操作通过「修改角色」弹窗完成,弹窗关闭后权限编辑页显示新角色配置 + +--- + +## 5. 功能说明 + +### 5.1 子模块结构 + +权限管理模块分为两个子模块,均位于「人事OA / 组织人事 / 权限管理」路径下: + +| 子模块 | 功能定位 | +|--------|----------| +| 权限管理(人员视角) | 以员工为维度,查看、分配、个性化调整每个员工的权限 | +| 角色管理(角色视角) | 以角色为维度,创建和配置权限模板,供批量分配使用 | + +--- + +### 5.2 权限模型设计 + +Fonrey 采用 **RBAC(基于角色的访问控制)+ 个人权限叠加** 的混合权限模型: + +``` +员工实际权限 = 角色基础权限 + 个人定制权限覆盖 +``` + +- **角色权限**:角色是权限的"模板",相同角色的员工拥有一致的默认权限 +- **个人权限**:管理员可在角色基础上为特定员工增加或收窄特定权限项,形成个人定制权限 +- **个人权限优先**:当个人权限与角色权限存在差异时,个人权限值生效 +- **不一致标记**:系统在人员列表中标记「权限与角色权限不一致」的员工,方便管理员识别并决定是否同步 + +--- + +### 5.3 权限管理 - 人员列表 + +#### 5.3.1 列表结构 + +| 字段 | 说明 | +|------|------| +| 员工姓名 | 显示姓名,可作为搜索关键词 | +| 工号 | 员工系统工号 | +| 部门 | 当前所属部门 | +| 职务 | 当前职务 | +| 角色 | 当前分配的角色名称 | +| 管理范围 | 该员工数据可见范围(如「上海豪园店二组」),点击「详情」查看明细 | +| 操作 | 修改权限 / 复制角色 / 扩充范围 / 范围 | + +#### 5.3.2 筛选条件 + +| 筛选项 | 类型 | 说明 | +|--------|------|------| +| 搜索 | 文本输入 | 支持姓名、员工号模糊搜索 | +| 员工部门 | 下拉 | 选择部门过滤 | +| 角色 | 下拉 | 按角色名过滤 | +| 职务名称 | 下拉 | 按职务过滤 | +| 权限与角色权限不一致 | 快捷筛选按钮 | 一键筛选个人权限已被单独定制的员工 | + +#### 5.3.3 行级操作说明 + +| 操作 | 说明 | +|------|------| +| 修改权限 | 进入该员工的个人权限编辑页,在角色权限基础上进行个性化调整 | +| 复制角色 | 将当前员工的角色(包含个人定制权限)复制给其他员工 | +| 扩充范围 | 调整该员工的数据可见范围(如从「本组」扩展到「本门店」) | +| 范围 | 查看当前员工的管理范围详情 | + +--- + +### 5.4 权限管理 - 个人权限编辑页 + +#### 5.4.1 模块导航(左侧树形菜单) + +| 模块 | 子菜单(示例) | +|------|---------------| +| 首页 | 首页 | +| 房源 | 二手 & 租赁 / 小区 / 商圈精耕 / 举证 & 检核 / 挂牌分析 / 房源广场 | +| 新房 | 新房楼盘管理 / 新房(置业顾问视角)| +| 客源 | 客源 | +| 交易 | 交易管理 / 二手房售后管理 / 新房售后管理 | +| 数据 | 报表管理 / 资料客统计 / 行程量化 / 房客权益查询 | +| 营销 | 短视频 / 巧克力(营销工具)| +| 人事OA | 组织 / 审批 / 考勤 / 任务 / 内容 | +| 合同 | 合同管理 | +| 三网 | 三网经纪人后台 / 三网授权管理 | +| 系统 | 系统工具 / 业务工具 / 安装与登录授权 | +| 移动端 | 移动端 | +| 智能门店 | 智慧大屏 / VR 换装 | +| 在线充值 | 电话充值 / 增值服务 | + +#### 5.4.2 权限值类型 + +| 类型 | 控件形式 | 示例权限项 | +|------|----------|-----------| +| 开关型 | Toggle(开 / 关) | 今日新上房源是否显示、管理点赞信息和屏蔽点赞 | +| 范围型 | 下拉选择 | 查看私客列表(本人 / 本组 / 本门店 / 全公司)| +| 数值型 | 数字输入框 | 每日最多查看联系人数量(0 = 不限制)| + +#### 5.4.3 客源模块权限分组(参考截图详细梳理) + +客源模块的权限按以下分组组织: + +**私客基础权限** + +| 权限项 | 值类型 | 说明 | +|--------|--------|------| +| 个人私客数量上限 | 数值型 | 999+ = 不限制,0 = 不允许 | +| 查看私客房源进出页(非保护客) | 范围型 | 控制查看客源保护的私客房源进出页 | +| 查看私客房源进出页(保护客) | 范围型 | 控制已保护客的私客房源进出页 | +| 私客转公客 | 范围型 | — | +| 查看私客(保护客) | 范围型 | 查看己经纪人名下的保护客 | +| 查看私客(合保客) | 范围型 | — | +| 编辑私客(保护客) | 范围型 | 编辑本人工员工名下保护的私客信息 | +| 设置取消私客保护范围 | 范围型 | 设置取消相关员工的私客的保护范围 | +| 私客(非保护)承接客 | 范围型 | 私客(非保护客)承接客的范围 | +| 私客(保护客)承接客 | 范围型 | 私客(保护客)承接客的范围 | + +**公客基础权限** + +| 权限项 | 值类型 | 说明 | +|--------|--------|------| +| 公客查看范围 | 范围型 | 控制公客查看范围 | +| 查看公客详情 | 开关型 | — | +| 查看公私特殊客 | 开关型 | 跟公客查看范围和相同,启用后,还可对对查看范围内的公客特殊客,若关闭,无法在公客查看私客 | +| 改公客状态 | 开关型 | — | +| 编辑公客 | 开关型 | — | +| 公客开客资格 | 范围型 | 公客开客资格的范围 | +| 公客详情跟进记录查看范围 | 范围型 | 以跟客人为准,控制跟进记录可看到的跟客历史记录 | + +**成交客基础权限** + +| 权限项 | 值类型 | 说明 | +|--------|--------|------| +| 查看成交(私客类型) | 范围型 | 控制员工查看的成交情况范围 | +| 查看成交(公客类型) | 范围型 | 控制员工查看公客号码的成交来源范围;查看成交权限为本组时,支持查看本组及以上共享层级的成交 | +| 查看成交跟进 | 范围型 | — | +| 成交客查看范围切换 | 开关型 | 跟成交客查看范围和相同,启用后,还可对对查看范围内的成交客实两次切换,若关闭,无法在成交客查看范围以外切换 | +| 查看成交编辑来源人员限来的成交来源字段 | 范围型 | 控制查看成交编辑来源人员填写的成交来源字段 | +| 查看成交客备注 | 范围型 | — | +| 形成成交客列列表 | 开关型 | 成交客列号列表 | + +**联系人基础权限** + +| 权限项 | 值类型 | 说明 | +|--------|--------|------| +| 私客(非保护客)成交查看号码 | 范围型 | 控制查看客源保护的私客、私客的号码范围 | +| 成交客查看号码 | 范围型 | 控制查看成交客的私客的号码范围;支持查看本组及以上共享层级的成交号码 | +| 私客(保护客)号码 | 范围型 | 控制查看保护客的号码范围 | +| 营销短信/成交联系人【联系人名称】最多个数 | 数值型 | — | +| 查看【公客人号码】最多个数 | 数值型 | 控制公客查看号码的范围,999+ = 不限制 | +| 拨打私客(非保护客)电话 | 范围型 | 控制拨打非保护私客的号码范围 | +| 拨打私客(保护客)电话 | 范围型 | 控制拨打保护私客的号码范围 | +| 成交客打电话 | 范围型 | 控制拨打成交客的号码范围 | +| 公客拨打电话 | 开关型 | 控制拨打公客的号码范围 | +| 编辑私客(非保护客)& 成交联系人 | 范围型 | 控制修改保护客、私客的号码信息,有权时对对刷新联系人 | +| 编辑私客(保护客)联系人 | 范围型 | 控制修改保护客联系人号码信息,有权时对对刷新联系人 | +| 编辑私客(非保护客)& 成交联系人号码 | 范围型 | 控制修改保护客、私客的号码信息 | +| 编辑私客(保护客)联系人号码 | 范围型 | — | +| 公客联系人号码 | 范围型 | 控制公客联系人号码范围 | + +**管理权限** + +| 权限项 | 值类型 | 说明 | +|--------|--------|------| +| 前跑源(查看已跑跑前源) | 开关型 | — | +| 不公客查看号码可划打次数限制 | 开关型 | — | +| 手动原客户为公客 | 开关型 | — | +| 某个范围修改关联员工 | 范围型 | 可修改么么范围内的关联员工,包括添加合作人 | +| 批量修改私客 / 公客来源 | 开关型 | — | +| 查看客户客人操作日志 | 开关型 | 启用后,可查看某人评语中手号码模板、客户客人不可过... | +| 不受到拨号手号码打划打次数限制 | 开关型 | — | +| 跑跑跑 | 开关型 | — | +| 查看客户号码,超频强制刷回跑跑跑 | 开关型 | 乙乙,可以查看更改不超限制号码,普通产业学刷回 | +| 查看备案客 | 开关型 | 查看客户学记录 | +| 接管跑跑新客 | 开关型 | 查看化学优化修改客跑跑新接管员工 | +| 拆解员工划协办 | 范围型 | 控制拆解员工人员划协办 | +| 置换跑跑工跑跑户 | 范围型 | 控制置换跑跑客跑跑户范围 | +| 允许合并自己的私跑跑 | 开关型 | 开启后,允许合并入跑客人登录人员合并入本人的私跑跑 | + +**空客** + +| 权限项 | 值类型 | 说明 | +|--------|--------|------| +| 空跑跑单中哪些单元号房号查看 | 下拉选择 | 以置业顾问人为准 | +| 空跑跑跑单查看范围 | 范围型 | 以置业顾问人为准 | +| 空跑跑单中件查看范围 | 范围型 | 以上述人为准 | + +**带看/随行权限** + +| 权限项 | 值类型 | 说明 | +|--------|--------|------| +| 带跑跑新增 | 开关型 | — | +| 带跑跑单中哪些单元号查看 | 范围型 | 以某某人为准 | +| 带跑跑编辑、作废 | 范围型 | — | +| 私客/成交跑跑记录查看范围 | 范围型 | 以某某人为准 | +| 查看单中中体查看 | 范围型 | 以上述人为准 | +| 公客详情跑跑用应用单查看 | 范围型 | 以上述人为准,此时以跑跑员及跑跑项实项目生效 | + +#### 5.4.4 楼盘(小区)模块权限分组 + +**楼盘管理** + +| 权限项 | 值类型 | 说明 | +|--------|--------|------| +| 楼盘管理查看 | 开关型 | 关闭后,则不显示楼盘管理系统模块 | +| 楼盘结构查看 | 开关型 | 开启后,可以查看楼栋-单元-房号数据 | +| 新增/批量新增楼盘 | 开关型 | 允许新增楼盘 | +| 新增/批量新增楼栋、单元、房号 | 开关型 | 新增楼栋、单元、房号数据 | +| 编辑楼盘 | 开关型 | 编辑楼盘 | +| 编辑楼栋/单元/房号信息 | 开关型 | 编辑楼栋、单元、房号信息 | +| 关联标准库/取关 | 开关型 | 若启用,则可关联至标准楼盘、标准楼栋、单元、房号 | +| 删除楼盘 | 开关型 | 删除楼盘 | +| 删除楼盘数据(一并删除房源) | 开关型 | 若启用,则可无视是否存在房源,对不同层级及以下的数据全部删除 | +| 删除楼栋、单元、房号 | 开关型 | 删除楼栋、单元、房号 | +| 合并楼盘 | 开关型 | 若启用,则可合并不同层级楼盘数据(楼栋、单元、房号)| +| 移动楼栋/单元/房号数据 | 开关型 | 若启用,则可将A楼盘楼栋单元及以下数据移动至B楼盘;转移房号不能跨小区进行转移 | +| 锁定/解锁楼盘 | 开关型 | 操作锁定解锁楼盘 | +| 候审房源地址数据查看范围 | 范围型 | 设置员工是否查看部门内其他员工的候审房源地址数据 | +| 楼盘挂牌成交数据 | 开关型 | 开启后,显示楼盘挂牌及成交数据信息 | +| 司内成交明细及套数 | 开关型 | 开启后,显示公司成交的房源明细信息及成交套数 | +| 区域管理 | 开关型 | 若启用,则可对区域商圈进行新增、合并、关联操作 | +| 查看销控盘 | 开关型 | 开启后,可在楼盘管理系统-楼盘里,查看销控盘;注意:员工查看销控盘时房源地址是直接可见的,建议只给管理层开启!!!| +| 查看销控盘时,只可查看本部门作业范围内的楼盘 | 开关型 | 开启后,只可查看本部门作业范围内的楼盘的销控盘;关闭,则跟作业范围无关,「查看销控盘」权限开启即可查看所有楼盘的销控盘;系统管理员不受限制 | + +**楼盘资料管理** + +| 权限项 | 值类型 | 说明 | +|--------|--------|------| +| 楼盘照片 | 开关型 | 开启后,显示楼盘照片列表 | +| 管理照片 | 开关型 | 楼盘管理系统-楼盘照片,包含上传照片、设为封面 | +| 删除照片 | 开关型 | 允许删除照片 | +| 下载照片 | 开关型 | 允许下载照片 | +| 楼盘附件 | 开关型 | 开启后,显示楼盘附件模块 | +| 管理附件 | 开关型 | 允许上传楼盘附件 | +| 下载附件 | 开关型 | 允许下载楼盘附件 | +| 删除附件 | 开关型 | 允许删除楼盘附件 | +| 周边配套 | 开关型 | 开启后,显示周边配套模块 | +| 学校管理列表 | 开关型 | 开启后,显示楼盘管理系统中的学校管理列表 | +| 学校管理 | 开关型 | 包含新增、编辑、删除 | + +**楼盘处理** + +| 权限项 | 值类型 | 说明 | +|--------|--------|------| +| 楼盘反馈列表 | 范围型 | 可查看小区反馈列表的数据范围 | +| 楼盘反馈处理 | 开关型 | 包含处理、不予处理操作 | + +--- + +### 5.5 角色管理 + +#### 5.5.1 角色列表 + +| 字段 | 说明 | +|------|------| +| 角色名称 | 角色唯一名称,支持排序 | +| 角色类别 | 如置业顾问、店管、总经等类别,影响权限可选范围 | +| 应用人数 | 当前使用该角色的员工数量,点击「查看」查看名单 | +| 引用该角色配置 | 该角色权限是基于哪个角色模板创建的 | +| 创建时间 | 角色创建时间 | +| 修改时间 | 最后一次权限修改时间 | + +#### 5.5.2 已知系统内置角色(来自截图) + +| 角色名称 | 角色类别 | 适用场景 | +|----------|----------|----------| +| 刘文龙 | 置业顾问 | 高级业务员 | +| 最大权限角色 | 总经 | 系统管理员/超管角色 | +| 行政人员 | 置业顾问 | 行政人员 | +| 分行经理 | 店管 | 分行级别管理职务 | +| 高级业务员 | 置业顾问 | 标准销售顾问 | + +#### 5.5.3 角色类别说明 + +角色类别在创建时必选,且创建后**不可随意修改**(仅允许创建者修改),原因是角色类别会直接影响权限的可配置范围(不同类别允许的权限上限不同)。 + +--- + +### 5.6 数据范围(管理范围)说明 + +权限管理中「数据范围」是权限系统的核心维度,控制员工可以看到哪个层级的业务数据: + +| 数据范围值 | 说明 | +|-----------|------| +| 本人 | 仅查看/操作自己名下的数据 | +| 本组 | 查看/操作所在店组的数据 | +| 本门店 | 查看/操作所在门店的所有数据 | +| 本区域 | 查看/操作所在区域范围内的数据 | +| 全公司 | 查看/操作公司所有数据(管理层权限)| +| 无 | 无权查看/操作 | + +> 注:不同权限项的可选范围不同,如某权限项只有「本人 / 本门店 / 全公司」三个选项,另一权限项可能有完整的五档选项。具体可选范围以权限编辑页的下拉选项为准。 + +--- + +## 6. 技术考量 + +### 依赖关系 + +| 依赖系统 / 模块 | 用途 | 风险等级 | +|----------------|------|----------| +| 组织人事管理(org 模块) | 员工 / 部门数据读取,权限与员工身份绑定 | 高 | +| django-tenants | 权限数据必须严格按租户 Schema 隔离,严禁跨租户查询 | 高 | +| Redis 缓存 | 员工权限频繁读取,建议缓存员工权限快照,更新时主动失效 | 中 | + +### 已知风险 + +| 风险 | 可能性 | 影响 | 缓解策略 | +|------|--------|------|----------| +| 权限变更实时生效的一致性问题 | 中 | 高 | 角色/个人权限变更后主动清除 Redis 中该员工权限缓存,强制下次请求重新加载 | +| 权限项数量巨大(14+ 模块,数百个权限项)导致编辑页性能问题 | 中 | 中 | 左侧导航按模块懒加载权限数据,避免一次性加载全部权限项 | +| 多角色合并规则(已锁定 v1.1) | - | - | **规则**:同一员工多角色取**并集(最宽松原则)**。BOOLEAN→OR;SCOPE→MAX(self 2%,或出现跨租户数据泄漏问题,立即回滚并通知所有租户管理员。 + +--- + +## 8. 附录 + +### 8.1 截图参考索引 + +| 截图文件 | 完整路径 | 对应功能 | +|---------|---------|---------| +| `权限管理-人员列表.png` | `Project/fonrey/screenshots/权限管理/权限管理-人员列表.png` | 5.3 权限管理人员列表 | +| `权限管理-修改个人权限-客源.png` | `Project/fonrey/screenshots/权限管理/权限管理-修改个人权限-客源.png` | 5.4 个人权限编辑 - 客源模块 | +| `权限管理-人员编辑特定权限.png` | `Project/fonrey/screenshots/权限管理/权限管理-人员编辑特定权限.png` | Story 4 - 侧边 Drawer 编辑单个权限项 | +| `权限管理-批量设置角色.png` | `Project/fonrey/screenshots/权限管理/权限管理-批量设置角色.png` | Story 2 - 批量设置角色 Modal | +| `角色管理-角色列表.png` | `Project/fonrey/screenshots/权限管理/角色管理-角色列表.png` | 5.5.1 角色列表 | +| `角色管理-添加角色1.png` | `Project/fonrey/screenshots/权限管理/原始图片/角色管理-添加角色1.png` | Story 6 - 新增角色 Modal | +| `角色管理-修改角色.png` | `Project/fonrey/screenshots/权限管理/原始图片/角色管理-修改角色.png` | Story 8 - 修改角色(切换员工角色)| +| `权限-房源-小区.png` | `Project/fonrey/screenshots/权限管理/权限-房源-小区.png` | 5.4.4 楼盘(小区)模块权限分组 | +| `权限-客源-客源.png` | `Project/fonrey/screenshots/权限管理/权限-客源-客源.png` | 5.4.3 客源模块权限分组(角色编辑视角)| +| `权限-房源-挂牌分析.png` | `Project/fonrey/screenshots/权限管理/权限-房源-挂牌分析.png` | 5.4 房源 - 挂牌分析模块权限 | +| `权限-房源-商圈精耕.png` | `Project/fonrey/screenshots/权限管理/权限-房源-商圈精耕.png` | 5.4 房源 - 商圈精耕模块权限 | +| `权限-房源-举证检核.png` | `Project/fonrey/screenshots/权限管理/权限-房源-举证检核.png` | 5.4 房源 - 举证检核模块权限 | +| `权限-客源-客源-table.png` | `Project/fonrey/screenshots/权限管理/权限-客源-客源-table.png` | 5.4.3 客源权限表格视图 | +| `权限-合同-合同管理.png` | `Project/fonrey/screenshots/权限管理/权限-合同-合同管理.png` | 5.4 合同管理模块权限 | +| `权限-人事QA-考勤.png` | `Project/fonrey/screenshots/权限管理/权限-人事QA-考勤.png` | 5.4 人事OA - 考勤权限 | +| `权限-人事QA-组织.png` | `Project/fonrey/screenshots/权限管理/权限-人事QA-组织.png` | 5.4 人事OA - 组织权限 | +| `权限-人事QA-审批.png` | `Project/fonrey/screenshots/权限管理/权限-人事QA-审批.png` | 5.4 人事OA - 审批权限 | +| `权限-人事QA-任务.png` | `Project/fonrey/screenshots/权限管理/权限-人事QA-任务.png` | 5.4 人事OA - 任务权限 | +| `权限-人事QA-内容.png` | `Project/fonrey/screenshots/权限管理/权限-人事QA-内容.png` | 5.4 人事OA - 内容权限 | +| `权限-交易-交易管理.jpg` | `Project/fonrey/screenshots/权限管理/权限-交易-交易管理.jpg` | 5.4 交易 - 交易管理权限 | +| `权限-交易-二手房售后管理.png` | `Project/fonrey/screenshots/权限管理/权限-交易-二手房售后管理.png` | 5.4 交易 - 二手房售后管理权限 | +| `权限-交易-新房售后管理.png` | `Project/fonrey/screenshots/权限管理/权限-交易-新房售后管理.png` | 5.4 交易 - 新房售后管理权限 | +| `权限-三网-三网经纪人后台.png` | `Project/fonrey/screenshots/权限管理/权限-三网-三网经纪人后台.png` | 5.4 三网 - 三网经纪人后台权限 | + +### 8.2 权限模块完整导航结构 + +基于截图梳理的权限配置模块树(以角色编辑页左侧导航为准): + +``` +权限配置 +├── 首页 +├── 房源 +│ ├── 二手 & 租赁 +│ ├── 小区(楼盘管理) +│ ├── 商圈精耕 +│ ├── 举证 & 检核 +│ ├── 挂牌分析 +│ └── 房源广场 +├── 新房 +├── 客源 +├── 交易 +│ ├── 交易管理 +│ ├── 二手房售后管理 +│ └── 新房售后管理 +├── 数据 +│ ├── 报表管理 +│ ├── 资料客统计 +│ ├── 行程量化 +│ └── 房客权益查询 +├── 营销 +│ ├── 短视频 +│ └── 巧克力 +├── 人事OA +│ ├── 组织 +│ ├── 审批 +│ ├── 考勤 +│ ├── 任务 +│ └── 内容 +├── 合同 +│ └── 合同管理 +├── 三网 +│ ├── 三网经纪人后台 +│ └── 三网授权管理 +├── 系统 +│ ├── 系统工具 +│ ├── 业务工具 +│ └── 安装与登录授权 +├── 移动端 +├── 智能门店 +│ ├── 智慧大屏 +│ └── VR 换装 +└── 在线充值 + ├── 电话充值 + └── 增值服务 +``` diff --git a/Project/fonrey/PRD/系统配置/系统配置.md b/Project/fonrey/PRD/系统配置/系统配置.md deleted file mode 100644 index 76ef63bb..00000000 --- a/Project/fonrey/PRD/系统配置/系统配置.md +++ /dev/null @@ -1,128 +0,0 @@ -## 首页设置 - - -## 房源设置 -### 新增/编辑/查看 - - -### 字段/标签设置 - - -### 相关方设置 - - -### 相关方保护规则设置 - - -### 跟进/面访/回访 - - -### 实勘视频/VR/实地核验 - - -### 预约拍摄设置 - - -### 钥匙/委托/政府核验 - - -### 作业盘设置 - - -### 维护人员设置 - - -### 列表/房源/分级 - - -### 营销设置 - - -### 楼盘设置 - - -### 资料房/业主委托/预录入 - - -### 隐私保护及防骚扰 - - -### 房源检查及纠错 - - -## 新房设置 -### 新房基本设置 - -### 新房参数设置 - - -## 客源设置 -### 客源基本配置 - - -### 客源参数配置 - - -### 客源相关方配置 - -### 客源行政跨部权限 - -## 交易设置 - -### 交易流程 - -### 二手售后流程 - -### 新房售后流程 - -### 参数&备件条件 - -## 财务设置 - -### 业绩管理 - -### 资金管理 - -### 结算设置 - -### 提成设置 - - -## 人事OA设置 - -### 组织人事基本设置 - -### 员工自动升降级设置 - -### 审批流程设置 - -## 任务设置 - -### 参数设置 - -### 入职周年祝福设置 - - -## 合同设置 - -### 合同基本设置 - -## 通用及移动端设置 - -### 指标设置 -### 安全设置 - -### 其他设置 - -### 电话智能监控设置 - -### 黑名单设置 - -## 安装与登录设置 - - - - - - - diff --git a/Project/fonrey/PRD/系统配置/系统配置参数数据.md b/Project/fonrey/PRD/系统配置/系统配置参数数据.md new file mode 100644 index 00000000..ca387168 --- /dev/null +++ b/Project/fonrey/PRD/系统配置/系统配置参数数据.md @@ -0,0 +1,1100 @@ +## 1. 首页设置 + +#### 1.1 员工信息模块 + +| 设置项 | 当前值 | 说明 | +| -------- | ------ | ------------ | +| 是否展示员工司龄 | 🔴(开启) | 若开启则首页展示员工司龄 | +#### 1.2 行程模块显示指标 +| 内容 | +| ------ | +| 买卖 租赁 | + +#### 1.3 首页业绩显示设置 + +| 内容 | +| -------------------------------------------------------------------------------- | +| 统计审批中和审批通过的转定业绩:录转定/认购后统计审批中、审批驳回和审批通过的业绩,若无转定/认购,直接签约则统计录签约后审批中、审批驳回和审批通过的分成后业绩 | + +#### 1.4 排行榜设置 + +| 设置项 | 当前值 | 说明 | +| -------------- | ------------------ | ------------------------------------------------------------------------------------------------ | +| 是否显示业绩和单数 | 🔴(开启) | 若开启则排行榜中显示业绩和单数,若关闭则不显示 | +| 业绩计算方式 | 统计审批中和审批通过的转定单量和业绩 | 录转定/认购后统计审批中、审批驳回和审批通过的单量和业绩,若无转定/认购,直接签约则统计录签约后审批中、审批驳回和审批通过的单量和分成后业绩 | +| 默认按店或组排名 | 门店 | 首页排行榜默认默认按此部门级别统计排名,选择门店则默认按门店统计排名 | +| 默认展示全公司前10排名数据 | ⚪(关闭) | 若开启则默认展示全公司前10名的个人/部门的业绩、单量排名数据。若排行榜权限是无或本人,只能看默认排行数据;若排行榜权限是本部或全部,展示默认排行数据,也可以选择权限范围内的部门查看其排行数据 | +| 过滤账号 | 无限制 | 添加的账号不会出现在首页排行榜中 | +| 过滤部门 | 无限制 | 添加的部门不会出现在首页排行榜中 | +#### 1.5 成交战报设置 + +| 设置项 | 当前值 | 说明 | +| -------- | ------ | ----------------------- | +| 成交时间范围 | 不限制 | 只展示成交天数在此范围内的成交战报,空=不限制 | +| 成交业绩范围 | 不限制 | 只展示成交业绩在此范围内的成交战报,空=不限制 | +| 是否显示业绩 | ⚪(关闭) | 若开启则成交战报中显示业绩,若关闭则不显示 | +| 是否显示房源 | 🔴(开启) | 若开启则成交战报中显示房源名称,若关闭则不显示 | +| 是否显示房源总价 | ⚪(关闭) | 若开启则成交战报中显示房源总价,若关闭则不显示 | + + +## 2. 房源设置 +### 2.1 新增/编辑/查看 +#### 新增/编辑设置 + +| 分类 | 设置项 | 当前值 | 说明 | +| ----------- | ------------------------ | ------------- | -------------------------------------------------------------------- | +| **新增** | | | | +| | 新增时属性可选 | 公盘/私盘 | 新增房源时房源属性选择范围(包括重新挂牌) | +| | 新增房源状态可选 | 出租/出售/租售/暂缓 | 如果是租售分离公司,租售状态不会生效;如果是启用不售/不租,暂缓不会生效 | +| | 房源新增时参与房源判重的未挂牌状态范围 | 我售/我租/无效 | 新增房源时对楼盘-楼栋-单元-房号查重,重复的房源不允许新增 | +| | 新增房源审核通过后可见 | ⚪(关闭) | 如果开启,新增审批通过之后才可见,新增审批中仅有提交人和当前审批人可见;如果关闭,新增审批中就立即可见 | +| | 新增房源审批驳回后,房源的处理方式 | 暂缓/不租不售 | | +| **激活/重新挂牌** | | | | +| | 激活房源时属性可选填字段 | 无 | 激活房源时房源属性选择范围,为空代表默认当前房源属性不可修改 | +| | 激活场景下是否可新增业主电话 | 🔴(开启) | 开启后,房源激活挂牌时,经纪人可新增业主并获得号码方 | +| | 重新挂牌场景下是否可新增业主电话 | 🔴(开启) | 开启后,房源重新挂牌时,经纪人可新增业主并获得号码方 | +| | 激活房源审核通过后可见 | ⚪(关闭) | 如果开启,激活审核通过后变更状态,激活审批中显示原状态,仅有提交人和当前审批人可见。如果关闭审核通过后可见,激活审批提交后立即显示新状态 | +| | 重新挂牌审批驳回后,房源的处理方式 | 暂缓/不租不售 | 本配置适用于:房源「重新挂牌」的审批驳回。房源「激活」的审批驳回不适用(会退回原状态) | +| | 新增/激活时保护房设置 | 非保护房 | 若开通真房微门店等营销系统,设置为非保护房后会将房源数据同步到对应的营销系统 | +| | 我售房源重新挂牌 | 不限制 | 控制我售房源何种流程结束之后可以重新挂牌 | +| | 下架房源号码纠错审批通过后,纠错人可以优先改状态 | 0小时 | 下架房源被纠错并添加新号码,审批通过后,设置时长内仅纠错人可以改状态 | +| | 重复激活/重新挂牌时长限制 | 999天 | 控制同一房源,同一员工,多长时间内不允许重复激活/重新挂牌,999=不限制 | +| **编辑/数量限制** | | | | +| | 房本年限可选 | 未知/满二/不满五年/满五 | 可以控制二手源"房本年限"字段的可选范围 | +| | 每人拥有私盘数量限制 | 999套 | 999=不限制,0=不允许 | +| | 每个部门拥有私盘数量限制 | 999套 | 999=不限制,0=不允许 | +| | 出售同业主号码数量上限 | 999套 | 999=不限制,控制同一业主号码同一用途最多可以被录入多少套出售房源,未挂牌/预录入房源不算 | +| | 出租同业主号码数量上限 | 999套 | 999=不限制,控制同一业主号码同一用途最多可以被录入多少套出租房源,未挂牌/预录入房源不算 | +#### 状态设置 + +| 设置项 | 当前值 | 说明 | +| ---------------------- | ---------- | -------------------------------------------------------------------------------------------------------------- | +| 暂缓与不售/不租状态启用配置 | 暂缓 | 暂缓与不售/不租只能选择其中一个,未被启用的状态后续不再产生新增数据,历史已存在的数据维持不变 | +| 设定哪些房源状态不在列表筛选范围 | 验真超时/不租/不售 | 设定哪些房源状态在列表查询的状态筛选位置不显示 | +| 未挂牌房源状态是否允许改为其他未挂牌房源状态 | ⚪(关闭) | 若开启,暂缓/不售/不租/他售/他租/验真超时状态不可以改为暂缓、不售、不租、他售、他租、无效中的任一状态 | +| 房源下架凭证 | 非必填 | 设置发起房源改状态纠错时,举证信息提交规则 | +| 新增验真期间不允许修改房源状态 | ⚪(关闭) | 若开启,房源在新增验真期间不允许修改房源状态 | +| 激活验真验真期间不允许修改房源状态 | 🔴(开启) | 若开启,房源在激活验真期间不允许修改房源状态 | +| 业主号码纠错中不允许修改房源状态 | ⚪(关闭) | 若开启,房源在业主号码纠错中不允许修改房源状态 | +| 调价中不允许修改房源状态 | ⚪(关闭) | 若开启,房源在调价中不允许修改房源状态 | +| 挂牌房源无号码,状态自动变更为 | - | 若开启,挂牌房源的所有号码因纠错/验真场景被删除后,房源状态自动变更(实时)(手动删号码的房源状态不会自动变更);开关开启当晚24点,系统将自动处理无号码的库存挂牌房源状态(审批中/验真中/有进行中的交易的房源,不处理) | +| | | | +#### 价格设置 + +**基础设置** + +|设置项|当前值|说明| +|---|---|---| +|售底价是否禁用|⚪(关闭)|在调价/激活房源/重新挂牌时隐藏售底价。该场景下调价/激活房源/重新挂牌时售底价同步清空| +|租底价是否禁用|⚪(关闭)|在调价/激活房源/重新挂牌时隐藏租底价。该场景下调价/激活房源/重新挂牌时租底价同步清空| +|仅相关方可查看底价模式|⚪(关闭)|开启后,相关方权限里可配置「查看/修改底价」,开启的相关方才可查看&修改底价 去开启。另:本模式开启后,所有人的房源列表的底价字段都会隐藏| +|商铺写字楼租单价单位及计算公式|按日租单价:元/m²/天(月租=单价_365/12_面积)|修改单位后,历史数据同步计算修改单位;若单位未修改只修改日租单价计算公式,则历史数据不影响| + +**调价设置** + +|设置项|当前值|说明| +|---|---|---| +|价格计算基准|售价/租价|设置何种类型的降价可成为相关方,何种类型的价格为维护人价差计算标准| + +|房源类型|价格计算基准|是否阶梯比例|降价比例(设置可成为相关方需要达到的降价比例)| +|---|---|---|---| +|售|原价|统一比例|-| +|租|原价|统一比例|-| + +|设置项|当前值|说明| +|---|---|---| +|调价成功覆盖相关方|无|调价通过后,达到调价比例则覆盖相关方(议价方若启用,则调售价达到降价比例默认覆盖,调租价是否覆盖按下方配置。启用议价方)| +|租价调价达到降价比例是否覆盖议价方|🔴(开启)|若开启,调租价/租底价达到降价比例可成为议价方(调售价达到议价比例默认覆盖议价方)| + +**调价真实性管理** + +|设置项|当前值|说明| +|---|---|---| +|调价时的凭证填写要求|非必填|开启议价审批后,此配置才生效。去设置| +|若调价凭证的录音仍在生成中,可选择话单编号|🔴(开启)|若调价凭证的录音仍在生成中,可选择话单编号。注:时长小于2秒的录音不可选择| +|调价后发短信给业主确认|无|若启用,经纪人可在调整对应价格时发短信给业主确认,业主确认即为调价完成(无需审批)。短信费根据贵司配置从对应账号扣费。点击查看议价审批&业主短信确认的规则| +|业主短信的生效时长|24小时|业主超时未回复(短信发送时间起),则短信自动失效。短信失效后,下一个经纪人可再次操作调价。| +|可按角色设置/按相关方设置哪些员工在调价时无需业主短信确认和调价审批,直接调价完成||查看规则图示。去设置角色 去设置相关方| + +**调价真实性管理·高级设置(若无特殊诉求,可不设置)** + +|设置项|当前值|说明| +|---|---|---| +|开启业主调价短信后,按调价幅度设置具体方式|⚪(关闭)|请注意:业主调价短信和议价审批均开启,此功能才生效。您可自定义不同调价幅度下的调价举证方式。调价幅度的计算依据,按「价格计算基准」来算| + +**成交价管理** + +| 设置项 | 当前值 | 说明 | +| -------------------- | ----- | ------------------------------- | +| 他售房源必须录入成交信息 | ⚪(关闭) | 若开启,录入他售房源或改状态为他售时,必须填写成交价和成交时间 | +| 他售房源是否展示在成交列表,您可前往设置 | | | +#### 房源海报设置 +以下是截图中的完整文字内容: + +| 设置项 | 当前值 | 说明 | +| --------- | ------------------------------ | ---------------------------------------------------------------------------------------- | +| 公司logo | (图片:HUJU logo,Web:www.huju.cn) | | +| 公司简称 | 沪居房产 | | +| 海报主题色 | (青绿色色块) | 设置默认的海报主题色 | +| 主题色是否支持修改 | 是 | 若选择是,表示经纪人可制作海报时调整海报主题色 | +| 二维码 | - | 公司房源二维码与海报制作人无关,房源页将展示推荐经纪人展位;仅开通企业网店的公司可设置企业网店二维码;仅未开通老巧客力的公司可设置公司巧客力二维码;可选择自定义上传唯一二维码; | +| 二维码是否支持修改 | 是 | 若选择是,表示经纪人可制作海报时选择使用巧客力个人房源二维码/自定义上传二维码 | + +#### 其他设置 + +| 设置项 | 当前值 | 说明 | +| ----------------------- | ------ | -------------------------------------------------------------------------------------------------------------------------------------------------- | +| 交易过户/结盘成功后更新业主同时更新首录方 | ⚪(关闭) | 交易过户/结盘后将新增客户电话作为业主,是否同步将交易归属人更新为首录方 | +| 房源详情页的相关方模块展示私信入口 | 🔴(开启) | | +| 相关方员工变更部门,房源相关方所在部门自动更新 | ⚪(关闭) | 开启后,相关方员工所在部门变更,未挂牌房源的相关方所在部门每晚凌晨自动更新成他的当前部门;关闭后,未挂牌房源的相关方部门不随员工部门异动而变更。(注:挂牌房源实时更新)。请注意:若贵司开启了房源自动转公盘/转状态的批处理规则,若员工部门更新,可能会导致员工房源变更。请通知员工跟进好这类房源! | +| 存在重复地址的房源时可通知哪些职务的员工 | 无 | 若存在重复地址的房源,第二天早上9点发送消息给对应职务的员工 | + +### 2.2 字段/标签设置 +#### 字段必填要求 +**字段填写要求和新增页展示设置** + +| 用途 | 交易状态 | 必填字段 | 选填字段 | 操作 | +| -------- | ----- | -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --- | +| 住宅/商住/别墅 | 出售 | 朝向、装修 | 二级用途、售底价、房屋现状、租约到期时间、唯一住房、包税费、购房付款方式、售房原因、来源、看房时间、房源备注、有无抵押、抵押说明、有无贷款、贷款说明、有无限制、限制说明、有无查封、查封说明、学校、学区是否占用、学区释放时间、套内面积、建成年代、电梯、产权性质、产权年限、微信、房源标签、营销标题(售)、核心卖点(售)、户型介绍、小区介绍、业主心态 | 修改 | +| 住宅/商住/别墅 | 出租 | 朝向、装修 | 二级用途、租底价、房屋现状、租约到期时间、租房付款方式、租金包含、来源、看房时间、房源备注、学校、学区是否占用、学区释放时间、套内面积、建成年代、电梯、租赁方式、微信、房屋配套、房源标签、营销标题(租)、核心卖点(租)、户型介绍、小区介绍 | 修改 | +| 住宅/商住/别墅 | 租售 | 朝向、装修 | 二级用途、售底价、房屋现状、租约到期时间、唯一住房、包税费、购房付款方式、售房原因、来源、看房时间、房源备注、有无抵押、抵押说明、有无贷款、贷款说明、有无限制、限制说明、有无查封、查封说明、学校、学区是否占用、学区释放时间、套内面积、建成年代、电梯、产权性质、产权年限、微信、房屋配套、房源标签、营销标题(售)、营销标题(租)、核心卖点(售)、核心卖点(租)、户型介绍、小区介绍、业主心态、租底价、租房付款方式、租金包含、租赁方式 | 修改 | +| 住宅/商住/别墅 | 他售/不售 | 朝向、装修 | 二级用途、售底价、房屋现状、租约到期时间、唯一住房、包税费、购房付款方式、售房原因、来源、看房时间、房源备注、有无抵押、抵押说明、有无贷款、贷款说明、有无限制、限制说明、有无查封、查封说明、学校、学区是否占用、学区释放时间、套内面积、建成年代、电梯、产权性质、产权年限、微信、房源标签 | 修改 | +| 住宅/商住/别墅 | 他租/不租 | 朝向、装修 | 二级用途、租底价、房屋现状、租约到期时间、租房付款方式、租金包含、来源、看房时间、房源备注、学校、学区是否占用、学区释放时间、套内面积、建成年代、电梯、租赁方式、微信、房屋配套、房源标签 | 修改 | +| 住宅/商住/别墅 | 暂缓 | 朝向、装修 | 二级用途、售底价、房屋现状、租约到期时间、唯一住房、包税费、购房付款方式、售房原因、来源、看房时间、房源备注、有无抵押、抵押说明、有无贷款、贷款说明、有无限制、限制说明、有无查封、查封说明、学校、学区是否占用、学区释放时间、套内面积、建成年代、电梯、产权性质、产权年限、微信、房屋配套、房源标签、租底价、租房付款方式、租金包含、租赁方式 | 修改 | +| 商铺 | 出售 | 朝向、装修 | 二级用途、售底价、层高、开间、房屋现状、租约到期时间、购房付款方式、售房原因、来源、看房时间、房源备注、产权年限、微信、房源标签 | 修改 | +| 商铺 | 出租 | 朝向、装修 | 二级用途、进深、层高、开间、租底价、房屋现状、租约到期时间、租房付款方式、来源、看房时间、房源备注、微信、房源标签、转让费、起租期限、免租期限 | 修改 | +| 商铺 | 租售 | 朝向、装修 | 二级用途、进深、层高、开间、售底价、房屋现状、租约到期时间、包税费、购房付款方式、售房原因、来源、看房时间、房源备注、产权年限、微信、房源标签、租底价、租房付款方式、转让费、起租期限、免租期限 | 修改 | +| 商铺 | 他售/不售 | 朝向、装修 | 二级用途、进深、层高、开间、售底价、房屋现状、租约到期时间、包税费、购房付款方式、售房原因、来源、看房时间、房源备注、产权年限、微信、房源标签 | 修改 | +| 商铺 | 他租/不租 | 朝向、装修 | 二级用途、进深、层高、开间、租底价、房屋现状、租约到期时间、租房付款方式、来源、看房时间、房源备注、微信、房源标签、转让费、起租期限、免租期限 | 修改 | +| 商铺 | 暂缓 | 朝向、装修 | 二级用途、进深、层高、开间、售底价、房屋现状、租约到期时间、包税费、购房付款方式、售房原因、来源、看房时间、房源备注、产权年限、微信、房源标签、租底价、租房付款方式、转让费、起租期限、免租期限 | 修改 | +| 写字楼 | 出售 | 朝向、装修 | 二级用途、售底价、房屋现状、租约到期时间、包税费、购房付款方式、售房原因、来源、看房时间、房源备注、电梯、微信、房源标签 | 修改 | +| 写字楼 | 出租 | 朝向、装修 | 二级用途、房屋现状、租约到期时间、租房付款方式、租赁方式、来源、看房时间、房源备注、电梯、微信、房源标签、起租期限、免租期限 | 修改 | +| 写字楼 | 租售 | 朝向、装修 | 二级用途、售底价、房屋现状、租约到期时间、包税费、购房付款方式、售房原因、来源、看房时间、房源备注、电梯、微信、房源标签、租底价、租房付款方式、租赁方式、起租期限、免租期限 | 修改 | +| 写字楼 | 他售/不售 | 朝向、装修 | 二级用途、售底价、房屋现状、租约到期时间、包税费、购房付款方式、售房原因、来源、看房时间、房源备注、电梯、微信、房源标签 | 修改 | +| 写字楼 | 他租/不租 | 朝向、装修 | 二级用途、租底价、房屋现状、租约到期时间、租房付款方式、租赁方式、来源、看房时间、房源备注、电梯、微信、房源标签、起租期限、免租期限 | 修改 | +| 写字楼 | 暂缓 | 朝向、装修 | 二级用途、售底价、房屋现状、租约到期时间、包税费、购房付款方式、售房原因、来源、看房时间、房源备注、电梯、微信、房源标签、租底价、租房付款方式、租赁方式、起租期限、免租期限 | 修改 | +| 其他 | 出售 | 户型、朝向、装修 | 二级用途、售底价、房屋现状、租约到期时间、唯一住房、包税费、购房付款方式、售房原因、来源、看房时间、房源备注、有无抵押、抵押说明、有无贷款、贷款说明、有无限制、限制说明、有无查封、查封说明、学校、学区是否占用、学区释放时间、套内面积、建成年代、电梯、产权性质、产权年限、微信、房屋配套、房源标签、营销标题(售)、核心卖点(售)、户型介绍、小区介绍、业主心态 | 修改 | +| 其他 | 出租 | 户型、朝向、装修 | 二级用途、租底价、房屋现状、租约到期时间、租房付款方式、租金包含、来源、看房时间、房源备注、学校、学区是否占用、学区释放时间、套内面积、建成年代、电梯、租赁方式、微信、房屋配套、房源标签、营销标题(租)、核心卖点(租)、户型介绍、小区介绍 | 修改 | +| 其他 | 租售 | 户型、朝向、装修 | 二级用途、售底价、房屋现状、租约到期时间、唯一住房、包税费、购房付款方式、售房原因、来源、看房时间、房源备注、有无抵押、抵押说明、有无贷款、贷款说明、有无限制、限制说明、有无查封、查封说明、学校、学区是否占用、学区释放时间、套内面积、建成年代、电梯、产权性质、产权年限、微信、房屋配套、房源标签、营销标题(售)、营销标题(租)、核心卖点(售)、核心卖点(租)、户型介绍、小区介绍、业主心态、租底价、租房付款方式、租金包含、租赁方式 | 修改 | +| 其他 | 他售/不售 | 户型、朝向、装修 | 二级用途、售底价、房屋现状、租约到期时间、唯一住房、包税费、购房付款方式、售房原因、来源、看房时间、房源备注、有无抵押、抵押说明、有无贷款、贷款说明、有无限制、限制说明、有无查封、查封说明、学校、学区是否占用、学区释放时间、套内面积、建成年代、电梯、产权性质、产权年限、微信、房源标签 | 修改 | +| 其他 | 他租/不租 | 户型、朝向、装修 | 二级用途、租底价、房屋现状、租约到期时间、租房付款方式、租金包含、来源、看房时间、房源备注、学校、学区是否占用、学区释放时间、套内面积、建成年代、电梯、租赁方式、微信、房屋配套、房源标签 | 修改 | +| 其他 | 暂缓 | 户型、朝向、装修 | 二级用途、售底价、房屋现状、租约到期时间、唯一住房、包税费、购房付款方式、售房原因、来源、看房时间、房源备注、有无抵押、抵押说明、有无贷款、贷款说明、有无限制、限制说明、有无查封、查封说明、学校、学区是否占用、学区释放时间、套内面积、建成年代、电梯、产权性质、产权年限、微信、房屋配套、房源标签、租底价、租房付款方式、租金包含、租赁方式 | 修改 | +**修改字段必填要求样板** + +| 录入字段 | 填写要求 | 录入页展示 | +| ------- | ----------- | --------- | +| 二级用途 | ○ 必填 ● 选填 | 🔴(开启) | +| 朝向 | ● 必填 ○ 选填 | 🔴(开启,浅色) | +| 装修 | ● 必填 ○ 选填 | 🔴(开启,浅色) | +| 售底价 | ○ 必填 ● 选填 | ⚪(关闭) | +| 房屋现状 | ○ 必填 ● 选填 | ⚪(关闭) | +| 租约到期时间 | ○ 必填 ● 选填 | ⚪(关闭) | +| 唯一住房 | ○ 必填 ● 选填 | ⚪(关闭) | +| 包税费 | ○ 必填 ● 选填 | ⚪(关闭) | +| 购房付款方式 | ○ 必填 ● 选填 | ⚪(关闭) | +| 售房原因 | ○ 必填 ● 选填 | ⚪(关闭) | +| 来源 | ○ 必填 ● 选填 | ⚪(关闭) | +| 看房时间 | ○ 必填 ● 选填 | ⚪(关闭) | +| 房源备注 | ○ 必填 ● 选填 | ⚪(关闭) | +| 有无抵押 | ○ 必填 ● 选填 | ⚪(关闭) | +| 抵押说明 | ○ 必填 ● 选填 | ⚪(关闭) | +| 有无贷款 | ○ 必填 ● 选填 | ⚪(关闭) | +| 贷款说明 | ○ 必填 ● 选填 | ⚪(关闭) | +| 有无限制 | ○ 必填 ● 选填 | ⚪(关闭) | +| 限制说明 | ○ 必填 ● 选填 | ⚪(关闭) | +| 有无查封 | ○ 必填 ● 选填 | ⚪(关闭) | +| 查封说明 | ○ 必填 ● 选填 | ⚪(关闭) | +| 学校 | (灰色)必填 ● 选填 | ⚪(关闭) | +| 学区是否占用 | ○ 必填 ● 选填 | ⚪(关闭) | +| 学区释放时间 | ○ 必填 ● 选填 | ⚪(关闭) | +| 套内面积 | ○ 必填 ● 选填 | ⚪(关闭) | +| 建成年代 | ○ 必填 ● 选填 | ⚪(关闭) | +| 电梯 | ○ 必填 ● 选填 | ⚪(关闭) | +| 产权性质 | ○ 必填 ● 选填 | ⚪(关闭) | +| 产权年限 | ○ 必填 ● 选填 | ⚪(关闭) | +| 微信 | ○ 必填 ● 选填 | ⚪(关闭) | +| 房源标签 | ○ 必填 ● 选填 | ⚪(关闭) | +| 营销标题(售) | ○ 必填 ● 选填 | ⚪(关闭) | +#### 自定义字段 + +| 字段名称 | 字段类型 | 选项参数 | 房源用途 | 房源状态 | 操作 | +| ---- | ---- | ---- | ------------------ | ----------------------- | ----- | +| 产证号 | 文本输入 | | 住宅/商住/别墅、商铺、写字楼、其他 | 出售、出租、租售、他售/不售、他租/不租、暂缓 | 修改 删除 | +#### 自定义预设参数值 +以下是截图中的完整文字内容: + +| 参数项 | 项目值 | 操作 | +| ------- | ----------------------------------------------------- | --- | +| 购房付款方式 | 一次付清、按揭付款、分批次付款、垫资解按 | 修改 | +| 租房付款方式 | 押一付三、押一付一、押二付一、0押金、半年付、年付、季租、月租 | 修改 | +| 其他房源用途 | 车库、车位、平房、四合院、仓库、厂房、地皮、铺厂、网点、写厂 | 修改 | +| 看房时间 | 随时可看、提前预约、不方便看 | 修改 | +| 商铺二级用途 | 无 | 修改 | +| 委托作废类型 | 录错委托信息、系统自动作废、其他 | 修改 | +| 别墅二级用途 | 联排别墅、独栋别墅、双拼别墅、叠加别墅 | 修改 | +| 来源 | 驻守、网络、老客户、派单、朋友、上门、同事、广告、来电、来访、扫街、中介、资料房、资料客、业主委托、预录入 | 修改 | +| 住宅二级用途 | 普通住宅、花园洋房 | 修改 | +| 写字楼二级用途 | 无 | 修改 | +| 商住二级用途 | 无 | 修改 | +| 产权性质 | 商品房、房改房、集资房、经济适用房 | 修改 | +| 委托违约类型 | 他司成交、多家委托、终止挂牌、其他 | 修改 | +| 调价举证方式 | 业主短信确认议价、提交议价审批 | 修改 | +| 凭证填写要求 | 非必填、录音/图片必填其中一项、仅录音必填、仅图片必填、录音/图片均必填 | 修改 | +| 价格类型 | 售价/售底价、租价/租底价 | 修改 | +| 委托附件类型 | 委托书、产权人身份证件、委托人身份证件、第三方代签授权证明、房产证、其他 | 修改 | +#### 标签设置 + +以下是截图中的完整文字内容: + +| 标签名称 | 样式 | 标签说明 | 来源 | 类别 | 状态 | 各部门可设标签数量 | 操作 | +| ---- | ---- | --------------------- | --- | --- | ----- | --------- | ----- | +| 房源属性 | 私 | 依据房源的属性显示对应的私特封,公盘不显示 | 预制类 | - | ● 已启用 | - | 禁用 修改 | +| 速销 | 速销 | 该房源有当前一个有效的速销委托 | 预制类 | - | ● 已启用 | - | 禁用 修改 | +| 独家 | 独家 | 该房源有当前一个有效的独家委托 | 预制类 | - | ● 已启用 | - | 禁用 修改 | +| 有钥匙 | 🔑 | 该房源有当前一个有效的钥匙 | 预制类 | - | ● 已启用 | - | 禁用 修改 | +| 电梯 | 电梯 | 房源是电梯房 | 预制类 | - | ● 已启用 | - | 禁用 修改 | +| 满N | 满N | 该房源的购买时间满几年,对应显示为满几 | 预制类 | - | ● 已启用 | - | 禁用 修改 | +| 唯一 | 唯一 | 该房源为唯一住房 | 预制类 | - | ● 已启用 | - | 禁用 修改 | +| 有照片 | 📷 | 该房源相册有图片 | 预制类 | - | ● 已启用 | - | 禁用 修改 | +| 贷款 | 贷款 | 该房源有贷款 | 预制类 | - | ● 已启用 | - | 禁用 修改 | +| 视频 | 视频 | 该房源相册有视频 | 预制类 | - | ● 已启用 | - | 禁用 修改 | +| AI视频 | AI视频 | 该房源有当前一个有效的AI视频 | 预制类 | - | ● 已启用 | - | 禁用 修改 | +| 有VR | VR | 该房源相册有VR | 预制类 | - | ● 已启用 | - | 禁用 修改 | +| 3D | 3D | 房源有发布成功的3D户型图 | 预制类 | - | ● 已启用 | - | 禁用 修改 | +| 一键换装 | 一键换装 | 该房源VR已经支持至少一种装修风格 | 预制类 | - | ● 已启用 | - | 禁用 修改 | +| 一般委托 | 一般委托 | 该房源有当前一个有效的一般委托 | 预制类 | - | ● 已启用 | - | 禁用 修改 | +**修改标签** + +| 字段 | 内容 | +| ------ | ------------ | +| 标题 | 修改预制标签 | +| * 标签名称 | 满N | +| 颜色设置 | 默认 / 次要 / 重要 | +| 标签预览 | 满N | +| 操作按钮 | 确定 / 取消 | +### 2.3 相关方设置 +#### 相关方设置 + +| 相关方 | 相关方说明 | 状态 | 启动权限 | 操作 | +| ------ | ------------------------------ | --- | ------------------------ | -------------- | +| 平台摄影师 | 开启平台实勘功能后,在房源预约拍摄完成后统一处理为系统管理员 | 停用 | | 权限配置 | +| 维护人 | 出租或出售房源的维护人 | 停用 | | 权限配置 | +| 售维护人 | 出售房源的维护人(租、售维护人分开时自动启用) | 停用 | | 权限配置 | +| 租维护人 | 出租房源的维护人(租、售维护人分开时自动启用) | 停用 | | 权限配置 | +| 摄影师 | 在房源预约拍摄中被指定为摄影师的员工 | 停用 | | 权限配置 | +| 房源成交方 | 将房源变为我租/我售状态成交的员工 | 启用 | 查看对应房源等9项 | 权限配置 停用 | +| 速销委托方 | 在房源中和业主签订速销委托且委托并没结束的员工 | 启用 | 查看对应房源等15项 | 权限配置 停用 | +| 独家售委托方 | 在房源中和业主签订独家委托且委托并没结束的员工 | 启用 | 查看对应房源等15项 | 权限配置 停用 | +| 独家租委托方 | 在房源中和业主签订独家委托且委托并没结束的员工 | 启用 | undefined等2项 | 权限配置 停用 | +| 一般售委托方 | 在房源中和业主签订一般委托且委托并没结束的员工 | 启用 | 查看对应房源等6项 | 权限配置 停用 | +| 一般租委托方 | 在房源中和业主签订一般委托且委托并没结束的员工 | 启用 | 查看对应房源等6项 | 权限配置 停用 | +| 私盘方 | 将房源设为私盘的员工 | 启用 | 查看对应房源等24项 | 权限配置 停用 | +| 出售方 | 将房源新增或激活为出售/租售状态的员工 | 启用 | 查看对应房源等4项 | 权限配置 停用 | +| 出租方 | 将房源新增或激活为出租/租售状态的员工 | 启用 | 查看对应房源等4项 | 权限配置 停用 | +| 号码方 | 在房源中首次新增联系人号码的员工 | 启用 | 修改为[暂缓/不售/不租/他售/他租]状态等6项 | 权限配置 停用 | +| 实勘方 | 第一个提交实勘并审核通过的 | 启用 | 查看对应房源等7项 | 权限配置 停用 | +| 全景方 | 在房源中成功添加全景的员工 | 启用 | | 权限配置 停用 设置成为条件 | +| 钥匙方 | 在房源中收取钥匙并且尚未被业主收回的员工 | 启用 | 查看对应房源等4项 | 权限配置 停用 | +| 视频方 | 在房源中成功添加视频的员工 | 启用 | 查看对应房源等4项 | 权限配置 停用 | +| 议价方 | 将房源价格/底价降低超过一定比例的员工 | 启用 | 查看对应房源等3项 | 权限配置 停用 设置触发条件 | +| 特盘方 | 将房源设为特盘的员工 | 启用 | 查看对应房源等5项 | 权限配置 停用 | +| 封盘方 | 将房源设为封盘的员工 | 启用 | 查看对应房源等5项 | 权限配置 停用 | +| 首录方 | 第一个将房源登入系统的员工 | 启用 | 查看对应房源等2项 | 权限配置 停用 | +| 售核验方 | 在房源中录入政府核验并审核通过的员工 | 停用 | | 权限配置 启用 | +| 租核验方 | 在房源中录入政府核验并审核通过的员工 | 停用 | | 权限配置 启用 | +| 归属人1 | | 停用 | | 权限配置 启用 编辑 删除 | +| 归属人2 | | 停用 | | 权限配置 启用 编辑 删除 | +| 归属人3 | | 停用 | | 权限配置 启用 编辑 删除 | +| 员工 | 归属人改名 | 启用 | | 权限配置 停用 编辑 删除 | +| 员工 | 归属人改名 | 启用 | | 权限配置 停用 编辑 删除 | +| 员工 | 归属人改名 | 启用 | | 权限配置 停用 编辑 删除 | +相关方权限配置 **<待补充>** +#### 相关方消息通知 + +|设置项|当前值|说明| +|---|---|---| +|租约到期提醒|30天|房源租约到期前*天,发消息提醒房源所有相关方| + +**房源属性更改,通知哪些相关方** + +|房源状态|接收消息的相关人员|说明| +|---|---|---| +|私盘手动转公盘|无|注:私盘方默认收到消息,无需设置| +|房源转封盘|无|设置后,所有房源(含公盘/私盘/特盘)转封盘(含通过交易自动转封盘和手动改封盘),所选相关方能收到消息通知| +|封盘解封|无|设置后,封盘解封为公盘/特盘(含自动解和手动解封),所选相关方能收到消息通知。注:原封盘方默认收到消息,无需设置;若房源解封成为私盘/特盘,新私盘方/特盘方默认收到消息,无需设置| +|租约到期|该房源所有相关方|-| + +**房源删除,通知哪些相关方** + +| 房源状态 | 接收消息的相关人员 | 说明 | +| ----- | --------- | --- | +| 房源被删除 | 无 | - | +| | | | + +### 2.4 相关方保护规则设置 + +#### 新增房源/房源下架 + +| 设置项 | 当前值 | 说明 | 操作 | +| ------------------------------- | ---------- | --------------------------------------------------- | --- | +| 新增房源后,优先成为钥匙方/ 委托方/ 实勘方的保护规则 🔘 | | | 修改 | +| 保护时长计算标准 | 房源挂牌 后开始计算 | | | +| 出售房源 — 人员保护 | ⚪(关闭) | 开启后,所选相关方将可以在保护时长内更改房源的对应内容 | | +| 出售房源 — 部门保护 | ⚪(关闭) | 开启后,所选相关方所在部门范围内的人将可以在保护时长内更改房源的对应内容 配置说明 | | +| 出租房源 — 人员保护 | ⚪(关闭) | 开启后,所选相关方将可以在保护时长内更改房源的对应内容 | | +| 出租房源 — 部门保护 | ⚪(关闭) | 开启后,所选相关方所在部门范围内的人将可以在保护时长内更改房源的对应内容 配置说明 | | +| 房源下架时的资源清空规则 该配置和下方的保护时长设置联动 | | | 修改 | +| 房源下架后自动处理钥匙 | 无 | 这些房源状态变更后,系统自动退还钥匙,并清空钥匙方(我售/ 我租默认不清空) | | +| 房源下架后自动处理委托 | 无 | 这些房源状态变更后,系统自动作废委托,并清空委托方(我售/ 我租处理委托为【已成交】,并不清空委托方) | | + +#### 房源有效 + +**房源变为有效时,相关方的保护时长设置**                         修改 + +0~999整数,0为不保护;999为永久保护; 保护时长的开始时间:按房源在系统内的最新下架时间开始计算(精确到秒) 禁用的相关方,若设置过保护期,下次使用时默认前一次的保护期 + +**以下状态的房源,改为出售房源时,允许设置保护天数** + +|相关方|我售/我租|无效|暂缓/不租不售 🔘|他售/他租| +|---|---|---|---|---| +|首录方 🔘|999天|999天|999天|999天| +|出售方 🔘|0天|0天|0天|0天| +|实勘方|999天|999天|999天|999天| +|视频方|999天|999天|999天|999天| +|全景方|999天|999天|999天|999天| +|钥匙方 🔘|999天|999天|999天|999天| +|委托方 🔘|999天|999天|999天|999天| +|私盘方|999天|999天|999天|999天| +|议价方|999天|999天|999天|999天| +|号码方|999天|999天|999天|999天| +|自定义相关方 🔘|999天|999天|999天|999天| + +**以下状态的房源,改为出租房源时,允许设置保护天数** + +| 相关方 | 我售/我租 | 无效 | 暂缓/不租不售 🔘 | 他售/他租 | +| --------- | ----- | ---- | ---------- | ----- | +| 首录方 🔘 | 999天 | 999天 | 999天 | 999天 | +| 出租方 🔘 | 0天 | 0天 | 0天 | 0天 | +| 实勘方 | 999天 | 999天 | 999天 | 999天 | +| 视频方 | 999天 | 999天 | 999天 | 999天 | +| 全景方 | 999天 | 999天 | 999天 | 999天 | +| 钥匙方 🔘 | 999天 | 999天 | 999天 | 999天 | +| 委托方 🔘 | 999天 | 999天 | 999天 | 999天 | +| 私盘方 | 999天 | 999天 | 999天 | 999天 | +| 议价方 | 999天 | 999天 | 999天 | 999天 | +| 号码方 | 999天 | 999天 | 999天 | 999天 | +| 自定义相关方 🔘 | 999天 | 999天 | 999天 | 999天 | +#### 相关方保护失败 + +**相关方保护失败时,实勘图片、房源全景、房源视频的处理方式**             修改 + +| 设置项 | 当前值 | 说明 | +| ------------- | --- | ---------------------------- | +| 保留哪些类型的实勘图片资源 | 无 | 相关方保护失败时,清空相关方,保留哪些类型的实勘图片资源 | +| 保留哪些类型的全景资源 | 无 | 相关方保护失败时,清空相关方,保留哪些类型的全景资源 | +| 保留哪些类型的视频资源 | 无 | 相关方保护失败时,清空相关方,保留哪些类型的视频资源 | + + +### 2.5 跟进/面访/回访 +#### 跟进-基础设置 + +**跟进-基础设置**                         修改 + +|设置项|当前值|说明| +|---|---|---| +|跟进智能总结|🔴(开启)|开启后,可将近期跟进提交AI分析,提炼关键信息。查看跟进智能总结规则| +|影响最后跟进日的跟进类型|写入跟进|举例说明,若仅选择写入跟进,即只有写入跟进的时间才会变更最后跟进日时间,相关列表筛选均以该时间为准| +|影响出售方最后跟进日的跟进类型|写入跟进|若选择写入跟进,则房源出售方写入跟进时才会变更出售方最后跟进日| +|影响出租方最后跟进日的跟进类型|写入跟进|若选择写入跟进,则房源出租方写入跟进时才会变更出租方最后跟进日| +|影响私盘方最后跟进日的跟进类型|写入跟进|若选择写入跟进,则私盘方写入跟进时才会变更私盘方最后跟进日| +|影响维护人最后跟进日的跟进类型|写入跟进|暂不支持配置| +|跟进置顶条数上限|3条|单套房源可置顶的写入跟进数量上限,999=不限制,0=不允许| +|超时未跟进设置(满足条件的房源,【最后跟进日】超过设置天数后视为超时未跟进)||| + +| 条件 | 天数 | +| --------- | --- | +| 【标签】速销、独家 | 7 | +#### 跟进-目的设置 + +| 目的名称 | 是否标签必填 | 来源 | 操作 | +| ------ | ------ | --- | ----- | +| 业主跟进 | 否 | 预制 | 修改 | +| 议价 | 否 | 预制 | 修改 | +| 回访 | 否 | 预制 | 修改 | +| 谈委托 | 否 | 预制 | 修改 | +| 带看 | 否 | 预制 | 修改 | +| 勘察看房 | 否 | 预制 | 修改 | +| 派单驻守 | 否 | 预制 | 修改 | +| AI业主跟进 | 否 | 预制 | 修改 | +| 拜访 | 否 | 自定义 | 修改 删除 | +| 保留 | 否 | 自定义 | 修改 删除 | +| 电话 | 否 | 自定义 | 修改 删除 | +| 短信 | 否 | 自定义 | 修改 删除 | +| 房源未认证 | 否 | 自定义 | 修改 删除 | +| 激活 | 否 | 自定义 | 修改 删除 | +| 接待 | 否 | 自定义 | 修改 删除 | +| 勘察 | 否 | 自定义 | 修改 删除 | +| 看房 | 否 | 自定义 | 修改 删除 | +| 派单 | 否 | 自定义 | 修改 删除 | +| 企业来电通 | 否 | 自定义 | 修改 删除 | +| 去电 | 否 | 自定义 | 修改 删除 | +| 申请 | 否 | 自定义 | 修改 删除 | +| 未接通 | 否 | 自定义 | 修改 删除 | +| 信函 | 否 | 自定义 | 修改 删除 | +| 修改 | 否 | 自定义 | 修改 删除 | +| 邮件 | 否 | 自定义 | 修改 删除 | +| 转房客 | 否 | 自定义 | 修改 删除 | + +#### 跟进-标签设置 + +| 标签名称 | 所属跟进目的 | 来源 | 操作 | +| ---- | ------------------------------------------------------------------------------------------------ | --- | ----- | +| 在售 | 业主跟进、议价、回访、谈委托、带看、勘察看房、派单驻守、AI业主跟进、拜访、保留、电话、短信、房源未认证、激活、接待、勘察、看房、派单、企业来电通、去电、申请、未接通、信函、修改、邮件、转房客 | 预制 | 修改 | +| 在租 | 业主跟进、议价、回访、谈委托、带看、勘察看房、派单驻守、AI业主跟进、拜访、保留、电话、短信、房源未认证、激活、接待、勘察、看房、派单、企业来电通、去电、申请、未接通、信函、修改、邮件、转房客 | 预制 | 修改 | +| 不售 | 业主跟进、议价、回访、谈委托、带看、勘察看房、派单驻守、AI业主跟进、拜访、保留、电话、短信、房源未认证、激活、接待、勘察、看房、派单、企业来电通、去电、申请、未接通、信函、修改、邮件、转房客 | 预制 | 修改 | +| 不租 | 业主跟进、议价、回访、谈委托、带看、勘察看房、派单驻守、AI业主跟进、拜访、保留、电话、短信、房源未认证、激活、接待、勘察、看房、派单、企业来电通、去电、申请、未接通、信函、修改、邮件、转房客 | 预制 | 修改 | +| 他售 | 业主跟进、议价、回访、谈委托、带看、勘察看房、派单驻守、AI业主跟进、拜访、保留、电话、短信、房源未认证、激活、接待、勘察、看房、派单、企业来电通、去电、申请、未接通、信函、修改、邮件、转房客 | 预制 | 修改 | +| 他租 | 业主跟进、议价、回访、谈委托、带看、勘察看房、派单驻守、AI业主跟进、拜访、保留、电话、短信、房源未认证、激活、接待、勘察、看房、派单、企业来电通、去电、申请、未接通、信函、修改、邮件、转房客 | 预制 | 修改 | +| 推房 | 业主跟进、议价、回访、谈委托、带看、勘察看房、派单驻守、AI业主跟进、拜访、保留、电话、短信、房源未认证、激活、接待、勘察、看房、派单、企业来电通、去电、申请、未接通、信函、修改、邮件、转房客 | 自定义 | 修改 删除 | +| 维护 | 业主跟进、议价、回访、谈委托、带看、勘察看房、派单驻守、AI业主跟进、拜访、保留、电话、短信、房源未认证、激活、接待、勘察、看房、派单、企业来电通、去电、申请、未接通、信函、修改、邮件、转房客 | 自定义 | 修改 删除 | +| 其他 | 业主跟进、议价、回访、谈委托、带看、勘察看房、派单驻守、AI业主跟进、拜访、保留、电话、短信、房源未认证、激活、接待、勘察、看房、派单、企业来电通、去电、申请、未接通、信函、修改、邮件、转房客 | 自定义 | 修改 删除 | + +#### 跟进-模板设置 + +| 模版名称 | 模版内容 | 所属跟进目的 | 来源 | 操作 | +| ------ | --------------------------------------------------------------- | ------------------------------------------------------------------------------------------------ | --- | ----- | +| 买卖重要信息 | 1.税费情况: 2.购房付款方式: 3.贷款情况: 4.联系人是否是产权人: 5.学区情况: 6.户口情况: | 业主跟进、议价、回访、谈委托、带看、勘察看房、派单驻守、AI业主跟进、拜访、保留、电话、短信、房源未认证、激活、接待、勘察、看房、派单、企业来电通、去电、申请、未接通、信函、修改、邮件、转房客 | 预制 | 修改 删除 | +| 议价 | 1.最新价格: 2.心里底价: 3.业主心态: 4.付款方式: 5.税费情况: 6.不同意降价的原因: 7.价格到了是否能签: | 议价 | 预制 | 修改 删除 | +#### 面访设置 + +| 设置项 | 当前值 | 说明 | +| ------------------ | -------- | ------------------------------------------------- | +| 录入面访 | 🔴(开启) | 若开启,则可录入面访 | +| 补录时间限制 | 最多可补录7天前 | 填0代表只可录入当天的面访 | +| 面访附件必填 | 🔴(开启) | 若开启,则录入面访时附件必填 | +| 面访图片只可实时拍照,不可从相册选择 | ⚪(关闭) | 若开启,则面访图片只可实时拍照(拍照包含时间和地点),不可从相册选择;若关闭,可从相册选择任意图片 | + +#### 业主服务报告 + +| 设置项 | 当前值 | 说明 | +| ------ | ------- | ------------------------------------------- | +| 公司logo | (上传图片) | 推荐尺寸200x100px,png格式 | +| 公司简称 | - | 公司简称,建议不超过10字 | +| 报告主题色 | (橙红色色块) | 点击色块修改主题色 | +| 二维码 | - | | +| 封面 | (上传图片) | 展示在看房报告的首页,适用于对公司服务形象要求较高的企业,推荐尺寸为511*742px | +| 封底 | (上传图片) | 展示在看房报告的最后,适用于对公司服务形象要求较高的企业,推荐尺寸为511*742px | + +#### 回访设置 + +| 设置项 | 当前值 | 说明 | +| --------- | ----- | -------------------------------- | +| 新增/激活房源回访 | ⚪(关闭) | 若开启,将对新增/激活房源的「申请人」的「直属上级」开放回访入口 | +#### 业主话术宝典 + +**业主话术宝典**                         新增话术宝典 + +| 话术名称 | 话术内容 | 来源 | 操作 | +| ---- | -------- | --- | ----- | +| 议价话术 | 议价话术.pdf | 预制 | 修改 删除 | + + + +### 2.6 实勘视频/VR/实地核验 + **<待补充>** + +### 2.7 预约拍摄设置 + **<待补充>** +### 2.8 钥匙/委托/政府核验 +#### 钥匙设置 + +**基础设置** + +|设置项|当前值|说明| +|---|---|---| +|钥匙新增/编辑附件必填|⚪(关闭)|若开启,新增/编辑钥匙必须上传附件| +|借钥匙的附件必填|⚪(关闭)|若开启,员工借机械锁的钥匙时(含直接借钥匙和扫码借钥匙),必须上传抵押证件| +|电脑端归还钥匙时附件必填|⚪(关闭)|若开启,员工在电脑端归还机械锁钥匙时,必须上传归还证明。移动端不受开关影响,必须上传| +|钥匙退回业主附件必填|⚪(关闭)|若开启,将钥匙退回业主时,必须上传附件| +|新增钥匙时的录音要求|非必选|经纪人仅可选择到48小时内他自己的跟进录音;当「新增钥匙成功的管理要求」选择"业主授权或钥匙审批通过后,钥匙新增完成"时,"仅认证方式为「发起审批」时录音必选"才会生效| +|若录音仍在生成中,可选择话单编号|🔴(开启)|开启后,若录音仍在生成中,可选择话单编号| + +**新增钥匙时的业主在线确认钥匙授权设置** + +|设置项|当前值|说明| +|---|---|---| +|新增钥匙时,业主在线确认钥匙授权|⚪(关闭)|若开启,则经纪人在新增钥匙时,可以邀请业主做在线确认钥匙的授权| + +**消息提醒设置** + +| 设置项 | 当前值 | 说明 | +| ----------------------- | ----- | --------------------------------------------------------------------------------------------------- | +| 钥匙新增成功后,通知到保管部门的哪个职务的员工 | 无 | 请注意:1、仅当保管部门是门店或店组时,才给所选职务的员工发消息,否则不发送消息;2、通知的部门范围,含保管部门及其下属子部门 | +| 钥匙借出和归还,通知钥匙方 | ⚪(关闭) | | +| 超时未归还钥匙提醒 | 1天 | 超过所配置时间未归还钥匙,每天给经纪人发归还钥匙的消息提醒;借出当日算1天。举例:设置1天未归还提醒,10月1日借钥匙未归还,则10月2日起每天上午9点,经纪人收到提醒(直至归还)。注:不填则不提醒 | + +#### 委托-基础设置 + +| 设置项 | 当前值 | 说明 | +| --------------------------------- | -------------------- | ----------------------------------------------------------- | +| 委托录入类型 | 一般租/售委托/独家租/售委托/速销委托 | 业务员在新增委托时可选择的委托类型 | +| 同时段录委托需符合优先级规则 | 🔴(开启) | 若开启,同一委托期限内,若已存在更高级别委托,不允许录入了更低级别委托(委托级别:速销>独家>一般) | +| 同时段内有在线签署中&签署成功的委托,则其他人不可发起 | ⚪(关闭) | 若开启,则同时段内若有在线签署中或签署成功的委托,则其他人不可发起,保护时段内在线签约人的权益 | +| 是否开启隐盘功能 | ⚪(关闭) | 开启后,独家委托与速销委托可以设置隐盘,限制无管理隐盘权限的人的相关操作 | +| 业务员可申请隐盘天数配置 | 无 | 业务员在新增委托时可下拉选择的隐盘天数 | +| 委托到期提醒 | 1天 | 委托到期前*天提醒房源所有相关方 | +| 线上申请速销金出款/回收 | ⚪(关闭) | 开启后,速销金的出款/回收需发起审批;速销委托审批通过后自动发起速销金出款任务,委托终止自动发起速销金去向标记任务 | +| 小程序签约委托短信邀请 | ⚪(关闭) | 开启后,经纪人可短信邀请客户小程序签约(短信需从公司账户扣费) | +| 委托的「产权人/授权第三方」的联系人允许选择"其他" | 🔴(开启) | 若开启,则员工可直接添加号码或从已有号码里选择;若关闭,则经纪人不可直接添加号码,必须从房源业主/联系人上选择已有号码 | +| 委托签署后,委托人和产权人真实姓名覆盖房源上对应的业主/联系人姓名 | 🔴(开启) | | +| 成为独家售委托方后覆盖 | 无 | 开启后,委托审批通过且委托期限开始,成为委托方后,覆盖相关方,若维护人拆分租售,则覆盖售维护人 | +| 成为速销委托方后覆盖 | 无 | 开启后,委托审批通过且委托期限开始,成为委托方后,覆盖相关方,若维护人拆分租售,则覆盖售维护人 | + +#### 委托到期/作废后发送消息给指定人 +指定人可在每天早上10点收到前一天到期/作废的独家委托、速销委托明细汇总 + +| 委托类型 | 消息发送条件 | 指定人 | 操作 | +| --------- | --------- | --- | --- | +| 速销委托、独家委托 | 委托到期、委托作废 | - | 编辑 | + +#### 委托-附件及签约方式设置 +若开启在线签约,请至我的模版中设置合同模版 + +| 委托类型 | 线下签约必填附件 | 线上签约必填附件 | 支持补录附件 | 委托书签约方式 | 小程序签约时允许业主主动上传身份证&产证图片 | 操作 | +| ----- | --------------- | ----------- | ------ | ------- | ---------------------- | --- | +| 一般售委托 | 委托书 | - | - | 线下签约 | - | 编辑 | +| 一般租委托 | 委托书 | - | - | 线下签约 | - | 编辑 | +| 独家售委托 | 委托书、产权人身份证件、房产证 | 产权人身份证件、房产证 | - | 线下签约 | - | 编辑 | +| 独家租委托 | 委托书、产权人身份证件、房产证 | 产权人身份证件、房产证 | - | 线下签约 | - | 编辑 | +| 速销委托 | 委托书、产权人身份证件、房产证 | 产权人身份证件、房产证 | - | 线下签约 | - | 编辑 | + +#### 政府核验-基础设置 +**政府核验 - 基础设置**                         编辑 + +| 设置项 | 当前值 | 说明 | +| ---------- | ----- | -------------------------------------- | +| 存量房源核验信息录入 | ⚪(关闭) | 若开启,可录入核验信息;核验填写内容在下方「政府核验-录入字段设置」内配置。 | + +#### 政府核验-录入字段设置 +**售政府核验录入设置** + +|规则应用范围|必填字段|选填字段|操作| +|---|---|---|---| +|暂无录入设置 新增设置|||| + +**租政府核验录入设置** + +| 规则应用范围 | 必填字段 | 选填字段 | 操作 | +| ----------- | ---- | ---- | --- | +| 暂无录入设置 新增设置 | | | | + +### 2.9 作业盘设置 + **<待补充>** + +### 2.10维护人员设置 + **<待补充>** + +### 列表/房源/等级 +#### 房源列表设置 +**房源列表设置**                         修改 + +| 设置项 | 当前值 | 说明 | +| ----------- | ------ | ---------------------------------------------------------------------------------------------------- | +| 不在房源列表展示的类型 | - | 未通过政府核验状态(未上传、审批中、已作废、已过期),对全员生效(为防止缓存生效,建议提前一天配置) | +| 房源列表默认可见设置 | ⚪(关闭) | 用于配置不同职务进入全部/未挂牌/成交房源列表时,列表默认展示哪些的房源;全部/未挂牌列表选择默认展示房源后,未默认展示的房源状态仍可以通过列表筛选项进行查询展示,成交列表不展示的房源不会被搜索出来。 | +| 他售房源展示在成交列表 | 🔴(开启) | 开启后,成交列表将展示我售和他售房源 | + +#### 房源等级设置 + +| 设置项 | 当前值 | 说明 | +| ------------------ | --- | --------------------------------------------- | +| 长期不活跃暂缓房源降级(D级转E级) | - | 控制长期未挂牌的D级"暂缓"房源的等级变更,超过后自动转E级;建议365天,0/空=不执行 | + +### 营销设置 + + +### 楼盘设置 +#### 楼盘基本设置 + +以下是截图中的完整文字内容: + +**楼盘基础设置** + +|设置项|当前值|说明| +|---|---|---| +|开启楼盘重复查询|🔴(开启)|若启用,则会定时进行楼盘重复查询提醒| +|录入房源时可选择未新增的标准楼盘|有房号的标准小区|开启时,经纪人可在房源录入/预录入环节进行楼盘搜索,检索范围会根据配置增加未新增下来的标准楼盘;注:如果配置【全部标准小区】,则对于磐石没有房号的小区,在房源录入时可自行新增楼栋-单元-房号,请谨慎使用;预录入环节不会展示【没有房号的标准小区】| +|房源自动合并规则|按照房源状态进行保留|选择一键合并时,房源合并自动保留哪个的配置选项| +|楼盘/楼栋/单元/房号数据删除无视是否存在房源|🔴(开启)|若启用,删除对应数据会将房源一并删除| +|候审房源地址|🔴(开启)|若启用,录入房源若未检索到栋/单元/房号数据时,提示录入"候审地址"入口,可优先录入地址,后提交材料反馈| +|提交超时有效期(h)|48|自录入成功时间起开始计算,超出设定的有效期时间后,则释放相应地址| +|转正超时有效期(h)|24|状态变更为"待转正"时间起开始计算,超出设定的有效期时间后,则释放相应地址| +|是否接收楼盘新增消息|⚪(关闭)|开启后,楼盘管理员可接收58楼盘字典的新增楼盘的通知| + +| 楼盘管理员 接受楼盘相关消息通知的人员 | 操作 | +| ------------------- | --- | +| 系统管理组-XXX | | + +### 资料房/业主委托/预录入 + + +### 隐私保护及防骚扰 +#### 房源地址隐藏 +**房源地址隐藏** 楼栋单元房号排序受房源地址隐藏规则影响,为防止泄盘当筛选了未设置隐藏的房源条件时可支持排序   修改 + +| 设置项 | 当前值 | 说明 | +| ----------------------- | ---------------- | ----------------------------------------------------------------- | +| 隐藏房源名称 | PC端/移动端 | 控制PC端/移动端:房源列表和房源详情等的房源名称的隐藏 | +| 隐藏房源名称内容 | 楼栋/单元/房号/实际楼层+房号 | 隐藏房源名称内容 | +| 隐藏房源名称属性范围 | 特盘/封盘 | 隐藏已勾选房源属性的字段内容 | +| 房源列表的"楼栋单元房号",哪些不允许精确搜索 | 楼栋/单元/房号/实际楼层+房号 | 若允许精确搜索,在房源列表搜索楼栋/单元时,会有下拉框展示对应小区的楼栋/单元,可直接点选;若不允许精确搜索,则楼栋/单元无下拉框 | + +#### 号码拨打限制 +**号码拨打限制**                         修改 + +| 设置项 | 当前值 | 说明 | +| ---------------- | ------- | ------------------------------------------ | +| 每套房源每天可拨打/查看号码次数 | 999次 | 该套房源拨打和查看号码的总次数,999=不限制,0=不允许 | +| 每天可拨打业主号码时间范围 | 从0时至24时 | 每天只可在设置的时间范围内拨打号码(仅限商务号/回拨,如不用商务号/回拨不受此限制) | + +#### 房源成交后的保护机制 +**房源成交后的保护机制** 机制一更灵活(均可查看房源),机制二保护性更高(仅相关方可查看房源)。建议根据管理强度选择其中一种。  修改 + +**机制一:房源成交N天内封盘,其他经纪人不可联系业主/查看地址,只有相关方可操作** + +**我售** + +|设置项|当前值|说明| +|---|---|---| +|房源变为我售,自动封盘|无|交易转定/签约,房源状态变更为我售时,系统自动将该房源转为封盘| +|售房的封盘期限|999天后解封|房源属性被修改为封盘后,何时之后会自动解除封盘变成公盘。若选择按固定期限,999=不自动变为公盘,0=仅当天封盘| + +**我租** + +|设置项|当前值|说明| +|---|---|---| +|房源变为我租,自动封盘|无|交易签约,房源状态变更为我租时,系统自动将该房源转为封盘| +|租房的封盘期限|999天后解封|房源属性被修改为封盘后,何时之后会自动解除封盘变成公盘。若选择按固定期限,999=不自动变为公盘,0=仅当天封盘| + +|提示|操作| +|---|---| +|请确认已设置以下权限,否则机制不生效|| +|关闭经纪人查看封盘地址/电话权限说明|去关闭 怎么关闭 ②| +|开启相关方的查看房源权限|去开启 怎么开启 ②| + +**机制二:房源成交N天内保护,其他经纪人不可查看该房源,只有相关方可查看** + +|设置项|当前值|说明| +|---|---|---| +|我租状态保护时长|60天|控制"我租"房源的保护时长,在保护时间内,无查看权限的员工不可查看;0=不保护(0~999)| +|我售状态保护时长|60天|控制"我售"房源的保护时长,在保护时间内,无查看权限的员工不可查看;0=不保护(0~999)| +|他租状态保护时长|0天|控制"他租"房源的保护时长,在保护时间内,无查看权限的员工不可查看;0=不保护(0~999)| +|他售状态保护时长|0天|控制"他售"房源的保护时长,在保护时间内,无查看权限的员工不可查看;0=不保护(0~999)| + +|提示|操作| +|---|---| +|请确认已设置以下权限,否则机制不生效|| +|关闭经纪人查看保护期内房源权限|去关闭 怎么关闭 ②| +|开启相关方的查看房源权限|去开启 怎么开启 ②| + +**房源成交/下架后业主处理**   修改 + +| 设置项 | 当前值 | 说明 | +| ----------- | --- | ------------------------------------------- | +| 标记业主为历史成交业主 | 我售 | 出售/租售房源,手动修改房态或因交易变更房态为选中状态时,业主将自动标记为历史成交业主 | + +#### 房源成交/下架后业主处理 + +**房源成交/下架后业主处理**                         修改 + +| 设置项 | 当前值 | 说明 | +| ----------- | --- | ------------------------------------------- | +| 标记业主为历史成交业主 | 我售 | 出售/租售房源,手动修改房态或因交易变更房态为选中状态时,业主将自动标记为历史成交业主 | +#### 成交消息设置 +**成交消息设置**                         修改 + +**房源成交后发送消息给相关人员** + +| 房源状态 | 消息发送时间 | 接收消息的相关人员 | 对应相关方的直属上级是否接收消息 | +| ----- | ------ | --------- | ---------------- | +| 房源变我售 | 立刻发 | 该房源所有相关方 | 否 | +| 房源变我租 | 立刻发 | 该房源所有相关方 | 否 | +### 房源检查及纠错 + **<待补充>** + + +## 3. 新房设置 +### 新房基本设置 + +### 新房参数设置 + + +## 4. 客源设置 +### 4.1客源基本配置 +#### 新增设置 + +| 设置项 | 当前值 | 说明 | +| --------------- | ------ | -------------------------------------------------------------------------------- | +| 新增私客查重范围 | 本人 | 查重范围定义:N级部门及其所有直系子部门 | +| 重客提醒范围 | 无 | 开启配置后,选择范围内的经纪人也有相同号码的私客,将展示出归属人和首录人信息。因涉及私密信息,请谨慎开启配置 | +| 新增私客的公客查重范围 | 无 | 选择本部时新增私客不与登录人可见范围内的公客重复;选择全部时新增私客不与全公司公客重复,新增客户必须从公客中拉私。选择无时,新增私客可以与公客重复,不进行判重。 | +| 成交客查重范围 | 不查重 | 设置新增私客时与成交客的查重范围。 | +| 是否开启公私客、公客成交客合并 | 🔴(开启) | | +| 自动合并与成交客重复的公客 | ⚪(关闭) | 开启后,自动将与成交客号码相同的公司内公客合并进成交客,每天自动执行一次 | +| 新增私客驳回后跳公 | 🔴(开启) | 若开启,新增私客驳回后,需要在规定时间内(延期处理设置项中选择)完善信息并重新提交,否则此客跳公;如关闭,审批驳回客源自动删除 | +| 新增私客驳回后延期处理 | 立即生效 | 若选择立即生效,则新增私客驳回后立即跳公/删除;若选择延期,则经纪人可以在1天/2天内修改客源信息后重新提交客增审批 | +| 允许新房场景快速录客 | ⚪(关闭) | 开启后,在手机端新房报备页面需要添加客源时,允许只填写姓名性别电话状态后直接进行报备 | +#### 必填设置 + +| 分类 | 设置项(左列) | 状态 | 设置项(右列) | 状态 | +| -------- | ------- | ------ | ------- | ------ | +| **基础信息** | | | | | +| | 等级 | 🔴(开启) | 名下房产 | ⚪(关闭) | +| | 来源 | 🔴(开启) | 贷款记录 | ⚪(关闭) | +| | 购房目的 | ⚪(关闭) | 付款方式 | ⚪(关闭) | +| | 租赁方式 | 🔴(开启) | | | +| **需求信息** | | | | | +| | 总价 | 🔴(开启) | 租价 | 🔴(开启) | +| | 居室 | 🔴(开启) | 面积 | 🔴(开启) | +| | 装修 | ⚪(关闭) | 意向商圈 | ⚪(关闭) | +| | 意向新房楼盘 | ⚪(关闭) | 意向小区 | ⚪(关闭) | +| | 楼层 | ⚪(关闭) | 交通 | ⚪(关闭) | +| | 备注 | ⚪(关闭) | | | +#### 其他设置 + +|设置项|当前值|说明| +|---|---|---| +|每个公客每天可拨打/查看号码次数|5次|| +|影响最后跟进日的跟进类型|全部写入跟进|敏感信息跟进包括新增/编辑/删除联系人;修改跟进包括编辑基础信息/需求/等级/状态;其他跟进包括交易相关/主动转公客/公客转私客/客源成交| +|影响最后跟进日的跟进范围|全部|选择客源归属人后,在手写跟进范围内,仅当前客源归属人的跟进计算最后跟进日,他人的手写跟进不计算| +|保护客数量限制|每个经纪人可最多设置0个保护客|最多设置100个保护客(保护客不参与跳公)| +|跟进置顶条数上限|5条|单个私客/公客 可置顶的写入跟进数量上限,999=不限制,0=不允许| +|离职员工的私客自动转公|⚪(关闭)|开启后,离职员工的私客,将自动跳转至门店/店组(若有) 公客池;历史离职员工的私客也将在当日凌晨自动跳公| +|成交人非归属人时转成交状态|🔴(开启)|开启后,客户成交人非归属人时,客户停留在私客,不转为成交客,状态调整为"已租/已购";关闭时,将归属人的客户转为成交客,归属人和成交人均可看见该客户| +|客源批量处理时刻|系统自动|若为系统自动,则每日凌晨进行客源批量处理;处理范围包括资料客/营销客/私客转公、客源转暂缓、公客分级跳| +|员工请假是否执行客源批处理|🔴(开启)|若关闭,则员工当天请假时(【按天请假】或【按小时请假,当天请假小时数≥8小时】),凌晨不执行该员工的客源批量处理操作。| +|同一客户成交是否提醒该客户的其他归属人|🔴(开启)|开启后,客户被本公司经纪人转为"我购/我租"状态时,将自动通知同号码客户的其他归属人。| +|展示成交信息|🔴(开启)|通知同号码成交客的其他归属人时,展示成交人、成交房源等信息信息。| +|保护客跨部门操作|⚪(关闭)|在"本部"权限范围内,控制操作保护客范围,开启则表示查看、操作本部及以及扩充部门范围的保护客;关闭则只查看准确的本部门数据| +|私客(非保护客)跨部门操作|⚪(关闭)|在"本部"权限范围内,控制操作非保护客的私客范围,开启则表示操作本部及以及扩充部门范围的非保护客的私客;关闭则只查看准确的本部门数据| +|公客跨部门操作|⚪(关闭)|在"本部"权限范围内,控制操作公客范围,开启则表示操作本部及以及扩充部门范围的公客;关闭则只查看准确的本部门数据| +|成交客跨部门操作|⚪(关闭)|在"本部"权限范围内,控制操作成交客范围,开启则表示操作本部及以及扩充部门范围的成交客;关闭则只查看准确的本部门数据| +|公客自动合并|🔴(开启)|开启开关后,公司的同归属人公客将进行自动合并。| +|公客中证件信息不可见|⚪(关闭)|开启开关后,在公客信息中,证件信息不可见。| +|向客源合作人发送状态变化通知|⚪(关闭)|开启后,当客源状态发生变化会向合作人发送站内消息。| +|手动转公发送消息通知|⚪(关闭)|开启后,有经纪人手动将私客转公时向所选人员发送消息通知。| +|智能配盘配盘范围|公盘、私盘、特盘、封盘|智能配盘仅推送选择的房源| +|客源强制写跟进|⚪(关闭)|开启后,查看过客源的电话号码或者拨打过电话后必须写跟进,否则不能查看或拨打其他电话号码| +|客源跟进必填图片|-|开启后,对已设置的跟进场景提交时图片校验必填,请开启后提示升级 app 至最新版!| +#### 资料客设置 + +|设置项|当前值|说明| +|---|---|---| +|每个资料客每天可拨打/查看号码次数限制|5次|| +|重复资料客是否隐藏|⚪(关闭)|开启后,若司内有多个资料客重复,则保留新增时间最早的资料客,后面新增的资料客直接在列表隐藏,且无法通过详情页翻页查看。| +|资料客跨部门操作|⚪(关闭)|在"本部"权限范围内,控制操作资料客范围,开启则表示查看、操作本部及以及扩充部门范围的资料客;关闭则只查看准确的本部门数据。| +|资料客转正锁定导入人为首录人|⚪(关闭)|开启后,资料客转正时会自动填充导入人为首录人并锁定,仅有权限角色可以修改。| +|资料客导入时与公司客源查重|⚪(关闭)|开启后,资料客导入时会与所选类型的客源查重,重复的资料客会被隐藏不在列表中展示。| +|资料客查看号码视为拨打电话|⚪(关闭)|开启后,成功查看资料客号码会视为成功拨出号码,需填写联系情况。| +#### 私客列表展示设置 + **<待补充>** + +#### 公客列表展示设置 + **<待补充>** + +#### 带看设置 +以下是截图中的完整文字内容: + +| 设置项 | 当前值 | 说明 | +| ----------------------- | ---------- | ------------------------------------------------------------------------------------------------------ | +| 请选择录入带看的客源类型 | 公客、私客、成交客 | 允许所选的客源类型创建带看单 | +| 是否开启补录带看 | 🔴(开启) | 若关闭则PC端无法新增带看,移动端只能轨迹带看或打卡带看 | +| 请选择补录带看业务类型 | 二手、租房、新房 | 允许使用补录带看方式创建该类型的带看单 | +| 补录带看时间配置 | 能补录过去30天 | 时间范围:0~30天,0天表示今天 | +| 是否在补录带看时可关联外出记录 | ⚪(关闭) | 开启后,可以在补录带看时关联外出记录。 | +| 带看回访任务开始时间以带看时间计算 | 🔴(开启) | 开启时,带看回访任务的开始时间为带看时间,关闭时,带看回访任务的开始时间为带看单的提交时间。 | +| 带看情况必填 | 🔴(开启) | | +| 带看附件必填 | ⚪(关闭) | 当带看附件为必填时,可配合使用【是否图片位置定位】控制上传的图片是否含位置 | +| 带看反馈必填 | ⚪(关闭) | 开启后录入带看时必须对二手带看单内的房源录入带看反馈,符合条件的反馈内容将展示在安居客&58app房源页,请填写合适的文字内容 | +| 新房带看无需关联报备记录 | ⚪(关闭) | 开启后,新房代理盘进行直接带看、补录带看时不需要关联报备记录即可提交。注意!开启后将允许员工录入不关联报备记录的新房带看,带看真实性会降低,同时新房的到访保护期、新房交易进度等功能将不可用,建议保持关闭。 | +| 是否开启审核通过后作废 | ⚪(关闭) | 若关闭则无作废功能,开启后可在有效时间内作废审核通过的带看单(权限配置请移步【角色权限-客源-带看权限】) | +| 可作废时间设置 | 能作废审批通过后0天 | 控制最长可以审核通过后几天的带看,0表示今天,999表示无限 | +| 陪看人必填 | ⚪(关闭) | 当开启时,录入带看必须至少有1名陪看人 | +| 是否开启陪看定位 | ⚪(关闭) | 在app端直接带看时邀请的陪看人必须进行定位 | +| 是否开启带看评价 | ⚪(关闭) | 若开启则带看审批通过后经纪人可邀请客户进行带看评价 | +| 带看确认书 | ⚪(关闭) | 若开启则经纪人可录入租/售带看单后实现带看确认单在线签约 | +| 带看日期不能早于房源首次录入日期 | ⚪(关闭) | 开启后带看日期不能早于房源首次录入日期 | +| 带看日期不能早于客源首次录入日期 | ⚪(关闭) | 开启后带看日期不能早于客源首次录入日期 | +| 是否要求录入带看的房源有效(出售、出租、租售) | ⚪(关闭) | 有效房源的判断不能早于实时房源状态,并非带看日期时的房源状态 | +| 带看评价本人是否可见 | 🔴(开启) | 关闭后本人权限不可见客户的带看评价反馈,仅本部全部权限可见 | +| 带看首看保护 🔘 | ⚪(关闭) | 开启后可分别根据租售设置首看保护时间 | +| 是否支持生成看房报告 | 🔴(开启) | 看房报告用于带看后生成pdf文件发送给客户,提升公司服务品质,仅支持二手 | +| 二手看房报告加入交易保障宣传页 | 🔴(开启) | 如开启,二手看房报告将加入二手交易保障宣传页,未上传服务承诺时将作为最后一页,上传服务承诺时将在服务承诺的前一页 | +| 上传服务承诺 | 上传图片 | 展示在看房报告的最后,展示公司服务承诺和服务标准,推荐尺寸为511*742px | +| 上传封面图 | 上传图片 | 展示在看房报告的首页,适用于对公司服务形象要求较高的企业,推荐尺寸为511*742px | +| 上传公司logo | 上传图片 | 展示在看房报告封面图及内页页眉部分,若不上传则以系统上传的logo展示,推荐尺寸为200*100px | +#### 营销客设置 + +|设置项|当前值|说明| +|---|---|---| +|允许隐号客录入客源|🔴(开启)|若关闭,隐号客必须完善号码后才能拉私、跳公。| +|客源来源自动匹配营销客来源时限|30日|在营销客新增后的一定天数内,先新增同一号码的客源后新增营销客时,将客源修改为营销客来源。| + +#### 预约带看设置 + +|设置项|当前值|说明| +|---|---|---| +|开启预约带看|⚪(关闭)|关闭则不展示新房预约入口| +|二租预约带看开关|🔴(开启)|| +|预约带看作废时限|超过24小时自动作废|填写数字,1-999,999表示不限| +|是否限制可预约时间|⚪(关闭)|若关闭表示预约时间不限,可提前录入带看| + +#### 空看设置 + +|设置项|当前值|说明| +|---|---|---| +|是否管理空看/踩盘发起条件|⚪(关闭)|若关闭则表示不能发起空看| +|空看/踩盘图片必填|⚪(关闭)|当附件为必填时,可配合使用【是否图片位置定位】控制上传的图片是否含位置| +|是否图片位置定位|⚪(关闭)|开启后经纪人可进行补录空看/踩盘,当【空看/踩盘附件必填】开启时,上传附件时至少需要有一张图片有地理位置信息| +|空看/踩盘情况必填|⚪(关闭)|| +|是否支持补录空看/踩盘|🔴(开启)|若关闭后仅app可录入轨迹空看/踩盘| +|请选择补录空看业务类型|租房、二手、新房|允许使用补录空看方式创建该类型的空看单| +|同经纪人同房源空看/踩盘限制|1天内,同一经纪人同一房源只能发起1次|若要求房源同经纪人不可发起重复空看可填999| +|补录空看/踩盘时间限制|可补录1天空看|若填写0表示只可录入当天空看| +|是否开启陪看定位|⚪(关闭)|在app端直接空看/踩盘时邀请的陪看人必须进行定位| +|是否要求房源实勘后录入空看|⚪(关闭)|开启后必须房源录入实勘后才允许录入空看| +|是否要求录入空看的房源有效(出售、出租、租售)|⚪(关闭)|有效房源的判断时间为提交时实时房源状态,并非空看日期时的房源状态| + + +### 4.2 客源参数配置 + +#### 预设参数 +**预设参数不可修改初始项目值,智能新增项目值** + +|参数项|项目值|操作| +|---|---|---| +|跟进目的|回拨、推房、带看、维护、其他、带看回访、新增私客回访、拜访、保留、电话、短信、房源未认证、激活、接待、勘察、看房、派单、企业来电通、去电、申请、未接通、信函、修改、邮件、转房客|修改| +|来源|线上:网络-网络,58同城-58同城,安居客-安居客,微信-微信,巧客力-巧客力,抖音-抖音-小程序,官网App-官网App,诸葛-诸葛-话单,诸葛-诸葛-留资,诸葛-诸葛-im,房天下-房天下-来电,房天下-房天下-其他,房天下-房天下-im,高德-高德-话单,高德-高德-留资,高德-高德-im,百度-百度-话单,百度-百度-留资,百度-百度-im,幸福里-幸福里-留资,抖音-抖音-短视频,抖音-抖音-直播,抖音-抖音-企业主页,抖音-抖音-私信,抖音-抖音-订阅文章,抖音-抖音-群聊,抖音-抖音-独立店铺,抖音-抖音-搜索,抖音-抖音-服务,抖音-抖音-其他,抖音-抖音-平台房源,抖音-抖音-手动录入,购房通-购房通-微聊,购房通-购房通-电话,金色-金色-小程序,视频号-视频号-私信,小红书-小红书-私信留资,小红书-小红书-预约组件,小红书-小红书-名片(企微),小红书-小红书-服务卡,小红书-小红书-落地页,58-58,赶集网-赶集网,来电-来电,来电通(微聊)-来电通(微聊) 线下:门店接待,社区接待,驻守派单,业主转客,老客户转介绍,同事朋友介绍,老客户委托,上门,同事,资料客,系统导入,广告,来访,朋友,扫街,中介|修改| +#### 自定义参数 + **<待补充>** 可新增自定义参数 + +### 4.3 客源相关方配置 +#### 添加相关方 + **<待补充>** + +#### 相关方配置 + +|相关方|相关方说明|状态|操作| +|---|---|---|---| +|首录人|将客源录入系统的员工|● 启用|权限设置| +|归属人|将客源设为私客的员工|● 启用|| +|成交人|将客源成交的员工|● 启用|权限设置| +|合作人|合作人可与归属人一起做跟进、带看、成交行为;启用配置后支持添加合作人,最多5个|● 停用|权限设置 启用| +|归属人1||● 停用|权限设置 启用 编辑 删除| +|归属人2||● 停用|权限设置 启用 编辑 删除| +|归属人3||● 停用|权限设置 启用 编辑 删除| +|首看保护人|带看首看人保护仅应用于开启了带看首看保护规则时交易分佣使用|● 停用|| +#### 相关方权限设置 + **<待补充>** + + +### 4.4 客源行政跨部权限 + **<待补充>** + +**提示信息:** 跨部门可以拥有被管理部门的选定权限(子部门需单独选择),且仅当跨部部门员工对应权限为本部时才生效; 例如,跨部门的员工A的查看公客权限为本人,经理B为本部时,在本页面开启查看跨部的公客时,经纪人A无法看到被管理部门的公客,而经理B可以看到。 + +**请选择跨部部门(左侧列表):** + +|层级|部门/组名| +|---|---| +|一级|沪居地产| +|二级|嘉宏公寓店| +|三级|嘉宏公寓店一组| +|三级|嘉宏公寓店业务部| +|二级|上海豪园店| +|三级|上海豪园店一组| +|三级|上海豪园店业务部| +|三级|上海豪园店二组| +|二级|都市港湾店| +|三级|都市港湾店一组(红色高亮)| +|三级|都市港湾店三组| +|三级|都市港湾店业务部| +|二级|系统管理组| + +**请选择被管理部门及权限(右侧表格):** + +|部门|查看客源详情|常规业务操作(包括查看跟进、编辑客户等)|敏感业务操作(包括查看号码、拨号、修改联系人)| +|---|---|---|---| +|沪居地产|关闭|关闭|关闭| +|嘉宏公寓店|关闭|关闭|关闭| +|嘉宏公寓店一组|关闭|关闭|关闭| +|嘉宏公寓店业务部|关闭|关闭|关闭| +|上海豪园店|关闭|关闭|关闭| +|上海豪园店一组|关闭|关闭|关闭| +|上海豪园店业务部|关闭|关闭|关闭| +|上海豪园店二组|关闭|关闭|关闭| +|都市港湾店|关闭|关闭|关闭| +|都市港湾店一组|关闭|关闭|关闭| +|都市港湾店三组|关闭|关闭|关闭| +|都市港湾店业务部|关闭|关闭|关闭| +|系统管理组|关闭|关闭|关闭| + +## 5. 交易设置 + +### 5.1 交易流程 +**基础设置**   修改 + +|设置项|当前值|说明| +|---|---|---| +|意向超期未转定/签约,交易自动退意向|⚪(关闭)|至意向截止日,超期后自动退意向| +|意向超期未转定/签约,房源自动解封|天|从录入意向次日起计算,超期后房源自动解封| +|意向金超期未收,自动退意向|天|从录入意向次日起计算,超期后自动退意向| +|转定后房客转为成交状态|🔴(开启)|开启则转定后房客自动变为成交状态,关闭则签约后房客变为成交状态| +|二手交易未结案可结盘|⚪(关闭)|开启后二手交易售后流程未结案交易也可以操作结盘,关闭则不可操作结盘| +|二手交易/租赁交易备案信息录入|🔴(开启)|开启后具有备案管理权限的人可以操作备案信息录入,交易详情/交易列表显示备案状态及信息| +|安心交易申请时的公司主体名称|-|用于直营公司安心交易申请时兜底使用的公司主体名称,请填写正确的公司名称避免后续理赔失败。加盟型公司请维护好签约主体或者加盟门店列表| +|交易进度可分享客户/业主|🔴(开启)|开启后经纪人和售后人员可以分享交易进度给客户/业主| + +|二维码渠道|操作| +|---|---| +|摆台|下载二维码| +|宣传页|下载二维码| + +**环节管理** + +二手交易 新房交易 租赁交易 其他交易 + +|环节名称|管理要求|可评价角色|内容|操作| +|---|---|---|---|---| +|新增交易|使用此环节-不可跳过|-|-|修改| +|意向|使用此环节-可跳过|-|意向日期、意向价格、意向截止日、意向金、意向协议、产证地址、业主姓...|修改| +|转定|使用此环节-可跳过|-|转定日期、转定价格、预约签约日、定金、代收定金、居间协议、产证地址...|修改| +|签约|使用此环节-不可跳过|客户、业主、经纪人|签约日期、成交价/月租金、是否贷款、贷款方式、合同价格、首付比例、签...|修改| +|售后|使用此环节-不可跳过|-|-|| +|结案|使用此环节-不可跳过|-|结案凭证、结案日期|修改| + +**签约设置**   修改 + +|设置项|当前值|说明| +|---|---|---| +|预约签约|⚪(关闭)|若开启则可向权证派发任务,若关闭则仍由归属人完成各环节| + +**二手成交房源平台应用** + +|设置项|当前值|说明| +|---|---|---| +|二手成交房源在58安居客C端展示|⚪(关闭)|开启则代表已同意《二手成交房源在58同城、安居客平台展示的授权》开启或关闭后生效时效为次日,了解规则详情请点击《二手成交房源在58安居客C端展示规则》| +|二手成交房源用于58安居客平台评估经纪人服务能力的授权|🔴(开启)|开启则代表已同意《二手成交房源用于58同城、安居客平台评估经纪人服务能力的授权》并立即生效,由于可为经纪人在58安居客平台经纪人神奇分、二手房房东神奇分加分,本配置默认开启,后续可按需关闭。了解详情规则请点击《二手成交房源在58同城、安居客平台评估经纪人服务能力的场景应用》| + +### 5.2 二手售后流程 + +### 5.3 新房售后流程 + +### 5.4 参数&备件条件 + +#### 交易参数 + + +#### 财务参数 + + +#### 售后参数 + + +#### 附件参数 + + +## 6. 财务设置 + +### 业绩管理 + +### 资金管理 + +### 结算设置 + +### 提成设置 + + +## 7. 人事OA设置 + +### 组织人事基本设置 + +**组织人事基本设置**                         编辑 + +**员工信息设置** + +|设置项|当前值|说明| +|---|---|---| +|工龄计算方式|从首次入职开始计算|员工工龄的计算方式| +|自动生成工号|⚪(关闭)|开启后,新增员工将会按照规则自动依次递增生成工号| +|修改头像|🔴(开启)|控制是否允许员工上传和修改个人头像| +|修改联系方式|🔴(开启)|控制是否允许员工新增和修改电话信息| + +**员工入职必填设置** + +**个人信息** + +|设置项(左列)|当前值|设置项(右列)|当前值| +|---|---|---|---| +|住址|⚪(关闭)|紧急联系人及电话|⚪(关闭)| +|身份证所在地|⚪(关闭)||| + +**相关资料上传** + +|设置项(左列)|当前值|设置项(右列)|当前值| +|---|---|---|---| +|身份证|⚪(关闭)|学历证书|⚪(关闭)| +|证明文件|⚪(关闭)||| + +**账号设置** + +|设置项|当前值|说明| +|---|---|---| +|离职审批中账号冻结|⚪(关闭)|开则发起离职审批后,该员工账号冻结,审批驳回自动解冻| + +**通讯录** + +|设置项|当前值|说明| +|---|---|---| +|显示员工列表|🔴(开启)|开启则显示员工列表,关闭则不显示员工列表仅支持精确搜索员工姓名/姓名拼音首字母/工号/手机号查找(若允许按门店搜索通讯录的开关开启,则也支持按门店搜索)| + +**门店设置** + +|设置项|当前值|说明| +|---|---|---| +|自动生成门店编号|⚪(关闭)|开启后,新增门店将会按照规则自动依次递增生成门店编号| + +### 员工自动升降级设置 + +### 审批流程设置 + +## 任务设置 + +### 参数设置 + +### 入职周年祝福设置 + + +## 8. 合同设置 + +### 合同基本设置 + +## 9. 通用及移动端设置 + +### 指标设置 +### 安全设置 + +### 其他设置 + +### 电话智能监控设置 + +### 黑名单设置 + +## 10. 安装与登录设置 + + + + + + + diff --git a/Project/fonrey/PRD/系统配置/系统配置数据模型设计说明_for_Atlas.md b/Project/fonrey/PRD/系统配置/系统配置数据模型设计说明_for_Atlas.md new file mode 100644 index 00000000..ca7c5cd9 --- /dev/null +++ b/Project/fonrey/PRD/系统配置/系统配置数据模型设计说明_for_Atlas.md @@ -0,0 +1,275 @@ +# 系统配置模块 — 数据模型设计说明 + +**致**:Atlas(架构师) +**来自**:Nova(PM) +**日期**:2026-04-27 +**关联 PRD**:`PRD/系统配置/系统配置模块PRD.md` +**关联文档**:`DATA_MODEL/ENUMS.md`、`DATA_MODEL/DATA_MODEL.md` + +--- + +## 一、背景与问题 + +在设计系统配置模块的数据模型时,我发现当前 `DATA_MODEL/ENUMS.md` 已经明确了「固定枚举」与「可配置枚举」的分层设计,但两者的边界在文档中未完全显式化。本说明文档的目的是: + +1. 厘清三类配置数据各自应存在哪张表 +2. 指出需要新增的两张表及其建议 DDL +3. 说明与 ENUMS.md 现有设计的关系,以及需要 Atlas 补充/修改的内容 + +请 Atlas 在完成 `DATA_MODEL/DATA_MODEL.md` 和 `DATA_MODEL/ENUMS.md` 的修订后,同步通知 Nova 确认。 + +--- + +## 二、三类配置数据的划分 + +系统配置涉及三类性质不同的数据,**分属不同的表和 Schema**,请严格区分: + +### 类型 A:固定系统枚举(存 Public Schema / `enum_labels`) + +**特征**: +- 值域固定,所有租户共享同一套 +- 与数据库 `CHECK CONSTRAINT` 绑定(如 `decoration IN ('rough','plain','simple','medium','fine','luxury')`) +- 只能由平台研发通过 migration 修改 +- 租户管理员**无权**增删 + +**代表字段**:`property.decoration`(装修)、`property.orientation`(朝向)、`property.status`(交易状态)、`client.status`(客源状态)、`client.grade`(客源等级)、`common.gender`、`common.id_type` + +**现状**:ENUMS.md 已完整定义,`enum_labels` 表 DDL 已存在。**无需改动。** + +--- + +### 类型 B:租户可配置枚举(存 Tenant Schema / `lookup_items`,**需新增**) + +**特征**: +- 各租户选项不同(如来源渠道:A 公司有「抖音」,B 公司没有) +- 租户管理员可通过界面增删排序 +- 系统预制初始值(`is_system = True`),预制值不可删除但可停用 +- **无** `CHECK CONSTRAINT`(值域动态) +- 与 `enum_labels` 完全独立,不存在于 Public Schema + +**代表字段**:客源来源(`client.source`)、跟进目的(`client_follow_logs.follow_purpose`)、房源来源(`property.source`) + +**ENUMS.md 现状**: +- `§2.14 跟进目的` 已明确标注「此枚举为可配置项,存储方式:`lookup_items` 表」,但 `lookup_items` 的 DDL 尚未在任何 DATA_MODEL 文档中定义 +- `client.source`(来源)在 ENUMS.md 中未定义(因为它是可配置的),但竞品系统有 50+ 预制来源选项 + +**需要 Atlas 做的事**: +1. 在 `DATA_MODEL/DATA_MODEL.md` 中新增 `lookup_groups` 和 `lookup_items` 表的 DDL +2. 在 ENUMS.md 中补充一节「可配置枚举说明」,列出哪些 domain 属于 `lookup_items` 而非 `enum_labels` +3. 确认 `apps/setting/` 下新增 `lookup.py` models 文件 + +**建议 DDL(供参考,Atlas 可调整)**: + +```sql +-- ============================================================ +-- 可配置枚举分组(租户 Schema) +-- ============================================================ +CREATE TABLE lookup_groups ( + id UUID PRIMARY KEY DEFAULT gen_random_uuid(), + module VARCHAR(50) NOT NULL, -- 'client' | 'property' + key VARCHAR(100) NOT NULL, -- 'source' | 'follow_purpose' + label_zh VARCHAR(50) NOT NULL, -- 界面显示名称,如「客源来源」 + created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), + updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), + UNIQUE (module, key) +); + +-- ============================================================ +-- 可配置枚举选项(租户 Schema) +-- ============================================================ +CREATE TABLE lookup_items ( + id UUID PRIMARY KEY DEFAULT gen_random_uuid(), + group_id UUID NOT NULL REFERENCES lookup_groups(id) ON DELETE CASCADE, + value VARCHAR(100) NOT NULL, -- 存储值(英文 key,建议 snake_case) + label_zh VARCHAR(50) NOT NULL, -- 显示文本 + is_system BOOLEAN NOT NULL DEFAULT FALSE, -- True=系统预制,不可删除 + is_active BOOLEAN NOT NULL DEFAULT TRUE, + sort_order SMALLINT NOT NULL DEFAULT 0, + created_by UUID REFERENCES staff(id), + created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), + updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), + UNIQUE (group_id, value) +); + +CREATE INDEX idx_lookup_items_group_active ON lookup_items(group_id, is_active, sort_order); +``` + +**预制种子数据参考**(需写入 migration fixtures,`is_system = TRUE`): + +| module | key | 预制选项(部分) | +|--------|-----|----------------| +| `client` | `source` | 门店接待、老客户转介绍、驻守派单、上门、网络-58同城、网络-安居客、微信、朋友介绍 | +| `client` | `follow_purpose` | 回拨、推房、带看、维护、其他 | +| `property` | `source` | 主动开发、业主上门、老客户转介绍、网络来电 | + +--- + +### 类型 C:行为规则与开关(存 Tenant Schema,**需新增两张表**) + +#### C-1:键值配置表 `tenant_settings` + +**特征**: +- 存储开关(bool)、阈值(int)、枚举选择(string)等标量类型配置 +- 每个 key 全局唯一,有默认值 +- 租户管理员通过界面修改 + +**建议 DDL**: + +```sql +-- ============================================================ +-- 租户标量配置表(键值对) +-- ============================================================ +CREATE TABLE tenant_settings ( + id UUID PRIMARY KEY DEFAULT gen_random_uuid(), + category VARCHAR(50) NOT NULL, -- 配置分类:'client' | 'property' | 'showroom' + key VARCHAR(100) NOT NULL, -- 配置 key,如 'duplicate_check_scope' + value JSONB NOT NULL, -- 存储任意类型(bool/int/str/list) + value_type VARCHAR(20) NOT NULL, -- 'bool' | 'int' | 'string' | 'enum'(用于前端渲染) + updated_by UUID REFERENCES staff(id), + updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), + UNIQUE (category, key) +); +``` + +**MVP 阶段需要预置的 key**: + +| category | key | value_type | 默认值 | 说明 | +|----------|-----|-----------|--------|------| +| `client` | `duplicate_check_scope` | `enum` | `"self"` | 新增私客查重范围:`self`/`dept`/`company` | + +#### C-2:字段必填规则表 `field_requirement_rules` + +**特征**: +- 按「模块 × 实体用途 × 交易状态 × 字段」四元组确定一条规则 +- 规则值为三态:`required` / `optional` / `hidden` +- MVP 仅需支持 `property` 模块 + +**建议 DDL**: + +```sql +-- ============================================================ +-- 字段必填/隐藏规则表(租户 Schema) +-- ============================================================ +CREATE TABLE field_requirement_rules ( + id UUID PRIMARY KEY DEFAULT gen_random_uuid(), + module VARCHAR(20) NOT NULL, -- 'property' | 'client' + entity_type VARCHAR(50) NOT NULL, -- property_type 值,如 'residential' | 'shop' + trade_status VARCHAR(50) NOT NULL, -- 'sale' | 'rent' | 'sale_rent'(or '*' 表示所有) + field_key VARCHAR(50) NOT NULL, -- 字段 key,如 'orientation' | 'decoration' + requirement VARCHAR(10) NOT NULL -- 'required' | 'optional' | 'hidden' + CHECK (requirement IN ('required', 'optional', 'hidden')), + updated_by UUID REFERENCES staff(id), + updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), + UNIQUE (module, entity_type, trade_status, field_key) +); + +CREATE INDEX idx_field_req_lookup ON field_requirement_rules(module, entity_type, trade_status); +``` + +**MVP 初始规则**(建议由研发预置,管理员可覆盖): + +| module | entity_type | trade_status | field_key | requirement | +|--------|-------------|--------------|-----------|-------------| +| `property` | `residential` | `sale` | `orientation` | `optional` | +| `property` | `residential` | `sale` | `decoration` | `optional` | +| `property` | `residential` | `sale` | `floor` | `optional` | +| `property` | `residential` | `rent` | `decoration` | `optional` | +| `property` | `residential` | `rent` | `floor` | `optional` | + +--- + +## 三、与 ENUMS.md 的冲突与修改建议 + +### 冲突点 1:`lookup_items` DDL 缺失 + +**现状**:ENUMS.md §2.14 和 §六.4 已提到「可配置枚举通过 `lookup_items` 表管理」,但 `lookup_items` 的 DDL 既不在 ENUMS.md 中,也不在 DATA_MODEL.md 中。 + +**建议修改**:在 `DATA_MODEL/ENUMS.md` 末尾(或新增 §七)补充 `lookup_groups` + `lookup_items` 的 DDL 和说明,明确与 `enum_labels` 的区别: + +```markdown +## 七、可配置枚举(lookup_items) + +与 `enum_labels`(Public Schema,固定)不同,`lookup_items` 存储在 **Tenant Schema**, +由租户管理员自主维护。适用于各租户选项不同的枚举字段。 + +[此处补充 DDL 和说明] + +**属于 lookup_items 的 domain**: +- `client.source`(客源来源) +- `client.follow_purpose`(跟进目的)— 已在 §2.14 说明 +- `property.source`(房源来源) +``` + +### 冲突点 2:`client.source`(来源)未在 ENUMS.md 定义 + +**现状**:来源是可配置枚举,不应在 ENUMS.md 中定义固定值。但目前 ENUMS.md 中没有任何地方说明「哪些 domain 是可配置的、对应哪张表」,导致读者不清楚来源应该去哪里查。 + +**建议修改**:在 ENUMS.md §六 维护约定中新增一条: + +```markdown +5. **可配置枚举对照表**:以下 domain 属于 `lookup_items`,不在本文件定义, + 不建立 CHECK 约束,请查阅 `PRD/系统配置/系统配置模块PRD.md`: + - `client.source` + - `client.follow_purpose`(已标注) + - `property.source` +``` + +### 冲突点 3:`tenant_settings` 和 `field_requirement_rules` 完全缺失 + +**现状**:现有 DATA_MODEL 文档未涵盖这两张表。 + +**建议修改**:在 `DATA_MODEL/DATA_MODEL.md` 中新增「系统配置模块数据模型」章节,包含这两张表的 DDL。(本文件的建议 DDL 见第二章 C 节) + +--- + +## 四、服务层约定(供研发参考) + +所有业务模块通过统一服务层读取配置,**禁止直接查询配置表**: + +```python +# apps/setting/services/tenant_settings_service.py + +class TenantSettingsService: + + def get(self, key: str, default=None): + """ + 读取标量配置(tenant_settings 表) + 缓存 key:{tenant_schema}:setting:kv:{key},TTL 5min + """ + + def get_lookup_items(self, module: str, key: str) -> list[dict]: + """ + 获取可配置枚举选项(lookup_items 表) + 仅返回 is_active=True 的项,按 sort_order 排序 + 缓存 key:{tenant_schema}:setting:lookup:{module}.{key},TTL 5min + 写入时主动 invalidate + """ + + def get_field_requirements( + self, module: str, entity_type: str, trade_status: str + ) -> dict[str, str]: + """ + 获取字段必填规则,返回 {field_key: 'required'|'optional'|'hidden'} + 缓存 key:{tenant_schema}:setting:field_req:{module}.{entity_type}.{trade_status},TTL 5min + """ +``` + +--- + +## 五、需要 Atlas 完成的具体动作 + +| 编号 | 动作 | 修改文件 | 优先级 | +|------|------|---------|--------| +| A-1 | 新增 `lookup_groups` + `lookup_items` DDL | `DATA_MODEL/DATA_MODEL.md` 或单独 `DATA_MODEL_SETTING.md` | P0(开发依赖) | +| A-2 | 新增 `tenant_settings` DDL | 同上 | P0 | +| A-3 | 新增 `field_requirement_rules` DDL | 同上 | P0 | +| A-4 | ENUMS.md §七 补充可配置枚举说明和对照表 | `DATA_MODEL/ENUMS.md` | P0 | +| A-5 | ENUMS.md §六 维护约定新增第 5 条(可配置枚举对照) | `DATA_MODEL/ENUMS.md` | P0 | +| A-6 | 确认 `entity_type` 字段的值域与 `property.property_type` 的 CHECK 约束完全一致 | `DATA_MODEL_PROPERTY.md` 对齐 | P0 | +| A-7 | 确认 `trade_status` 字段的值域(`sale`/`rent`/`sale_rent`/`*`)是否与 `property.status` 兼容 | `DATA_MODEL_PROPERTY.md` 对齐 | P1 | + +完成以上动作后,请更新 `DATA_MODEL/DATA_MODEL.md` 的版本号,并通知 Nova 做最终 PRD 对齐确认。 + +--- + +*本文档由 Nova 起草,数据模型最终决策权归 Atlas。如有架构层面的调整,请反馈给 Nova 同步更新 PRD 中的技术考量章节。* diff --git a/Project/fonrey/PRD/系统配置/系统配置模块PRD.md b/Project/fonrey/PRD/系统配置/系统配置模块PRD.md new file mode 100644 index 00000000..6a743b25 --- /dev/null +++ b/Project/fonrey/PRD/系统配置/系统配置模块PRD.md @@ -0,0 +1,273 @@ +# PRD:系统配置模块(MVP) + +**状态**:Draft +**作者**:Nova(PM) +**最后更新**:2026-04-27 +**版本**:v0.1 +**关联 Task**:US-SETTING-001 +**相关文档**:`DATA_MODEL/ENUMS.md`、`PRD/系统配置/系统配置参数数据.md`、`DATA_MODEL/DATA_MODEL.md` + +--- + +## 1. 问题陈述 + +**背景**:Fonrey 各业务模块(房源录入、客源录入、跟进记录、带看)中存在大量下拉选项、业务规则开关、字段必填控制。如果这些值硬编码在代码中,将导致: +- 不同租户无法根据自身业务习惯调整选项(如来源渠道、跟进目的) +- 管理员无法灵活控制录入数据质量(如哪些字段必填) +- 业务规则变更(如查重范围)需要研发介入,无法自服务 + +**核心问题**:租户管理员无法通过界面自主维护业务枚举选项和录入规则,导致高频配置变更依赖研发,降低了系统的可用性与租户自服务能力。 + +**MVP 范围决策**:竞品系统配置涵盖 10+ 大类、100+ 设置项,MVP 阶段仅实现影响核心业务链路的 3 类配置,其余推迟至 P1/P2。 + +--- + +## 2. 目标与成功指标 + +| 目标 | 度量指标 | 当前基线 | 目标值 | 测量窗口 | +| ------------- | -------------- | ------------- | -------------------- | -------- | +| 管理员可自主维护枚举选项 | 系统配置依赖研发变更的工单数 | 100%(所有变更需研发) | 0(枚举类变更全部自服务) | 上线后 30 天 | +| 房源/客源录入数据质量提升 | 必填字段为空的录入比例 | 未知(当前无必填控制) | < 5% | 上线后 60 天 | +| 配置变更生效时效 | 配置保存到前端生效的时间 | N/A | ≤ 5 分钟(Redis 缓存 TTL) | — | + +--- + +## 3. 非目标(MVP 明确不做) + +以下内容在竞品中存在,但 MVP 阶段不实现: + +- ❌ 房源标签配置(颜色/排序/启用)— 标签功能整体推迟至 P1 +- ❌ 私盘数量上限配置 — 推迟至 P1(当前无私盘流转业务逻辑) +- ❌ 带看规则配置(补录时间、附件必填等)— 带看功能推迟至 P1 +- ❌ 跟进置顶条数限制 — 推迟至 P1 +- ❌ 公司信息(Logo、名称、联系方式)— 归入系统管理模块(平台运营层),非租户配置 +- ❌ 区域/商圈配置 — 归入楼盘管理模块(US-COMPLEX-003) +- ❌ 委托/交易/财务/合同相关配置 — 超出 MVP 范围 +- ❌ 通知消息配置 — P2 +- ❌ 发布平台配置 — P2 + +--- + +## 4. 目标用户 + +**主要角色**:系统管理员(租户侧,每租户 1~3 人) + +> 典型画像:门店运营负责人或行政主管,熟悉业务流程,无技术背景,通过系统后台进行日常运营配置。使用频率:初始开通时高频(完成初始化配置),此后低频(按需调整)。 + +**间接受益角色**: +- 一线经纪人 — 看到的下拉选项和必填规则由管理员配置决定 +- 店长/经理 — 配置直接影响客源来源分析报表的数据质量 + +--- + +## 5. User Stories 与验收标准 + +--- + +### US-SETTING-001-A:管理员配置可选枚举值(Lookup Items) + +> **As** 系统管理员, +> **I want** 在「系统设置 → 参数配置」页面维护各业务模块的下拉选项(如客源来源、跟进目的), +> **So that** 经纪人录入时看到的选项符合公司实际业务,不再依赖研发修改代码。 + +#### 验收标准 + +**AC-1:参数分组展示** +- Given 管理员进入「系统设置 → 参数配置」 +- When 页面加载完成 +- Then 页面按模块分组展示所有可配置参数项,至少包含: + - 「客源」分组:客源来源、跟进目的 + - 「房源」分组:房源来源 +- 每个分组展示当前已有选项列表(名称 + 排序 + 状态) + +**AC-2:新增自定义选项** +- Given 管理员点击某参数项的「编辑」按钮 +- When 弹出编辑抽屉,填写「选项名称」并提交 +- Then 新选项追加至列表末尾,排序值自动计算 +- And 经纪人在录入界面的对应下拉中立即可见该新选项(刷新后生效) + +**AC-3:停用选项(不可删除系统预制项)** +- Given 管理员在编辑态对某选项执行「停用」操作 +- When 确认提交 +- Then 该选项的 `is_active` 置为 False +- And 前端录入下拉中不再展示该选项 +- And 历史已选该值的记录保留原值不变,仅展示时标注「已停用」 +- And 系统预制选项(`is_system = True`)的「删除」按钮禁用,仅可停用 + +**AC-4:调整选项排序** +- Given 管理员在编辑态拖拽选项或修改排序值 +- When 保存后 +- Then 经纪人录入下拉中按新排序展示 + +**AC-5:缓存一致性** +- Given 管理员保存配置变更 +- When 变更写入数据库成功 +- Then 对应 Redis 缓存 key 主动失效(`{tenant_schema}:setting:lookup:{module}.{key}`) +- And 所有经纪人在下次请求时获取到最新选项(最长 5 分钟延迟) + +**AC-6:MVP 必须覆盖的参数项** + +| 模块 | 参数 key | 中文名 | 系统预制值(部分示例) | +|------|---------|--------|------------------| +| `client` | `source` | 客源来源 | 门店接待、老客户转介绍、网络(58/安居客)、驻守、上门、朋友介绍 | +| `client` | `follow_purpose` | 跟进目的 | 回拨、推房、带看、维护、其他 | +| `property` | `source` | 房源来源 | 主动开发、业主上门、老客户转介绍、网络来电 | + +--- + +### US-SETTING-001-B:管理员配置房源字段必填规则 + +> **As** 系统管理员, +> **I want** 按「房源用途 × 交易状态」的组合,控制哪些字段在录入时为必填/选填/隐藏, +> **So that** 系统能在录入时强制采集公司要求的关键信息,提升房源数据完整度。 + +#### 验收标准 + +**AC-1:规则配置页面** +- Given 管理员进入「系统设置 → 房源字段规则」 +- When 页面加载 +- Then 以「用途 × 交易状态」为维度展示配置矩阵,MVP 仅需支持: + - 住宅 × 出售 + - 住宅 × 出租 + - 商铺 × 出售(可选) + - 商铺 × 出租(可选) +- 每个组合展示可配置字段列表,字段来源见 AC-4 + +**AC-2:规则编辑** +- Given 管理员点击某组合的「编辑」按钮 +- When 进入编辑态 +- Then 每个字段显示当前规则(必填 / 选填 / 隐藏),以三态 Toggle 或 Radio 形式展示 +- And 管理员修改后点击「保存」提交 + +**AC-3:规则应用于录入界面** +- Given 管理员保存了「住宅 × 出售」的规则:朝向=必填,车位数=隐藏 +- When 经纪人在录入界面新增「住宅 × 出售」房源 +- Then 朝向字段显示必填标记(*),提交时若为空则拦截并提示 +- And 车位数字段不显示(隐藏) +- And 规则变更在配置保存后立即对新录入生效(不影响存量房源) + +**AC-4:MVP 可配置字段范围** + +| 字段 | 字段 key | 说明 | +|------|---------|------| +| 朝向 | `orientation` | 对应 `property.orientation` 枚举 | +| 装修情况 | `decoration` | 对应 `property.decoration` 枚举 | +| 楼层 | `floor` | 所在楼层 / 总楼层 | +| 建筑面积 | `building_area` | 数值字段 | +| 套内面积 | `inner_area` | 数值字段 | +| 房型(室/厅/卫) | `room_layout` | 数值字段组 | +| 产权年限 | `ownership_years` | 数值字段 | +| 车位数 | `parking_count` | 数值字段 | + +> **注**:字段是否存在于数据模型由 `DATA_MODEL_PROPERTY.md` 决定,本配置只控制「是否必填/展示」,不新增字段。 + +--- + +### US-SETTING-001-C:管理员配置客源录入规则 + +> **As** 系统管理员, +> **I want** 配置新增私客时的查重范围,以及必填字段控制, +> **So that** 减少客源重复录入风险,并确保客源数据质量满足公司管理要求。 + +#### 验收标准 + +**AC-1:查重范围配置** +- Given 管理员进入「系统设置 → 客源规则」 +- When 查看「新增私客查重范围」设置项 +- Then 可选值为: + - `本人`(默认)— 同一经纪人不可重复录入同一手机号 + - `本部门` — 同部门内不可重复 + - `全公司` — 全租户范围不可重复 +- And 每个选项有说明文案,明确告知管理员改动影响范围 + +**AC-2:查重规则应用** +- Given 管理员将查重范围设置为「本部门」 +- When 经纪人录入私客手机号时 +- Then 系统在失焦后实时检测同部门内是否存在相同手机号(加密比对) +- And 若存在重复,页面提示:「该号码在本部门已有记录,归属人:XXX,录入时间:XX」 +- And 经纪人可选择「仍然录入」(走审批流)或「放弃」 + +**AC-3:客源必填字段配置** +- Given 管理员在「客源规则」页面勾选必填字段 +- When 保存 +- Then 经纪人录入私客时,已勾选的字段显示必填标记(*),提交时校验 +- And MVP 可配置必填的字段范围: + +| 字段 | 字段 key | 默认值 | +|------|---------|--------| +| 等级 | `grade` | 必填 | +| 来源 | `source` | 必填 | +| 求购/求租总价区间 | `budget_range` | 选填 | +| 居室需求 | `room_requirement` | 选填 | +| 购房目的 | `buying_purpose` | 选填 | + +**AC-4:配置变更即时生效** +- Given 管理员修改任一客源规则并保存 +- When 经纪人下次打开录入界面 +- Then 应用最新规则(无需重新登录) +- And Redis 缓存 key `{tenant_schema}:setting:client_rules` 在保存时主动失效 + +--- + +## 6. 解决方案概述 + +**页面结构**: + +``` +系统设置(侧边栏) +├── 参数配置 ← US-SETTING-001-A(Lookup Items 管理) +├── 房源字段规则 ← US-SETTING-001-B(FieldRequirementRule) +└── 客源规则 ← US-SETTING-001-C(TenantSetting + 必填规则) +``` + +**核心设计决策**: + +1. **Lookup Items 与 enum_labels 分离**:固定系统枚举(装修/朝向/状态/等级)存放在 Public Schema 的 `enum_labels` 表,由平台管理员通过 migration 维护,租户无权修改。可配置枚举(来源/跟进目的)存放在 Tenant Schema 的 `lookup_items` 表,由租户管理员自主维护。详见数据模型说明文档。 + +2. **字段规则不新增字段**:`field_requirement_rules` 只控制「必填/选填/隐藏」状态,字段本身的存在性由数据模型决定。避免配置层与数据模型层职责混淆。 + +3. **所有配置读取走服务层**:业务模块(房源/客源录入)通过 `TenantSettingsService` 统一读取配置,不直接查表,便于统一缓存管理。 + +--- + +## 7. 技术考量 + +**依赖**: +- `apps/setting/` — 配置模块宿主 App(已在 AGENTS.md 目录结构中定义) +- `core/cache.py` — Redis 工具(租户前缀管理) +- `DATA_MODEL/ENUMS.md` — `enum_labels` 设计权威来源,`lookup_items` 需与之对齐 + +**已知风险**: + +| 风险 | 可能性 | 影响 | 缓解措施 | +|------|--------|------|---------| +| 缓存失效不及时导致配置延迟生效 | 中 | 低 | 保存时主动 invalidate;最长 5 min TTL 兜底 | +| 字段必填规则与前端渲染逻辑耦合 | 中 | 中 | 后端在每次 form 请求时返回规则快照,前端不缓存规则 | +| 历史数据与「已停用枚举值」展示冲突 | 低 | 低 | 已停用值在展示时追加「(已停用)」后缀,数据库值不变 | + +**待解决的 Open Questions**(启动开发前必须确认): + +- [ ] `lookup_items` 表的最终 DDL 由 Atlas 确认后同步至 `DATA_MODEL/DATA_MODEL.md` — **Owner: Atlas / Deadline: 开发启动前** +- [ ] 字段必填规则是否需要支持「按角色」粒度(如经纪人必填、店长选填)— **当前决策:MVP 不做角色粒度,全员统一规则。如需变更请在 Review 中提出。** +- [ ] `FieldRequirementRule` 中「房源用途」的枚举值与 `property.property_type` 是否完全一致 — **Owner: Atlas 对齐 DATA_MODEL_PROPERTY.md** + +--- + +## 8. 上线计划 + +| 阶段 | 时间 | 受众 | 成功门槛 | +|------|------|------|---------| +| 内部联调 | Sprint N | 开发团队 + 测试 | 3 个 US 核心流程无 P0 Bug | +| Alpha 验证 | Sprint N+1 | 1 家种子客户管理员 | 管理员可独立完成初始化配置,无需研发介入 | +| MVP 上线 | Sprint N+2 | 全部租户 | 配置变更工单量为 0(全自服务) | + +**回滚条件**:配置保存后前端报错率 > 5%,或经纪人录入报错率相比上线前上升 > 2%,立即回滚并排查。 + +--- + +## 9. 附录 + +- [竞品系统配置参数数据](./系统配置参数数据.md) +- [数据模型设计说明(写给 Atlas)](./系统配置数据模型设计说明_for_Atlas.md) +- ENUMS.md:`DATA_MODEL/ENUMS.md` +- 总体数据模型:`DATA_MODEL/DATA_MODEL.md` diff --git a/Project/fonrey/TECH_STACK/TECH_STACK.md b/Project/fonrey/TECH_STACK/TECH_STACK.md index 8886cca2..3175e5cb 100644 --- a/Project/fonrey/TECH_STACK/TECH_STACK.md +++ b/Project/fonrey/TECH_STACK/TECH_STACK.md @@ -132,7 +132,7 @@ apps/property/ | ----- | ---------------------------------- | -------------------------- | ------------------------------------- | | 登录认证 | [`登录管理技术方案.md`](./登录管理技术方案.md) | `PRD/登录管理/` | `DATA_MODEL/DATA_MODEL_LOGIN.md` | | 权限管理 | [`权限管理系统技术方案.md`](./权限管理系统技术方案.md) | `PRD/权限管理/` | `DATA_MODEL/DATA_MODEL_PERMISSION.md` | -| 房源管理 | _待补充_ | `PRD/房源管理/` | `DATA_MODEL/DATA_MODEL_PROPERTY.md` | +| 房源管理 | [`房源管理技术方案.md`](./房源管理技术方案.md) | `PRD/房源管理/` | `DATA_MODEL/DATA_MODEL_PROPERTY.md` | | 客源管理 | _待补充_ | `PRD/客源管理/` | `DATA_MODEL/DATA_MODEL_CLIENT.md` | | 楼盘管理 | _待补充_ | `PRD/房源管理/`(含楼盘) | `DATA_MODEL/DATA_MODEL_COMPLEX.md` | | 组织人事 | _待补充_ | `PRD/组织人事管理/` | `DATA_MODEL/DATA_MODEL_ORG.md` | diff --git a/Project/fonrey/TECH_STACK/房源管理技术方案.md b/Project/fonrey/TECH_STACK/房源管理技术方案.md new file mode 100644 index 00000000..33450d6c --- /dev/null +++ b/Project/fonrey/TECH_STACK/房源管理技术方案.md @@ -0,0 +1,444 @@ +> **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.md`(v2.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/...` + - 数据 API(JSON):`/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 API(P0) + +| 端点 | 方法 | 鉴权 | 权限码(建议) | 说明 | +|---|---|---|---|---| +| `/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/` + +```json +{ + "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` + +```json +{ + "id": "uuid", + "code": "FY202604270001", + "redirect_url": "/property/uuid/", + "message": "保存成功" +} +``` + +## 6.2 列表查询 + +`POST /api/property/list/query/` + +```json +{ + "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` + +```json +{ + "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/` + +```json +{ + "from_status": "sale", + "to_status": "paused", + "reason": "业主暂不出售" +} +``` + +校验规则: +- 必须符合状态机(例如 sale -> paused/other_sale/deal) +- reason 必填,<= 50 字 + +## 6.4 调价 + +`POST /api/property/{id}/price/change/` + +```json +{ + "sale_price": "350.00", + "bottom_price": "338.00", + "reason": "业主急售" +} +``` + +成功后联动: +- 更新当前挂牌价 +- 追加 `price_changes` 记录 +- 触发详情页价格区域局刷 + +## 6.5 写跟进 + +`POST /api/property/{id}/follow-logs/` + +```json +{ + "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/` +```json +{"query_snapshot": {...}, "columns": ["code", "title", "status", "sale_price"]} +``` + +2) 查询:`GET /api/property/export/jobs/{job_id}/` +```json +{"status":"running", "progress":65} +``` + +3) 下载:`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/"` +- 切 Tab:`hx-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_logs`(`sensitive_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/svg`(P0 与 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 的能力(如地图找房、商业地产)只能写“预留”,不得提前实现 diff --git a/Project/fonrey/TECH_STACK/权限管理系统技术方案.md b/Project/fonrey/TECH_STACK/权限管理系统技术方案.md index 24ceedc8..cc6c0432 100644 --- a/Project/fonrey/TECH_STACK/权限管理系统技术方案.md +++ b/Project/fonrey/TECH_STACK/权限管理系统技术方案.md @@ -1,4 +1,4 @@ -> **For AI assistants**: Read this entire file before writing any code. All decisions here are final. Do not suggest alternatives unless asked. +**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 + Redis diff --git a/Project/fonrey/UI_DESIGN/preview.html b/Project/fonrey/UI_DESIGN/preview.html index b7627ec6..f63e0e4b 100644 --- a/Project/fonrey/UI_DESIGN/preview.html +++ b/Project/fonrey/UI_DESIGN/preview.html @@ -1,816 +1,816 @@ - - - - -Fonrey UI System · 样板预览 v1.0 - - - - - - - - - -
-
- -
-
F
- Fonrey · 房睿 -
- -
- - -
- - -
-
- -
- - -
-
WS
- 魏深 -
-
-
-
- - -
- - - - -
- - -
-
- -

全部房源

-

管理租户下所有房源数据 · 最近同步于 2 分钟前

-
-
- - - -
-
- - -
-
-
-
-
在售房源
-
24,891
-
- - - +4.2% - -
-
较上周 +1,003
-
-
-
-
-
本月新增
-
1,284
-
- +12.8% -
-
目标 1,500 · 完成 85%
-
-
-
-
-
-
-
-
待审核
-
12
-
- 需处理 -
-
查看待审核列表 →
-
-
-
-
-
本月成交
-
86
-
- -2.1% -
-
GMV ¥2.14亿
-
-
- - -
- -
- -
- - -
-
- -
- - -
- - - - - - -
- -
- - -
- 已筛选: - - 价格 500-800万 - - - - 朝阳·大望路 - - - -
-
- - -
-
- 共 1,284 条结果 - · - 已选 3 条 - -
-
- - - -
-
- - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
编号房源标题户型面积 (㎡)总价 (万)单价 (元/㎡)状态维护人录入时间操作
F20268142 -
-
- -
-
-
绿城百合公寓 · 南北通透三居 · 业主诚心出售
-
大望路 · 绿城百合公寓 · 中楼层/32层
-
-
-
3室2厅128.5068052,918在售 -
-
- 魏深 -
-
2026-04-20 14:32 -
- - -
-
F20267891 -
-
-
-
- 万科翡翠长安 · 精装两居 · 满五唯一 - 急售 -
-
CBD · 万科翡翠长安 · 高楼层/28层
-
-
-
2室1厅89.20 - 780720 - 80,717待核验 -
-
- 李明泽 -
-
2026-04-19 09:15
F20267403 -
-
-
-
远洋万和城 · 花园洋房 · 带车位
-
亮马桥 · 远洋万和城 · 低楼层/6层
-
-
-
4室2厅186.001,28068,817已成交 -
-
- 张晓雨 -
-
2026-04-15 16:48
F20266912 -
-
-
-
- 华贸城 · 顶跃复式 · 精装未住 - VR - 钥匙 -
-
建外 · 华贸城 · 顶层/26层
-
-
-
5室3厅280.502,68095,544在售 -
-
- 王建国 -
-
2026-04-12 11:20
F20266541 -
-
-
-
观湖国际 · 商住两用
-
国贸 · 观湖国际
-
-
-
1室52.8038071,970已下架2026-03-28 08:05
-
- - -
-
- 显示 1-20 条,共 1,284 条 -
-
- - - - - - - - - -
-
-
- - -
- - -
-

表单组件 · Form

-
-
- - -

不超过 50 字,将用于客户端展示

-
-
-
- - -
-
- - -
-
-
- - -

价格必须是数字

-
-
- - -
-
- - - - - -
-
- - -
-
-
- - -
- - -
-

按钮与标签 · Buttons & Badges

-
- - - - - - - -
-
- Primary - Success - Warning - Danger - Info - Neutral - 带圆点 -
-
- - K - 快捷键样式 -
-
- - -
-

提示条 · Alert

-
-
- -
-
提示
-
房源信息将在审核后对外展示
-
-
-
- -
-
即将过期
-
3 个房源委托将在 7 天内到期
-
-
-
- -
-
操作失败
-
无法删除该房源,仍有关联跟进记录
-
-
-
-
- - -
-

跟进时间线 · Timeline

-
    -
  1. - -
    -
    - 魏深 - 今天 14:32 -
    -
    带客户看房,客户对户型满意,但希望价格再谈 20 万
    -
    - 看房 - 高意向 -
    -
    -
  2. -
  3. - -
    -
    - 李明泽 - 昨天 10:12 -
    -
    电话跟进业主,确认可协商空间为 30 万
    -
    -
  4. -
  5. - -
    -
    - 系统 - 04-20 14:32 -
    -
    房源录入系统,分配维护人 魏深
    -
    -
  6. -
-
- -
-
- - -
-

颜色系统 · Color Palette

- -
-
-
Primary (Teal · 品牌主色)
-
-
50 #F0FDFA
-
100 #CCFBF1
-
200 #99F6E4
-
500 #14B8A6
-
600 基准
-
700 #115E59
-
800 #134E4A
-
-
- -
-
Neutral (Slate · 中性灰)
-
-
50
-
100
-
200
-
300
-
400
-
500
-
600
-
700
-
800
-
900
-
-
- -
-
Semantic · 语义色
-
-
-
-
-
Success
-
#16A34A
-
-
-
-
-
-
Warning
-
#D97706
-
-
-
-
-
-
Danger
-
#DC2626
-
-
-
-
-
-
Info
-
#2563EB
-
-
-
-
-
-
- - -
-

字体层级 · Typography

-
-
-
H1 · 20/600
-
全部房源
-
-
-
H2 · 16/600
-
房源基本信息
-
-
-
Body · 14/400
-
绿城百合公寓 · 南北通透三居 · 业主诚心出售
-
-
-
Data · 14/500
-
680 万 · 128.50 ㎡
-
-
-
Number · 20/600
-
24,891
-
-
-
Caption · 12/400
-
最近同步于 2 分钟前
-
-
-
Mono · 12/400
-
F20268142
-
-
-
- -
- Fonrey UI System v1.0 · Preview · 2026-04-25 -
-
-
- - -
-
-
- -
-
-
保存成功
-
房源信息已更新
-
- -
-
-
- -
-
-
有 3 条新消息
-
点击查看 →
-
-
-
- - - - + + + + +Fonrey UI System · 样板预览 v1.0 + + + + + + + + + +
+
+ +
+
F
+ Fonrey · 房睿 +
+ +
+ + +
+ + +
+
+ +
+ + +
+
WS
+ 魏深 +
+
+
+
+ + +
+ + + + +
+ + +
+
+ +

全部房源

+

管理租户下所有房源数据 · 最近同步于 2 分钟前

+
+
+ + + +
+
+ + +
+
+
+
+
在售房源
+
24,891
+
+ + + +4.2% + +
+
较上周 +1,003
+
+
+
+
+
本月新增
+
1,284
+
+ +12.8% +
+
目标 1,500 · 完成 85%
+
+
+
+
+
+
+
+
待审核
+
12
+
+ 需处理 +
+
查看待审核列表 →
+
+
+
+
+
本月成交
+
86
+
+ -2.1% +
+
GMV ¥2.14亿
+
+
+ + +
+ +
+ +
+ + +
+
+ +
+ + +
+ + + + + + +
+ +
+ + +
+ 已筛选: + + 价格 500-800万 + + + + 朝阳·大望路 + + + +
+
+ + +
+
+ 共 1,284 条结果 + · + 已选 3 条 + +
+
+ + + +
+
+ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
编号房源标题户型面积 (㎡)总价 (万)单价 (元/㎡)状态维护人录入时间操作
F20268142 +
+
+ +
+
+
绿城百合公寓 · 南北通透三居 · 业主诚心出售
+
大望路 · 绿城百合公寓 · 中楼层/32层
+
+
+
3室2厅128.5068052,918在售 +
+
+ 魏深 +
+
2026-04-20 14:32 +
+ + +
+
F20267891 +
+
+
+
+ 万科翡翠长安 · 精装两居 · 满五唯一 + 急售 +
+
CBD · 万科翡翠长安 · 高楼层/28层
+
+
+
2室1厅89.20 + 780720 + 80,717待核验 +
+
+ 李明泽 +
+
2026-04-19 09:15
F20267403 +
+
+
+
远洋万和城 · 花园洋房 · 带车位
+
亮马桥 · 远洋万和城 · 低楼层/6层
+
+
+
4室2厅186.001,28068,817已成交 +
+
+ 张晓雨 +
+
2026-04-15 16:48
F20266912 +
+
+
+
+ 华贸城 · 顶跃复式 · 精装未住 + VR + 钥匙 +
+
建外 · 华贸城 · 顶层/26层
+
+
+
5室3厅280.502,68095,544在售 +
+
+ 王建国 +
+
2026-04-12 11:20
F20266541 +
+
+
+
观湖国际 · 商住两用
+
国贸 · 观湖国际
+
+
+
1室52.8038071,970已下架2026-03-28 08:05
+
+ + +
+
+ 显示 1-20 条,共 1,284 条 +
+
+ + + + + + + + + +
+
+
+ + +
+ + +
+

表单组件 · Form

+
+
+ + +

不超过 50 字,将用于客户端展示

+
+
+
+ + +
+
+ + +
+
+
+ + +

价格必须是数字

+
+
+ + +
+
+ + + + + +
+
+ + +
+
+
+ + +
+ + +
+

按钮与标签 · Buttons & Badges

+
+ + + + + + + +
+
+ Primary + Success + Warning + Danger + Info + Neutral + 带圆点 +
+
+ + K + 快捷键样式 +
+
+ + +
+

提示条 · Alert

+
+
+ +
+
提示
+
房源信息将在审核后对外展示
+
+
+
+ +
+
即将过期
+
3 个房源委托将在 7 天内到期
+
+
+
+ +
+
操作失败
+
无法删除该房源,仍有关联跟进记录
+
+
+
+
+ + +
+

跟进时间线 · Timeline

+
    +
  1. + +
    +
    + 魏深 + 今天 14:32 +
    +
    带客户看房,客户对户型满意,但希望价格再谈 20 万
    +
    + 看房 + 高意向 +
    +
    +
  2. +
  3. + +
    +
    + 李明泽 + 昨天 10:12 +
    +
    电话跟进业主,确认可协商空间为 30 万
    +
    +
  4. +
  5. + +
    +
    + 系统 + 04-20 14:32 +
    +
    房源录入系统,分配维护人 魏深
    +
    +
  6. +
+
+ +
+
+ + +
+

颜色系统 · Color Palette

+ +
+
+
Primary (Teal · 品牌主色)
+
+
50 #F0FDFA
+
100 #CCFBF1
+
200 #99F6E4
+
500 #14B8A6
+
600 基准
+
700 #115E59
+
800 #134E4A
+
+
+ +
+
Neutral (Slate · 中性灰)
+
+
50
+
100
+
200
+
300
+
400
+
500
+
600
+
700
+
800
+
900
+
+
+ +
+
Semantic · 语义色
+
+
+
+
+
Success
+
#16A34A
+
+
+
+
+
+
Warning
+
#D97706
+
+
+
+
+
+
Danger
+
#DC2626
+
+
+
+
+
+
Info
+
#2563EB
+
+
+
+
+
+
+ + +
+

字体层级 · Typography

+
+
+
H1 · 20/600
+
全部房源
+
+
+
H2 · 16/600
+
房源基本信息
+
+
+
Body · 14/400
+
绿城百合公寓 · 南北通透三居 · 业主诚心出售
+
+
+
Data · 14/500
+
680 万 · 128.50 ㎡
+
+
+
Number · 20/600
+
24,891
+
+
+
Caption · 12/400
+
最近同步于 2 分钟前
+
+
+
Mono · 12/400
+
F20268142
+
+
+
+ +
+ Fonrey UI System v1.0 · Preview · 2026-04-25 +
+
+
+ + +
+
+
+ +
+
+
保存成功
+
房源信息已更新
+
+ +
+
+
+ +
+
+
有 3 条新消息
+
点击查看 →
+
+
+
+ + + + diff --git a/Project/fonrey/UI_SYSTEM/UI_SYSTEM.md b/Project/fonrey/UI_SYSTEM/UI_SYSTEM.md index f6336abc..b9f70dfe 100644 --- a/Project/fonrey/UI_SYSTEM/UI_SYSTEM.md +++ b/Project/fonrey/UI_SYSTEM/UI_SYSTEM.md @@ -51,7 +51,7 @@ | Token | Hex | Tailwind 类 | 使用场景 | | ------------- | --------- | ---------------- | ------------------------- | | `primary-50` | `#F0FDFA` | `bg-primary-50` | 页面强调区微底色、Tag 极淡底 | -| `primary-100` | `#CCFBF1 | `bg-primary-100` | 选中背景、标签底色 | +| `primary-100` | `#CCFBF1` | `bg-primary-100` | 选中背景、标签底色 | | `primary-200` | `#99F6E4` | `bg-primary-200` | Hover 标签底色 | | `primary-500` | `#14B8A6` | `bg-primary-500` | 辅助主色(图标、强调文字) | | `primary-600` | `#0F766E` | `bg-primary-600` | **主按钮、激活态、Tab 下划线(基准主色)** | diff --git a/Project/fonrey/VIBE_CODING_开工前缺失清单.md b/Project/fonrey/VIBE_CODING_开工前缺失清单.md new file mode 100644 index 00000000..e42abaaf --- /dev/null +++ b/Project/fonrey/VIBE_CODING_开工前缺失清单.md @@ -0,0 +1,101 @@ +# Fonrey Web Coding 开工前缺失清单 + +> 记录时间:2026-04-26 +> 目的:在开始 Web Coding 落地前,把缺失但会直接卡住实施的文档一次补齐。 + +## 一、必须补齐的 6 份关键文档 + +### 1. 项目入口文档 +- README.md / 项目总览 +- 本地启动步骤 +- 环境变量说明 +- 数据库初始化与迁移说明 +- 种子数据说明 + +### 2. ADR 架构决策记录 +需要冻结以下决策: +- 登录态:session / token / 混合方案 +- django-tenants 本地开发模式 +- 单租户 MVP 与多租户架构共存方式 +- HTMX 页面局刷约定 +- 目录结构最终落点 +- 状态机与枚举字典权威来源 + +### 3. 枚举字典 / 状态字典 +建议新增: +- ENUMS.md +- STATE_MACHINE.md + +至少冻结: +- 客源状态 +- 客源等级 +- 房源状态 +- 操作日志类型 +- 租户状态机 + +要求统一: +- 中文值 +- 英文值 +- 数据库 CHECK 值 +- UI 展示值 +- 允许的状态迁移 + +### 4. 页面路由 + 组件映射 +需要明确: +- 每个模块有哪些页面 +- 每个页面对应什么 URL +- 每个页面复用哪些组件 +- 哪些页面是列表 / 详情 / 弹窗 / 抽屉 / partial +- 每个页面的空态、加载态、错误态、权限态 + +### 5. API 契约规范 +需要明确: +- 请求 / 响应格式 +- 错误码规范 +- 分页规范 +- 搜索 / 筛选规范 +- 上传规范 +- 文件下载规范 +- 权限拒绝返回规范 + +### 6. 本地开发与验证手册 +需要明确: +- 本地环境启动方式 +- PostgreSQL / Redis / Celery 启动方式 +- django-tenants 初始化方式 +- 测试租户创建方式 +- 管理员账号 seed 方式 +- 静态资源与对象存储本地替代方案 +- dev / staging / production 配置差异 + +## 二、建议优先级 + +### P0:先补,不补就不能稳定开工 +- 项目入口文档 +- ADR +- 枚举字典 / 状态字典 +- 页面路由 + 组件映射 + +### P1:随后补,直接影响实现质量 +- API 契约规范 +- 本地开发与验证手册 + +## 三、当前项目的直接风险 + +- 需求、数据模型、任务表已经较完整,但“可执行工程包”还不够 +- Review 已指出枚举不一致、分页规范缺位、性能基准缺位等问题 +- 没有启动手册和种子数据,Web Coding 容易停留在文档层,无法稳定进入实现层 + +## 四、建议的落地顺序 + +1. 先补 README / 启动手册 +2. 冻结 ADR +3. 冻结 ENUMS / STATE_MACHINE +4. 补页面路由与组件映射 +5. 补 API 契约 +6. 补本地开发与验证手册 +7. 再开始正式 Web Coding + +--- + +这份清单的目标不是增加文档数量,而是减少实现时的来回返工。 diff --git a/Project/fonrey/prompt/PRD - 为系统设置生成PRD 设计文档.md b/Project/fonrey/prompt/PRD - 为系统设置生成PRD 设计文档.md new file mode 100644 index 00000000..ea610a1b --- /dev/null +++ b/Project/fonrey/prompt/PRD - 为系统设置生成PRD 设计文档.md @@ -0,0 +1,347 @@ +# Fonrey PRD 需求文档生成提示词模板 + +> 本模板专注于**产品需求定义**:做什么、为谁做、怎么验收。 +> 技术实现细节(数据模型 DDL、API 路由、架构设计)由配套的 **TECH_STACK & DATA_MODEL 模板**负责,两份文档互不重复。 + +--- + +## ✅ 使用前检查清单 + +- [ ] 已填写本次设计的模块 / 功能名称 +- [ ] 已确认参考的已有 PRD 路径(可留空) +- [ ] 已准备好产品截图或草图(如有,直接附在消息中) +- [ ] 已明确本次功能的优先级范围(P0 / P1 / P2) +- [ ] TECH_STACK.md 已存在,可供 AI 读取技术约束 + +--- + +## 📋 完整提示词(复制后填写 `【...】` 再发送) + + +## 角色与背景 + +你是 **Nova**,一名拥有 10 年以上经验的资深产品经理,擅长 B2B SaaS 产品的全生命周期管理。 +核心方法论:先问问题再给答案,先定义问题再讨论方案,先看证据再拍板决策。 +你输出的每一份需求文档都必须包含清晰的用户故事、可量化的验收标准、明确的边界(Non-Goals)。 +你永远不写模糊需求,每条需求都可以被工程师直接实现、测试和验收。 + +**你的职责边界**: +- ✅ 负责:功能范围定义、用户故事、验收标准、字段规范、页面结构、权限要求、性能指标 +- ❌ 不负责:数据库 DDL、API 路由代码、系统架构设计——这些由配套技术文档承接 + +--- + +## 项目背景 + +**工作目录**:`~/Workspace/nexus` + +**项目概览**: +我正在开发 **Fonrey(房睿)**——一款面向房地产经纪公司的 B2B SaaS 平台。 +核心目标:解决房源 / 客源信息散乱、跟进缺失、重复录入等痛点,支撑 89,000+ 条数据量级下的高效匹配。 + +**目标用户(按使用频率)**: +- 🔴 一线经纪人(高频,核心用户) +- 🟠 店长 / 区域经理(每日使用) +- 🟡 运营 / 行政人员(每日使用) +- ⚪ 系统管理员(不定期) + +**已覆盖的核心模块**:房源管理、客源管理、楼盘管理、系统设置 + +--- + +## 技术约束参考 + +请读取 `Project/fonrey/TECH_STACK/TECH_STACK.md` 了解技术约束。 +PRD 中涉及交互模式时须遵守以下原则,**不得建议替代方案**: + +| 约束项 | 要求 | +|--------|------| +| 前端交互 | HTMX 局部刷新 + Alpine.js 前端状态,❌ 禁止 React/Vue/Angular | +| 页面刷新 | ❌ 禁止整页刷新,所有操作使用 HTMX 局部更新 | +| 异步任务 | 耗时 > 500ms 的操作须标注"需 Celery 异步处理" | +| 文件存储 | 上传至 Cloudflare R2,PRD 中注明文件类型和大小限制即可 | +| 当前阶段 | 仅 Web 端,移动端为 v2 规划,本期 PRD 不涉及 | + +> 技术实现方案(models.py、urls.py、视图函数)由工程师参考配套 TECH 文档设计,PRD 不输出代码。 + +--- + +## 方法论参考 + +请读取 `Project/fonrey/prompt/product-manager.md` 并运用其中的专业知识与 PRD 格式规范。 + +核心原则(生成文档时必须体现): +1. **先问题后方案**:每个功能点必须说明"解决了谁的什么痛点" +2. **Non-Goals 必填**:明确本次不做什么,防止需求蔓延 +3. **验收标准可测试**:每条 AC 格式为 `Given / When / Then`,含正常流与异常流 +4. **优先级标注**:P0(MVP 必须)/ P1(重要但可延迟)/ P2(优化迭代) +5. **技术风险前置**:依赖关系和已知风险须在文档中体现(描述风险,不设计方案) + +--- + +## 参考已有 PRD(保持格式一致) + +请参考以下已完成 PRD 的格式、章节结构和细化程度: + +- 房源管理PRD: `Project/fonrey/PRD/房源管理/房源管理模块PRD.md` +- 楼盘管理PRD: `Project/fonrey/PRD/房源管理/楼盘管理模块PRD.md` +- 客源管理PRD: `Project/fonrey/PRD/客源管理/客源管理模块PRD.md` +- 权限管理PRD: `Project/fonrey/PRD/权限管理/权限管理模块PRD.md` + - 权限管理样本数据:`Project/fonrey/PRD/权限管理/首页.md` + - 权限管理样本数据:`Project/fonrey/PRD/权限管理/房源-二手租赁.md` + - 权限管理样本数据:`Project/fonrey/PRD/权限管理/客源.md` + - 权限管理样本数据:`Project/fonrey/PRD/权限管理/小区.md` +- 组织人事管理PRD: `Project/fonrey/PRD/组织人事管理/组织人事管理模块PRD.md` +- 系统管理PRD: `Project/fonrey/PRD/系统管理/系统管理模块PRD` +- 登录管理PRD: `Project/fonrey/PRD/登录管理/用户登录管理模块PRD.md` +- 发布管理PRD: `Project/fonrey/PRD/发布管理/客户端发布管理模块PRD.md` + + +--- + +## 本次需求 + +### 🎯 我要设计的功能 / 模块 + +**【描述本次设计内容,例如: +"楼盘管理模块中的【楼盘详情页】,包含:楼盘基础信息展示与编辑、楼栋管理(列表/新增/编辑)、户型结构管理、楼盘照片管理、区域/商圈关联"】** + +### 📎 补充材料 + +【说明附上了哪些参考材料,例如: +- 已附上截图:竞品 A 的楼盘详情页(3 张) +- 已附上草图:手绘交互流程图 +- 无截图,请根据文字描述生成】 + +### 🗂️ 功能范围与优先级 + +【列出本次优先级范围,例如: +**P0(本期必须上线)**: +- 楼盘基础信息展示与编辑(名称、地址、建成年份、容积率等) +- 楼栋列表(分页、新增、编辑、删除) + +**P1(本期随 P0 一起上线,允许适当简化)**: +- 户型结构管理(按楼栋挂载) +- 楼盘照片上传(支持排序,格式和大小见业务规则) + +**P2(后续迭代,本次文档描述边界,不做细化)**: +- 价格走势图表 +- 周边配套(地铁/学校/商场) +- 楼盘数据统计面板】 + +### 💡 已知的业务规则 / 约束 + +【填写已确认的业务规则,例如: +- 楼盘是房源的基础数据底座,删除楼盘前需检查是否有挂载的在售房源 +- 一个楼盘可有多个楼栋,一个楼栋可有多个户型 +- 楼盘照片最多 20 张,单张限 10MB,格式限 JPG / PNG / WEBP +- 区域/商圈关联关系从 region app 读取,本模块不维护区域数据 +- 楼盘数据属于租户隔离数据(complex app),需遵守多租户规范】 + +--- + +## 输出要求 + +请按以下结构输出完整 PRD,保存至: +`Project/fonrey/PRD/【模块名称】/【功能名称】PRD.md` + +输出语言:**中文**(技术术语、字段名可保留英文) + +--- + +# PRD:【功能名称】 + +**状态**:Draft +**作者**:Billy(PM) +**最后更新**:【当前日期】 +**版本**:v0.1 +**关联 Django App**:【如 complex / property / client】 +**关联干系人**:工程负责人 / 设计负责人 / 运营负责人 + +--- + +## 1. 问题陈述(Problem Statement) + +- 目标用户是谁,他们面临什么具体痛点 +- 当前无此功能时用户如何绕过(Workaround) +- 不解决此问题的业务成本 + +--- + +## 2. 目标与成功指标(Goals & Success Metrics) + +| 目标 | 衡量指标 | 当前基线 | 目标值 | 测量窗口 | +|------|---------|---------|--------|---------| +| | | | | | + +--- + +## 3. 非目标(Non-Goals) + +- 本次明确不做的内容(含原因) +- 延后到 v2 的功能(含触发条件) + +--- + +## 4. 用户故事与验收标准(User Stories & Acceptance Criteria) + +> 按角色分组,每条用户故事附带可测试的 AC。 + +### 角色:一线经纪人 + +**US-01**:【用户故事标题】 +> As a 一线经纪人, I want to 【操作】 so that 【价值】 + +**AC-01-01(正常流)**: +- Given 【前置条件】 +- When 【触发动作】 +- Then 【预期结果】 + +**AC-01-02(异常流)**: +- Given 【前置条件】 +- When 【触发动作】 +- Then 【预期结果,含错误提示文案】 + +### 角色:店长 / 区域经理 + +【同上结构,按需补充】 + +--- + +## 5. 功能详细设计(Feature Specification) + +### 5.1 信息架构 / 页面结构 + +- 描述页面层级、导航路径、关键区块布局 +- 说明各功能区块的排布逻辑(不含视觉稿,纯文字描述) + +### 5.2 核心交互流程 + +> 说明关键操作的完整步骤,注明前端交互模式。 + +**流程示例:新增楼栋** +1. 用户点击「新增楼栋」按钮 +2. (HTMX)局部加载新增表单至侧边抽屉,不刷新整页 +3. 用户填写楼栋信息并提交 +4. (HTMX)提交后局部刷新楼栋列表区域,显示 Toast 成功提示 +5. 若校验失败,(HTMX)局部渲染表单错误状态,不关闭抽屉 + +> 对于涉及多选、计数、弹窗展开收起等纯前端状态,注明"由 Alpine.js 维护"即可,不写具体代码。 + +### 5.3 字段规范 + +| 字段名 | 展示名称 | 类型 | 是否必填 | 校验规则 | 说明 | +|--------|---------|------|---------|---------|------| +| | | | | | | + +### 5.4 权限控制 + +| 操作 | 一线经纪人 | 店长/区域经理 | 运营/行政 | 系统管理员 | +|------|-----------|-------------|---------|----------| +| 查看 | | | | | +| 新增 | | | | | +| 编辑 | | | | | +| 删除 | | | | | + +> 如存在数据范围限制(如经纪人只能看自己名下的房源),在此说明。 + +### 5.5 性能要求 + +> 以需求方式陈述,不设计技术方案。 + +- 列表页首屏加载(含分页)应在 __ms 内完成(P95) +- 以下操作耗时可能 > 500ms,须做异步处理并展示进度反馈:【列出操作名称】 +- 图片上传须展示上传进度条 + +--- + +## 6. 边界场景与异常处理(Edge Cases & Error Handling) + +| 场景 | 预期处理方式 | 前端提示文案 | +|------|------------|------------| +| 删除楼盘时存在关联在售房源 | 阻止删除,提示关联数量 | "该楼盘下有 N 套在售房源,请先处理后再删除" | +| 图片上传超出 10MB | 上传前校验,拒绝上传 | "图片大小不能超过 10MB" | +| 表单提交网络超时 | Toast 错误提示,保留表单内容 | "提交失败,请检查网络后重试" | + +--- + +## 7. 依赖与风险(Dependencies & Risks) + +| 类型 | 描述 | 影响 | 缓解措施 | +|------|------|------|---------| +| 依赖 | 本模块依赖 region app 提供区域数据 | 若 region 数据未完成,关联功能无法上线 | 先用占位下拉,region 就绪后接入 | +| 风险 | 楼盘照片批量上传可能阻塞主线程 | 用户体验差 | 标注需异步处理,技术方案见 TECH 文档 | + +--- + +## 8. 上线计划(Launch Plan) + +| 阶段 | 时间 | 受众 | 通过标准 | +|------|------|------|---------| +| 内测 | | 内部团队 | | +| 灰度 | | 指定经纪公司 | | +| 全量 | | 所有租户 | | + +--- + +## 9. 待确认问题(Open Questions) + +- [ ] 问题描述 — 负责人 — 截止时间 + +--- + +## 10. 附录(Appendix) + +- 相关截图 / 草图 +- 竞品参考 +- 关联文档:`Project/fonrey/TECH_STACK/TECH_STACK.md`、`Project/fonrey/DATA_MODEL/DATA_MODEL.md` + + +--- + +## 补充说明 + +- 如果提供了产品截图,请先分析截图中的功能模块、交互模式、数据字段,再结合文字描述生成 PRD +- 如发现需求描述存在逻辑矛盾或遗漏关键场景,请在输出 PRD 前先提出问题,不要自行填充假设 +- PRD **不输出** models.py、urls.py 代码草稿——这些内容由工程师基于 PRD + TECH 文档实现 + + +--- + +## 📌 使用说明 + +| 步骤 | 操作 | +|------|------| +| **1** | 复制上方代码块中的完整提示词 | +| **2** | 填写所有 `【...】` 占位符 | +| **3** | 如有截图 / 草图,直接附在消息中 | +| **4** | 确认 TECH_STACK.md 已存在,AI 会自动读取 | +| **5** | 发送,等待生成完整 PRD | + +--- + +## 🔁 快捷变体 + +### 变体 A:仅输出用户故事 + AC(跳过完整 PRD) + +在提示词末尾追加: +``` +请只输出第 4 章(用户故事与验收标准),其余章节暂不输出。 +``` + +### 变体 B:基于已有草稿补全润色 + +在提示词末尾追加: +``` +我已有一份草稿如下,请补全缺失章节,润色表达,并检查是否与技术约束冲突: +【粘贴草稿内容】 +``` + +### 变体 C:补充 HTMX / Alpine.js 交互规范描述 + +在提示词末尾追加: +``` +请在 5.2 节每个核心交互流程末尾,补充「前端交互说明」小节,明确指出: +- 该步骤使用 hx-get / hx-post / hx-swap 的哪种触发模式 +- Alpine.js 需要维护哪些 x-data 状态(仅描述状态名称和含义,不写代码) +- 是否需要触发 Toast 通知,通知文案是什么 diff --git a/Project/fonrey/prompt/提示词模板/PRD_提示词模板_v2.md b/Project/fonrey/prompt/提示词模板/PRD_提示词模板_v2.md index 12f9249d..ea610a1b 100644 --- a/Project/fonrey/prompt/提示词模板/PRD_提示词模板_v2.md +++ b/Project/fonrey/prompt/提示词模板/PRD_提示词模板_v2.md @@ -20,7 +20,7 @@ ## 角色与背景 -你是 **Billy**,一名拥有 10 年以上经验的资深产品经理,擅长 B2B SaaS 产品的全生命周期管理。 +你是 **Nova**,一名拥有 10 年以上经验的资深产品经理,擅长 B2B SaaS 产品的全生命周期管理。 核心方法论:先问问题再给答案,先定义问题再讨论方案,先看证据再拍板决策。 你输出的每一份需求文档都必须包含清晰的用户故事、可量化的验收标准、明确的边界(Non-Goals)。 你永远不写模糊需求,每条需求都可以被工程师直接实现、测试和验收。