chore: sync local project changes
This commit is contained in:
@@ -133,10 +133,10 @@
|
||||
| 房源设置(字段必填/自定义字段/标签) | **P0** | 影响录入表单 |
|
||||
| 相关方设置 | **P1** | |
|
||||
| 客源设置(基本配置/参数配置) | **P1** | |
|
||||
| 人事OA设置 | **P2** | |
|
||||
| 交易设置 | **P2** | |
|
||||
| 财务设置 | **P2** | |
|
||||
| 合同设置 | **P2** | |
|
||||
| 人事OA设置 | **P2** | 依赖人事OA模块完整规划,本期不实现 |
|
||||
| 交易设置 | **P2** | 依赖交易模块完整规划,本期不实现 |
|
||||
| 财务设置 | **Out of Scope** | 消费方「财务管理模块」为 Out of Scope,配置面板无意义,随模块一并排除 |
|
||||
| 合同设置 | **Out of Scope** | 消费方「合同管理模块」为 Out of Scope,配置面板无意义,随模块一并排除 |
|
||||
|
||||
#### 🖥️ 系统管理(运营后台)
|
||||
|
||||
|
||||
@@ -108,8 +108,8 @@
|
||||
| [US-ORG-022](#US-ORG-022-管理员查看门店分布地图) | 组织人事 | 管理员查看门店分布地图 | [ ] |
|
||||
| [US-SETTING-020](#US-SETTING-020-管理员配置人事OA相关参数) | 系统配置 | 管理员配置人事OA相关参数 | [ ] |
|
||||
| [US-SETTING-021](#US-SETTING-021-管理员配置交易规则) | 系统配置 | 管理员配置交易规则 | [ ] |
|
||||
| [US-SETTING-022](#US-SETTING-022-管理员配置财务规则) | 系统配置 | 管理员配置财务规则 | [ ] |
|
||||
| [US-SETTING-023](#US-SETTING-023-管理员配置合同模板) | 系统配置 | 管理员配置合同模板 | [ ] |
|
||||
| ~~US-SETTING-022~~ | ~~系统配置~~ | ~~管理员配置财务规则~~ — **已移出,财务模块 Out of Scope** | ~~[ ]~~ |
|
||||
| ~~US-SETTING-023~~ | ~~系统配置~~ | ~~管理员配置合同模板~~ — **已移出,合同模块 Out of Scope** | ~~[ ]~~ |
|
||||
| [US-SYSTEM-020](#US-SYSTEM-020-平台管理员查看操作审计日志) | 系统管理 | 平台管理员查看操作审计日志 | [ ] |
|
||||
| [US-SYSTEM-021](#US-SYSTEM-021-平台管理员管理灰度发布滚动升级) | 系统管理 | 平台管理员管理灰度发布/滚动升级 | [ ] |
|
||||
|
||||
@@ -806,17 +806,13 @@
|
||||
- 状态:[ ]
|
||||
- 验收标准:(规划中,详细验收标准待PRD细化后补充)
|
||||
|
||||
##### US-SETTING-022 管理员配置财务规则
|
||||
##### ~~US-SETTING-022 管理员配置财务规则~~
|
||||
|
||||
- 参考PRD文档:`Project/fonrey/PRD/系统配置/系统配置.md` - 财务设置
|
||||
- 状态:[ ]
|
||||
- 验收标准:(规划中,详细验收标准待PRD细化后补充)
|
||||
> ⛔ **已移出路线图**:消费方「财务管理/提成结算模块」在 MVP 及近期版本中明确为 Out of Scope(见 PRD_MVP.md §3),对应的系统配置面板无实际消费方,随模块一并排除。若后续财务模块立项,本 US 随之恢复。
|
||||
|
||||
##### US-SETTING-023 管理员配置合同模板
|
||||
##### ~~US-SETTING-023 管理员配置合同模板~~
|
||||
|
||||
- 参考PRD文档:`Project/fonrey/PRD/系统配置/系统配置.md` - 合同设置
|
||||
- 状态:[ ]
|
||||
- 验收标准:(规划中,详细验收标准待PRD细化后补充)
|
||||
> ⛔ **已移出路线图**:消费方「合同管理模块」在 MVP 及近期版本中明确为 Out of Scope(见 PRD_MVP.md §3),对应的系统配置面板无实际消费方,随模块一并排除。若后续合同模块立项,本 US 随之恢复。
|
||||
|
||||
---
|
||||
|
||||
|
||||
5899
Project/fonrey/PRD/TASK_AGENT_READY.md
Normal file
5899
Project/fonrey/PRD/TASK_AGENT_READY.md
Normal file
File diff suppressed because it is too large
Load Diff
3104
Project/fonrey/PRD/TASK_AGENT_READY_P0.md
Normal file
3104
Project/fonrey/PRD/TASK_AGENT_READY_P0.md
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1,407 +1,407 @@
|
||||
# PRD: 客户端发布管理模块
|
||||
**状态**: Draft
|
||||
**作者**: 产品经理
|
||||
**最后更新**: 2026-04-24(v1.0 初稿)
|
||||
**版本**: 1.0
|
||||
**所属系统**: Fonrey 房产经纪管理系统
|
||||
**关联模块**: 系统管理、权限管理
|
||||
**干系人**: 工程负责人、运维负责人、系统管理员
|
||||
|
||||
---
|
||||
|
||||
## 1. 问题陈述
|
||||
|
||||
### 背景
|
||||
|
||||
Fonrey 房产经纪管理系统当前为纯 Web 应用,依赖用户自行通过浏览器访问。然而在实际部署场景中,经纪公司的终端设备环境高度复杂:
|
||||
|
||||
- **浏览器版本参差不齐**:经纪人使用的 Windows 设备可能运行 IE11、旧版 Edge、或未更新的 Chrome,导致 HTMX + Alpine.js 等现代前端技术出现兼容性问题,系统体验碎片化
|
||||
- **交付和部署门槛高**:IT 能力薄弱的经纪公司无法独立配置浏览器访问方式,URL 记忆成本高,容易访问错误版本
|
||||
- **版本管理缺失**:后端服务升级后,用户仍可能使用旧版缓存页面操作,导致接口不兼容和功能异常
|
||||
- **无官方入口**:用户通过私发链接访问系统,存在钓鱼仿冒风险,且无法统一品牌形象
|
||||
|
||||
### 目标用户
|
||||
|
||||
| 角色 | 使用场景 | 使用频率 |
|
||||
|------|---------|----------|
|
||||
| 一线经纪人 | 下载安装客户端、日常登录使用系统、接受自动更新 | 每日 |
|
||||
| 店长/经理 | 同上 | 每日 |
|
||||
| 系统管理员 | 发布新版本、管理安装包下载地址、监控客户端版本分布 | 按需 |
|
||||
| IT 运维人员 | 维护更新服务器、签名证书、构建发布流水线 | 按发布周期 |
|
||||
|
||||
### 核心痛点
|
||||
|
||||
1. **无法控制用户使用的浏览器环境**,兼容性问题无法从根源解决
|
||||
2. **升级依赖用户主动刷新浏览器**,后端 API 变更时旧客户端可能造成数据错误
|
||||
3. **缺乏官方分发渠道**,无法向终端用户传递信任感和版本一致性保障
|
||||
4. **SaaS 多租户管理系统需要统一、可控的客户端入口**,避免因客户端环境差异导致的支持成本上升
|
||||
|
||||
---
|
||||
|
||||
## 2. 目标与成功指标
|
||||
|
||||
| 目标 | 指标 | 当前基准 | 目标值 | 衡量周期 |
|
||||
|------|------|---------|--------|---------|
|
||||
| 消除浏览器兼容性问题 | 因浏览器兼容产生的支持工单数 | 待统计 | 降低 ≥ 90% | 上线后 60 天 |
|
||||
| 提升版本一致性 | 在线用户中使用最新版本客户端的比例 | 0%(无客户端) | ≥ 95% | 版本发布后 7 天 |
|
||||
| 降低部署门槛 | 新客户从获取安装包到完成首次登录的时间 | 无基准 | ≤ 10 分钟 | 上线后首批客户反馈 |
|
||||
| 自动更新成功率 | 客户端自动更新完成率(收到更新通知 → 升级完成) | 无基准 | ≥ 98% | 每次版本发布后 48 小时 |
|
||||
|
||||
---
|
||||
|
||||
## 3. 非目标(本期不做)
|
||||
|
||||
- **不支持 macOS / Linux 客户端**:目标用户群体 99% 使用 Windows,macOS 版本为后续规划
|
||||
- **不支持移动端 App(iOS / Android)**:移动端为 v2 规划,本期不涉及
|
||||
- **不开发私有化部署的离线安装方案**:本期聚焦 SaaS 在线版,私有化部署另行规划
|
||||
- **不包含客户端内置的离线模式**:系统需联网使用,客户端不缓存业务数据供离线访问
|
||||
- **不包含客户端层面的安全加固(如代码混淆、反逆向)**:本期以功能交付为优先,安全加固列入后续迭代
|
||||
|
||||
---
|
||||
|
||||
## 4. 用户故事与验收标准
|
||||
|
||||
---
|
||||
|
||||
### Story 1:经纪人下载并安装客户端
|
||||
|
||||
**As** 一线经纪人,**I want** 通过公司提供的网址下载一个安装程序并完成安装,**So that** 我可以立即打开登录界面使用 Fonrey 系统,无需手动配置浏览器。
|
||||
|
||||
**验收标准**:
|
||||
- [ ] 官方下载页面可通过指定 URL 访问,页面展示最新版本号、发布日期及下载按钮
|
||||
- [ ] 下载产物为单一 `.exe` 安装包(或免安装便携版 `.zip`),文件大小控制在合理范围内
|
||||
- [ ] 双击安装包后,安装向导步骤不超过 3 步(下一步 → 选择安装路径 → 安装),无需勾选额外组件
|
||||
- [ ] 安装完成后,桌面自动生成快捷方式(图标为 Fonrey 品牌 Logo)
|
||||
- [ ] 首次启动后直接显示登录界面,无需用户手动输入任何 URL
|
||||
- [ ] 安装包经过代码签名,Windows SmartScreen 不弹出"无法识别的应用"警告
|
||||
- [ ] 安装过程无需管理员权限(支持用户级安装到 `%APPDATA%` 目录),降低企业 IT 审批障碍
|
||||
|
||||
---
|
||||
|
||||
### Story 2:经纪人使用客户端正常登录并使用系统
|
||||
|
||||
**As** 一线经纪人,**I want** 打开客户端后直接访问 Fonrey 系统的完整功能,**So that** 我的日常使用体验与使用 Chrome 浏览器无差异,且不受本机安装的浏览器版本影响。
|
||||
|
||||
**验收标准**:
|
||||
- [ ] 客户端内嵌现代 Chromium 内核(如基于 Electron 或 WebView2),版本不低于 Chromium 100,支持现代 Web 标准(ES2020、CSS Grid、Fetch API 等)
|
||||
- [ ] HTMX 局部刷新、Alpine.js 状态交互、Tailwind CSS 样式在客户端中渲染效果与 Chrome 最新版一致
|
||||
- [ ] 支持 Cookie / Session 存储,登录状态在客户端关闭后保留(复用 Django Session 机制)
|
||||
- [ ] 文件上传(图片、附件)、文件下载(Excel 导出)在客户端中正常工作
|
||||
- [ ] 客户端窗口支持最大化、最小化、拖拽调整大小,支持多显示器
|
||||
- [ ] 客户端标题栏显示应用名称和当前版本号(如:`Fonrey 房睿 v1.2.3`)
|
||||
- [ ] 客户端不显示浏览器默认的地址栏、书签栏、扩展工具栏,保持沉浸式应用体验
|
||||
|
||||
---
|
||||
|
||||
### Story 3:客户端感知新版本并自动升级
|
||||
|
||||
**As** 一线经纪人,**I want** 客户端在有新版本时自动提示并完成升级,**So that** 我无需手动下载安装,始终使用最新版本,不会因版本落后导致功能异常。
|
||||
|
||||
**验收标准**:
|
||||
- [ ] 客户端启动时及运行期间(每隔 4 小时)自动向更新服务器检查最新版本
|
||||
- [ ] 有新版本时,客户端右下角弹出非阻断式通知:"发现新版本 vX.X.X,点击立即更新",用户可选择"立即更新"或"稍后提醒"
|
||||
- [ ] 点击"立即更新"后,客户端在后台静默下载更新包,进度条显示下载进度
|
||||
- [ ] 下载完成后提示用户"更新已就绪,重启客户端完成安装",用户选择"立即重启"或"下次启动时安装"
|
||||
- [ ] 重启后,新版本生效,标题栏版本号更新,历史会话自动恢复(用户无需重新登录)
|
||||
- [ ] 支持强制更新模式:服务端可标记某版本为"强制升级",客户端不展示"稍后提醒"选项,必须升级后方可继续使用(用于重大 API 兼容性变更场景)
|
||||
- [ ] 更新失败时(网络中断、磁盘空间不足等),客户端显示错误提示并保持当前版本正常运行,不影响用户当前操作
|
||||
|
||||
---
|
||||
|
||||
### Story 4:系统管理员发布新版本
|
||||
|
||||
**As** 系统管理员,**I want** 通过管理后台上传新版客户端安装包并配置版本信息,**So that** 客户端能感知到更新并引导用户升级。
|
||||
|
||||
**验收标准**:
|
||||
- [ ] 系统管理后台提供"客户端版本管理"页面(位于系统管理模块下)
|
||||
- [ ] 支持上传 `.exe` 安装包,并填写版本号(遵循 SemVer:`X.Y.Z`)、版本说明(更新日志,支持 Markdown)、发布日期
|
||||
- [ ] 支持设置版本类型:普通更新 / 强制更新
|
||||
- [ ] 支持设置版本状态:草稿(不对外生效)/ 已发布 / 已下线
|
||||
- [ ] 发布后,更新服务器 API 即时返回最新版本信息,客户端下次检测时可感知
|
||||
- [ ] 支持版本回滚:将指定历史版本重新设为"已发布",自动将当前版本标记为已下线
|
||||
- [ ] 支持查看各版本的下载量和活跃客户端版本分布统计
|
||||
|
||||
---
|
||||
|
||||
### Story 5:管理员监控客户端版本分布
|
||||
|
||||
**As** 系统管理员,**I want** 查看当前所有在线客户端的版本分布情况,**So that** 了解升级覆盖率,对仍在使用旧版本的客户端发出提醒或强制升级。
|
||||
|
||||
**验收标准**:
|
||||
- [ ] 客户端版本管理页面展示版本分布统计:各版本在线客户端数量及占比(饼图或条形图)
|
||||
- [ ] 支持按租户维度查看版本分布(多租户场景下,区分不同经纪公司的版本使用情况)
|
||||
- [ ] 支持对指定版本范围的用户推送"强制更新"通知(如:将所有低于 v1.5.0 的客户端标记为强制更新)
|
||||
|
||||
---
|
||||
|
||||
## 5. 功能详细说明
|
||||
|
||||
### 5.1 技术架构选型
|
||||
|
||||
#### 5.1.1 客户端技术方案
|
||||
|
||||
基于 Fonrey 现有技术栈(Django + HTMX + Alpine.js + Tailwind CSS,后端已采用 Docker Compose 部署),客户端本质是一个**内嵌现代 Chromium 内核的原生 Windows 应用外壳(Shell)**,其核心职责是:
|
||||
|
||||
1. 提供操作系统级原生窗口(标题栏、任务栏图标、托盘)
|
||||
2. 内嵌高版本 Chromium 内核加载 Fonrey Web 应用 URL
|
||||
3. 实现版本检测与自动更新逻辑
|
||||
4. 处理文件下载、本地存储等 OS 级能力
|
||||
|
||||
**推荐方案:Electron(主选)**
|
||||
|
||||
| 维度 | Electron | Tauri | WebView2 封装 |
|
||||
|------|---------|-------|--------------|
|
||||
| 内核控制 | ✅ 捆绑 Chromium,100% 可控 | ❌ 依赖系统 WebView,版本不可控 | ⚠️ 依赖 Windows 内置 WebView2 Runtime |
|
||||
| 包体大小 | ~150MB(可接受) | ~5MB | ~5MB |
|
||||
| 生态成熟度 | ✅ 最成熟,社区最大 | ✅ 较新但活跃 | ⚠️ 微软官方但文档偏少 |
|
||||
| 自动更新支持 | ✅ `electron-updater` 成熟方案 | ✅ 内置更新器 | ⚠️ 需自行实现 |
|
||||
| 跨平台 | ✅ Win/Mac/Linux | ✅ | ❌ 仅 Windows |
|
||||
| 团队技术匹配 | ✅ 主进程用 Node.js,渲染层纯 Web | ⚠️ 主进程需 Rust | ✅ 主进程用 C# |
|
||||
| **推荐度** | **✅ 主选** | 次选 | 备选 |
|
||||
|
||||
**选型决策**:采用 **Electron + electron-updater**。理由:
|
||||
|
||||
- 内嵌 Chromium 内核是本需求的核心约束,Electron 是唯一能 100% 保证内核版本可控的主流方案
|
||||
- `electron-updater` 配合 GitHub Releases 或自建 S3/R2 存储可实现完整的版本管理与自动更新流程,开发成本最低
|
||||
- 渲染层完全复用 Fonrey 现有 Web 技术栈,无需新增前端框架学习成本
|
||||
- 团队具备 JavaScript/Node.js 能力,主进程开发门槛可控
|
||||
|
||||
**技术决策**:客户端不内置任何业务逻辑,所有业务功能由服务端 Fonrey Web 应用提供。客户端仅负责加载 Web 应用、更新管理和 OS 级能力(窗口、托盘、文件下载路径)。
|
||||
|
||||
---
|
||||
|
||||
#### 5.1.2 更新服务架构
|
||||
|
||||
更新机制采用**差量检测 + 全量包下载**模式:
|
||||
|
||||
```
|
||||
客户端启动 / 定时检测(每4小时)
|
||||
│
|
||||
▼
|
||||
GET /api/client/updates/latest?platform=win32&arch=x64¤t_version=1.2.0
|
||||
│
|
||||
▼
|
||||
更新服务器(Fonrey 后端 Django API)
|
||||
返回:{ latest_version, download_url, release_notes, force_update, checksum }
|
||||
│
|
||||
├── 无更新 → 继续正常运行
|
||||
│
|
||||
└── 有更新 → 弹出通知
|
||||
│
|
||||
├── 用户点击"立即更新" → 后台下载 .exe / NSIS 更新包
|
||||
│ │
|
||||
│ └── 下载完成 → 校验 SHA256 → 提示重启安装
|
||||
│
|
||||
└── 用户选择"稍后" → 下次启动再提示
|
||||
```
|
||||
|
||||
**更新包存储**:上传至 Cloudflare R2(与现有对象存储一致),通过 Cloudflare CDN 加速下载,全国用户均可获得稳定下载速度。
|
||||
|
||||
**版本 API 端点**(新增至 Django 后端):
|
||||
|
||||
| 端点 | 方法 | 说明 |
|
||||
|------|------|------|
|
||||
| `/api/client/updates/latest/` | GET | 客户端查询最新版本,返回版本信息和下载 URL |
|
||||
| `/api/client/updates/` | GET | 管理端查询版本列表(需认证) |
|
||||
| `/api/client/updates/` | POST | 管理端发布新版本(需管理员权限) |
|
||||
| `/api/client/updates/<id>/` | PATCH | 管理端修改版本状态(发布/下线/强制) |
|
||||
|
||||
---
|
||||
|
||||
#### 5.1.3 安装包签名与分发
|
||||
|
||||
**代码签名**:
|
||||
- 使用 EV 代码签名证书(推荐购买 DigiCert 或 Sectigo EV 证书)
|
||||
- 通过 `electron-builder` 在 CI/CD 构建时自动签名
|
||||
- 签名后安装包经 Windows SmartScreen 审核,用户安装时不触发安全警告
|
||||
|
||||
**安装包分发**:
|
||||
- 官方下载页:独立 HTML 页面托管于 Cloudflare Pages 或 Nginx 静态站
|
||||
- 页面展示:最新版本号 + 发布日期 + 更新日志 + 下载按钮
|
||||
- 下载 URL 格式:`https://download.fonrey.com/releases/v1.2.3/fonrey-setup-1.2.3-win.exe`
|
||||
- 同时提供便携版(Portable):`fonrey-portable-1.2.3-win.zip`,供无安装权限的企业环境使用
|
||||
|
||||
---
|
||||
|
||||
### 5.2 客户端功能规格
|
||||
|
||||
#### 5.2.1 主窗口
|
||||
|
||||
| 属性 | 规格 |
|
||||
|------|------|
|
||||
| 默认窗口尺寸 | 1280 × 800(最小:1024 × 600) |
|
||||
| 标题栏 | 显示 `Fonrey 房睿 v{version}`,含原生最小化/最大化/关闭按钮 |
|
||||
| 内嵌 URL | 启动时加载 `https://{tenant}.fonrey.com`(或私有化部署地址,可配置) |
|
||||
| 地址栏 | 不显示(沉浸式应用模式) |
|
||||
| 右键菜单 | 仅保留"复制"/"粘贴"/"检查元素(仅开发模式)",移除"查看源代码"等浏览器默认项 |
|
||||
| 外部链接 | 点击 `target="_blank"` 链接时,在系统默认浏览器中打开,不在客户端内新窗口打开 |
|
||||
|
||||
#### 5.2.2 系统托盘
|
||||
|
||||
| 功能 | 说明 |
|
||||
|------|------|
|
||||
| 托盘图标 | Fonrey Logo,鼠标悬停显示 `Fonrey 房睿 - 已连接` / `- 离线` |
|
||||
| 右键菜单 | 打开主窗口 / 检查更新 / 关于 / 退出 |
|
||||
| 最小化行为 | 点击关闭按钮时最小化至托盘(不退出程序),用户通过托盘图标恢复窗口 |
|
||||
|
||||
#### 5.2.3 网络状态感知
|
||||
|
||||
| 状态 | 客户端行为 |
|
||||
|------|-----------|
|
||||
| 正常联网 | 加载 Fonrey Web 应用,状态栏显示"已连接" |
|
||||
| 网络断开 | 显示全屏提示页:"网络连接已断开,请检查您的网络后重试",提供"重新连接"按钮 |
|
||||
| 服务器维护 | 服务器返回 503 时,展示维护提示页(内容由服务端控制) |
|
||||
|
||||
#### 5.2.4 文件下载处理
|
||||
|
||||
- Excel 导出等文件下载触发时,客户端调用系统原生"另存为"对话框,用户选择保存路径
|
||||
- 下载完成后,状态栏显示"下载完成,点击打开"提示,点击可直接打开文件
|
||||
|
||||
---
|
||||
|
||||
### 5.3 版本管理后台(系统管理模块新增页面)
|
||||
|
||||
**页面路径**:系统管理 → 客户端发布管理
|
||||
|
||||
#### 5.3.1 版本列表
|
||||
|
||||
| 列 | 说明 |
|
||||
|----|------|
|
||||
| 版本号 | SemVer 格式,如 `v1.2.3` |
|
||||
| 版本类型 | 普通更新 / 强制更新(红色标签) |
|
||||
| 状态 | 草稿 / 已发布(绿色)/ 已下线(灰色) |
|
||||
| 发布时间 | 版本设为已发布的时间 |
|
||||
| 下载量 | 该版本安装包被下载次数 |
|
||||
| 操作 | 发布 / 下线 / 编辑 / 复制下载链接 |
|
||||
|
||||
#### 5.3.2 新增/编辑版本表单
|
||||
|
||||
| 字段 | 类型 | 必填 | 说明 |
|
||||
|------|------|------|------|
|
||||
| 版本号 | 文本输入 | 是 | 格式:`X.Y.Z`,自动校验 SemVer 格式 |
|
||||
| 版本类型 | 单选 | 是 | 普通更新 / 强制更新 |
|
||||
| 最低兼容版本 | 文本输入 | 否 | 低于该版本的客户端将被强制更新(如填写 `1.0.0`,则低于此版本的客户端强制升级) |
|
||||
| 安装包(EXE) | 文件上传 | 是 | 上传至 Cloudflare R2,最大 500MB |
|
||||
| 便携版(ZIP) | 文件上传 | 否 | 同上 |
|
||||
| SHA256 校验值 | 文本输入(自动填充) | 是 | 上传后系统自动计算并填充,用于客户端下载完成后校验完整性 |
|
||||
| 更新日志 | Markdown 文本区域 | 是 | 展示给用户看的版本说明,最多 2000 字 |
|
||||
| 发布说明(内部) | 文本区域 | 否 | 仅内部查看的技术说明,不对外展示 |
|
||||
| 状态 | 单选 | 是 | 草稿 / 立即发布 |
|
||||
|
||||
#### 5.3.3 版本分布统计
|
||||
|
||||
| 图表 | 说明 |
|
||||
|------|------|
|
||||
| 版本分布饼图 | 按客户端版本号统计当前活跃用户数量及占比 |
|
||||
| 升级进度趋势图 | 新版本发布后,各天累计升级完成的用户比例(折线图) |
|
||||
| 租户版本明细 | 按租户(经纪公司)展示其员工的客户端版本分布 |
|
||||
|
||||
---
|
||||
|
||||
### 5.4 更新 API 规格
|
||||
|
||||
#### GET `/api/client/updates/latest/`
|
||||
|
||||
**请求参数(Query String)**:
|
||||
|
||||
| 参数 | 类型 | 必填 | 说明 |
|
||||
|------|------|------|------|
|
||||
| `platform` | string | 是 | 平台标识,如 `win32` |
|
||||
| `arch` | string | 是 | CPU 架构,如 `x64` / `arm64` |
|
||||
| `current_version` | string | 是 | 客户端当前版本号,如 `1.2.0` |
|
||||
|
||||
**响应示例(有新版本)**:
|
||||
|
||||
```json
|
||||
{
|
||||
"has_update": true,
|
||||
"latest_version": "1.3.0",
|
||||
"force_update": false,
|
||||
"download_url": "https://download.fonrey.com/releases/v1.3.0/fonrey-setup-1.3.0-win.exe",
|
||||
"portable_url": "https://download.fonrey.com/releases/v1.3.0/fonrey-portable-1.3.0-win.zip",
|
||||
"checksum_sha256": "a1b2c3d4...",
|
||||
"release_notes": "## v1.3.0 更新内容\n- 新增客源智能配房功能\n- 修复房源列表筛选条件保存异常",
|
||||
"release_date": "2026-05-01"
|
||||
}
|
||||
```
|
||||
|
||||
**响应示例(已是最新)**:
|
||||
|
||||
```json
|
||||
{
|
||||
"has_update": false,
|
||||
"latest_version": "1.3.0"
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 6. 技术实现注意事项
|
||||
|
||||
### 6.1 依赖关系
|
||||
|
||||
| 依赖项 | 说明 | 负责方 | 风险等级 |
|
||||
|--------|------|--------|---------|
|
||||
| Electron 框架 | 客户端技术基础,需评估 License(MIT,商业可用) | 前端/客户端工程师 | 低 |
|
||||
| EV 代码签名证书 | 需提前申请,EV 证书审核周期 1-2 周 | IT/运维 | 中(需提前排期) |
|
||||
| Cloudflare R2 存储桶 | 存放安装包,利用现有账号新增 bucket | 运维 | 低 |
|
||||
| `electron-updater` | 自动更新库,需配合更新 API 端点实现 | 客户端工程师 | 低 |
|
||||
| Django 更新 API | 新增 `/api/client/updates/` 相关接口 | 后端工程师 | 低 |
|
||||
| CI/CD 构建流水线 | 自动构建、签名、上传安装包 | 运维/DevOps | 中 |
|
||||
|
||||
### 6.2 已知风险
|
||||
|
||||
| 风险 | 可能性 | 影响 | 缓解措施 |
|
||||
|------|--------|------|---------|
|
||||
| EV 证书申请延迟 | 中 | 高(无签名包无法正常分发) | MVP 阶段可使用普通 OV 证书临时过渡,但需向用户说明安全警告原因 |
|
||||
| Electron 包体过大导致下载放弃 | 低 | 中 | 使用 `electron-builder` 的 `asar` 压缩 + 分片下载;首包控制在 150MB 以内 |
|
||||
| 企业网络拦截 CDN 下载 | 中 | 中 | 提供备用下载 URL(直连服务器),支持客户手动下载后本地安装 |
|
||||
| 自动更新期间用户强制关闭 | 低 | 低 | 更新包下载完成后才替换原文件,下载中断不影响现有版本正常运行 |
|
||||
| 多租户场景下 URL 配置问题 | 低 | 高 | 客户端启动时加载的 URL 通过配置文件指定,支持定制化部署;SaaS 版统一指向主域名 |
|
||||
|
||||
### 6.3 开放问题(开发启动前必须解决)
|
||||
|
||||
- [ ] **租户 URL 如何分发到客户端?** 选项 A:客户端硬编码主域名,由服务端重定向到租户子域(`fonrey.com` → `{tenant}.fonrey.com`);选项 B:安装包内置配置文件,由销售/运维在分发给客户前填写租户子域。——**Owner**: 产品 + 工程 **Deadline**: 开发启动前
|
||||
- [ ] **代码签名证书采购主体和预算是否确认?** — **Owner**: IT 负责人 **Deadline**: 立项后 1 周
|
||||
- [ ] **CI/CD 平台选型是否确定?**(GitHub Actions / Jenkins / 其他)— **Owner**: 运维负责人 **Deadline**: 开发启动前
|
||||
- [ ] **便携版(Portable ZIP)是否纳入 v1 范围?** 便携版可解决企业无安装权限场景,但增加测试成本。— **Owner**: PM **Deadline**: 立项后 1 周
|
||||
|
||||
---
|
||||
|
||||
## 7. 发布计划
|
||||
|
||||
| 阶段 | 时间 | 受众 | 成功门槛 |
|
||||
|------|------|------|---------|
|
||||
| 内部 Alpha | 开发完成后 1 周 | 内部团队 + 1 家种子客户 | 核心流程无 P0 Bug,自动更新机制验证通过 |
|
||||
| 封闭 Beta | Alpha + 2 周 | 3-5 家头部客户 | 安装成功率 ≥ 95%,自动更新成功率 ≥ 95%,无 P0/P1 Bug |
|
||||
| 正式发布(GA) | Beta + 1 周 | 全部客户 | Beta 阶段目标达成 |
|
||||
|
||||
**回滚标准**:若正式发布后 24 小时内出现以下情况,立即下线该版本并恢复上一稳定版本为"已发布":
|
||||
- 自动更新失败率 > 5%
|
||||
- 客户端白屏/崩溃率 > 2%
|
||||
- 收到 P0 级安全漏洞报告
|
||||
|
||||
---
|
||||
|
||||
## 8. 附录
|
||||
|
||||
### 8.1 竞品参考
|
||||
|
||||
| 产品 | 客户端方案 | 更新机制 |
|
||||
|------|-----------|---------|
|
||||
| 企业微信 | Electron + 自研内核 | 强制更新,启动时自动下载 |
|
||||
| 飞书 | Electron | 后台静默更新,重启生效 |
|
||||
| 钉钉 | Electron | 同上 |
|
||||
|
||||
> 房产经纪行业的竞品(如房客多、云客优)均采用 Electron 方案,验证了技术路线的合理性。
|
||||
|
||||
### 8.2 术语表
|
||||
|
||||
| 术语 | 定义 |
|
||||
|------|------|
|
||||
| SemVer | 语义化版本控制(Semantic Versioning):`主版本号.次版本号.补丁号`,如 `1.2.3` |
|
||||
| Electron | 由 GitHub 开发的开源框架,允许使用 Web 技术(HTML/CSS/JS)构建跨平台桌面应用,内嵌 Chromium 和 Node.js |
|
||||
| electron-updater | Electron 生态中成熟的自动更新库,支持增量更新和全量更新 |
|
||||
| EV 证书 | Extended Validation 代码签名证书,由 CA 机构颁发,可消除 Windows SmartScreen 安全警告 |
|
||||
| SHA256 | 安全散列算法,用于验证下载文件的完整性,防止篡改或下载损坏 |
|
||||
| Portable | 便携版,无需安装,解压即用,适合无管理员权限的企业环境 |
|
||||
# PRD: 客户端发布管理模块
|
||||
**状态**: Draft
|
||||
**作者**: 产品经理
|
||||
**最后更新**: 2026-04-24(v1.0 初稿)
|
||||
**版本**: 1.0
|
||||
**所属系统**: Fonrey 房产经纪管理系统
|
||||
**关联模块**: 系统管理、权限管理
|
||||
**干系人**: 工程负责人、运维负责人、系统管理员
|
||||
|
||||
---
|
||||
|
||||
## 1. 问题陈述
|
||||
|
||||
### 背景
|
||||
|
||||
Fonrey 房产经纪管理系统当前为纯 Web 应用,依赖用户自行通过浏览器访问。然而在实际部署场景中,经纪公司的终端设备环境高度复杂:
|
||||
|
||||
- **浏览器版本参差不齐**:经纪人使用的 Windows 设备可能运行 IE11、旧版 Edge、或未更新的 Chrome,导致 HTMX + Alpine.js 等现代前端技术出现兼容性问题,系统体验碎片化
|
||||
- **交付和部署门槛高**:IT 能力薄弱的经纪公司无法独立配置浏览器访问方式,URL 记忆成本高,容易访问错误版本
|
||||
- **版本管理缺失**:后端服务升级后,用户仍可能使用旧版缓存页面操作,导致接口不兼容和功能异常
|
||||
- **无官方入口**:用户通过私发链接访问系统,存在钓鱼仿冒风险,且无法统一品牌形象
|
||||
|
||||
### 目标用户
|
||||
|
||||
| 角色 | 使用场景 | 使用频率 |
|
||||
|------|---------|----------|
|
||||
| 一线经纪人 | 下载安装客户端、日常登录使用系统、接受自动更新 | 每日 |
|
||||
| 店长/经理 | 同上 | 每日 |
|
||||
| 系统管理员 | 发布新版本、管理安装包下载地址、监控客户端版本分布 | 按需 |
|
||||
| IT 运维人员 | 维护更新服务器、签名证书、构建发布流水线 | 按发布周期 |
|
||||
|
||||
### 核心痛点
|
||||
|
||||
1. **无法控制用户使用的浏览器环境**,兼容性问题无法从根源解决
|
||||
2. **升级依赖用户主动刷新浏览器**,后端 API 变更时旧客户端可能造成数据错误
|
||||
3. **缺乏官方分发渠道**,无法向终端用户传递信任感和版本一致性保障
|
||||
4. **SaaS 多租户管理系统需要统一、可控的客户端入口**,避免因客户端环境差异导致的支持成本上升
|
||||
|
||||
---
|
||||
|
||||
## 2. 目标与成功指标
|
||||
|
||||
| 目标 | 指标 | 当前基准 | 目标值 | 衡量周期 |
|
||||
|------|------|---------|--------|---------|
|
||||
| 消除浏览器兼容性问题 | 因浏览器兼容产生的支持工单数 | 待统计 | 降低 ≥ 90% | 上线后 60 天 |
|
||||
| 提升版本一致性 | 在线用户中使用最新版本客户端的比例 | 0%(无客户端) | ≥ 95% | 版本发布后 7 天 |
|
||||
| 降低部署门槛 | 新客户从获取安装包到完成首次登录的时间 | 无基准 | ≤ 10 分钟 | 上线后首批客户反馈 |
|
||||
| 自动更新成功率 | 客户端自动更新完成率(收到更新通知 → 升级完成) | 无基准 | ≥ 98% | 每次版本发布后 48 小时 |
|
||||
|
||||
---
|
||||
|
||||
## 3. 非目标(本期不做)
|
||||
|
||||
- **不支持 macOS / Linux 客户端**:目标用户群体 99% 使用 Windows,macOS 版本为后续规划
|
||||
- **不支持移动端 App(iOS / Android)**:移动端为 v2 规划,本期不涉及
|
||||
- **不开发私有化部署的离线安装方案**:本期聚焦 SaaS 在线版,私有化部署另行规划
|
||||
- **不包含客户端内置的离线模式**:系统需联网使用,客户端不缓存业务数据供离线访问
|
||||
- **不包含客户端层面的安全加固(如代码混淆、反逆向)**:本期以功能交付为优先,安全加固列入后续迭代
|
||||
|
||||
---
|
||||
|
||||
## 4. 用户故事与验收标准
|
||||
|
||||
---
|
||||
|
||||
### Story 1:经纪人下载并安装客户端
|
||||
|
||||
**As** 一线经纪人,**I want** 通过公司提供的网址下载一个安装程序并完成安装,**So that** 我可以立即打开登录界面使用 Fonrey 系统,无需手动配置浏览器。
|
||||
|
||||
**验收标准**:
|
||||
- [ ] 官方下载页面可通过指定 URL 访问,页面展示最新版本号、发布日期及下载按钮
|
||||
- [ ] 下载产物为单一 `.exe` 安装包(或免安装便携版 `.zip`),文件大小控制在合理范围内
|
||||
- [ ] 双击安装包后,安装向导步骤不超过 3 步(下一步 → 选择安装路径 → 安装),无需勾选额外组件
|
||||
- [ ] 安装完成后,桌面自动生成快捷方式(图标为 Fonrey 品牌 Logo)
|
||||
- [ ] 首次启动后直接显示登录界面,无需用户手动输入任何 URL
|
||||
- [ ] 安装包经过代码签名,Windows SmartScreen 不弹出"无法识别的应用"警告
|
||||
- [ ] 安装过程无需管理员权限(支持用户级安装到 `%APPDATA%` 目录),降低企业 IT 审批障碍
|
||||
|
||||
---
|
||||
|
||||
### Story 2:经纪人使用客户端正常登录并使用系统
|
||||
|
||||
**As** 一线经纪人,**I want** 打开客户端后直接访问 Fonrey 系统的完整功能,**So that** 我的日常使用体验与使用 Chrome 浏览器无差异,且不受本机安装的浏览器版本影响。
|
||||
|
||||
**验收标准**:
|
||||
- [ ] 客户端内嵌现代 Chromium 内核(如基于 Electron 或 WebView2),版本不低于 Chromium 100,支持现代 Web 标准(ES2020、CSS Grid、Fetch API 等)
|
||||
- [ ] HTMX 局部刷新、Alpine.js 状态交互、Tailwind CSS 样式在客户端中渲染效果与 Chrome 最新版一致
|
||||
- [ ] 支持 Cookie / Session 存储,登录状态在客户端关闭后保留(复用 Django Session 机制)
|
||||
- [ ] 文件上传(图片、附件)、文件下载(Excel 导出)在客户端中正常工作
|
||||
- [ ] 客户端窗口支持最大化、最小化、拖拽调整大小,支持多显示器
|
||||
- [ ] 客户端标题栏显示应用名称和当前版本号(如:`Fonrey 房睿 v1.2.3`)
|
||||
- [ ] 客户端不显示浏览器默认的地址栏、书签栏、扩展工具栏,保持沉浸式应用体验
|
||||
|
||||
---
|
||||
|
||||
### Story 3:客户端感知新版本并自动升级
|
||||
|
||||
**As** 一线经纪人,**I want** 客户端在有新版本时自动提示并完成升级,**So that** 我无需手动下载安装,始终使用最新版本,不会因版本落后导致功能异常。
|
||||
|
||||
**验收标准**:
|
||||
- [ ] 客户端启动时及运行期间(每隔 4 小时)自动向更新服务器检查最新版本
|
||||
- [ ] 有新版本时,客户端右下角弹出非阻断式通知:"发现新版本 vX.X.X,点击立即更新",用户可选择"立即更新"或"稍后提醒"
|
||||
- [ ] 点击"立即更新"后,客户端在后台静默下载更新包,进度条显示下载进度
|
||||
- [ ] 下载完成后提示用户"更新已就绪,重启客户端完成安装",用户选择"立即重启"或"下次启动时安装"
|
||||
- [ ] 重启后,新版本生效,标题栏版本号更新,历史会话自动恢复(用户无需重新登录)
|
||||
- [ ] 支持强制更新模式:服务端可标记某版本为"强制升级",客户端不展示"稍后提醒"选项,必须升级后方可继续使用(用于重大 API 兼容性变更场景)
|
||||
- [ ] 更新失败时(网络中断、磁盘空间不足等),客户端显示错误提示并保持当前版本正常运行,不影响用户当前操作
|
||||
|
||||
---
|
||||
|
||||
### Story 4:系统管理员发布新版本
|
||||
|
||||
**As** 系统管理员,**I want** 通过管理后台上传新版客户端安装包并配置版本信息,**So that** 客户端能感知到更新并引导用户升级。
|
||||
|
||||
**验收标准**:
|
||||
- [ ] 系统管理后台提供"客户端版本管理"页面(位于系统管理模块下)
|
||||
- [ ] 支持上传 `.exe` 安装包,并填写版本号(遵循 SemVer:`X.Y.Z`)、版本说明(更新日志,支持 Markdown)、发布日期
|
||||
- [ ] 支持设置版本类型:普通更新 / 强制更新
|
||||
- [ ] 支持设置版本状态:草稿(不对外生效)/ 已发布 / 已下线
|
||||
- [ ] 发布后,更新服务器 API 即时返回最新版本信息,客户端下次检测时可感知
|
||||
- [ ] 支持版本回滚:将指定历史版本重新设为"已发布",自动将当前版本标记为已下线
|
||||
- [ ] 支持查看各版本的下载量和活跃客户端版本分布统计
|
||||
|
||||
---
|
||||
|
||||
### Story 5:管理员监控客户端版本分布
|
||||
|
||||
**As** 系统管理员,**I want** 查看当前所有在线客户端的版本分布情况,**So that** 了解升级覆盖率,对仍在使用旧版本的客户端发出提醒或强制升级。
|
||||
|
||||
**验收标准**:
|
||||
- [ ] 客户端版本管理页面展示版本分布统计:各版本在线客户端数量及占比(饼图或条形图)
|
||||
- [ ] 支持按租户维度查看版本分布(多租户场景下,区分不同经纪公司的版本使用情况)
|
||||
- [ ] 支持对指定版本范围的用户推送"强制更新"通知(如:将所有低于 v1.5.0 的客户端标记为强制更新)
|
||||
|
||||
---
|
||||
|
||||
## 5. 功能详细说明
|
||||
|
||||
### 5.1 技术架构选型
|
||||
|
||||
#### 5.1.1 客户端技术方案
|
||||
|
||||
基于 Fonrey 现有技术栈(Django + HTMX + Alpine.js + Tailwind CSS,后端已采用 Docker Compose 部署),客户端本质是一个**内嵌现代 Chromium 内核的原生 Windows 应用外壳(Shell)**,其核心职责是:
|
||||
|
||||
1. 提供操作系统级原生窗口(标题栏、任务栏图标、托盘)
|
||||
2. 内嵌高版本 Chromium 内核加载 Fonrey Web 应用 URL
|
||||
3. 实现版本检测与自动更新逻辑
|
||||
4. 处理文件下载、本地存储等 OS 级能力
|
||||
|
||||
**推荐方案:Electron(主选)**
|
||||
|
||||
| 维度 | Electron | Tauri | WebView2 封装 |
|
||||
|------|---------|-------|--------------|
|
||||
| 内核控制 | ✅ 捆绑 Chromium,100% 可控 | ❌ 依赖系统 WebView,版本不可控 | ⚠️ 依赖 Windows 内置 WebView2 Runtime |
|
||||
| 包体大小 | ~150MB(可接受) | ~5MB | ~5MB |
|
||||
| 生态成熟度 | ✅ 最成熟,社区最大 | ✅ 较新但活跃 | ⚠️ 微软官方但文档偏少 |
|
||||
| 自动更新支持 | ✅ `electron-updater` 成熟方案 | ✅ 内置更新器 | ⚠️ 需自行实现 |
|
||||
| 跨平台 | ✅ Win/Mac/Linux | ✅ | ❌ 仅 Windows |
|
||||
| 团队技术匹配 | ✅ 主进程用 Node.js,渲染层纯 Web | ⚠️ 主进程需 Rust | ✅ 主进程用 C# |
|
||||
| **推荐度** | **✅ 主选** | 次选 | 备选 |
|
||||
|
||||
**选型决策**:采用 **Electron + electron-updater**。理由:
|
||||
|
||||
- 内嵌 Chromium 内核是本需求的核心约束,Electron 是唯一能 100% 保证内核版本可控的主流方案
|
||||
- `electron-updater` 配合 GitHub Releases 或自建 S3/R2 存储可实现完整的版本管理与自动更新流程,开发成本最低
|
||||
- 渲染层完全复用 Fonrey 现有 Web 技术栈,无需新增前端框架学习成本
|
||||
- 团队具备 JavaScript/Node.js 能力,主进程开发门槛可控
|
||||
|
||||
**技术决策**:客户端不内置任何业务逻辑,所有业务功能由服务端 Fonrey Web 应用提供。客户端仅负责加载 Web 应用、更新管理和 OS 级能力(窗口、托盘、文件下载路径)。
|
||||
|
||||
---
|
||||
|
||||
#### 5.1.2 更新服务架构
|
||||
|
||||
更新机制采用**差量检测 + 全量包下载**模式:
|
||||
|
||||
```
|
||||
客户端启动 / 定时检测(每4小时)
|
||||
│
|
||||
▼
|
||||
GET /api/client/updates/latest?platform=win32&arch=x64¤t_version=1.2.0
|
||||
│
|
||||
▼
|
||||
更新服务器(Fonrey 后端 Django API)
|
||||
返回:{ latest_version, download_url, release_notes, force_update, checksum }
|
||||
│
|
||||
├── 无更新 → 继续正常运行
|
||||
│
|
||||
└── 有更新 → 弹出通知
|
||||
│
|
||||
├── 用户点击"立即更新" → 后台下载 .exe / NSIS 更新包
|
||||
│ │
|
||||
│ └── 下载完成 → 校验 SHA256 → 提示重启安装
|
||||
│
|
||||
└── 用户选择"稍后" → 下次启动再提示
|
||||
```
|
||||
|
||||
**更新包存储**:上传至 Cloudflare R2(与现有对象存储一致),通过 Cloudflare CDN 加速下载,全国用户均可获得稳定下载速度。
|
||||
|
||||
**版本 API 端点**(新增至 Django 后端):
|
||||
|
||||
| 端点 | 方法 | 说明 |
|
||||
|------|------|------|
|
||||
| `/api/client/updates/latest/` | GET | 客户端查询最新版本,返回版本信息和下载 URL |
|
||||
| `/api/client/updates/` | GET | 管理端查询版本列表(需认证) |
|
||||
| `/api/client/updates/` | POST | 管理端发布新版本(需管理员权限) |
|
||||
| `/api/client/updates/<id>/` | PATCH | 管理端修改版本状态(发布/下线/强制) |
|
||||
|
||||
---
|
||||
|
||||
#### 5.1.3 安装包签名与分发
|
||||
|
||||
**代码签名**:
|
||||
- 使用 EV 代码签名证书(推荐购买 DigiCert 或 Sectigo EV 证书)
|
||||
- 通过 `electron-builder` 在 CI/CD 构建时自动签名
|
||||
- 签名后安装包经 Windows SmartScreen 审核,用户安装时不触发安全警告
|
||||
|
||||
**安装包分发**:
|
||||
- 官方下载页:独立 HTML 页面托管于 Cloudflare Pages 或 Nginx 静态站
|
||||
- 页面展示:最新版本号 + 发布日期 + 更新日志 + 下载按钮
|
||||
- 下载 URL 格式:`https://download.fonrey.com/releases/v1.2.3/fonrey-setup-1.2.3-win.exe`
|
||||
- 同时提供便携版(Portable):`fonrey-portable-1.2.3-win.zip`,供无安装权限的企业环境使用
|
||||
|
||||
---
|
||||
|
||||
### 5.2 客户端功能规格
|
||||
|
||||
#### 5.2.1 主窗口
|
||||
|
||||
| 属性 | 规格 |
|
||||
|------|------|
|
||||
| 默认窗口尺寸 | 1280 × 800(最小:1024 × 600) |
|
||||
| 标题栏 | 显示 `Fonrey 房睿 v{version}`,含原生最小化/最大化/关闭按钮 |
|
||||
| 内嵌 URL | 启动时加载 `https://{tenant}.fonrey.com`(或私有化部署地址,可配置) |
|
||||
| 地址栏 | 不显示(沉浸式应用模式) |
|
||||
| 右键菜单 | 仅保留"复制"/"粘贴"/"检查元素(仅开发模式)",移除"查看源代码"等浏览器默认项 |
|
||||
| 外部链接 | 点击 `target="_blank"` 链接时,在系统默认浏览器中打开,不在客户端内新窗口打开 |
|
||||
|
||||
#### 5.2.2 系统托盘
|
||||
|
||||
| 功能 | 说明 |
|
||||
|------|------|
|
||||
| 托盘图标 | Fonrey Logo,鼠标悬停显示 `Fonrey 房睿 - 已连接` / `- 离线` |
|
||||
| 右键菜单 | 打开主窗口 / 检查更新 / 关于 / 退出 |
|
||||
| 最小化行为 | 点击关闭按钮时最小化至托盘(不退出程序),用户通过托盘图标恢复窗口 |
|
||||
|
||||
#### 5.2.3 网络状态感知
|
||||
|
||||
| 状态 | 客户端行为 |
|
||||
|------|-----------|
|
||||
| 正常联网 | 加载 Fonrey Web 应用,状态栏显示"已连接" |
|
||||
| 网络断开 | 显示全屏提示页:"网络连接已断开,请检查您的网络后重试",提供"重新连接"按钮 |
|
||||
| 服务器维护 | 服务器返回 503 时,展示维护提示页(内容由服务端控制) |
|
||||
|
||||
#### 5.2.4 文件下载处理
|
||||
|
||||
- Excel 导出等文件下载触发时,客户端调用系统原生"另存为"对话框,用户选择保存路径
|
||||
- 下载完成后,状态栏显示"下载完成,点击打开"提示,点击可直接打开文件
|
||||
|
||||
---
|
||||
|
||||
### 5.3 版本管理后台(系统管理模块新增页面)
|
||||
|
||||
**页面路径**:系统管理 → 客户端发布管理
|
||||
|
||||
#### 5.3.1 版本列表
|
||||
|
||||
| 列 | 说明 |
|
||||
|----|------|
|
||||
| 版本号 | SemVer 格式,如 `v1.2.3` |
|
||||
| 版本类型 | 普通更新 / 强制更新(红色标签) |
|
||||
| 状态 | 草稿 / 已发布(绿色)/ 已下线(灰色) |
|
||||
| 发布时间 | 版本设为已发布的时间 |
|
||||
| 下载量 | 该版本安装包被下载次数 |
|
||||
| 操作 | 发布 / 下线 / 编辑 / 复制下载链接 |
|
||||
|
||||
#### 5.3.2 新增/编辑版本表单
|
||||
|
||||
| 字段 | 类型 | 必填 | 说明 |
|
||||
|------|------|------|------|
|
||||
| 版本号 | 文本输入 | 是 | 格式:`X.Y.Z`,自动校验 SemVer 格式 |
|
||||
| 版本类型 | 单选 | 是 | 普通更新 / 强制更新 |
|
||||
| 最低兼容版本 | 文本输入 | 否 | 低于该版本的客户端将被强制更新(如填写 `1.0.0`,则低于此版本的客户端强制升级) |
|
||||
| 安装包(EXE) | 文件上传 | 是 | 上传至 Cloudflare R2,最大 500MB |
|
||||
| 便携版(ZIP) | 文件上传 | 否 | 同上 |
|
||||
| SHA256 校验值 | 文本输入(自动填充) | 是 | 上传后系统自动计算并填充,用于客户端下载完成后校验完整性 |
|
||||
| 更新日志 | Markdown 文本区域 | 是 | 展示给用户看的版本说明,最多 2000 字 |
|
||||
| 发布说明(内部) | 文本区域 | 否 | 仅内部查看的技术说明,不对外展示 |
|
||||
| 状态 | 单选 | 是 | 草稿 / 立即发布 |
|
||||
|
||||
#### 5.3.3 版本分布统计
|
||||
|
||||
| 图表 | 说明 |
|
||||
|------|------|
|
||||
| 版本分布饼图 | 按客户端版本号统计当前活跃用户数量及占比 |
|
||||
| 升级进度趋势图 | 新版本发布后,各天累计升级完成的用户比例(折线图) |
|
||||
| 租户版本明细 | 按租户(经纪公司)展示其员工的客户端版本分布 |
|
||||
|
||||
---
|
||||
|
||||
### 5.4 更新 API 规格
|
||||
|
||||
#### GET `/api/client/updates/latest/`
|
||||
|
||||
**请求参数(Query String)**:
|
||||
|
||||
| 参数 | 类型 | 必填 | 说明 |
|
||||
|------|------|------|------|
|
||||
| `platform` | string | 是 | 平台标识,如 `win32` |
|
||||
| `arch` | string | 是 | CPU 架构,如 `x64` / `arm64` |
|
||||
| `current_version` | string | 是 | 客户端当前版本号,如 `1.2.0` |
|
||||
|
||||
**响应示例(有新版本)**:
|
||||
|
||||
```json
|
||||
{
|
||||
"has_update": true,
|
||||
"latest_version": "1.3.0",
|
||||
"force_update": false,
|
||||
"download_url": "https://download.fonrey.com/releases/v1.3.0/fonrey-setup-1.3.0-win.exe",
|
||||
"portable_url": "https://download.fonrey.com/releases/v1.3.0/fonrey-portable-1.3.0-win.zip",
|
||||
"checksum_sha256": "a1b2c3d4...",
|
||||
"release_notes": "## v1.3.0 更新内容\n- 新增客源智能配房功能\n- 修复房源列表筛选条件保存异常",
|
||||
"release_date": "2026-05-01"
|
||||
}
|
||||
```
|
||||
|
||||
**响应示例(已是最新)**:
|
||||
|
||||
```json
|
||||
{
|
||||
"has_update": false,
|
||||
"latest_version": "1.3.0"
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 6. 技术实现注意事项
|
||||
|
||||
### 6.1 依赖关系
|
||||
|
||||
| 依赖项 | 说明 | 负责方 | 风险等级 |
|
||||
|--------|------|--------|---------|
|
||||
| Electron 框架 | 客户端技术基础,需评估 License(MIT,商业可用) | 前端/客户端工程师 | 低 |
|
||||
| EV 代码签名证书 | 需提前申请,EV 证书审核周期 1-2 周 | IT/运维 | 中(需提前排期) |
|
||||
| Cloudflare R2 存储桶 | 存放安装包,利用现有账号新增 bucket | 运维 | 低 |
|
||||
| `electron-updater` | 自动更新库,需配合更新 API 端点实现 | 客户端工程师 | 低 |
|
||||
| Django 更新 API | 新增 `/api/client/updates/` 相关接口 | 后端工程师 | 低 |
|
||||
| CI/CD 构建流水线 | 自动构建、签名、上传安装包 | 运维/DevOps | 中 |
|
||||
|
||||
### 6.2 已知风险
|
||||
|
||||
| 风险 | 可能性 | 影响 | 缓解措施 |
|
||||
|------|--------|------|---------|
|
||||
| EV 证书申请延迟 | 中 | 高(无签名包无法正常分发) | MVP 阶段可使用普通 OV 证书临时过渡,但需向用户说明安全警告原因 |
|
||||
| Electron 包体过大导致下载放弃 | 低 | 中 | 使用 `electron-builder` 的 `asar` 压缩 + 分片下载;首包控制在 150MB 以内 |
|
||||
| 企业网络拦截 CDN 下载 | 中 | 中 | 提供备用下载 URL(直连服务器),支持客户手动下载后本地安装 |
|
||||
| 自动更新期间用户强制关闭 | 低 | 低 | 更新包下载完成后才替换原文件,下载中断不影响现有版本正常运行 |
|
||||
| 多租户场景下 URL 配置问题 | 低 | 高 | 客户端启动时加载的 URL 通过配置文件指定,支持定制化部署;SaaS 版统一指向主域名 |
|
||||
|
||||
### 6.3 开放问题(开发启动前必须解决)
|
||||
|
||||
- [ ] **租户 URL 如何分发到客户端?** 选项 A:客户端硬编码主域名,由服务端重定向到租户子域(`fonrey.com` → `{tenant}.fonrey.com`);选项 B:安装包内置配置文件,由销售/运维在分发给客户前填写租户子域。——**Owner**: 产品 + 工程 **Deadline**: 开发启动前
|
||||
- [ ] **代码签名证书采购主体和预算是否确认?** — **Owner**: IT 负责人 **Deadline**: 立项后 1 周
|
||||
- [ ] **CI/CD 平台选型是否确定?**(GitHub Actions / Jenkins / 其他)— **Owner**: 运维负责人 **Deadline**: 开发启动前
|
||||
- [ ] **便携版(Portable ZIP)是否纳入 v1 范围?** 便携版可解决企业无安装权限场景,但增加测试成本。— **Owner**: PM **Deadline**: 立项后 1 周
|
||||
|
||||
---
|
||||
|
||||
## 7. 发布计划
|
||||
|
||||
| 阶段 | 时间 | 受众 | 成功门槛 |
|
||||
|------|------|------|---------|
|
||||
| 内部 Alpha | 开发完成后 1 周 | 内部团队 + 1 家种子客户 | 核心流程无 P0 Bug,自动更新机制验证通过 |
|
||||
| 封闭 Beta | Alpha + 2 周 | 3-5 家头部客户 | 安装成功率 ≥ 95%,自动更新成功率 ≥ 95%,无 P0/P1 Bug |
|
||||
| 正式发布(GA) | Beta + 1 周 | 全部客户 | Beta 阶段目标达成 |
|
||||
|
||||
**回滚标准**:若正式发布后 24 小时内出现以下情况,立即下线该版本并恢复上一稳定版本为"已发布":
|
||||
- 自动更新失败率 > 5%
|
||||
- 客户端白屏/崩溃率 > 2%
|
||||
- 收到 P0 级安全漏洞报告
|
||||
|
||||
---
|
||||
|
||||
## 8. 附录
|
||||
|
||||
### 8.1 竞品参考
|
||||
|
||||
| 产品 | 客户端方案 | 更新机制 |
|
||||
|------|-----------|---------|
|
||||
| 企业微信 | Electron + 自研内核 | 强制更新,启动时自动下载 |
|
||||
| 飞书 | Electron | 后台静默更新,重启生效 |
|
||||
| 钉钉 | Electron | 同上 |
|
||||
|
||||
> 房产经纪行业的竞品(如房客多、云客优)均采用 Electron 方案,验证了技术路线的合理性。
|
||||
|
||||
### 8.2 术语表
|
||||
|
||||
| 术语 | 定义 |
|
||||
|------|------|
|
||||
| SemVer | 语义化版本控制(Semantic Versioning):`主版本号.次版本号.补丁号`,如 `1.2.3` |
|
||||
| Electron | 由 GitHub 开发的开源框架,允许使用 Web 技术(HTML/CSS/JS)构建跨平台桌面应用,内嵌 Chromium 和 Node.js |
|
||||
| electron-updater | Electron 生态中成熟的自动更新库,支持增量更新和全量更新 |
|
||||
| EV 证书 | Extended Validation 代码签名证书,由 CA 机构颁发,可消除 Windows SmartScreen 安全警告 |
|
||||
| SHA256 | 安全散列算法,用于验证下载文件的完整性,防止篡改或下载损坏 |
|
||||
| Portable | 便携版,无需安装,解压即用,适合无管理员权限的企业环境 |
|
||||
|
||||
@@ -1942,6 +1942,134 @@
|
||||
|
||||
---
|
||||
|
||||
## 6. 技术考量
|
||||
|
||||
### 6.0 核心技术设计
|
||||
|
||||
#### 6.0.1 客源状态机
|
||||
|
||||
客源在生命周期内的状态流转是系统的核心业务逻辑,必须在后端通过状态机严格控制,禁止跨状态直接跳转。
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────┐
|
||||
│ ▼
|
||||
[录入] ──► 私客(求购/求租/暂缓)──► 公客 ──► 成交客
|
||||
│ │
|
||||
│ 手动转公/自动掉公 │ 转私客(若有权限)
|
||||
│ │
|
||||
▼ ▼
|
||||
无效客 无效客
|
||||
```
|
||||
|
||||
| 状态 | 允许流转目标 | 触发方式 |
|
||||
|------|------------|---------|
|
||||
| 私客(求购) | 求租、暂缓、公客、成交客、无效 | 手动操作 / 掉公规则 |
|
||||
| 私客(求租) | 求购、暂缓、公客、成交客、无效 | 手动操作 / 掉公规则 |
|
||||
| 私客(暂缓) | 求购、求租、公客、无效 | 手动操作 |
|
||||
| 公客 | 无效 | 手动操作(暂不支持公转私) |
|
||||
| 成交客 | — | 终态,不可流转 |
|
||||
| 无效客 | — | 终态,不可流转 |
|
||||
|
||||
**实现要求**:
|
||||
- 所有状态变更须通过后端 API 的状态机校验,前端不直接修改状态字段
|
||||
- 每次状态变更自动写入 `ClientStatusChangeLog` 审计表(变更人、变更前后状态、时间、理由)
|
||||
- 状态变更失败须返回明确错误码,前端展示友好提示
|
||||
|
||||
---
|
||||
|
||||
#### 6.0.2 重复客源检测算法
|
||||
|
||||
重复检测是客源管理的核心数据质量保障。采用**异步检测 + 前端提示**策略,不阻塞录入流程。
|
||||
|
||||
**检测触发时机**:
|
||||
1. 录入时:提交表单后,后端异步触发检测,结果以橙色提示横幅展示
|
||||
2. 编辑手机号时:号码变更保存后重新触发
|
||||
3. 批量导入后:全量扫描,生成重复报告
|
||||
|
||||
**去重匹配规则(按优先级)**:
|
||||
|
||||
| 优先级 | 匹配维度 | 匹配逻辑 | 说明 |
|
||||
|--------|---------|---------|------|
|
||||
| P0 | 手机号精确匹配 | `phone_normalized = normalize(input_phone)` | 去除空格、+86、国际区号后精确比对 |
|
||||
| P1 | 手机号模糊匹配 | 去除格式差异后匹配 | 处理 `135****8888` 与 `13500008888` 等录入差异 |
|
||||
| P2 | 姓名 + 意向商圈组合 | 同名 + 相同意向区域 | 辅助人工判断,不自动合并 |
|
||||
|
||||
**去重处理规则**:
|
||||
- **私客与私客重复**:提示「该手机号已存在于 [员工姓名] 名下私客,请确认是否为同一客户」,由操作人决定是否继续录入或转为该员工协作方
|
||||
- **私客与公客重复**:提示「该手机号已在公客池中,请确认业务归属后操作」
|
||||
- **合并客户**:合并以**首录时间更早**的记录为主数据,跟进记录、带看记录全部合并至主记录,被合并记录保留为「已合并」历史副本,不可恢复
|
||||
|
||||
**数据模型**:
|
||||
```python
|
||||
class ClientDuplicateLog(TenantModel):
|
||||
source_client = ForeignKey(Client, related_name='duplicate_source')
|
||||
target_client = ForeignKey(Client, related_name='duplicate_target')
|
||||
match_type = CharField(choices=['phone_exact', 'phone_fuzzy', 'name_area'])
|
||||
detected_at = DateTimeField(auto_now_add=True)
|
||||
resolved_by = ForeignKey(User, null=True)
|
||||
resolution = CharField(choices=['merged', 'ignored', 'pending'])
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
#### 6.0.3 私客掉公(自动转公)机制
|
||||
|
||||
掉公规则由运营配置,初期建议默认值如下(待业务确认后写入系统配置模块):
|
||||
|
||||
| 触发条件 | 默认值 | 是否可配置 |
|
||||
|---------|--------|----------|
|
||||
| 私客无跟进天数 | 30 天 | 是(系统配置模块) |
|
||||
| 触发检测频率 | 每日凌晨 02:00 Celery 定时任务 | 否 |
|
||||
| 提前预警天数 | 到期前 3 天,系统消息通知归属人 | 是 |
|
||||
|
||||
**掉公流程**:
|
||||
```
|
||||
Celery Beat(每日 02:00)
|
||||
└─► 扫描:last_follow_up_at < NOW() - 掉公天数 AND status='private'
|
||||
└─► 批量更新状态为 'public'
|
||||
└─► 写入 ClientStatusChangeLog(operator='system')
|
||||
└─► 触发消息推送:「您的 N 个客源已自动转入公客池」
|
||||
```
|
||||
|
||||
**边界情况**:
|
||||
- 暂缓状态的私客**不参与**掉公计算
|
||||
- 成交客、无效客**不参与**掉公计算
|
||||
- 掉公后归属人变更为 `NULL`,首录人保留
|
||||
|
||||
---
|
||||
|
||||
#### 6.0.4 敏感号码权限与留痕
|
||||
|
||||
手机号码为核心敏感数据,访问须满足以下要求:
|
||||
|
||||
| 场景 | 展示方式 | 查看权限 | 留痕要求 |
|
||||
|------|---------|---------|---------|
|
||||
| 列表页 | `+86 135****8888` 打码 | 无需额外权限 | 不留痕 |
|
||||
| 详情页联系人面板 | `+86 135****8888` 打码 | 无需额外权限 | 不留痕 |
|
||||
| 点击「查看号码」 | 展示完整号码 10 秒后重新打码 | 需「查看客源完整号码」权限 | **必须留痕**:写入操作日志 |
|
||||
| 编辑联系人 | 打码显示 + 「查看号码」链接 | 查看需权限,编辑需「编辑客源联系人」权限 | 查看留痕 |
|
||||
|
||||
**实现要求**:
|
||||
- 号码存储使用字段级加密(AES-256),与房源模块同等安全标准
|
||||
- 查看完整号码的 API 须独立端点(不含在标准详情接口内),方便审计
|
||||
- 操作日志异步写入,不影响查看响应时间
|
||||
|
||||
---
|
||||
|
||||
#### 6.0.5 列表性能策略
|
||||
|
||||
当前截图显示公客池已有 28,878 条,私客总量持续增长,列表性能须在设计阶段预防:
|
||||
|
||||
| 策略 | 说明 |
|
||||
|------|------|
|
||||
| 服务端分页 | 所有列表接口默认 20 条/页,禁止前端全量加载 |
|
||||
| 筛选条件下推 | 所有筛选条件传至 Django ORM,生成 SQL WHERE 子句,不做内存过滤 |
|
||||
| 索引设计 | 联合索引:`(tenant_id, status,归属人, 最后跟进时间)`;手机号哈希索引(辅助去重查询) |
|
||||
| 慢查询监控 | 超过 500ms 的查询写入慢日志,上线前需通过 EXPLAIN ANALYZE 验证核心列表查询 |
|
||||
| 智能配房批量计算 | 不在请求链路内实时计算,通过 Celery 定时或客源更新时异步触发,结果缓存至 Redis |
|
||||
|
||||
---
|
||||
|
||||
### 6.1 依赖关系
|
||||
|
||||
| 系统/模块 | 依赖原因 | 优先级风险 |
|
||||
|
||||
@@ -43,7 +43,7 @@
|
||||
|
||||
## 3. 非目标(本期不做)
|
||||
|
||||
- 不包含细化到行级(Row-level)的数据权限(如仅允许查看特定小区的房源),本期数据范围控制以「本人 / 本部门 / 全公司」三档为主
|
||||
- 不包含细化到行级(Row-level)的数据权限(如仅允许查看特定小区的房源);本期数据范围控制采用**五档模型**:本人 / 本组 / 本门店 / 本区域 / 全公司。注意:并非所有权限项均开放五档,各项的实际可选范围以权限编辑页的下拉配置为准(例如某些权限项仅提供「本人 / 本门店 / 全公司」三个选项)
|
||||
- 不包含权限申请审批工作流(员工自助申请权限需上级审批),本期由管理员直接操作
|
||||
- 不包含操作日志的可视化看板(日志写入,查询能力在后续版本规划)
|
||||
- 不包含 IP 白名单、登录时段等安全策略配置(安全策略模块另行规划)
|
||||
|
||||
@@ -1,36 +1,26 @@
|
||||
# PRD:系统管理模块(Admin & System Management)
|
||||
|
||||
**Status**: Draft
|
||||
**Author**: Alex (Product Manager)
|
||||
**Last Updated**: 2026-04-24
|
||||
**Version**: 1.0
|
||||
**Stakeholders**: 工程负责人、运营团队、安全合规、客户成功团队
|
||||
|
||||
---
|
||||
|
||||
## 0. 模块定位与背景
|
||||
|
||||
Fonrey 是一套面向房产经纪公司的 B2B SaaS 平台,采用 `django-tenants` 实现 PostgreSQL Schema 级别的多租户隔离。随着平台商业化推进,运营团队需要一套独立的管理后台(Admin Console)来管理租户生命周期、系统升级、备份恢复及合规审计。
|
||||
|
||||
**核心问题**:平台运营团队当前缺乏统一的工具来:
|
||||
|
||||
1. 管理数百家经纪公司(租户)的开通、暂停、注销流程
|
||||
2. 在不中断服务的前提下对平台进行版本升级与灰度发布
|
||||
3. 应对数据灾难场景(数据误删、升级失败)时快速恢复
|
||||
4. 满足合规要求,对所有高危操作留存完整审计轨迹
|
||||
|
||||
**本模块不解决**:
|
||||
|
||||
- 租户内部的业务功能(房源、客源、楼盘管理)——已在各自 PRD 中覆盖
|
||||
- 移动端管理能力——v2 规划
|
||||
- 财务收费与发票系统——独立财务模块
|
||||
- 自动化客服与工单系统——独立支持模块
|
||||
**状态**:Draft
|
||||
**作者**:产品经理
|
||||
**最后更新**:2026-04-24
|
||||
**版本**:v1.0
|
||||
**利益相关方**:工程负责人、运营团队、安全合规、客户成功团队
|
||||
|
||||
---
|
||||
|
||||
## 1. 问题陈述
|
||||
|
||||
### 1.1 核心痛点
|
||||
### 1.1 背景
|
||||
|
||||
Fonrey 是一套面向房产经纪公司的 B2B SaaS 平台,采用 `django-tenants` 实现 PostgreSQL Schema 级别的多租户隔离。随着平台商业化推进,运营团队需要一套独立的管理后台(Admin Console)来管理租户生命周期、系统升级、备份恢复及合规审计。
|
||||
|
||||
**本模块解决的核心问题**:平台运营团队当前缺乏统一的工具来:
|
||||
1. 管理数百家经纪公司(租户)的开通、暂停、注销流程
|
||||
2. 在不中断服务的前提下对平台进行版本升级与灰度发布
|
||||
3. 应对数据灾难场景(数据误删、升级失败)时快速恢复
|
||||
4. 满足合规要求,对所有高危操作留存完整审计轨迹
|
||||
|
||||
### 1.2 核心痛点
|
||||
|
||||
| 痛点 | 影响方 | 当前代价 |
|
||||
|------|--------|---------|
|
||||
@@ -39,7 +29,7 @@ Fonrey 是一套面向房产经纪公司的 B2B SaaS 平台,采用 `django-ten
|
||||
| 数据备份无策略,灾难恢复依赖人工 | 平台稳定性 | 数据丢失风险 |
|
||||
| 高危操作无审计日志,合规风险暴露 | 管理层/合规 | 法律与客户信任风险 |
|
||||
|
||||
### 1.2 目标用户
|
||||
### 1.3 目标用户
|
||||
|
||||
| 角色 | 使用场景 | 频率 |
|
||||
| --------------------------- | ----------- | ------ |
|
||||
|
||||
@@ -465,7 +465,127 @@
|
||||
|
||||
---
|
||||
|
||||
## 6. 上线计划
|
||||
## 6. 技术考量
|
||||
|
||||
### 6.1 依赖关系
|
||||
|
||||
| 系统/模块 | 依赖原因 | 优先级风险 |
|
||||
|-----------|---------|-----------|
|
||||
| 登录管理模块 | 员工账号的创建、冻结、密码重置由登录模块提供接口 | 高 |
|
||||
| 权限管理模块 | 员工的角色/权限分配在人事模块发起,权限模块执行 | 高 |
|
||||
| 系统配置模块 | 职务类别、部门级别、奖惩类型等枚举值从系统配置读取 | 中 |
|
||||
|
||||
### 6.2 核心技术设计
|
||||
|
||||
#### 6.2.1 组织树存储方案
|
||||
|
||||
采用 **Closure Table(闭包表)** 存储多层级部门树,最大支持 8 层嵌套:
|
||||
|
||||
| 方案 | 优点 | 缺点 | 选用理由 |
|
||||
|------|------|------|---------|
|
||||
| Adjacency List | 写入简单 | 递归查询慢,需多次 SQL | ❌ 不适合 8 层嵌套 |
|
||||
| Nested Set | 读取极快 | 写入时需重排序,高并发写冲突大 | ❌ 人事模块写入频繁 |
|
||||
| **Closure Table** | 读写均衡,查询任意层级 O(1) | 存储量略多 | ✅ **选用** |
|
||||
|
||||
**数据结构**:
|
||||
```python
|
||||
class OrgUnit(TenantModel): # 部门节点
|
||||
id = UUIDField(primary_key=True)
|
||||
name = CharField(max_length=100)
|
||||
level = CharField(choices=['事业部','大区','区域','片区','门店','店组','职能'])
|
||||
parent = ForeignKey('self', null=True, on_delete=PROTECT) # 直接父节点
|
||||
is_direct = BooleanField(default=True) # True=直营, False=加盟
|
||||
deleted_at = DateTimeField(null=True)
|
||||
|
||||
class OrgUnitClosure(TenantModel): # 闭包表
|
||||
ancestor = ForeignKey(OrgUnit, related_name='descendants')
|
||||
descendant = ForeignKey(OrgUnit, related_name='ancestors')
|
||||
depth = IntegerField() # 0=自身, 1=子, 2=孙...
|
||||
```
|
||||
|
||||
**查询示例**:
|
||||
- 查某节点所有子孙:`WHERE ancestor_id = X AND depth > 0`
|
||||
- 查某节点完整路径:`WHERE descendant_id = X ORDER BY depth DESC`
|
||||
- 移动节点:删除旧闭包记录 + 插入新闭包记录(事务内执行)
|
||||
|
||||
#### 6.2.2 员工状态机
|
||||
|
||||
员工在系统内的状态须通过后端状态机严格控制:
|
||||
|
||||
```
|
||||
[录入] ──► 试用期 ──► 正式 ──► 离职
|
||||
│ │
|
||||
└──────────────┘
|
||||
复职
|
||||
│
|
||||
▼
|
||||
试用期 / 正式(恢复上次状态)
|
||||
```
|
||||
|
||||
| 状态 | 允许流转目标 | 触发方式 |
|
||||
|------|------------|---------|
|
||||
| 试用期 | 正式、离职 | 管理员手动操作 |
|
||||
| 正式 | 离职 | 管理员手动操作 |
|
||||
| 离职 | 复职 | 管理员手动操作 |
|
||||
| 冻结 | 启用(需先恢复员工状态) | 账号冻结操作 |
|
||||
|
||||
**实现要求**:
|
||||
- 每次状态变更写入 `StaffChangeLog`(异动记录表),字段包含:变更人、变更类型、变更前后值、变更时间、备注
|
||||
- 员工离职时,系统自动:① 冻结关联登录账号 ② 解除权限角色 ③ 归属客源触发掉公检查
|
||||
- 员工状态变更失败返回明确错误码,前端展示友好提示
|
||||
|
||||
#### 6.2.3 异动记录审计策略
|
||||
|
||||
异动记录为**只追加(append-only)**设计,不支持修改或删除:
|
||||
|
||||
| 异动类型枚举 | 触发场景 |
|
||||
|------------|---------|
|
||||
| 入职 | 员工首次录入系统 |
|
||||
| 转正 | 试用期转为正式员工 |
|
||||
| 调岗 | 员工所属部门变更 |
|
||||
| 上级变动 | 直接上级变更 |
|
||||
| 离职 | 办理离职手续 |
|
||||
| 复职 | 离职员工重新入职 |
|
||||
| 账号冻结 | 账号被冻结 |
|
||||
| 账号启用 | 账号从冻结恢复 |
|
||||
|
||||
```python
|
||||
class StaffChangeLog(TenantModel):
|
||||
staff = ForeignKey(Staff)
|
||||
change_type = CharField(choices=[...]) # 见枚举表
|
||||
before_value = JSONField(null=True) # 变更前状态快照
|
||||
after_value = JSONField(null=True) # 变更后状态快照
|
||||
operator = ForeignKey(User)
|
||||
remark = TextField(blank=True)
|
||||
created_at = DateTimeField(auto_now_add=True)
|
||||
# 无 updated_at / deleted_at — append-only
|
||||
```
|
||||
|
||||
#### 6.2.4 敏感数据脱敏
|
||||
|
||||
| 数据 | 存储方式 | 展示方式 | 查看权限 |
|
||||
|------|---------|---------|---------|
|
||||
| 手机号 | AES-256-GCM 加密 + SHA-256 哈希索引 | `159****9696` | 需「查看员工手机号」权限,留操作日志 |
|
||||
| 证件号码 | AES-256-GCM 加密 | `410***********3037` | 需「查看员工证件」权限,留操作日志 |
|
||||
| 通讯录号码 | AES-256-GCM 加密 | 脱敏显示 | 点击「查看号码」后临时展示,留痕 |
|
||||
|
||||
### 6.3 已知风险
|
||||
|
||||
| 风险 | 可能性 | 影响 | 缓解措施 |
|
||||
|------|--------|------|---------|
|
||||
| 大型机构部门树深度超过 8 层 | 低 | 中 | 前端录入时限制最大深度,超出提示联系运营调整 |
|
||||
| 员工大批量导入时账号创建并发冲突 | 中 | 中 | 批量导入走 Celery 异步任务,序列化账号创建 |
|
||||
| 组织调整时历史客源/房源归属关系错乱 | 中 | 高 | 员工调岗不改变现有资源归属,仅更新组织关系;业务重新分配由管理员手动操作 |
|
||||
|
||||
### 6.4 待确认问题
|
||||
|
||||
- [ ] 员工工号规则:系统自动生成还是管理员手动填写?格式约定是什么? — 待业务确认 — 开发前必须明确
|
||||
- [ ] 「复职」时是否复用原有账号?还是重新创建新账号? — 待产品/法务确认
|
||||
- [ ] 部门移动操作(将某节点及其子树挂到新父节点)是否在 MVP 范围内? — 待产品确认
|
||||
|
||||
---
|
||||
|
||||
## 7. 上线计划
|
||||
|
||||
| 阶段 | 时间 | 受众 | 验收门槛 |
|
||||
|------|------|------|----------|
|
||||
|
||||
Reference in New Issue
Block a user